diff --git a/Xext/EVI.c b/Xext/EVI.c new file mode 100644 index 000000000..8ccc31af2 --- /dev/null +++ b/Xext/EVI.c @@ -0,0 +1,179 @@ +/* $Xorg: EVI.c,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc. +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. +********************************************************/ +#include "X.h" +#include "Xproto.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "dix.h" +#define _XEVI_SERVER_ +#include "XEVIstr.h" +#include "EVIstruct.h" +static unsigned char XEVIReqCode = 0; +static EviPrivPtr eviPriv; +static int +ProcEVIQueryVersion(ClientPtr client) +{ + REQUEST(xEVIQueryVersionReq); + xEVIQueryVersionReply rep; + register int n; + REQUEST_SIZE_MATCH (xEVIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XEVI_MAJOR_VERSION; + rep.minorVersion = XEVI_MAJOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xEVIQueryVersionReply), (char *)&rep); + return (client->noClientException); +} +#define swapEviInfo(eviInfo, l) \ +{ \ + int l1 = l; \ + xExtendedVisualInfo *eviInfo1 = eviInfo; \ + while (l1-- > 0) { \ + swapl(&eviInfo1->core_visual_id, n); \ + swapl(&eviInfo1->transparency_value, n); \ + swaps(&eviInfo1->num_colormap_conflicts, n); \ + eviInfo1++; \ + } \ +} +#define swapVisual(visual, l) \ +{ \ + int l1 = l; \ + VisualID32 *visual1 = visual; \ + while (l1-- > 0) { \ + swapl(visual1, n); \ + visual1++; \ + } \ +} +static int +ProcEVIGetVisualInfo(ClientPtr client) +{ + REQUEST(xEVIGetVisualInfoReq); + xEVIGetVisualInfoReply rep; + int n, n_conflict, n_info, sz_info, sz_conflict; + VisualID32 *conflict; + xExtendedVisualInfo *eviInfo; + int status; + REQUEST_FIXED_SIZE(xEVIGetVisualInfoReq, stuff->n_visual * sz_VisualID32); + status = eviPriv->getVisualInfo((VisualID32 *)&stuff[1], (int)stuff->n_visual, + &eviInfo, &n_info, &conflict, &n_conflict); + if (status != Success) + return status; + sz_info = n_info * sz_xExtendedVisualInfo; + sz_conflict = n_conflict * sz_VisualID32; + rep.type = X_Reply; + rep.n_info = n_info; + rep.n_conflicts = n_conflict; + rep.sequenceNumber = client->sequence; + rep.length = (sz_info + sz_conflict) >> 2; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.n_info, n); + swapl(&rep.n_conflicts, n); + swapEviInfo(eviInfo, n_info); + swapVisual(conflict, n_conflict); + } + WriteToClient(client, sz_xEVIGetVisualInfoReply, (char *)&rep); + WriteToClient(client, sz_info, (char *)eviInfo); + WriteToClient(client, sz_conflict, (char *)conflict); + eviPriv->freeVisualInfo(eviInfo, conflict); + return (client->noClientException); +} +static int +ProcEVIDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_EVIQueryVersion: + return ProcEVIQueryVersion (client); + case X_EVIGetVisualInfo: + return ProcEVIGetVisualInfo (client); + default: + return BadRequest; + } +} +static int +SProcEVIQueryVersion(client) +ClientPtr client; +{ + REQUEST(xEVIQueryVersionReq); + int n; + swaps(&stuff->length, n); + return ProcEVIQueryVersion(client); +} +static int +SProcEVIGetVisualInfo(ClientPtr client) +{ + register int n; + REQUEST(xEVIGetVisualInfoReq); + swaps(&stuff->length, n); + return ProcEVIGetVisualInfo(client); +} +static int +SProcEVIDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_EVIQueryVersion: + return SProcEVIQueryVersion (client); + case X_EVIGetVisualInfo: + return SProcEVIGetVisualInfo (client); + default: + return BadRequest; + } +} +/*ARGSUSED*/ +static void +EVIResetProc(ExtensionEntry *extEntry) +{ + eviDDXReset(); +} +/**************** + * XEVIExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ +void +EVIExtensionInit(void) +{ + ExtensionEntry *extEntry, *AddExtension(); + if (extEntry = AddExtension(EVINAME, 0, 0, + ProcEVIDispatch, + SProcEVIDispatch, + EVIResetProc, StandardMinorOpcode)) + { + XEVIReqCode = (unsigned char)extEntry->base; + eviPriv = eviDDXInit(); + } +} diff --git a/Xext/EVIstruct.h b/Xext/EVIstruct.h new file mode 100644 index 000000000..9bb24b0d2 --- /dev/null +++ b/Xext/EVIstruct.h @@ -0,0 +1,53 @@ +/* $Xorg: EVIstruct.h,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc. +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. +********************************************************/ +#ifndef EVI_STRUCT_H +#define EVI_STRUCT_H +/* + ****************************************************************************** + ** Per-ddx data + ****************************************************************************** + */ +typedef int (*GetVisualInfoProc)( +#if NeedNestedPrototypes + VisualID32*, + int, + xExtendedVisualInfo**, + int*, + VisualID32**, + int* +#endif +); +typedef void (*FreeVisualInfoProc)( +#if NeedNestedPrototypes + xExtendedVisualInfo*, + VisualID32* +#endif +); +typedef struct _EviPrivRec { + GetVisualInfoProc getVisualInfo; + FreeVisualInfoProc freeVisualInfo; +} EviPrivRec, *EviPrivPtr; +extern EviPrivPtr eviDDXInit(); +extern void eviDDXReset(); +#endif /* EVI_STRUCT_H */ diff --git a/Xext/README.xtest1-ddx b/Xext/README.xtest1-ddx new file mode 100644 index 000000000..bdf7943b7 --- /dev/null +++ b/Xext/README.xtest1-ddx @@ -0,0 +1,90 @@ +There are several code fragments that need to be placed in the device +dependent part of the server. These are described below. These code +fragments are device and implementation dependent. + +This code fragment should go in your ddx InitInput() routine: + +#ifdef XTESTEXT1 +extern KeyCode xtest_command_key; +#endif + +#ifdef XTESTEXT1 + xtest_command_key = ; +#endif + +This code fragment should go at the front of the file that handles +keyboards: + +#ifdef XTESTEXT1 +/* + * defined in xtestext1di.c + */ +extern int on_steal_input; +extern Bool XTestStealKeyData(); +#endif XTESTEXT1 + +This code fragment should go in the function that parses input from the +keyboard or pointer after you know what input action has occurred, but before +you have told the server about it. If conditionalizes the actual function +call to pass the information on: + +#ifdef XTESTEXT1 + if (!on_steal_input || + XTestStealKeyData(code, direction, dev_type, x, y)) +#endif /* XTESTEXT1 */ + handle_device_event(...); + +This code fragment should go in the function that handles mouse motion after +you have figured out how much the mouse has moved: + +#ifdef XTESTEXT1 + if (on_steal_input) + XTestStealMotionData(dx, dy, dev, x, y); +#endif XTESTEXT1 + + +This code fragment should go at the front of the os-specific code where +you wait (by doing a select on the socket in our implementation) for +something to happen: + +#ifdef XTESTEXT1 +extern int playback_on; +void XTestComputeWaitTime(); +#endif XTESTEXT1 + +These code fragments should go in the os-specific code on both sides of +where you wait (by doing a select on the socket in our implementation) +for something to happen: + +#ifdef XTESTEXT1 + if (playback_on) + XTestComputeWaitTime(wt = &waittime); +#endif XTESTEXT1 + ... code to do select ... + WakeupHandler(i, LastSelectMask); +#ifdef XTESTEXT1 + if (playback_on) + i = XTestProcessInputAction(i, &waittime); +#endif XTESTEXT1 + + +You also need to implement the following routines (documentation +is needed; for now, see server/ddx/hp/hp/x_hil.c): + +void +XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey) + int dev_type; + int keycode; + int keystate; + int mousex; + int mousey; + +void +XTestGetPointerPos(fmousex, fmousey) + short *fmousex, *fmousey; + +void +XTestJumpPointer(jx, jy, dev_type) + int jx; + int jy; + int dev_type; diff --git a/Xext/SecurityPolicy b/Xext/SecurityPolicy new file mode 100644 index 000000000..cc521c263 --- /dev/null +++ b/Xext/SecurityPolicy @@ -0,0 +1,88 @@ +version-1 + +# $Xorg: SecurityPolicy,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ + +# The site policy fields are interpreted by the XC-QUERY-SECURITY-1 +# authorization protocol. The values are arbitrary and site-specific. +# Refer to the Security Extension Specification for the usage of the policies. +#sitepolicy A +#sitepolicy B +#sitepolicy C + +# Property access rules: +# property +# ::= any | root | +# ::= | = +# :== [ | | ]* +# :== r | w | d +# r read +# w write +# d delete +# :== a | i | e +# a allow +# i ignore +# e error + +# Allow reading of application resources, but not writing. +property RESOURCE_MANAGER root ar iw +property SCREEN_RESOURCES root ar iw + +# Ignore attempts to use cut buffers. Giving errors causes apps to crash, +# and allowing access may give away too much information. +property CUT_BUFFER0 root irw +property CUT_BUFFER1 root irw +property CUT_BUFFER2 root irw +property CUT_BUFFER3 root irw +property CUT_BUFFER4 root irw +property CUT_BUFFER5 root irw +property CUT_BUFFER6 root irw +property CUT_BUFFER7 root irw + +# If you are using Motif, you probably want these. +property _MOTIF_DEFAULT_BINDINGS root ar iw +property _MOTIF_DRAG_WINDOW root ar iw +property _MOTIF_DRAG_TARGETS any ar iw +property _MOTIF_DRAG_ATOMS any ar iw +property _MOTIF_DRAG_ATOM_PAIRS any ar iw + +# If you are running CDE you also need these +property _MOTIF_WM_INFO root arw +property TT_SESSION root irw +property WM_ICON_SIZE root irw +property "SDT Pixel Set" any irw + +# The next two rules let xwininfo -tree work when untrusted. +property WM_NAME any ar + +# Allow read of WM_CLASS, but only for windows with WM_NAME. +# This might be more restrictive than necessary, but demonstrates +# the facility, and is also an attempt to +# say "top level windows only." +property WM_CLASS WM_NAME ar + +# These next three let xlsclients work untrusted. Think carefully +# before including these; giving away the client machine name and command +# may be exposing too much. +property WM_STATE WM_NAME ar +property WM_CLIENT_MACHINE WM_NAME ar +property WM_COMMAND WM_NAME ar + +# To let untrusted clients use the standard colormaps created by +# xstdcmap, include these lines. +property RGB_DEFAULT_MAP root ar +property RGB_BEST_MAP root ar +property RGB_RED_MAP root ar +property RGB_GREEN_MAP root ar +property RGB_BLUE_MAP root ar +property RGB_GRAY_MAP root ar + +# To let untrusted clients use the color management database created +# by xcmsdb, include these lines. +property XDCCC_LINEAR_RGB_CORRECTION root ar +property XDCCC_LINEAR_RGB_MATRICES root ar +property XDCCC_GRAY_SCREENWHITEPOINT root ar +property XDCCC_GRAY_CORRECTION root ar + +# To let untrusted clients use the overlay visuals that many vendors +# support, include this line. +property SERVER_OVERLAY_VISUALS root ar diff --git a/Xext/appgroup.c b/Xext/appgroup.c new file mode 100644 index 000000000..71e74da38 --- /dev/null +++ b/Xext/appgroup.c @@ -0,0 +1,810 @@ +/* +Copyright 1996, 1998, 2001 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. +*/ +/* $Xorg: appgroup.c,v 1.6 2001/02/09 02:04:32 xorgcvs Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "colormapst.h" +#include "servermd.h" +#define _XAG_SERVER_ +#include "Xagstr.h" +#define _SECURITY_SERVER +#include "security.h" +#include "Xfuncproto.h" + +#define XSERV_t +#include +#include "../os/osdep.h" + +#include + +typedef struct _AppGroupRec { + struct _AppGroupRec* next; + XID appgroupId; + ClientPtr* clients; + int nclients; + ClientPtr leader; + Bool single_screen; + Window default_root; + VisualID root_visual; + Colormap default_colormap; + Pixel black_pixel; + Pixel white_pixel; + xConnSetupPrefix connSetupPrefix; + char* ConnectionInfo; +} AppGroupRec, *AppGroupPtr; + +static int ProcXagDispatch (), SProcXagDispatch (); +static void XagResetProc (); + +static unsigned char XagReqCode = 0; +static int XagErrorBase; +static int XagCallbackRefCount = 0; + +static RESTYPE RT_APPGROUP; +static AppGroupPtr appGrpList = NULL; + +extern WindowPtr* WindowTable; +extern xConnSetupPrefix connSetupPrefix; +extern char* ConnectionInfo; + +static +int XagAppGroupFree (what, id) + pointer what; + XID id; /* unused */ +{ + int i; + AppGroupPtr pAppGrp = (AppGroupPtr) what; + + if (pAppGrp->leader) + for (i = 0; i < pAppGrp->nclients; i++) { + pAppGrp->clients[i]->appgroup = NULL; + CloseDownClient (pAppGrp->clients[i]); + } + + if (pAppGrp == appGrpList) + appGrpList = appGrpList->next; + else { + AppGroupPtr tpAppGrp; + for (tpAppGrp = appGrpList; + tpAppGrp->next != NULL; + tpAppGrp = tpAppGrp->next) { + if (tpAppGrp->next == pAppGrp) { + tpAppGrp->next = tpAppGrp->next->next; + break; + } + } + } + (void) xfree (pAppGrp->clients); + (void) xfree (pAppGrp->ConnectionInfo); + (void) xfree (what); + return Success; +} + +/* static */ +void XagClientStateChange (pcbl, nulldata, calldata) + CallbackListPtr* pcbl; + pointer nulldata; + pointer calldata; +{ + SecurityAuthorizationPtr pAuth; + NewClientInfoRec* pci = (NewClientInfoRec*) calldata; + ClientPtr pClient = pci->client; + AppGroupPtr pAppGrp; + XID authId; + + if (!pClient->appgroup) { + switch (pClient->clientState) { + + case ClientStateAuthenticating: + case ClientStateRunning: + case ClientStateCheckingSecurity: + return; + + case ClientStateInitial: + case ClientStateCheckedSecurity: + /* + * If the client is connecting via a firewall proxy (which + * uses XC-QUERY-SECURITY-1, then the authId is available + * during ClientStateCheckedSecurity, otherwise it's + * available during ClientStateInitial. + * + * Don't get it from pClient because can't guarantee the order + * of the callbacks and the security extension might not have + * plugged it in yet. + */ + authId = AuthorizationIDOfClient(pClient); + break; + + case ClientStateGone: + case ClientStateRetained: + /* + * Don't get if from AuthorizationIDOfClient because can't + * guarantee the order of the callbacks and the security + * extension may have torn down the client's private data + */ + authId = pClient->authId; + break; + } + + if (authId == None) + return; + + pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(pClient, + authId, SecurityAuthorizationResType, SecurityReadAccess); + + if (pAuth == NULL) + return; + + for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next) + if (pAppGrp->appgroupId == pAuth->group) break; + } else { + pAppGrp = pClient->appgroup; + } + + if (!pAppGrp) + return; + + switch (pClient->clientState) { + case ClientStateAuthenticating: + case ClientStateRunning: + case ClientStateCheckingSecurity: + break; + + case ClientStateInitial: + case ClientStateCheckedSecurity: + /* see the comment above about Initial vs. CheckedSecurity */ + { + /* if this client already in AppGroup, don't add it again */ + int i; + for (i = 0; i < pAppGrp->nclients; i++) + if (pClient == pAppGrp->clients[i]) return; + } + pAppGrp->clients = (ClientPtr*) xrealloc (pAppGrp->clients, + ++pAppGrp->nclients * sizeof (ClientPtr)); + pAppGrp->clients[pAppGrp->nclients - 1] = pClient; + pClient->appgroup = pAppGrp; + break; + + case ClientStateGone: + case ClientStateRetained: /* client disconnected, dump it */ + { + int i; + for (i = 0; i < pAppGrp->nclients; i++) + if (pAppGrp->clients[i] == pClient) { + pAppGrp->clients[i] = NULL; + break; + } + for (i = 0; i < pAppGrp->nclients; i++) + if (pAppGrp->clients[i] == NULL && i + 1 < pAppGrp->nclients) + pAppGrp->clients[i] = pAppGrp->clients[i + 1]; + pAppGrp->nclients--; + } + pClient->appgroup = NULL; /* redundant, pClient will be freed */ + break; + } +} + +void +XagExtensionInit () +{ + ExtensionEntry* extEntry; + + if (extEntry = AddExtension (XAGNAME, + 0, + XagNumberErrors, + ProcXagDispatch, + SProcXagDispatch, + XagResetProc, + StandardMinorOpcode)) { + XagReqCode = (unsigned char)extEntry->base; + XagErrorBase = extEntry->errorBase; + RT_APPGROUP = CreateNewResourceType (XagAppGroupFree); + } +} + +/*ARGSUSED*/ +static +void XagResetProc (extEntry) + ExtensionEntry* extEntry; +{ + DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL); + XagCallbackRefCount = 0; + while (appGrpList) XagAppGroupFree ((pointer) appGrpList, 0); +} + +static +int ProcXagQueryVersion (client) + register ClientPtr client; +{ + REQUEST (xXagQueryVersionReq); + xXagQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xXagQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.server_major_version = XAG_MAJOR_VERSION; + rep.server_minor_version = XAG_MINOR_VERSION; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swaps (&rep.server_major_version, n); + swaps (&rep.server_minor_version, n); + } + WriteToClient (client, sizeof (xXagQueryVersionReply), (char *)&rep); + return client->noClientException; +} + +static +void ProcessAttr (pAppGrp, client, attrib_mask, attribs) + AppGroupPtr pAppGrp; + ClientPtr client; + unsigned int attrib_mask; + CARD32* attribs; +{ + int i; + + for (i = 0; i <= XagNappGroupLeader; i++) { + switch (attrib_mask & (1 << i)) { + case XagSingleScreenMask: + pAppGrp->single_screen = *attribs; + break; + case XagDefaultRootMask: + pAppGrp->default_root = *attribs; + break; + case XagRootVisualMask: + pAppGrp->root_visual = *attribs; + break; + case XagDefaultColormapMask: + pAppGrp->default_colormap = *attribs; + break; + case XagBlackPixelMask: + pAppGrp->black_pixel = *attribs; + break; + case XagWhitePixelMask: + pAppGrp->white_pixel = *attribs; + break; + case XagAppGroupLeaderMask: + pAppGrp->leader = client; + break; + default: continue; + } + attribs++; + } +} + +static +void CreateConnectionInfo (pAppGrp) + AppGroupPtr pAppGrp; +{ + extern int connBlockScreenStart; + xConnSetup *setup = (xConnSetup*) ConnectionInfo; + xWindowRoot* rootp; + xWindowRoot* roots[MAXSCREENS]; + unsigned int rootlens[MAXSCREENS]; + xDepth* depth; + int olen; + int snum, i; + + rootp = (xWindowRoot*) (ConnectionInfo + connBlockScreenStart); + for (snum = 0; snum < screenInfo.numScreens; snum++) { + + rootlens[snum] = sizeof (xWindowRoot); + roots[snum] = rootp; + + depth = (xDepth*) (rootp + 1); + for (i = 0; i < rootp->nDepths; i++) { + rootlens[snum] += sizeof (xDepth) + + depth->nVisuals * sizeof (xVisualType); + depth = (xDepth *)(((char*)(depth + 1)) + + depth->nVisuals * sizeof (xVisualType)); + } + rootp = (xWindowRoot*) depth; + } + snum = 0; + if (pAppGrp->default_root) { + for (; snum < screenInfo.numVideoScreens; snum++) { + if (roots[snum]->windowId == pAppGrp->default_root) + break; + } + } + olen = connBlockScreenStart + rootlens[snum]; + for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++) + olen += rootlens[i]; + pAppGrp->ConnectionInfo = (char*) xalloc (olen); + if (!pAppGrp->ConnectionInfo) + return; + memmove (pAppGrp->ConnectionInfo, ConnectionInfo, connBlockScreenStart); + ((xConnSetup*) (pAppGrp->ConnectionInfo))->numRoots = + 1 + screenInfo.numScreens - screenInfo.numVideoScreens; + memmove (pAppGrp->ConnectionInfo + connBlockScreenStart, + (void*) roots[snum], rootlens[snum]); + rootp = (xWindowRoot*) (pAppGrp->ConnectionInfo + connBlockScreenStart); + if (pAppGrp->default_colormap) { + rootp->defaultColormap = pAppGrp->default_colormap; + rootp->whitePixel = pAppGrp->white_pixel; + rootp->blackPixel = pAppGrp->black_pixel; + } + if (pAppGrp->root_visual) + rootp->rootVisualID = pAppGrp->root_visual; + rootp = (xWindowRoot*) (((char*)rootp) + rootlens[snum]); + for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++) { + memmove ((void*) rootp, (void*) roots[i], rootlens[i]); + rootp = (xWindowRoot*) (((char*) rootp) + rootlens[i]); + } + pAppGrp->connSetupPrefix = connSetupPrefix; + pAppGrp->connSetupPrefix.length = olen >> 2; +} + +static +AppGroupPtr CreateAppGroup (client, appgroupId, attrib_mask, attribs) + ClientPtr client; + XID appgroupId; + unsigned int attrib_mask; + CARD32* attribs; +{ + AppGroupPtr pAppGrp; + int i; + + pAppGrp = (AppGroupPtr) xalloc (sizeof(AppGroupRec)); + if (pAppGrp) { + pAppGrp->next = appGrpList; + appGrpList = pAppGrp; + pAppGrp->appgroupId = appgroupId; + pAppGrp->clients = (ClientPtr*) xalloc (0); + pAppGrp->nclients = 0; + pAppGrp->leader = NULL; + pAppGrp->default_root = 0; + pAppGrp->root_visual = 0; + pAppGrp->default_colormap = 0; + pAppGrp->black_pixel = -1; + pAppGrp->white_pixel = -1; + pAppGrp->ConnectionInfo = NULL; + ProcessAttr (pAppGrp, client, attrib_mask, attribs); + } + return pAppGrp; +} + +static +int AttrValidate (client, attrib_mask, pAppGrp) + ClientPtr client; + int attrib_mask; + AppGroupPtr pAppGrp; +{ + WindowPtr pWin; + int idepth, ivids, found; + ScreenPtr pScreen; + DepthPtr pDepth; + ColormapPtr pColormap; + + pWin = LookupWindow (pAppGrp->default_root, client); + /* XXX check that pWin is not NULL */ + pScreen = pWin->drawable.pScreen; + if (WindowTable[pScreen->myNum]->drawable.id != pAppGrp->default_root) + return BadWindow; + pDepth = pScreen->allowedDepths; + if (pAppGrp->root_visual) { + found = FALSE; + for (idepth = 0; idepth < pScreen->numDepths; idepth++, pDepth++) { + for (ivids = 0; ivids < pDepth->numVids; ivids++) { + if (pAppGrp->root_visual == pDepth->vids[ivids]) { + found = TRUE; + break; + } + } + } + if (!found) + return BadMatch; + } + if (pAppGrp->default_colormap) { + + pColormap = (ColormapPtr)LookupIDByType (pAppGrp->default_colormap, RT_COLORMAP); + /* XXX check that pColormap is not NULL */ + if (pColormap->pScreen != pScreen) + return BadColor; + if (pColormap->pVisual->vid != (pAppGrp->root_visual ? pAppGrp->root_visual : pScreen->rootVisual)) + return BadMatch; + } + return client->noClientException; +} + +/* static */ +int ProcXagCreate (client) + register ClientPtr client; +{ + REQUEST (xXagCreateReq); + AppGroupPtr pAppGrp; + int ret; + + REQUEST_AT_LEAST_SIZE (xXagCreateReq); + + LEGAL_NEW_RESOURCE (stuff->app_group, client); + pAppGrp = CreateAppGroup (client, stuff->app_group, + stuff->attrib_mask, (CARD32*) &stuff[1]); + if (!pAppGrp) + return BadAlloc; + ret = AttrValidate (client, stuff->attrib_mask, pAppGrp); + if (ret != Success) { + XagAppGroupFree ((pointer)pAppGrp, (XID)0); + return ret; + } + if (pAppGrp->single_screen) { + CreateConnectionInfo (pAppGrp); + if (!pAppGrp->ConnectionInfo) + return BadAlloc; + } + if (!AddResource (stuff->app_group, RT_APPGROUP, (pointer)pAppGrp)) + return BadAlloc; + if (XagCallbackRefCount++ == 0) + (void) AddCallback (&ClientStateCallback, XagClientStateChange, NULL); + return client->noClientException; +} + +/* static */ +int ProcXagDestroy (client) + register ClientPtr client; +{ + AppGroupPtr pAppGrp; + REQUEST (xXagDestroyReq); + + REQUEST_SIZE_MATCH (xXagDestroyReq); + pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client, + (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess); + if (!pAppGrp) return XagBadAppGroup; + FreeResource ((XID)stuff->app_group, RT_NONE); + if (--XagCallbackRefCount == 0) + (void) DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL); + return client->noClientException; +} + +static +int ProcXagGetAttr (client) + register ClientPtr client; +{ + AppGroupPtr pAppGrp; + REQUEST (xXagGetAttrReq); + xXagGetAttrReply rep; + int n; + + REQUEST_SIZE_MATCH (xXagGetAttrReq); + pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client, + (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess); + if (!pAppGrp) return XagBadAppGroup; + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.default_root = pAppGrp->default_root; + rep.root_visual = pAppGrp->root_visual; + rep.default_colormap = pAppGrp->default_colormap; + rep.black_pixel = pAppGrp->black_pixel; + rep.white_pixel = pAppGrp->white_pixel; + rep.single_screen = pAppGrp->single_screen; + rep.app_group_leader = (pAppGrp->leader) ? 1 : 0; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swapl (&rep.default_root, n); + swapl (&rep.root_visual, n); + swapl (&rep.default_colormap, n); + swapl (&rep.black_pixel, n); + swapl (&rep.white_pixel, n); + } + WriteToClient (client, sizeof (xXagGetAttrReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcXagQuery (client) + register ClientPtr client; +{ + ClientPtr pClient; + AppGroupPtr pAppGrp; + REQUEST (xXagQueryReq); + int n; + + REQUEST_SIZE_MATCH (xXagQueryReq); + pClient = LookupClient (stuff->resource, client); + for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next) + for (n = 0; n < pAppGrp->nclients; n++) + if (pAppGrp->clients[n] == pClient) { + xXagQueryReply rep; + + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.app_group = pAppGrp->appgroupId; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swapl (&rep.app_group, n); + } + WriteToClient (client, sizeof (xXagQueryReply), (char *)&rep); + return client->noClientException; + } + + return BadMatch; +} + +static +int ProcXagCreateAssoc (client) + register ClientPtr client; +{ + REQUEST (xXagCreateAssocReq); + + REQUEST_SIZE_MATCH (xXagCreateAssocReq); +#ifdef WIN32 + if (stuff->window_type != XagWindowTypeWin32) +#else + if (stuff->window_type != XagWindowTypeX11) +#endif + return BadMatch; +#ifdef WIN32 /* and Mac, etc */ + if (!LocalClient (client)) + return BadAccess; +#endif + +/* Macintosh, OS/2, and MS-Windows servers have some work to do here */ + + return client->noClientException; +} + +static +int ProcXagDestroyAssoc (client) + register ClientPtr client; +{ + REQUEST (xXagDestroyAssocReq); + + REQUEST_SIZE_MATCH (xXagDestroyAssocReq); +/* Macintosh, OS/2, and MS-Windows servers have some work to do here */ + return client->noClientException; +} + +static +int ProcXagDispatch (client) + register ClientPtr client; +{ + REQUEST (xReq); + switch (stuff->data) + { + case X_XagQueryVersion: + return ProcXagQueryVersion (client); + case X_XagCreate: + return ProcXagCreate (client); + case X_XagDestroy: + return ProcXagDestroy (client); + case X_XagGetAttr: + return ProcXagGetAttr (client); + case X_XagQuery: + return ProcXagQuery (client); + case X_XagCreateAssoc: + return ProcXagCreateAssoc (client); + case X_XagDestroyAssoc: + return ProcXagDestroyAssoc (client); + default: + return BadRequest; + } +} + +static +int SProcXagQueryVersion (client) + register ClientPtr client; +{ + register int n; + REQUEST(xXagQueryVersionReq); + swaps(&stuff->length, n); + return ProcXagQueryVersion(client); +} + +static +int SProcXagCreate (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagCreateReq); + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXagCreateReq); + swapl (&stuff->app_group, n); + swapl (&stuff->attrib_mask, n); + SwapRestL (stuff); + return ProcXagCreate (client); +} + +static +int SProcXagDestroy (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagDestroyReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagDestroyReq); + swapl (&stuff->app_group, n); + return ProcXagDestroy (client); +} + +static +int SProcXagGetAttr (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagGetAttrReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagGetAttrReq); + swapl (&stuff->app_group, n); + return ProcXagGetAttr (client); +} + +static +int SProcXagQuery (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagQueryReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagQueryReq); + swapl (&stuff->resource, n); + return ProcXagQuery (client); +} + +static +int SProcXagCreateAssoc (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagCreateAssocReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagCreateAssocReq); + swapl (&stuff->window, n); + swapl (&stuff->window_type, n); + swaps (&stuff->system_window_len, n); + return ProcXagCreateAssoc (client); +} + +static +int SProcXagDestroyAssoc (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagDestroyAssocReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagDestroyAssocReq); + swapl (&stuff->window, n); + return ProcXagDestroyAssoc (client); +} + +static +int SProcXagDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XagQueryVersion: + return SProcXagQueryVersion (client); + case X_XagCreate: + return SProcXagCreate (client); + case X_XagDestroy: + return SProcXagDestroy (client); + case X_XagGetAttr: + return SProcXagGetAttr (client); + case X_XagQuery: + return SProcXagQuery (client); + case X_XagCreateAssoc: + return SProcXagCreateAssoc (client); + case X_XagDestroyAssoc: + return SProcXagDestroyAssoc (client); + default: + return BadRequest; + } +} + +Colormap XagDefaultColormap (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->default_colormap : None); +} + +VisualID XagRootVisual (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->root_visual : 0); +} + +ClientPtr XagLeader (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->leader : NULL); +} + +/* + * Return whether the Map request event should be sent to the appgroup leader. + * We don't want to send it to the leader when the window is on a different + * screen, e.g. a print screen. + */ +Bool XagIsControlledRoot (client, pParent) + ClientPtr client; + WindowPtr pParent; +{ + if (client->appgroup) { + if (client->appgroup->single_screen && + pParent->drawable.id == client->appgroup->default_root) + return TRUE; + else if (!pParent->parent) + return TRUE; + else + return FALSE; + } + return FALSE; +} + +void XagConnectionInfo (client, conn_prefix, conn_info, num_screen) + ClientPtr client; + xConnSetupPrefix** conn_prefix; + char** conn_info; + int* num_screen; +{ + if (client->appgroup && client->appgroup->ConnectionInfo) { + *conn_prefix = &client->appgroup->connSetupPrefix; + *conn_info = client->appgroup->ConnectionInfo; + *num_screen = ((xConnSetup*)(client->appgroup->ConnectionInfo))->numRoots; + } +} + +XID XagId (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->appgroupId : 0); +} + +void XagGetDeltaInfo (client, buf) + ClientPtr client; + CARD32* buf; +{ + *buf++ = (CARD32) client->appgroup->default_root; + *buf++ = (CARD32) client->appgroup->root_visual; + *buf++ = (CARD32) client->appgroup->default_colormap; + *buf++ = (CARD32) client->appgroup->black_pixel; + *buf = (CARD32) client->appgroup->white_pixel; +} + +void XagCallClientStateChange (client) + ClientPtr client; +{ + if (appGrpList) { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + XagClientStateChange (NULL, NULL, (pointer)&clientinfo); + } +} diff --git a/Xext/bigreq.c b/Xext/bigreq.c new file mode 100644 index 000000000..4f4bf5c02 --- /dev/null +++ b/Xext/bigreq.c @@ -0,0 +1,86 @@ +/* $Xorg: bigreq.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +/* + +Copyright 1992, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "bigreqstr.h" + +static unsigned char XBigReqCode; +static int ProcBigReqDispatch(); +static void BigReqResetProc(); + +void +BigReqExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(XBigReqExtensionName, 0, 0, + ProcBigReqDispatch, ProcBigReqDispatch, + BigReqResetProc, StandardMinorOpcode)) + XBigReqCode = (unsigned char)extEntry->base; + DeclareExtensionSecurity(XBigReqExtensionName, TRUE); +} + +/*ARGSUSED*/ +static void +BigReqResetProc (extEntry) + ExtensionEntry *extEntry; +{ +} + +static int +ProcBigReqDispatch (client) + register ClientPtr client; +{ + REQUEST(xBigReqEnableReq); + xBigReqEnableReply rep; + register int n; + + if (client->swapped) { + swaps(&stuff->length, n); + } + if (stuff->brReqType != X_BigReqEnable) + return BadRequest; + REQUEST_SIZE_MATCH(xBigReqEnableReq); + client->big_requests = TRUE; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.max_request_size = MAX_BIG_REQUEST_SIZE; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.max_request_size, n); + } + WriteToClient(client, sizeof(xBigReqEnableReply), (char *)&rep); + return(client->noClientException); +} diff --git a/Xext/cup.c b/Xext/cup.c new file mode 100644 index 000000000..4e8cf66b4 --- /dev/null +++ b/Xext/cup.c @@ -0,0 +1,340 @@ +/* $Xorg: cup.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +/* + +Copyright 1997, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XCUP_SERVER_ +#include "Xcupstr.h" +#include "Xfuncproto.h" + +#include "../os/osdep.h" + +static int ProcDispatch (), SProcDispatch (); +static void ResetProc (); + +static unsigned char ReqCode = 0; +static int ErrorBase; + +#if defined(WIN32) || defined(TESTWIN32) +#define HAVE_SPECIAL_DESKTOP_COLORS +#endif + +static xColorItem citems[] = { +#ifndef HAVE_SPECIAL_DESKTOP_COLORS +#define CUP_BLACK_PIXEL 0 +#define CUP_WHITE_PIXEL 1 + /* pix red green blue */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 0xffff, 0xffff, 0xffff, 0, 0 } +#else +#ifndef WIN32 + /* + This approximates the MS-Windows desktop colormap for testing + purposes but has black and white pixels in the typical Unix + locations, which should be switched if necessary if your system + has blackPixel and whitePixel swapped. No entries are provided + for colormap entries 254 and 255 because AllocColor/FindColor + will reuse entries zero and one. + */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 0xffff, 0xffff, 0xffff, 0, 0 }, + { 2, 0x8000, 0, 0, 0, 0 }, + { 3, 0, 0x8000, 0, 0, 0 }, + { 4, 0x8000, 0x8000, 0, 0, 0 }, + { 5, 0, 0, 0x8000, 0, 0 }, + { 6, 0x8000, 0, 0x8000, 0, 0 }, + { 7, 0, 0x8000, 0x8000, 0, 0 }, + { 8, 0xc000, 0xc000, 0xc000, 0, 0 }, + { 9, 0xc000, 0xdc00, 0xc000, 0, 0 }, + { 246, 0xa000, 0xa000, 0xa000, 0, 0 }, + { 247, 0x8000, 0x8000, 0x8000, 0, 0 }, + { 248, 0xffff, 0, 0, 0, 0 }, + { 249, 0, 0xffff, 0, 0, 0 }, + { 250, 0xffff, 0xffff, 0, 0, 0 }, + { 251, 0, 0, 0xffff, 0, 0 }, + { 252, 0xffff, 0, 0xffff, 0, 0 }, + { 253, 0, 0xffff, 0xffff, 0, 0 } +#else + /* + this is the MS-Windows desktop, adjusted for X's 16-bit color + specifications. + */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 0x8000, 0, 0, 0, 0 }, + { 2, 0, 0x8000, 0, 0, 0 }, + { 3, 0x8000, 0x8000, 0, 0, 0 }, + { 4, 0, 0, 0x8000, 0, 0 }, + { 5, 0x8000, 0, 0x8000, 0, 0 }, + { 6, 0, 0x8000, 0x8000, 0, 0 }, + { 7, 0xc000, 0xc000, 0xc000, 0, 0 }, + { 8, 0xc000, 0xdc00, 0xc000, 0, 0 }, + { 9, 0xa600, 0xca00, 0xf000, 0, 0 }, + { 246, 0xff00, 0xfb00, 0xf000, 0, 0 }, + { 247, 0xa000, 0xa000, 0xa400, 0, 0 }, + { 248, 0x8000, 0x8000, 0x8000, 0, 0 }, + { 249, 0xff00, 0, 0, 0, 0 }, + { 250, 0, 0xff00, 0, 0, 0 }, + { 251, 0xff00, 0xff00, 0, 0, 0 }, + { 252, 0, 0, 0xff00, 0, 0 }, + { 253, 0xff00, 0, 0xff00, 0, 0 }, + { 254, 0, 0xff00, 0xff00, 0, 0 }, + { 255, 0xff00, 0xff00, 0xff00, 0, 0 } +#endif +#endif +}; +#define NUM_DESKTOP_COLORS (sizeof citems / sizeof citems[0]) + +void +XcupExtensionInit () +{ + ExtensionEntry* extEntry; + + if (extEntry = AddExtension (XCUPNAME, + 0, + XcupNumberErrors, + ProcDispatch, + SProcDispatch, + ResetProc, + StandardMinorOpcode)) { + ReqCode = (unsigned char)extEntry->base; + ErrorBase = extEntry->errorBase; + } + + /* PC servers initialize the desktop colors (citems) here! */ +} + +/*ARGSUSED*/ +static +void ResetProc (extEntry) + ExtensionEntry* extEntry; +{ +} + +static +int ProcQueryVersion (client) + register ClientPtr client; +{ + REQUEST (xXcupQueryVersionReq); + xXcupQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xXcupQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.server_major_version = XCUP_MAJOR_VERSION; + rep.server_minor_version = XCUP_MINOR_VERSION; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swaps (&rep.server_major_version, n); + swaps (&rep.server_minor_version, n); + } + WriteToClient (client, sizeof (xXcupQueryVersionReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcGetReservedColormapEntries (client) + register ClientPtr client; +{ + REQUEST (xXcupGetReservedColormapEntriesReq); + xXcupGetReservedColormapEntriesReply rep; + xColorItem* cptr; + register int n; + + REQUEST_SIZE_MATCH (xXcupGetReservedColormapEntriesReq); + +#ifndef HAVE_SPECIAL_DESKTOP_COLORS + citems[CUP_BLACK_PIXEL].pixel = + screenInfo.screens[stuff->screen]->blackPixel; + citems[CUP_WHITE_PIXEL].pixel = + screenInfo.screens[stuff->screen]->whitePixel; +#endif + + rep.type = X_Reply; + rep.sequence_number = client->sequence; + rep.length = NUM_DESKTOP_COLORS * 3; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + } + WriteToClient (client, sizeof (xXcupGetReservedColormapEntriesReply), (char *)&rep); + for (n = 0, cptr = citems; n < NUM_DESKTOP_COLORS; n++, cptr++) { + if (client->swapped) SwapColorItem (cptr); + WriteToClient (client, SIZEOF(xColorItem), (char *)cptr); + } + return client->noClientException; +} + +static +int ProcStoreColors (client) + register ClientPtr client; +{ + REQUEST (xXcupStoreColorsReq); + ColormapPtr pcmp; + + REQUEST_AT_LEAST_SIZE (xXcupStoreColorsReq); + pcmp = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + + if (pcmp) { + int ncolors, n; + xXcupStoreColorsReply rep; + xColorItem* cptr; + Pixel pixel; + + if (!(pcmp->class & DynamicClass)) + return BadMatch; + + ncolors = (client->req_len << 2) - SIZEOF (xXcupStoreColorsReq); + if (ncolors % SIZEOF(xColorItem)) + return BadLength; + + ncolors /= SIZEOF (xColorItem); + + + for (n = 0, cptr = (xColorItem*) &stuff[1]; n < ncolors; n++) { + Pixel pixel = cptr->pixel; + + if (AllocColor (pcmp, + &cptr->red, &cptr->green, &cptr->blue, + &pixel, client->index) == Success) { + cptr->pixel = pixel; + cptr->flags = 0x08; + } else + cptr->flags = 0; + cptr = (xColorItem*) (((char*)cptr) + SIZEOF(xColorItem)); + } + + rep.type = X_Reply; + rep.sequence_number = client->sequence; + rep.length = ncolors * 3; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + } + WriteToClient (client, sizeof (xXcupGetReservedColormapEntriesReply), (char *)&rep); + for (n = 0, cptr = (xColorItem*) &stuff[1]; n < ncolors; n++) { + if (client->swapped) SwapColorItem (cptr); + WriteToClient (client, SIZEOF(xColorItem), (char *)cptr); + cptr = (xColorItem*) (((char*)cptr) + SIZEOF(xColorItem)); + } + return client->noClientException; + } else { + client->errorValue = stuff->cmap; + return BadColor; + } +} + +static +int ProcDispatch (client) + register ClientPtr client; +{ + REQUEST (xReq); + switch (stuff->data) + { + case X_XcupQueryVersion: + return ProcQueryVersion (client); + case X_XcupGetReservedColormapEntries: + return ProcGetReservedColormapEntries (client); + case X_XcupStoreColors: + return ProcStoreColors (client); + default: + return BadRequest; + } +} + +static +int SProcQueryVersion (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xXcupQueryVersionReq); + swaps(&stuff->length, n); + return ProcQueryVersion(client); +} + +static +int SProcGetReservedColormapEntries (client) + ClientPtr client; +{ + register int n; + + REQUEST (xXcupGetReservedColormapEntriesReq); + swaps (&stuff->length, n); + swapl (&stuff->screen, n); + REQUEST_AT_LEAST_SIZE (xXcupGetReservedColormapEntriesReq); + return ProcGetReservedColormapEntries (client); +} + +static +int SProcStoreColors (client) + ClientPtr client; +{ + register int n; + int count; + xColorItem* pItem; + + REQUEST (xXcupStoreColorsReq); + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXcupStoreColorsReq); + swapl(&stuff->cmap, n); + pItem = (xColorItem*) &stuff[1]; + for(count = LengthRestB(stuff)/sizeof(xColorItem); --count >= 0; ) + SwapColorItem(pItem++); + return ProcStoreColors (client); +} + +static +int SProcDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XcupQueryVersion: + return SProcQueryVersion (client); + case X_XcupGetReservedColormapEntries: + return SProcGetReservedColormapEntries (client); + case X_XcupStoreColors: + return SProcStoreColors (client); + default: + return BadRequest; + } +} + + diff --git a/Xext/dpms.c b/Xext/dpms.c new file mode 100644 index 000000000..ebc992dc2 --- /dev/null +++ b/Xext/dpms.c @@ -0,0 +1,433 @@ +/* $Xorg: dpms.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */ +/***************************************************************** + +Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "dpms.h" +#include "dpmsstr.h" +#include + +static unsigned char DPMSCode; +static int ProcDPMSDispatch(), SProcDPMSDispatch(); +static void DPMSResetProc(); +static int ProcDPMSGetVersion(), SProcDPMSGetVersion(); +static int ProcDPMSGetTimeouts(), SProcDPMSGetTimeouts(); +static int ProcDPMSSetTimeouts(), ProcDPMSSetTimeouts(); +static int ProcDPMSEnable(), ProcDPMSEnable(); +static int ProcDPMSDisable(), ProcDPMSDisable(); +static int ProcDPMSForceLevel(), ProcDPMSForceLevel(); + +extern void Swap32Write(); /* XXX should be in header file */ +extern CARD32 ScreenSaverTime; +extern CARD32 DPMSStandbyTime; +extern CARD32 DPMSSuspendTime; +extern CARD32 DPMSOffTime; +extern BOOL DPMSCapableFlag; +extern BOOL DPMSEnabled; +extern CARD16 DPMSPowerLevel; + +void +DPMSExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(DPMSExtensionName, 0, 0, + ProcDPMSDispatch, SProcDPMSDispatch, + DPMSResetProc, StandardMinorOpcode)) + DPMSCode = (unsigned char)extEntry->base; + return; +} + +/*ARGSUSED*/ +static void +DPMSResetProc (extEntry) + ExtensionEntry *extEntry; +{ +} + +static int +ProcDPMSGetVersion(client) + register ClientPtr client; +{ + REQUEST(xDPMSGetVersionReq); + xDPMSGetVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = DPMSMajorVersion; + rep.minorVersion = DPMSMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xDPMSGetVersionReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSCapable(client) + register ClientPtr client; +{ + REQUEST(xDPMSCapableReq); + xDPMSCapableReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.capable = DPMSCapableFlag; + + WriteToClient(client, sizeof(xDPMSCapableReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSGetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSGetTimeoutsReq); + xDPMSGetTimeoutsReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.standby = DPMSStandbyTime / MILLI_PER_SECOND; + rep.suspend = DPMSSuspendTime / MILLI_PER_SECOND; + rep.off = DPMSOffTime / MILLI_PER_SECOND; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.standby, n); + swaps(&rep.suspend, n); + swaps(&rep.off, n); + } + WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSSetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSSetTimeoutsReq); + register int n; + + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + if ((stuff->off != 0)&&(stuff->off < stuff->suspend)) + { + client->errorValue = stuff->off; + return BadValue; + } + if ((stuff->suspend != 0)&&(stuff->suspend < stuff->standby)) + { + client->errorValue = stuff->suspend; + return BadValue; + } + + DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND; + DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND; + DPMSOffTime = stuff->off * MILLI_PER_SECOND; + + return(client->noClientException); +} + +static int +ProcDPMSEnable(client) + register ClientPtr client; +{ + REQUEST(xDPMSEnableReq); + + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + if (DPMSCapableFlag) + DPMSEnabled = TRUE; + + return(client->noClientException); +} + +static int +ProcDPMSDisable(client) + register ClientPtr client; +{ + REQUEST(xDPMSDisableReq); + + REQUEST_SIZE_MATCH(xDPMSDisableReq); + +#ifdef DPMSExtension + DPMSSet(DPMSModeOn); +#endif + + DPMSEnabled = FALSE; + + return(client->noClientException); +} + +static int +ProcDPMSForceLevel(client) + register ClientPtr client; +{ + REQUEST(xDPMSForceLevelReq); + + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + if (!DPMSEnabled) + return BadMatch; + + if (stuff->level == DPMSModeOn) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis(); + } +#if 0 + else if (stuff->level == DPMSModeStandby) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis() - DPMSStandbyTime; + } else if (stuff->level == DPMSModeSuspend) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis() - DPMSSuspendTime; + } else if (stuff->level == DPMSModeOff) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis() - DPMSOffTime; + } else { + client->errorValue = stuff->level; + return BadValue; + } +#endif + +#ifdef DPMSExtension + DPMSSet(stuff->level); +#endif + + return(client->noClientException); +} + +static int +ProcDPMSInfo(client) + register ClientPtr client; +{ + REQUEST(xDPMSInfoReq); + xDPMSInfoReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.power_level = DPMSPowerLevel; + rep.state = DPMSEnabled; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.power_level, n); + } + WriteToClient(client, sizeof(xDPMSInfoReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_DPMSGetVersion: + return ProcDPMSGetVersion(client); + case X_DPMSCapable: + return ProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return ProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return ProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return ProcDPMSEnable(client); + case X_DPMSDisable: + return ProcDPMSDisable(client); + case X_DPMSForceLevel: + return ProcDPMSForceLevel(client); + case X_DPMSInfo: + return ProcDPMSInfo(client); + default: + return BadRequest; + } +} + +static int +SProcDPMSGetVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xDPMSGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return ProcDPMSGetVersion(client); +} + +static int +SProcDPMSCapable(client) + register ClientPtr client; +{ + REQUEST(xDPMSCapableReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + return ProcDPMSCapable(client); +} + +static int +SProcDPMSGetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSGetTimeoutsReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + return ProcDPMSGetTimeouts(client); +} + +static int +SProcDPMSSetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSSetTimeoutsReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + swaps(&stuff->standby, n); + swaps(&stuff->suspend, n); + swaps(&stuff->off, n); + return ProcDPMSSetTimeouts(client); +} + +static int +SProcDPMSEnable(client) + register ClientPtr client; +{ + REQUEST(xDPMSEnableReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + return ProcDPMSEnable(client); +} + +static int +SProcDPMSDisable(client) + register ClientPtr client; +{ + REQUEST(xDPMSDisableReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSDisableReq); + + return ProcDPMSDisable(client); +} + +static int +SProcDPMSForceLevel(client) + register ClientPtr client; +{ + REQUEST(xDPMSForceLevelReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + swaps(&stuff->level, n); + + return ProcDPMSForceLevel(client); +} + +static int +SProcDPMSInfo(client) + register ClientPtr client; +{ + REQUEST(xDPMSInfoReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + return ProcDPMSInfo(client); +} + +static int +SProcDPMSDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_DPMSGetVersion: + return SProcDPMSGetVersion(client); + case X_DPMSCapable: + return SProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return SProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return SProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return SProcDPMSEnable(client); + case X_DPMSDisable: + return SProcDPMSDisable(client); + case X_DPMSForceLevel: + return SProcDPMSForceLevel(client); + case X_DPMSInfo: + return SProcDPMSInfo(client); + default: + return BadRequest; + } +} diff --git a/Xext/dpmsstubs.c b/Xext/dpmsstubs.c new file mode 100644 index 000000000..6f635f42b --- /dev/null +++ b/Xext/dpmsstubs.c @@ -0,0 +1,48 @@ +/* $Xorg: dpmsstubs.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */ +/***************************************************************** + +Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +typedef int Bool; + +#define FALSE 0 + +Bool DPMSSupported() +{ + return FALSE; +} + +int DPSMGet(level) + int *level; +{ + return -1; +} + +void DPMSSet(level) +{ + +} diff --git a/Xext/mbuf.c b/Xext/mbuf.c new file mode 100644 index 000000000..c65ed3dd2 --- /dev/null +++ b/Xext/mbuf.c @@ -0,0 +1,2041 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mbuf.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#include "multibufst.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" +#ifndef WIN32 +#include +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#endif + +/* given an OtherClientPtr obj, get the ClientPtr */ +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +/* given a MultibufferPtr b, get the ClientPtr */ +#define bClient(b) (clients[CLIENT_ID(b->pPixmap->drawable.id)]) + +#define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask) + +#ifdef PANORAMIX +extern int PanoramiXNumScreens; +extern Bool noPanoramiXExtension; +extern PanoramiXWindow *PanoramiXWinRoot; +extern PanoramiXPmap *PanoramiXPmapRoot; +extern PanoramiXData *panoramiXdataPtr; +#endif + +/* The _Multibuffer and _Multibuffers structures below refer to each other, + * so we need this forward declaration + */ + +typedef struct _Multibuffers *MultibuffersPtr; + +/* + * per-Multibuffer data + */ + +typedef struct _Multibuffer { + MultibuffersPtr pMultibuffers; /* associated window data */ + Mask eventMask; /* MultibufferClobberNotifyMask|ExposureMask|MultibufferUpdateNotifyMask */ + Mask otherEventMask; /* mask of all other clients event masks */ + OtherClients *otherClients; /* other clients that want events */ + int number; /* index of this buffer into array */ + int side; /* always Mono */ + int clobber; /* Unclobbered, PartiallyClobbered, FullClobbered */ + PixmapPtr pPixmap; /* associated pixmap */ +} MultibufferRec, *MultibufferPtr; + +/* + * per-window data + */ + +typedef struct _Multibuffers { + WindowPtr pWindow; /* associated window */ + int numMultibuffer; /* count of buffers */ + int refcnt; /* ref count for delete */ + int displayedMultibuffer; /* currently active buffer */ + int updateAction; /* Undefined, Background, Untouched, Copied */ + int updateHint; /* Frequent, Intermittent, Static */ + int windowMode; /* always Mono */ + + TimeStamp lastUpdate; /* time of last update */ + + unsigned short width, height; /* last known window size */ + short x, y; /* for static gravity */ + + MultibufferPtr buffers; /* array of numMultibuffer buffers */ +} MultibuffersRec; + +/* + * per-screen data + */ +typedef struct _MultibufferScreen { + Bool (*PositionWindow)(); +} MultibufferScreenRec, *MultibufferScreenPtr; + +/* + * per display-image-buffers request data. + */ + +typedef struct _DisplayRequest { + struct _DisplayRequest *next; + TimeStamp activateTime; + ClientPtr pClient; + XID id; +} DisplayRequestRec, *DisplayRequestPtr; + +static unsigned char MultibufferReqCode; +static int MultibufferEventBase; +static int MultibufferErrorBase; +int MultibufferScreenIndex = -1; +int MultibufferWindowIndex = -1; + +static void PerformDisplayRequest (); +static void DisposeDisplayRequest (); +static Bool QueueDisplayRequest (); + +static void BumpTimeStamp (); + +void MultibufferExpose (); +void MultibufferUpdate (); +static void AliasMultibuffer (); +int CreateImageBuffers (); +void DestroyImageBuffers (); +int DisplayImageBuffers (); +static void RecalculateMultibufferOtherEvents (); +static int EventSelectForMultibuffer(); + + +/* + * The Pixmap associated with a buffer can be found as a resource + * with this type + */ +RESTYPE MultibufferDrawableResType; +static int MultibufferDrawableDelete (); +/* + * The per-buffer data can be found as a resource with this type. + * the resource id of the per-buffer data is the same as the resource + * id of the pixmap + */ +static RESTYPE MultibufferResType; +static int MultibufferDelete (); +/* + * The per-window data can be found as a resource with this type, + * using the window resource id + */ +static RESTYPE MultibuffersResType; +static int MultibuffersDelete (); +/* + * Clients other than the buffer creator attach event masks in + * OtherClient structures; each has a resource of this type. + */ +static RESTYPE OtherClientResType; +static int OtherClientDelete (); + +/**************** + * MultibufferExtensionInit + * + * Called from InitExtensions in main() + * + ****************/ + +static int ProcMultibufferDispatch(), SProcMultibufferDispatch(); +static void MultibufferResetProc(); +static void SClobberNotifyEvent(), SUpdateNotifyEvent(); +static Bool MultibufferPositionWindow(); + +void +MultibufferExtensionInit() +{ + ExtensionEntry *extEntry; + int i, j; + ScreenPtr pScreen; + MultibufferScreenPtr pMultibufferScreen; + + /* + * allocate private pointers in windows and screens. Allocating + * window privates may seem like an unnecessary expense, but every + * PositionWindow call must check to see if the window is + * multi-buffered; a resource lookup is too expensive. + */ + MultibufferScreenIndex = AllocateScreenPrivateIndex (); + if (MultibufferScreenIndex < 0) + return; + MultibufferWindowIndex = AllocateWindowPrivateIndex (); + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + if (!AllocateWindowPrivate (pScreen, MultibufferWindowIndex, 0) || + !(pMultibufferScreen = (MultibufferScreenPtr) xalloc (sizeof (MultibufferScreenRec)))) + { + for (j = 0; j < i; j++) + xfree (screenInfo.screens[j]->devPrivates[MultibufferScreenIndex].ptr); + return; + } + pScreen->devPrivates[MultibufferScreenIndex].ptr = (pointer) pMultibufferScreen; + /* + * wrap PositionWindow to resize the pixmap when the window + * changes size + */ + pMultibufferScreen->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = MultibufferPositionWindow; + } + /* + * create the resource types + */ + MultibufferDrawableResType = + CreateNewResourceType(MultibufferDrawableDelete)|RC_CACHED|RC_DRAWABLE; + MultibufferResType = CreateNewResourceType(MultibufferDelete); + MultibuffersResType = CreateNewResourceType(MultibuffersDelete); + OtherClientResType = CreateNewResourceType(OtherClientDelete); + if (MultibufferDrawableResType && MultibufferResType && + MultibuffersResType && OtherClientResType && + (extEntry = AddExtension(MULTIBUFFER_PROTOCOL_NAME, + MultibufferNumberEvents, + MultibufferNumberErrors, + ProcMultibufferDispatch, SProcMultibufferDispatch, + MultibufferResetProc, StandardMinorOpcode))) + { + MultibufferReqCode = (unsigned char)extEntry->base; + MultibufferEventBase = extEntry->eventBase; + MultibufferErrorBase = extEntry->errorBase; + EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = SClobberNotifyEvent; + EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = SUpdateNotifyEvent; + } +} + +/*ARGSUSED*/ +static void +MultibufferResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + ScreenPtr pScreen; + MultibufferScreenPtr pMultibufferScreen; + + if (MultibufferScreenIndex < 0) + return; + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + if (pScreen->devPrivates[MultibufferScreenIndex].ptr) + { + pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr; + pScreen->PositionWindow = pMultibufferScreen->PositionWindow; + xfree (pMultibufferScreen); + } + } +} + +static int +ProcGetBufferVersion (client) + register ClientPtr client; +{ + REQUEST(xMbufGetBufferVersionReq); + xMbufGetBufferVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = MULTIBUFFER_MAJOR_VERSION; + rep.minorVersion = MULTIBUFFER_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof (xMbufGetBufferVersionReply), (char *)&rep); + return (client->noClientException); +} + +static void +SetupBackgroundPainter (pWin, pGC) + WindowPtr pWin; + GCPtr pGC; +{ + pointer gcvalues[4]; + int ts_x_origin, ts_y_origin; + PixUnion background; + int backgroundState; + Mask gcmask; + + /* + * First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + + ts_x_origin = ts_y_origin = 0; + while (pWin->backgroundState == ParentRelative) { + ts_x_origin -= pWin->origin.x; + ts_y_origin -= pWin->origin.y; + pWin = pWin->parent; + } + backgroundState = pWin->backgroundState; + background = pWin->background; + + switch (backgroundState) + { + case BackgroundPixel: + gcvalues[0] = (pointer) background.pixel; + gcvalues[1] = (pointer) FillSolid; + gcmask = GCForeground|GCFillStyle; + break; + + case BackgroundPixmap: + gcvalues[0] = (pointer) FillTiled; + gcvalues[1] = (pointer) background.pixmap; + gcvalues[2] = (pointer) ts_x_origin; + gcvalues[3] = (pointer) ts_y_origin; + gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; + break; + + default: + gcvalues[0] = (pointer) GXnoop; + gcmask = GCFunction; + } + DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE); +} + +int +CreateImageBuffers (pWin, nbuf, ids, action, hint) + WindowPtr pWin; + int nbuf; + XID *ids; + int action; + int hint; +{ + MultibuffersPtr pMultibuffers; + MultibufferPtr pMultibuffer; + ScreenPtr pScreen; + int width, height, depth; + int i; + GCPtr pClearGC = NULL; + xRectangle clearRect; + + DestroyImageBuffers(pWin); + pMultibuffers = (MultibuffersPtr) xalloc (sizeof (MultibuffersRec) + + nbuf * sizeof (MultibufferRec)); + if (!pMultibuffers) + return BadAlloc; + pMultibuffers->pWindow = pWin; + pMultibuffers->buffers = (MultibufferPtr) (pMultibuffers + 1); + pMultibuffers->refcnt = pMultibuffers->numMultibuffer = 0; + if (!AddResource (pWin->drawable.id, MultibuffersResType, (pointer) pMultibuffers)) + return BadAlloc; + width = pWin->drawable.width; + height = pWin->drawable.height; + depth = pWin->drawable.depth; + pScreen = pWin->drawable.pScreen; + + if (pWin->backgroundState != None) + { + pClearGC = GetScratchGC (pWin->drawable.depth, pScreen); + SetupBackgroundPainter (pWin, pClearGC); + clearRect.x = clearRect.y = 0; + clearRect.width = width; + clearRect.height = height; + } + + for (i = 0; i < nbuf; i++) + { + pMultibuffer = &pMultibuffers->buffers[i]; + pMultibuffer->eventMask = 0L; + pMultibuffer->otherEventMask = 0L; + pMultibuffer->otherClients = (OtherClientsPtr) NULL; + pMultibuffer->number = i; + pMultibuffer->side = MultibufferSideMono; + pMultibuffer->clobber = MultibufferUnclobbered; + pMultibuffer->pMultibuffers = pMultibuffers; + if (!AddResource (ids[i], MultibufferResType, (pointer) pMultibuffer)) + break; + pMultibuffer->pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth); + if (!pMultibuffer->pPixmap) + break; + if (!AddResource (ids[i], MultibufferDrawableResType, (pointer) pMultibuffer->pPixmap)) + { + FreeResource (ids[i], MultibufferResType); + (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap); + break; + } + pMultibuffer->pPixmap->drawable.id = ids[i]; + + if (i > 0 && pClearGC) + { + ValidateGC((DrawablePtr)pMultibuffer->pPixmap, pClearGC); + (*pClearGC->ops->PolyFillRect)((DrawablePtr)pMultibuffer->pPixmap, + pClearGC, 1, &clearRect); + } + } + pMultibuffers->numMultibuffer = i; + pMultibuffers->refcnt = i; + pMultibuffers->displayedMultibuffer = -1; + if (i > 0) + AliasMultibuffer (pMultibuffers, 0); + pMultibuffers->updateAction = action; + pMultibuffers->updateHint = hint; + pMultibuffers->windowMode = MultibufferModeMono; + pMultibuffers->lastUpdate.months = 0; + pMultibuffers->lastUpdate.milliseconds = 0; + pMultibuffers->width = width; + pMultibuffers->height = height; + pWin->devPrivates[MultibufferWindowIndex].ptr = (pointer) pMultibuffers; + if (pClearGC) FreeScratchGC(pClearGC); + return Success; +} + +#ifdef PANORAMIX +static int +ProcPanoramiXCreateImageBuffers (client) + register ClientPtr client; +{ + REQUEST(xMbufCreateImageBuffersReq); + + register int result; + int i, j, k, len; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *next; + PanoramiXWindow *pPanoramiXids; + PanoramiXWindow *pPanoramiXPrev_ids; + PanoramiXPmap *local; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + CARD32 *value, *orig_ids; + XID *ids; + XID ID; + DrawablePtr pDrawable; + + REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->window); + IF_RETURN(!pPanoramiXWin, BadRequest); + len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2); + ids = (XID *)ALLOCATE_LOCAL(sizeof(XID)*len); + orig_ids = (XID *)ALLOCATE_LOCAL(sizeof(XID)*len); + if (!ids) + return BadAlloc; + memcpy((char *)orig_ids, (char *) &stuff[1], len * sizeof(XID)); + value = (CARD32 *)&stuff[1]; + /* New resources are pixmaps */ + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->window = pPanoramiXWin->info[j].id; + for (i = 0; i < len; i++) { + ids[i] = (XID)orig_ids[i]; + /* These will be MultibufferDrawableResType & MultibufferResType */ + pPanoramiXPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXPmap, ids[i]); + if (!pPanoramiXPmap) { + local = (PanoramiXWindow *)Xcalloc(sizeof(PanoramiXWindow)); + for (k = 0; k <= PanoramiXNumScreens - 1; k++) { + ID = k ? FakeClientID(client->index) : ids[i]; + local->info[k].id = ID; + } + local->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot); + pPanoramiXPmap->next = local; + value[i] = local->info[j].id; + }else + value[i] = pPanoramiXPmap->info[j].id; + } + if (!j) + noPanoramiXExtension = TRUE; + result = ProcCreateImageBuffers (client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + if (result != Success) { + if (ids) + Xfree(ids); + if (orig_ids) + Xfree(orig_ids); + if (local) + Xfree(local); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcCreateImageBuffers (client) + register ClientPtr client; +{ + REQUEST(xMbufCreateImageBuffersReq); + xMbufCreateImageBuffersReply rep; + register int n; + WindowPtr pWin; + XID *ids; + int len, nbuf; + int i; + int err; + + REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq); + len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2); + if (len == 0) + return BadLength; + if (!(pWin = LookupWindow (stuff->window, client))) + return BadWindow; + if (pWin->drawable.class == InputOnly) + return BadMatch; + switch (stuff->updateAction) + { + case MultibufferUpdateActionUndefined: + case MultibufferUpdateActionBackground: + case MultibufferUpdateActionUntouched: + case MultibufferUpdateActionCopied: + break; + default: + client->errorValue = stuff->updateAction; + return BadValue; + } + switch (stuff->updateHint) + { + case MultibufferUpdateHintFrequent: + case MultibufferUpdateHintIntermittent: + case MultibufferUpdateHintStatic: + break; + default: + client->errorValue = stuff->updateHint; + return BadValue; + } + nbuf = len; + ids = (XID *) &stuff[1]; + for (i = 0; i < nbuf; i++) + { + LEGAL_NEW_RESOURCE(ids[i], client); + } + err = CreateImageBuffers (pWin, nbuf, ids, + stuff->updateAction, stuff->updateHint); + if (err != Success) + return err; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.numberBuffer = ((MultibuffersPtr) (pWin->devPrivates[MultibufferWindowIndex].ptr))->numMultibuffer; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.numberBuffer, n); + } +#ifdef PANORAMIX + if (noPanoramiXExtension) +#endif + WriteToClient(client, sizeof (xMbufCreateImageBuffersReply), (char*)&rep); + return (client->noClientException); +} + +static int +ProcDisplayImageBuffers (client) + register ClientPtr client; +{ + REQUEST(xMbufDisplayImageBuffersReq); + MultibufferPtr *pMultibuffer; + MultibuffersPtr *ppMultibuffers; + int nbuf; + XID *ids; + int i, j; + CARD32 minDelay; + TimeStamp activateTime, bufferTime; + +#ifdef PANORAMIX + WindowPtr pWndw; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + MultibufferPtr *pScrn0Multibuffer; + MultibuffersPtr *ppScrn0Multibuffers; + int k; + int panoramiX_buf = 0; + Bool FoundScreen; + +#endif + + REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq); + nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2); + if (!nbuf) + return Success; + minDelay = stuff->minDelay; + ids = (XID *) &stuff[1]; +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + int maxbuf = 0; + maxbuf = nbuf * PanoramiXNumScreens; + ppScrn0Multibuffers = (MultibuffersPtr *) xalloc(maxbuf * sizeof (MultibuffersPtr)); + pScrn0Multibuffer = (MultibufferPtr *) xalloc (maxbuf * sizeof(MultibufferPtr)); + if (!ppScrn0Multibuffers || !pScrn0Multibuffer) + { + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + xfree (ppScrn0Multibuffers); + xfree (pScrn0Multibuffer); + client->errorValue = 0; + return BadAlloc; + } + } +#endif + ppMultibuffers = (MultibuffersPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibuffersPtr)); + pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibufferPtr)); + if (!ppMultibuffers || !pMultibuffer) + { + if (ppMultibuffers) DEALLOCATE_LOCAL(ppMultibuffers); + if (pMultibuffer) DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = 0; + return BadAlloc; + } + activateTime.months = 0; + activateTime.milliseconds = 0; + for (i = 0; i < nbuf; i++) + { +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + pPanoramiXPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXPmap, ids[i]); + if (!pPanoramiXPmap){ + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + xfree (ppMultibuffers); + xfree (pMultibuffer); + client->errorValue = ids[i]; + return MultibufferErrorBase + MultibufferBadBuffer; + } + FoundScreen = FALSE; + pScrn0Multibuffer[panoramiX_buf] = (MultibufferPtr) + LookupIDByType (ids[i], MultibufferResType); + ppScrn0Multibuffers[i] = pScrn0Multibuffer[i]->pMultibuffers; + pWndw = ppScrn0Multibuffers[i]->pWindow; + for (k = 0; (k < PanoramiXNumScreens && !FoundScreen); k++) { + pMultibuffer[panoramiX_buf] = (MultibufferPtr) + LookupIDByType (pPanoramiXPmap->info[k].id, MultibufferResType); + if (!pMultibuffer[i]) + { + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + xfree (ppMultibuffers); + xfree (pMultibuffer); + client->errorValue = ids[i]; + return MultibufferErrorBase + MultibufferBadBuffer; + } + ppMultibuffers[panoramiX_buf] = pMultibuffer[panoramiX_buf]->pMultibuffers; + /* Figure out where the buffer resides, which screens */ + if ( ((pWndw->drawable.x < 0) && + (pWndw->drawable.x + pWndw->drawable.width < 0)) + || ( (pWndw->drawable.x > + panoramiXdataPtr[k].x + panoramiXdataPtr[k].width) && + (pWndw->drawable.x + pWndw->drawable.width > + panoramiXdataPtr[k].x + panoramiXdataPtr[k].width))) + /* its not on screen - k -, try next screen */ + continue; + if ( ((pWndw->drawable.y < 0) && + (pWndw->drawable.y + pWndw->drawable.height < 0)) + || ( (pWndw->drawable.y > + panoramiXdataPtr[k].y + panoramiXdataPtr[k].height) && + (pWndw->drawable.y + pWndw->drawable.height > + panoramiXdataPtr[k].y + panoramiXdataPtr[k].height))) + /* its not on screen - k -, try next screen */ + continue; + + /* The window resides on screen k, which means we need to + keep the buffer information for this screen */ + panoramiX_buf++; + + /* Is it only on this screen, or does it enter onto another + screen */ + if ( ((pWndw->drawable.x + pWndw->drawable.width) <= + (panoramiXdataPtr[k].x + panoramiXdataPtr[k].width)) && + ((pWndw->drawable.y + pWndw->drawable.height) <= + (panoramiXdataPtr[k].y + + panoramiXdataPtr[k].height )) ) + FoundScreen = TRUE; + } /* for each screen k */ + for (j = 0; j < i; j++) + { + if (ppScrn0Multibuffers[i] == ppScrn0Multibuffers[j]) + { + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + DEALLOCATE_LOCAL(ppScrn0Multibuffers); + DEALLOCATE_LOCAL(pScrn0Multibuffer); + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = ids[i]; + return BadMatch; + } + } + bufferTime = ppScrn0Multibuffers[i]->lastUpdate; + }else { +#endif + pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], +MultibufferResType); + if (!pMultibuffer[i]) + { + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = ids[i]; + return MultibufferErrorBase + MultibufferBadBuffer; + } + ppMultibuffers[i] = pMultibuffer[i]->pMultibuffers; + for (j = 0; j < i; j++) + { + if (ppMultibuffers[i] == ppMultibuffers[j]) + { + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = ids[i]; + return BadMatch; + } + } + bufferTime = ppMultibuffers[i]->lastUpdate; +#ifdef PANORAMIX + } +#endif + BumpTimeStamp (&bufferTime, minDelay); + if (CompareTimeStamps (bufferTime, activateTime) == LATER) + activateTime = bufferTime; + } + UpdateCurrentTime (); + if (CompareTimeStamps (activateTime, currentTime) == LATER && + QueueDisplayRequest (client, activateTime)) + { + ; + } + else +#ifdef PANORAMIX + if (!noPanoramiXExtension){ + PerformDisplayRequest (ppMultibuffers, pMultibuffer, panoramiX_buf); + }else +#endif + PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf); + +#ifdef PANORAMIX + if (!noPanoramiXExtension){ + DEALLOCATE_LOCAL(ppScrn0Multibuffers); + DEALLOCATE_LOCAL(pScrn0Multibuffer); + } +#endif + + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + return Success; +} + +#ifdef PANORAMIX +static int +ProcPanoramiXDestroyImageBuffers (client) + ClientPtr client; +{ + REQUEST (xMbufDestroyImageBuffersReq); + WindowPtr pWin; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->window); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->window = pPanoramiXWin->info[j].id; + result = ProcDestroyImageBuffers (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcDestroyImageBuffers (client) + register ClientPtr client; +{ + REQUEST (xMbufDestroyImageBuffersReq); + WindowPtr pWin; + + REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq); + if (!(pWin = LookupWindow (stuff->window, client))) + return BadWindow; + DestroyImageBuffers (pWin); + return Success; +} + +#ifdef PANORAMIX +static int +ProcPanoramiXSetMBufferAttributes (client) + ClientPtr client; +{ + REQUEST (xMbufSetMBufferAttributesReq); + WindowPtr pWin; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH (xMbufSetMBufferAttributesReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->window); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->window = pPanoramiXWin->info[j].id; + result = ProcSetMBufferAttributes (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif +#ifdef PANORAMIX +int +#else +static int +#endif +ProcSetMBufferAttributes (client) + register ClientPtr client; +{ + REQUEST (xMbufSetMBufferAttributesReq); + WindowPtr pWin; + MultibuffersPtr pMultibuffers; + int len; + Mask vmask; + Mask index; + CARD32 updateHint; + XID *vlist; + + REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType); + if (!pMultibuffers) + return BadMatch; + len = stuff->length - (sizeof (xMbufSetMBufferAttributesReq) >> 2); + vmask = stuff->valueMask; + if (len != Ones (vmask)) + return BadLength; + vlist = (XID *) &stuff[1]; + while (vmask) + { + index = (Mask) lowbit (vmask); + vmask &= ~index; + switch (index) + { + case MultibufferWindowUpdateHint: + updateHint = (CARD32) *vlist; + switch (updateHint) + { + case MultibufferUpdateHintFrequent: + case MultibufferUpdateHintIntermittent: + case MultibufferUpdateHintStatic: + pMultibuffers->updateHint = updateHint; + break; + default: + client->errorValue = updateHint; + return BadValue; + } + vlist++; + break; + default: + client->errorValue = stuff->valueMask; + return BadValue; + } + } + return Success; +} + +static int +ProcGetMBufferAttributes (client) + ClientPtr client; +{ + REQUEST (xMbufGetMBufferAttributesReq); + WindowPtr pWin; + MultibuffersPtr pMultibuffers; + XID *ids; + xMbufGetMBufferAttributesReply rep; + int i, n; + + REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType); + if (!pMultibuffers) + return BadAccess; + ids = (XID *) ALLOCATE_LOCAL (pMultibuffers->numMultibuffer * sizeof (XID)); + if (!ids) + return BadAlloc; + for (i = 0; i < pMultibuffers->numMultibuffer; i++) + ids[i] = pMultibuffers->buffers[i].pPixmap->drawable.id; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = pMultibuffers->numMultibuffer; + rep.displayedBuffer = pMultibuffers->displayedMultibuffer; + rep.updateAction = pMultibuffers->updateAction; + rep.updateHint = pMultibuffers->updateHint; + rep.windowMode = pMultibuffers->windowMode; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.displayedBuffer, n); + SwapLongs (ids, pMultibuffers->numMultibuffer); + } + WriteToClient (client, sizeof(xMbufGetMBufferAttributesReply), + (char *)&rep); + WriteToClient (client, (int)(pMultibuffers->numMultibuffer * sizeof (XID)), + (char *)ids); + DEALLOCATE_LOCAL((pointer) ids); + return client->noClientException; +} + +static int +ProcSetBufferAttributes (client) + register ClientPtr client; +{ + REQUEST(xMbufSetBufferAttributesReq); + MultibufferPtr pMultibuffer; + int len; + Mask vmask, index; + XID *vlist; + Mask eventMask; + int result; + + REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq); + pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType); + if (!pMultibuffer) + return MultibufferErrorBase + MultibufferBadBuffer; + len = stuff->length - (sizeof (xMbufSetBufferAttributesReq) >> 2); + vmask = stuff->valueMask; + if (len != Ones (vmask)) + return BadLength; + vlist = (XID *) &stuff[1]; + while (vmask) + { + index = (Mask) lowbit (vmask); + vmask &= ~index; + switch (index) + { + case MultibufferBufferEventMask: + eventMask = (Mask) *vlist; + vlist++; + result = EventSelectForMultibuffer (pMultibuffer, client, eventMask); + if (result != Success) + return result; + break; + default: + client->errorValue = stuff->valueMask; + return BadValue; + } + } + return Success; +} + +ProcGetBufferAttributes (client) + register ClientPtr client; +{ + REQUEST(xMbufGetBufferAttributesReq); + MultibufferPtr pMultibuffer; + xMbufGetBufferAttributesReply rep; + OtherClientsPtr other; + int n; + + REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq); + pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType); + if (!pMultibuffer) + return MultibufferErrorBase + MultibufferBadBuffer; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.window = pMultibuffer->pMultibuffers->pWindow->drawable.id; + if (bClient (pMultibuffer) == client) + rep.eventMask = pMultibuffer->eventMask; + else + { + rep.eventMask = (Mask) 0L; + for (other = pMultibuffer->otherClients; other; other = other->next) + if (SameClient (other, client)) + { + rep.eventMask = other->mask; + break; + } + } + rep.bufferIndex = pMultibuffer->number; + rep.side = pMultibuffer->side; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.window, n); + swapl(&rep.eventMask, n); + swaps(&rep.bufferIndex, n); + } + WriteToClient(client, sizeof (xMbufGetBufferAttributesReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcGetBufferInfo (client) + register ClientPtr client; +{ + REQUEST (xMbufGetBufferInfoReq); + DrawablePtr pDrawable; + xMbufGetBufferInfoReply rep; + ScreenPtr pScreen; + int i, j, k; + int n; + xMbufBufferInfo *pInfo; + int nInfo; + DepthPtr pDepth; + + pDrawable = (DrawablePtr) LookupDrawable (stuff->drawable, client); + if (!pDrawable) + return BadDrawable; + pScreen = pDrawable->pScreen; + nInfo = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + nInfo += pDepth->numVids; + } + pInfo = (xMbufBufferInfo *) + ALLOCATE_LOCAL (nInfo * sizeof (xMbufBufferInfo)); + if (!pInfo) + return BadAlloc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = nInfo * (sizeof (xMbufBufferInfo) >> 2); + rep.normalInfo = nInfo; + rep.stereoInfo = 0; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.normalInfo, n); + swaps(&rep.stereoInfo, n); + } + + k = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + for (j = 0; j < pDepth->numVids; j++) + { + pInfo[k].visualID = pDepth->vids[j]; + pInfo[k].maxBuffers = 0; + pInfo[k].depth = pDepth->depth; + if (client->swapped) + { + swapl (&pInfo[k].visualID, n); + swaps (&pInfo[k].maxBuffers, n); + } + k++; + } + } + WriteToClient (client, sizeof (xMbufGetBufferInfoReply), (pointer) &rep); + WriteToClient (client, (int) nInfo * sizeof (xMbufBufferInfo), (pointer) pInfo); + DEALLOCATE_LOCAL ((pointer) pInfo); + return client->noClientException; +} + +static int +ProcClearImageBufferArea (client) + register ClientPtr client; +{ + REQUEST (xMbufClearImageBufferAreaReq); + MultibufferPtr pMultibuffer; + WindowPtr pWin; + xRectangle clearRect; + int width, height; + DrawablePtr pDrawable; + ScreenPtr pScreen; + + REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq); + pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType); + if (!pMultibuffer) + return MultibufferErrorBase + MultibufferBadBuffer; + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + pWin = pMultibuffer->pMultibuffers->pWindow; + width = pWin->drawable.width; + height = pWin->drawable.height; + pScreen = pWin->drawable.pScreen; + + clearRect.x = stuff->x; + clearRect.y = stuff->y; + clearRect.width = stuff->width ? stuff->width : width; + clearRect.height = stuff->height ? stuff->height : height; + + if (pWin->backgroundState != None) + { + GCPtr pClearGC; + pClearGC = GetScratchGC (pWin->drawable.depth, pScreen); + SetupBackgroundPainter (pWin, pClearGC); + + if (pMultibuffer->number == pMultibuffer->pMultibuffers->displayedMultibuffer) + pDrawable = (DrawablePtr)pWin; + else + pDrawable = (DrawablePtr)pMultibuffer->pPixmap; + + ValidateGC(pDrawable, pClearGC); + (*pClearGC->ops->PolyFillRect) (pDrawable, pClearGC, 1, &clearRect); + FreeScratchGC(pClearGC); + } + + if (stuff->exposures) + { + RegionRec region; + BoxRec box; + box.x1 = clearRect.x; + box.y1 = clearRect.y; + box.x2 = clearRect.x + clearRect.width; + box.y2 = clearRect.y + clearRect.height; + REGION_INIT(pScreen, ®ion, &box, 1); + MultibufferExpose(pMultibuffer, ®ion); + REGION_UNINIT(pScreen, ®ion); + } + return Success; +} + +static int +ProcMultibufferDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_MbufGetBufferVersion: + return ProcGetBufferVersion (client); + case X_MbufCreateImageBuffers: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXCreateImageBuffers (client); + else + return ProcCreateImageBuffers (client); +#else + return ProcCreateImageBuffers (client); +#endif + case X_MbufDisplayImageBuffers: + return ProcDisplayImageBuffers (client); + case X_MbufDestroyImageBuffers: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXDestroyImageBuffers (client); + else + return ProcDestroyImageBuffers (client); +#else + return ProcDestroyImageBuffers (client); +#endif + case X_MbufSetMBufferAttributes: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXSetMBufferAttributes (client); + else + return ProcSetMBufferAttributes (client); +#else + return ProcSetMBufferAttributes (client); +#endif + case X_MbufGetMBufferAttributes: + return ProcGetMBufferAttributes (client); + case X_MbufSetBufferAttributes: + return ProcSetBufferAttributes (client); + case X_MbufGetBufferAttributes: + return ProcGetBufferAttributes (client); + case X_MbufGetBufferInfo: + return ProcGetBufferInfo (client); + case X_MbufClearImageBufferArea: + return ProcClearImageBufferArea (client); + default: + return BadRequest; + } +} + +static int +SProcGetBufferVersion (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetBufferVersionReq); + + swaps (&stuff->length, n); + return ProcGetBufferVersion (client); +} + +static int +SProcCreateImageBuffers (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufCreateImageBuffersReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq); + swapl (&stuff->window, n); + SwapRestL(stuff); + return ProcCreateImageBuffers (client); +} + +static int +SProcDisplayImageBuffers (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufDisplayImageBuffersReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq); + swaps (&stuff->minDelay, n); + swaps (&stuff->maxDelay, n); + SwapRestL(stuff); + return ProcDisplayImageBuffers (client); +} + +static int +SProcDestroyImageBuffers (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufDestroyImageBuffersReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq); + swapl (&stuff->window, n); + return ProcDestroyImageBuffers (client); +} + +static int +SProcSetMBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufSetMBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq); + swapl (&stuff->window, n); + swapl (&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSetMBufferAttributes (client); +} + +static int +SProcGetMBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetMBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq); + swapl (&stuff->window, n); + return ProcGetMBufferAttributes (client); +} + +static int +SProcSetBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufSetBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq); + swapl (&stuff->buffer, n); + swapl (&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSetBufferAttributes (client); +} + +static int +SProcGetBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq); + swapl (&stuff->buffer, n); + return ProcGetBufferAttributes (client); +} + +static int +SProcGetBufferInfo (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetBufferInfoReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq); + swapl (&stuff->drawable, n); + return ProcGetBufferInfo (client); +} + +static int +SProcClearImageBufferArea(client) + register ClientPtr client; +{ + register char n; + REQUEST(xMbufClearImageBufferAreaReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq); + swapl(&stuff->buffer, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcClearImageBufferArea(client); +} + +static int +SProcMultibufferDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_MbufGetBufferVersion: + return SProcGetBufferVersion (client); + case X_MbufCreateImageBuffers: + return SProcCreateImageBuffers (client); + case X_MbufDisplayImageBuffers: + return SProcDisplayImageBuffers (client); + case X_MbufDestroyImageBuffers: + return SProcDestroyImageBuffers (client); + case X_MbufSetMBufferAttributes: + return SProcSetMBufferAttributes (client); + case X_MbufGetMBufferAttributes: + return SProcGetMBufferAttributes (client); + case X_MbufSetBufferAttributes: + return SProcSetBufferAttributes (client); + case X_MbufGetBufferAttributes: + return SProcGetBufferAttributes (client); + case X_MbufGetBufferInfo: + return SProcGetBufferInfo (client); + case X_MbufClearImageBufferArea: + return SProcClearImageBufferArea (client); + default: + return BadRequest; + } +} + +static void +SUpdateNotifyEvent (from, to) + xMbufUpdateNotifyEvent *from, *to; +{ + to->type = from->type; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->buffer, to->buffer); + cpswapl (from->timeStamp, to->timeStamp); +} + +static void +SClobberNotifyEvent (from, to) + xMbufClobberNotifyEvent *from, *to; +{ + to->type = from->type; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->buffer, to->buffer); + to->state = from->state; +} + +static void +PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf) + MultibufferPtr *pMultibuffer; + MultibuffersPtr *ppMultibuffers; + int nbuf; +{ + GCPtr pGC; + PixmapPtr pPrevPixmap, pNewPixmap; + xRectangle clearRect; + WindowPtr pWin; + RegionPtr pExposed; + int i; + MultibufferPtr pPrevMultibuffer; + XID graphicsExpose; + + UpdateCurrentTime (); + for (i = 0; i < nbuf; i++) + { + pWin = ppMultibuffers[i]->pWindow; + pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen); + pPrevMultibuffer = + &ppMultibuffers[i]->buffers[ppMultibuffers[i]->displayedMultibuffer]; + pPrevPixmap = pPrevMultibuffer->pPixmap; + pNewPixmap = pMultibuffer[i]->pPixmap; + switch (ppMultibuffers[i]->updateAction) + { + case MultibufferUpdateActionUndefined: + break; + case MultibufferUpdateActionBackground: + SetupBackgroundPainter (pWin, pGC); + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = pPrevPixmap->drawable.width; + clearRect.height = pPrevPixmap->drawable.height; + (*pGC->ops->PolyFillRect) ((DrawablePtr)pPrevPixmap, pGC, + 1, &clearRect); + break; + case MultibufferUpdateActionUntouched: + /* copy the window to the pixmap that represents the + * currently displayed buffer + */ + if (pPrevMultibuffer->eventMask & ExposureMask) + { + graphicsExpose = TRUE; + DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE); + } + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + pExposed = (*pGC->ops->CopyArea) + ((DrawablePtr) pWin, + (DrawablePtr) pPrevPixmap, + pGC, + 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + + /* if we couldn't copy the whole window to the buffer, + * send expose events (if any client wants them) + */ + if (pPrevMultibuffer->eventMask & ExposureMask) + { /* some client wants expose events */ + if (pExposed) + { + RegionPtr pWinSize; + ScreenPtr pScreen = pWin->drawable.pScreen; + extern RegionPtr CreateUnclippedWinSize(); + + pWinSize = CreateUnclippedWinSize (pWin); + /* pExposed is window-relative, but at this point + * pWinSize is screen-relative. Make pWinSize be + * window-relative so that region ops involving + * pExposed and pWinSize behave sensibly. + */ + REGION_TRANSLATE(pScreen, pWinSize, + -pWin->drawable.x, + -pWin->drawable.y); + REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize); + REGION_DESTROY(pScreen, pWinSize); + MultibufferExpose (pPrevMultibuffer, pExposed); + REGION_DESTROY(pScreen, pExposed); + } + graphicsExpose = FALSE; + DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE); + } + break; /* end case MultibufferUpdateActionUntouched */ + + case MultibufferUpdateActionCopied: + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, + (DrawablePtr)pPrevPixmap, pGC, + 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + break; + } /* end switch on update action */ + + /* display the new buffer */ + ValidateGC ((DrawablePtr)pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin, pGC, + 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + ppMultibuffers[i]->lastUpdate = currentTime; + MultibufferUpdate (pMultibuffer[i], + ppMultibuffers[i]->lastUpdate.milliseconds); + AliasMultibuffer (ppMultibuffers[i], + pMultibuffer[i] - ppMultibuffers[i]->buffers); + FreeScratchGC (pGC); + } +} + +DrawablePtr +GetBufferPointer (pWin, i) + WindowPtr pWin; + int i; +{ + MultibuffersPtr pMultibuffers; + + if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr)) + return NULL; + return (DrawablePtr) pMultibuffers->buffers[i].pPixmap; +} + +int +DisplayImageBuffers (ids, nbuf) + XID *ids; + int nbuf; +{ + MultibufferPtr *pMultibuffer; + MultibuffersPtr *pMultibuffers; + int i, j; + + pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL (nbuf * sizeof *pMultibuffer + + nbuf * sizeof *pMultibuffers); + if (!pMultibuffer) + return BadAlloc; + pMultibuffers = (MultibuffersPtr *) (pMultibuffer + nbuf); + for (i = 0; i < nbuf; i++) + { + pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], MultibufferResType); + if (!pMultibuffer[i]) + { + DEALLOCATE_LOCAL (pMultibuffer); + return MultibufferErrorBase + MultibufferBadBuffer; + } + pMultibuffers[i] = pMultibuffer[i]->pMultibuffers; + for (j = 0; j < i; j++) + if (pMultibuffers[i] == pMultibuffers[j]) + { + DEALLOCATE_LOCAL (pMultibuffer); + return BadMatch; + } + } + PerformDisplayRequest (pMultibuffers, pMultibuffer, nbuf); + DEALLOCATE_LOCAL (pMultibuffer); + return Success; +} + + +static Bool +QueueDisplayRequest (client, activateTime) + ClientPtr client; + TimeStamp activateTime; +{ + /* see xtest.c:ProcXTestFakeInput for code similar to this */ + + if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) + { + return FALSE; + } + /* swap the request back so we can simply re-execute it */ + if (client->swapped) + { + register int n; + REQUEST (xMbufDisplayImageBuffersReq); + + SwapRestL(stuff); + swaps (&stuff->length, n); + swaps (&stuff->minDelay, n); + swaps (&stuff->maxDelay, n); + } + ResetCurrentRequest (client); + client->sequence--; + return TRUE; +} + + +/* + * Deliver events to a buffer + */ + +static int +DeliverEventsToMultibuffer (pMultibuffer, pEvents, count, filter) + MultibufferPtr pMultibuffer; + xEvent *pEvents; + int count; + Mask filter; +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + OtherClients *other; + + /* if nobody wants the event, we're done */ + if (!((pMultibuffer->otherEventMask|pMultibuffer->eventMask) & filter)) + return 0; + + /* maybe send event to owner */ + if (attempt = TryClientEvents( + bClient(pMultibuffer), pEvents, count, pMultibuffer->eventMask, filter, (GrabPtr) 0)) + { + if (attempt > 0) + deliveries++; + else + nondeliveries--; + } + + /* maybe send event to other clients */ + for (other = pMultibuffer->otherClients; other; other=other->next) + { + if (attempt = TryClientEvents( + rClient(other), pEvents, count, other->mask, filter, (GrabPtr) 0)) + { + if (attempt > 0) + deliveries++; + else + nondeliveries--; + } + } + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* + * Send Expose events to interested clients + */ + +void +MultibufferExpose (pMultibuffer, pRegion) + MultibufferPtr pMultibuffer; + RegionPtr pRegion; +{ + if (pRegion && !REGION_NIL(pRegion)) + { + xEvent *pEvent; + PixmapPtr pPixmap; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + pPixmap = pMultibuffer->pPixmap; + REGION_TRANSLATE(pPixmap->drawable.pScreen, pRegion, + -pPixmap->drawable.x, -pPixmap->drawable.y); + /* XXX MultibufferExpose "knows" the region representation */ + numRects = REGION_NUM_RECTS(pRegion); + pBox = REGION_RECTS(pRegion); + + pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)); + if (pEvent) { + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pPixmap->drawable.id; + pe->u.expose.x = pBox->x1; + pe->u.expose.y = pBox->y1; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = (numRects - i); + } + (void) DeliverEventsToMultibuffer (pMultibuffer, pEvent, numRects, + ExposureMask); + DEALLOCATE_LOCAL(pEvent); + } + } +} + +/* send UpdateNotify event */ +void +MultibufferUpdate (pMultibuffer, time) + MultibufferPtr pMultibuffer; + CARD32 time; +{ + xMbufUpdateNotifyEvent event; + + event.type = MultibufferEventBase + MultibufferUpdateNotify; + event.buffer = pMultibuffer->pPixmap->drawable.id; + event.timeStamp = time; + (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event, + 1, (Mask)MultibufferUpdateNotifyMask); +} + +/* + * The sample implementation will never generate MultibufferClobberNotify + * events + */ + +void +MultibufferClobber (pMultibuffer) + MultibufferPtr pMultibuffer; +{ + xMbufClobberNotifyEvent event; + + event.type = MultibufferEventBase + MultibufferClobberNotify; + event.buffer = pMultibuffer->pPixmap->drawable.id; + event.state = pMultibuffer->clobber; + (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event, + 1, (Mask)MultibufferClobberNotifyMask); +} + +/* + * make the resource id for buffer i refer to the window + * drawable instead of the pixmap; + */ + +static void +AliasMultibuffer (pMultibuffers, i) + MultibuffersPtr pMultibuffers; + int i; +{ + MultibufferPtr pMultibuffer; + + if (i == pMultibuffers->displayedMultibuffer) + return; + /* + * remove the old association + */ + if (pMultibuffers->displayedMultibuffer >= 0) + { + pMultibuffer = &pMultibuffers->buffers[pMultibuffers->displayedMultibuffer]; + ChangeResourceValue (pMultibuffer->pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pMultibuffer->pPixmap); + } + /* + * make the new association + */ + pMultibuffer = &pMultibuffers->buffers[i]; + ChangeResourceValue (pMultibuffer->pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pMultibuffers->pWindow); + pMultibuffers->displayedMultibuffer = i; +} + +/* + * free everything associated with multibuffering for this + * window + */ + +void +DestroyImageBuffers (pWin) + WindowPtr pWin; +{ + FreeResourceByType (pWin->drawable.id, MultibuffersResType, FALSE); + /* Zero out the window's pointer to the buffers so they won't be reused */ + pWin->devPrivates[MultibufferWindowIndex].ptr = NULL; +} + +/* + * resize the buffers when the window is resized + */ + +static Bool +MultibufferPositionWindow (pWin, x, y) + WindowPtr pWin; + int x, y; +{ + ScreenPtr pScreen; + MultibufferScreenPtr pMultibufferScreen; + MultibuffersPtr pMultibuffers; + MultibufferPtr pMultibuffer; + int width, height; + int i; + int dx, dy, dw, dh; + int sourcex, sourcey; + int destx, desty; + PixmapPtr pPixmap; + GCPtr pGC; + int savewidth, saveheight; + xRectangle clearRect; + Bool clear; + + pScreen = pWin->drawable.pScreen; + pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr; + (*pMultibufferScreen->PositionWindow) (pWin, x, y); + + /* if this window is not multibuffered, we're done */ + if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr)) + return TRUE; + + /* if new size is same as old, we're done */ + if (pMultibuffers->width == pWin->drawable.width && + pMultibuffers->height == pWin->drawable.height) + return TRUE; + + width = pWin->drawable.width; + height = pWin->drawable.height; + dx = pWin->drawable.x - pMultibuffers->x; + dy = pWin->drawable.x - pMultibuffers->y; + dw = width - pMultibuffers->width; + dh = height - pMultibuffers->height; + GravityTranslate (0, 0, -dx, -dy, dw, dh, + pWin->bitGravity, &destx, &desty); + + /* if the window grew, remember to paint the window background, + * and maybe send expose events, for the new areas of the buffers + */ + clear = pMultibuffers->width < width || pMultibuffers->height < height || + pWin->bitGravity == ForgetGravity; + + sourcex = 0; + sourcey = 0; + savewidth = pMultibuffers->width; + saveheight = pMultibuffers->height; + /* clip rectangle to source and destination */ + if (destx < 0) + { + savewidth += destx; + sourcex -= destx; + destx = 0; + } + if (destx + savewidth > width) + savewidth = width - destx; + if (desty < 0) + { + saveheight += desty; + sourcey -= desty; + desty = 0; + } + if (desty + saveheight > height) + saveheight = height - desty; + + pMultibuffers->width = width; + pMultibuffers->height = height; + pMultibuffers->x = pWin->drawable.x; + pMultibuffers->y = pWin->drawable.y; + + pGC = GetScratchGC (pWin->drawable.depth, pScreen); + if (clear) + { + SetupBackgroundPainter (pWin, pGC); + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = width; + clearRect.height = height; + } + for (i = 0; i < pMultibuffers->numMultibuffer; i++) + { + pMultibuffer = &pMultibuffers->buffers[i]; + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pWin->drawable.depth); + if (!pPixmap) + { + DestroyImageBuffers (pWin); + break; + } + ValidateGC ((DrawablePtr)pPixmap, pGC); + /* + * I suppose this could avoid quite a bit of work if + * it computed the minimal area required. + */ + if (clear) + (*pGC->ops->PolyFillRect) ((DrawablePtr)pPixmap, pGC, 1, &clearRect); + if (pWin->bitGravity != ForgetGravity) + { + (*pGC->ops->CopyArea) ((DrawablePtr)pMultibuffer->pPixmap, + (DrawablePtr)pPixmap, pGC, + sourcex, sourcey, savewidth, saveheight, + destx, desty); + } + pPixmap->drawable.id = pMultibuffer->pPixmap->drawable.id; + (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap); + pMultibuffer->pPixmap = pPixmap; + if (i != pMultibuffers->displayedMultibuffer) + { + ChangeResourceValue (pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pPixmap); + } + } + FreeScratchGC (pGC); + return TRUE; +} + +/* Resource delete func for MultibufferDrawableResType */ +/*ARGSUSED*/ +static int +MultibufferDrawableDelete (value, id) + pointer value; + XID id; +{ + DrawablePtr pDrawable = (DrawablePtr)value; + WindowPtr pWin; + MultibuffersPtr pMultibuffers; + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW) + { + pWin = (WindowPtr) pDrawable; + pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr; + pPixmap = pMultibuffers->buffers[pMultibuffers->displayedMultibuffer].pPixmap; + } + else + { + pPixmap = (PixmapPtr) pDrawable; + } + (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); + return Success; +} + +/* Resource delete func for MultibufferResType */ +/*ARGSUSED*/ +static int +MultibufferDelete (value, id) + pointer value; + XID id; +{ + MultibufferPtr pMultibuffer = (MultibufferPtr)value; + MultibuffersPtr pMultibuffers; + + pMultibuffers = pMultibuffer->pMultibuffers; + if (--pMultibuffers->refcnt == 0) + { + FreeResourceByType (pMultibuffers->pWindow->drawable.id, + MultibuffersResType, TRUE); + xfree (pMultibuffers); + } + return Success; +} + +/* Resource delete func for MultibuffersResType */ +/*ARGSUSED*/ +static int +MultibuffersDelete (value, id) + pointer value; + XID id; +{ + MultibuffersPtr pMultibuffers = (MultibuffersPtr)value; + int i; + + if (pMultibuffers->refcnt == pMultibuffers->numMultibuffer) + { + for (i = pMultibuffers->numMultibuffer; --i >= 0; ) + FreeResource (pMultibuffers->buffers[i].pPixmap->drawable.id, 0); + } + return Success; +} + +/* Resource delete func for OtherClientResType */ +static int +OtherClientDelete (value, id) + pointer value; + XID id; +{ + MultibufferPtr pMultibuffer = (MultibufferPtr)value; + register OtherClientsPtr other, prev; + + prev = 0; + for (other = pMultibuffer->otherClients; other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + pMultibuffer->otherClients = other->next; + xfree (other); + RecalculateMultibufferOtherEvents (pMultibuffer); + break; + } + prev = other; + } + return Success; +} + +static int +EventSelectForMultibuffer (pMultibuffer, client, mask) + MultibufferPtr pMultibuffer; + ClientPtr client; + Mask mask; +{ + OtherClientsPtr other; + + if (mask & ~ValidEventMasks) + { + client->errorValue = mask; + return BadValue; + } + if (bClient (pMultibuffer) == client) + { + pMultibuffer->eventMask = mask; + } + else /* some other client besides the creator wants events */ + { + for (other = pMultibuffer->otherClients; other; other = other->next) + { + if (SameClient (other, client)) + { + if (mask == 0) + { + FreeResource (other->resource, RT_NONE); + break; + } + other->mask = mask; + break; + } + } + if (!other) + { /* new client that never selected events on this buffer before */ + other = (OtherClients *) xalloc (sizeof (OtherClients)); + if (!other) + return BadAlloc; + other->mask = mask; + other->resource = FakeClientID (client->index); + if (!AddResource (other->resource, OtherClientResType, (pointer) pMultibuffer)) + { + xfree (other); + return BadAlloc; + } + other->next = pMultibuffer->otherClients; + pMultibuffer->otherClients = other; + } + RecalculateMultibufferOtherEvents (pMultibuffer); + } + return (client->noClientException); +} + +/* or together all the otherClients event masks */ +static void +RecalculateMultibufferOtherEvents (pMultibuffer) + MultibufferPtr pMultibuffer; +{ + Mask otherEventMask; + OtherClients *other; + + otherEventMask = 0L; + for (other = pMultibuffer->otherClients; other; other = other->next) + otherEventMask |= other->mask; + pMultibuffer->otherEventMask = otherEventMask; +} + +/* add milliseconds to a timestamp, handling overflow */ +static void +BumpTimeStamp (ts, inc) +TimeStamp *ts; +CARD32 inc; +{ + CARD32 newms; + + newms = ts->milliseconds + inc; + if (newms < ts->milliseconds) + ts->months++; + ts->milliseconds = newms; +} diff --git a/Xext/mbufbf.c b/Xext/mbufbf.c new file mode 100644 index 000000000..3c873086f --- /dev/null +++ b/Xext/mbufbf.c @@ -0,0 +1,1052 @@ +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* $Xorg: mbufbf.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" +#include "validate.h" +#include + +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#define _MULTIBUF_BUFFER_ +#include "multibufst.h" + +/* +Support for doublebuffer hardare + +This code is designed to support doublebuffer hardware where the +displayed buffer is selected on a per-pixel basis by an additional bit +plane, called the select plane. It could probably be easily modified +to work with systems that use window-id planes. + +This is done by creating a new drawable type, DRAWABLE_BUFFER. The +type has the same exact layout as a window drawable. Your code should +treat a DRAWABLE_BUFFER the same as it would tread a DRAWABLE_WINDOW +when handling the gc drawing functions. In addition, PaintWindowBackground, +CopyWindow, and all of the gc drawing functions to be able to draw into both +framebuffers. Which framebuffer to draw into is selected by the contents of + pWin->devPrivates[frameWindowPrivateIndex]. +The content of the devPrivate is either from frameBuffer[0] or +frameBuffer[1], depending on which buffer is being drawn into. When + pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[0], +the functions should draw into the front framebuffer. When + pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[1], +the functions should draw into the back framebuffer. + +In addition, you need to provide a function that allows you to copy +bits between the buffers (optional since CopyArea can be used) and a +function that draws into the select plane. Then, you need to register +your functions and other information, by calling: + +void +RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane, + CopyBufferBitsFunc, DrawSelectPlaneFunc) + int nInfo; + xMbufBufferInfo *pInfo; + DevUnion *frameBuffer; + DevUnion selectPlane; + +"pInfo" is an array indicating which visuals and depths that double +buffering is supported on. "nInfo" is the length of the array. + +"frameBuffer" is array of length 2. The contents of the array element +is ddx-specific. The content of frameBuffer[0] should, when placed in +the window private, indicate that framebuffer 0 should be drawn into. +The contents of frameBuffer[1], when placed into the window private, +should indicate that framebuffer 1 should be drawn into. + +"selectPlane" is ddx-specific. It should contain information +neccessary for your displayProc to access the select plane. +It is passed to DrawSelectPlaneFunc. + +"CopyBufferBitsFunc" is a ddx-specific function that copies from one +buffer of a multibuffered window to another buffer. If the CopyBufferBitsFunc +is NULL, a default function will be used that calls pScreen->CopyArea. + + void CopyBufferBitsFunc(pMBWindow, srcBufferNum, dstBufferNum) + mbufWindowPtr pMBWindow; + int srcBufferNum, dstBufferNum; + +"DrawSelectPlaneFunc" is a ddx-specific function that fills the +regions "prgn" of select plane with the value "bufferNum". If +selectPlane is a DrawablePtr (such as a PixmapPtr), you can pass +NULL for DrawSelectPlaneFunc, a default function will be used that +calls FillRectangle on the selectPlane. + + void DrawSelectPlaneFunc(pScreen, selectPlane, prgn, bufferNum) + ScreenPtr pScreen; + DevUnion selectPlane; + RegionPtr prgn; + long bufferNum; + +... +... +... + +*/ + +#define MAX_BUFFERS 2 /* Only supports 2 buffers */ +#define FRONT_BUFFER 0 +#define BACK_BUFFER 1 + + +/* Buffer drawables have the same structure as window drawables */ +typedef WindowRec BufferRec; +typedef WindowPtr BufferPtr; + + +/* + * Call RegisterHdwrBuffer for every screen that has doublebuffer hardware. + */ + +static int bufNumInfo[MAXSCREENS]; +static xMbufBufferInfo *bufInfo[MAXSCREENS]; +static DevUnion *bufFrameBuffer[MAXSCREENS]; +static DevUnion bufselectPlane[MAXSCREENS]; +static void (* bufCopyBufferBitsFunc[MAXSCREENS])(); +static void (* bufDrawSelectPlaneFunc[MAXSCREENS])(); + +static Bool bufMultibufferInit(); + + +void +RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane, + CopyBufferBitsFunc, DrawSelectPlaneFunc) + ScreenPtr pScreen; + int nInfo; + xMbufBufferInfo *pInfo; + DevUnion *frameBuffer; + DevUnion selectPlane; + void (* CopyBufferBitsFunc)(); + void (* DrawSelectPlaneFunc)(); +{ + bufNumInfo[pScreen->myNum] = nInfo; + bufInfo[pScreen->myNum] = pInfo; + bufFrameBuffer[pScreen->myNum] = frameBuffer; + bufselectPlane[pScreen->myNum] = selectPlane; + + bufCopyBufferBitsFunc[pScreen->myNum] = CopyBufferBitsFunc; + bufDrawSelectPlaneFunc[pScreen->myNum] = DrawSelectPlaneFunc; + + /* Register ourselves with device-independent multibuffers code */ + RegisterMultibufferInit(pScreen, bufMultibufferInit); +} + + +/* + * Called by Multibuffer extension initialization. + * Initializes mbufScreenRec and its devPrivate. + */ + +static Bool NoopDDA_True() { return TRUE; } +static Bool bufPositionWindow(); +static int bufCreateImageBuffers(); +static void bufDestroyImageBuffers(); +static void bufDisplayImageBuffers(); +static void bufClearImageBufferArea(); +static void bufDestroyBuffer(); +static void bufCopyBufferBits(); +static void bufDrawSelectPlane(); +static void bufWrapScreenFuncs(); +static void bufResetProc(); + +static void bufPostValidateTree(); +static void bufClipNotify(); +static void bufWindowExposures(); +static Bool bufChangeWindowAttributes(); +static void bufClearToBackground(); +static void bufCopyWindow(); + +extern WindowPtr *WindowTable; + +static Bool +bufMultibufferInit(pScreen, pMBScreen) + ScreenPtr pScreen; + mbufScreenPtr pMBScreen; +{ + mbufBufferPrivPtr pMBPriv; + BoxRec box; + + /* Multibuffer info */ + pMBScreen->nInfo = bufNumInfo[pScreen->myNum]; + pMBScreen->pInfo = bufInfo[pScreen->myNum]; + + /* Hooks */ + pMBScreen->CreateImageBuffers = bufCreateImageBuffers; + pMBScreen->DestroyImageBuffers = bufDestroyImageBuffers; + pMBScreen->DisplayImageBuffers = bufDisplayImageBuffers; + pMBScreen->ClearImageBufferArea = bufClearImageBufferArea; + pMBScreen->ChangeMBufferAttributes = NoopDDA_True; + pMBScreen->ChangeBufferAttributes = NoopDDA_True; + pMBScreen->DeleteBufferDrawable = bufDestroyBuffer; + pMBScreen->WrapScreenFuncs = bufWrapScreenFuncs; + pMBScreen->ResetProc = bufResetProc; + /* Create devPrivate part */ + pMBPriv = (mbufBufferPrivPtr) xalloc(sizeof *pMBPriv); + if (!pMBPriv) + return (FALSE); + + pMBScreen->devPrivate.ptr = (pointer) pMBPriv; + pMBPriv->frameBuffer = bufFrameBuffer[pScreen->myNum]; + pMBPriv->selectPlane = bufselectPlane[pScreen->myNum]; + + /* + * Initializing the subtractRgn to the screen area will ensure that + * the selectPlane will get cleared on the first PostValidateTree. + */ + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + + pMBPriv->rgnChanged = TRUE; + REGION_INIT(pScreen, &pMBPriv->backBuffer, &box, 1); + REGION_INIT(pScreen, &pMBPriv->subtractRgn, &box, 1); + REGION_INIT(pScreen, &pMBPriv->unionRgn, NullBox, 0); + + /* Misc functions */ + pMBPriv->CopyBufferBits = bufCopyBufferBitsFunc[pScreen->myNum]; + pMBPriv->DrawSelectPlane = bufDrawSelectPlaneFunc[pScreen->myNum]; + + if (!pMBPriv->CopyBufferBits) + pMBPriv->CopyBufferBits = bufCopyBufferBits; + + if (!pMBPriv->DrawSelectPlane) + pMBPriv->DrawSelectPlane = bufDrawSelectPlane; + + /* screen functions */ + pMBPriv->funcsWrapped = 0; + pMBPriv->inClearToBackground = FALSE; + pMBPriv->WindowExposures = NULL; + pMBPriv->CopyWindow = NULL; + pMBPriv->ClearToBackground = NULL; + pMBPriv->ClipNotify = NULL; + pMBPriv->ChangeWindowAttributes = NULL; + + /* Start out wrapped to clear select plane */ + WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree); + return TRUE; +} + +static void +UpdateBufferFromWindow(pBuffer, pWin) + BufferPtr pBuffer; + WindowPtr pWin; +{ + pBuffer->drawable.x = pWin->drawable.x; + pBuffer->drawable.y = pWin->drawable.y; + pBuffer->drawable.width = pWin->drawable.width; + pBuffer->drawable.height = pWin->drawable.height; + + pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + /* Update for PaintWindowBackground */ + pBuffer->parent = pWin->parent; + + /* + * Make the borderClip the same as the clipList so + * NotClippedByChildren comes out with just clipList. + */ + + pBuffer->clipList = pWin->clipList; + pBuffer->borderClip = pWin->clipList; + pBuffer->winSize = pWin->winSize; + pBuffer->borderSize = pWin->borderSize; + + pBuffer->origin = pWin->origin; +} + +static BufferPtr +bufCreateBuffer(pScreen, pWin, bufferNum) + ScreenPtr pScreen; + WindowPtr pWin; + int bufferNum; +{ + mbufBufferPrivPtr pMBPriv; + DevUnion *devPrivates; + BufferPtr pBuffer; + int i; + + pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + pBuffer = AllocateWindow(pWin->drawable.pScreen); + if (!pBuffer) + return (NULL); + + /* XXX- Until we know what is needed, copy everything. */ + devPrivates = pBuffer->devPrivates; + *pBuffer = *pWin; + pBuffer->devPrivates = devPrivates; + + pBuffer->drawable.type = DRAWABLE_BUFFER; + pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pBuffer->nextSib = NULL; + pBuffer->prevSib = NULL; + pBuffer->firstChild = NULL; + pBuffer->lastChild = NULL; + + /* XXX - Worry about backingstore later */ + pBuffer->backStorage = NULL; + pBuffer->backingStore = NotUseful; + + /* XXX - Need to call pScreen->CreateWindow for tile/stipples + * or should I just copy the devPrivates? + */ + + for (i=0; i < pScreen->WindowPrivateLen; i++) + pBuffer->devPrivates[i] = pWin->devPrivates[i]; + + pBuffer->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[bufferNum]; + + return pBuffer; +} + +static void +bufDestroyBuffer(pDrawable) + DrawablePtr pDrawable; +{ + xfree(pDrawable); +} + +/*ARGSUSED*/ +static int +bufCreateImageBuffers (pWin, nbuf, ids, action, hint) + WindowPtr pWin; + int nbuf; + XID *ids; + int action; + int hint; +{ + ScreenPtr pScreen; + mbufScreenPtr pMBScreen; + mbufWindowPtr pMBWindow; + mbufBufferPtr pMBBuffer; + int i; + + pScreen = pWin->drawable.pScreen; + pMBScreen = MB_SCREEN_PRIV(pScreen); + pMBWindow = MB_WINDOW_PRIV(pWin); + + pMBWindow->devPrivate.ptr = (pointer) REGION_CREATE(pScreen, 0,0); + if (!pMBWindow->devPrivate.ptr) + return(0); + REGION_COPY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr, + &pWin->clipList); + + for (i = 0; i < nbuf; i++) + { + pMBBuffer = pMBWindow->buffers + i; + pMBBuffer->pDrawable = (DrawablePtr) bufCreateBuffer(pScreen,pWin,i); + + if (!pMBBuffer->pDrawable) + break; + + if (!AddResource (ids[i], MultibufferDrawableResType, + (pointer) pMBBuffer->pDrawable)) + { + bufDestroyBuffer((BufferPtr) pMBBuffer->pDrawable); + break; + } + pMBBuffer->pDrawable->id = ids[i]; + + /* + * If window is already mapped, generate exposures and + * clear the area of the newly buffers. + */ + + if ((pWin->realized) && (i != pMBWindow->displayedMultibuffer)) + (* pMBScreen->ClearImageBufferArea)(pMBBuffer, 0,0, 0,0, TRUE); + } + + return i; +} + +static void +bufDestroyImageBuffers(pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen; + mbufWindowPtr pMBWindow; + + pScreen = pWin->drawable.pScreen; + + if (pMBWindow = MB_WINDOW_PRIV(pWin)) + { + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + /* + * if the backbuffer is currently being displayed, move the bits + * to the frontbuffer and display it instead. + */ + + if (pWin->realized && (pMBWindow->displayedMultibuffer == BACK_BUFFER)) + { + (* pMBPriv->CopyBufferBits)(pMBWindow, BACK_BUFFER, FRONT_BUFFER); + REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, + &pMBPriv->backBuffer, &pWin->clipList); + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &pWin->clipList, FRONT_BUFFER); + } + + /* Switch window rendering to front buffer */ + pWin->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[FRONT_BUFFER]; + + REGION_DESTROY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr); + pMBWindow->devPrivate.ptr = NULL; + } +} + +/* + * Can be replaced by pScreen->ClearToBackground if pBuffer->eventMask + * and wOtherEventsMasks(pBuffer) were setup. + */ + +static void +bufClearImageBufferArea(pMBBuffer, x,y, w,h, generateExposures) + mbufBufferPtr pMBBuffer; + short x,y; + unsigned short w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + BufferPtr pBuffer; + + pBuffer = (BufferPtr) pMBBuffer->pDrawable; + /* compute everything using ints to avoid overflow */ + + x1 = pBuffer->drawable.x + x; + y1 = pBuffer->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pBuffer->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pBuffer->drawable.height - (int) y; + + extents = &pBuffer->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pBuffer->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pBuffer->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pBuffer, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pBuffer->clipList); + if (pBuffer->backgroundState != None) + (*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND); + if (generateExposures) + MultibufferExpose(pMBBuffer, ®); +#ifdef _notdef + /* XXBS - This is the original miClearToBackground code. + * WindowExposures needs to be called (or the functionality emulated) + * in order for backingStore to work, but first, pBuffer->eventMask + * and wOtherEventsMasks(pBuffer) need to be setup correctly. + */ + + if (generateExposures) + (*pScreen->WindowExposures)(pBuffer, ®, pBSReg); + else if (pBuffer->backgroundState != None) + (*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND); +#endif + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +static void +bufWrapScreenFuncs(pScreen) + ScreenPtr pScreen; +{ + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClipNotify, bufClipNotify); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,WindowExposures,bufWindowExposures); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,ChangeWindowAttributes, bufChangeWindowAttributes); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClearToBackground,bufClearToBackground); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,CopyWindow,bufCopyWindow); +} + +static void +bufResetProc(pScreen) + ScreenPtr pScreen; +{ + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + /* + * frameBuffer, selectPlane, and pInfo should be freed by + * whoever called RegisterDoubleBufferHardware + */ + + REGION_UNINIT(pScreen, &pMBPriv->backBuffer); + REGION_UNINIT(pScreen, &pMBPriv->subtractRgn); + REGION_UNINIT(pScreen, &pMBPriv->unionRgn); + xfree(pMBPriv); +} + +/*---------------------------------------------------------------------------*/ + +/* + * Used if CopyBufferBitsFunc is not provided when registering. + * This should work for everybody since CopyArea needs to support + * copying between buffers anyway. + */ + +static void +bufCopyBufferBits(pMBWindow, srcBufferNum, dstBufferNum) + mbufWindowPtr pMBWindow; + int srcBufferNum, dstBufferNum; +{ + DrawablePtr pSrcBuffer, pDstBuffer; + GCPtr pGC; + + pSrcBuffer = pMBWindow->buffers[srcBufferNum].pDrawable; + pDstBuffer = pMBWindow->buffers[dstBufferNum].pDrawable; + + pGC = GetScratchGC (pDstBuffer->depth, pDstBuffer->pScreen); + if (!pGC) + return; + + ValidateGC (pDstBuffer, pGC); + (* pGC->ops->CopyArea) (pSrcBuffer, pDstBuffer, pGC, + 0,0, pDstBuffer->width, pDstBuffer->height, 0,0); + FreeScratchGC (pGC); +} + +/* + * Used if DrawSelectPlanFunc is not provided for when registering. + * However, it only works if selectPlane.ptr is a drawable. Also + * assumes that painting with color 0 selects the front buffer, + * while color 1 selects the back buffer. + */ + +static void +bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum) + ScreenPtr pScreen; + DevUnion selectPlane; + RegionPtr prgn; + long bufferNum; +{ + DrawablePtr pDrawable; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register xRectangle *prect; + int numRects; + XID value; + + if (REGION_NUM_RECTS(prgn) == 0) + return; + + pDrawable = (DrawablePtr) selectPlane.ptr; + pGC = GetScratchGC (pDrawable->depth, pScreen); + if (!pGC) + return; + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + { + FreeScratchGC(pGC); + return; + } + + value = (XID) bufferNum; + DoChangeGC(pGC, GCForeground, &value, 0); + ValidateGC(pDrawable, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1; + prect->y = pbox->y1; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (* pGC->ops->PolyFillRect)(pDrawable, pGC, numRects, prect); + + DEALLOCATE_LOCAL(prect); + FreeScratchGC (pGC); +} + + +static void +bufDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf) + ScreenPtr pScreen; + mbufBufferPtr *ppMBBuffer; + mbufWindowPtr *ppMBWindow; + int nbuf; +{ + WindowPtr pWin; + BufferPtr pPrevBuffer, pNewBuffer; + int i, number; + mbufBufferPrivPtr pMBPriv; + mbufBufferPtr pPrevMBBuffer; + + pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + for (i = 0; i < nbuf; i++) + { + number = ppMBBuffer[i]->number; /* 0=frontbuffer, 1=backbuffer */ + pWin = ppMBWindow[i]->pWindow; + pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]); + + pPrevBuffer = (BufferPtr) pPrevMBBuffer->pDrawable; + pNewBuffer = (BufferPtr) ppMBBuffer[i]->pDrawable; + + if (pPrevBuffer != pNewBuffer) + { + RegionPtr backBuffer = &pMBPriv->backBuffer; + + /* + * Update the select plane and the backBuffer region. + */ + + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &pWin->clipList, number); + + if (number == BACK_BUFFER) + REGION_UNION(pScreen, backBuffer, backBuffer, + &pWin->clipList); + else + REGION_SUBTRACT(pScreen, backBuffer, backBuffer, + &pWin->clipList); + + /* Switch which framebuffer the window draws into */ + pWin->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[number]; + } + + switch (ppMBWindow[i]->updateAction) + { + case MultibufferUpdateActionUndefined: + break; + case MultibufferUpdateActionBackground: + (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea) + (pPrevMBBuffer, 0,0, 0,0, FALSE); + break; + case MultibufferUpdateActionUntouched: + break; + case MultibufferUpdateActionCopied: + if (pPrevBuffer != pNewBuffer) + { + (* pMBPriv->CopyBufferBits) (ppMBWindow[i], + ppMBBuffer[i]->number, pPrevMBBuffer->number); + } + break; + } + } +} + +/* Updates the backBuffer region and paints the selectPlane. */ + +static void +bufPostValidateTree(pParent, pChild, kind) + WindowPtr pParent, pChild; + VTKind kind; +{ + ScreenPtr pScreen; + mbufBufferPrivPtr pMBPriv; + + if (pParent) + pScreen = pParent->drawable.pScreen; + else if (pChild) + pScreen = pChild->drawable.pScreen; + else + return; /* Hopeless */ + + pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree); + if (pScreen->PostValidateTree) + (* pScreen->PostValidateTree)(pParent, pChild, kind); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree); + + /* Does backBuffer need to change? */ + if (pMBPriv->rgnChanged) + { + RegionRec exposed; + RegionPtr pSubtractRgn, pUnionRgn; + Bool overlap; + + pMBPriv->rgnChanged = FALSE; + + pSubtractRgn = &pMBPriv->subtractRgn; + pUnionRgn = &pMBPriv->unionRgn; + REGION_VALIDATE(pScreen, pSubtractRgn, &overlap); +#ifdef DEBUG + if (overlap) + FatalError("bufPostValidateTree: subtractRgn overlaps"); +#endif + REGION_VALIDATE(pScreen, pUnionRgn, &overlap); +#ifdef DEBUG + if (overlap) + FatalError("bufPostValidateTree: unionRgn overlaps"); +#endif + + /* Update backBuffer: subtract must come before union */ + REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer, + pSubtractRgn); + REGION_UNION(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer, + pUnionRgn); + + /* Paint gained and lost backbuffer areas in select plane */ + REGION_INIT(pScreen, &exposed, NullBox, 0); + REGION_SUBTRACT(pScreen, &exposed, pSubtractRgn, pUnionRgn); + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &exposed, FRONT_BUFFER); + + REGION_SUBTRACT(pScreen, &exposed, pUnionRgn, pSubtractRgn); + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &exposed, BACK_BUFFER); + + REGION_UNINIT(pScreen, &exposed); + REGION_EMPTY(pScreen, pSubtractRgn); + REGION_EMPTY(pScreen, pUnionRgn); + } +} + +/* XXX - Knows region internals. */ + +static Bool +RegionsEqual(reg1, reg2) + RegionPtr reg1; + RegionPtr reg2; +{ + int i; + BoxPtr rects1, rects2; + + if (reg1->extents.x1 != reg2->extents.x1) return FALSE; + if (reg1->extents.x2 != reg2->extents.x2) return FALSE; + if (reg1->extents.y1 != reg2->extents.y1) return FALSE; + if (reg1->extents.y2 != reg2->extents.y2) return FALSE; + if (REGION_NUM_RECTS(reg1) != REGION_NUM_RECTS(reg2)) return FALSE; + + rects1 = REGION_RECTS(reg1); + rects2 = REGION_RECTS(reg2); + for (i = 0; i != REGION_NUM_RECTS(reg1); i++) { + if (rects1[i].x1 != rects2[i].x1) return FALSE; + if (rects1[i].x2 != rects2[i].x2) return FALSE; + if (rects1[i].y1 != rects2[i].y1) return FALSE; + if (rects1[i].y2 != rects2[i].y2) return FALSE; + } + return TRUE; +} + +/* + * If the window is multibuffered and displaying the backbuffer, + * add the old clipList to the subtractRgn and add the new clipList + * to the unionRgn. PostValidateTree will use subtractRgn and unionRgn + * to update the backBuffer region and the selectPlane. + * + * Copy changes to the window structure into the buffers. + * Send ClobberNotify events. + */ + +static void +bufClipNotify(pWin, dx,dy) + WindowPtr pWin; + int dx,dy; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + mbufWindowPtr pMBWindow; + int i; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify); + if (pScreen->ClipNotify) + (* pScreen->ClipNotify)(pWin, dx,dy); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify); + + if (pMBWindow = MB_WINDOW_PRIV(pWin)) + { + RegionPtr pOldClipList = (RegionPtr) pMBWindow->devPrivate.ptr; + + if (! RegionsEqual(pOldClipList, &pWin->clipList)) + { + if (pMBWindow->displayedMultibuffer == BACK_BUFFER) + { + pMBPriv->rgnChanged = TRUE; + REGION_APPEND(pScreen, &pMBPriv->subtractRgn, pOldClipList); + REGION_APPEND(pScreen, &pMBPriv->unionRgn, &pWin->clipList); + } + + REGION_COPY(pScreen, pOldClipList,&pWin->clipList); + } + + /* Update buffer x,y,w,h, and clipList */ + for (i=0; inumMultibuffer; i++) + { + mbufBufferPtr pMBBuffer = pMBWindow->buffers + i; + if (pMBBuffer->clobber != pWin->visibility) + { + pMBBuffer->clobber = pWin->visibility; + MultibufferClobber(pMBBuffer); + } + UpdateBufferFromWindow(pMBBuffer->pDrawable, pWin); + } + } +} + +/* + * Updates buffer's background fields when the window's changes. + * This is necessary because pScreen->PaintWindowBackground + * is used to paint the buffer. + * + * XXBS - Backingstore state will have be tracked too if it is supported. + */ + +static Bool +bufChangeWindowAttributes(pWin, mask) + WindowPtr pWin; + unsigned long mask; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + mbufWindowPtr pMBWindow; + Bool ret; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes); + ret = (* pScreen->ChangeWindowAttributes)(pWin, mask); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes); + + if (pMBWindow = MB_WINDOW_PRIV(pWin)) + { + if (mask & (CWBackPixmap | CWBackPixel)) + { + BufferPtr pBuffer; + int i; + + for (i=0; idisplayedMultibuffer; i++) + { + pBuffer = (BufferPtr) pMBWindow->buffers[i].pDrawable; + pBuffer->backgroundState = pWin->backgroundState; + pBuffer->background = pWin->background; + } + } + } + return ret; +} + +/* + * Send exposures and clear the background for a buffer whenever + * its corresponding window is exposed, except when called by + * ClearToBackground. + */ + +static void +bufWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin); + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + RegionRec tmp_rgn; + int i; + Bool handleBuffers; + + handleBuffers = (!pMBPriv->inClearToBackground) && + (pWin->drawable.type == DRAWABLE_WINDOW) && + pMBWindow && (prgn && !REGION_NIL(prgn)); + + /* miWindowExposures munges prgn and other_exposed. */ + if (handleBuffers) + { + REGION_INIT(pScreen, &tmp_rgn, NullBox, 0); + REGION_COPY(pScreen, &tmp_rgn,prgn); + } + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures); + (* pScreen->WindowExposures) (pWin, prgn, other_exposed); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures); + + if (!handleBuffers) + return; + + /* + * Send expose events to all clients. Paint the exposed region for all + * buffers except the displayed buffer since it is handled when the + * window is painted. + * + * XXBS - Will have to be re-written to handle BackingStore on buffers. + */ + + for (i=0; inumMultibuffer; i++) + { + mbufBufferPtr pMBBuffer; + BufferPtr pBuffer; + + pMBBuffer = pMBWindow->buffers + i; + pBuffer = (BufferPtr) pMBBuffer->pDrawable; + + if (i != pMBWindow->displayedMultibuffer) + (* pScreen->PaintWindowBackground)(pBuffer,&tmp_rgn,PW_BACKGROUND); + if ((pMBBuffer->otherEventMask | pMBBuffer->eventMask) & ExposureMask) + MultibufferExpose(pMBBuffer, &tmp_rgn); + } + + REGION_UNINIT(pScreen, &tmp_rgn); +} + +/* + * Set ``inClearToBackground'' so that WindowExposures does not attempt + * to send expose events or clear the background on the buffers. + */ + +static void +bufClearToBackground(pWin, x,y,w,h, sendExpose) + WindowPtr pWin; + int x,y, w,h; + Bool sendExpose; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + pMBPriv->inClearToBackground = TRUE; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground); + (* pScreen->ClearToBackground)(pWin, x,y,w,h, sendExpose); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground); + + pMBPriv->inClearToBackground = FALSE; +} + +/* + * Move bits in both buffers. It does this by calling pScreen->CopyWindow + * twice, once with the root window's devPrivate[frameWindowPrivateIndex] + * pointing to the frontbuffer pixmap and once with it pointed to the + * backbuffer pixmap. It does this if there are *any* existing multibuffered + * window... a possible optimization is to copy the backbuffer only if this + * window or its inferiors are multibuffered. May be faster, maybe not. + * + * XXX - Only works if your CopyWindow checks the root window's devPrivate + * to see which buffer to draw into. Works for cfbPaintWindow. + */ + +/*ARGSUSED*/ +static void +bufCopyWindow(pWin, ptOldOrg, prgnSrc) + WindowPtr pWin; + DDXPointRec ptOldOrg; + RegionPtr prgnSrc; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + WindowPtr pwinroot; + DevUnion save; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow); + + pwinroot = WindowTable[pScreen->myNum]; + save = pwinroot->devPrivates[frameWindowPrivateIndex]; + + /* + * Copy front buffer + */ + + pwinroot->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[FRONT_BUFFER]; + (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* + * Copy back buffer + */ + + /* CopyWindow translates prgnSrc... translate it back for 2nd call. */ + REGION_TRANSLATE(pScreen, prgnSrc, + ptOldOrg.x - pWin->drawable.x, + ptOldOrg.y - pWin->drawable.y); + pwinroot->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[BACK_BUFFER]; + (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + pwinroot->devPrivates[frameWindowPrivateIndex] = save; + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow); +} diff --git a/Xext/mbufpx.c b/Xext/mbufpx.c new file mode 100644 index 000000000..9474cc9aa --- /dev/null +++ b/Xext/mbufpx.c @@ -0,0 +1,646 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mbufpx.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" +#include + +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#define _MULTIBUF_PIXMAP_ +#include "multibufst.h" + + +static Bool NoopDDA_True() { return TRUE; } + +static Bool pixPositionWindow(); +static int pixCreateImageBuffers(); +static void pixDisplayImageBuffers(); +static void pixClearImageBufferArea(); +static void pixDeleteBufferDrawable(); +static void pixWrapScreenFuncs(); +static void pixResetProc(); + +Bool +pixMultibufferInit(pScreen, pMBScreen) + ScreenPtr pScreen; + mbufScreenPtr pMBScreen; +{ + int i, j, k; + xMbufBufferInfo *pInfo; + int nInfo; + DepthPtr pDepth; + mbufPixmapPrivPtr pMBPriv; + + pMBScreen->CreateImageBuffers = pixCreateImageBuffers; + pMBScreen->DestroyImageBuffers = (void (*)())NoopDDA; + pMBScreen->DisplayImageBuffers = pixDisplayImageBuffers; + pMBScreen->ClearImageBufferArea = pixClearImageBufferArea; + pMBScreen->ChangeMBufferAttributes = NoopDDA_True; + pMBScreen->ChangeBufferAttributes = NoopDDA_True; + pMBScreen->DeleteBufferDrawable = pixDeleteBufferDrawable; + pMBScreen->WrapScreenFuncs = pixWrapScreenFuncs; + pMBScreen->ResetProc = pixResetProc; + + /* Support every depth and visual combination that the screen does */ + + nInfo = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + nInfo += pDepth->numVids; + } + + pInfo = (xMbufBufferInfo *) xalloc (nInfo * sizeof (xMbufBufferInfo)); + if (!pInfo) + return FALSE; + + k = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + for (j = 0; j < pDepth->numVids; j++) + { + pInfo[k].visualID = pDepth->vids[j]; + pInfo[k].maxBuffers = 0; + pInfo[k].depth = pDepth->depth; + k++; + } + } + + pMBScreen->nInfo = nInfo; + pMBScreen->pInfo = pInfo; + + /* + * Setup the devPrivate to mbufScreenRec + */ + + pMBPriv = (mbufPixmapPrivPtr) xalloc(sizeof(* pMBPriv)); + if (!pMBPriv) + { + xfree(pInfo); + return (FALSE); + } + pMBScreen->devPrivate.ptr = (pointer) pMBPriv; + pMBPriv->PositionWindow = NULL; + pMBPriv->funcsWrapped = 0; + + return TRUE; +} + +/*ARGSUSED*/ +static int +pixCreateImageBuffers (pWin, nbuf, ids, action, hint) + WindowPtr pWin; + int nbuf; + XID *ids; + int action; + int hint; +{ + mbufWindowPtr pMBWindow; + mbufBufferPtr pMBBuffer; + ScreenPtr pScreen; + int width, height, depth; + int i; + + pMBWindow = MB_WINDOW_PRIV(pWin); + + width = pWin->drawable.width; + height = pWin->drawable.height; + depth = pWin->drawable.depth; + pScreen = pWin->drawable.pScreen; + + for (i = 0; i < nbuf; i++) + { + pMBBuffer = &pMBWindow->buffers[i]; + pMBBuffer->pDrawable = (DrawablePtr) + (*pScreen->CreatePixmap) (pScreen, width, height, depth); + if (!pMBBuffer->pDrawable) + break; + + if (!AddResource (ids[i], MultibufferDrawableResType, + (pointer) pMBBuffer->pDrawable)) + { + (*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable); + break; + } + pMBBuffer->pDrawable->id = ids[i]; + + /* + * In the description of the CreateImageBuffers request: + * "If the window is mapped, or if these image buffers have + * backing store, their contents will be tiled with the window + * background, and zero or more expose events will be generated + * for each of these buffers." + */ + + (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea) + (pMBBuffer, 0,0, 0,0, TRUE); + } + + return i; +} + +/* + * set up the gc to clear the pixmaps; + */ +static Bool +SetupBackgroundPainter (pWin, pGC) + WindowPtr pWin; + GCPtr pGC; +{ + XID gcvalues[4]; + int ts_x_origin, ts_y_origin; + PixUnion background; + int backgroundState; + Mask gcmask; + + /* + * First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + + ts_x_origin = ts_y_origin = 0; + while (pWin->backgroundState == ParentRelative) { + ts_x_origin -= pWin->origin.x; + ts_y_origin -= pWin->origin.y; + pWin = pWin->parent; + } + backgroundState = pWin->backgroundState; + background = pWin->background; + + switch (backgroundState) + { + case BackgroundPixel: + gcvalues[0] = (XID) background.pixel; + gcvalues[1] = FillSolid; + gcmask = GCForeground|GCFillStyle; + break; + + case BackgroundPixmap: + gcvalues[0] = FillTiled; + gcvalues[1] = (XID) background.pixmap; + gcvalues[2] = ts_x_origin; + gcvalues[3] = ts_y_origin; + gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; + break; + + default: + return FALSE; + } + DoChangeGC(pGC, gcmask, gcvalues, TRUE); + return TRUE; +} + +static void +MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects) + WindowPtr pWin; + DrawablePtr pDrawable; + int nrects; + xRectangle *pRects; +{ + GCPtr pGC; + + pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen); + if (SetupBackgroundPainter(pWin, pGC)) + { + ValidateGC(pDrawable, pGC); + (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, pRects); + } + FreeScratchGC(pGC); +} + +static void +MultibufferPaintBackgroundRegion(pWin, pDrawable, pRegion) + WindowPtr pWin; + DrawablePtr pDrawable; + RegionPtr pRegion; +{ + xRectangle *pRects; + int nrects = REGION_NUM_RECTS(pRegion); + BoxPtr pbox = REGION_RECTS(pRegion); + + pRects = (xRectangle *)ALLOCATE_LOCAL(nrects * sizeof(xRectangle)); + if (pRects) + { + int i; + for (i = 0; i < nrects; i++) + { + pRects[i].x = pbox->x1; + pRects[i].y = pbox->y1; + pRects[i].width = pbox->x2 - pbox->x1; + pRects[i].height = pbox->y2 - pbox->y1; + } + MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects); + DEALLOCATE_LOCAL(pRects); + } +} + +static void +pixDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf) + mbufBufferPtr *ppMBBuffer; + mbufWindowPtr *ppMBWindow; + int nbuf; +{ + GCPtr pGC = NULL; + PixmapPtr pPrevPixmap, pNewPixmap; + WindowPtr pWin; + RegionPtr pExposed; + int i; + mbufBufferPtr pPrevMBBuffer; + XID bool; + xRectangle r; + + UpdateCurrentTime (); + for (i = 0; i < nbuf; i++) + { + pWin = ppMBWindow[i]->pWindow; + + /* Time to get a different scratch GC? */ + + if (!pGC + || pGC->depth != pWin->drawable.depth + || pGC->pScreen != pWin->drawable.pScreen) + { + if (pGC) FreeScratchGC(pGC); + pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen); + } + pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]); + pPrevPixmap = (PixmapPtr) pPrevMBBuffer->pDrawable; + pNewPixmap = (PixmapPtr) ppMBBuffer[i]->pDrawable; + + if (pPrevPixmap == pNewPixmap) + { + /* "If a specified buffer is already displayed, any delays and + * update action will still be performed for that buffer." + * + * We special-case this because applications do occasionally + * request a redundant DisplayImageBuffers, and we can save + * strokes by recognizing that the only update action that will + * change the buffer contents in this case is Background. + */ + if (ppMBWindow[i]->updateAction == MultibufferUpdateActionBackground) + { + r.x = r.y = 0; + r.width = pWin->drawable.width; + r.height = pWin->drawable.height; + MultibufferPaintBackgroundRectangles(pWin, (DrawablePtr)pWin, + 1, &r); + } + } + else /* different buffer is being displayed */ + { + /* perform update action */ + + switch (ppMBWindow[i]->updateAction) + { + case MultibufferUpdateActionUndefined: + break; + + case MultibufferUpdateActionBackground: + + r.x = r.y = 0; + r.width = pPrevPixmap->drawable.width; + r.height = pPrevPixmap->drawable.height; + MultibufferPaintBackgroundRectangles(pWin, + (DrawablePtr)pPrevPixmap, + 1, &r); + break; + + case MultibufferUpdateActionUntouched: + + /* copy the window to the pixmap that represents the + * currently displayed buffer + */ + + if (pPrevMBBuffer->eventMask & ExposureMask) + { + bool = TRUE; + DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE); + } + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + pExposed = (*pGC->ops->CopyArea)((DrawablePtr) pWin, + (DrawablePtr) pPrevPixmap, + pGC, + 0, 0, + pWin->drawable.width, + pWin->drawable.height, + 0, 0); + + /* if we couldn't copy the whole window to the buffer, + * send expose events (if any client wants them) + */ + + if (pPrevMBBuffer->eventMask & ExposureMask) + { /* some client wants expose events */ + if (pExposed) + { + RegionPtr pWinSize; + extern RegionPtr CreateUnclippedWinSize(); + ScreenPtr pScreen = pWin->drawable.pScreen; + pWinSize = CreateUnclippedWinSize (pWin); + /* + * pExposed is window-relative, but at this point + * pWinSize is screen-relative. Make pWinSize be + * window-relative so that region ops involving + * pExposed and pWinSize behave sensibly. + */ + REGION_TRANSLATE(pScreen, pWinSize, + -pWin->drawable.x, + -pWin->drawable.y); + REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize); + REGION_DESTROY(pScreen, pWinSize); + MultibufferExpose (pPrevMBBuffer, pExposed); + REGION_DESTROY(pScreen, pExposed); + } + bool = FALSE; + DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE); + } /* end some client wants expose events */ + + break; /* end case MultibufferUpdateActionUntouched */ + + case MultibufferUpdateActionCopied: + + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, + (DrawablePtr)pPrevPixmap, pGC, + 0, 0, pWin->drawable.width, + pWin->drawable.height, 0, 0); + break; + + } /* end switch on update action */ + + /* display the new buffer */ + + ValidateGC ((DrawablePtr)pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin, + pGC, 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + } + + ppMBWindow[i]->lastUpdate = currentTime; + } + + if (pGC) FreeScratchGC (pGC); + return; +} + +/* + * resize the buffers when the window is resized + */ + +static Bool +pixPositionWindow (pWin, x, y) + WindowPtr pWin; + int x, y; +{ + ScreenPtr pScreen; + mbufPixmapPrivPtr pMBPriv; + mbufWindowPtr pMBWindow; + mbufBufferPtr pMBBuffer; + int width, height; + int i; + int dx, dy, dw, dh; + int sourcex, sourcey; + int destx, desty; + PixmapPtr pPixmap; + GCPtr pGC; + int savewidth, saveheight; + Bool clear; + RegionRec exposedRegion; + Bool ret; + + pScreen = pWin->drawable.pScreen; + pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen); + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow); + ret = (* pScreen->PositionWindow) (pWin, x, y); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow); + + if (!(pMBWindow = MB_WINDOW_PRIV(pWin))) + return ret; + + /* if new size is same as old, we're done */ + + if (pMBWindow->width == pWin->drawable.width && + pMBWindow->height == pWin->drawable.height) + return ret; + + width = pWin->drawable.width; + height = pWin->drawable.height; + dx = pWin->drawable.x - pMBWindow->x; + dy = pWin->drawable.x - pMBWindow->y; + dw = width - pMBWindow->width; + dh = height - pMBWindow->height; + GravityTranslate (0, 0, -dx, -dy, dw, dh, + pWin->bitGravity, &destx, &desty); + + /* if the window grew, remember to paint the window background, + * and maybe send expose events, for the new areas of the buffers + */ + + clear = pMBWindow->width < width || pMBWindow->height < height || + pWin->bitGravity == ForgetGravity; + + sourcex = 0; + sourcey = 0; + savewidth = pMBWindow->width; + saveheight = pMBWindow->height; + /* clip rectangle to source and destination */ + if (destx < 0) + { + savewidth += destx; + sourcex -= destx; + destx = 0; + } + if (destx + savewidth > width) + savewidth = width - destx; + if (desty < 0) + { + saveheight += desty; + sourcey -= desty; + desty = 0; + } + if (desty + saveheight > height) + saveheight = height - desty; + + pMBWindow->width = width; + pMBWindow->height = height; + pMBWindow->x = pWin->drawable.x; + pMBWindow->y = pWin->drawable.y; + + if (clear) + { + BoxRec box; + + box.x1 = box.y1 = 0; + box.x2 = width; + box.y2 = height; + REGION_INIT(pScreen, &exposedRegion, &box, 1); + if (pWin->bitGravity != ForgetGravity) + { + RegionRec preservedRegion; + box.x1 = destx; + box.y1 = desty; + box.x2 = destx + savewidth; + box.y2 = desty + saveheight; + REGION_INIT(pScreen, &preservedRegion, &box, 1); + REGION_SUBTRACT(pScreen, &exposedRegion, &exposedRegion, &preservedRegion); + REGION_UNINIT(pScreen, &preservedRegion); + } + + } /* end if (clear) */ + + pGC = GetScratchGC (pWin->drawable.depth, pScreen); + + /* create buffers with new window size */ + + for (i = 0; i < pMBWindow->numMultibuffer; i++) + { + pMBBuffer = &pMBWindow->buffers[i]; + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, pWin->drawable.depth); + if (!pPixmap) + { + (* MB_SCREEN_PRIV(pScreen)->DestroyImageBuffers)(pWin); + break; + } + if (clear) + { + MultibufferPaintBackgroundRegion(pWin, (DrawablePtr)pPixmap, &exposedRegion); + MultibufferExpose(pMBBuffer, &exposedRegion); + } + if (pWin->bitGravity != ForgetGravity) + { + ValidateGC ((DrawablePtr)pPixmap, pGC); + (*pGC->ops->CopyArea) (pMBBuffer->pDrawable, (DrawablePtr)pPixmap, + pGC, + sourcex, sourcey, savewidth, saveheight, + destx, desty); + } + pPixmap->drawable.id = pMBBuffer->pDrawable->id; + (*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable); + pMBBuffer->pDrawable = (DrawablePtr) pPixmap; + if (i != pMBWindow->displayedMultibuffer) + { + ChangeResourceValue (pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pPixmap); + } + } + FreeScratchGC (pGC); + if (clear) + REGION_UNINIT(pScreen, &exposedRegion); + return TRUE; +} + +static void +pixWrapScreenFuncs(pScreen) + ScreenPtr pScreen; +{ + mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen); + WRAP_SCREEN_FUNC(pScreen, pMBPriv, PositionWindow, pixPositionWindow); +} + +static void +pixResetProc(pScreen) + ScreenPtr pScreen; +{ + mbufScreenPtr pMBScreen = MB_SCREEN_PRIV(pScreen); + mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen); + + xfree(pMBScreen->pInfo); + xfree(pMBPriv); +} + +static void +pixClearImageBufferArea(pMBBuffer, x,y, width,height, exposures) + mbufBufferPtr pMBBuffer; + short x, y; + unsigned short width, height; + Bool exposures; +{ + WindowPtr pWin; + ScreenPtr pScreen; + BoxRec box; + RegionRec region; + int w_width, w_height; + DrawablePtr pDrawable; + + pWin = pMBBuffer->pMBWindow->pWindow; + pScreen = pWin->drawable.pScreen; + + w_width = pWin->drawable.width; + w_height = pWin->drawable.height; + + box.x1 = x; + box.y1 = y; + box.x2 = width ? (box.x1 + width) : w_width; + box.y2 = height ? (box.y1 + height) : w_height; + + if (box.x1 < 0) box.x1 = 0; + if (box.y1 < 0) box.y1 = 0; + if (box.x2 > w_width) box.x2 = w_width; + if (box.y2 > w_height) box.y2 = w_height; + + REGION_INIT(pScreen, ®ion, &box, 1); + + if (pMBBuffer->number == pMBBuffer->pMBWindow->displayedMultibuffer) + pDrawable = (DrawablePtr) pWin; + else + pDrawable = pMBBuffer->pDrawable; + + MultibufferPaintBackgroundRegion(pWin, pDrawable, ®ion); + + if (exposures) + MultibufferExpose(pMBBuffer, ®ion); + + REGION_UNINIT(pScreen, ®ion); +} + +static void +pixDeleteBufferDrawable(pDrawable) + DrawablePtr pDrawable; +{ + (* pDrawable->pScreen->DestroyPixmap)((PixmapPtr) pDrawable); +} diff --git a/Xext/mitmisc.c b/Xext/mitmisc.c new file mode 100644 index 000000000..63e496209 --- /dev/null +++ b/Xext/mitmisc.c @@ -0,0 +1,153 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* RANDOM CRUFT! THIS HAS NO OFFICIAL X CONSORTIUM OR X PROJECT TEAM BLESSING */ + +/* $Xorg: mitmisc.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#define _MITMISC_SERVER_ +#include "mitmiscstr.h" + +extern Bool permitOldBugs; + +static unsigned char MITReqCode; +static int ProcMITDispatch(), SProcMITDispatch(); +static void MITResetProc(); + +void +MITMiscExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(MITMISCNAME, 0, 0, + ProcMITDispatch, SProcMITDispatch, + MITResetProc, StandardMinorOpcode)) + MITReqCode = (unsigned char)extEntry->base; +} + +/*ARGSUSED*/ +static void +MITResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcMITSetBugMode(client) + register ClientPtr client; +{ + REQUEST(xMITSetBugModeReq); + + REQUEST_SIZE_MATCH(xMITSetBugModeReq); + if ((stuff->onOff != xTrue) && (stuff->onOff != xFalse)) + { + client->errorValue = stuff->onOff; + return BadValue; + } + permitOldBugs = stuff->onOff; + return(client->noClientException); +} + +static int +ProcMITGetBugMode(client) + register ClientPtr client; +{ + REQUEST(xMITGetBugModeReq); + xMITGetBugModeReply rep; + register int n; + + REQUEST_SIZE_MATCH(xMITGetBugModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.onOff = permitOldBugs; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xMITGetBugModeReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcMITDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_MITSetBugMode: + return ProcMITSetBugMode(client); + case X_MITGetBugMode: + return ProcMITGetBugMode(client); + default: + return BadRequest; + } +} + +static int +SProcMITSetBugMode(client) + register ClientPtr client; +{ + register int n; + REQUEST(xMITSetBugModeReq); + + swaps(&stuff->length, n); + return ProcMITSetBugMode(client); +} + +static int +SProcMITGetBugMode(client) + register ClientPtr client; +{ + register int n; + REQUEST(xMITGetBugModeReq); + + swaps(&stuff->length, n); + return ProcMITGetBugMode(client); +} + +static int +SProcMITDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_MITSetBugMode: + return SProcMITSetBugMode(client); + case X_MITGetBugMode: + return SProcMITGetBugMode(client); + default: + return BadRequest; + } +} diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c new file mode 100644 index 000000000..2d3eb7c42 --- /dev/null +++ b/Xext/panoramiX.c @@ -0,0 +1,780 @@ +/* $Xorg: panoramiX.c,v 1.5 2000/08/17 19:47:57 cpqbld Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ + +#define NEED_REPLIES +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "gc.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "window.h" +#include "windowstr.h" +#include "pixmapstr.h" +#if 0 +#include +#include +#endif +#include "panoramiX.h" +#include "panoramiXproto.h" + +static unsigned char PanoramiXReqCode = 0; +/* + * PanoramiX data declarations + */ + +int PanoramiXPixWidth; +int PanoramiXPixHeight; +int PanoramiXNumScreens; + +PanoramiXData *panoramiXdataPtr; +PanoramiXWindow *PanoramiXWinRoot; +PanoramiXGC *PanoramiXGCRoot; +PanoramiXCmap *PanoramiXCmapRoot; +PanoramiXPmap *PanoramiXPmapRoot; + +PanoramiXEdge panoramiXEdgePtr[MAXSCREENS]; +RegionRec PanoramiXScreenRegion[MAXSCREENS]; +PanoramiXCDT PanoramiXColorDepthTable[MAXSCREENS]; +PanoramiXDepth PanoramiXLargestScreenDepth; + +int (* SavedProcVector[256]) (); +ScreenInfo *GlobalScrInfo; + +static int panoramiXGeneration; +static int ProcPanoramiXDispatch(); +/* + * Function prototypes + */ + +static void locate_neighbors(int); +static void PanoramiXResetProc(ExtensionEntry*); + +/* + * External references for data variables + */ + +extern int SProcPanoramiXDispatch(); +extern Bool noPanoramiXExtension; +extern Bool PanoramiXVisibilityNotifySent; +extern WindowPtr *WindowTable; +#if 0 +extern ScreenArgsRec screenArgs[MAXSCREENS]; +#endif +extern int defaultBackingStore; +extern char *ConnectionInfo; +extern int connBlockScreenStart; +extern int (* ProcVector[256]) (); + +/* + * Server dispatcher function replacements + */ + +int PanoramiXCreateWindow(), PanoramiXChangeWindowAttributes(); +int PanoramiXDestroyWindow(), PanoramiXDestroySubwindows(); +int PanoramiXChangeSaveSet(), PanoramiXReparentWindow(); +int PanoramiXMapWindow(), PanoramiXMapSubwindows(); +int PanoramiXUnmapWindow(), PanoramiXUnmapSubwindows(); +int PanoramiXConfigureWindow(), PanoramiXCirculateWindow(); +int PanoramiXGetGeometry(), PanoramiXChangeProperty(); +int PanoramiXDeleteProperty(), PanoramiXSendEvent(); +int PanoramiXCreatePixmap(), PanoramiXFreePixmap(); +int PanoramiXCreateGC(), PanoramiXChangeGC(); +int PanoramiXCopyGC(); +int PanoramiXSetDashes(), PanoramiXSetClipRectangles(); +int PanoramiXFreeGC(), PanoramiXClearToBackground(); +int PanoramiXCopyArea(), PanoramiXCopyPlane(); +int PanoramiXPolyPoint(), PanoramiXPolyLine(); +int PanoramiXPolySegment(), PanoramiXPolyRectangle(); +int PanoramiXPolyArc(), PanoramiXFillPoly(); +int PanoramiXPolyFillArc(), PanoramiXPolyFillRectangle(); +int PanoramiXPutImage(), PanoramiXGetImage(); +int PanoramiXPolyText8(), PanoramiXPolyText16(); +int PanoramiXImageText8(), PanoramiXImageText16(); +int PanoramiXCreateColormap(), PanoramiXFreeColormap(); +int PanoramiXInstallColormap(), PanoramiXUninstallColormap(); +int PanoramiXAllocColor(), PanoramiXAllocNamedColor(); +int PanoramiXAllocColorCells(); +int PanoramiXFreeColors(), PanoramiXStoreColors(); + +/* + * PanoramiXExtensionInit(): + * Called from InitExtensions in main(). + * Register PanoramiXeen Extension + * Initialize global variables. + */ + +void PanoramiXExtensionInit(int argc, char *argv[]) +{ + int i, j, PhyScrNum, ArgScrNum; + Bool success = FALSE; + ExtensionEntry *extEntry, *AddExtension(); + PanoramiXData *panoramiXtempPtr; + ScreenPtr pScreen; + + if (!noPanoramiXExtension) + { + GlobalScrInfo = &screenInfo; /* For debug visibility */ + PanoramiXNumScreens = screenInfo.numScreens; + if (PanoramiXNumScreens == 1) { /* Only 1 screen */ + noPanoramiXExtension = TRUE; + return; + } + + while (panoramiXGeneration != serverGeneration) { + extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, + ProcPanoramiXDispatch, + SProcPanoramiXDispatch, PanoramiXResetProc, + StandardMinorOpcode); + if (!extEntry) { + ErrorF("PanoramiXExtensionInit(): failed to AddExtension\n"); + break; + } + PanoramiXReqCode = (unsigned char)extEntry->base; + + /* + * First make sure all the basic allocations succeed. If not, + * run in non-PanoramiXeen mode. + */ + + panoramiXdataPtr = (PanoramiXData *) Xcalloc(PanoramiXNumScreens * sizeof(PanoramiXData)); + PanoramiXWinRoot = (PanoramiXWindow *) Xcalloc(sizeof(PanoramiXWindow)); + PanoramiXGCRoot = (PanoramiXGC *) Xcalloc(sizeof(PanoramiXGC)); + PanoramiXCmapRoot = (PanoramiXCmap *) Xcalloc(sizeof(PanoramiXCmap)); + PanoramiXPmapRoot = (PanoramiXPmap *) Xcalloc(sizeof(PanoramiXPmap)); + BREAK_IF(!(panoramiXdataPtr && PanoramiXWinRoot && PanoramiXGCRoot && + PanoramiXCmapRoot && PanoramiXPmapRoot)); + + panoramiXGeneration = serverGeneration; + success = TRUE; + } + + if (!success) { + noPanoramiXExtension = TRUE; + ErrorF("%s Extension failed to initialize\n", PANORAMIX_PROTOCOL_NAME); + return; + } + + /* Set up a default configuration base on horizontal ordering */ + for (i = PanoramiXNumScreens -1; i >= 0 ; i--) { + panoramiXdataPtr[i].above = panoramiXdataPtr[i].below = -1; + panoramiXdataPtr[i].left = panoramiXdataPtr[i].right = -1; + panoramiXEdgePtr[i].no_edges = TRUE; + } + for (i = PanoramiXNumScreens - 1; i >= 0; i--) { + panoramiXdataPtr[i].left = i - 1; + panoramiXdataPtr[i].right = i + 1; + } + panoramiXdataPtr[PanoramiXNumScreens - 1].right = -1; + + /* + * Position the screens relative to each other based on + * command line options. + */ + +#if 0 + for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) { + if (wsRemapPhysToLogScreens) + i = wsPhysToLogScreens[PhyScrNum]; + else + i = PhyScrNum; + if (i < 0) + continue; + panoramiXdataPtr[i].width = (screenInfo.screens[i])->width; + panoramiXdataPtr[i].height = (screenInfo.screens[i])->height; + if (screenArgs[i].flags & ARG_EDGE_L) { + ArgScrNum = screenArgs[PhyScrNum].edge_left; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].left = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].right = i; + else { + if ( i >= 1 ) + panoramiXdataPtr[i - 1].right = -1; + } + } + if (screenArgs[i].flags & ARG_EDGE_R) { + ArgScrNum = screenArgs[PhyScrNum].edge_right; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].right = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].left = i; + } + if (screenArgs[i].flags & ARG_EDGE_T) { + ArgScrNum = screenArgs[PhyScrNum].edge_top; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].above = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].below = i; + } + if (screenArgs[i].flags & ARG_EDGE_B) { + ArgScrNum = screenArgs[PhyScrNum].edge_bottom; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].below = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].above = i; + } + } +#else + for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) { + i = PhyScrNum; + if (i < 0) + continue; + panoramiXdataPtr[i].width = (screenInfo.screens[i])->width; + panoramiXdataPtr[i].height = (screenInfo.screens[i])->height; + } +#endif + + /* + * Find the upper-left screen and then locate all the others + */ + panoramiXtempPtr = panoramiXdataPtr; + for (i = PanoramiXNumScreens; i; i--, panoramiXtempPtr++) + if (panoramiXtempPtr->above == -1 && panoramiXtempPtr->left == -1) + break; + locate_neighbors(PanoramiXNumScreens - i); + + /* + * Put our processes into the ProcVector + */ + + for (i = 256; i--; ) + SavedProcVector[i] = ProcVector[i]; + + ProcVector[X_CreateWindow] = PanoramiXCreateWindow; + ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes; + ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow; + ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows; + ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet; + ProcVector[X_ReparentWindow] = PanoramiXReparentWindow; + ProcVector[X_MapWindow] = PanoramiXMapWindow; + ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows; + ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow; + ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows; + ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; + ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; + ProcVector[X_GetGeometry] = PanoramiXGetGeometry; + ProcVector[X_ChangeProperty] = PanoramiXChangeProperty; + ProcVector[X_DeleteProperty] = PanoramiXDeleteProperty; + ProcVector[X_SendEvent] = PanoramiXSendEvent; + ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; + ProcVector[X_FreePixmap] = PanoramiXFreePixmap; + ProcVector[X_CreateGC] = PanoramiXCreateGC; + ProcVector[X_ChangeGC] = PanoramiXChangeGC; + ProcVector[X_CopyGC] = PanoramiXCopyGC; + ProcVector[X_SetDashes] = PanoramiXSetDashes; + ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles; + ProcVector[X_FreeGC] = PanoramiXFreeGC; + ProcVector[X_ClearArea] = PanoramiXClearToBackground; + ProcVector[X_CopyArea] = PanoramiXCopyArea;; + ProcVector[X_CopyPlane] = PanoramiXCopyPlane;; + ProcVector[X_PolyPoint] = PanoramiXPolyPoint; + ProcVector[X_PolyLine] = PanoramiXPolyLine; + ProcVector[X_PolySegment] = PanoramiXPolySegment; + ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle; + ProcVector[X_PolyArc] = PanoramiXPolyArc; + ProcVector[X_FillPoly] = PanoramiXFillPoly; + ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle; + ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc; + ProcVector[X_PutImage] = PanoramiXPutImage; + ProcVector[X_GetImage] = PanoramiXGetImage; + ProcVector[X_PolyText8] = PanoramiXPolyText8; + ProcVector[X_PolyText16] = PanoramiXPolyText16; + ProcVector[X_ImageText8] = PanoramiXImageText8; + ProcVector[X_ImageText16] = PanoramiXImageText16; + ProcVector[X_CreateColormap] = PanoramiXCreateColormap; + ProcVector[X_FreeColormap] = PanoramiXFreeColormap; + ProcVector[X_InstallColormap] = PanoramiXInstallColormap; + ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; + ProcVector[X_AllocColor] = PanoramiXAllocColor; + ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; + ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; + ProcVector[X_FreeColors] = PanoramiXFreeColors; + ProcVector[X_StoreColors] = PanoramiXStoreColors; + + } + else + return; +} +extern +Bool PanoramiXCreateConnectionBlock(void) +{ + int i; + int old_width, old_height; + int width_mult, height_mult; + xWindowRoot *root; + xConnSetup *setup; + + /* + * Do normal CreateConnectionBlock but faking it for only one screen + */ + + if (!CreateConnectionBlock()) { + return FALSE; + } + + /* + * OK, change some dimensions so it looks as if it were one big screen + */ + + setup = (xConnSetup *) ConnectionInfo; + setup->numRoots = 1; + root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); + + old_width = root->pixWidth; + old_height = root->pixHeight; + for (i = PanoramiXNumScreens - 1; i >= 0; i--) { + if (panoramiXdataPtr[i].right == -1 ) + root->pixWidth = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; + if (panoramiXdataPtr[i].below == -1) + root->pixHeight = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; + } + PanoramiXPixWidth = root->pixWidth; + PanoramiXPixHeight = root->pixHeight; + width_mult = root->pixWidth / old_width; + height_mult = root->pixHeight / old_height; + root->mmWidth *= width_mult; + root->mmHeight *= height_mult; + return TRUE; +} + +extern +Bool PanoramiXCreateScreenRegion(pWin) +WindowPtr pWin; +{ + ScreenPtr pScreen; + BoxRec box; + int i; + Bool ret; + + pScreen = pWin->drawable.pScreen; + for (i = 0; i < PanoramiXNumScreens; i++) { + box.x1 = 0 - panoramiXdataPtr[i].x; + box.x2 = box.x1 + PanoramiXPixWidth; + box.y1 = 0 - panoramiXdataPtr[i].y; + box.y2 = box.y1 + PanoramiXPixHeight; + REGION_INIT(pScreen, &PanoramiXScreenRegion[i], &box, 1); + ret = REGION_NOTEMPTY(pScreen, &PanoramiXScreenRegion[i]); + if (!ret) + return ret; + } + return ret; +} + +extern +void PanoramiXDestroyScreenRegion(pWin) +WindowPtr pWin; +{ + ScreenPtr pScreen; + int i; + Bool ret; + + pScreen = pWin->drawable.pScreen; + for (i = 0; i < PanoramiXNumScreens; i++) + REGION_DESTROY(pScreen, &PanoramiXScreenRegion[i]); +} + +/* + * Assign the Root window and colormap ID's in the PanoramiXScreen Root + * linked lists. Note: WindowTable gets setup in dix_main by + * InitRootWindow, and GlobalScrInfo is screenInfo which gets setup + * by InitOutput. + */ +extern +void PanoramiXConsolidate(void) +{ + int i,j,k,v,d,n, thisMaxDepth; + int depthIndex; + DepthPtr pDepth, pLargeDepth; + VisualPtr pVisual; + VisualID it; + register WindowPtr pWin, pLargeWin; + Bool SameDepth; + + PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[PanoramiXNumScreens -1])->numDepths; + PanoramiXLargestScreenDepth.screenNum = PanoramiXNumScreens - 1; + SameDepth = TRUE; + for (i = 0; i < 2; i++) + { + for (j =0; j < 6; j++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].numDepths=0; + for (n = 0; n < 6; n++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].listDepths[n]=0; + } + for (k = 0; k < 33; k++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].numVids=0; + for (v = 0; v < 10; v++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].vid[v]=0; + } + } + } + } + for (i = PanoramiXNumScreens - 1; i >= 0; i--) + { + PanoramiXWinRoot->info[i].id = WindowTable[i]->drawable.id; + PanoramiXCmapRoot->info[i].id = (screenInfo.screens[i])->defColormap; + + /* Create a Color-Depth-Table, this will help us deal + with mixing graphics boards and visuals, of course + given that the boards support multi-screen to begin + with. Fill the panoramiXCDT table by screen, then + visual type and allowable depths. + */ + pWin = WindowTable[i]; + if ( (screenInfo.screens[i])->numDepths > + PanoramiXLargestScreenDepth.numDepths ) + { + PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[i])->numDepths; + PanoramiXLargestScreenDepth.screenNum = i; + SameDepth = FALSE; + } + for (v = 0, pVisual = pWin->drawable.pScreen->visuals; + v < pWin->drawable.pScreen->numVisuals; v++, pVisual++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].numDepths = (screenInfo.screens[i])->numDepths; + for ( j = 0; j < (screenInfo.screens[i])->numDepths; j++) + { + pDepth = (DepthPtr) &pWin->drawable.pScreen->allowedDepths[j]; + PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].listDepths[j] = pDepth->depth; + for (d = 0; d < pDepth->numVids; d++) + { + if (pVisual->vid == pDepth->vids[d]) + { + PanoramiXColorDepthTable[i]. + panoramiXScreenMap[pVisual->class].vmap[pDepth->depth]. + vid[ + PanoramiXColorDepthTable[i]. + panoramiXScreenMap[pVisual->class]. + vmap[pDepth->depth].numVids++ + ] + = pDepth->vids[d]; + } + } + } + } + PanoramiXColorDepthTable[i].numVisuals = 6; + } /* for each screen */ + /* Fill in ColorDepthTable for mixed visuals with varying depth. + Can't do that until we figure out how to handle mixed visuals + and varying card visual/depth initialization. If we can decide + how to map the relationship, then we can use this table to + shove the information into and use for cross-referencing when + necessary. + + In the meantime, check to see if the screens are the same, + if they don't then disable panoramiX, print out a message, + don't support this mode. + */ +} + +/* Since locate_neighbors is recursive, a quick simple example + is in order.This mostly so you can see what the initial values are. + + Given 3 screens: + upperleft screen[0] + panoramiXdataPtr[0].x = 0 + panoramiXdataPtr[0].y = 0 + panoramiXdataPtr[0].width = 640 + panoramiXdataPtr[0].height = 480 + panoramiXdataPtr[0].below = -1 + panoramiXdataPtr[0].right = 1 + panoramiXdataPtr[0].above = -1 + panoramiXdataPtr[0].left = -1 + middle screen[1] + panoramiXdataPtr[1].x = 0 + panoramiXdataPtr[1].y = 0 + panoramiXdataPtr[1].width = 640 + panoramiXdataPtr[1].height = 480 + panoramiXdataPtr[1].below = -1 + panoramiXdataPtr[1].right = 2 + panoramiXdataPtr[1].above = -1 + panoramiXdataPtr[1].left = 0 + last right screen[2] + panoramiXdataPtr[2].x = 0 + panoramiXdataPtr[2].y = 0 + panoramiXdataPtr[2].width = 640 + panoramiXdataPtr[2].height = 480 + panoramiXdataPtr[2].below = -1 + panoramiXdataPtr[2].right = -1 + panoramiXdataPtr[2].above = -1 + panoramiXdataPtr[2].left = 1 + + Calling locate_neighbors(0) results in: + panoramiXdataPtr[0].x = 0 + panoramiXdataPtr[0].y = 0 + panoramiXdataPtr[1].x = 640 + panoramiXdataPtr[1].y = 0 + panoramiXdataPtr[2].x = 1280 + panoramiXdataPtr[2].y = 0 +*/ + +static void locate_neighbors(int i) +{ + int j; + + j = panoramiXdataPtr[i].right; + if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) { + panoramiXdataPtr[j].x = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; + panoramiXdataPtr[j].y = panoramiXdataPtr[i].y; + locate_neighbors(j); + } + j = panoramiXdataPtr[i].below; + if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) { + panoramiXdataPtr[j].y = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; + panoramiXdataPtr[j].x = panoramiXdataPtr[i].x; + locate_neighbors(j); + } +} + + + +/* + * PanoramiXResetProc() + * Exit, deallocating as needed. + */ + +static void PanoramiXResetProc(extEntry) + ExtensionEntry* extEntry; +{ + int i; + PanoramiXList *pPanoramiXList; + PanoramiXList *tempList; + + for (pPanoramiXList = PanoramiXPmapRoot; pPanoramiXList; pPanoramiXList = tempList){ + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + for (pPanoramiXList = PanoramiXCmapRoot; pPanoramiXList; pPanoramiXList = tempList){ + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + for (pPanoramiXList = PanoramiXGCRoot; pPanoramiXList; pPanoramiXList = tempList) { + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + for (pPanoramiXList = PanoramiXWinRoot; pPanoramiXList; pPanoramiXList = tempList) { + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + screenInfo.numScreens = PanoramiXNumScreens; + for (i = 256; i--; ) + ProcVector[i] = SavedProcVector[i]; + Xfree(panoramiXdataPtr); + +} + + +int +#if NeedFunctionPrototypes +ProcPanoramiXQueryVersion (ClientPtr client) +#else +ProcPanoramiXQueryVersion (client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXQueryVersionReq); + xPanoramiXQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = PANORAMIX_MAJOR_VERSION; + rep.minorVersion = PANORAMIX_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +int +#if NeedFunctionPrototypes +ProcPanoramiXGetState(ClientPtr client) +#else +ProcPanoramiXGetState(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPanoramiXExtension; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.state, n); + } + WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); + return client->noClientException; + +} + +int +#if NeedFunctionPrototypes +ProcPanoramiXGetScreenCount(ClientPtr client) +#else +ProcPanoramiXGetScreenCount(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = PanoramiXNumScreens; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.ScreenCount, n); + } + WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcPanoramiXGetScreenSize(ClientPtr client) +#else +ProcPanoramiXGetScreenSize(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + /* screen dimensions */ + rep.width = panoramiXdataPtr[stuff->screen].width; + rep.height = panoramiXdataPtr[stuff->screen].height; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (rep.width, n); + swaps (rep.height, n); + } + WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); + return client->noClientException; +} + + +void PrintList(PanoramiXList *head) +{ + int i = 0; + + for (; head; i++, head = head->next) + fprintf(stderr, "%2d next = 0x%010lx, id[0] = 0x%08x, id[1] = 0x%08x\n", + i, head->next, head->info[0].id, head->info[1].id); +} +static int +#if NeedFunctionPrototypes +ProcPanoramiXDispatch (ClientPtr client) +#else +ProcPanoramiXDispatch (client) + ClientPtr client; +#endif +{ REQUEST(xReq); + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return ProcPanoramiXQueryVersion(client); + case X_PanoramiXGetState: + return ProcPanoramiXGetState(client); + case X_PanoramiXGetScreenCount: + return ProcPanoramiXGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return ProcPanoramiXGetScreenSize(client); + } + return BadRequest; +} diff --git a/Xext/panoramiXSwap.c b/Xext/panoramiXSwap.c new file mode 100644 index 000000000..c6bb5071e --- /dev/null +++ b/Xext/panoramiXSwap.c @@ -0,0 +1,158 @@ +/* $Xorg: panoramiXSwap.c,v 1.4 2000/08/17 19:47:57 cpqbld Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ + +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "gc.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "window.h" +#include "windowstr.h" +#include "pixmapstr.h" +#if 0 +#include +#include +#endif +#include "panoramiX.h" +#include "panoramiXproto.h" + + +/* +/* + * External references for data variables + */ + +extern Bool noPanoramiXExtension; +extern Bool PanoramiXVisibilityNotifySent; +extern WindowPtr *WindowTable; +extern int defaultBackingStore; +extern char *ConnectionInfo; +extern int connBlockScreenStart; +extern int (* ProcVector[256]) (); + +#if NeedFunctionPrototypes +#define PROC_EXTERN(pfunc) extern int pfunc(ClientPtr) +#else +#define PROC_EXTERN(pfunc) extern int pfunc() +#endif + +PROC_EXTERN(ProcPanoramiXQueryVersion); +PROC_EXTERN(ProcPanoramiXGetState); +PROC_EXTERN(ProcPanoramiXGetScreenCount); +PROC_EXTERN(PropPanoramiXGetScreenSize); + +static int +#if NeedFunctionPrototypes +SProcPanoramiXQueryVersion (ClientPtr client) +#else +SProcPanoramiXQueryVersion (client) + register ClientPtr client; +#endif +{ + register int n; + REQUEST(xPanoramiXQueryVersionReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + return ProcPanoramiXQueryVersion(client); +} + +static int +#if NeedFunctionPrototypes +SProcPanoramiXGetState(ClientPtr client) +#else +SProcPanoramiXGetState(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + +} + +static int +#if NeedFunctionPrototypes +SProcPanoramiXGetScreenCount(ClientPtr client) +#else +SProcPanoramixGetScreenCount(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return ProcPanoramiXGetScreenCount(client); +} + +static int +#if NeedFunctionPrototypes +SProcPanoramiXGetScreenSize(ClientPtr client) +#else +SProcPanoramiXGetScreenSize(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return ProcPanoramiXGetScreenSize(client); +} + +int +#if NeedFunctionPrototypes +SProcPanoramiXDispatch (ClientPtr client) +#else +SProcPanoramiXDispatch (client) + ClientPtr client; +#endif +{ REQUEST(xReq); + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return SProcPanoramiXQueryVersion(client); + case X_PanoramiXGetState: + return SProcPanoramiXGetState(client); + case X_PanoramiXGetScreenCount: + return SProcPanoramiXGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return SProcPanoramiXGetScreenSize(client); + return BadRequest; + } +} diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c new file mode 100644 index 000000000..cd54bdcb3 --- /dev/null +++ b/Xext/panoramiXprocs.c @@ -0,0 +1,3034 @@ +/* $Xorg: panoramiXprocs.c,v 1.5 2000/08/17 19:47:57 cpqbld Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ + +#include +#include "X.h" +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xproto.h" +#include "windowstr.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "inputstr.h" +#include "migc.h" +#include "misc.h" +#include "dixstruct.h" +#include "panoramiX.h" + +extern Bool noPanoramiXExtension; +extern Bool PanoramiXVisibilityNotifySent; +extern Bool PanoramiXMapped; +extern int PanoramiXNumScreens; +extern int PanoramiXPixWidth; +extern int PanoramiXPixHeight; +extern PanoramiXWindow *PanoramiXWinRoot; +extern PanoramiXGC *PanoramiXGCRoot; +extern PanoramiXCmap *PanoramiXCmapRoot; +extern PanoramiXPmap *PanoramiXPmapRoot; +extern PanoramiXData *panoramiXdataPtr; +extern PanoramiXCDT PanoramiXColorDepthTable[MAXSCREENS]; +extern ScreenInfo *GlobalScrInfo; +extern int (* SavedProcVector[256])(); +extern void (* ReplySwapVector[256])(); +extern WindowPtr *WindowTable; +extern char *ConnectionInfo; +extern int connBlockScreenStart; + +extern XID clientErrorValue; + +extern void Swap32Write(); + +extern long defaultScreenSaverTime; +extern long defaultScreenSaverInterval; +extern int defaultScreenSaverBlanking; +extern int defaultScreenSaverAllowExposures; +static ClientPtr onlyClient; +static Bool grabbingClient = FALSE; +#ifdef __alpha /* THIS NEEDS TO BE LONG !!!! Change driver! */ +int *checkForInput[2]; +#else +long *checkForInput[2]; +#endif +extern int connBlockScreenStart; + +extern int (* InitialVector[3]) (); +extern int (* ProcVector[256]) (); +extern int (* SwappedProcVector[256]) (); +extern void (* EventSwapVector[128]) (); +extern void (* ReplySwapVector[256]) (); +extern void Swap32Write(), SLHostsExtend(), SQColorsExtend(), +WriteSConnectionInfo(); +extern void WriteSConnSetupPrefix(); +extern char *ClientAuthorized(); +extern Bool InsertFakeRequest(); +static void KillAllClients(); +static void DeleteClientFromAnySelections(); +extern void ProcessWorkQueue(); + + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number active clients */ + +char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + + + +extern int Ones(); + +int PanoramiXCreateWindow(register ClientPtr client) +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result, j = 0; + unsigned len; + Bool FoundIt = FALSE; + Window winID; + Window parID; + PanoramiXWindow *localWin; + PanoramiXWindow *parentWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXCmap *pPanoramiXCmap = NULL; + PanoramiXPmap *pBackgndPmap = NULL; + PanoramiXPmap *pBorderPmap = NULL; + VisualID orig_visual; + XID orig_wid; + int orig_x, orig_y; + register Mask orig_mask; + int cmap_offset = 0; + int pback_offset = 0; + int pbord_offset = 0; + int class_index, this_class_index; + int vid_index, this_vid_index; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + IF_RETURN((Ones((Mask)stuff->mask) != len), BadLength); + orig_mask = stuff->mask; + PANORAMIXFIND_ID(parentWin, stuff->parent); + if (parentWin) { + localWin = (PanoramiXWindow *)Xcalloc(sizeof(PanoramiXWindow)); + IF_RETURN(!localWin, BadAlloc); + } else { + return BadWindow; + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWBackPixmap)) { + XID pmapID; + + pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pback_offset); + if (pmapID) { + pBackgndPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBackgndPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWBorderPixmap)) { + XID pmapID; + + pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pbord_offset); + if (pmapID) { + pBorderPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBorderPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWColormap)) { + Colormap cmapID; + + cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); + cmapID = *((CARD32 *) &stuff[1] + cmap_offset); + if (cmapID) { + pPanoramiXCmap = PanoramiXCmapRoot; + PANORAMIXFIND_ID(pPanoramiXCmap, cmapID); + } + } + orig_x = stuff->x; + orig_y = stuff->y; + orig_wid = stuff->wid; + orig_visual = stuff->visual; + for (j = 0; j <= PanoramiXNumScreens - 1; j++) { + winID = j ? FakeClientID(client->index) : orig_wid; + localWin->info[j].id = winID; + } + localWin->FreeMe = FALSE; + localWin->visibility = VisibilityNotViewable; + localWin->VisibilitySent = FALSE; + PANORAMIXFIND_LAST(pPanoramiXWin, PanoramiXWinRoot); + pPanoramiXWin->next = localWin; + if ( (stuff->visual != CopyFromParent) && (stuff->depth != 0)) + { + /* Find the correct visual for this screen */ + for (class_index = 0; class_index < PanoramiXColorDepthTable[0].numVisuals; +class_index++) + { + for (vid_index = 0; vid_index < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[stuff->depth].numVids; vid_index++) + { + if ( stuff->visual == PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[stuff->depth].vid[vid_index] ) + { + this_class_index = class_index; + this_vid_index = vid_index; + FoundIt = TRUE; + break; + } + } + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (parentWin == PanoramiXWinRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + stuff->wid = localWin->info[j].id; + parID = (XID)(parentWin->info[j].id); + pParent = (WindowPtr)SecurityLookupWindow(parID, client,SecurityReadAccess); + IF_RETURN((!pParent),BadWindow); + stuff->parent = parID; + if ( (orig_visual != CopyFromParent) && (stuff->depth != 0) && FoundIt ) + { + stuff->visual = PanoramiXColorDepthTable[j].panoramiXScreenMap[this_class_index].vmap[stuff->depth].vid[this_vid_index]; + } + if (pBackgndPmap) + *((CARD32 *) &stuff[1] + pback_offset) = pBackgndPmap->info[j].id; + if (pBorderPmap) + *((CARD32 *) &stuff[1] + pbord_offset) = pBorderPmap->info[j].id; + if (pPanoramiXCmap) + *((CARD32 *) &stuff[1] + cmap_offset) = pPanoramiXCmap->info[j].id; + stuff->mask = orig_mask; + result = (*SavedProcVector[X_CreateWindow])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXWin->next = NULL; + if (localWin) + Xfree(localWin); + } + return (result); +} + + + +int PanoramiXChangeWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + int j; + Window winID; + Mask orig_valueMask; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWinback = NULL; + PanoramiXCmap *pPanoramiXCmap = NULL; + PanoramiXPmap *pBackgndPmap = NULL; + PanoramiXPmap *pBorderPmap = NULL; + int cmap_offset = 0; + int pback_offset = 0; + int pbord_offset = 0; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + IF_RETURN((len != Ones((Mask) stuff->valueMask)), BadLength); + orig_valueMask = stuff->valueMask; + winID = stuff->window; + for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->window); + pPanoramiXWin = pPanoramiXWin->next) + pPanoramiXWinback = pPanoramiXWin; + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, winID); + IF_RETURN(!pPanoramiXWin, BadWindow); + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWBackPixmap)) { + XID pmapID; + + pback_offset = Ones((Mask)stuff->valueMask & (CWBackPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pback_offset); + if (pmapID) { + pBackgndPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBackgndPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWBorderPixmap)) { + XID pmapID; + + pbord_offset = Ones((Mask)stuff->valueMask & (CWBorderPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pbord_offset); + if (pmapID) { + pBorderPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBorderPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWColormap )) { + Colormap cmapID; + + cmap_offset = Ones((Mask)stuff->valueMask & (CWColormap - 1)); + cmapID = *((CARD32 *) &stuff[1] + cmap_offset); + if (cmapID) { + pPanoramiXCmap = PanoramiXCmapRoot; + PANORAMIXFIND_ID(pPanoramiXCmap, cmapID); + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + stuff->valueMask = orig_valueMask; + if (pBackgndPmap) + *((CARD32 *) &stuff[1] + pback_offset) = pBackgndPmap->info[j].id; + if (pBorderPmap) + *((CARD32 *) &stuff[1] + pbord_offset) = pBorderPmap->info[j].id; + if (pPanoramiXCmap) + *((CARD32 *) &stuff[1] + cmap_offset) = pPanoramiXCmap->info[j].id; + result = (*SavedProcVector[X_ChangeWindowAttributes])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXWinback && + pPanoramiXWin && pPanoramiXWin->FreeMe) { + pPanoramiXWinback->next = pPanoramiXWin->next; + Xfree(pPanoramiXWin); + } + return (result); +} + + +int PanoramiXDestroyWindow(ClientPtr client) +{ + REQUEST(xResourceReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWinback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->id); + pPanoramiXWin = pPanoramiXWin->next) + pPanoramiXWinback = pPanoramiXWin; + IF_RETURN(!pPanoramiXWin,BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->id = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_DestroyWindow])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXWinback && + pPanoramiXWin && pPanoramiXWin->FreeMe) { + pPanoramiXWinback->next = pPanoramiXWin->next; + Xfree(pPanoramiXWin); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXDestroySubwindows(ClientPtr client) +{ + REQUEST(xResourceReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWinback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->id); + pPanoramiXWin = pPanoramiXWin->next) + pPanoramiXWinback = pPanoramiXWin; + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->id = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_DestroySubwindows])(client); + } + if ((result == Success) && pPanoramiXWinback && + pPanoramiXWin && pPanoramiXWin->FreeMe) { + pPanoramiXWinback->next = pPanoramiXWin->next; + Xfree(pPanoramiXWin); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXChangeSaveSet(ClientPtr client) +{ + REQUEST(xChangeSaveSetReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + if (!stuff->window) + result = (* SavedProcVector[X_ChangeSaveSet])(client); + else { + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_ChangeSaveSet])(client); + } + } + return (result); +} + + +int PanoramiXReparentWindow(register ClientPtr client) +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXPar = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + PANORAMIXFIND_ID(pPanoramiXPar, stuff->parent); + IF_RETURN(!pPanoramiXPar, BadWindow); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXPar), j) { + stuff->window = pPanoramiXWin->info[j].id; + stuff->parent = pPanoramiXPar->info[j].id; + result = (*SavedProcVector[X_ReparentWindow])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXMapWindow(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + Window winID; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility */ + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, +SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + winID = pPanoramiXWin->info[j].id; + pWin = (WindowPtr) SecurityLookupWindow(winID, +client,SecurityReadAccess); + IF_RETURN((!pWin), BadWindow); + stuff->id = winID; + result = (*SavedProcVector[X_MapWindow])(client); + } + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + return (result); +} + + +int PanoramiXMapSubwindows(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility values */ + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + stuff->id = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_MapSubwindows])(client); + } + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXUnmapWindow(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility values */ + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + stuff->id = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_UnmapWindow])(client); + } + + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + PANORAMIX_FREE(client); + return (client->noClientException); +} + + +int PanoramiXUnmapSubwindows(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility values */ + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + stuff->id = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_UnmapSubwindows])(client); + } + + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + PANORAMIX_FREE(client); + return (client->noClientException); +} + + +int PanoramiXConfigureWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + unsigned len, i, things; + XID changes[32]; + register Mask orig_mask; + int j, sib_position; + Window winID; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXSib = NULL; + int x_off = 0, y_off = 0; + XID *pStuff; + XID *origStuff, *modStuff; + Mask local_mask; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + things = Ones((Mask)stuff->mask); + IF_RETURN((things != len), BadLength); + orig_mask = stuff->mask; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + if (!pPanoramiXWin) { + client->errorValue = stuff->window; + return (BadWindow); + } + if (things > 0) { + pStuff = (XID *) ALLOCATE_LOCAL(things * sizeof(XID)); + memcpy((char *) pStuff, (char *) &stuff[1], things * sizeof(XID)); + local_mask = (CWSibling | CWX | CWY) & ((Mask) stuff->mask); + if (local_mask & CWSibling) { + sib_position = Ones((Mask) stuff->mask & (CWSibling - 1)); + pPanoramiXSib = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXSib, *(pStuff + sib_position)); + } + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + winID = pPanoramiXWin->info[j].id; + pWin = (WindowPtr)SecurityLookupWindow(winID, client,SecurityReadAccess); + if (!pWin) { + client->errorValue = pPanoramiXWin->info[0].id; + return (BadWindow); + } + stuff->window = winID; + if (pWin->parent + && (pWin->parent->drawable.id == PanoramiXWinRoot->info[j].id)) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + modStuff = (XID *) &stuff[1]; + origStuff = pStuff; + i = things; + if (local_mask & CWX) { + *modStuff++ = *origStuff++ - x_off; + i--; + } + if (local_mask & CWY) { + *modStuff++ = *origStuff++ - y_off; + i--; + } + for ( ; i; i--) + *modStuff++ = *origStuff++; + if (pPanoramiXSib) + *((XID *) &stuff[1] + sib_position) = pPanoramiXSib->info[j].id; + stuff->mask = orig_mask; + result = (*SavedProcVector[X_ConfigureWindow])(client); + } + DEALLOCATE_LOCAL(pStuff); + PANORAMIX_FREE(client); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXCirculateWindow(register ClientPtr client) +{ + REQUEST(xCirculateWindowReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_CirculateWindow])(client); + } + return (result); +} + + +int PanoramiXGetGeometry(register ClientPtr client) +{ + xGetGeometryReply rep; + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + VERIFY_GEOMETRABLE (pDraw, stuff->id, client); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep.depth = pDraw->depth; + + if (stuff->id == PanoramiXWinRoot->info[0].id) { + xConnSetup *setup = (xConnSetup *) ConnectionInfo; + xWindowRoot *root = (xWindowRoot *) + (ConnectionInfo + connBlockScreenStart); + + rep.width = root->pixWidth; + rep.height = root->pixHeight; + } else { + rep.width = pDraw->width; + rep.height = pDraw->height; + } + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) { + register WindowPtr pWin = (WindowPtr)pDraw; + rep.x = pWin->origin.x - wBorderWidth (pWin); + rep.y = pWin->origin.y - wBorderWidth (pWin); + rep.borderWidth = pWin->borderWidth; + } else { /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + rep.x = rep.y = rep.borderWidth = 0; + } + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return (client->noClientException); +} + + +int PanoramiXChangeProperty(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + REQUEST(xChangePropertyReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_ChangeProperty])(client); + if (result != Success) { + stuff->window = pPanoramiXWin->info[0].id; + break; + } + } + return (result); +} + + +int PanoramiXDeleteProperty(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + REQUEST(xDeletePropertyReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_DeleteProperty])(client); + BREAK_IF(result != Success); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXSendEvent(ClientPtr client) +{ + int result, j; + BYTE orig_type; + Mask orig_eventMask; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + REQUEST(xSendEventReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xSendEventReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->destination); + orig_type = stuff->event.u.u.type; + orig_eventMask = stuff->eventMask; + if (!pPanoramiXWin) { + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_SendEvent])(client); + noPanoramiXExtension = FALSE; + } + else { + noPanoramiXExtension = FALSE; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->destination = pPanoramiXWin->info[j].id; + stuff->eventMask = orig_eventMask; + stuff->event.u.u.type = orig_type; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_SendEvent])(client); + noPanoramiXExtension = FALSE; + } + } + return (result); +} + + +int PanoramiXCreatePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + int result, j; + Pixmap pmapID; + PanoramiXWindow *pPanoramiXWin; + PanoramiXPmap *pPanoramiXPmap; + PanoramiXPmap *localPmap; + XID orig_pid; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + + localPmap =(PanoramiXPmap *) Xcalloc(sizeof(PanoramiXPmap)); + IF_RETURN(!localPmap, BadAlloc); + + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!pDraw, BadDrawable); + + pPanoramiXWin = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadWindow); + + orig_pid = stuff->pid; + FOR_NSCREENS_OR_ONCE(pPanoramiXPmap, j) { + pmapID = j ? FakeClientID(client->index) : orig_pid; + localPmap->info[j].id = pmapID; + } + localPmap->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot); + pPanoramiXPmap->next = localPmap; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->pid = localPmap->info[j].id; + stuff->drawable = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_CreatePixmap])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXPmap->next = NULL; + if (localPmap) + Xfree(localPmap); + } + return (result); +} + + +int PanoramiXFreePixmap(ClientPtr client) +{ + PixmapPtr pMap; + int result, j; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + PanoramiXPmap *pPanoramiXPmapback = NULL; + REQUEST(xResourceReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXPmap && (pPanoramiXPmap->info[0].id != stuff->id); + pPanoramiXPmap = pPanoramiXPmap->next) + pPanoramiXPmapback = pPanoramiXPmap; + if (!pPanoramiXPmap) + result = (* SavedProcVector[X_FreePixmap])(client); + else { + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->id = pPanoramiXPmap->info[j].id; + result = (* SavedProcVector[X_FreePixmap])(client); + } + if ((result == Success) && pPanoramiXPmapback && + pPanoramiXPmap && pPanoramiXPmap->FreeMe ) { + pPanoramiXPmapback->next = pPanoramiXPmap->next; + Xfree(pPanoramiXPmap); + } + } + return (result); +} + + +int PanoramiXCreateGC(register ClientPtr client) +{ + int result, j; + GC *pGC; + DrawablePtr pDraw; + unsigned len, i; + REQUEST(xCreateGCReq); + GContext GCID; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *localGC; + PanoramiXGC *pPanoramiXGC; + PanoramiXPmap *pPanoramiXTile = NULL, *pPanoramiXStip = NULL; + PanoramiXPmap *pPanoramiXClip = NULL; + int tile_offset, stip_offset, clip_offset; + XID orig_GC; + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!pDraw, BadDrawable); + pPanoramiXWin = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + IF_RETURN((len != Ones((Mask)stuff->mask)), BadLength); + localGC = (PanoramiXGC *) Xcalloc(sizeof(PanoramiXGC)); + IF_RETURN(!localGC, BadAlloc); + orig_GC = stuff->gc; + if ((Mask)stuff->mask & GCTile) { + XID tileID; + + tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); + tileID = *((CARD32 *) &stuff[1] + tile_offset); + if (tileID) { + pPanoramiXTile = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXTile, tileID); + } + } + if ((Mask)stuff->mask & GCStipple) { + XID stipID; + + stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); + stipID = *((CARD32 *) &stuff[1] + stip_offset); + if (stipID) { + pPanoramiXStip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXStip, stipID); + } + } + if ((Mask)stuff->mask & GCClipMask) { + XID clipID; + + clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); + clipID = *((CARD32 *) &stuff[1] + clip_offset); + if (clipID) { + pPanoramiXClip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXClip, clipID); + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + GCID = j ? FakeClientID(client->index) : orig_GC; + localGC->info[j].id = GCID; + } + localGC->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXGC, PanoramiXGCRoot); + pPanoramiXGC->next = localGC; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->gc = localGC->info[j].id; + stuff->drawable = pPanoramiXWin->info[j].id; + if (pPanoramiXTile) + *((CARD32 *) &stuff[1] + tile_offset) = pPanoramiXTile->info[j].id; + if (pPanoramiXStip) + *((CARD32 *) &stuff[1] + stip_offset) = pPanoramiXStip->info[j].id; + if (pPanoramiXClip) + *((CARD32 *) &stuff[1] + clip_offset) = pPanoramiXClip->info[j].id; + result = (* SavedProcVector[X_CreateGC])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXGC->next = NULL; + Xfree(localGC); + } + return (result); +} + + +int PanoramiXChangeGC(ClientPtr client) +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result, j; + unsigned len; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + PanoramiXPmap *pPanoramiXTile = NULL, *pPanoramiXStip = NULL; + PanoramiXPmap *pPanoramiXClip = NULL; + int tile_offset, stip_offset, clip_offset; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + VERIFY_GC(pGC, stuff->gc, client); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + IF_RETURN((len != Ones((Mask)stuff->mask)), BadLength); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + if ((Mask)stuff->mask & GCTile) { + XID tileID; + + tile_offset = Ones((Mask)stuff->mask & (GCTile -1) ); + tileID = *((CARD32 *) &stuff[1] + tile_offset); + if (tileID) { + pPanoramiXTile = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXTile, tileID); + } + } + if ((Mask)stuff->mask & GCStipple) { + XID stipID; + + stip_offset = Ones((Mask)stuff->mask & (GCStipple -1 )); + stipID = *((CARD32 *) &stuff[1] + stip_offset); + if (stipID) { + pPanoramiXStip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXStip, stipID); + } + } + if ((Mask)stuff->mask & GCClipMask) { + XID clipID; + + clip_offset = Ones((Mask)stuff->mask & (GCClipMask -1)); + clipID = *((CARD32 *) &stuff[1] + clip_offset); + if (clipID) { + pPanoramiXClip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXClip, clipID); + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXTile) + *((CARD32 *) &stuff[1] + tile_offset) = pPanoramiXTile->info[j].id; + if (pPanoramiXStip) + *((CARD32 *) &stuff[1] + stip_offset) = pPanoramiXStip->info[j].id; + if (pPanoramiXClip) + *((CARD32 *) &stuff[1] + clip_offset) = pPanoramiXClip->info[j].id; + result = (* SavedProcVector[X_ChangeGC])(client); + BREAK_IF(result != Success); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXCopyGC(ClientPtr client) +{ + int j, result; + PanoramiXGC *pPanoramiXGCSrc = PanoramiXGCRoot; + PanoramiXGC *pPanoramiXGCDst = PanoramiXGCRoot; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + PANORAMIXFIND_ID(pPanoramiXGCSrc, stuff->srcGC); + IF_RETURN(!pPanoramiXGCSrc, BadGC); + PANORAMIXFIND_ID(pPanoramiXGCDst, stuff->dstGC); + IF_RETURN(!pPanoramiXGCDst, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGCDst, j) { + stuff->srcGC = pPanoramiXGCSrc->info[j].id; + stuff->dstGC = pPanoramiXGCDst->info[j].id; + result = (* SavedProcVector[X_CopyGC])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXSetDashes(ClientPtr client) +{ + GC *pGC; + REQUEST(xSetDashesReq); + int result, j; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + VERIFY_GC(pGC, stuff->gc, client); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_SetDashes])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXSetClipRectangles(register ClientPtr client) +{ + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + int j; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_SetClipRectangles])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXFreeGC(ClientPtr client) +{ + register GC *pGC; + REQUEST(xResourceReq); + int result, j; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + PanoramiXGC *pPanoramiXGCback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXGC && (pPanoramiXGC->info[0].id != stuff->id); + pPanoramiXGC = pPanoramiXGC->next) + pPanoramiXGCback = pPanoramiXGC; + IF_RETURN(!pPanoramiXGC, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->id = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_FreeGC])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXGCback && + pPanoramiXGC && pPanoramiXGC->FreeMe) { + pPanoramiXGCback->next = pPanoramiXGC->next; + if (pPanoramiXGC) + Xfree(pPanoramiXGC); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXClearToBackground(register ClientPtr client) +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + int result, j; + Window winID; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + int orig_x, orig_y; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xClearAreaReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + winID = pPanoramiXWin->info[j].id; + pWin = (WindowPtr) SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!pWin) { + client->errorValue = pPanoramiXWin->info[0].id; + return (BadWindow); + } + stuff->window = winID; + if (pWin->drawable.id == PanoramiXWinRoot->info[j].id) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ClearArea])(client); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXCopyArea(ClientPtr client) +{ + int j, result; + Window srcID, dstID; + DrawablePtr pSrc, pDst; + GContext GCID; + GC *pGC; + PanoramiXWindow *pPanoramiXSrcRoot; + PanoramiXWindow *pPanoramiXDstRoot; + PanoramiXWindow *pPanoramiXSrc; + PanoramiXWindow *pPanoramiXDst; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + REQUEST(xCopyAreaReq); + int srcx = stuff->srcX, srcy = stuff->srcY; + int dstx = stuff->dstX, dsty = stuff->dstY; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) { + VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } else { + pSrc = pDst; + } + pPanoramiXSrcRoot = (pSrc->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXDstRoot = (pDst->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXSrc = pPanoramiXSrcRoot; + pPanoramiXDst = pPanoramiXDstRoot; + PANORAMIXFIND_ID(pPanoramiXSrc, stuff->srcDrawable); + IF_RETURN(!pPanoramiXSrc, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXDst, stuff->dstDrawable); + IF_RETURN(!pPanoramiXDst, BadDrawable); + GCID = stuff->gc; + PANORAMIXFIND_ID(pPanoramiXGC, GCID); + IF_RETURN(!pPanoramiXGC, BadGC); + + FOR_NSCREENS_OR_ONCE(pPanoramiXSrc, j) { + stuff->dstDrawable = pPanoramiXDst->info[j].id; + stuff->srcDrawable = pPanoramiXSrc->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXSrc == pPanoramiXSrcRoot) { + stuff->srcX = srcx - panoramiXdataPtr[j].x; + stuff->srcY = srcy - panoramiXdataPtr[j].y; + } + if (pPanoramiXDst == pPanoramiXDstRoot) { + stuff->dstX = dstx - panoramiXdataPtr[j].x; + stuff->dstY = dsty - panoramiXdataPtr[j].y; + } + result = (* SavedProcVector[X_CopyArea])(client); + BREAK_IF(result != Success); + } + return (result); +} + +int PanoramiXCopyPlane(ClientPtr client) +{ + int SrcScr = -1, DstScr = -1; + PixmapPtr pMap = NULL; + Pixmap pmapID; + PanoramiXRect SrcRect, DstRect; + int i, j, k; + Window srcID, dstID; + DrawablePtr pSrc, pDst; + GContext GCID; + GContext GCIDbase; + GC *pGC; + PanoramiXWindow *pPanoramiXSrc; + PanoramiXWindow *pPanoramiXDst; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + RegionPtr *PanoramiXRgnPtrs; + RegionPtr *FetchRgnPtrs = NULL; + RegionPtr pRgn; + REQUEST(xCopyPlaneReq); + int srcx = stuff->srcX, srcy = stuff->srcY; + int dstx = stuff->dstX, dsty = stuff->dstY; + int width = stuff->width, height = stuff->height; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) { + VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client); + if (pDst->pScreen != pSrc->pScreen) { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } else { + pSrc = pDst; + } + + /* + * Check to see if stuff->bitPlane has exactly ONE good bit set + */ + + + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (pSrc->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pPanoramiXSrc = (pSrc->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXDst = (pDst->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXSrc, stuff->srcDrawable); + IF_RETURN(!pPanoramiXSrc, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXDst, stuff->dstDrawable); + IF_RETURN(!pPanoramiXDst, BadDrawable); + GCIDbase = stuff->gc; + PANORAMIXFIND_ID(pPanoramiXGC, GCIDbase); + IF_RETURN(!pPanoramiXGC, BadGC); + + /* + * Unless both are pixmaps, need to do special things to accomodate + * being on multiple screens, different screens, etc. + */ + + if (pSrc->type != DRAWABLE_PIXMAP) { + SrcRect.x = pSrc->x + srcx; + SrcRect.y = pSrc->y + srcy; + SrcRect.width = width; + SrcRect.height = height; + for (SrcScr = PanoramiXNumScreens - 1; SrcScr>=0; SrcScr-- ) + if (RECTA_SUBSUMES_RECTB(panoramiXdataPtr[SrcScr], SrcRect)) + break; + } + if (pDst->type != DRAWABLE_PIXMAP) { + DstRect.x = pDst->x + dstx; + DstRect.y = pDst->y + dsty; + DstRect.width = width; + DstRect.height = height; + for (DstScr = PanoramiXNumScreens - 1; DstScr>=0; DstScr--) + if (RECTA_SUBSUMES_RECTB(panoramiXdataPtr[DstScr], DstRect)) + break; + } + + /* + * If source is on multiple screens, different screen from destination, + * destination is on multiple screens, or destination is a pixmap, + * need to get info into local pixmap for subsequent transfer. + */ + + + if ((pSrc->type != DRAWABLE_PIXMAP) && + (SrcScr < 0 || DstScr < 0 || SrcScr != DstScr + || pDst->type == DRAWABLE_PIXMAP)) { + unsigned char save_alu; + RegionRec tempReg; + RegionPtr pCompositeClip; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + + pMap = (PixmapPtr) (*pSrc->pScreen->CreatePixmap)(pSrc->pScreen, + width, height, pGC->depth); + PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot); + pPanoramiXPmap->next = + (PanoramiXPmap *)Xcalloc(sizeof(PanoramiXPmap)); + pPanoramiXPmap = pPanoramiXPmap->next; + pmapID = FakeClientID(0); + AddResource(pmapID, RT_PIXMAP, (pointer)pMap); + for (j = PanoramiXNumScreens - 1; j>=0; j--) + pPanoramiXPmap->info[j].id = pmapID; + tempReg.extents.x1 = 0; + tempReg.extents.y1 = 0; + tempReg.extents.x2 = width; + tempReg.extents.y2 = height; + tempReg.data = NULL; + FetchRgnPtrs = + (RegionPtr *) ALLOCATE_LOCAL(PanoramiXNumScreens * sizeof(RegionPtr)); + i = 0; + FOR_NSCREENS_OR_ONCE(pPanoramiXSrc, j) { + if ((SrcScr >= 0) && pPanoramiXSrc) + j = SrcScr; + srcID = pPanoramiXSrc->info[j].id; + pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE, + SecurityReadAccess); + GCID = pPanoramiXGC->info[j].id; + pGC = (GC *) LookupIDByType(GCID, RT_GC); + pMap->drawable.pScreen = pSrc->pScreen; + pGC->pScreen = pSrc->pScreen; + save_alu = pGC->alu; + pGC->alu = GXcopy; + pCompositeClip = ((miPrivGC*) + (pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip; + ((miPrivGC*)(pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip = +&tempReg; + FetchRgnPtrs[i++] = (*pGC->ops->CopyPlane)(pSrc, (DrawablePtr) pMap, + pGC, srcx, srcy, width, height, 0, 0, stuff->bitPlane); + pGC->alu = save_alu; + ((miPrivGC*) (pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip = +pCompositeClip; + if (SrcScr >= 0) + j = 0; + } + } + + if (pMap) { + pSrc = (DrawablePtr) pMap; + srcx = 0; + srcy = 0; + } + PanoramiXRgnPtrs = + (RegionPtr *) ALLOCATE_LOCAL(PanoramiXNumScreens * sizeof(RegionPtr)); + k = 0; + /* if src and dst are entirely on one screen, + then we only need one simple transfer */ + if ((DstScr >= 0) && (pMap || (SrcScr >=0))) { + dstID = pPanoramiXDst->info[DstScr].id; + pDst = (DrawablePtr) SecurityLookupIDByClass(client, dstID, RC_DRAWABLE, + SecurityReadAccess); + GCID = pPanoramiXGC->info[DstScr].id; + pGC = (GC *) LookupIDByType(GCID, RT_GC); + ValidateGC(pDst, pGC); + if (pMap) { + pMap->drawable.pScreen = pDst->pScreen; + } else { + srcID = pPanoramiXSrc->info[SrcScr].id; + if (srcID != dstID) { + pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE, + SecurityReadAccess); + } else + pSrc = pDst; + } + if (pMap) + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + 1); + else + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + stuff->bitPlane); + }else { + FOR_NSCREENS_OR_ONCE(pPanoramiXDst, j) { + if (DstScr >= 0) { + dstID = pPanoramiXDst->info[DstScr].id; + GCID = pPanoramiXGC->info[DstScr].id; + } else { + dstID = pPanoramiXDst->info[j].id; + GCID = pPanoramiXGC->info[j].id; + } + pDst = (DrawablePtr) SecurityLookupIDByClass(client, dstID, RC_DRAWABLE, + SecurityReadAccess); + pGC = (GC *) LookupIDByType(GCID, RT_GC); + ValidateGC(pDst, pGC); + if (pMap) { + pMap->drawable.pScreen = pDst->pScreen; + } else { + srcID = pPanoramiXSrc->info[j].id; + if (srcID != dstID) { + pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE, + SecurityReadAccess); + } else { + pSrc = pDst; + } + } + if (pMap) + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + 1); + else + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + stuff->bitPlane); + } + } + + if (pMap) { + for (j = PanoramiXNumScreens - 1; j>=0; j--) + if (PanoramiXRgnPtrs[j]) + (*pDst->pScreen->RegionDestroy) (PanoramiXRgnPtrs[j]); + DEALLOCATE_LOCAL(PanoramiXRgnPtrs); + PanoramiXRgnPtrs = FetchRgnPtrs; + k = i; + } + j = 1; + i = 0; + pRgn = PanoramiXRgnPtrs[i]; + while ((j < k) && pRgn && !REGION_NIL(pRgn)) { + if (PanoramiXRgnPtrs[j]) { + (*pGC->pScreen->Intersect)(pRgn, pRgn, PanoramiXRgnPtrs[j++]); + } else { + pRgn = PanoramiXRgnPtrs[i++]; + } + } + for (j = 0 ; j < k; j++) { + pRgn = PanoramiXRgnPtrs[j]; + GCID = pPanoramiXGC->info[j].id; + pGC = (GC *) LookupIDByType(GCID, RT_GC); + if (pGC && pGC->graphicsExposures) + (*pDst->pScreen->SendGraphicsExpose) (client, pRgn, + stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + (*pDst->pScreen->RegionDestroy) (pRgn); + } + DEALLOCATE_LOCAL(PanoramiXRgnPtrs); + if (pMap) { + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + PanoramiXPmap *pback = PanoramiXPmapRoot; + + for (; pPanoramiXPmap && (pPanoramiXPmap->info[0].id != pmapID); + pPanoramiXPmap = pPanoramiXPmap->next) + pback = pPanoramiXPmap; + FreeResource(pPanoramiXPmap->info[0].id, RT_NONE); + if (pback) { + pback->next = pPanoramiXPmap->next; + Xfree(pPanoramiXPmap); + } + } + return (client->noClientException); +} + + +int PanoramiXPolyPoint(ClientPtr client) +{ + int result, npoint, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xPoint *origPts; + xPoint *origPtr, *modPtr; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, locDraw->id); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint > 0) { + origPts = (xPoint *) ALLOCATE_LOCAL(npoint * sizeof(xPoint)); + memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xPoint *) &stuff[1]; + origPtr = origPts; + for (i = npoint; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyPoint])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origPts); + return (result); + }else + return (client->noClientException); + +} + + +int PanoramiXPolyLine(ClientPtr client) +{ + int result, npoint, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xPoint *origPts; + xPoint *origPtr, *modPtr; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, locDraw->id); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != locDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 0){ + origPts = (xPoint *) ALLOCATE_LOCAL(npoint * sizeof(xPoint)); + memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xPoint *) &stuff[1]; + origPtr = origPts; + for (i = npoint; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyLine])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origPts); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolySegment(ClientPtr client) +{ + int result, nsegs, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xSegment *origSegs; + xSegment *origPtr, *modPtr; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != locDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + IF_RETURN((nsegs & 4), BadLength); + nsegs >>= 3; + if (nsegs > 0) { + origSegs = (xSegment *) ALLOCATE_LOCAL(nsegs * sizeof(xSegment)); + memcpy((char *) origSegs, (char *) &stuff[1], nsegs * +sizeof(xSegment)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xSegment *) &stuff[1]; + origPtr = origSegs; + for (i = nsegs; i; i--) { + modPtr->x1 = origPtr->x1 - x_off; + modPtr->y1 = origPtr->y1 - y_off; + modPtr->x2 = origPtr->x2 - x_off; + modPtr++->y2 = origPtr++->y2 - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolySegment])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origSegs); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyRectangle(ClientPtr client) +{ + int result, nrects, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xRectangle *origRecs; + xRectangle *origPtr, *modPtr; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + IF_RETURN((nrects & 4), BadLength); + nrects >>= 3; + if (nrects > 0){ + origRecs = (xRectangle *) ALLOCATE_LOCAL(nrects * sizeof(xRectangle)); + memcpy((char *) origRecs, (char *) &stuff[1], nrects * +sizeof(xRectangle)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xRectangle *) &stuff[1]; + origPtr = origRecs; + for (i = nrects; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr->y = origPtr->y - y_off; + modPtr->width = origPtr->width - x_off; + modPtr++->height = origPtr++->height - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyRectangle])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origRecs); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyArc(ClientPtr client) +{ + int result, narcs, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + xArc *origArcs; + xArc *origPtr, *modPtr; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : +PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + IF_RETURN((narcs % sizeof(xArc)), BadLength); + narcs /= sizeof(xArc); + if (narcs > 0){ + origArcs = (xArc *) ALLOCATE_LOCAL(narcs * sizeof(xArc)); + memcpy((char *) origArcs, (char *) &stuff[1], narcs * sizeof(xArc)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xArc *) &stuff[1]; + origPtr = origArcs; + for (i = narcs; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyArc])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origArcs); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXFillPoly(ClientPtr client) +{ + int result, count, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + DDXPointPtr locPts; + DDXPointPtr origPts, modPts; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + count = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (count > 0){ + locPts = (DDXPointPtr) ALLOCATE_LOCAL(count * sizeof(DDXPointRec)); + memcpy((char *) locPts, (char *) &stuff[1], count * +sizeof(DDXPointRec)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPts = (DDXPointPtr) &stuff[1]; + origPts = locPts; + for (i = count; i; i--) { + modPts->x = origPts->x - x_off; + modPts++->y = origPts++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_FillPoly])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(locPts); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyFillRectangle(ClientPtr client) +{ + int result, things, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + xRectangle *origThings; + xRectangle *origPtr, *modPtr; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : +PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + IF_RETURN((things & 4), BadLength); + things >>= 3; + if (things > 0){ + origThings = (xRectangle *) ALLOCATE_LOCAL(things * sizeof(xRectangle)); + memcpy((char *) origThings, (char *)&stuff[1], things * +sizeof(xRectangle)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xRectangle *) &stuff[1]; + origPtr = origThings; + for (i = things; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyFillRectangle])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origThings); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyFillArc(ClientPtr client) +{ + int result, arcs, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + xArc *origArcs; + xArc *origPtr, *modPtr; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : +PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + arcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + IF_RETURN((arcs % sizeof(xArc)), BadLength); + arcs /= sizeof(xArc); + if (arcs > 0) { + origArcs = (xArc *) ALLOCATE_LOCAL(arcs * sizeof(xArc)); + memcpy((char *) origArcs, (char *)&stuff[1], arcs * sizeof(xArc)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xArc *) &stuff[1]; + origPtr = origArcs; + for (i = arcs; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyFillArc])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origArcs); + return (result); + }else + return (client->noClientException); +} + + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ + +int PanoramiXPutImage(register ClientPtr client) +{ + register GC *pGC; + register DrawablePtr pDraw; + long lengthProto, /* length of scanline protocl padded */ + length; /* length of scanline server padded */ + char *tmpImage; + int j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXWindow *pPanoramiXRoot; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + int orig_x, orig_y; + int result; + + + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!pDraw, BadDrawable); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin,BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->dstX; + orig_y = stuff->dstY; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + if (pDraw->type == DRAWABLE_PIXMAP) { + if (stuff->width > panoramiXdataPtr[j].width) + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + if (stuff->height > panoramiXdataPtr[j].height) + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PutImage])(client); + } + return(result); +} + + +typedef struct _SrcParts{ + int x1, y1, x2, y2, width, ByteWidth; + char *buf; +} SrcPartsRec; + + +int PanoramiXGetImage(register ClientPtr client) +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int height, linesDone; + long widthBytesLine, length; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + long widthBytesLineProto, lengthProto; + char *tmpImage; +#endif + Mask plane; + char *pBuf; + xGetImageReply xgi; + int j, k, ScrNum; + DrawablePtr locDraw; + SrcPartsRec srcParts; + BoxRec SrcBox; + char *BufPtr, *PartPtr; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST(xGetImageReq); + + height = stuff->height; + REQUEST_SIZE_MATCH(xGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + ScrNum = 0; + if (stuff->drawable == PanoramiXWinRoot->info[0].id) { + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) { + ScrNum = j; + VERIFY_DRAWABLE(pDraw, pPanoramiXWin->info[ScrNum].id, client); + if (stuff->x < panoramiXdataPtr[ScrNum].x && + stuff->y < panoramiXdataPtr[ScrNum].y ) + break; + } + } + if (pDraw->type == DRAWABLE_WINDOW) { + if (!((WindowPtr) pDraw)->realized /* Check for viewable */ + || pDraw->x + stuff->x < 0 /* Check for on screen */ + || pDraw->x + stuff->x + (int)stuff->width > PanoramiXPixWidth + || pDraw->y + stuff->y < 0 + || pDraw->y + stuff->y + height > PanoramiXPixHeight + || stuff->x < - wBorderWidth((WindowPtr)pDraw) /* Inside border */ + || stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int) pDraw->width + + panoramiXdataPtr[ScrNum].x + || stuff->y < -wBorderWidth((WindowPtr)pDraw) + || stuff->y + height > + wBorderWidth ((WindowPtr)pDraw) + (int) pDraw->height + + panoramiXdataPtr[ScrNum].y) + return(BadMatch); + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + xgi.visual = wVisual (((WindowPtr) pDraw)); + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadWindow); + } else { + if (stuff->x < 0 || stuff->x + (int)stuff->width > pDraw->width + || stuff->y < 0 || stuff->y + height > pDraw->height) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if (stuff->format == ZPixmap) { + widthBytesLine = PixmapBytePad(stuff->width, pDraw->depth); + length = widthBytesLine * height; + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLineProto = PixmapBytePadProto(stuff->width, pDraw->depth); + lengthProto = widthBytesLineProto * height; +#endif + } else { + widthBytesLine = BitmapBytePad(stuff->width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(stuff->planeMask & (plane | (plane - 1))); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLineProto = BitmapBytePadProto(stuff->width); + lengthProto = widthBytesLineProto * height * + Ones(stuff->planeMask & (plane | (plane - 1))); +#endif + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + xgi.length = (lengthProto + 3) >> 2; +#else + xgi.length = (length + 3) >> 2; +#endif + + if (widthBytesLine == 0 || height == 0) { + linesPerBuf = 0; + } else if (widthBytesLine >= IMAGE_BUFSIZE) { + linesPerBuf = 1; + } else { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) { + + /* + * Have to make sure intermediate buffers don't need padding + */ + + while ((linesPerBuf > 1) + && (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1))) { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1)) { + linesPerBuf++; + length += widthBytesLine; + } + } + IF_RETURN((!(pBuf = (char *) ALLOCATE_LOCAL(length))), BadAlloc); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* + * Check for protocol/server padding differences + */ + + if (widthBytesLine != widthBytesLineProto) + if (!(tmpImage = (char *) ALLOCATE_LOCAL(length))) { + DEALLOCATE_LOCAL(pBuf); + return (BadAlloc); + } +#endif + + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + + if (linesPerBuf == 0) { + + /* + * Nothing to do + */ + + } else if (stuff->format == ZPixmap) { + linesDone = 0; + while (height - linesDone > 0) { + nlines = min(linesPerBuf, height - linesDone); + if (pDraw->type == DRAWABLE_WINDOW) { + SrcBox.x1 = pDraw->x + stuff->x; + SrcBox.y1 = pDraw->y + stuff->y + linesDone; + SrcBox.x2 = SrcBox.x1 + stuff->width; + SrcBox.y2 = SrcBox.y1 + nlines; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + + /* + * If it isn't even on this screen, just continue. + */ + + if ((SrcBox.x1 >= panoramiXdataPtr[j].x + panoramiXdataPtr[j].width) + || (SrcBox.x2 <= panoramiXdataPtr[j].x) + || (SrcBox.y1 >= panoramiXdataPtr[j].y+panoramiXdataPtr[j].height) + || (SrcBox.y2 <= panoramiXdataPtr[j].y)) + continue; + + srcParts.x1 = max(SrcBox.x1 - panoramiXdataPtr[j].x, 0); + srcParts.x2 = min(SrcBox.x2 - panoramiXdataPtr[j].x, + panoramiXdataPtr[j].width); + srcParts.y1 = max(SrcBox.y1 - panoramiXdataPtr[j].y, 0); + srcParts.y2 = min(SrcBox.y2 - panoramiXdataPtr[j].y, + panoramiXdataPtr[j].height); + srcParts.width = srcParts.x2 - srcParts.x1; + srcParts.ByteWidth = PixmapBytePad(srcParts.width,pDraw->depth); + srcParts.buf = (char *) Xalloc(nlines * srcParts.ByteWidth); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, + pPanoramiXWin->info[j].id, + RC_DRAWABLE, + SecurityReadAccess); + (*pDraw->pScreen->GetImage)(locDraw, + srcParts.x1 - locDraw->x, + srcParts.y1 - locDraw->y, + srcParts.width, + srcParts.y2 - srcParts.y1, + stuff->format, + (unsigned long)stuff->planeMask, + srcParts.buf); + BufPtr = pBuf + + srcParts.x1 - stuff->x - (pDraw->x - panoramiXdataPtr[j].x) + + widthBytesLine * (srcParts.y1 - stuff->y + - (pDraw->y + linesDone - panoramiXdataPtr[j].y)); + PartPtr = srcParts.buf; + for (k = (srcParts.y2 - srcParts.y1); k; k--) { + bcopy(PartPtr, BufPtr, srcParts.width); + BufPtr += widthBytesLine; + PartPtr += srcParts.ByteWidth; + } + Xfree(srcParts.buf); + } + } else { + (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y + linesDone, + stuff->width, nlines, stuff->format, + (unsigned long)stuff->planeMask, pBuf); + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* + * For 64-bit server, convert image to pad to 32 bits + */ + + if ( widthBytesLine != widthBytesLineProto ) { + register char * bufPtr, * protoPtr; + register int i; + + bzero(tmpImage,length); + + for (i = 0, bufPtr = pBuf, protoPtr = tmpImage; i < nlines; + bufPtr += widthBytesLine, protoPtr += widthBytesLineProto, + i++) + memmove(protoPtr,bufPtr,widthBytesLineProto); + + /* + * Note this is NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLineProto), tmpImage); + } else +#endif + { + + /* + * Note this is NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), pBuf); + } + linesDone += nlines; + } + } else { /* XYPixmap */ + for (; plane; plane >>= 1) { + if (stuff->planeMask & plane) { + linesDone = 0; + while (height - linesDone > 0) { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + stuff->x, + stuff->y + linesDone, + stuff->width, + nlines, + stuff->format, + (unsigned long)plane, + pBuf); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* + * For 64-bit server, convert image to pad to 32 bits + */ + + if (widthBytesLine != widthBytesLineProto) { + register char * bufPtr, * protoPtr; + register int i; + + bzero(tmpImage, length); + + for (i = 0,bufPtr = pBuf,protoPtr =tmpImage; i < nlines; + bufPtr += widthBytesLine, + protoPtr += widthBytesLineProto, + i++) + bcopy(bufPtr, protoPtr, widthBytesLineProto); + + /* + * Note: NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLineProto), tmpImage); + } else +#endif + { + + /* + * Note: NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), pBuf); + } + linesDone += nlines; + } + } + } + } + DEALLOCATE_LOCAL(pBuf); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if (widthBytesLine != widthBytesLineProto) + DEALLOCATE_LOCAL(tmpImage); +#endif + return (client->noClientException); +} + + +int +PanoramiXPolyText8(register ClientPtr client) +{ + int result, j; + + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + PixmapPtr pPixmap; + GC *pGC; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != pDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + stuff->x = orig_x; + stuff->y = orig_y; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + if (!j) + noPanoramiXExtension = TRUE; + result = (*SavedProcVector[X_PolyText8])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + return (result); +} + +int +PanoramiXPolyText16(register ClientPtr client) +{ + int result, j; + + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + GC *pGC; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != pDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + stuff->x = orig_x; + stuff->y = orig_y; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + if (!j) + noPanoramiXExtension = TRUE; + result = (*SavedProcVector[X_PolyText16])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + return (result); +} + + + +int PanoramiXImageText8(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + GCPtr pGC; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + }else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + result = (*SavedProcVector[X_ImageText8])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXImageText16(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + GCPtr pGC; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + }else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + result = (*SavedProcVector[X_ImageText16])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXCreateColormap(register ClientPtr client) +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + DepthPtr pDepth; + + REQUEST(xCreateColormapReq); + + int i, result; + int vid_index, class_index; + int this_vid_index, this_class_index, this_depth; + int j = 0; + VisualID orig_visual; + Colormap cmapID; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXCmap *localCmap; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + short VisualClass; + Bool ClassKnown; + Bool FoundIt = FALSE; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + mid = stuff->mid; + orig_visual = stuff->visual; + j = 0; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + if (pPanoramiXWin) { + localCmap = (PanoramiXCmap *)Xcalloc(sizeof(PanoramiXCmap)); + IF_RETURN(!localCmap, BadAlloc); + } else { + return BadWindow; + } + for (j = 0; j <= PanoramiXNumScreens - 1; j++) { + cmapID = j ? FakeClientID(client->index) : mid; + localCmap->info[j].id = cmapID; + } + localCmap->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXCmap, PanoramiXCmapRoot); + pPanoramiXCmap->next = localCmap; + + /* Use Screen 0 to get the matching Visual ID */ + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if ( stuff->visual != CopyFromParent) + { + /* Find the correct visual for screen 0 */ + for (class_index = 0; class_index < PanoramiXColorDepthTable[0].numVisuals; +class_index++) + { + for (j = 0; j < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index +].numDepths; j++ ) + { + pDepth = (DepthPtr) &pWin->drawable.pScreen->allowedDepths[j]; + for (vid_index = 0; vid_index < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[pDepth->depth].numVids; vid_index++) + { + if ( stuff->visual == PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[pDepth->depth].vid[vid_index] ) + { + this_class_index = class_index; + this_vid_index = vid_index; + this_depth = pDepth->depth; + FoundIt = TRUE; + break; + } + } + } + } + } + if (!pWin) + return(BadWindow); + pScreen = pWin->drawable.pScreen; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->mid = localCmap->info[j].id; + stuff->window = pPanoramiXWin->info[j].id; + /* Look for the matching visual class, and use its + visual id for creating this colormap. */ + if ( orig_visual != CopyFromParent && FoundIt ) + { + stuff->visual = PanoramiXColorDepthTable[j].panoramiXScreenMap[this_class_index].vmap[this_depth].vid[this_vid_index]; + } + result = (* SavedProcVector[X_CreateColormap])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXCmap->next = NULL ; + if (localCmap) + Xfree(localCmap); + } + return (result); +} + + +int PanoramiXFreeColormap(ClientPtr client) +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + PanoramiXCmap *pPanoramiXCmapback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + + for (; pPanoramiXCmap && (pPanoramiXCmap->info[0].id != stuff->id); + pPanoramiXCmap = pPanoramiXCmap->next) + pPanoramiXCmapback = pPanoramiXCmap; + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->id = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_FreeColormap])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXCmapback && + pPanoramiXCmap && pPanoramiXCmap->FreeMe) { + pPanoramiXCmapback->next = pPanoramiXCmap->next; + Xfree(pPanoramiXCmap); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXInstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + + REQUEST_SIZE_MATCH(xResourceReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->id); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->id = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_InstallColormap])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXUninstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->id); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->id = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_UninstallColormap])(client); + BREAK_IF(result != Success); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXAllocColor(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + if (!pPanoramiXCmap){ + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColor])(client); + noPanoramiXExtension = FALSE; + }else { + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColor])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + } + return (result); +} + + +int PanoramiXAllocNamedColor(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocNamedColor])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXAllocColorCells(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + if (!pPanoramiXCmap) { + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColorCells])(client); + noPanoramiXExtension = FALSE; + }else { + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColorCells])(client); + noPanoramiXExtension = FALSE; + /* Because id's are eventually searched for in + some client list, we don't check for success + on fake id's last id will be real, we really + only care about results related to real id's + BREAK_IF(result != Success); + */ + } + } + return (result); +} + + +int PanoramiXFreeColors(register ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xFreeColorsReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_FreeColors])(client); + /* Because id's are eventually searched for in + some client list, we don't check for success + on fake id's last id will be real, we really + only care about results related to real id's */ + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXStoreColors(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + if (!pPanoramiXCmap) + result = (* SavedProcVector[X_StoreColors])(client); + else { + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_StoreColors])(client); + BREAK_IF(result != Success); + } + } + return (result); +} diff --git a/Xext/sampleEVI.c b/Xext/sampleEVI.c new file mode 100644 index 000000000..43265a73d --- /dev/null +++ b/Xext/sampleEVI.c @@ -0,0 +1,97 @@ +/* $Xorg: sampleEVI.c,v 1.3 2000/08/17 19:47:58 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc. +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. +********************************************************/ +#include "X.h" +#include "Xproto.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "dix.h" +#define _XEVI_SERVER_ +#include "XEVIstr.h" +#include "EVIstruct.h" +#include "scrnintstr.h" +static int sampleGetVisualInfo( + VisualID32 *visual, + int n_visual, + xExtendedVisualInfo **evi_rn, + int *n_info_rn, + VisualID32 **conflict_rn, + int *n_conflict_rn) +{ + int max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens; + VisualID32 *temp_conflict; + xExtendedVisualInfo *evi; + int max_visuals = 0, max_sz_conflict, sz_conflict = 0; + register int visualI, scrI, sz_evi = 0, conflictI, n_conflict; + *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi); + if (!*evi_rn) + return BadAlloc; + for (scrI = 0; scrI < screenInfo.numScreens; scrI++) { + if (screenInfo.screens[scrI]->numVisuals > max_visuals) + max_visuals = screenInfo.screens[scrI]->numVisuals; + } + max_sz_conflict = n_visual * sz_VisualID32 * screenInfo.numScreens * max_visuals; + temp_conflict = (VisualID32 *)xalloc(max_sz_conflict); + if (!temp_conflict) { + xfree(*evi_rn); + return BadAlloc; + } + for (scrI = 0; scrI < screenInfo.numScreens; scrI++) { + for (visualI = 0; visualI < n_visual; visualI++) { + evi[sz_evi].core_visual_id = visual[visualI]; + evi[sz_evi].screen = scrI; + evi[sz_evi].level = 0; + evi[sz_evi].transparency_type = XEVI_TRANSPARENCY_NONE; + evi[sz_evi].transparency_value = 0; + evi[sz_evi].min_hw_colormaps = 1; + evi[sz_evi].max_hw_colormaps = 1; + evi[sz_evi].num_colormap_conflicts = n_conflict = 0; + for (conflictI = 0; conflictI < n_conflict; conflictI++) + temp_conflict[sz_conflict++] = visual[visualI]; + sz_evi++; + } + } + *conflict_rn = temp_conflict; + *n_conflict_rn = sz_conflict; + *n_info_rn = sz_evi; + return Success; +} +static void sampleFreeVisualInfo( + xExtendedVisualInfo *evi, + VisualID32 *conflict) +{ + if (evi) + xfree(evi); + if (conflict) + xfree(conflict); +} +EviPrivPtr eviDDXInit() +{ + static EviPrivRec eviPriv; + eviPriv.getVisualInfo = sampleGetVisualInfo; + eviPriv.freeVisualInfo = sampleFreeVisualInfo; + return &eviPriv; +} +void eviDDXReset() +{ +} diff --git a/Xext/security.c b/Xext/security.c new file mode 100644 index 000000000..c2db8f4dd --- /dev/null +++ b/Xext/security.c @@ -0,0 +1,1995 @@ +/* $Xorg: security.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "propertyst.h" +#define _SECURITY_SERVER +#include "securstr.h" +#include +#include +#ifdef LBX +#define _XLBX_SERVER_ +#include "XLbx.h" +extern unsigned char LbxReqCode; +#endif +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#include /* for file reading operations */ +#include "Xatom.h" /* for XA_STRING */ + +#ifndef DEFAULTPOLICYFILE +# define DEFAULTPOLICYFILE NULL +#endif +#ifdef WIN32 +#include +#undef index +#endif + +static int SecurityErrorBase; /* first Security error number */ +static int SecurityEventBase; /* first Security event number */ + +CallbackListPtr SecurityValidateGroupCallback = NULL; /* see security.h */ + +RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */ + +static RESTYPE RTEventClient; + +/* Proc vectors for untrusted clients, swapped and unswapped versions. + * These are the same as the normal proc vectors except that extensions + * that haven't declared themselves secure will have ProcBadRequest plugged + * in for their major opcode dispatcher. This prevents untrusted clients + * from guessing extension major opcodes and using the extension even though + * the extension can't be listed or queried. + */ +int (*UntrustedProcVector[256])( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); +int (*SwappedUntrustedProcVector[256])( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); + +extern int ProcBadRequest(); + + +/* SecurityAudit + * + * Arguments: + * format is the formatting string to be used to interpret the + * remaining arguments. + * + * Returns: nothing. + * + * Side Effects: + * Writes the message to the log file if security logging is on. + */ + +void +SecurityAudit(char *format, ...) +{ + va_list args; + + if (auditTrailLevel < SECURITY_AUDIT_LEVEL) + return; + AuditPrefix(format); + va_start(args, format); + VErrorF(format, args); + va_end(args); +} /* SecurityAudit */ + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +/* SecurityDeleteAuthorization + * + * Arguments: + * value is the authorization to delete. + * id is its resource ID. + * + * Returns: Success. + * + * Side Effects: + * Frees everything associated with the authorization. + */ + +static int +SecurityDeleteAuthorization(value, id) + pointer value; + XID id; +{ + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; + unsigned short name_len, data_len; + char *name, *data; + int status; + int i; + OtherClientsPtr pEventClient; + + /* Remove the auth using the os layer auth manager */ + + status = AuthorizationFromID(pAuth->id, &name_len, &name, + &data_len, &data); + assert(status); + status = RemoveAuthorization(name_len, name, data_len, data); + assert(status); + + /* free the auth timer if there is one */ + + if (pAuth->timer) TimerFree(pAuth->timer); + + /* send revoke events */ + + while (pEventClient = pAuth->eventClients) + { + /* send revocation event event */ + ClientPtr client = rClient(pEventClient); + + if (!client->clientGone) + { + xSecurityAuthorizationRevokedEvent are; + are.type = SecurityEventBase + XSecurityAuthorizationRevoked; + are.sequenceNumber = client->sequence; + are.authId = pAuth->id; + WriteEventsToClient(client, 1, (xEvent *)&are); + } + FreeResource(pEventClient->resource, RT_NONE); + } + + /* kill all clients using this auth */ + + for (i = 1; iauthId == pAuth->id)) + CloseDownClient(clients[i]); + } + + SecurityAudit("revoked authorization ID %d\n", pAuth->id); + xfree(pAuth); + return Success; + +} /* SecurityDeleteAuthorization */ + + +/* resource delete function for RTEventClient */ +static int +SecurityDeleteAuthorizationEventClient(value, id) + pointer value; + XID id; +{ + OtherClientsPtr pEventClient, prev = NULL; + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; + + for (pEventClient = pAuth->eventClients; + pEventClient; + pEventClient = pEventClient->next) + { + if (pEventClient->resource == id) + { + if (prev) + prev->next = pEventClient->next; + else + pAuth->eventClients = pEventClient->next; + xfree(pEventClient); + return(Success); + } + prev = pEventClient; + } + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} /* SecurityDeleteAuthorizationEventClient */ + + +/* SecurityComputeAuthorizationTimeout + * + * Arguments: + * pAuth is the authorization for which we are computing the timeout + * seconds is the number of seconds we want to wait + * + * Returns: + * the number of milliseconds that the auth timer should be set to + * + * Side Effects: + * Sets pAuth->secondsRemaining to any "overflow" amount of time + * that didn't fit in 32 bits worth of milliseconds + */ + +static CARD32 +SecurityComputeAuthorizationTimeout(pAuth, seconds) + SecurityAuthorizationPtr pAuth; + unsigned int seconds; +{ + /* maxSecs is the number of full seconds that can be expressed in + * 32 bits worth of milliseconds + */ + CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND; + + if (seconds > maxSecs) + { /* only come here if we want to wait more than 49 days */ + pAuth->secondsRemaining = seconds - maxSecs; + return maxSecs * MILLI_PER_SECOND; + } + else + { /* by far the common case */ + pAuth->secondsRemaining = 0; + return seconds * MILLI_PER_SECOND; + } +} /* SecurityStartAuthorizationTimer */ + +/* SecurityAuthorizationExpired + * + * This function is passed as an argument to TimerSet and gets called from + * the timer manager in the os layer when its time is up. + * + * Arguments: + * timer is the timer for this authorization. + * time is the current time. + * pval is the authorization whose time is up. + * + * Returns: + * A new time delay in milliseconds if the timer should wait some + * more, else zero. + * + * Side Effects: + * Frees the authorization resource if the timeout period is really + * over, otherwise recomputes pAuth->secondsRemaining. + */ + +static CARD32 +SecurityAuthorizationExpired(timer, time, pval) + OsTimerPtr timer; + CARD32 time; + pointer pval; +{ + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval; + + assert(pAuth->timer == timer); + + if (pAuth->secondsRemaining) + { + return SecurityComputeAuthorizationTimeout(pAuth, + pAuth->secondsRemaining); + } + else + { + FreeResource(pAuth->id, RT_NONE); + return 0; + } +} /* SecurityAuthorizationExpired */ + +/* SecurityStartAuthorizationTimer + * + * Arguments: + * pAuth is the authorization whose timer should be started. + * + * Returns: nothing. + * + * Side Effects: + * A timer is started, set to expire after the timeout period for + * this authorization. When it expires, the function + * SecurityAuthorizationExpired will be called. + */ + +static void +SecurityStartAuthorizationTimer(pAuth) + SecurityAuthorizationPtr pAuth; +{ + pAuth->timer = TimerSet(pAuth->timer, 0, + SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout), + SecurityAuthorizationExpired, pAuth); +} /* SecurityStartAuthorizationTimer */ + + +/* Proc functions all take a client argument, execute the request in + * client->requestBuffer, and return a protocol error status. + */ + +static int +ProcSecurityQueryVersion(client) + ClientPtr client; +{ + REQUEST(xSecurityQueryVersionReq); + xSecurityQueryVersionReply rep; + + /* paranoia: this "can't happen" because this extension is hidden + * from untrusted clients, but just in case... + */ + if (client->trustLevel != XSecurityClientTrusted) + return BadRequest; + + REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.majorVersion = SECURITY_MAJOR_VERSION; + rep.minorVersion = SECURITY_MINOR_VERSION; + if(client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), + (char *)&rep); + return (client->noClientException); +} /* ProcSecurityQueryVersion */ + + +static int +SecurityEventSelectForAuthorization(pAuth, client, mask) + SecurityAuthorizationPtr pAuth; + ClientPtr client; + Mask mask; +{ + OtherClients *pEventClient; + + for (pEventClient = pAuth->eventClients; + pEventClient; + pEventClient = pEventClient->next) + { + if (SameClient(pEventClient, client)) + { + if (mask == 0) + FreeResource(pEventClient->resource, RT_NONE); + else + pEventClient->mask = mask; + return Success; + } + } + + pEventClient = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!pEventClient) + return BadAlloc; + pEventClient->mask = mask; + pEventClient->resource = FakeClientID(client->index); + pEventClient->next = pAuth->eventClients; + if (!AddResource(pEventClient->resource, RTEventClient, + (pointer)pAuth)) + { + xfree(pEventClient); + return BadAlloc; + } + pAuth->eventClients = pEventClient; + + return Success; +} /* SecurityEventSelectForAuthorization */ + + +static int +ProcSecurityGenerateAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityGenerateAuthorizationReq); + int len; /* request length in CARD32s*/ + Bool removeAuth = FALSE; /* if bailout, call RemoveAuthorization? */ + SecurityAuthorizationPtr pAuth = NULL; /* auth we are creating */ + int err; /* error to return from this function */ + int status; /* return value from os functions */ + XID authId; /* authorization ID assigned by os layer */ + xSecurityGenerateAuthorizationReply rep; /* reply struct */ + unsigned int trustLevel; /* trust level of new auth */ + XID group; /* group of new auth */ + CARD32 timeout; /* timeout of new auth */ + CARD32 *values; /* list of supplied attributes */ + char *protoname; /* auth proto name sent in request */ + char *protodata; /* auth proto data sent in request */ + unsigned int authdata_len; /* # bytes of generated auth data */ + char *pAuthdata; /* generated auth data */ + Mask eventMask; /* what events on this auth does client want */ + + /* paranoia: this "can't happen" because this extension is hidden + * from untrusted clients, but just in case... + */ + if (client->trustLevel != XSecurityClientTrusted) + return BadRequest; + + /* check request length */ + + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + len = SIZEOF(xSecurityGenerateAuthorizationReq) >> 2; + len += (stuff->nbytesAuthProto + (unsigned)3) >> 2; + len += (stuff->nbytesAuthData + (unsigned)3) >> 2; + values = ((CARD32 *)stuff) + len; + len += Ones(stuff->valueMask); + if (client->req_len != len) + return BadLength; + + /* check valuemask */ + if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes) + { + client->errorValue = stuff->valueMask; + return BadValue; + } + + /* check timeout */ + timeout = 60; + if (stuff->valueMask & XSecurityTimeout) + { + timeout = *values++; + } + + /* check trustLevel */ + trustLevel = XSecurityClientUntrusted; + if (stuff->valueMask & XSecurityTrustLevel) + { + trustLevel = *values++; + if (trustLevel != XSecurityClientTrusted && + trustLevel != XSecurityClientUntrusted) + { + client->errorValue = trustLevel; + return BadValue; + } + } + + /* check group */ + group = None; + if (stuff->valueMask & XSecurityGroup) + { + group = *values++; + if (SecurityValidateGroupCallback) + { + SecurityValidateGroupInfoRec vgi; + vgi.group = group; + vgi.valid = FALSE; + CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi); + + /* if nobody said they recognized it, it's an error */ + + if (!vgi.valid) + { + client->errorValue = group; + return BadValue; + } + } + } + + /* check event mask */ + eventMask = 0; + if (stuff->valueMask & XSecurityEventMask) + { + eventMask = *values++; + if (eventMask & ~XSecurityAllEventMasks) + { + client->errorValue = eventMask; + return BadValue; + } + } + + protoname = (char *)&stuff[1]; + protodata = protoname + ((stuff->nbytesAuthProto + (unsigned)3) >> 2); + + /* call os layer to generate the authorization */ + + authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname, + stuff->nbytesAuthData, protodata, + &authdata_len, &pAuthdata); + if ((XID) ~0L == authId) + { + err = SecurityErrorBase + XSecurityBadAuthorizationProtocol; + goto bailout; + } + + /* now that we've added the auth, remember to remove it if we have to + * abort the request for some reason (like allocation failure) + */ + removeAuth = TRUE; + + /* associate additional information with this auth ID */ + + pAuth = (SecurityAuthorizationPtr)xalloc(sizeof(SecurityAuthorizationRec)); + if (!pAuth) + { + err = BadAlloc; + goto bailout; + } + + /* fill in the auth fields */ + + pAuth->id = authId; + pAuth->timeout = timeout; + pAuth->group = group; + pAuth->trustLevel = trustLevel; + pAuth->refcnt = 0; /* the auth was just created; nobody's using it yet */ + pAuth->secondsRemaining = 0; + pAuth->timer = NULL; + pAuth->eventClients = NULL; + + /* handle event selection */ + if (eventMask) + { + err = SecurityEventSelectForAuthorization(pAuth, client, eventMask); + if (err != Success) + goto bailout; + } + + if (!AddResource(authId, SecurityAuthorizationResType, pAuth)) + { + err = BadAlloc; + goto bailout; + } + + /* start the timer ticking */ + + if (pAuth->timeout != 0) + SecurityStartAuthorizationTimer(pAuth); + + /* tell client the auth id and data */ + + rep.type = X_Reply; + rep.length = (authdata_len + 3) >> 2; + rep.sequenceNumber = client->sequence; + rep.authId = authId; + rep.dataLength = authdata_len; + + if (client->swapped) + { + register char n; + swapl(&rep.length, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.authId, n); + swaps(&rep.dataLength, n); + } + + WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply), + (char *)&rep); + WriteToClient(client, authdata_len, pAuthdata); + + SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n", + client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout, + pAuth->group, eventMask); + + /* the request succeeded; don't call RemoveAuthorization or free pAuth */ + + removeAuth = FALSE; + pAuth = NULL; + err = client->noClientException; + +bailout: + if (removeAuth) + RemoveAuthorization(stuff->nbytesAuthProto, protoname, + authdata_len, pAuthdata); + if (pAuth) xfree(pAuth); + return err; + +} /* ProcSecurityGenerateAuthorization */ + +static int +ProcSecurityRevokeAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityRevokeAuthorizationReq); + SecurityAuthorizationPtr pAuth; + + /* paranoia: this "can't happen" because this extension is hidden + * from untrusted clients, but just in case... + */ + if (client->trustLevel != XSecurityClientTrusted) + return BadRequest; + + REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); + + pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client, + stuff->authId, SecurityAuthorizationResType, SecurityDestroyAccess); + if (!pAuth) + return SecurityErrorBase + XSecurityBadAuthorization; + + FreeResource(stuff->authId, RT_NONE); + return Success; +} /* ProcSecurityRevokeAuthorization */ + + +static int +ProcSecurityDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SecurityQueryVersion: + return ProcSecurityQueryVersion(client); + case X_SecurityGenerateAuthorization: + return ProcSecurityGenerateAuthorization(client); + case X_SecurityRevokeAuthorization: + return ProcSecurityRevokeAuthorization(client); + default: + return BadRequest; + } +} /* ProcSecurityDispatch */ + +static int +SProcSecurityQueryVersion(client) + ClientPtr client; +{ + REQUEST(xSecurityQueryVersionReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion,n); + return ProcSecurityQueryVersion(client); +} /* SProcSecurityQueryVersion */ + + +static int +SProcSecurityGenerateAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityGenerateAuthorizationReq); + register char n; + CARD32 *values; + unsigned long nvalues; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + swaps(&stuff->nbytesAuthProto, n); + swaps(&stuff->nbytesAuthData, n); + swapl(&stuff->valueMask, n); + values = (CARD32 *)(&stuff[1]) + + ((stuff->nbytesAuthProto + (unsigned)3) >> 2) + + ((stuff->nbytesAuthData + (unsigned)3) >> 2); + nvalues = (((CARD32 *)stuff) + stuff->length) - values; + SwapLongs(values, nvalues); + return ProcSecurityGenerateAuthorization(client); +} /* SProcSecurityGenerateAuthorization */ + + +static int +SProcSecurityRevokeAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityRevokeAuthorizationReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); + swapl(&stuff->authId, n); + return ProcSecurityRevokeAuthorization(client); +} /* SProcSecurityRevokeAuthorization */ + + +static int +SProcSecurityDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SecurityQueryVersion: + return SProcSecurityQueryVersion(client); + case X_SecurityGenerateAuthorization: + return SProcSecurityGenerateAuthorization(client); + case X_SecurityRevokeAuthorization: + return SProcSecurityRevokeAuthorization(client); + default: + return BadRequest; + } +} /* SProcSecurityDispatch */ + +static void +SwapSecurityAuthorizationRevokedEvent(from, to) + xSecurityAuthorizationRevokedEvent *from, *to; +{ + to->type = from->type; + to->detail = from->detail; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->authId, to->authId); +} + +/* SecurityDetermineEventPropogationLimits + * + * This is a helper function for SecurityCheckDeviceAccess. + * + * Arguments: + * dev is the device for which the starting and stopping windows for + * event propogation should be determined. + * The values pointed to by ppWin and ppStopWin are not used. + * + * Returns: + * ppWin is filled in with a pointer to the window at which event + * propogation for the given device should start given the current + * state of the server (pointer position, window layout, etc.) + * ppStopWin is filled in with the window at which event propogation + * should stop; events should not go to ppStopWin. + * + * Side Effects: none. + */ + +static void +SecurityDetermineEventPropogationLimits(dev, ppWin, ppStopWin) + DeviceIntPtr dev; + WindowPtr *ppWin; + WindowPtr *ppStopWin; +{ + WindowPtr pFocusWin = dev->focus ? dev->focus->win : NoneWin; + + if (pFocusWin == NoneWin) + { /* no focus -- events don't go anywhere */ + *ppWin = *ppStopWin = NULL; + return; + } + + if (pFocusWin == PointerRootWin) + { /* focus follows the pointer */ + *ppWin = GetSpriteWindow(); + *ppStopWin = NULL; /* propogate all the way to the root */ + } + else + { /* a real window is set for the focus */ + WindowPtr pSpriteWin = GetSpriteWindow(); + *ppStopWin = pFocusWin->parent; /* don't go past the focus window */ + + /* if the pointer is in a subwindow of the focus window, start + * at that subwindow, else start at the focus window itself + */ + if (IsParent(pFocusWin, pSpriteWin)) + *ppWin = pSpriteWin; + else *ppWin = pFocusWin; + } +} /* SecurityDetermineEventPropogationLimits */ + + +/* SecurityCheckDeviceAccess + * + * Arguments: + * client is the client attempting to access a device. + * dev is the device being accessed. + * fromRequest is TRUE if the device access is a direct result of + * the client executing some request and FALSE if it is a + * result of the server trying to send an event (e.g. KeymapNotify) + * to the client. + * Returns: + * TRUE if the device access should be allowed, else FALSE. + * + * Side Effects: + * An audit message is generated if access is denied. + */ + +Bool +SecurityCheckDeviceAccess(client, dev, fromRequest) + ClientPtr client; + DeviceIntPtr dev; + Bool fromRequest; +{ + WindowPtr pWin, pStopWin; + Bool untrusted_got_event; + Bool found_event_window; + Mask eventmask; + int reqtype; + + /* trusted clients always allowed to do anything */ + if (client->trustLevel == XSecurityClientTrusted) + return TRUE; + + /* device security other than keyboard is not implemented yet */ + if (dev != inputInfo.keyboard) + return TRUE; + + /* some untrusted client wants access */ + + if (fromRequest) + { + reqtype = ((xReq *)client->requestBuffer)->reqType; + switch (reqtype) + { + /* never allow these */ + case X_ChangeKeyboardMapping: + case X_ChangeKeyboardControl: + case X_SetModifierMapping: + SecurityAudit("client %d attempted request %d\n", + client->index, reqtype); + return FALSE; + default: + break; + } + } + + untrusted_got_event = FALSE; + found_event_window = FALSE; + + if (dev->grab) + { + untrusted_got_event = + ((rClient(dev->grab))->trustLevel != XSecurityClientTrusted); + } + else + { + SecurityDetermineEventPropogationLimits(dev, &pWin, &pStopWin); + + eventmask = KeyPressMask | KeyReleaseMask; + while ( (pWin != pStopWin) && !found_event_window) + { + OtherClients *other; + + if (pWin->eventMask & eventmask) + { + found_event_window = TRUE; + client = wClient(pWin); + if (client->trustLevel != XSecurityClientTrusted) + { + untrusted_got_event = TRUE; + } + } + if (wOtherEventMasks(pWin) & eventmask) + { + found_event_window = TRUE; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & eventmask) + { + client = rClient(other); + if (client->trustLevel != XSecurityClientTrusted) + { + untrusted_got_event = TRUE; + break; + } + } + } + } + if (wDontPropagateMask(pWin) & eventmask) + break; + pWin = pWin->parent; + } /* while propogating the event */ + } + + /* allow access by untrusted clients only if an event would have gone + * to an untrusted client + */ + + if (!untrusted_got_event) + { + char *devname = dev->name; + if (!devname) devname = "unnamed"; + if (fromRequest) + SecurityAudit("client %d attempted request %d device %d (%s)\n", + client->index, reqtype, dev->id, devname); + else + SecurityAudit("client %d attempted to access device %d (%s)\n", + client->index, dev->id, devname); + } + return untrusted_got_event; +} /* SecurityCheckDeviceAccess */ + + + +/* SecurityAuditResourceIDAccess + * + * Arguments: + * client is the client doing the resource access. + * id is the resource id. + * + * Returns: NULL + * + * Side Effects: + * An audit message is generated with details of the denied + * resource access. + */ + +static pointer +SecurityAuditResourceIDAccess(client, id) + ClientPtr client; + XID id; +{ + int cid = CLIENT_ID(id); + int reqtype = ((xReq *)client->requestBuffer)->reqType; + switch (reqtype) + { + case X_ChangeProperty: + case X_DeleteProperty: + case X_GetProperty: + { + xChangePropertyReq *req = + (xChangePropertyReq *)client->requestBuffer; + int propertyatom = req->property; + char *propertyname = NameForAtom(propertyatom); + + SecurityAudit("client %d attempted request %d with window 0x%x property %s of client %d\n", + client->index, reqtype, id, propertyname, cid); + break; + } + default: + { + SecurityAudit("client %d attempted request %d with resource 0x%x of client %d\n", + client->index, reqtype, id, cid); + break; + } + } + return NULL; +} /* SecurityAuditResourceIDAccess */ + + +/* SecurityCheckResourceIDAccess + * + * This function gets plugged into client->CheckAccess and is called from + * SecurityLookupIDByType/Class to determine if the client can access the + * resource. + * + * Arguments: + * client is the client doing the resource access. + * id is the resource id. + * rtype is its type or class. + * access_mode represents the intended use of the resource; see + * resource.h. + * rval is a pointer to the resource structure for this resource. + * + * Returns: + * If access is granted, the value of rval that was passed in, else NULL. + * + * Side Effects: + * Disallowed resource accesses are audited. + */ + +static pointer +SecurityCheckResourceIDAccess(client, id, rtype, access_mode, rval) + ClientPtr client; + XID id; + RESTYPE rtype; + Mask access_mode; + pointer rval; +{ + int cid = CLIENT_ID(id); + int reqtype = ((xReq *)client->requestBuffer)->reqType; + + if (SecurityUnknownAccess == access_mode) + return rval; /* for compatibility, we have to allow access */ + + switch (reqtype) + { /* these are always allowed */ + case X_QueryTree: + case X_TranslateCoords: + case X_GetGeometry: + /* property access is controlled in SecurityCheckPropertyAccess */ + case X_GetProperty: + case X_ChangeProperty: + case X_DeleteProperty: + case X_RotateProperties: + case X_ListProperties: + return rval; + default: + break; + } + + if (cid != 0) + { /* not a server-owned resource */ + /* + * The following 'if' restricts clients to only access resources at + * the same trustLevel. Since there are currently only two trust levels, + * and trusted clients never call this function, this degenerates into + * saying that untrusted clients can only access resources of other + * untrusted clients. One way to add the notion of groups would be to + * allow values other than Trusted (0) and Untrusted (1) for this field. + * Clients at the same trust level would be able to use each other's + * resources, but not those of clients at other trust levels. I haven't + * tried it, but this probably mostly works already. The obvious + * competing alternative for grouping clients for security purposes is to + * use app groups. dpw + */ + if (client->trustLevel == clients[cid]->trustLevel +#ifdef XAPPGROUP + || (RT_COLORMAP == rtype && + XagDefaultColormap (client) == (Colormap) id) +#endif + ) + return rval; + else + return SecurityAuditResourceIDAccess(client, id); + } + else /* server-owned resource - probably a default colormap or root window */ + { + if (RT_WINDOW == rtype || RC_DRAWABLE == rtype) + { + switch (reqtype) + { /* the following operations are allowed on root windows */ + case X_CreatePixmap: + case X_CreateGC: + case X_CreateWindow: + case X_CreateColormap: + case X_ListProperties: + case X_GrabPointer: + case X_UngrabButton: + case X_QueryBestSize: + case X_GetWindowAttributes: + break; + case X_SendEvent: + { /* see if it is an event specified by the ICCCM */ + xSendEventReq *req = (xSendEventReq *) + (client->requestBuffer); + if (req->propagate == xTrue + || + (req->eventMask != ColormapChangeMask && + req->eventMask != StructureNotifyMask && + req->eventMask != + (SubstructureRedirectMask|SubstructureNotifyMask) + ) + || + (req->event.u.u.type != UnmapNotify && + req->event.u.u.type != ConfigureRequest && + req->event.u.u.type != ClientMessage + ) + ) + { /* not an ICCCM event */ + return SecurityAuditResourceIDAccess(client, id); + } + break; + } /* case X_SendEvent on root */ + + case X_ChangeWindowAttributes: + { /* Allow selection of PropertyNotify and StructureNotify + * events on the root. + */ + xChangeWindowAttributesReq *req = + (xChangeWindowAttributesReq *)(client->requestBuffer); + if (req->valueMask == CWEventMask) + { + CARD32 value = *((CARD32 *)(req + 1)); + if ( (value & + ~(PropertyChangeMask|StructureNotifyMask)) == 0) + break; + } + return SecurityAuditResourceIDAccess(client, id); + } /* case X_ChangeWindowAttributes on root */ + + default: + { +#ifdef LBX + /* XXX really need per extension dispatching */ + if (reqtype == LbxReqCode) { + switch (((xReq *)client->requestBuffer)->data) { + case X_LbxGetProperty: + case X_LbxChangeProperty: + return rval; + default: + break; + } + } +#endif + /* others not allowed */ + return SecurityAuditResourceIDAccess(client, id); + } + } + } /* end server-owned window or drawable */ + else if (SecurityAuthorizationResType == rtype) + { + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval; + if (pAuth->trustLevel != client->trustLevel) + return SecurityAuditResourceIDAccess(client, id); + } + else if (RT_COLORMAP != rtype) + { /* don't allow anything else besides colormaps */ + return SecurityAuditResourceIDAccess(client, id); + } + } + return rval; +} /* SecurityCheckResourceIDAccess */ + + +/* SecurityClientStateCallback + * + * Arguments: + * pcbl is &ClientStateCallback. + * nullata is NULL. + * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) + * which contains information about client state changes. + * + * Returns: nothing. + * + * Side Effects: + * + * If a new client is connecting, its authorization ID is copied to + * client->authID. If this is a generated authorization, its reference + * count is bumped, its timer is cancelled if it was running, and its + * trustlevel is copied to client->trustLevel. + * + * If a client is disconnecting and the client was using a generated + * authorization, the authorization's reference count is decremented, and + * if it is now zero, the timer for this authorization is started. + */ + +static void +SecurityClientStateCallback(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + NewClientInfoRec *pci = (NewClientInfoRec *)calldata; + ClientPtr client = pci->client; + + switch (client->clientState) + { + case ClientStateRunning: + { + XID authId = AuthorizationIDOfClient(client); + SecurityAuthorizationPtr pAuth; + + client->authId = authId; + pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, + SecurityAuthorizationResType); + if (pAuth) + { /* it is a generated authorization */ + pAuth->refcnt++; + if (pAuth->refcnt == 1) + { + if (pAuth->timer) TimerCancel(pAuth->timer); + } + client->trustLevel = pAuth->trustLevel; + if (client->trustLevel != XSecurityClientTrusted) + { + client->CheckAccess = SecurityCheckResourceIDAccess; + client->requestVector = client->swapped ? + SwappedUntrustedProcVector : UntrustedProcVector; + } + } + break; + } + case ClientStateGone: + case ClientStateRetained: /* client disconnected */ + { + XID authId = client->authId; + SecurityAuthorizationPtr pAuth; + + pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, + SecurityAuthorizationResType); + if (pAuth) + { /* it is a generated authorization */ + pAuth->refcnt--; + if (pAuth->refcnt == 0) + { + SecurityStartAuthorizationTimer(pAuth); + } + } + break; + } + default: break; + } +} /* SecurityClientStateCallback */ + +#ifdef LBX +Bool +SecuritySameLevel(client, authId) + ClientPtr client; + XID authId; +{ + SecurityAuthorizationPtr pAuth; + + pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, + SecurityAuthorizationResType); + if (pAuth) + return client->trustLevel == pAuth->trustLevel; + return client->trustLevel == XSecurityClientTrusted; +} +#endif + +/* SecurityCensorImage + * + * Called after pScreen->GetImage to prevent pieces or trusted windows from + * being returned in image data from an untrusted window. + * + * Arguments: + * client is the client doing the GetImage. + * pVisibleRegion is the visible region of the window. + * widthBytesLine is the width in bytes of one horizontal line in pBuf. + * pDraw is the source window. + * x, y, w, h is the rectangle of image data from pDraw in pBuf. + * format is the format of the image data in pBuf: ZPixmap or XYPixmap. + * pBuf is the image data. + * + * Returns: nothing. + * + * Side Effects: + * Any part of the rectangle (x, y, w, h) that is outside the visible + * region of the window will be destroyed (overwritten) in pBuf. + */ +void +SecurityCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h, + format, pBuf) + ClientPtr client; + RegionPtr pVisibleRegion; + long widthBytesLine; + DrawablePtr pDraw; + int x, y, w, h; + unsigned int format; + char * pBuf; +{ + RegionRec imageRegion; /* region representing x,y,w,h */ + RegionRec censorRegion; /* region to obliterate */ + BoxRec imageBox; + int nRects; + + imageBox.x1 = x; + imageBox.y1 = y; + imageBox.x2 = x + w; + imageBox.y2 = y + h; + REGION_INIT(pScreen, &imageRegion, &imageBox, 1); + REGION_INIT(pScreen, &censorRegion, NullBox, 0); + + /* censorRegion = imageRegion - visibleRegion */ + REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion); + nRects = REGION_NUM_RECTS(&censorRegion); + if (nRects > 0) + { /* we have something to censor */ + GCPtr pScratchGC = NULL; + PixmapPtr pPix = NULL; + xRectangle *pRects = NULL; + Bool failed = FALSE; + int depth = 1; + int bitsPerPixel = 1; + int i; + BoxPtr pBox; + + /* convert region to list-of-rectangles for PolyFillRect */ + + pRects = (xRectangle *)ALLOCATE_LOCAL(nRects * sizeof(xRectangle *)); + if (!pRects) + { + failed = TRUE; + goto failSafe; + } + for (pBox = REGION_RECTS(&censorRegion), i = 0; + i < nRects; + i++, pBox++) + { + pRects[i].x = pBox->x1; + pRects[i].y = pBox->y1 - imageBox.y1; + pRects[i].width = pBox->x2 - pBox->x1; + pRects[i].height = pBox->y2 - pBox->y1; + } + + /* use pBuf as a fake pixmap */ + + if (format == ZPixmap) + { + depth = pDraw->depth; + bitsPerPixel = pDraw->bitsPerPixel; + } + + pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, + depth, bitsPerPixel, + widthBytesLine, (pointer)pBuf); + if (!pPix) + { + failed = TRUE; + goto failSafe; + } + + pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); + if (!pScratchGC) + { + failed = TRUE; + goto failSafe; + } + + ValidateGC(&pPix->drawable, pScratchGC); + (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, + pScratchGC, nRects, pRects); + + failSafe: + if (failed) + { + /* Censoring was not completed above. To be safe, wipe out + * all the image data so that nothing trusted gets out. + */ + bzero(pBuf, (int)(widthBytesLine * h)); + } + if (pRects) DEALLOCATE_LOCAL(pRects); + if (pScratchGC) FreeScratchGC(pScratchGC); + if (pPix) FreeScratchPixmapHeader(pPix); + } + REGION_UNINIT(pScreen, &imageRegion); + REGION_UNINIT(pScreen, &censorRegion); +} /* SecurityCensorImage */ + +/**********************************************************************/ + +typedef struct _PropertyAccessRec { + ATOM name; + ATOM mustHaveProperty; + char *mustHaveValue; + char windowRestriction; +#define SecurityAnyWindow 0 +#define SecurityRootWindow 1 +#define SecurityWindowWithProperty 2 + char readAction; + char writeAction; + char destroyAction; + struct _PropertyAccessRec *next; +} PropertyAccessRec, *PropertyAccessPtr; + +static PropertyAccessPtr PropertyAccessList = NULL; +static char SecurityDefaultAction = SecurityErrorOperation; +static char *SecurityPolicyFile = DEFAULTPOLICYFILE; +static ATOM SecurityMaxPropertyName = 0; + +static char *SecurityKeywords[] = { +#define SecurityKeywordComment 0 + "#", +#define SecurityKeywordProperty 1 + "property", +#define SecurityKeywordSitePolicy 2 + "sitepolicy", +#define SecurityKeywordRoot 3 + "root", +#define SecurityKeywordAny 4 + "any" +}; + +#define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *)) + +#undef PROPDEBUG +/*#define PROPDEBUG 1*/ + +static void +SecurityFreePropertyAccessList() +{ + while (PropertyAccessList) + { + PropertyAccessPtr freeit = PropertyAccessList; + PropertyAccessList = PropertyAccessList->next; + xfree(freeit); + } +} /* SecurityFreePropertyAccessList */ + + +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') ) + +static char * +SecuritySkipWhitespace(p) + char *p; +{ + while (SecurityIsWhitespace(*p)) + p++; + return p; +} /* SecuritySkipWhitespace */ + + +static char * +SecurityParseString(rest) + char **rest; +{ + char *startOfString; + char *s = *rest; + char endChar = 0; + + s = SecuritySkipWhitespace(s); + + if (*s == '"' || *s == '\'') + { + endChar = *s++; + startOfString = s; + while (*s && (*s != endChar)) + s++; + } + else + { + startOfString = s; + while (*s && !SecurityIsWhitespace(*s)) + s++; + } + if (*s) + { + *s = '\0'; + *rest = s + 1; + return startOfString; + } + else + { + *rest = s; + return (endChar) ? NULL : startOfString; + } +} /* SecurityParseString */ + + +static int +SecurityParseKeyword(p) + char **p; +{ + int i; + char *s = *p; + s = SecuritySkipWhitespace(s); + for (i = 0; i < NUMKEYWORDS; i++) + { + int len = strlen(SecurityKeywords[i]); + if (strncmp(s, SecurityKeywords[i], len) == 0) + { + *p = s + len; + return (i); + } + } + *p = s; + return -1; +} /* SecurityParseKeyword */ + + +static Bool +SecurityParsePropertyAccessRule(p) + char *p; +{ + char *propname; + char c; + char action = SecurityDefaultAction; + char readAction, writeAction, destroyAction; + PropertyAccessPtr pacl, prev, cur; + ATOM atom; + char *mustHaveProperty = NULL; + char *mustHaveValue = NULL; + Bool invalid; + char windowRestriction; + int size; + int keyword; + + /* get property name */ + propname = SecurityParseString(&p); + if (!propname || (strlen(propname) == 0)) + return FALSE; + + /* get window on which property must reside for rule to apply */ + + keyword = SecurityParseKeyword(&p); + if (keyword == SecurityKeywordRoot) + windowRestriction = SecurityRootWindow; + else if (keyword == SecurityKeywordAny) + windowRestriction = SecurityAnyWindow; + else /* not root or any, must be a property name */ + { + mustHaveProperty = SecurityParseString(&p); + if (!mustHaveProperty || (strlen(mustHaveProperty) == 0)) + return FALSE; + windowRestriction = SecurityWindowWithProperty; + p = SecuritySkipWhitespace(p); + if (*p == '=') + { /* property value is specified too */ + p++; /* skip over '=' */ + mustHaveValue = SecurityParseString(&p); + if (!mustHaveValue) + return FALSE; + } + } + + /* get operations and actions */ + + invalid = FALSE; + readAction = writeAction = destroyAction = SecurityDefaultAction; + while ( (c = *p++) && !invalid) + { + switch (c) + { + case 'i': action = SecurityIgnoreOperation; break; + case 'a': action = SecurityAllowOperation; break; + case 'e': action = SecurityErrorOperation; break; + + case 'r': readAction = action; break; + case 'w': writeAction = action; break; + case 'd': destroyAction = action; break; + + default : + if (!SecurityIsWhitespace(c)) + invalid = TRUE; + break; + } + } + if (invalid) + return FALSE; + + /* We've successfully collected all the information needed for this + * property access rule. Now record it in a PropertyAccessRec. + */ + size = sizeof(PropertyAccessRec); + + /* If there is a property value string, allocate space for it + * right after the PropertyAccessRec. + */ + if (mustHaveValue) + size += strlen(mustHaveValue) + 1; + pacl = (PropertyAccessPtr)Xalloc(size); + if (!pacl) + return FALSE; + + pacl->name = MakeAtom(propname, strlen(propname), TRUE); + if (pacl->name == BAD_RESOURCE) + { + Xfree(pacl); + return FALSE; + } + if (mustHaveProperty) + { + pacl->mustHaveProperty = MakeAtom(mustHaveProperty, + strlen(mustHaveProperty), TRUE); + if (pacl->mustHaveProperty == BAD_RESOURCE) + { + Xfree(pacl); + return FALSE; + } + } + else + pacl->mustHaveProperty = 0; + + if (mustHaveValue) + { + pacl->mustHaveValue = (char *)(pacl + 1); + strcpy(pacl->mustHaveValue, mustHaveValue); + } + else + pacl->mustHaveValue = NULL; + + SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name); + + pacl->windowRestriction = windowRestriction; + pacl->readAction = readAction; + pacl->writeAction = writeAction; + pacl->destroyAction = destroyAction; + + /* link the new rule into the list of rules in order of increasing + * property name (atom) value to make searching easier + */ + + for (prev = NULL, cur = PropertyAccessList; + cur && cur->name <= pacl->name; + prev = cur, cur = cur->next) + ; + if (!prev) + { + pacl->next = cur; + PropertyAccessList = pacl; + } + else + { + prev->next = pacl; + pacl->next = cur; + } + return TRUE; +} /* SecurityParsePropertyAccessRule */ + +static char **SecurityPolicyStrings = NULL; +static int nSecurityPolicyStrings = 0; + +static Bool +SecurityParseSitePolicy(p) + char *p; +{ + char *policyStr = SecurityParseString(&p); + char *copyPolicyStr; + char **newStrings; + + if (!policyStr) + return FALSE; + + copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1); + if (!copyPolicyStr) + return TRUE; + strcpy(copyPolicyStr, policyStr); + newStrings = (char **)Xrealloc(SecurityPolicyStrings, + sizeof (char *) * (nSecurityPolicyStrings + 1)); + if (!newStrings) + { + Xfree(copyPolicyStr); + return TRUE; + } + + SecurityPolicyStrings = newStrings; + SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr; + + return TRUE; + +} /* SecurityParseSitePolicy */ + + +char ** +SecurityGetSitePolicyStrings(n) + int *n; +{ + *n = nSecurityPolicyStrings; + return SecurityPolicyStrings; +} /* SecurityGetSitePolicyStrings */ + +static void +SecurityFreeSitePolicyStrings() +{ + if (SecurityPolicyStrings) + { + assert(nSecurityPolicyStrings); + while (nSecurityPolicyStrings--) + { + Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]); + } + Xfree(SecurityPolicyStrings); + SecurityPolicyStrings = NULL; + nSecurityPolicyStrings = 0; + } +} /* SecurityFreeSitePolicyStrings */ + + +static void +SecurityLoadPropertyAccessList() +{ + FILE *f; + int lineNumber = 0; + + SecurityMaxPropertyName = 0; + + if (!SecurityPolicyFile) + return; + + f = fopen(SecurityPolicyFile, "r"); + if (!f) + { + ErrorF("error opening security policy file %s\n", + SecurityPolicyFile); + return; + } + + while (!feof(f)) + { + char buf[200]; + Bool validLine; + char *p; + + if (!(p = fgets(buf, sizeof(buf), f))) + break; + lineNumber++; + + /* if first line, check version number */ + if (lineNumber == 1) + { + char *v = SecurityParseString(&p); + if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0) + { + ErrorF("%s: invalid security policy file version, ignoring file\n", + SecurityPolicyFile); + break; + } + validLine = TRUE; + } + else + { + switch (SecurityParseKeyword(&p)) + { + case SecurityKeywordComment: + validLine = TRUE; + break; + + case SecurityKeywordProperty: + validLine = SecurityParsePropertyAccessRule(p); + break; + + case SecurityKeywordSitePolicy: + validLine = SecurityParseSitePolicy(p); + break; + + default: + validLine = (*p == '\0'); /* blank lines OK, others not */ + break; + } + } + + if (!validLine) + ErrorF("Line %d of %s invalid, ignoring\n", + lineNumber, SecurityPolicyFile); + } /* end while more input */ + +#ifdef PROPDEBUG + { + PropertyAccessPtr pacl; + char *op = "aie"; + for (pacl = PropertyAccessList; pacl; pacl = pacl->next) + { + ErrorF("property %s ", NameForAtom(pacl->name)); + switch (pacl->windowRestriction) + { + case SecurityAnyWindow: ErrorF("any "); break; + case SecurityRootWindow: ErrorF("root "); break; + case SecurityWindowWithProperty: + { + ErrorF("%s ", NameForAtom(pacl->mustHaveProperty)); + if (pacl->mustHaveValue) + ErrorF(" = \"%s\" ", pacl->mustHaveValue); + + } + break; + } + ErrorF("%cr %cw %cd\n", op[pacl->readAction], + op[pacl->writeAction], op[pacl->destroyAction]); + } + } +#endif /* PROPDEBUG */ + + fclose(f); +} /* SecurityLoadPropertyAccessList */ + + +static Bool +SecurityMatchString(ws, cs) + char *ws; + char *cs; +{ + while (*ws && *cs) + { + if (*ws == '*') + { + Bool match = FALSE; + ws++; + while (!(match = SecurityMatchString(ws, cs)) && *cs) + { + cs++; + } + return match; + } + else if (*ws == *cs) + { + ws++; + cs++; + } + else break; + } + return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') ) + && (*cs == '\0') ); +} /* SecurityMatchString */ + +#ifdef PROPDEBUG +#include +#include +#endif + + +char +SecurityCheckPropertyAccess(client, pWin, propertyName, access_mode) + ClientPtr client; + WindowPtr pWin; + ATOM propertyName; + Mask access_mode; +{ + PropertyAccessPtr pacl; + char action = SecurityDefaultAction; + + /* if client trusted or window untrusted, allow operation */ + + if ( (client->trustLevel == XSecurityClientTrusted) || + (wClient(pWin)->trustLevel != XSecurityClientTrusted) ) + return SecurityAllowOperation; + +#ifdef PROPDEBUG + /* For testing, it's more convenient if the property rules file gets + * reloaded whenever it changes, so we can rapidly try things without + * having to reset the server. + */ + { + struct stat buf; + static time_t lastmod = 0; + int ret = stat(SecurityPolicyFile , &buf); + if ( (ret == 0) && (buf.st_mtime > lastmod) ) + { + ErrorF("reloading property rules\n"); + SecurityFreePropertyAccessList(); + SecurityLoadPropertyAccessList(); + lastmod = buf.st_mtime; + } + } +#endif + + /* If the property atom is bigger than any atoms on the list, + * we know we won't find it, so don't even bother looking. + */ + if (propertyName <= SecurityMaxPropertyName) + { + /* untrusted client operating on trusted window; see if it's allowed */ + + for (pacl = PropertyAccessList; pacl; pacl = pacl->next) + { + if (pacl->name < propertyName) + continue; + if (pacl->name > propertyName) + break; + + /* pacl->name == propertyName, so see if it applies to this window */ + + switch (pacl->windowRestriction) + { + case SecurityAnyWindow: /* always applies */ + break; + + case SecurityRootWindow: + { + /* if not a root window, this rule doesn't apply */ + if (pWin->parent) + continue; + } + break; + + case SecurityWindowWithProperty: + { + PropertyPtr pProp = wUserProps (pWin); + Bool match = FALSE; + char *p; + char *pEndData; + + while (pProp) + { + if (pProp->propertyName == pacl->mustHaveProperty) + break; + pProp = pProp->next; + } + if (!pProp) + continue; + if (!pacl->mustHaveValue) + break; + if (pProp->type != XA_STRING || pProp->format != 8) + continue; + + p = pProp->data; + pEndData = ((char *)pProp->data) + pProp->size; + while (!match && p < pEndData) + { + if (SecurityMatchString(pacl->mustHaveValue, p)) + match = TRUE; + else + { /* skip to the next string */ + while (*p++ && p < pEndData) + ; + } + } + if (!match) + continue; + } + break; /* end case SecurityWindowWithProperty */ + } /* end switch on windowRestriction */ + + /* If we get here, the property access rule pacl applies. + * If pacl doesn't apply, something above should have + * executed a continue, which will skip the follwing code. + */ + action = SecurityAllowOperation; + if (access_mode & SecurityReadAccess) + action = max(action, pacl->readAction); + if (access_mode & SecurityWriteAccess) + action = max(action, pacl->writeAction); + if (access_mode & SecurityDestroyAccess) + action = max(action, pacl->destroyAction); + break; + } /* end for each pacl */ + } /* end if propertyName <= SecurityMaxPropertyName */ + + if (SecurityAllowOperation != action) + { /* audit the access violation */ + int cid = CLIENT_ID(pWin->drawable.id); + int reqtype = ((xReq *)client->requestBuffer)->reqType; + char *actionstr = (SecurityIgnoreOperation == action) ? + "ignored" : "error"; + SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n", + client->index, reqtype, pWin->drawable.id, + NameForAtom(propertyName), propertyName, cid, actionstr); + } + return action; +} /* SecurityCheckPropertyAccess */ + + +/* SecurityResetProc + * + * Arguments: + * extEntry is the extension information for the security extension. + * + * Returns: nothing. + * + * Side Effects: + * Performs any cleanup needed by Security at server shutdown time. + */ + +static void +SecurityResetProc(extEntry) + ExtensionEntry *extEntry; +{ + SecurityFreePropertyAccessList(); + SecurityFreeSitePolicyStrings(); +} /* SecurityResetProc */ + + +int +XSecurityOptions(argc, argv, i) + int argc; + char **argv; + int i; +{ + if (strcmp(argv[i], "-sp") == 0) + { + if (i < argc) + SecurityPolicyFile = argv[++i]; + return (i + 1); + } + return (i); +} /* XSecurityOptions */ + + + +/* SecurityExtensionInit + * + * Arguments: none. + * + * Returns: nothing. + * + * Side Effects: + * Enables the Security extension if possible. + */ + +void +SecurityExtensionInit() +{ + ExtensionEntry *extEntry; + int i; + + SecurityAuthorizationResType = + CreateNewResourceType(SecurityDeleteAuthorization); + + RTEventClient = CreateNewResourceType( + SecurityDeleteAuthorizationEventClient); + + if (!SecurityAuthorizationResType || !RTEventClient) + return; + + RTEventClient |= RC_NEVERRETAIN; + + if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL)) + return; + + extEntry = AddExtension(SECURITY_EXTENSION_NAME, + XSecurityNumberEvents, XSecurityNumberErrors, + ProcSecurityDispatch, SProcSecurityDispatch, + SecurityResetProc, StandardMinorOpcode); + + SecurityErrorBase = extEntry->errorBase; + SecurityEventBase = extEntry->eventBase; + + EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = + SwapSecurityAuthorizationRevokedEvent; + + /* initialize untrusted proc vectors */ + + for (i = 0; i < 128; i++) + { + UntrustedProcVector[i] = ProcVector[i]; + SwappedUntrustedProcVector[i] = SwappedProcVector[i]; + } + + /* make sure insecure extensions are not allowed */ + + for (i = 128; i < 256; i++) + { + if (!UntrustedProcVector[i]) + { + UntrustedProcVector[i] = ProcBadRequest; + SwappedUntrustedProcVector[i] = ProcBadRequest; + } + } + + SecurityLoadPropertyAccessList(); + +} /* SecurityExtensionInit */ diff --git a/Xext/shape.c b/Xext/shape.c new file mode 100644 index 000000000..bff7d2502 --- /dev/null +++ b/Xext/shape.c @@ -0,0 +1,1217 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: shape.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _SHAPE_SERVER_ /* don't want Xlib structures */ +#include "shapestr.h" +#include "regionstr.h" +#include "gcstruct.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#endif + +static int ShapeFreeClient(), ShapeFreeEvents(); +static void SendShapeNotify(); +static int ProcShapeDispatch(), SProcShapeDispatch(); +static void ShapeResetProc(), SShapeNotifyEvent(); + +static unsigned char ShapeReqCode = 0; +static int ShapeEventBase = 0; +static RESTYPE ClientType, EventType; /* resource types for event masks */ + +#ifdef PANORAMIX +extern int PanoramiXNumScreens; +extern Bool noPanoramiXExtension; +extern PanoramiXWindow *PanoramiXWinRoot; +extern PanoramiXPmap *PanoramiXPmapRoot; +#endif +/* + * each window has a list of clients requesting + * ShapeNotify events. Each client has a resource + * for each window it selects ShapeNotify input for, + * this resource is used to delete the ShapeNotifyRec + * entry from the per-window queue. + */ + +typedef struct _ShapeEvent *ShapeEventPtr; + +typedef struct _ShapeEvent { + ShapeEventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; +} ShapeEventRec; + +/**************** + * ShapeExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ + +void +ShapeExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + ClientType = CreateNewResourceType(ShapeFreeClient); + EventType = CreateNewResourceType(ShapeFreeEvents); + if (ClientType && EventType && + (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, + ProcShapeDispatch, SProcShapeDispatch, + ShapeResetProc, StandardMinorOpcode))) + { + ShapeReqCode = (unsigned char)extEntry->base; + ShapeEventBase = extEntry->eventBase; + EventSwapVector[ShapeEventBase] = SShapeNotifyEvent; + } +} + +/*ARGSUSED*/ +static void +ShapeResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static +RegionOperate (client, pWin, kind, destRgnp, srcRgn, op, xoff, yoff, create) + ClientPtr client; + WindowPtr pWin; + int kind; + RegionPtr *destRgnp, srcRgn; + int op; + int xoff, yoff; + RegionPtr (*create)(); /* creates a reasonable *destRgnp */ +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (srcRgn && (xoff || yoff)) + REGION_TRANSLATE(pScreen, srcRgn, xoff, yoff); + if (!pWin->parent) + { + if (srcRgn) + REGION_DESTROY(pScreen, srcRgn); + return Success; + } + switch (op) { + case ShapeSet: + if (*destRgnp) + REGION_DESTROY(pScreen, *destRgnp); + *destRgnp = srcRgn; + srcRgn = 0; + break; + case ShapeUnion: + if (*destRgnp) + REGION_UNION(pScreen, *destRgnp, *destRgnp, srcRgn); + break; + case ShapeIntersect: + if (*destRgnp) + REGION_INTERSECT(pScreen, *destRgnp, *destRgnp, srcRgn); + else { + *destRgnp = srcRgn; + srcRgn = 0; + } + break; + case ShapeSubtract: + if (!*destRgnp) + *destRgnp = (*create)(pWin); + REGION_SUBTRACT(pScreen, *destRgnp, *destRgnp, srcRgn); + break; + case ShapeInvert: + if (!*destRgnp) + *destRgnp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); + else + REGION_SUBTRACT(pScreen, *destRgnp, srcRgn, *destRgnp); + break; + default: + client->errorValue = op; + return BadValue; + } + if (srcRgn) + REGION_DESTROY(pScreen, srcRgn); + (*pScreen->SetShape) (pWin); + SendShapeNotify (pWin, kind); + return Success; +} + +static RegionPtr +CreateBoundingShape (pWin) + WindowPtr pWin; +{ + BoxRec extents; + + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); +} + +static RegionPtr +CreateClipShape (pWin) + WindowPtr pWin; +{ + BoxRec extents; + + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); +} + +static int +ProcShapeQueryVersion (client) + register ClientPtr client; +{ + REQUEST(xShapeQueryVersionReq); + xShapeQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xShapeQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SHAPE_MAJOR_VERSION; + rep.minorVersion = SHAPE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xShapeQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/***************** + * ProcShapeRectangles + * + *****************/ +#ifdef PANORAMIX +static int +ProcPanoramiXShapeRectangles (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeRectanglesReq); + xRectangle *prects; + int nrects, ctype; + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + int destBounding; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + result = ProcShapeRectangles (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeRectangles (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeRectanglesReq); + xRectangle *prects; + int nrects, ctype; + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + int destBounding; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + UpdateCurrentTime(); + pWin = LookupWindow (stuff->dest, client); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + destBounding = 1; + createDefault = CreateBoundingShape; + break; + case ShapeClip: + destBounding = 0; + createDefault = CreateClipShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq)); + if (nrects & 4) + return BadLength; + nrects >>= 3; + prects = (xRectangle *) &stuff[1]; + ctype = VerifyRectOrder(nrects, prects, (int)stuff->ordering); + if (ctype < 0) + return BadMatch; + srcRgn = RECTS_TO_REGION(pScreen, nrects, prects, ctype); + + if (!pWin->optional) + MakeWindowOptional (pWin); + if (destBounding) + destRgn = &pWin->optional->boundingShape; + else + destRgn = &pWin->optional->clipShape; + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +/************** + * ProcShapeMask + **************/ + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeMask (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeMaskReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + PixmapPtr pPixmap; + RegionPtr (*createDefault)(); + int destBounding; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXPmap *pPmap = PanoramiXPmapRoot; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + PANORAMIXFIND_ID(pPmap, stuff->src); + IF_RETURN(!pPmap, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + stuff->src = pPmap->info[j].id; + result = ProcShapeMask (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeMask (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeMaskReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + PixmapPtr pPixmap; + RegionPtr (*createDefault)(); + int destBounding; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + UpdateCurrentTime(); + pWin = SecurityLookupWindow (stuff->dest, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + destBounding = 1; + createDefault = CreateBoundingShape; + break; + case ShapeClip: + destBounding = 0; + createDefault = CreateClipShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (stuff->src == None) + srcRgn = 0; + else { + pPixmap = (PixmapPtr) SecurityLookupIDByType(client, stuff->src, + RT_PIXMAP, SecurityReadAccess); + if (!pPixmap) + return BadPixmap; + if (pPixmap->drawable.pScreen != pScreen || + pPixmap->drawable.depth != 1) + return BadMatch; + srcRgn = BITMAP_TO_REGION(pScreen, pPixmap); + if (!srcRgn) + return BadAlloc; + } + + if (!pWin->optional) + MakeWindowOptional (pWin); + if (destBounding) + destRgn = &pWin->optional->boundingShape; + else + destRgn = &pWin->optional->clipShape; + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +/************ + * ProcShapeCombine + ************/ +#ifdef PANORAMIX +static int +ProcPanoramiXShapeCombine (client) + register ClientPtr client; +{ + WindowPtr pSrcWin, pDestWin; + ScreenPtr pScreen; + REQUEST(xShapeCombineReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + RegionPtr (*createSrc)(); + RegionPtr tmp; + int destBounding; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_AT_LEAST_SIZE (xShapeCombineReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + result = ProcShapeCombine (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeCombine (client) + register ClientPtr client; +{ + WindowPtr pSrcWin, pDestWin; + ScreenPtr pScreen; + REQUEST(xShapeCombineReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + RegionPtr (*createSrc)(); + RegionPtr tmp; + int destBounding; + + REQUEST_SIZE_MATCH (xShapeCombineReq); + UpdateCurrentTime(); + pDestWin = LookupWindow (stuff->dest, client); + if (!pDestWin) + return BadWindow; + if (!pDestWin->optional) + MakeWindowOptional (pDestWin); + switch (stuff->destKind) { + case ShapeBounding: + destBounding = 1; + createDefault = CreateBoundingShape; + break; + case ShapeClip: + destBounding = 0; + createDefault = CreateClipShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pDestWin->drawable.pScreen; + + pSrcWin = LookupWindow (stuff->src, client); + if (!pSrcWin) + return BadWindow; + switch (stuff->srcKind) { + case ShapeBounding: + srcRgn = wBoundingShape (pSrcWin); + createSrc = CreateBoundingShape; + break; + case ShapeClip: + srcRgn = wClipShape (pSrcWin); + createSrc = CreateClipShape; + break; + default: + client->errorValue = stuff->srcKind; + return BadValue; + } + if (pSrcWin->drawable.pScreen != pScreen) + { + return BadMatch; + } + + if (srcRgn) { + tmp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); + REGION_COPY(pScreen, tmp, srcRgn); + srcRgn = tmp; + } else + srcRgn = (*createSrc) (pSrcWin); + + if (!pDestWin->optional) + MakeWindowOptional (pDestWin); + if (destBounding) + destRgn = &pDestWin->optional->boundingShape; + else + destRgn = &pDestWin->optional->clipShape; + + return RegionOperate (client, pDestWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +/************* + * ProcShapeOffset + *************/ +#ifdef PANORAMIX +static int +ProcPanoramiXShapeOffset (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeOffsetReq); + RegionPtr srcRgn; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_AT_LEAST_SIZE (xShapeOffsetReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + result = ProcShapeOffset (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeOffset (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeOffsetReq); + RegionPtr srcRgn; + + REQUEST_SIZE_MATCH (xShapeOffsetReq); + UpdateCurrentTime(); + pWin = LookupWindow (stuff->dest, client); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + srcRgn = wBoundingShape (pWin); + break; + case ShapeClip: + srcRgn = wClipShape(pWin); + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (srcRgn) + { + REGION_TRANSLATE(pScreen, srcRgn, stuff->xOff, stuff->yOff); + (*pScreen->SetShape) (pWin); + } + SendShapeNotify (pWin, (int)stuff->destKind); + return Success; +} + +static int +ProcShapeQueryExtents (client) + register ClientPtr client; +{ + REQUEST(xShapeQueryExtentsReq); + WindowPtr pWin; + xShapeQueryExtentsReply rep; + BoxRec extents, *pExtents; + register int n; + + REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.boundingShaped = (wBoundingShape(pWin) != 0); + rep.clipShaped = (wClipShape(pWin) != 0); + if (wBoundingShape(pWin)) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, wBoundingShape(pWin)); + extents = *pExtents; + } else { + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + } + rep.xBoundingShape = extents.x1; + rep.yBoundingShape = extents.y1; + rep.widthBoundingShape = extents.x2 - extents.x1; + rep.heightBoundingShape = extents.y2 - extents.y1; + if (wClipShape(pWin)) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, wClipShape(pWin)); + extents = *pExtents; + } else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + } + rep.xClipShape = extents.x1; + rep.yClipShape = extents.y1; + rep.widthClipShape = extents.x2 - extents.x1; + rep.heightClipShape = extents.y2 - extents.y1; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.xBoundingShape, n); + swaps(&rep.yBoundingShape, n); + swaps(&rep.widthBoundingShape, n); + swaps(&rep.heightBoundingShape, n); + swaps(&rep.xClipShape, n); + swaps(&rep.yClipShape, n); + swaps(&rep.widthClipShape, n); + swaps(&rep.heightClipShape, n); + } + WriteToClient(client, sizeof (xShapeQueryExtentsReply), (char *)&rep); + return (client->noClientException); +} + +/*ARGSUSED*/ +static int +ShapeFreeClient (data, id) + pointer data; + XID id; +{ + ShapeEventPtr pShapeEvent; + WindowPtr pWin; + ShapeEventPtr *pHead, pCur, pPrev; + + pShapeEvent = (ShapeEventPtr) data; + pWin = pShapeEvent->window; + pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + } + } + xfree ((pointer) pShapeEvent); + return 1; +} + +/*ARGSUSED*/ +static int +ShapeFreeEvents (data, id) + pointer data; + XID id; +{ + ShapeEventPtr *pHead, pCur, pNext; + + pHead = (ShapeEventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +static int +ProcShapeSelectInput (client) + register ClientPtr client; +{ + REQUEST(xShapeSelectInputReq); + WindowPtr pWin; + ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH (xShapeSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (ShapeEventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, SecurityWriteAccess); + switch (stuff->enable) { + case xTrue: + if (pHead) { + + /* check for existing entry. */ + for (pShapeEvent = *pHead; + pShapeEvent; + pShapeEvent = pShapeEvent->next) + { + if (pShapeEvent->client == client) + return Success; + } + } + + /* build the entry */ + pNewShapeEvent = (ShapeEventPtr) + xalloc (sizeof (ShapeEventRec)); + if (!pNewShapeEvent) + return BadAlloc; + pNewShapeEvent->next = 0; + pNewShapeEvent->client = client; + pNewShapeEvent->window = pWin; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewShapeEvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewShapeEvent)) + return BadAlloc; + /* + * create a resource to contain a pointer to the list + * of clients selecting input. This must be indirect as + * the list may be arbitrarily rearranged which cannot be + * done through the resource database. + */ + if (!pHead) + { + pHead = (ShapeEventPtr *) xalloc (sizeof (ShapeEventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewShapeEvent->next = *pHead; + *pHead = pNewShapeEvent; + break; + case xFalse: + /* delete the interest */ + if (pHead) { + pNewShapeEvent = 0; + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + if (pShapeEvent->client == client) + break; + pNewShapeEvent = pShapeEvent; + } + if (pShapeEvent) { + FreeResource (pShapeEvent->clientResource, ClientType); + if (pNewShapeEvent) + pNewShapeEvent->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + xfree (pShapeEvent); + } + } + break; + default: + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + +/* + * deliver the event + */ + +static void +SendShapeNotify (pWin, which) + WindowPtr pWin; + int which; +{ + ShapeEventPtr *pHead, pShapeEvent; + ClientPtr client; + xShapeNotifyEvent se; + BoxRec extents; + RegionPtr region; + BYTE shaped; + + pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (!pHead) + return; + if (which == ShapeBounding) { + region = wBoundingShape(pWin); + if (region) { + extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); + shaped = xTrue; + } else { + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + shaped = xFalse; + } + } else { + region = wClipShape(pWin); + if (region) { + extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); + shaped = xTrue; + } else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + shaped = xFalse; + } + } + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + client = pShapeEvent->client; + if (client == serverClient || client->clientGone) + continue; + se.type = ShapeNotify + ShapeEventBase; + se.kind = which; + se.window = pWin->drawable.id; + se.sequenceNumber = client->sequence; + se.x = extents.x1; + se.y = extents.y1; + se.width = extents.x2 - extents.x1; + se.height = extents.y2 - extents.y1; + se.time = currentTime.milliseconds; + se.shaped = shaped; + WriteEventsToClient (client, 1, (xEvent *) &se); + } +} + +static int +ProcShapeInputSelected (client) + register ClientPtr client; +{ + REQUEST(xShapeInputSelectedReq); + WindowPtr pWin; + ShapeEventPtr pShapeEvent, *pHead; + int enabled; + xShapeInputSelectedReply rep; + register int n; + + REQUEST_SIZE_MATCH (xShapeInputSelectedReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + pHead = (ShapeEventPtr *) SecurityLookupIDByType(client, + pWin->drawable.id, EventType, SecurityReadAccess); + enabled = xFalse; + if (pHead) { + for (pShapeEvent = *pHead; + pShapeEvent; + pShapeEvent = pShapeEvent->next) + { + if (pShapeEvent->client == client) { + enabled = xTrue; + break; + } + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.enabled = enabled; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + } + WriteToClient (client, sizeof (xShapeInputSelectedReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcShapeGetRectangles (client) + register ClientPtr client; +{ + REQUEST(xShapeGetRectanglesReq); + WindowPtr pWin; + xShapeGetRectanglesReply rep; + xRectangle *rects; + int nrects, i; + RegionPtr region; + register int n; + + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + switch (stuff->kind) { + case ShapeBounding: + region = wBoundingShape(pWin); + break; + case ShapeClip: + region = wClipShape(pWin); + break; + default: + client->errorValue = stuff->kind; + return BadValue; + } + if (!region) { + nrects = 1; + rects = (xRectangle *) ALLOCATE_LOCAL (sizeof (xRectangle)); + if (!rects) + return BadAlloc; + switch (stuff->kind) { + case ShapeBounding: + rects->x = - (int) wBorderWidth (pWin); + rects->y = - (int) wBorderWidth (pWin); + rects->width = pWin->drawable.width + wBorderWidth (pWin); + rects->height = pWin->drawable.height + wBorderWidth (pWin); + break; + case ShapeClip: + rects->x = 0; + rects->y = 0; + rects->width = pWin->drawable.width; + rects->height = pWin->drawable.height; + break; + } + } else { + BoxPtr box; + nrects = REGION_NUM_RECTS(region); + box = REGION_RECTS(region); + rects = (xRectangle *) ALLOCATE_LOCAL (nrects * sizeof (xRectangle)); + if (!rects && nrects) + return BadAlloc; + for (i = 0; i < nrects; i++, box++) { + rects[i].x = box->x1; + rects[i].y = box->y1; + rects[i].width = box->x2 - box->x1; + rects[i].height = box->y2 - box->y1; + } + } + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = (nrects * sizeof (xRectangle)) >> 2; + rep.ordering = YXBanded; + rep.nrects = nrects; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.nrects, n); + SwapShorts ((short *)rects, (unsigned long)nrects * 4); + } + WriteToClient (client, sizeof (rep), (char *) &rep); + WriteToClient (client, nrects * sizeof (xRectangle), (char *) rects); + DEALLOCATE_LOCAL (rects); + return client->noClientException; +} + +static int +ProcShapeDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return ProcShapeQueryVersion (client); + case X_ShapeRectangles: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeRectangles (client); + else + return ProcShapeRectangles (client); +#else + return ProcShapeRectangles (client); +#endif + case X_ShapeMask: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeMask (client); + else + return ProcShapeMask (client); +#else + return ProcShapeMask (client); +#endif + case X_ShapeCombine: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeCombine (client); + else + return ProcShapeCombine (client); +#else + return ProcShapeCombine (client); +#endif + case X_ShapeOffset: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeOffset (client); + else + return ProcShapeOffset (client); +#else + return ProcShapeOffset (client); +#endif + case X_ShapeQueryExtents: + return ProcShapeQueryExtents (client); + case X_ShapeSelectInput: + return ProcShapeSelectInput (client); + case X_ShapeInputSelected: + return ProcShapeInputSelected (client); + case X_ShapeGetRectangles: + return ProcShapeGetRectangles (client); + default: + return BadRequest; + } +} + +static void +SShapeNotifyEvent(from, to) + xShapeNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswapl (from->window, to->window); + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswaps (from->x, to->x); + cpswaps (from->y, to->y); + cpswaps (from->width, to->width); + cpswaps (from->height, to->height); + cpswapl (from->time, to->time); + to->shaped = from->shaped; +} + +static int +SProcShapeQueryVersion (client) + register ClientPtr client; +{ + register int n; + REQUEST (xShapeQueryVersionReq); + + swaps (&stuff->length, n); + return ProcShapeQueryVersion (client); +} + +static int +SProcShapeRectangles (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeRectanglesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + SwapRestS(stuff); + return ProcShapeRectangles (client); +} + +static int +SProcShapeMask (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeMaskReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeMaskReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + swapl (&stuff->src, n); + return ProcShapeMask (client); +} + +static int +SProcShapeCombine (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeCombineReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeCombineReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + swapl (&stuff->src, n); + return ProcShapeCombine (client); +} + +static int +SProcShapeOffset (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeOffsetReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeOffsetReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + return ProcShapeOffset (client); +} + +static int +SProcShapeQueryExtents (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeQueryExtentsReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); + swapl (&stuff->window, n); + return ProcShapeQueryExtents (client); +} + +static int +SProcShapeSelectInput (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeSelectInputReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeSelectInputReq); + swapl (&stuff->window, n); + return ProcShapeSelectInput (client); +} + +static int +SProcShapeInputSelected (client) + register ClientPtr client; +{ + register int n; + REQUEST (xShapeInputSelectedReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeInputSelectedReq); + swapl (&stuff->window, n); + return ProcShapeInputSelected (client); +} + +static int +SProcShapeGetRectangles (client) + register ClientPtr client; +{ + REQUEST(xShapeGetRectanglesReq); + register char n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + swapl (&stuff->window, n); + return ProcShapeGetRectangles (client); +} + +static int +SProcShapeDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return SProcShapeQueryVersion (client); + case X_ShapeRectangles: + return SProcShapeRectangles (client); + case X_ShapeMask: + return SProcShapeMask (client); + case X_ShapeCombine: + return SProcShapeCombine (client); + case X_ShapeOffset: + return SProcShapeOffset (client); + case X_ShapeQueryExtents: + return SProcShapeQueryExtents (client); + case X_ShapeSelectInput: + return SProcShapeSelectInput (client); + case X_ShapeInputSelected: + return SProcShapeInputSelected (client); + case X_ShapeGetRectangles: + return SProcShapeGetRectangles (client); + default: + return BadRequest; + } +} diff --git a/Xext/shm.c b/Xext/shm.c new file mode 100644 index 000000000..0a9f3af59 --- /dev/null +++ b/Xext/shm.c @@ -0,0 +1,1010 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#include +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include "shmstr.h" +#include "Xfuncproto.h" + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(), fbShmPutImage(); +static PixmapPtr fbShmCreatePixmap(); +static int ProcShmDispatch(), SProcShmDispatch(); +static int ShmDetachSegment(); +static void ShmResetProc(), SShmCompletionEvent(); + +static unsigned char ShmReqCode; +static int ShmCompletionCode; +static int BadShmSegCode; +static RESTYPE ShmSegType, ShmPixType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + +void +ShmExtensionInit() +{ + ExtensionEntry *extEntry; + int i; + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + sharedPixmaps = xFalse; + pixmapFormat = 0; +#else + sharedPixmaps = xTrue; + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + shmFuncs[i] = &miFuncs; + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; +#endif + ShmSegType = CreateNewResourceType(ShmDetachSegment); + ShmPixType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && ShmPixType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs(pScreen, funcs) + ScreenPtr pScreen; + ShmFuncsPtr funcs; +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat(pScreen, format) + ScreenPtr pScreen; + int format; +{ + shmPixFormat[pScreen->myNum] = format; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + REQUEST(xShmQueryVersionReq); + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + return; + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + /*XXX*/depth, PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + FreeScratchPixmapHeader(pPixmap); + } + else + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); +} + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + long lengthProto; + char *tmpImage; + int tmpAlloced = 0; +#endif + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = PixmapBytePadProto(stuff->totalWidth, 1); +#endif + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = PixmapBytePadProto(stuff->totalWidth, 1); + lengthProto *= stuff->depth; +#endif + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = PixmapBytePadProto(stuff->totalWidth, stuff->depth); +#endif + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + VERIFY_SHMSIZE(shmdesc, stuff->offset, lengthProto * stuff->totalHeight, + client); +#else + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); +#endif + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* handle 64 bit case where protocol may pad to 32 and we want 64 + * In this case, length is what the server wants and lengthProto is + * what the protocol thinks it is. If the the two are different, + * copy the protocol version (i.e. the memory shared between the + * server and the client) to a version with a scanline pad of 64. + */ + if (length != lengthProto) + { + register int i; + char * stuffptr, /* pointer into protocol data */ + * tmpptr; /* new location to copy to */ + + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->totalHeight))) + return (BadAlloc); + tmpAlloced = 1; + + bzero(tmpImage,length*stuff->totalHeight); + + if (stuff->format == XYPixmap) + { + int lineBytes = PixmapBytePad(stuff->totalWidth, 1); + int lineBytesProto = PixmapBytePadProto(stuff->totalWidth, 1); + int depth = stuff->depth; + + stuffptr = shmdesc->addr + stuff->offset ; + tmpptr = tmpImage; + for (i = 0; i < stuff->totalHeight*stuff->depth; + stuffptr += lineBytesProto,tmpptr += lineBytes, i++) + bcopy(stuffptr,tmpptr,lineBytesProto); + } + else + { + for (i = 0, + stuffptr = shmdesc->addr + stuff->offset, + tmpptr=tmpImage; + i < stuff->totalHeight; + stuffptr += lengthProto,tmpptr += length, i++) + bcopy(stuffptr,tmpptr,lengthProto); + } + } + /* handle 64-bit case where stuff is not 64-bit aligned + */ + else if ((unsigned long)(shmdesc->addr+stuff->offset) & + (sizeof(long)-1)) + { + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->totalHeight))) + return (BadAlloc); + tmpAlloced = 1; + bcopy((char *)(shmdesc->addr+stuff->offset), + tmpImage, + length*stuff->totalHeight); + } + else + tmpImage = (char *)(shmdesc->addr+stuff->offset); +#endif + + if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || + ((stuff->format != ZPixmap) && + (stuff->srcX < screenInfo.bitmapScanlinePad) && + ((stuff->format == XYBitmap) || + ((stuff->srcY == 0) && + (stuff->srcHeight == stuff->totalHeight))))) && + ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, + stuff->dstX, stuff->dstY, + stuff->totalWidth, stuff->srcHeight, + stuff->srcX, stuff->format, +#ifdef INTERNAL_VS_EXTERNAL_PADDING + tmpImage + +#else + shmdesc->addr + stuff->offset + +#endif + (stuff->srcY * length)); + else + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, +#ifdef INTERNAL_VS_EXTERNAL_PADDING + tmpImage); + +#else + shmdesc->addr + stuff->offset); +#endif + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if (tmpAlloced) + DEALLOCATE_LOCAL(tmpImage); +#endif + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer, length; + Mask plane; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + long widthBytesLine,widthBytesLineProto; + long lenPerProto,lengthProto; + char *tmpImage; + int tmpAlloced = 0; +#endif + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLine = PixmapBytePad(stuff->width, pDraw->depth); + length = widthBytesLine * stuff->height; + widthBytesLineProto = PixmapBytePadProto(stuff->width, pDraw->depth); + lengthProto = widthBytesLineProto * stuff->height; +#else + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; +#endif + } + else + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLine = PixmapBytePad(stuff->width, 1); + lenPer = widthBytesLine * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + + widthBytesLineProto = PixmapBytePadProto(stuff->width, 1); + lenPerProto = widthBytesLineProto * stuff->height; + lengthProto = lenPerProto * Ones(stuff->planeMask & + (plane | (plane - 1))); +#else + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); +#endif + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + VERIFY_SHMSIZE(shmdesc, stuff->offset, lengthProto, client); + xgi.size = lengthProto; +#else + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; +#endif + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* check for protocol/server padding differences. + */ + if ((widthBytesLine != widthBytesLineProto) || + ((unsigned long)shmdesc->addr + stuff->offset & (sizeof(long)-1))) + { + /* temp stuff for 64 bit alignment stuff */ + register char * bufPtr, * protoPtr; + register int i; + + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + tmpAlloced = 1; + + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + tmpImage); + + /* for 64-bit server, convert image to pad to 32 bits + */ + bzero(shmdesc->addr + stuff->offset,lengthProto); + + for (i=0,bufPtr=tmpImage,protoPtr=shmdesc->addr + stuff->offset; + i < stuff->height; + bufPtr += widthBytesLine,protoPtr += widthBytesLineProto, + i++) + bcopy(bufPtr,protoPtr,widthBytesLineProto); + } + else + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } +#else + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); +#endif + } + else + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* check for protocol/server padding differences. + */ + if ((widthBytesLine != widthBytesLineProto) || + ((unsigned long)shmdesc->addr + stuff->offset & + (sizeof(long)-1))) + { + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + tmpAlloced = 1; + } +#endif + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if ((widthBytesLine != widthBytesLineProto) || + ((unsigned long)shmdesc->addr + stuff->offset & + (sizeof(long)-1))) + { + /* get image for each plane. + */ + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + tmpImage); + + /* for 64-bit server, convert image to pad to 32 bits */ + bzero(shmdesc->addr+length, widthBytesLine); + bcopy(tmpImage, shmdesc->addr+length, widthBytesLineProto); + /* increment length */ + length += lenPerProto; + } + else /* no diff between protocol and server */ + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } +#else + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; +#endif + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if (tmpAlloced) + DEALLOCATE_LOCAL(tmpImage); +#endif + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); + if (!pPixmap) + return NullPixmap; + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + /*XXX*/depth, PixmapBytePad(width, depth), (pointer)addr)) + return NullPixmap; + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + shmdesc->refcnt++; + if (AddResource(stuff->pid, ShmPixType, (pointer)shmdesc)) + return(client->noClientException); + FreeResource(stuff->pid, RT_NONE); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: + return ProcShmPutImage(client); + case X_ShmGetImage: + return ProcShmGetImage(client); + case X_ShmCreatePixmap: + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + return SProcShmPutImage(client); + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} diff --git a/Xext/sleepuntil.c b/Xext/sleepuntil.c new file mode 100644 index 000000000..292924ed6 --- /dev/null +++ b/Xext/sleepuntil.c @@ -0,0 +1,211 @@ +/* + * $Xorg: sleepuntil.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ + * +Copyright 1992, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* dixsleep.c - implement millisecond timeouts for X clients */ + +#include "X.h" +#include "Xmd.h" +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +typedef struct _Sertafied { + struct _Sertafied *next; + TimeStamp revive; + ClientPtr pClient; + XID id; + void (*notifyFunc)(); + pointer closure; +} SertafiedRec, *SertafiedPtr; + +static SertafiedPtr pPending; +static RESTYPE SertafiedResType; +static Bool BlockHandlerRegistered; +static int SertafiedGeneration; +static void ClientAwaken(); +static int SertafiedDelete(); +static void SertafiedBlockHandler(); +static void SertafiedWakeupHandler(); + +ClientSleepUntil (client, revive, notifyFunc, closure) + ClientPtr client; + TimeStamp *revive; + void (*notifyFunc)(); + pointer closure; +{ + SertafiedPtr pRequest, pReq, pPrev; + + if (SertafiedGeneration != serverGeneration) + { + SertafiedResType = CreateNewResourceType (SertafiedDelete); + if (!SertafiedResType) + return FALSE; + SertafiedGeneration = serverGeneration; + BlockHandlerRegistered = FALSE; + } + pRequest = (SertafiedPtr) xalloc (sizeof (SertafiedRec)); + if (!pRequest) + return FALSE; + pRequest->pClient = client; + pRequest->revive = *revive; + pRequest->id = FakeClientID (client->index); + pRequest->closure = closure; + if (!BlockHandlerRegistered) + { + if (!RegisterBlockAndWakeupHandlers (SertafiedBlockHandler, + SertafiedWakeupHandler, + (pointer) 0)) + { + xfree (pRequest); + return FALSE; + } + BlockHandlerRegistered = TRUE; + } + pRequest->notifyFunc = 0; + if (!AddResource (pRequest->id, SertafiedResType, (pointer) pRequest)) + return FALSE; + if (!notifyFunc) + notifyFunc = ClientAwaken; + pRequest->notifyFunc = notifyFunc; + /* Insert into time-ordered queue, with earliest activation time coming first. */ + pPrev = 0; + for (pReq = pPending; pReq; pReq = pReq->next) + { + if (CompareTimeStamps (pReq->revive, *revive) == LATER) + break; + pPrev = pReq; + } + if (pPrev) + pPrev->next = pRequest; + else + pPending = pRequest; + pRequest->next = pReq; + IgnoreClient (client); + return TRUE; +} + +static void +ClientAwaken (client, closure) + ClientPtr client; + pointer closure; +{ + if (!client->clientGone) + AttendClient (client); +} + + +static int +SertafiedDelete (value, id) + pointer value; + XID id; +{ + SertafiedPtr pRequest = (SertafiedPtr)value; + SertafiedPtr pReq, pPrev; + + pPrev = 0; + for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) + if (pReq == pRequest) + { + if (pPrev) + pPrev->next = pReq->next; + else + pPending = pReq->next; + break; + } + if (pRequest->notifyFunc) + (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); + xfree (pRequest); + return TRUE; +} + +static void +SertafiedBlockHandler (data, wt, LastSelectMask) + pointer data; /* unused */ + OSTimePtr wt; /* wait time */ + pointer LastSelectMask; +{ + SertafiedPtr pReq, pNext; + unsigned long newdelay, olddelay; + TimeStamp now; + + if (!pPending) + return; + now.milliseconds = GetTimeInMillis (); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) + { + pNext = pReq->next; + if (CompareTimeStamps (pReq->revive, now) == LATER) + break; + FreeResource (pReq->id, RT_NONE); + + /* AttendClient() may have been called via the resource delete + * function so a client may have input to be processed and so + * set delay to 0 to prevent blocking in WaitForSomething(). + */ + AdjustWaitForDelay (wt, 0); + } + pReq = pPending; + if (!pReq) + return; + newdelay = pReq->revive.milliseconds - now.milliseconds; + AdjustWaitForDelay (wt, newdelay); +} + +static void +SertafiedWakeupHandler (data, i, LastSelectMask) + pointer data; + int i; + pointer LastSelectMask; +{ + SertafiedPtr pReq, pNext; + TimeStamp now; + + now.milliseconds = GetTimeInMillis (); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) + { + pNext = pReq->next; + if (CompareTimeStamps (pReq->revive, now) == LATER) + break; + FreeResource (pReq->id, RT_NONE); + } + if (!pPending) + { + RemoveBlockAndWakeupHandlers (SertafiedBlockHandler, + SertafiedWakeupHandler, + (pointer) 0); + BlockHandlerRegistered = FALSE; + } +} diff --git a/Xext/sync.c b/Xext/sync.c new file mode 100644 index 000000000..8274d2522 --- /dev/null +++ b/Xext/sync.c @@ -0,0 +1,2322 @@ +/* $Xorg: sync.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + +Copyright 1991, 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, +and Olivetti Research Limited, Cambridge, England. + + 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 Olivetti +not be used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. Digital and Olivetti +make no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL THEY 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. + +*/ + +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "X.h" +#include "Xproto.h" +#include "Xmd.h" +#include "misc.h" +#include "os.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _SYNC_SERVER +#include "sync.h" +#include "syncstr.h" + +/* + * Local Global Variables + */ +static int SyncReqCode; +static int SyncEventBase; +static int SyncErrorBase; +static RESTYPE RTCounter = 0; +static RESTYPE RTAwait; +static RESTYPE RTAlarm; +static RESTYPE RTAlarmClient; +static int SyncNumSystemCounters = 0; +static SyncCounter **SysCounterList = NULL; + +#define IsSystemCounter(pCounter) \ + (pCounter && (pCounter->client == NULL)) + +/* these are all the alarm attributes that pertain to the alarm's trigger */ +#define XSyncCAAllTrigger \ + (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) + +static void SyncComputeBracketValues( +#if NeedFunctionPrototypes + SyncCounter * /* pCounter */, + Bool /* startOver */ +#endif +); + +/* Each counter maintains a simple linked list of triggers that are + * interested in the counter. The two functions below are used to + * delete and add triggers on this list. + */ +static void +SyncDeleteTriggerFromCounter(pTrigger) + SyncTrigger *pTrigger; +{ + SyncTriggerList *pCur, *pPrev = NULL; + + /* pCounter needs to be stored in pTrigger before calling here. */ + + if (!pTrigger->pCounter) + return; + + for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) + { + if (pCur->pTrigger == pTrigger) + { + if (pPrev) + pPrev->next = pCur->next; + else + pTrigger->pCounter->pTriglist = pCur->next; + xfree(pCur); + break; + } + } + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE); +} + + +static int +SyncAddTriggerToCounter(pTrigger) + SyncTrigger *pTrigger; +{ + SyncTriggerList *pCur; + + if (!pTrigger->pCounter) + return Success; + + /* don't do anything if it's already there */ + for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) + { + if (pCur->pTrigger == pTrigger) + return Success; + } + + if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList)))) + return BadAlloc; + + pCur->pTrigger = pTrigger; + pCur->next = pTrigger->pCounter->pTriglist; + pTrigger->pCounter->pTriglist = pCur; + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE); + + return Success; +} + + +/* Below are four possible functions that can be plugged into + * pTrigger->CheckTrigger, corresponding to the four possible + * test-types. These functions are called after the counter's + * value changes but are also passed the old counter value + * so they can inspect both the old and new values. + * (PositiveTransition and NegativeTransition need to see both + * pieces of information.) These functions return the truth value + * of the trigger. + * + * All of them include the condition pTrigger->pCounter == NULL. + * This is because the spec says that a trigger with a counter value + * of None is always TRUE. + */ + +static Bool +SyncCheckTriggerPositiveComparison(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerNegativeComparison(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerPositiveTransition(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + (XSyncValueLessThan(oldval, pTrigger->test_value) && + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static Bool +SyncCheckTriggerNegativeTransition(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + (XSyncValueGreaterThan(oldval, pTrigger->test_value) && + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + + + +static int +SyncInitTrigger(client, pTrigger, counter, changes) + ClientPtr client; /* so we can set errorValue */ + SyncTrigger *pTrigger; + XSyncCounter counter; + Mask changes; +{ + SyncCounter *pCounter = pTrigger->pCounter; + int status; + Bool newcounter = FALSE; + + if (changes & XSyncCACounter) + { + if (counter == None) + pCounter = NULL; + else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType( + client, counter, RTCounter, SecurityReadAccess))) + { + client->errorValue = counter; + return SyncErrorBase + XSyncBadCounter; + } + if (pCounter != pTrigger->pCounter) + { /* new counter for trigger */ + SyncDeleteTriggerFromCounter(pTrigger); + pTrigger->pCounter = pCounter; + newcounter = TRUE; + } + } + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + if (changes & XSyncCAValueType) + { + if (pTrigger->value_type != XSyncRelative && + pTrigger->value_type != XSyncAbsolute) + { + client->errorValue = pTrigger->value_type; + return BadValue; + } + } + + if (changes & XSyncCATestType) + { + if (pTrigger->test_type != XSyncPositiveTransition && + pTrigger->test_type != XSyncNegativeTransition && + pTrigger->test_type != XSyncPositiveComparison && + pTrigger->test_type != XSyncNegativeComparison) + { + client->errorValue = pTrigger->test_type; + return BadValue; + } + /* select appropriate CheckTrigger function */ + + switch (pTrigger->test_type) + { + case XSyncPositiveTransition: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; + break; + case XSyncNegativeTransition: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; + break; + case XSyncPositiveComparison: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; + break; + case XSyncNegativeComparison: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; + break; + } + } + + if (changes & (XSyncCAValueType | XSyncCAValue)) + { + if (pTrigger->value_type == XSyncAbsolute) + pTrigger->test_value = pTrigger->wait_value; + else /* relative */ + { + Bool overflow; + if (pCounter == NULL) + return BadMatch; + + XSyncValueAdd(&pTrigger->test_value, pCounter->value, + pTrigger->wait_value, &overflow); + if (overflow) + { + client->errorValue = XSyncValueHigh32(pTrigger->wait_value); + return BadValue; + } + } + } + + /* we wait until we're sure there are no errors before registering + * a new counter on a trigger + */ + if (newcounter) + { + if ((status = SyncAddTriggerToCounter(pTrigger)) != Success) + return status; + } + else if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter, /*startOver*/ TRUE); + } + + return Success; +} + +/* AlarmNotify events happen in response to actions taken on an Alarm or + * the counter used by the alarm. AlarmNotify may be sent to multiple + * clients. The alarm maintains a list of clients interested in events. + */ +static void +SyncSendAlarmNotifyEvents(pAlarm) + SyncAlarm *pAlarm; +{ + SyncAlarmClientList *pcl; + xSyncAlarmNotifyEvent ane; + SyncTrigger *pTrigger = &pAlarm->trigger; + + UpdateCurrentTime(); + + ane.type = SyncEventBase + XSyncAlarmNotify; + ane.kind = XSyncAlarmNotify; + ane.sequenceNumber = pAlarm->client->sequence; + ane.alarm = pAlarm->alarm_id; + if (pTrigger->pCounter) + { + ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + } + else + { /* XXX what else can we do if there's no counter? */ + ane.counter_value_hi = ane.counter_value_lo = 0; + } + + ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); + ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); + ane.time = currentTime.milliseconds; + ane.state = pAlarm->state; + + /* send to owner */ + if (pAlarm->events && !pAlarm->client->clientGone) + WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); + + /* send to other interested clients */ + for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) + { + if (!pAlarm->client->clientGone) + { + ane.sequenceNumber = pcl->client->sequence; + WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); + } + } +} + + +/* CounterNotify events only occur in response to an Await. The events + * go only to the Awaiting client. + */ +static void +SyncSendCounterNotifyEvents(client, ppAwait, num_events) + ClientPtr client; + SyncAwait **ppAwait; + int num_events; +{ + xSyncCounterNotifyEvent *pEvents, *pev; + int i; + + if (client->clientGone) + return; + pev = pEvents = (xSyncCounterNotifyEvent *) + ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent)); + if (!pEvents) + return; + UpdateCurrentTime(); + for (i = 0; i < num_events; i++, ppAwait++, pev++) + { + SyncTrigger *pTrigger = &(*ppAwait)->trigger; + pev->type = SyncEventBase + XSyncCounterNotify; + pev->kind = XSyncCounterNotify; + pev->sequenceNumber = client->sequence; + pev->counter = pTrigger->pCounter->id; + pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); + pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + pev->time = currentTime.milliseconds; + pev->count = num_events - i - 1; /* events remaining */ + pev->destroyed = pTrigger->pCounter->beingDestroyed; + } + /* swapping will be taken care of by this */ + WriteEventsToClient(client, num_events, (xEvent *)pEvents); + DEALLOCATE_LOCAL(pEvents); +} + + +/* This function is called when an alarm's counter is destroyed. + * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). + */ +void +SyncAlarmCounterDestroyed(pTrigger) + SyncTrigger *pTrigger; +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + + pAlarm->state = XSyncAlarmInactive; + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->pCounter = NULL; +} + + +/* This function is called when an alarm "goes off." + * It is plugged into pTrigger->TriggerFired (for alarm triggers). + */ +static void +SyncAlarmTriggerFired(pTrigger) + SyncTrigger *pTrigger; +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + CARD64 new_test_value; + + /* no need to check alarm unless it's active */ + if (pAlarm->state != XSyncAlarmActive) + return; + + /* " if the counter value is None, or if the delta is 0 and + * the test-type is PositiveComparison or NegativeComparison, + * no change is made to value (test-value) and the alarm + * state is changed to Inactive before the event is generated." + */ + if (pAlarm->trigger.pCounter == NULL + || (XSyncValueIsZero(pAlarm->delta) + && (pAlarm->trigger.test_type == XSyncPositiveComparison + || pAlarm->trigger.test_type == XSyncNegativeComparison))) + pAlarm->state = XSyncAlarmInactive; + + new_test_value = pAlarm->trigger.test_value; + + if (pAlarm->state == XSyncAlarmActive) + { + Bool overflow; + CARD64 oldvalue; + SyncTrigger *pTrigger = &pAlarm->trigger; + + /* "The alarm is updated by repeatedly adding delta to the + * value of the trigger and re-initializing it until it + * becomes FALSE." + */ + oldvalue = pTrigger->test_value; + + /* XXX really should do something smarter here */ + + do + { + XSyncValueAdd(&pTrigger->test_value, pTrigger->test_value, + pAlarm->delta, &overflow); + } while (!overflow && + (*pTrigger->CheckTrigger)(pTrigger, + pTrigger->pCounter->value)); + + new_test_value = pTrigger->test_value; + pTrigger->test_value = oldvalue; + + /* "If this update would cause value to fall outside the range + * for an INT64...no change is made to value (test-value) and + * the alarm state is changed to Inactive before the event is + * generated." + */ + if (overflow) + { + new_test_value = oldvalue; + pAlarm->state = XSyncAlarmInactive; + } + } + /* The AlarmNotify event has to have the "new state of the alarm" + * which we can't be sure of until this point. However, it has + * to have the "old" trigger test value. That's the reason for + * all the newvalue/oldvalue shuffling above. After we send the + * events, give the trigger its new test value. + */ + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->test_value = new_test_value; +} + + +/* This function is called when an Await unblocks, either as a result + * of the trigger firing OR the counter being destroyed. + * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed + * (for Await triggers). + */ +static void +SyncAwaitTriggerFired(pTrigger) + SyncTrigger *pTrigger; +{ + SyncAwait *pAwait = (SyncAwait *)pTrigger; + int numwaits; + SyncAwaitUnion *pAwaitUnion; + SyncAwait **ppAwait; + int num_events = 0; + + pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; + numwaits = pAwaitUnion->header.num_waitconditions; + ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *)); + if (!ppAwait) + goto bail; + + pAwait = &(pAwaitUnion+1)->await; + + /* "When a client is unblocked, all the CounterNotify events for + * the Await request are generated contiguously. If count is 0 + * there are no more events to follow for this request. If + * count is n, there are at least n more events to follow." + * + * Thus, it is best to find all the counters for which events + * need to be sent first, so that an accurate count field can + * be stored in the events. + */ + for ( ; numwaits; numwaits--, pAwait++) + { + CARD64 diff; + Bool overflow, diffgreater, diffequal; + + /* "A CounterNotify event with the destroyed flag set to TRUE is + * always generated if the counter for one of the triggers is + * destroyed." + */ + if (pAwait->trigger.pCounter->beingDestroyed) + { + ppAwait[num_events++] = pAwait; + continue; + } + + /* "The difference between the counter and the test value is + * calculated by subtracting the test value from the value of + * the counter." + */ + XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, + pAwait->trigger.test_value, &overflow); + + /* "If the difference lies outside the range for an INT64, an + * event is not generated." + */ + if (overflow) + continue; + diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); + diffequal = XSyncValueEqual(diff, pAwait->event_threshold); + + /* "If the test-type is PositiveTransition or + * PositiveComparison, a CounterNotify event is generated if + * the difference is at least event-threshold. If the test-type + * is NegativeTransition or NegativeComparison, a CounterNotify + * event is generated if the difference is at most + * event-threshold." + */ + + if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || + pAwait->trigger.test_type == XSyncPositiveTransition) + && (diffgreater || diffequal)) + || + ((pAwait->trigger.test_type == XSyncNegativeComparison || + pAwait->trigger.test_type == XSyncNegativeTransition) + && (!diffgreater) /* less or equal */ + ) + ) + { + ppAwait[num_events++] = pAwait; + } + } + if (num_events) + SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, + num_events); + DEALLOCATE_LOCAL(ppAwait); + +bail: + /* unblock the client */ + AttendClient(pAwaitUnion->header.client); + /* delete the await */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); +} + + +/* This function should always be used to change a counter's value so that + * any triggers depending on the counter will be checked. + */ +void +SyncChangeCounter(pCounter, newval) + SyncCounter *pCounter; + CARD64 newval; +{ + SyncTriggerList *ptl, *pnext; + CARD64 oldval; + + oldval = pCounter->value; + pCounter->value = newval; + + /* run through triggers to see if any become true */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + pnext = ptl->next; + if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) + (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); + } + + if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter, /* startOver */ FALSE); + } +} + + +/* loosely based on dix/events.c/EventSelectForWindow */ +static Bool +SyncEventSelectForAlarm(pAlarm, client, wantevents) + SyncAlarm *pAlarm; + ClientPtr client; + Bool wantevents; +{ + SyncAlarmClientList *pClients; + + if (client == pAlarm->client) /* alarm owner */ + { + pAlarm->events = wantevents; + return Success; + } + + /* see if the client is already on the list (has events selected) */ + + for (pClients = pAlarm->pEventClients; pClients; + pClients = pClients->next) + { + if (pClients->client == client) + { + /* client's presence on the list indicates desire for + * events. If the client doesn't want events, remove it + * from the list. If the client does want events, do + * nothing, since it's already got them. + */ + if (!wantevents) + { + FreeResource(pClients->delete_id, RT_NONE); + } + return Success; + } + } + + /* if we get here, this client does not currently have + * events selected on the alarm + */ + + if (!wantevents) + /* client doesn't want events, and we just discovered that it + * doesn't have them, so there's nothing to do. + */ + return Success; + + /* add new client to pAlarm->pEventClients */ + + pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList)); + if (!pClients) + return BadAlloc; + + /* register it as a resource so it will be cleaned up + * if the client dies + */ + + pClients->delete_id = FakeClientID(client->index); + if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) + { + xfree(pClients); + return BadAlloc; + } + + /* link it into list after we know all the allocations succeed */ + + pClients->next = pAlarm->pEventClients; + pAlarm->pEventClients = pClients; + pClients->client = client; + return Success; +} + +/* + * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm + */ +static int +SyncChangeAlarmAttributes(client, pAlarm, mask, values) + ClientPtr client; + SyncAlarm *pAlarm; + Mask mask; + CARD32 *values; +{ + SyncAlarmClientList *pClients; + int status; + XSyncCounter counter; + Mask origmask = mask; + + counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; + + while (mask) + { + int index = lowbit(mask); + mask &= ~index; + switch (index) + { + case XSyncCACounter: + mask &= ~XSyncCACounter; + /* sanity check in SyncInitTrigger */ + counter = *values++; + break; + + case XSyncCAValueType: + mask &= ~XSyncCAValueType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.value_type = *values++; + break; + + case XSyncCAValue: + mask &= ~XSyncCAValue; + XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); + values += 2; + break; + + case XSyncCATestType: + mask &= ~XSyncCATestType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.test_type = *values++; + break; + + case XSyncCADelta: + mask &= ~XSyncCADelta; + XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); + values += 2; + break; + + case XSyncCAEvents: + mask &= ~XSyncCAEvents; + if ((*values != xTrue) && (*values != xFalse)) + { + client->errorValue = *values; + return BadValue; + } + status = SyncEventSelectForAlarm(pAlarm, client, + (Bool)(*values++)); + if (status != Success) + return status; + break; + + default: + client->errorValue = mask; + return BadValue; + } + } + + /* "If the test-type is PositiveComparison or PositiveTransition + * and delta is less than zero, or if the test-type is + * NegativeComparison or NegativeTransition and delta is + * greater than zero, a Match error is generated." + */ + if (origmask & (XSyncCADelta|XSyncCATestType)) + { + CARD64 zero; + XSyncIntToValue(&zero, 0); + if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || + (pAlarm->trigger.test_type == XSyncPositiveTransition)) + && XSyncValueLessThan(pAlarm->delta, zero)) + || + (((pAlarm->trigger.test_type == XSyncNegativeComparison) || + (pAlarm->trigger.test_type == XSyncNegativeTransition)) + && XSyncValueGreaterThan(pAlarm->delta, zero)) + ) + { + return BadMatch; + } + } + + /* postpone this until now, when we're sure nothing else can go wrong */ + if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, + origmask & XSyncCAAllTrigger)) != Success) + return status; + + /* XXX spec does not really say to do this - needs clarification */ + pAlarm->state = XSyncAlarmActive; + return Success; +} + + +static SyncCounter * +SyncCreateCounter(client, id, initialvalue) + ClientPtr client; + XSyncCounter id; + CARD64 initialvalue; +{ + SyncCounter *pCounter; + + if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter)))) + return (SyncCounter *)NULL; + + if (!AddResource(id, RTCounter, (pointer) pCounter)) + { + xfree((pointer) pCounter); + return (SyncCounter *)NULL; + } + + pCounter->client = client; + pCounter->id = id; + pCounter->value = initialvalue; + pCounter->pTriglist = NULL; + pCounter->beingDestroyed = FALSE; + pCounter->pSysCounterInfo = NULL; + return pCounter; +} + +static int FreeCounter( +#if NeedFunctionPrototypes + pointer /*env*/, + XID /*id*/ +#endif +); + +/* + * ***** System Counter utilities + */ + +pointer +SyncCreateSystemCounter(name, initial, resolution, counterType, + QueryValue, BracketValues) + char *name; + CARD64 initial; + CARD64 resolution; + SyncCounterType counterType; + void (*QueryValue) (); + void (*BracketValues) (); +{ + SyncCounter *pCounter; + + SysCounterList = (SyncCounter **)xrealloc(SysCounterList, + (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); + if (!SysCounterList) + return (pointer)NULL; + + /* this function may be called before SYNC has been initialized, so we + * have to make sure RTCounter is created. + */ + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter); + if (RTCounter == 0) + { + return (pointer)NULL; + } + } + + pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial); + + if (pCounter) + { + SysCounterInfo *psci; + + psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo)); + if (!psci) + { + FreeResource(pCounter->id, RT_NONE); + return (pointer) pCounter; + } + pCounter->pSysCounterInfo = psci; + psci->name = name; + psci->resolution = resolution; + psci->counterType = counterType; + psci->QueryValue = QueryValue; + psci->BracketValues = BracketValues; + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + SysCounterList[SyncNumSystemCounters++] = pCounter; + } + return (pointer) pCounter; +} + +void +SyncDestroySystemCounter(pSysCounter) + pointer pSysCounter; +{ + SyncCounter *pCounter = (SyncCounter *)pSysCounter; + FreeResource(pCounter->id, RT_NONE); +} + +static void +SyncComputeBracketValues(pCounter, startOver) + SyncCounter *pCounter; + Bool startOver; +{ + SyncTriggerList *pCur; + SyncTrigger *pTrigger; + SysCounterInfo *psci = pCounter->pSysCounterInfo; + CARD64 *pnewgtval = NULL; + CARD64 *pnewltval = NULL; + SyncCounterType ct; + + if (!pCounter) + return; + + ct = pCounter->pSysCounterInfo->counterType; + if (ct == XSyncCounterNeverChanges) + return; + + if (startOver) + { + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + } + + for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) + { + pTrigger = pCur->pTrigger; + + if (pTrigger->test_type == XSyncPositiveComparison && + ct != XSyncCounterNeverIncreases) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && + XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + } + else if (pTrigger->test_type == XSyncNegativeComparison && + ct != XSyncCounterNeverDecreases) + { + if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && + XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + else if ( (pTrigger->test_type == XSyncPositiveTransition && + ct != XSyncCounterNeverIncreases) + || + (pTrigger->test_type == XSyncNegativeTransition && + ct != XSyncCounterNeverDecreases) + ) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value)) + { + if (XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + else + if (XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + } + } /* end for each trigger */ + + if (pnewgtval || pnewltval) + { + (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); + } +} + +/* + * ***** Resource delete functions + */ + +/* ARGSUSED */ +static int +FreeAlarm(addr, id) + pointer addr; + XID id; +{ + SyncAlarm *pAlarm = (SyncAlarm *) addr; + SyncAlarmClientList *pClient; + + pAlarm->state = XSyncAlarmDestroyed; + + SyncSendAlarmNotifyEvents(pAlarm); + + /* delete event selections */ + + while (pAlarm->pEventClients) + FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); + + SyncDeleteTriggerFromCounter(&pAlarm->trigger); + + xfree(pAlarm); + return Success; +} + + +/* + * ** Cleanup after the destruction of a Counter + */ +/* ARGSUSED */ +static int +FreeCounter(env, id) + pointer env; + XID id; +{ + SyncCounter *pCounter = (SyncCounter *) env; + SyncTriggerList *ptl, *pnext; + + pCounter->beingDestroyed = TRUE; + /* tell all the counter's triggers that the counter has been destroyed */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); + pnext = ptl->next; + xfree(ptl); /* destroy the trigger list as we go */ + } + if (IsSystemCounter(pCounter)) + { + int i, found = 0; + + xfree(pCounter->pSysCounterInfo); + + /* find the counter in the list of system counters and remove it */ + + if (SysCounterList) + { + for (i = 0; i < SyncNumSystemCounters; i++) + { + if (SysCounterList[i] == pCounter) + { + found = i; + break; + } + } + if (found < (SyncNumSystemCounters-1)) + { + for (i = found; i < SyncNumSystemCounters-1; i++) + { + SysCounterList[i] = SysCounterList[i+1]; + } + } + } + SyncNumSystemCounters--; + } + xfree(pCounter); + return Success; +} + +/* + * ** Cleanup after Await + */ +/* ARGSUSED */ +static int +FreeAwait(addr, id) + pointer addr; + XID id; +{ + SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; + SyncAwait *pAwait; + int numwaits; + + pAwait = &(pAwaitUnion+1)->await; /* first await on list */ + + /* remove triggers from counters */ + + for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; + numwaits--, pAwait++) + { + /* If the counter is being destroyed, FreeCounter will delete + * the trigger list itself, so don't do it here. + */ + SyncCounter *pCounter = pAwait->trigger.pCounter; + if (pCounter && !pCounter->beingDestroyed) + SyncDeleteTriggerFromCounter(&pAwait->trigger); + } + xfree(pAwaitUnion); + return Success; +} + +/* loosely based on dix/events.c/OtherClientGone */ +static int +FreeAlarmClient(value, id) + pointer value; /* must conform to DeleteType */ + XID id; +{ + SyncAlarm *pAlarm = (SyncAlarm *)value; + SyncAlarmClientList *pCur, *pPrev; + + for (pPrev = NULL, pCur = pAlarm->pEventClients; + pCur; + pPrev = pCur, pCur = pCur->next) + { + if (pCur->delete_id == id) + { + if (pPrev) + pPrev->next = pCur->next; + else + pAlarm->pEventClients = pCur->next; + xfree(pCur); + return(Success); + } + } + FatalError("alarm client not on event list"); + /*NOTREACHED*/ +} + + +/* + * ***** Proc functions + */ + + +/* + * ** Initialize the extension + */ +static int +ProcSyncInitialize(client) + ClientPtr client; +{ + REQUEST(xSyncInitializeReq); + xSyncInitializeReply rep; + int n; + + REQUEST_SIZE_MATCH(xSyncInitializeReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SYNC_MAJOR_VERSION; + rep.minorVersion = SYNC_MINOR_VERSION; + rep.length = 0; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(rep), (char *) &rep); + return (client->noClientException); +} + +/* + * ** Get list of system counters available through the extension + */ +static int +ProcSyncListSystemCounters(client) + ClientPtr client; +{ + REQUEST(xSyncListSystemCountersReq); + xSyncListSystemCountersReply rep; + int i, len; + xSyncSystemCounter *list, *walklist; + + REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nCounters = SyncNumSystemCounters; + + for (i = len = 0; i < SyncNumSystemCounters; i++) + { + char *name = SysCounterList[i]->pSysCounterInfo->name; + /* pad to 4 byte boundary */ + len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3; + } + + if (len) + { + walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len); + if (!list) + return BadAlloc; + } + + rep.length = len >> 2; + + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.nCounters, n); + } + + for (i = 0; i < SyncNumSystemCounters; i++) + { + int namelen; + char *pname_in_reply; + SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; + + walklist->counter = SysCounterList[i]->id; + walklist->resolution_hi = XSyncValueHigh32(psci->resolution); + walklist->resolution_lo = XSyncValueLow32(psci->resolution); + namelen = strlen(psci->name); + walklist->name_length = namelen; + + if (client->swapped) + { + register char n; + swapl(&walklist->counter, n); + swapl(&walklist->resolution_hi, n); + swapl(&walklist->resolution_lo, n); + swaps(&walklist->name_length, n); + } + + pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; + strncpy(pname_in_reply, psci->name, namelen); + walklist = (xSyncSystemCounter *) (((char *)walklist) + + ((sz_xSyncSystemCounter + namelen + 3) & ~3)); + } + + WriteToClient(client, sizeof(rep), (char *) &rep); + if (len) + { + WriteToClient(client, len, (char *) list); + DEALLOCATE_LOCAL(list); + } + + return (client->noClientException); +} + +/* + * ** Set client Priority + */ +static int +ProcSyncSetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncSetPriorityReq); + ClientPtr priorityclient; + + REQUEST_SIZE_MATCH(xSyncSetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else if (!(priorityclient = LookupClient(stuff->id, client))) + { + client->errorValue = stuff->id; + return BadMatch; + } + + if (priorityclient->priority != stuff->priority) + { + priorityclient->priority = stuff->priority; + + /* The following will force the server back into WaitForSomething + * so that the change in this client's priority is immediately + * reflected. + */ + isItTimeToYield = TRUE; + dispatchException |= DE_PRIORITYCHANGE; + } + return Success; +} + +/* + * ** Get client Priority + */ +static int +ProcSyncGetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncGetPriorityReq); + xSyncGetPriorityReply rep; + ClientPtr priorityclient; + + REQUEST_SIZE_MATCH(xSyncGetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else if (!(priorityclient = LookupClient(stuff->id, client))) + { + client->errorValue = stuff->id; + return BadMatch; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.priority = priorityclient->priority; + + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.priority, n); + } + + WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); + + return (client->noClientException); +} + +/* + * ** Create a new counter + */ +static int +ProcSyncCreateCounter(client) + ClientPtr client; +{ + REQUEST(xSyncCreateCounterReq); + SyncCounter *pCounter; + CARD64 initial; + + REQUEST_SIZE_MATCH(xSyncCreateCounterReq); + + LEGAL_NEW_RESOURCE(stuff->cid, client); + + XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); + if (!SyncCreateCounter(client, stuff->cid, initial)) + return BadAlloc; + + return (client->noClientException); +} + +/* + * ** Set Counter value + */ +static int +ProcSyncSetCounter(client) + ClientPtr client; +{ + REQUEST(xSyncSetCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + + pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid, + RTCounter, SecurityWriteAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->cid; + return SyncErrorBase + XSyncBadCounter; + } + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Change Counter value + */ +static int +ProcSyncChangeCounter(client) + ClientPtr client; +{ + REQUEST(xSyncChangeCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + Bool overflow; + + REQUEST_SIZE_MATCH(xSyncChangeCounterReq); + + pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid, + RTCounter, SecurityWriteAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->cid; + return SyncErrorBase + XSyncBadCounter; + } + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); + if (overflow) + { + /* XXX 64 bit value can't fit in 32 bits; do the best we can */ + client->errorValue = stuff->value_hi; + return BadValue; + } + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Destroy a counter + */ +static int +ProcSyncDestroyCounter(client) + ClientPtr client; +{ + REQUEST(xSyncDestroyCounterReq); + SyncCounter *pCounter; + + REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); + + pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, + RTCounter, SecurityDestroyAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->counter; + return SyncErrorBase + XSyncBadCounter; + } + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->counter; + return BadAccess; + } + FreeResource(pCounter->id, RT_NONE); + return Success; +} + + +/* + * ** Await + */ +static int +ProcSyncAwait(client) + ClientPtr client; +{ + REQUEST(xSyncAwaitReq); + int len, items; + int n, i; + xSyncWaitCondition *pProtocolWaitConds; + int ret; + SyncAwaitUnion *pAwaitUnion; + SyncAwait *pAwait; + int status; + + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + + len = client->req_len << 2; + len -= sz_xSyncAwaitReq; + items = len / sz_xSyncWaitCondition; + + if (items * sz_xSyncWaitCondition != len) + { + return BadLength; + } + if (items == 0) + { + client->errorValue = items; /* XXX protocol change */ + return BadValue; + } + + pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; + + /* all the memory for the entire await list is allocated + * here in one chunk + */ + pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion)); + if (!pAwaitUnion) + return BadAlloc; + + /* first item is the header, remainder are real wait conditions */ + + pAwaitUnion->header.delete_id = FakeClientID(client->index); + if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) + { + xfree(pAwaitUnion); + return BadAlloc; + } + + /* don't need to do any more memory allocation for this request! */ + + pAwaitUnion->header.client = client; + pAwaitUnion->header.num_waitconditions = 0; + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) + { + if (pProtocolWaitConds->counter == None) /* XXX protocol change */ + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + client->errorValue = pProtocolWaitConds->counter; + return SyncErrorBase + XSyncBadCounter; + } + + /* sanity checks are in SyncInitTrigger */ + pAwait->trigger.pCounter = NULL; + pAwait->trigger.value_type = pProtocolWaitConds->value_type; + XSyncIntsToValue(&pAwait->trigger.wait_value, + pProtocolWaitConds->wait_value_lo, + pProtocolWaitConds->wait_value_hi); + pAwait->trigger.test_type = pProtocolWaitConds->test_type; + + status = SyncInitTrigger(client, &pAwait->trigger, + pProtocolWaitConds->counter, XSyncCAAllTrigger); + if (status != Success) + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + return status; + } + /* this is not a mistake -- same function works for both cases */ + pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; + pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; + XSyncIntsToValue(&pAwait->event_threshold, + pProtocolWaitConds->event_threshold_lo, + pProtocolWaitConds->event_threshold_hi); + pAwait->pHeader = &pAwaitUnion->header; + pAwaitUnion->header.num_waitconditions++; + } + + IgnoreClient(client); + + /* see if any of the triggers are already true */ + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pAwait++) + { + /* don't have to worry about NULL counters because the request + * errors before we get here out if they occur + */ + if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, + pAwait->trigger.pCounter->value)) + { + (*pAwait->trigger.TriggerFired)(&pAwait->trigger); + break; /* once is enough */ + } + } + return Success; +} + + +/* + * ** Query a counter + */ +static int +ProcSyncQueryCounter(client) + ClientPtr client; +{ + REQUEST(xSyncQueryCounterReq); + xSyncQueryCounterReply rep; + SyncCounter *pCounter; + + REQUEST_SIZE_MATCH(xSyncQueryCounterReq); + + pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, + RTCounter, SecurityReadAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->counter; + return SyncErrorBase + XSyncBadCounter; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + rep.value_hi = XSyncValueHigh32(pCounter->value); + rep.value_lo = XSyncValueLow32(pCounter->value); + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.value_hi, n); + swapl(&rep.value_lo, n); + } + WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); + return (client->noClientException); +} + + +/* + * ** Create Alarm + */ +static int +ProcSyncCreateAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncCreateAlarmReq); + SyncAlarm *pAlarm; + int status; + int i; + unsigned long len, vmask; + SyncTrigger *pTrigger; + + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + + LEGAL_NEW_RESOURCE(stuff->id, client); + + vmask = stuff->valueMask; + len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm)))) + { + return BadAlloc; + } + + /* set up defaults */ + + pTrigger = &pAlarm->trigger; + pTrigger->pCounter = NULL; + pTrigger->value_type = XSyncAbsolute; + XSyncIntToValue(&pTrigger->wait_value, 0L); + pTrigger->test_type = XSyncPositiveComparison; + pTrigger->TriggerFired = SyncAlarmTriggerFired; + pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; + status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); + if (status != Success) + { + xfree(pAlarm); + return status; + } + + pAlarm->client = client; + pAlarm->alarm_id = stuff->id; + XSyncIntToValue(&pAlarm->delta, 1L); + pAlarm->events = TRUE; + pAlarm->state = XSyncAlarmInactive; + pAlarm->pEventClients = NULL; + status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1]); + if (status != Success) + { + xfree(pAlarm); + return status; + } + + if (!AddResource(stuff->id, RTAlarm, pAlarm)) + { + xfree(pAlarm); + return BadAlloc; + } + + /* see if alarm already triggered. NULL counter will not trigger + * in CreateAlarm and sets alarm state to Inactive. + */ + + if (!pTrigger->pCounter) + { + pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ + } + else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) + { + (*pTrigger->TriggerFired)(pTrigger); + } + + return Success; +} + +/* + * ** Change Alarm + */ +static int +ProcSyncChangeAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncChangeAlarmReq); + SyncAlarm *pAlarm; + long vmask; + int len, status; + + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + + if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityWriteAccess))) + { + client->errorValue = stuff->alarm; + return SyncErrorBase + XSyncBadAlarm; + } + + vmask = stuff->valueMask; + len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1])) != Success) + return status; + + /* see if alarm already triggered. NULL counter WILL trigger + * in ChangeAlarm. + */ + + if (!pAlarm->trigger.pCounter || + (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, + pAlarm->trigger.pCounter->value)) + { + (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); + } + return Success; +} + +static int +ProcSyncQueryAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncQueryAlarmReq); + SyncAlarm *pAlarm; + xSyncQueryAlarmReply rep; + SyncTrigger *pTrigger; + + REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); + + pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityReadAccess); + if (!pAlarm) + { + client->errorValue = stuff->alarm; + return (SyncErrorBase + XSyncBadAlarm); + } + + rep.type = X_Reply; + rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + + pTrigger = &pAlarm->trigger; + rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; + +#if 0 /* XXX unclear what to do, depends on whether relative value-types + * are "consumed" immediately and are considered absolute from then + * on. + */ + rep.value_type = pTrigger->value_type; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); +#else + rep.value_type = XSyncAbsolute; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); +#endif + + rep.test_type = pTrigger->test_type; + rep.delta_hi = XSyncValueHigh32(pAlarm->delta); + rep.delta_lo = XSyncValueLow32(pAlarm->delta); + rep.events = pAlarm->events; + rep.state = pAlarm->state; + + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.counter, n); + swapl(&rep.wait_value_hi, n); + swapl(&rep.wait_value_lo, n); + swapl(&rep.test_type, n); + swapl(&rep.delta_hi, n); + swapl(&rep.delta_lo, n); + } + + WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); + return (client->noClientException); +} + + +static int +ProcSyncDestroyAlarm(client) + ClientPtr client; +{ + SyncAlarm *pAlarm; + REQUEST(xSyncDestroyAlarmReq); + + REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); + + if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityDestroyAccess))) + { + client->errorValue = stuff->alarm; + return SyncErrorBase + XSyncBadAlarm; + } + + FreeResource(stuff->alarm, RT_NONE); + return (client->noClientException); +} + +/* + * ** Given an extension request, call the appropriate request procedure + */ +static int +ProcSyncDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + + case X_SyncInitialize: + return ProcSyncInitialize(client); + case X_SyncListSystemCounters: + return ProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return ProcSyncCreateCounter(client); + case X_SyncSetCounter: + return ProcSyncSetCounter(client); + case X_SyncChangeCounter: + return ProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return ProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return ProcSyncDestroyCounter(client); + case X_SyncAwait: + return ProcSyncAwait(client); + case X_SyncCreateAlarm: + return ProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return ProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return ProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return ProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return ProcSyncSetPriority(client); + case X_SyncGetPriority: + return ProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Boring Swapping stuff ... + */ + +static int +SProcSyncInitialize(client) + ClientPtr client; +{ + REQUEST(xSyncInitializeReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncInitializeReq); + + return ProcSyncInitialize(client); +} + +static int +SProcSyncListSystemCounters(client) + ClientPtr client; +{ + REQUEST(xSyncListSystemCountersReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); + + return ProcSyncListSystemCounters(client); +} + +static int +SProcSyncCreateCounter(client) + ClientPtr client; +{ + REQUEST(xSyncCreateCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncCreateCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->initial_value_lo, n); + swapl(&stuff->initial_value_hi, n); + + return ProcSyncCreateCounter(client); +} + +static int +SProcSyncSetCounter(client) + ClientPtr client; +{ + REQUEST(xSyncSetCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncSetCounter(client); +} + +static int +SProcSyncChangeCounter(client) + ClientPtr client; +{ + REQUEST(xSyncChangeCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncChangeCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncChangeCounter(client); +} + +static int +SProcSyncQueryCounter(client) + ClientPtr client; +{ + REQUEST(xSyncQueryCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncQueryCounter(client); +} + +static int +SProcSyncDestroyCounter(client) + ClientPtr client; +{ + REQUEST(xSyncDestroyCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncDestroyCounter(client); +} + +static int +SProcSyncAwait(client) + ClientPtr client; +{ + REQUEST(xSyncAwaitReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + SwapRestL(stuff); + + return ProcSyncAwait(client); +} + + +static int +SProcSyncCreateAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncCreateAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + swapl(&stuff->id, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + + return ProcSyncCreateAlarm(client); +} + +static int +SProcSyncChangeAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncChangeAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + swapl(&stuff->alarm, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSyncChangeAlarm(client); +} + +static int +SProcSyncQueryAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncQueryAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncQueryAlarm(client); +} + +static int +SProcSyncDestroyAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncDestroyAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncDestroyAlarm(client); +} + +static int +SProcSyncSetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncSetPriorityReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetPriorityReq); + swapl(&stuff->id, n); + swapl(&stuff->priority, n); + + return ProcSyncSetPriority(client); +} + +static int +SProcSyncGetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncGetPriorityReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncGetPriorityReq); + swapl(&stuff->id, n); + + return ProcSyncGetPriority(client); +} + + +static int +SProcSyncDispatch(client) + ClientPtr client; +{ + int n; + + REQUEST(xReq); + + switch (stuff->data) + { + case X_SyncInitialize: + return SProcSyncInitialize(client); + case X_SyncListSystemCounters: + return SProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return SProcSyncCreateCounter(client); + case X_SyncSetCounter: + return SProcSyncSetCounter(client); + case X_SyncChangeCounter: + return SProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return SProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return SProcSyncDestroyCounter(client); + case X_SyncAwait: + return SProcSyncAwait(client); + case X_SyncCreateAlarm: + return SProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return SProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return SProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return SProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return SProcSyncSetPriority(client); + case X_SyncGetPriority: + return SProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Event Swapping + */ + +static void +SCounterNotifyEvent(from, to) + xSyncCounterNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->counter, to->counter); + cpswapl(from->wait_value_lo, to->wait_value_lo); + cpswapl(from->wait_value_hi, to->wait_value_hi); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->time, to->time); + cpswaps(from->count, to->count); + to->destroyed = from->destroyed; +} + + +static void +SAlarmNotifyEvent(from, to) + xSyncAlarmNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->alarm, to->alarm); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->alarm_value_lo, to->alarm_value_lo); + cpswapl(from->alarm_value_hi, to->alarm_value_hi); + cpswapl(from->time, to->time); + to->state = from->state; +} + +/* + * ** Close everything down. ** This is fairly simple for now. + */ +/* ARGSUSED */ +static void +SyncResetProc(extEntry) + ExtensionEntry *extEntry; +{ + xfree(SysCounterList); + SysCounterList = NULL; + RTCounter = 0; +} + + +static void SyncInitServerTime(); + +/* + * ** Initialise the extension. + */ +void +SyncExtensionInit() +{ + ExtensionEntry *extEntry; + + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter); + } + RTAlarm = CreateNewResourceType(FreeAlarm); + RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN; + RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN; + + if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || + RTAlarmClient == 0 || + (extEntry = AddExtension(SYNC_NAME, + XSyncNumberEvents, XSyncNumberErrors, + ProcSyncDispatch, SProcSyncDispatch, + SyncResetProc, + StandardMinorOpcode)) == NULL) + { + ErrorF("Sync Extension %d.%d failed to Initialise\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); + return; + } + + SyncReqCode = extEntry->base; + SyncEventBase = extEntry->eventBase; + SyncErrorBase = extEntry->errorBase; + EventSwapVector[SyncEventBase + XSyncCounterNotify] = SCounterNotifyEvent; + EventSwapVector[SyncEventBase + XSyncAlarmNotify] = SAlarmNotifyEvent; + + /* + * Although SERVERTIME is implemented by the OS layer, we initialise it + * here because doing it in OsInit() is too early. The resource database + * is not initialised when OsInit() is called. This is just about OK + * because there is always a servertime counter. + */ + SyncInitServerTime(); + +#ifdef DEBUG + fprintf(stderr, "Sync Extension %d.%d\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); +#endif +} + + +/* + * ***** SERVERTIME implementation - should go in its own file in OS directory? + */ + + +#ifndef WIN32 +#include +#endif + +static pointer ServertimeCounter; +static XSyncValue Now; +static XSyncValue *pnext_time; + +#define GetTime()\ +{\ + unsigned long millis = GetTimeInMillis();\ + unsigned long maxis = XSyncValueHigh32(Now);\ + if (millis < XSyncValueLow32(Now)) maxis++;\ + XSyncIntsToValue(&Now, millis, maxis);\ +} + +/* +*** Server Block Handler +*** code inspired by multibuffer extension + */ +/*ARGSUSED*/ +static void ServertimeBlockHandler(env, wt, LastSelectMask) +pointer env; +struct timeval **wt; +pointer LastSelectMask; +{ + XSyncValue delay; + unsigned long timeout; + + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + timeout = 0; + } + else + { + Bool overflow; + XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); + timeout = XSyncValueLow32(delay); + } + AdjustWaitForDelay(wt, timeout); /* os/utils.c */ + } +} + +/* +*** Wakeup Handler + */ +/*ARGSUSED*/ +static void ServertimeWakeupHandler(env, rc, LastSelectMask) +pointer env; +int rc; +pointer LastSelectMask; +{ + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + SyncChangeCounter(ServertimeCounter, Now); + } + } +} + +static void +ServertimeQueryValue(pCounter, pValue_return) + pointer pCounter; + CARD64 *pValue_return; +{ + GetTime(); + *pValue_return = Now; +} + +static void +ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater) + pointer pCounter; + CARD64 *pbracket_less; + CARD64 *pbracket_greater; +{ + if (!pnext_time && pbracket_greater) + { + RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + else if (pnext_time && !pbracket_greater) + { + RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + pnext_time = pbracket_greater; +} + +static void +SyncInitServerTime() +{ + CARD64 resolution; + + XSyncIntsToValue(&Now, GetTimeInMillis(), 0); + XSyncIntToValue(&resolution, 4); + ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, + XSyncCounterNeverDecreases, + ServertimeQueryValue, ServertimeBracketValues); + pnext_time = NULL; +} diff --git a/Xext/xcmisc.c b/Xext/xcmisc.c new file mode 100644 index 000000000..4977fdf88 --- /dev/null +++ b/Xext/xcmisc.c @@ -0,0 +1,218 @@ +/* $Xorg: xcmisc.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "xcmiscstr.h" + +static unsigned char XCMiscCode; +static int ProcXCMiscDispatch(), SProcXCMiscDispatch(); +static void XCMiscResetProc(); +extern void Swap32Write(); /* XXX should be in header file */ + +void +XCMiscExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(XCMiscExtensionName, 0, 0, + ProcXCMiscDispatch, SProcXCMiscDispatch, + XCMiscResetProc, StandardMinorOpcode)) + XCMiscCode = (unsigned char)extEntry->base; + DeclareExtensionSecurity(XCMiscExtensionName, TRUE); +} + +/*ARGSUSED*/ +static void +XCMiscResetProc (extEntry) + ExtensionEntry *extEntry; +{ +} + +static int +ProcXCMiscGetVersion(client) + register ClientPtr client; +{ + REQUEST(xXCMiscGetVersionReq); + xXCMiscGetVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XCMiscMajorVersion; + rep.minorVersion = XCMiscMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXCMiscGetVersionReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXCMiscGetXIDRange(client) + register ClientPtr client; +{ + REQUEST(xXCMiscGetXIDRangeReq); + xXCMiscGetXIDRangeReply rep; + register int n; + XID min_id, max_id; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq); + GetXIDRange(client->index, FALSE, &min_id, &max_id); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.start_id = min_id; + rep.count = max_id - min_id + 1; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.start_id, n); + swapl(&rep.count, n); + } + WriteToClient(client, sizeof(xXCMiscGetXIDRangeReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXCMiscGetXIDList(client) + register ClientPtr client; +{ + REQUEST(xXCMiscGetXIDListReq); + xXCMiscGetXIDListReply rep; + register int n; + XID *pids; + unsigned int count; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq); + + pids = (XID *)ALLOCATE_LOCAL(stuff->count * sizeof(XID)); + if (!pids) + { + return BadAlloc; + } + count = GetXIDList(client, stuff->count, pids); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = count; + rep.count = count; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.count, n); + } + WriteToClient(client, sizeof(xXCMiscGetXIDListReply), (char *)&rep); + if (count) + { + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, count * sizeof(XID), pids); + } + DEALLOCATE_LOCAL(pids); + return(client->noClientException); +} + +static int +ProcXCMiscDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XCMiscGetVersion: + return ProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return ProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return ProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} + +static int +SProcXCMiscGetVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXCMiscGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return ProcXCMiscGetVersion(client); +} + +static int +SProcXCMiscGetXIDRange(client) + register ClientPtr client; +{ + register int n; + REQUEST(xReq); + + swaps(&stuff->length, n); + return ProcXCMiscGetXIDRange(client); +} + +static int +SProcXCMiscGetXIDList(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXCMiscGetXIDListReq); + + swaps(&stuff->length, n); + swapl(&stuff->count, n); + return ProcXCMiscGetXIDList(client); +} + +static int +SProcXCMiscDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XCMiscGetVersion: + return SProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return SProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return SProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} diff --git a/Xext/xprint.c b/Xext/xprint.c new file mode 100644 index 000000000..6e2013140 --- /dev/null +++ b/Xext/xprint.c @@ -0,0 +1,2873 @@ +/* $Xorg: xprint.c,v 1.5 2001/03/05 20:42:36 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: xprint.c +** * +** * Copyright: Copyright 1993, 1995 Hewlett-Packard Company +** * +** * Copyright 1989 by The Massachusetts Institute of Technology +** * +** * 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 name of MIT not be used in +** * advertising or publicity pertaining to distribution of the +** * software without specific prior written permission. +** * M.I.T. makes no representation about the suitability of +** * this software for any purpose. It is provided "as is" +** * without any express or implied warranty. +** * +** * MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +** * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +** * NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE LI- +** * ABLE 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. +** * +** ********************************************************* +** +********************************************************************/ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#undef NEED_EVENTS +#include "misc.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "Xatom.h" +#define _XP_PRINT_SERVER_ +#include "Print.h" +#include "Printstr.h" +#undef _XP_PRINT_SERVER_ +#include "../Xprint/DiPrint.h" + +extern WindowPtr *WindowTable; /* declared in dix:globals.c */ + +extern WindowPtr XpDiValidatePrinter(); +extern char *XpDiGetDriverName(); +extern char *XpGetAttributes(); +extern char *XpGetOneAttribute(); +extern int XpRehashPrinterList(); +extern void XpSetFontResFunc(); + +static void XpResetProc(); + +static int ProcXpDispatch(); +static int ProcXpSwappedDispatch(); + +static int ProcXpQueryVersion(); +static int ProcXpGetPrinterList(); +static int ProcXpCreateContext(); +static int ProcXpSetContext(); +static int ProcXpGetContext(); +static int ProcXpDestroyContext(); +static int ProcXpGetContextScreen(); +static int ProcXpStartJob(); +static int ProcXpEndJob(); +static int ProcXpStartDoc(); +static int ProcXpEndDoc(); +static int ProcXpStartPage(); +static int ProcXpEndPage(); +static int ProcXpSelectInput(); +static int ProcXpInputSelected(); +static int ProcXpPutDocumentData(); +static int ProcXpGetDocumentData(); +static int ProcXpGetAttributes(); +static int ProcXpGetOneAttribute(); +static int ProcXpSetAttributes(); +static int ProcXpRehashPrinterList(); +static int ProcXpQueryScreens(); +static int ProcXpGetPageDimensions(); +static int ProcXpSetImageResolution(); +static int ProcXpGetImageResolution(); + +static void SwapXpNotifyEvent(); +static void SwapXpAttributeEvent(); + +static int SProcXpGetPrinterList(); +static int SProcXpCreateContext(); +static int SProcXpSetContext(); +static int SProcXpGetContext(); +static int SProcXpDestroyContext(); +static int SProcXpGetContextScreen(); +static int SProcXpStartJob(); +static int SProcXpEndJob(); +static int SProcXpStartDoc(); +static int SProcXpEndDoc(); +static int SProcXpStartPage(); +static int SProcXpEndPage(); +static int SProcXpSelectInput(); +static int SProcXpInputSelected(); +static int SProcXpPutDocumentData(); +static int SProcXpGetDocumentData(); +static int SProcXpGetAttributes(); +static int SProcXpGetOneAttribute(); +static int SProcXpSetAttributes(); +static int SProcXpRehashPrinterList(); +static int SProcXpGetPageDimensions(); +static int SProcXpSetImageResolution(); +static int SProcXpGetImageResolution(); + +static void SendXpNotify(); +static void SendAttributeNotify(); +static int XpFreeClient(); +static int XpFreeContext(); +static int XpFreePage(); +static int XpFreeEvents(); +static Bool XpCloseScreen(); +static CARD32 GetAllEventMasks(); +static struct _XpEvent *AddEventRec(); +static void DeleteEventRec(); +static struct _XpEvent *FindEventRec(); +static struct _XpClient *CreateXpClient(); +static void FreeXpClient(); +static void InitContextPrivates(); +static void ResetContextPrivates(); +static struct _XpClient *FindClient(); +static struct _XpClient *AcquireClient(); + +typedef struct _driver { + struct _driver *next; + char *name; + int (* CreateContext)(); +} XpDriverRec, *XpDriverPtr; + +typedef struct _xpScreen { + Bool (* CloseScreen)(); + struct _driver *drivers; +} XpScreenRec, *XpScreenPtr; + +/* + * Each context has a list of XpClients indicating which clients have + * associated this context with their connection. + * Each such client has a RTclient resource allocated for it, + * and this per-client + * resource is used to delete the XpClientRec if/when the client closes + * its connection. + * The list of XpClients is also walked if/when the context is destroyed + * so that the ContextPtr can be removed from the client's devPrivates. + */ +typedef struct _XpClient { + struct _XpClient *pNext; + ClientPtr client; + XpContextPtr context; + CARD32 eventMask; + XID contextClientID; /* unneeded sanity check? */ +} XpClientRec, *XpClientPtr; + +/* + * Each StartPage request specifies a window which forms the top level + * window of the page. One of the following structs is created as a + * RTpage resource with the same ID as the window itself. This enables + * us to clean up when/if the window is destroyed, and to prevent the + * same window from being simultaneously referenced in multiple contexts. + * The page resource is created at the first StartPage on a given window, + * and is only destroyed when/if the window is destroyed. When the + * EndPage is recieved (or an EndDoc or EndJob) the context field is + * set to NULL, but the resource remains alive. + */ +typedef struct _XpPage { + XpContextPtr context; +} XpPageRec, *XpPagePtr; + +typedef struct _XpStPageRec { + XpContextPtr pContext; + Bool slept; + XpPagePtr pPage; + WindowPtr pWin; +} XpStPageRec, *XpStPagePtr; + +typedef struct _XpStDocRec { + XpContextPtr pContext; + Bool slept; + CARD8 type; +} XpStDocRec, *XpStDocPtr; + +#define QUADPAD(x) ((((x)+3)>>2)<<2) + +/* + * Possible bit-mask values in the "state" field of a XpContextRec. + */ +#define JOB_STARTED (1 << 0) +#define DOC_RAW_STARTED (1 << 1) +#define DOC_COOKED_STARTED (1 << 2) +#define PAGE_STARTED (1 << 3) +#define GET_DOC_DATA_STARTED (1 << 4) +#define JOB_GET_DATA (1 << 5) + +static XpScreenPtr XpScreens[MAXSCREENS]; +static unsigned char XpReqCode; +static int XpEventBase; +static int XpErrorBase; +static int XpGeneration = 0; +static int XpWindowPrivateIndex; +static int XpClientPrivateIndex; + +/* Variables for the context private machinery. + * These must be initialized at compile time because + * main() calls InitOutput before InitExtensions, and the + * output drivers are likely to call AllocateContextPrivate. + * These variables are reset at CloseScreen time. CloseScreen + * is used because it occurs after FreeAllResources, and before + * the next InitOutput cycle. + */ +static int contextPrivateCount = 0; +static int contextPrivateLen = 0; +static unsigned *contextPrivateSizes = (unsigned *)NULL; +static unsigned totalContextSize = sizeof(XpContextRec); + +/* + * There are three types of resources involved. One is the resource associated + * with the context itself, with an ID specified by a printing client. The + * next is a resource created by us on the client's behalf (and unknown to + * the client) when a client inits or sets a context which allows us to + * track each client's interest in events + * on a particular context, and also allows us to clean up this interest + * record when/if the client's connection is closed. Finally, there is + * a resource created for each window that's specified in a StartPage. This + * resource carries the same ID as the window itself, and enables us to + * easily prevent the same window being referenced in multiple contexts + * simultaneously, and enables us to clean up if the window is destroyed + * before the EndPage. + */ +static RESTYPE RTclient, RTcontext, RTpage; + +/* + * allEvents is the OR of all the legal event mask bits. + */ +static CARD32 allEvents = XPPrintMask | XPAttributeMask; + + +/******************************************************************************* + * + * ExtensionInit, Driver Init functions, QueryVersion, and Dispatch procs + * + ******************************************************************************/ + +/* + * XpExtensionInit + * + * Called from InitExtensions in main() usually through miinitextension + * + */ + +void +XpExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + int i; + + RTclient = CreateNewResourceType(XpFreeClient); + RTcontext = CreateNewResourceType(XpFreeContext); + RTpage = CreateNewResourceType(XpFreePage); + if (RTclient && RTcontext && RTpage && + (extEntry = AddExtension(XP_PRINTNAME, XP_EVENTS, XP_ERRORS, + ProcXpDispatch, ProcXpSwappedDispatch, + XpResetProc, StandardMinorOpcode))) + { + XpReqCode = (unsigned char)extEntry->base; + XpEventBase = extEntry->eventBase; + XpErrorBase = extEntry->errorBase; + EventSwapVector[XpEventBase] = SwapXpNotifyEvent; + EventSwapVector[XpEventBase+1] = SwapXpAttributeEvent; + } + + if(XpGeneration != serverGeneration) + { + XpClientPrivateIndex = AllocateClientPrivateIndex(); + /* + * We allocate 0 length & simply stuff a pointer to the + * ContextRec in the DevUnion. + */ + if(AllocateClientPrivate(XpClientPrivateIndex, 0) != TRUE) + { + /* we can't alloc a client private, should we bail??? XXX */ + } + XpGeneration = serverGeneration; + } + + for(i = 0; i < MAXSCREENS; i++) + { + /* + * If a screen has registered with our extension, then we + * wrap the screen's CloseScreen function to allow us to + * reset our ContextPrivate stuff. Note that this + * requires a printing DDX to call XpRegisterInitFunc + * _before_ this extension is initialized - i.e. at screen init + * time, _not_ at root window creation time. + */ + if(XpScreens[i] != (XpScreenPtr)NULL) + { + XpScreens[i]->CloseScreen = screenInfo.screens[i]->CloseScreen; + screenInfo.screens[i]->CloseScreen = XpCloseScreen; + } + } + DeclareExtensionSecurity(XP_PRINTNAME, TRUE); +} + +static void +XpResetProc(extEntry) + ExtensionEntry extEntry; +{ + int i; + + /* + * We can't free up the XpScreens recs here, because extensions are + * closed before screens, and our CloseScreen function uses the XpScreens + * recs. + for(i = 0; i < MAXSCREENS; i++) + { + if(XpScreens[i] != (XpScreenPtr)NULL) + Xfree(XpScreens[i]); + XpScreens[i] = (XpScreenPtr)NULL; + } + */ +} + +static Bool +XpCloseScreen(index, pScreen) + int index; + ScreenPtr pScreen; +{ + Bool (* CloseScreen)(); + + CloseScreen = XpScreens[index]->CloseScreen; + if(XpScreens[index] != (XpScreenPtr)NULL) + { + XpDriverPtr pDriv, nextDriv; + + pDriv = XpScreens[index]->drivers; + while(pDriv != (XpDriverPtr)NULL) + { + nextDriv = pDriv->next; + Xfree(pDriv); + pDriv = nextDriv; + } + Xfree(XpScreens[index]); + } + XpScreens[index] = (XpScreenPtr)NULL; + + /* + * It's wasteful to call ResetContextPrivates() at every CloseScreen, + * but it's the best we know how to do for now. We do this because we + * have to wait until after all resources have been freed (so we know + * how to free the ContextRecs), and before the next InitOutput cycle. + * See dix/main.c for the order of initialization and reset. + */ + ResetContextPrivates(); + return (*CloseScreen)(index, pScreen); +} + +static void +FreeScreenEntry(pScreenEntry) + XpScreenPtr pScreenEntry; +{ + XpDriverPtr pDriver; + + pDriver = pScreenEntry->drivers; + while(pDriver != (XpDriverPtr)NULL) + { + XpDriverPtr tmp; + + tmp = pDriver->next; + xfree(pDriver); + pDriver = tmp; + } + xfree(pScreenEntry); +} + +/* + * XpRegisterInitFunc tells the print extension which screens + * are printers as opposed to displays, and what drivers are + * supported on each screen. This eliminates the need of + * allocating print-related private structures on windows on _all_ screens. + * It also hands the extension a pointer to the routine to be called + * whenever a context gets created for a particular driver on this screen. + */ +void +XpRegisterInitFunc(pScreen, driverName, initContext) + ScreenPtr pScreen; + char *driverName; + int (*initContext)(); +{ + XpDriverPtr pDriver; + + if(XpScreens[pScreen->myNum] == (XpScreenPtr)NULL) + { + if((XpScreens[pScreen->myNum] = + (XpScreenPtr) Xalloc(sizeof(XpScreenRec))) == (XpScreenPtr)NULL) + return; + XpScreens[pScreen->myNum]->CloseScreen = (Bool(*)())NULL; + XpScreens[pScreen->myNum]->drivers = (XpDriverPtr)NULL; + } + + if((pDriver = (XpDriverPtr)Xalloc(sizeof(XpDriverRec))) == + (XpDriverPtr)NULL) + return; + pDriver->next = XpScreens[pScreen->myNum]->drivers; + pDriver->name = driverName; + pDriver->CreateContext = initContext; + XpScreens[pScreen->myNum]->drivers = pDriver; +} + +static int +ProcXpDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch(stuff->data) + { + case X_PrintQueryVersion: + return ProcXpQueryVersion(client); + case X_PrintGetPrinterList: + return ProcXpGetPrinterList(client); + case X_PrintCreateContext: + return ProcXpCreateContext(client); + case X_PrintSetContext: + return ProcXpSetContext(client); + case X_PrintGetContext: + return ProcXpGetContext(client); + case X_PrintDestroyContext: + return ProcXpDestroyContext(client); + case X_PrintGetContextScreen: + return ProcXpGetContextScreen(client); + case X_PrintStartJob: + return ProcXpStartJob(client); + case X_PrintEndJob: + return ProcXpEndJob(client); + case X_PrintStartDoc: + return ProcXpStartDoc(client); + case X_PrintEndDoc: + return ProcXpEndDoc(client); + case X_PrintStartPage: + return ProcXpStartPage(client); + case X_PrintEndPage: + return ProcXpEndPage(client); + case X_PrintSelectInput: + return ProcXpSelectInput(client); + case X_PrintInputSelected: + return ProcXpInputSelected(client); + case X_PrintPutDocumentData: + return ProcXpPutDocumentData(client); + case X_PrintGetDocumentData: + return ProcXpGetDocumentData(client); + case X_PrintSetAttributes: + return ProcXpSetAttributes(client); + case X_PrintGetAttributes: + return ProcXpGetAttributes(client); + case X_PrintGetOneAttribute: + return ProcXpGetOneAttribute(client); + case X_PrintRehashPrinterList: + return ProcXpRehashPrinterList(client); + case X_PrintQueryScreens: + return ProcXpQueryScreens(client); + case X_PrintGetPageDimensions: + return ProcXpGetPageDimensions(client); + case X_PrintSetImageResolution: + return ProcXpSetImageResolution(client); + case X_PrintGetImageResolution: + return ProcXpGetImageResolution(client); + default: + return BadRequest; + } +} + +static int +ProcXpSwappedDispatch(client) + ClientPtr client; +{ + int temp; + REQUEST(xReq); + + switch(stuff->data) + { + case X_PrintQueryVersion: + swaps(&stuff->length, temp); + return ProcXpQueryVersion(client); + case X_PrintGetPrinterList: + return SProcXpGetPrinterList(client); + case X_PrintCreateContext: + return SProcXpCreateContext(client); + case X_PrintSetContext: + return SProcXpSetContext(client); + case X_PrintGetContext: + return SProcXpGetContext(client); + case X_PrintDestroyContext: + return SProcXpDestroyContext(client); + case X_PrintGetContextScreen: + return SProcXpGetContextScreen(client); + case X_PrintStartJob: + return SProcXpStartJob(client); + case X_PrintEndJob: + return SProcXpEndJob(client); + case X_PrintStartDoc: + return SProcXpStartDoc(client); + case X_PrintEndDoc: + return SProcXpEndDoc(client); + case X_PrintStartPage: + return SProcXpStartPage(client); + case X_PrintEndPage: + return SProcXpEndPage(client); + case X_PrintSelectInput: + return SProcXpSelectInput(client); + case X_PrintInputSelected: + return SProcXpInputSelected(client); + case X_PrintPutDocumentData: + return SProcXpPutDocumentData(client); + case X_PrintGetDocumentData: + return SProcXpGetDocumentData(client); + case X_PrintSetAttributes: + return SProcXpSetAttributes(client); + case X_PrintGetAttributes: + return SProcXpGetAttributes(client); + case X_PrintGetOneAttribute: + return SProcXpGetOneAttribute(client); + case X_PrintRehashPrinterList: + return SProcXpRehashPrinterList(client); + case X_PrintQueryScreens: + swaps(&stuff->length, temp); + return ProcXpQueryScreens(client); + case X_PrintGetPageDimensions: + return SProcXpGetPageDimensions(client); + case X_PrintSetImageResolution: + return SProcXpSetImageResolution(client); + case X_PrintGetImageResolution: + return SProcXpGetImageResolution(client); + default: + return BadRequest; + } +} + +static int +ProcXpQueryVersion(client) + ClientPtr client; +{ + REQUEST(xPrintQueryVersionReq); + xPrintQueryVersionReply rep; + register int n; + long l; + + REQUEST_SIZE_MATCH(xPrintQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XP_MAJOR_VERSION; + rep.minorVersion = XP_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sz_xPrintQueryVersionReply, (char *)&rep); + return client->noClientException; +} + +/******************************************************************************* + * + * GetPrinterList : Return a list of all printers associated with this + * server. Calls XpDiGetPrinterList, which is defined in + * the device-independent code in Xserver/Xprint. + * + ******************************************************************************/ + +static int +ProcXpGetPrinterList(client) + ClientPtr client; +{ + REQUEST(xPrintGetPrinterListReq); + int totalSize, numEntries; + XpDiListEntry **pList, *pEntry; + xPrintGetPrinterListReply *rep; + int n, i, totalBytes; + long l; + char *curByte; + + REQUEST_AT_LEAST_SIZE(xPrintGetPrinterListReq); + + totalSize = ((sz_xPrintGetPrinterListReq) >> 2) + + ((stuff->printerNameLen + 3) >> 2) + + ((stuff->localeLen + 3) >> 2); + if(totalSize != client->req_len) + return BadLength; + + pList = XpDiGetPrinterList(stuff->printerNameLen, (char *)(stuff + 1), + stuff->localeLen, (char *)((stuff + 1) + + QUADPAD(stuff->printerNameLen))); + + for(numEntries = 0, totalBytes = sz_xPrintGetPrinterListReply; + pList[numEntries] != (XpDiListEntry *)NULL; + numEntries++) + { + totalBytes += 2 * sizeof(CARD32); + totalBytes += QUADPAD(strlen(pList[numEntries]->name)); + totalBytes += QUADPAD(strlen(pList[numEntries]->description)); + } + + if((rep = (xPrintGetPrinterListReply *)xalloc(totalBytes)) == + (xPrintGetPrinterListReply *)NULL) + return BadAlloc; + + rep->type = X_Reply; + rep->length = (totalBytes - sz_xPrintGetPrinterListReply) >> 2; + rep->sequenceNumber = client->sequence; + rep->listCount = numEntries; + if (client->swapped) { + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, l); + swapl(&rep->listCount, l); + } + + for(i = 0, curByte = (char *)(rep + 1); i < numEntries; i++) + { + CARD32 *pCrd; + int len; + + pCrd = (CARD32 *)curByte; + len = strlen(pList[i]->name); + *pCrd = len; + if (client->swapped) + swapl((long *)curByte, l); + curByte += sizeof(CARD32); + strncpy(curByte, pList[i]->name, len); + curByte += QUADPAD(len); + + pCrd = (CARD32 *)curByte; + len = strlen(pList[i]->description); + *pCrd = len; + if (client->swapped) + swapl((long *)curByte, l); + curByte += sizeof(CARD32); + strncpy(curByte, pList[i]->description, len); + curByte += QUADPAD(len); + } + + XpDiFreePrinterList(pList); + + WriteToClient(client, totalBytes, (char *)rep); + xfree(rep); + return client->noClientException; +} + +/******************************************************************************* + * + * QueryScreens: Returns the list of screens which are associated with + * print drivers. + * + ******************************************************************************/ + +static int +ProcXpQueryScreens(client) + ClientPtr client; +{ + REQUEST(xPrintQueryScreensReq); + int i, numPrintScreens, totalSize; + WINDOW *pWinId; + xPrintQueryScreensReply *rep; + long l; + + REQUEST_SIZE_MATCH(xPrintQueryScreensReq); + + rep = (xPrintQueryScreensReply *)xalloc(sz_xPrintQueryScreensReply); + pWinId = (WINDOW *)(rep + 1); + + for(i = 0, numPrintScreens = 0, totalSize = sz_xPrintQueryScreensReply; + i < MAXSCREENS; i++) + { + /* + * If a screen has registered with our extension, then it's + * a printer screen. + */ + if(XpScreens[i] != (XpScreenPtr)NULL) + { + numPrintScreens++; + totalSize += sizeof(WINDOW); + rep = (xPrintQueryScreensReply *)xrealloc(rep, totalSize); + /* fix of bug: pWinId should be set again after reallocate rep */ + pWinId = (WINDOW *)(rep + 1); + *pWinId = WindowTable[i]->drawable.id; + if (client->swapped) + swapl((long *)pWinId, l); + } + } + + rep->type = X_Reply; + rep->sequenceNumber = client->sequence; + rep->length = (totalSize - sz_xPrintQueryScreensReply) >> 2; + rep->listCount = numPrintScreens; + if (client->swapped) + { + int n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, l); + swapl(&rep->listCount, l); + } + + WriteToClient(client, totalSize, (char *)rep); + xfree(rep); + return client->noClientException; +} + +static int +ProcXpGetPageDimensions(client) + ClientPtr client; +{ + REQUEST(xPrintGetPageDimensionsReq); + CARD16 width, height; + xRectangle rect; + xPrintGetPageDimensionsReply rep; + XpContextPtr pContext; + int result; + + REQUEST_SIZE_MATCH(xPrintGetPageDimensionsReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetMediumDimensions != (int (*)())NULL) + result = pContext->funcs.GetMediumDimensions(pContext, &width, &height); + else + return BadImplementation; + + if(pContext->funcs.GetReproducibleArea != (int (*)())NULL) + result = pContext->funcs.GetReproducibleArea(pContext, &rect); + else + return BadImplementation; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.width = width; + rep.height = height; + rep.rx = rect.x; + rep.ry = rect.y; + rep.rwidth = rect.width; + rep.rheight = rect.height; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.width, n); + swaps(&rep.height, n); + swaps(&rep.rx, n); + swaps(&rep.ry, n); + swaps(&rep.rwidth, n); + swaps(&rep.rheight, n); + } + + WriteToClient(client, sz_xPrintGetPageDimensionsReply, (char *)&rep); + return client->noClientException; +} + +static int +ProcXpSetImageResolution(client) + ClientPtr client; +{ + REQUEST(xPrintSetImageResolutionReq); + xPrintSetImageResolutionReply rep; + XpContextPtr pContext; + Bool status; + int result; + + REQUEST_SIZE_MATCH(xPrintSetImageResolutionReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + rep.prevRes = pContext->imageRes; + if(pContext->funcs.SetImageResolution != (int (*)())NULL) + result = pContext->funcs.SetImageResolution(pContext, + (int)stuff->imageRes, + &status); + else + status = FALSE; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.prevRes, n); + } + + WriteToClient(client, sz_xPrintSetImageResolutionReply, (char *)&rep); + return client->noClientException; +} + +static int +ProcXpGetImageResolution(client) + ClientPtr client; +{ + REQUEST(xPrintGetImageResolutionReq); + xPrintGetImageResolutionReply rep; + XpContextPtr pContext; + Bool status; + int result; + + REQUEST_SIZE_MATCH(xPrintGetImageResolutionReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.imageRes = pContext->imageRes; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.imageRes, n); + } + + WriteToClient(client, sz_xPrintGetImageResolutionReply, (char *)&rep); + return client->noClientException; +} + +/******************************************************************************* + * + * RehashPrinterList : Cause the server's list of printers to be rebuilt. + * This allows new printers to be added, or old ones + * deleted without needing to restart the server. + * + ******************************************************************************/ + +static int +ProcXpRehashPrinterList(client) + ClientPtr client; +{ + REQUEST(xPrintRehashPrinterListReq); + + REQUEST_SIZE_MATCH(xPrintRehashPrinterListReq); + + return XpRehashPrinterList(); +} + +/****************************************************************************** + * + * Context functions: Init, Set, Destroy, FreeContext + * AllocateContextPrivateIndex, AllocateContextPrivate + * and supporting functions. + * + * Init creates a context, creates a XpClientRec for the calling + * client, and stores the contextPtr in the client's devPrivates. + * + * Set creates a XpClientRec for the calling client, and stores the + * contextPtr in the client's devPrivates unless the context is None. + * If the context is None, then the client's connection association + * with any context is removed. + * + * Destroy frees any and all XpClientRecs associated with the context, + * frees the context itself, and removes the contextPtr from any + * relevant client devPrivates. + * + * FreeContext is called by FreeResource to free up a context. + * + ******************************************************************************/ + +/* + * CreateContext creates and initializes the memory for the context itself. + * The driver's CreateContext function + * is then called. + */ +static int +ProcXpCreateContext(client) + ClientPtr client; +{ + REQUEST(xPrintCreateContextReq); + XpScreenPtr pPrintScreen; + WindowPtr pRoot; + char *printerName, *driverName; + XpContextPtr pContext; + XpClientPtr pNewPrintClient; + int result = Success; + XpDriverPtr pDriver; + + REQUEST_AT_LEAST_SIZE(xPrintCreateContextReq); + + LEGAL_NEW_RESOURCE(stuff->contextID, client); + + /* + * Check to see if the printer name is valid. + */ + if((pRoot = XpDiValidatePrinter(stuff + 1, stuff->printerNameLen)) == + (WindowPtr)NULL) + return BadMatch; + + pPrintScreen = XpScreens[pRoot->drawable.pScreen->myNum]; + + /* + * Allocate and add the context resource. + */ + if((pContext = (XpContextPtr) xalloc(totalContextSize)) == + (XpContextPtr) NULL) + return BadAlloc; + + InitContextPrivates(pContext); + + if(AddResource(stuff->contextID, RTcontext, (pointer) pContext) + != TRUE) + { + xfree(pContext); + return BadAlloc; + } + + pContext->contextID = stuff->contextID; + pContext->clientHead = (XpClientPtr)NULL; + pContext->screenNum = pRoot->drawable.pScreen->myNum; + pContext->state = 0; + pContext->clientSlept = (ClientPtr)NULL; + pContext->imageRes = 0; + + pContext->funcs.DestroyContext = (int (*)())NULL; + pContext->funcs.StartJob = (int (*)())NULL; + pContext->funcs.EndJob = (int (*)())NULL; + pContext->funcs.StartDoc = (int (*)())NULL; + pContext->funcs.EndDoc = (int (*)())NULL; + pContext->funcs.StartPage = (int (*)())NULL; + pContext->funcs.EndPage = (int (*)())NULL; + pContext->funcs.PutDocumentData = (int (*)())NULL; + pContext->funcs.GetDocumentData = (int (*)())NULL; + pContext->funcs.GetAttributes = (char * (*)())NULL; + pContext->funcs.GetOneAttribute = (char * (*)())NULL; + pContext->funcs.SetAttributes = (int (*)())NULL; + pContext->funcs.AugmentAttributes = (int (*)())NULL; + pContext->funcs.GetMediumDimensions = (int (*)())NULL; + pContext->funcs.GetReproducibleArea = (int (*)())NULL; + pContext->funcs.SetImageResolution = (int (*)())NULL; + + if((pContext->printerName = (char *)xalloc(stuff->printerNameLen + 1)) == + (char *)NULL) + { + /* Freeing the context also causes the XpClients to be freed. */ + FreeResource(stuff->contextID, RT_NONE); + return BadAlloc; + } + strncpy(pContext->printerName, (char *)(stuff + 1), stuff->printerNameLen); + pContext->printerName[stuff->printerNameLen] = (char)'\0'; + + driverName = XpDiGetDriverName(pRoot->drawable.pScreen->myNum, + pContext->printerName); + + for(pDriver = pPrintScreen->drivers; + pDriver != (XpDriverPtr)NULL; + pDriver = pDriver->next) + { + if(!strcmp(driverName, pDriver->name)) + { + if(pDriver->CreateContext != (Bool (*)())NULL) + pDriver->CreateContext(pContext); + else + return BadImplementation; + break; + } + } + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +/* + * SetContext creates the calling client's contextClient resource, + * and stashes the contextID in the client's devPrivate. + */ +static int +ProcXpSetContext(client) + ClientPtr client; +{ + REQUEST(xPrintSetContextReq); + + XpContextPtr pContext; + XpClientPtr pPrintClient; + int result = Success; + + REQUEST_AT_LEAST_SIZE(xPrintSetContextReq); + + if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) != + (pointer)NULL) + { + /* + * Erase this client's knowledge of its old context, if any. + */ + if((pPrintClient = FindClient(pContext, client)) != (XpClientPtr)NULL) + { + XpUnsetFontResFunc(client); + + if(pPrintClient->eventMask == 0) + FreeXpClient(pPrintClient, TRUE); + } + + client->devPrivates[XpClientPrivateIndex].ptr = (pointer)NULL; + } + if(stuff->printContext == None) + return Success; + + /* + * Check to see that the supplied XID is really a valid print context + * in this server. + */ + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL) + return BadAlloc; + + client->devPrivates[XpClientPrivateIndex].ptr = pContext; + + XpSetFontResFunc(client); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +XpContextPtr +XpGetPrintContext(client) + ClientPtr client; +{ + return (client->devPrivates[XpClientPrivateIndex].ptr); +} + +static int +ProcXpGetContext(client) + ClientPtr client; +{ + REQUEST(xPrintGetContextReq); + xPrintGetContextReply rep; + + XpContextPtr pContext; + XpClientPtr pNewPrintClient; + int result = Success; + register int n; + register long l; + + REQUEST_SIZE_MATCH(xPrintGetContextReq); + + if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) == + (pointer)NULL) + rep.printContext = None; + else + rep.printContext = pContext->contextID; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.printContext, l); + } + WriteToClient(client, sz_xPrintGetContextReply, (char *)&rep); + return client->noClientException; +} + + +/* + * DestroyContext frees the context associated with the calling client. + * It operates by freeing the context resource ID, thus causing XpFreeContext + * to be called. + */ +static int +ProcXpDestroyContext(client) + ClientPtr client; +{ + REQUEST(xPrintDestroyContextReq); + + XpContextPtr pContext; + XpClientPtr pXpClient; + ClientPtr curClient; + + REQUEST_SIZE_MATCH(xPrintDestroyContextReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityDestroyAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + XpUnsetFontResFunc(client); + + FreeResource(pContext->contextID, RT_NONE); + + return Success; +} + +static int +ProcXpGetContextScreen(client) + ClientPtr client; +{ + REQUEST(xPrintGetContextScreenReq); + xPrintGetContextScreenReply rep; + XpContextPtr pContext; + int n; + long l; + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadContext; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.rootWindow = WindowTable[pContext->screenNum]->drawable.id; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.rootWindow, l); + } + + WriteToClient(client, sz_xPrintGetContextScreenReply, (char *)&rep); + return client->noClientException; +} + +/* + * XpFreeContext is the routine called by dix:FreeResource when a context + * resource ID is freed. + * It checks to see if there's a partial job pending on the context, and + * if so it calls the appropriate End procs with the cancel flag set. + * It calls the driver's DestroyContext routine to allow the driver to clean + * up any context-related memory or state. + * It calls FreeXpClient to free all the + * associated XpClientRecs and to set all the client->devPrivates to NULL. + * It frees the printer name string, and frees the context + * itself. + */ +static int +XpFreeContext(data, id) + pointer data; + XID id; +{ + XpContextPtr pContext = (XpContextPtr)data; + + /* Clean up any pending job on this context */ + if(pContext->state != 0) + { + if(pContext->state & PAGE_STARTED) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + pContext->funcs.EndPage(pContext, pWin, TRUE); + SendXpNotify(pContext, XPEndPageNotify, TRUE); + pContext->state &= ~PAGE_STARTED; + if(pPage) + pPage->context = (XpContextPtr)NULL; + } + if((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) + { + pContext->funcs.EndDoc(pContext, TRUE); + SendXpNotify(pContext, XPEndDocNotify, TRUE); + pContext->state &= ~DOC_RAW_STARTED; + pContext->state &= ~DOC_COOKED_STARTED; + } + if(pContext->funcs.EndJob != (int (*)())NULL) + { + pContext->funcs.EndJob(pContext, TRUE); + SendXpNotify(pContext, XPEndJobNotify, TRUE); + pContext->state &= ~JOB_STARTED; + pContext->state &= ~GET_DOC_DATA_STARTED; + } + } + + /* + * Tell the driver we're destroying the context + * This allows the driver to free and ContextPrivate data + */ + if(pContext->funcs.DestroyContext != (int (*)())NULL) + pContext->funcs.DestroyContext(pContext); + + /* Free up all the XpClientRecs */ + while(pContext->clientHead != (XpClientPtr)NULL) + { + FreeXpClient(pContext->clientHead, TRUE); + } + + xfree(pContext->printerName); + xfree(pContext); + return Success; /* ??? */ +} + +/* + * XpFreeClient is the routine called by dix:FreeResource when a RTclient + * is freed. It simply calls the FreeXpClient routine to do the work. + */ +static int +XpFreeClient(data, id) + pointer data; + XID id; +{ + FreeXpClient((XpClientPtr)data, TRUE); +} + +/* + * FreeXpClient + * frees the ClientRec passed in, and sets the client->devPrivates to NULL + * if the client->devPrivates points to the same context as the XpClient. + * Called from XpFreeContext(from FreeResource), and + * XpFreeClient. The boolean freeResource specifies whether or not to call + * FreeResource for the XpClientRec's XID. We should free it except if we're + * called from XpFreeClient (which is itself called from FreeResource for the + * XpClientRec's XID). + */ +static void +FreeXpClient(pXpClient, freeResource) + XpClientPtr pXpClient; + Bool freeResource; +{ + XpClientPtr pCurrent, pPrev; + XpContextPtr pContext = pXpClient->context; + + /* + * If we're freeing the clientRec associated with the context tied + * to the client's devPrivates, then we need to clear the devPrivates. + */ + if(pXpClient->client->devPrivates[XpClientPrivateIndex].ptr == + pXpClient->context) + { + pXpClient->client->devPrivates[XpClientPrivateIndex].ptr = + (pointer)NULL; + } + + for(pPrev = (XpClientPtr)NULL, pCurrent = pContext->clientHead; + pCurrent != (XpClientPtr)NULL; + pCurrent = pCurrent->pNext) + { + if(pCurrent == pXpClient) + { + if(freeResource == TRUE) + FreeResource (pCurrent->contextClientID, RTclient); + + if (pPrev != (XpClientPtr)NULL) + pPrev->pNext = pCurrent->pNext; + else + pContext->clientHead = pCurrent->pNext; + + xfree (pCurrent); + break; + } + pPrev = pCurrent; + } +} + +/* + * CreateXpClient takes a ClientPtr and returns a pointer to a + * XpClientRec which it allocates. It also initializes the Rec, + * including adding a resource on behalf of the client to enable the + * freeing of the Rec when the client's connection is closed. + */ +static XpClientPtr +CreateXpClient(client) + ClientPtr client; +{ + XpClientPtr pNewPrintClient; + XID clientResource; + + if((pNewPrintClient = (XpClientPtr)xalloc(sizeof(XpClientRec))) == + (XpClientPtr)NULL) + return (XpClientPtr)NULL; + + clientResource = FakeClientID(client->index); + if(!AddResource(clientResource, RTclient, (pointer)pNewPrintClient)) + { + xfree (pNewPrintClient); + return (XpClientPtr)NULL; + } + + pNewPrintClient->pNext = (XpClientPtr)NULL; + pNewPrintClient->client = client; + pNewPrintClient->context = (XpContextPtr)NULL; + pNewPrintClient->eventMask = 0; + pNewPrintClient->contextClientID = clientResource; + + return pNewPrintClient; +} + +/* + * XpFreePage is the routine called by dix:FreeResource to free the page + * resource built with the same ID as a page window. It checks to see + * if we're in the middle of a page, and if so calls the driver's EndPage + * function with 'cancel' set TRUE. It frees the memory associated with + * the page resource. + */ +static int +XpFreePage(data, id) + pointer data; + XID id; +{ + XpPagePtr page = (XpPagePtr)data; + int result = Success; + WindowPtr pWin = (WindowPtr )LookupIDByType(id, RT_WINDOW); + + /* Check to see if the window's being deleted in the middle of a page */ + if(page->context != (XpContextPtr)NULL && + page->context->state & PAGE_STARTED) + { + XpScreenPtr pPrintScreen = XpScreens[page->context->screenNum]; + if(page->context->funcs.EndPage != (int (*)())NULL) + result = page->context->funcs.EndPage(page->context, pWin, TRUE); + SendXpNotify(page->context, XPEndPageNotify, (int)TRUE); + page->context->pageWin = 0; /* None, NULL??? XXX */ + } + + xfree(page); + return result; +} + +/* + * ContextPrivate machinery. + * Context privates are intended for use by the drivers, allowing the + * drivers to maintain context-specific data. The driver should free + * the associated data at DestroyContext time. + */ + +static void +InitContextPrivates(context) + XpContextPtr context; +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalContextSize == sizeof(XpContextRec)) + ppriv = (DevUnion *)NULL; + else + ppriv = (DevUnion *)(context + 1); + + context->devPrivates = ppriv; + sizes = contextPrivateSizes; + ptr = (char *)(ppriv + contextPrivateLen); + for (i = contextPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } +} + +static void +ResetContextPrivates() +{ + contextPrivateCount = 0; + contextPrivateLen = 0; + xfree(contextPrivateSizes); + contextPrivateSizes = (unsigned *)NULL; + totalContextSize = sizeof(XpContextRec); + +} + +int +XpAllocateContextPrivateIndex() +{ + return contextPrivateCount++; +} + +Bool +XpAllocateContextPrivate(index, amount) + int index; + unsigned amount; +{ + unsigned oldamount; + + if (index >= contextPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(contextPrivateSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (contextPrivateLen <= index) + { + nsizes[contextPrivateLen++] = 0; + totalContextSize += sizeof(DevUnion); + } + contextPrivateSizes = nsizes; + } + oldamount = contextPrivateSizes[index]; + if (amount > oldamount) + { + contextPrivateSizes[index] = amount; + totalContextSize += (amount - oldamount); + } + return TRUE; +} + +static XpClientPtr +AcquireClient(pContext, client) + XpContextPtr pContext; + ClientPtr client; +{ + XpClientPtr pXpClient; + + if((pXpClient = FindClient(pContext, client)) != (XpClientPtr)NULL) + return pXpClient; + + if((pXpClient = CreateXpClient(client)) == (XpClientPtr)NULL) + return (XpClientPtr)NULL; + + pXpClient->context = pContext; + pXpClient->pNext = pContext->clientHead; + pContext->clientHead = pXpClient; + + return pXpClient; +} + +static XpClientPtr +FindClient(pContext, client) + XpContextPtr pContext; + ClientPtr client; +{ + XpClientPtr pXpClient; + + for(pXpClient = pContext->clientHead; pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + if(pXpClient->client == client) return pXpClient; + } + return (XpClientPtr)NULL; +} + + +/****************************************************************************** + * + * Start/End Functions: StartJob, EndJob, StartDoc, EndDoc, StartPage, EndPage + * + ******************************************************************************/ + +static int +ProcXpStartJob(client) + ClientPtr client; +{ + REQUEST(xPrintStartJobReq); + XpContextPtr pContext; + int result = Success; + XpScreenPtr pPrintScreen; + + REQUEST_SIZE_MATCH(xPrintStartJobReq); + + /* Check to see that a context has been established by this client. */ + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadContext; + + if(pContext->state != 0) + return XpErrorBase+XPBadSequence; + + if(stuff->saveData != XPSpool && stuff->saveData != XPGetData) + { + client->errorValue = stuff->saveData; + return BadValue; + } + + pPrintScreen = XpScreens[pContext->screenNum]; + if(pContext->funcs.StartJob != (int (*)())NULL) + result = pContext->funcs.StartJob(pContext, + (stuff->saveData == XPGetData)? TRUE:FALSE); + else + return BadImplementation; + + pContext->state = JOB_STARTED; + if(stuff->saveData == XPGetData) + pContext->state |= JOB_GET_DATA; + + SendXpNotify(pContext, XPStartJobNotify, FALSE); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndJob(client) + ClientPtr client; +{ + REQUEST(xPrintEndJobReq); + XpScreenPtr pPrintScreen; + WindowPtr pWin; + int result = Success; + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintEndJobReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + pPrintScreen = XpScreens[pContext->screenNum]; + + if(!(pContext->state & JOB_STARTED)) + return XpErrorBase+XPBadSequence; + + /* Check for missing EndDoc */ + if((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) + { + if(pContext->state & PAGE_STARTED) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + if(stuff->cancel != TRUE) + return XpErrorBase+XPBadSequence; + + if(pContext->funcs.EndPage != (int (*)())NULL) + result = pContext->funcs.EndPage(pContext, pWin, TRUE); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndPageNotify, TRUE); + + pContext->state &= ~PAGE_STARTED; + + if(pPage) + pPage->context = (XpContextPtr)NULL; + + if(result != Success) return result; + } + + if(pContext->funcs.EndDoc != (int (*)())NULL) + result = pContext->funcs.EndDoc(pContext, stuff->cancel); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndDocNotify, stuff->cancel); + } + + if(pContext->funcs.EndJob != (int (*)())NULL) + result = pContext->funcs.EndJob(pContext, stuff->cancel); + else + return BadImplementation; + + pContext->state = 0; + + SendXpNotify(pContext, XPEndJobNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static Bool +DoStartDoc(client, c) + ClientPtr client; + XpStDocPtr c; +{ + XpScreenPtr pPrintScreen; + int result = Success; + XpContextPtr pContext = c->pContext; + + if(c->pContext->state & JOB_GET_DATA && + !(c->pContext->state & GET_DOC_DATA_STARTED)) + { + if(!c->slept) + { + c->slept = TRUE; + ClientSleep(client, DoStartDoc, (pointer) c); + c->pContext->clientSlept = client; + } + return TRUE; + } + + pPrintScreen = XpScreens[pContext->screenNum]; + + if(pContext->funcs.StartDoc != (int (*)())NULL) + result = pContext->funcs.StartDoc(pContext, c->type); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + if(c->type == XPDocNormal) + pContext->state |= DOC_COOKED_STARTED; + else + pContext->state |= DOC_RAW_STARTED; + + SendXpNotify(pContext, XPStartDocNotify, (int)FALSE); + + xfree(c); + return TRUE; +} + +static int +ProcXpStartDoc(client) + ClientPtr client; +{ + REQUEST(xPrintStartDocReq); + XpScreenPtr pPrintScreen; + int result = Success; + XpContextPtr pContext; + XpStDocPtr c; + + REQUEST_SIZE_MATCH(xPrintStartDocReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & JOB_STARTED) || + pContext->state & DOC_RAW_STARTED || + pContext->state & DOC_COOKED_STARTED) + return XpErrorBase+XPBadSequence; + + if(stuff->type != XPDocNormal && stuff->type != XPDocRaw) + { + client->errorValue = stuff->type; + return BadValue; + } + + c = (XpStDocPtr)xalloc(sizeof(XpStDocRec)); + c->pContext = pContext; + c->type = stuff->type; + c->slept = FALSE; + (void)DoStartDoc(client, c); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndDoc(client) + ClientPtr client; +{ + REQUEST(xPrintEndDocReq); + XpScreenPtr pPrintScreen; + XpContextPtr pContext; + int result = Success; + + REQUEST_SIZE_MATCH(xPrintEndDocReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + pPrintScreen = XpScreens[pContext->screenNum]; + + if(!(pContext->state & DOC_RAW_STARTED) && + !(pContext->state & DOC_COOKED_STARTED)) + return XpErrorBase+XPBadSequence; + + if(pContext->state & PAGE_STARTED) + { + if(stuff->cancel == TRUE) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + if(pContext->funcs.EndPage != (int (*)())NULL) + result = pContext->funcs.EndPage(pContext, pWin, TRUE); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndPageNotify, TRUE); + + if(pPage) + pPage->context = (XpContextPtr)NULL; + } + else + return XpErrorBase+XPBadSequence; + if(result != Success) + return result; + } + + if(pContext->funcs.EndDoc != (int (*)())NULL) + result = pContext->funcs.EndDoc(pContext, stuff->cancel); + else + return BadImplementation; + + pContext->state &= ~DOC_RAW_STARTED; + pContext->state &= ~DOC_COOKED_STARTED; + + SendXpNotify(pContext, XPEndDocNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static Bool +DoStartPage(client, c) + ClientPtr client; + XpStPagePtr c; +{ + XpScreenPtr pPrintScreen; + WindowPtr pWin = c->pWin; + int result = Success; + XpContextPtr pContext = c->pContext; + XpPagePtr pPage; + + if(c->pContext->state & JOB_GET_DATA && + !(c->pContext->state & GET_DOC_DATA_STARTED)) + { + if(!c->slept) + { + c->slept = TRUE; + ClientSleep(client, DoStartPage, (pointer) c); + c->pContext->clientSlept = client; + } + return TRUE; + } + + if(!(pContext->state & DOC_COOKED_STARTED)) + { + /* Implied StartDoc if it was omitted */ + if(pContext->funcs.StartDoc != (int (*)())NULL) + result = pContext->funcs.StartDoc(pContext, XPDocNormal); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + if(result != Success) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, result); + return TRUE; + } + + pContext->state |= DOC_COOKED_STARTED; + SendXpNotify(pContext, XPStartDocNotify, (int)FALSE); + } + + /* ensure the window's not already being used as a page */ + if((pPage = (XpPagePtr)LookupIDByType(c->pWin->drawable.id, RTpage)) != + (XpPagePtr)NULL) + { + if(pPage->context != (XpContextPtr)NULL) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadWindow); + return TRUE; + } + } + else + { + if((pPage = (XpPagePtr)xalloc(sizeof(XpPageRec))) == (XpPagePtr)NULL) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadAlloc); + return TRUE; + } + if(AddResource(c->pWin->drawable.id, RTpage, pPage) == FALSE) + { + xfree(pPage); + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadAlloc); + return TRUE; + } + } + + pPage->context = pContext; + pContext->pageWin = c->pWin->drawable.id; + + pPrintScreen = XpScreens[pContext->screenNum]; + + + if(pContext->funcs.StartPage != (int (*)())NULL) + result = pContext->funcs.StartPage(pContext, pWin); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + pContext->state |= PAGE_STARTED; + + (void)MapWindow(pWin, client); + + SendXpNotify(pContext, XPStartPageNotify, (int)FALSE); + + return TRUE; +} + +static int +ProcXpStartPage(client) + ClientPtr client; +{ + REQUEST(xPrintStartPageReq); + XpScreenPtr pPrintScreen; + WindowPtr pWin; + int result = Success; + XpContextPtr pContext; + XpPagePtr pPage; + XpStPagePtr c; + + REQUEST_SIZE_MATCH(xPrintStartPageReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & JOB_STARTED)) + return XpErrorBase+XPBadSequence; + + /* can't have pages in a raw documented */ + if(pContext->state & DOC_RAW_STARTED) + return XpErrorBase+XPBadSequence; + + if(pContext->state & PAGE_STARTED) + return XpErrorBase+XPBadSequence; + + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin || pWin->drawable.pScreen->myNum != pContext->screenNum) + return BadWindow; + + if((c = (XpStPagePtr)xalloc(sizeof(XpStPageRec))) == (XpStPagePtr)NULL) + return BadAlloc; + c->pContext = pContext; + c->slept = FALSE; + c->pWin = pWin; + + (void)DoStartPage(client, c); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndPage(client) + ClientPtr client; +{ + REQUEST(xPrintEndPageReq); + XpScreenPtr pPrintScreen; + int result = Success; + XpContextPtr pContext; + XpPagePtr page; + WindowPtr pWin; + + REQUEST_SIZE_MATCH(xPrintEndPageReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & PAGE_STARTED)) + return XpErrorBase+XPBadSequence; + + pPrintScreen = XpScreens[pContext->screenNum]; + pWin = (WindowPtr )LookupIDByType(pContext->pageWin, RT_WINDOW); + + /* Call the ddx's EndPage proc. */ + if(pContext->funcs.EndPage != (int (*)())NULL) + result = pContext->funcs.EndPage(pContext, pWin, stuff->cancel); + else + return BadImplementation; + + if((page = (XpPagePtr)LookupIDByType(pContext->pageWin, RTpage)) != + (XpPagePtr)NULL) + page->context = (XpContextPtr)NULL; + + pContext->state &= ~PAGE_STARTED; + pContext->pageWin = 0; /* None, NULL??? XXX */ + + (void)UnmapWindow(pWin, FALSE); + + SendXpNotify(pContext, XPEndPageNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +/******************************************************************************* + * + * Document Data Functions: PutDocumentData, GetDocumentData + * + ******************************************************************************/ + +static int +ProcXpPutDocumentData(client) + ClientPtr client; +{ + REQUEST(xPrintPutDocumentDataReq); + XpContextPtr pContext; + DrawablePtr pDraw; + int result = Success; + int len, totalSize; + char *pData, *pDoc_fmt, *pOptions; + + REQUEST_AT_LEAST_SIZE(xPrintPutDocumentDataReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & DOC_RAW_STARTED) && + !(pContext->state & DOC_COOKED_STARTED)) + return XpErrorBase+XPBadSequence; + + if (stuff->drawable) { + if (pContext->state & DOC_RAW_STARTED) + return BadDrawable; + pDraw = (DrawablePtr)LookupDrawable(stuff->drawable, client); + if (!pDraw || pDraw->pScreen->myNum != pContext->screenNum) + return BadDrawable; + } else { + if (pContext->state & DOC_COOKED_STARTED) + return BadDrawable; + pDraw = NULL; + } + + pData = (char *)(&stuff[1]); + + totalSize = (stuff->len_data + 3) >> 2; + pDoc_fmt = pData + (totalSize << 2); + + totalSize += (stuff->len_fmt + 3) >> 2; + pOptions = pData + (totalSize << 2); + + totalSize += (stuff->len_options + 3) >> 2; + if((totalSize + (sz_xPrintPutDocumentDataReq >> 2)) != client->req_len) + return BadLength; + + if(pContext->funcs.PutDocumentData != (int (*)())NULL) + { + result = (*pContext->funcs.PutDocumentData)(pContext, pDraw, + pData, stuff->len_data, + pDoc_fmt, stuff->len_fmt, + pOptions, stuff->len_options, + client); + } + else + return BadImplementation; + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpGetDocumentData(client) + ClientPtr client; +{ + REQUEST(xPrintGetDocumentDataReq); + xPrintGetDocumentDataReply rep; + XpScreenPtr pPrintScreen; + XpContextPtr pContext; + int result = Success; + + REQUEST_SIZE_MATCH(xPrintGetDocumentDataReq); + + if((pContext = (XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetDocumentData == (int (*)())NULL) + return BadImplementation; + + if(!(pContext->state & JOB_GET_DATA) || + pContext->state & GET_DOC_DATA_STARTED) + return XpErrorBase+XPBadSequence; + + if(stuff->maxBufferSize <= 0) + { + client->errorValue = stuff->maxBufferSize; + return BadValue; /* gotta have a positive buffer size */ + } + + result = (*pContext->funcs.GetDocumentData)(pContext, client, + stuff->maxBufferSize); + if(result != Success) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.dataLen = 0; + rep.statusCode = 1; + rep.finishedFlag = TRUE; + if (client->swapped) { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.statusCode, l); /* XXX Why are these longs??? */ + swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */ + } + (void)WriteToClient(client,sz_xPrintGetDocumentDataReply,(char *)&rep); + } + else + pContext->state |= GET_DOC_DATA_STARTED; + + if(pContext->clientSlept != (ClientPtr)NULL) + { + ClientSignal(pContext->clientSlept); + ClientWakeup(pContext->clientSlept); + pContext->clientSlept = (ClientPtr)NULL; + } + + return result; +} + +/******************************************************************************* + * + * Attribute requests: GetAttributes, SetAttributes, GetOneAttribute + * + ******************************************************************************/ + +static int +ProcXpGetAttributes(client) + ClientPtr client; +{ + REQUEST(xPrintGetAttributesReq); + XpContextPtr pContext; + char *attrs; + xPrintGetAttributesReply *pRep; + int totalSize, n; + unsigned long l; + + REQUEST_SIZE_MATCH(xPrintGetAttributesReq); + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + if(stuff->type != XPServerAttr) + { + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetAttributes == (char *(*)())NULL) + return BadImplementation; + if((attrs = (*pContext->funcs.GetAttributes)(pContext, stuff->type)) == + (char *)NULL) + return BadAlloc; + } + else + { + if((attrs = XpGetAttributes((XpContextPtr)NULL, XPServerAttr)) == + (char *)NULL) + return BadAlloc; + } + + totalSize = sz_xPrintGetAttributesReply + QUADPAD(strlen(attrs)); + if((pRep = (xPrintGetAttributesReply *)malloc(totalSize)) == + (xPrintGetAttributesReply *)NULL) + return BadAlloc; + + pRep->type = X_Reply; + pRep->length = (totalSize - sz_xPrintGetAttributesReply) >> 2; + pRep->sequenceNumber = client->sequence; + pRep->stringLen = strlen(attrs); + + if (client->swapped) { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, l); + swapl(&pRep->stringLen, l); + } + + strncpy((char*)(pRep + 1), attrs, strlen(attrs)); + xfree(attrs); + + WriteToClient(client, totalSize, (char *)pRep); + + xfree(pRep); + + return client->noClientException; +} + +static int +ProcXpSetAttributes(client) + ClientPtr client; +{ + REQUEST(xPrintSetAttributesReq); + int result = Success; + XpContextPtr pContext; + char *attr; + + REQUEST_AT_LEAST_SIZE(xPrintSetAttributesReq); + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + /* + * Disallow changing of read-only attribute pools + */ + if(stuff->type == XPPrinterAttr || stuff->type == XPServerAttr) + return BadMatch; + + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.SetAttributes == (int (*)())NULL) + return BadImplementation; + + /* + * Check for attributes being set after their relevant phase + * has already begun (e.g. Job attributes set after StartJob). + */ + if((pContext->state & JOB_STARTED) && stuff->type == XPJobAttr) + return XpErrorBase+XPBadSequence; + if(((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) && stuff->type == XPDocAttr) + return XpErrorBase+XPBadSequence; + if((pContext->state & PAGE_STARTED) && stuff->type == XPPageAttr) + return XpErrorBase+XPBadSequence; + + if((attr = (char *)malloc(stuff->stringLen + 1)) == (char *)NULL) + return BadAlloc; + + strncpy(attr, (char *)(stuff + 1), stuff->stringLen); + attr[stuff->stringLen] = (char)'\0'; + + if(stuff->rule == XPAttrReplace) + (*pContext->funcs.SetAttributes)(pContext, stuff->type, attr); + else if(stuff->rule == XPAttrMerge) + (*pContext->funcs.AugmentAttributes)(pContext, stuff->type, attr); + else + { + client->errorValue = stuff->rule; + result = BadValue; + } + + xfree(attr); + + SendAttributeNotify(pContext, stuff->type); + + return result; +} + +static int +ProcXpGetOneAttribute(client) + ClientPtr client; +{ + REQUEST(xPrintGetOneAttributeReq); + XpContextPtr pContext; + char *value, *attrName; + xPrintGetOneAttributeReply *pRep; + int totalSize, n; + unsigned long l; + + REQUEST_AT_LEAST_SIZE(xPrintGetOneAttributeReq); + + totalSize = ((sz_xPrintGetOneAttributeReq) >> 2) + + ((stuff->nameLen + 3) >> 2); + if(totalSize != client->req_len) + return BadLength; + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + if((attrName = (char *)malloc(stuff->nameLen + 1)) == (char *)NULL) + return BadAlloc; + strncpy(attrName, (char *)(stuff+1), stuff->nameLen); + attrName[stuff->nameLen] = (char)'\0'; + + if(stuff->type != XPServerAttr) + { + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetOneAttribute == (char *(*)())NULL) + return BadImplementation; + if((value = (*pContext->funcs.GetOneAttribute)(pContext, stuff->type, + attrName)) == (char *)NULL) + return BadAlloc; + } + else + { + if((value = XpGetOneAttribute((XpContextPtr)NULL, XPServerAttr, + attrName)) == (char *)NULL) + return BadAlloc; + } + + free(attrName); + + totalSize = sz_xPrintGetOneAttributeReply + QUADPAD(strlen(value)); + if((pRep = (xPrintGetOneAttributeReply *)malloc(totalSize)) == + (xPrintGetOneAttributeReply *)NULL) + return BadAlloc; + + pRep->type = X_Reply; + pRep->length = (totalSize - sz_xPrintGetOneAttributeReply) >> 2; + pRep->sequenceNumber = client->sequence; + pRep->valueLen = strlen(value); + + if (client->swapped) { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, l); + swapl(&pRep->valueLen, l); + } + + strncpy((char*)(pRep + 1), value, strlen(value)); + + WriteToClient(client, totalSize, (char *)pRep); + + xfree(pRep); + + return client->noClientException; +} + +/******************************************************************************* + * + * Print Event requests: SelectInput InputSelected, SendXpNotify + * + ******************************************************************************/ + + +static int +ProcXpSelectInput(client) + ClientPtr client; +{ + REQUEST(xPrintSelectInputReq); + int result = Success; + XpContextPtr pContext; + XpClientPtr pPrintClient; + + REQUEST_SIZE_MATCH(xPrintSelectInputReq); + + /* + * Check to see that the supplied XID is really a valid print context + * in this server. + */ + if((pContext=(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(stuff->eventMask & ~allEvents) + { + client->errorValue = stuff->eventMask; + return BadValue; /* bogus event mask bits */ + } + + if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL) + return BadAlloc; + + pPrintClient->eventMask = stuff->eventMask; + + return result; +} + +static int +ProcXpInputSelected(client) + ClientPtr client; +{ + REQUEST(xPrintInputSelectedReq); + xPrintInputSelectedReply rep; + register int n; + long l, allMask; + WindowPtr pWin; + XpClientPtr pXpClient; + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintInputSelectedReq); + + if((pContext=(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + pXpClient = FindClient(pContext, client); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.eventMask = (pXpClient != (XpClientPtr)NULL)? pXpClient->eventMask : 0; + rep.allEventsMask = GetAllEventMasks(pContext); + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.eventMask, l); + swapl(&rep.allEventsMask, l); + } + + WriteToClient(client, sz_xPrintInputSelectedReply, (char *)&rep); + return client->noClientException; +} + +static void +SendAttributeNotify(pContext, which) + XpContextPtr pContext; + int which; +{ + XpClientPtr pXpClient; + xPrintAttributeEvent ae; + ClientPtr client; + + pXpClient = pContext->clientHead; + if(pXpClient == (XpClientPtr)NULL) + return; /* Nobody's interested in the events (or this context). */ + + for (pXpClient = pContext->clientHead; + pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + client = pXpClient->client; + if (client == serverClient || client->clientGone || + !(pXpClient->eventMask & XPAttributeMask)) + continue; + ae.type = XPAttributeNotify + XpEventBase; + ae.detail = which; + ae.printContext = pContext->contextID; + ae.sequenceNumber = client->sequence; + WriteEventsToClient (client, 1, (xEvent *) &ae); + } +} +static void +SendXpNotify(pContext, which, val) + XpContextPtr pContext; + int which; + int val; +{ + XpClientPtr pXpClient; + xPrintPrintEvent pe; + ClientPtr client; + + pXpClient = pContext->clientHead; + if(pXpClient == (XpClientPtr)NULL) + return; /* Nobody's interested in the events (or this context). */ + + for (pXpClient = pContext->clientHead; + pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + client = pXpClient->client; + if (client == serverClient || client->clientGone || + !(pXpClient->eventMask & XPPrintMask)) + continue; + pe.type = XPPrintNotify + XpEventBase; + pe.detail = which; + pe.printContext = pContext->contextID; + pe.cancel = (Bool)val; + pe.sequenceNumber = client->sequence; + WriteEventsToClient (client, 1, (xEvent *) &pe); + } +} + +static CARD32 +GetAllEventMasks(pContext) + XpContextPtr pContext; +{ + XpClientPtr pPrintClient; + CARD32 totalMask = (CARD32)0; + + for (pPrintClient = pContext->clientHead; + pPrintClient != (XpClientPtr)NULL; + pPrintClient = pPrintClient->pNext) + { + totalMask |= pPrintClient->eventMask; + } + return totalMask; +} + +/* + * XpContextOfClient - returns the XpContextPtr to the context + * associated with the specified client, or NULL if the client + * does not currently have a context set. + */ +XpContextPtr +XpContextOfClient(client) + ClientPtr client; +{ + XpContextPtr pContext; + + return (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr; +} + + +/******************************************************************************* + * + * Swap-request functions + * + ******************************************************************************/ + +static int +SProcXpCreateContext(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintCreateContextReq); + + swaps(&stuff->length, i); + swapl(&stuff->contextID, n); + swapl(&stuff->printerNameLen, n); + swapl(&stuff->localeLen, n); + return ProcXpCreateContext(client); +} + +static int +SProcXpGetPrinterList(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintGetPrinterListReq); + + swaps(&stuff->length, i); + swapl(&stuff->printerNameLen, n); + swapl(&stuff->localeLen, n); + return ProcXpGetPrinterList(client); +} + +static int +SProcXpRehashPrinterList(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintRehashPrinterListReq); + swaps(&stuff->length, i); + return ProcXpRehashPrinterList(client); +} + +static int +SProcXpSetContext(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintSetContextReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, i); + return ProcXpSetContext(client); +} + +static int +SProcXpGetContext(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintGetContextReq); + swaps(&stuff->length, i); + return ProcXpGetContext(client); +} + +static int +SProcXpDestroyContext(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintDestroyContextReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpDestroyContext(client); +} + +static int +SProcXpGetContextScreen(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintGetContextScreenReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetContextScreen(client); +} + +static int +SProcXpInputSelected(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintInputSelectedReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpInputSelected(client); +} + +static int +SProcXpStartJob(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintStartJobReq); + swaps(&stuff->length, i); + return ProcXpStartJob(client); +} + +static int +SProcXpEndJob(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintEndJobReq); + swaps(&stuff->length, i); + return ProcXpEndJob(client); +} + +static int +SProcXpStartDoc(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintStartDocReq); + swaps(&stuff->length, i); + return ProcXpStartDoc(client); +} + +static int +SProcXpEndDoc(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintEndDocReq); + swaps(&stuff->length, i); + return ProcXpEndDoc(client); +} + +static int +SProcXpStartPage(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintStartPageReq); + swaps(&stuff->length, i); + swapl(&stuff->window, n); + return ProcXpStartPage(client); +} + +static int +SProcXpEndPage(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintEndPageReq); + swaps(&stuff->length, i); + return ProcXpEndPage(client); +} + +static int +SProcXpPutDocumentData(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintPutDocumentDataReq); + swaps(&stuff->length, i); + swapl(&stuff->drawable, n); + swapl(&stuff->len_data, n); + swaps(&stuff->len_fmt, i); + swaps(&stuff->len_options, i); + return ProcXpPutDocumentData(client); +} + +static int +SProcXpGetDocumentData(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetDocumentDataReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->maxBufferSize, n); + return ProcXpGetDocumentData(client); +} + +static int +SProcXpGetAttributes(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetAttributesReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetAttributes(client); +} + +static int +SProcXpSetAttributes(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintSetAttributesReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->stringLen, n); + return ProcXpSetAttributes(client); +} + +static int +SProcXpGetOneAttribute(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetOneAttributeReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->nameLen, n); + return ProcXpGetOneAttribute(client); +} + +static int +SProcXpSelectInput(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintSelectInputReq); + swaps(&stuff->length, i); + swapl(&stuff->eventMask, n); + swapl(&stuff->printContext, n); + return ProcXpSelectInput(client); +} +static int +SProcXpGetPageDimensions(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetPageDimensionsReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetPageDimensions(client); +} +static int +SProcXpSetImageResolution(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintSetImageResolutionReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swaps(&stuff->imageRes, i); + return ProcXpSetImageResolution(client); +} +static int +SProcXpGetImageResolution(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetImageResolutionReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetImageResolution(client); +} + +static void +SwapXpNotifyEvent(src, dst) + xPrintPrintEvent *src, *dst; +{ + /* + * Swap the sequence number and context fields. + */ + cpswaps(src->sequenceNumber, dst->sequenceNumber); + cpswapl(src->printContext, dst->printContext); + + /* + * Copy the byte-long fields. + */ + dst->type = src->type; + dst->detail = src->detail; + dst->cancel = src->cancel; +} + +static void +SwapXpAttributeEvent(src, dst) + xPrintAttributeEvent *src, *dst; +{ + /* + * Swap the sequence number and context fields. + */ + cpswaps(src->sequenceNumber, dst->sequenceNumber); + cpswapl(src->printContext, dst->printContext); + + /* + * Copy the byte-long fields. + */ + dst->type = src->type; + dst->detail = src->detail; +} diff --git a/Xext/xtest.c b/Xext/xtest.c new file mode 100644 index 000000000..a07cf6186 --- /dev/null +++ b/Xext/xtest.c @@ -0,0 +1,533 @@ +/* $Xorg: xtest.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + +Copyright 1992, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#define _XTEST_SERVER_ +#include "XTest.h" +#include "xteststr.h" +#ifdef XINPUT +#include "XI.h" +#include "XIproto.h" +#define EXTENSION_EVENT_BASE 64 +#endif /* XINPUT */ + +static unsigned char XTestReqCode; +static int ProcXTestDispatch(), SProcXTestDispatch(); +static void XTestResetProc(); +static int XTestSwapFakeInput(); +CursorPtr GetSpriteCursor(); +WindowPtr GetCurrentRootWindow(); +#ifdef XINPUT +extern int DeviceValuator; +DeviceIntPtr LookupDeviceIntRec(); +#endif /* XINPUT */ + +void +XTestExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(XTestExtensionName, 0, 0, + ProcXTestDispatch, SProcXTestDispatch, + XTestResetProc, StandardMinorOpcode)) + XTestReqCode = (unsigned char)extEntry->base; +} + +/*ARGSUSED*/ +static void +XTestResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcXTestGetVersion(client) + register ClientPtr client; +{ + REQUEST(xXTestGetVersionReq); + xXTestGetVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XTestMajorVersion; + rep.minorVersion = XTestMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXTestCompareCursor(client) + register ClientPtr client; +{ + REQUEST(xXTestCompareCursorReq); + xXTestCompareCursorReply rep; + WindowPtr pWin; + CursorPtr pCursor; + register int n; + + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + pWin = (WindowPtr)LookupWindow(stuff->window, client); + if (!pWin) + return(BadWindow); + if (stuff->cursor == None) + pCursor = NullCursor; + else if (stuff->cursor == XTestCurrentCursor) + pCursor = GetSpriteCursor(); + else { + pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR); + if (!pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.same = (wCursor(pWin) == pCursor); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXTestFakeInput(client) + register ClientPtr client; +{ + REQUEST(xXTestFakeInputReq); + int nev; + int n; + xEvent *ev; + DeviceIntPtr dev; + WindowPtr root; + int type; +#ifdef XINPUT + Bool extension = FALSE; + deviceValuator *dv; + int base; + int *values; +#endif /* XINPUT */ + + nev = (stuff->length << 2) - sizeof(xReq); + if ((nev % sizeof(xEvent)) || !nev) + return BadLength; + nev /= sizeof(xEvent); + UpdateCurrentTime(); + ev = (xEvent *)&((xReq *)stuff)[1]; + type = ev->u.u.type & 0177; +#ifdef XINPUT + if (type >= EXTENSION_EVENT_BASE) + { + type -= DeviceValuator; + switch (type) { + case XI_DeviceKeyPress: + case XI_DeviceKeyRelease: + case XI_DeviceButtonPress: + case XI_DeviceButtonRelease: + case XI_DeviceMotionNotify: + case XI_ProximityIn: + case XI_ProximityOut: + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + if (nev == 1 && type == XI_DeviceMotionNotify) + return BadLength; + if (type == XI_DeviceMotionNotify) + base = ((deviceValuator *)(ev+1))->first_valuator; + else + base = 0; + for (n = 1; n < nev; n++) + { + dv = (deviceValuator *)(ev + n); + if (dv->type != DeviceValuator) + { + client->errorValue = dv->type; + return BadValue; + } + if (dv->first_valuator != base) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + if (!dv->num_valuators || dv->num_valuators > 6) + { + client->errorValue = dv->num_valuators; + return BadValue; + } + base += dv->num_valuators; + } + type = type - XI_DeviceKeyPress + KeyPress; + extension = TRUE; + } + else +#endif /* XINPUT */ + { + if (nev != 1) + return BadLength; + switch (type) + { + case KeyPress: + case KeyRelease: + case MotionNotify: + case ButtonPress: + case ButtonRelease: + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + } + if (ev->u.keyButtonPointer.time) + { + TimeStamp activateTime; + CARD32 ms; + + activateTime = currentTime; + ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; + if (ms < activateTime.milliseconds) + activateTime.months++; + activateTime.milliseconds = ms; + ev->u.keyButtonPointer.time = 0; + + /* see mbuf.c:QueueDisplayRequest for code similar to this */ + + if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) + { + return BadAlloc; + } + /* swap the request back so we can simply re-execute it */ + if (client->swapped) + { + (void) XTestSwapFakeInput(client, (xReq *)stuff); + swaps(&stuff->length, n); + } + ResetCurrentRequest (client); + client->sequence--; + return Success; + } +#ifdef XINPUT + if (extension) + { + dev = LookupDeviceIntRec(stuff->deviceid & 0177); + if (!dev) + { + client->errorValue = stuff->deviceid & 0177; + return BadValue; + } + if (nev > 1) + { + dv = (deviceValuator *)(ev + 1); + if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + if (dv->first_valuator + dv->num_valuators > + dev->valuator->numAxes) + { + client->errorValue = dv->num_valuators; + return BadValue; + } + } + } +#endif /* XINPUT */ + switch (type) + { + case KeyPress: + case KeyRelease: +#ifdef XINPUT + if (!extension) +#endif /* XINPUT */ + dev = (DeviceIntPtr)LookupKeyboardDevice(); + if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode || + ev->u.u.detail > dev->key->curKeySyms.maxKeyCode) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + case MotionNotify: +#ifdef XINPUT + if (extension) + { + if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute) + { + values = dev->valuator->axisVal + dv->first_valuator; + for (n = 1; n < nev; n++) + { + dv = (deviceValuator *)(ev + n); + switch (dv->num_valuators) + { + case 6: + dv->valuator5 += values[5]; + case 5: + dv->valuator4 += values[4]; + case 4: + dv->valuator3 += values[3]; + case 3: + dv->valuator2 += values[2]; + case 2: + dv->valuator1 += values[1]; + case 1: + dv->valuator0 += values[0]; + } + values += 6; + } + } + break; + } +#endif /* XINPUT */ + dev = (DeviceIntPtr)LookupPointerDevice(); + if (ev->u.keyButtonPointer.root == None) + root = GetCurrentRootWindow(); + else + { + root = LookupWindow(ev->u.keyButtonPointer.root, client); + if (!root) + return BadWindow; + if (root->parent) + { + client->errorValue = ev->u.keyButtonPointer.root; + return BadValue; + } + } + if (ev->u.u.detail == xTrue) + { + int x, y; + GetSpritePosition(&x, &y); + ev->u.keyButtonPointer.rootX += x; + ev->u.keyButtonPointer.rootY += y; + } + else if (ev->u.u.detail != xFalse) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + if (ev->u.keyButtonPointer.rootX < 0) + ev->u.keyButtonPointer.rootX = 0; + else if (ev->u.keyButtonPointer.rootX >= root->drawable.width) + ev->u.keyButtonPointer.rootX = root->drawable.width - 1; + if (ev->u.keyButtonPointer.rootY < 0) + ev->u.keyButtonPointer.rootY = 0; + else if (ev->u.keyButtonPointer.rootY >= root->drawable.height) + ev->u.keyButtonPointer.rootY = root->drawable.height - 1; + if (root != GetCurrentRootWindow()) + { + NewCurrentScreen(root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, + ev->u.keyButtonPointer.rootY); + return client->noClientException; + } + (*root->drawable.pScreen->SetCursorPosition) + (root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, + ev->u.keyButtonPointer.rootY, FALSE); + break; + case ButtonPress: + case ButtonRelease: +#ifdef XINPUT + if (!extension) +#endif /* XINPUT */ + dev = (DeviceIntPtr)LookupPointerDevice(); + if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + } + if (screenIsSaved == SCREEN_SAVER_ON) + SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset); + ev->u.keyButtonPointer.time = currentTime.milliseconds; + (*dev->public.processInputProc)(ev, dev, nev); + return client->noClientException; +} + +static int +ProcXTestGrabControl(client) + register ClientPtr client; +{ + REQUEST(xXTestGrabControlReq); + + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) + { + client->errorValue = stuff->impervious; + return(BadValue); + } + if (stuff->impervious) + MakeClientGrabImpervious(client); + else + MakeClientGrabPervious(client); + return(client->noClientException); +} + +static int +ProcXTestDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return ProcXTestGetVersion(client); + case X_XTestCompareCursor: + return ProcXTestCompareCursor(client); + case X_XTestFakeInput: + return ProcXTestFakeInput(client); + case X_XTestGrabControl: + return ProcXTestGrabControl(client); + default: + return BadRequest; + } +} + +static int +SProcXTestGetVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXTestGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + swaps(&stuff->minorVersion, n); + return ProcXTestGetVersion(client); +} + +static int +SProcXTestCompareCursor(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXTestCompareCursorReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + swapl(&stuff->window, n); + swapl(&stuff->cursor, n); + return ProcXTestCompareCursor(client); +} + +static int +XTestSwapFakeInput(client, req) + register ClientPtr client; + xReq *req; +{ + register int nev; + register xEvent *ev; + xEvent sev; + void (*proc)(), NotImplemented(); + + nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); + for (ev = (xEvent *)&req[1]; --nev >= 0; ev++) + { + /* Swap event */ + proc = EventSwapVector[ev->u.u.type & 0177]; + /* no swapping proc; invalid event type? */ + if (!proc || (int (*)()) proc == (int (*)()) NotImplemented) { + client->errorValue = ev->u.u.type; + return BadValue; + } + (*proc)(ev, &sev); + *ev = sev; + } + return Success; +} + +static int +SProcXTestFakeInput(client) + register ClientPtr client; +{ + register int n; + REQUEST(xReq); + + swaps(&stuff->length, n); + n = XTestSwapFakeInput(client, stuff); + if (n != Success) + return n; + return ProcXTestFakeInput(client); +} + +static int +SProcXTestGrabControl(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXTestGrabControlReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + return ProcXTestGrabControl(client); +} + +static int +SProcXTestDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return SProcXTestGetVersion(client); + case X_XTestCompareCursor: + return SProcXTestCompareCursor(client); + case X_XTestFakeInput: + return SProcXTestFakeInput(client); + case X_XTestGrabControl: + return SProcXTestGrabControl(client); + default: + return BadRequest; + } +} diff --git a/Xext/xtest1dd.c b/Xext/xtest1dd.c new file mode 100644 index 000000000..38c977557 --- /dev/null +++ b/Xext/xtest1dd.c @@ -0,0 +1,1613 @@ +/* $Xorg: xtest1dd.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + * File: xtest1dd.c + * + * This file contains the device dependent parts of the input + * synthesis extension. + */ + +/* + + +Copyright 1986, 1987, 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation + +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 name of Hewlett-Packard not be used in +advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +Hewlett-Packard makes no representations about the +suitability of this software for any purpose. It is provided +"as is" without express or implied warranty. + +This software is not subject to any license of the American +Telephone and Telegraph Company or of the Regents of the +University of California. + +*/ + +/*************************************************************** + * include files + ***************************************************************/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#include +#include "Xos.h" +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#define XTestSERVER_SIDE +#include "xtestext1.h" + +/*************************************************************** + * defines + ***************************************************************/ + +/* + * the size of the fake input action array + */ +#define ACTION_ARRAY_SIZE 100 + +/*************************************************************** + * externals + ***************************************************************/ + +/* + * Holds the xTestInputAction event type code. + * This is defined in xtestext1di.c. + */ +extern int XTestInputActionType; +/* + * Holds the xTestFakeAck event type code. + * This is defined in xtestext1di.c. + */ +extern int XTestFakeAckType; +/* + * used in the WriteReplyToClient macro + */ +extern void (* ReplySwapVector[256]) (); + +extern int exclusive_steal; + +/*************************************************************** + * variables + ***************************************************************/ + +/* + * array to hold fake input actions + */ +struct { + /* + * holds the action type, one of: XTestDELAY_ACTION, + * XTestKEY_ACTION, XTestMOTION_ACTION, XTestJUMP_ACTION + */ + CARD8 type; + /* + * holds the device type, in the range 0 to 15 + */ + CARD8 device; + /* + * for XTestKEY_ACTION type, holds the keycode + */ + CARD8 keycode; + /* + * for XTestKEY_ACTION type, holds the key up/down state + */ + CARD8 keystate; + /* + * for XTestMOTION_ACTION and XTestJUMP_ACTION types, + * holds the x and y coordinates to move the mouse to + */ + int x; + int y; + /* + * holds the time to delay (in milliseconds) before performing + * the action + */ + CARD32 delay_time; +}action_array[ACTION_ARRAY_SIZE]; + +/* + * write index for input action array + */ +static int write_index = 0; +/* + * read index for input action array + */ +static int read_index = 0; +/* + * this is where the input actions are accumulated until they are sent + * to a client (in a wire event) + */ +static xTestInputActionEvent input_action_packet; +/* + * holds the index (in bytes) into the input actions buffer in the + * current input action event + */ +static int packet_index; +/* + * set to 1 when the input action event is full and needs to be sent to the + * client + */ +static int input_action_event_full = 0; +/* + * logical x position of the mouse during input action gathering + */ +short xtest_mousex; +/* + * logical y position of the mouse during input action gathering + */ +short xtest_mousey; +/* + * logical x position of the mouse during input action playback + */ +static short mx; +/* + * logical y position of the mouse during input action playback + */ +static short my; +/* + * logical x position of the mouse while we are reading fake input actions + * from the client and putting them into the fake input action array + */ +static short pmousex; +/* + * logical y position of the mouse while we are reading fake input actions + * from the client and putting them into the fake input action array + */ +static short pmousey; +/* + * The playback_on flag is set to 1 while there are input actions in the + * input action array. It is set to 0 when the server has received all of + * the user actions. + */ +int playback_on = 0; +/* + * identity of the client using XTestGetInput to get user input actions + */ +ClientPtr current_xtest_client; +/* + * if 1 send multiple input actions per XTestInputAction event; + * if 0 send one input action per XTestInputAction event + */ +static char packed_mode; +/* + * identity of the client using the XTestFakeInput function to send some + * fake input actions to the server + */ +ClientPtr playback_client = NULL; +/* + * Set to 1 when the XTestFAKE_ACK_REQUEST flag is set in a XTestFakeInput + * request. Set back to 0 when all of the input actions have been sent + * to the server. + */ +static int acknowledge = 0; +/* + * The server's idea of the current time is saved in these variables when + * a XTestFakeInput request is received. It is restored when all fake input + * actions are sent to the server or when the playback client disconnects. + */ +static int saved_sec; +static int saved_usec; +/* + * Set to 1 when there is a valid time in saved_sec and saved_usec. + */ +static int time_saved = 0; +/* + * holds the extension's notion of what the current time is while it is + * sending input actions to a client + */ +static struct timeval current_time; +/* + * holds the time when the extension should place the next fake input action + * into the server's normal events queue + */ +static struct timeval play_time; +/* + * set to 1 when play_time is first set, cleared to 0 when the + * client using the extension disconnects, or when XTestReset is called + */ +static char play_clock = 0; +/* + * holds the amount of time left until the next input action from the + * input action array can be sent to the server + */ +static struct timeval rtime; +/* + * Set to 1 after the extension is done waiting for the correct time delay + * for an input action to be sent to the server. Remains a 1 until the time + * delay for the next input action is computed. Then set to 0 if the + * extension has to wait for the correct time delay. + */ +static int go_for_next = 1; +/* + * needed to restore waitime if playback is to be aborted + */ +static struct timeval *restorewait; +/* + * tmon special command key + * + * To use the test monitor program (called tmon) efficiently, it is + * desirable to have the extension be able to recognize a special "trigger" + * key. If the extension did not do this, tmon would have to have the + * extension send all keyboard user input actions exclusively to tmon, + * only to have tmon send them right back if they were not the command key. + * + * If the extension can recognize the command key, then tmon can let the + * extension handle keyboard user input actions normally until the command + * key is pressed (and released), and only then have the extension start + * sending keyboard user input actions exclusively to tmon. + * + * Any key on the keyboard can be used for this command key. It is most + * convenient if it is a low-frequency key. If you want to generate a + * normal occurrance of this key to a client, just hit it twice. Tmon + * will recognize the first occurrance of the key, take control of the input + * actions, and wait for certain keys. If it sees another occurrance of the + * command key, it will send one occurrance of the command key to the + * extension, and go back to waiting. + * + * set and also referenced in device layer + * XXX there should be a way to set this through the protocol + */ +KeyCode xtest_command_key = 0; + +/*************************************************************** + * function declarations + ***************************************************************/ + +void flush_input_actions(); +void XTestStealJumpData(); +void XTestGenerateEvent(); +void XTestGetPointerPos(); +void XTestJumpPointer(); + +static void parse_key_fake(); +static void parse_motion_fake(); +static void parse_jump_fake(); +static void parse_delay_fake(); +static void send_ack(); +static void start_play_clock(); +static void compute_action_time(); +static int find_residual_time(); + +static CARD16 check_time_event(); +static CARD32 current_ms(); +static int there_is_room(); + +/****************************************************************************** + * + * stop_stealing_input + * + * Stop stealing input actions. + */ +void +stop_stealing_input() +{ +/* + * put any code that you might need to stop stealing input actions here + */ + if (packet_index != 0) + { + /* + * if there is a partially full input action event waiting + * when this function is called, send it to the client + */ + flush_input_actions(); + } +} + +/****************************************************************************** + * + * steal_input + * + * Start stealing input actions and sending them to the passed-in client. + */ +void +steal_input(client, mode) +/* + * which client is to receive the input action events + */ +ClientPtr client; +/* + * what input action packing mode to use. one of 0, XTestPACKED_MOTION, + * or XTestPACKED_ACTIONS; optionally 'or'ed with XTestEXCLUSIVE, + */ +CARD32 mode; +{ + if (packet_index != 0) + { + /* + * if there is a partially full input action event waiting + * when this function is called, send it to the client + */ + flush_input_actions(); + } + else + { + /* + * otherwise, set up a new input action event + */ + input_action_packet.type = XTestInputActionType; + packet_index = 0; + } + /* + * set up the new input action packing mode + */ + packed_mode = mode & ~(XTestEXCLUSIVE); + /* + * keep track of where the mouse is + */ + XTestGetPointerPos(&xtest_mousex, &xtest_mousey); + /* + * keep track of which client is getting input actions + */ + current_xtest_client = client; + /* + * find out what time it is + */ + X_GETTIMEOFDAY(¤t_time); + /* + * jump to the initial position of the mouse, using a device type of 0. + */ + XTestStealJumpData(xtest_mousex, xtest_mousey, 0); +} + +/****************************************************************************** + * + * flush_input_actions + * + * Write the input actions event to the current requesting client + * and re-initialize the input action event. + */ +void +flush_input_actions() +{ + /* + * pointer to the input action event + */ + char *rep; + /* + * loop index + */ + int i; + + if (packet_index == 0) + { + /* + * empty input actions event + */ + return; + } + else if (packet_index < XTestACTIONS_SIZE) + { + /* + * fill to the end of the input actions event with 0's + */ + for (i = packet_index; i sequence; + /* + * send the input action event to the client + */ + WriteEventsToClient(current_xtest_client, 1, (xEvent *) rep); + /* + * re-initialize the input action event + */ + input_action_event_full = 0; + input_action_packet.type = XTestInputActionType; + packet_index = 0; +} + +/****************************************************************************** + * + * XTestStealJumpData + * + * Create one or more input actions and put them in the input action + * event. The input actions will be an (maybe) XTestDELAY_ACTION + * and an XTestJUMP_ACTION. + */ +void +XTestStealJumpData(jx, jy, dev_type) +/* + * the x and y coordinates to jump to + */ +short jx; +short jy; +/* + * which device caused the jump + */ +int dev_type; +{ + XTestJumpInfo *jmp_ptr; + /* + * time delta (in ms) from previous event + */ + CARD16 tchar; + + /* + * Get the time delta from the previous event. If needed, + * the check_time_event routine will put an XTestDELAY_ACTION + * type action in the input action event. + */ + tchar = check_time_event(); + if (!there_is_room(sizeof(XTestJumpInfo))) + { + /* + * If there isn't room in the input action event for + * an XTestJUMP_ACTION, then send that event to the + * client and start filling an empty one. + */ + flush_input_actions(); + } + /* + * update the logical mouse position + */ + xtest_mousex = jx; + xtest_mousey = jy; + /* + * point jmp_ptr to the correct place in the input action event + */ + jmp_ptr = (XTestJumpInfo *) + &(input_action_packet.actions[packet_index]); + /* + * compute the input action header + */ + jmp_ptr->header = (XTestPackDeviceID(dev_type) | XTestJUMP_ACTION); + /* + * set the x and y coordinates to jump to in the input action + */ + jmp_ptr->jumpx = jx; + jmp_ptr->jumpy = jy; + /* + * set the delay time in the input action + */ + jmp_ptr->delay_time = tchar; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + sizeof(XTestJumpInfo); + if (packed_mode == 0) + { + /* + * if input actions are not packed, send the input + * action event to the client + */ + flush_input_actions(); + } +} + +/****************************************************************************** + * + * current_ms + * + * Returns the number of milliseconds from the passed-in time to the + * current time, and then updates the passed-in time to the current time. + */ +static CARD32 +current_ms(otime) +struct timeval *otime; +{ + struct timeval tval; + unsigned long ctime; + unsigned long sec; + unsigned long usec; + + /* + * get the current time + */ + X_GETTIMEOFDAY(&tval); + if (tval.tv_usec < otime->tv_usec) + { + /* + * borrow a second's worth of microseconds if needed + */ + usec = tval.tv_usec - otime->tv_usec + 1000000; + sec = tval.tv_sec - 1 - otime->tv_sec; + } + else + { + usec = tval.tv_usec - otime->tv_usec; + sec = tval.tv_sec - otime->tv_sec; + } + /* + * update the passed-in time to the new time + */ + *otime = tval; + /* + * compute the number of milliseconds contained in + * 'sec' seconds and 'usec' microseconds + */ + ctime = (sec * 1000000 + usec) / 1000; + return (ctime); +} + +/****************************************************************************** + * + * check_time_event + * + * If time delta is > XTestSHORT_DELAY_TIME then insert a time event + * and return 0; else return the delay time. + */ +static CARD16 +check_time_event() +{ + CARD32 tstamp; + CARD16 tchar; + XTestDelayInfo *tptr; + + /* + * get the number of milliseconds between input actions + */ + tstamp = current_ms(¤t_time); + /* + * if the number of milliseconds is too large to fit in a CARD16, + * then add a XTestDELAY_ACTION to the input action event. + */ + if (tstamp > XTestSHORT_DELAY_TIME) + { + /* + * If there isn't room in the input action event for + * an XTestDELAY_ACTION, then send that event to the + * client and start filling an empty one. + */ + if (!there_is_room(sizeof(XTestDelayInfo))) + { + flush_input_actions(); + } + /* + * point tptr to the correct place in the input action event + */ + tptr = (XTestDelayInfo *) + (&(input_action_packet.actions[packet_index])); + /* + * compute the input action header + */ + tptr->header = XTestPackDeviceID(XTestDELAY_DEVICE_ID) | + XTestDELAY_ACTION; + /* + * set the delay time in the input action + */ + tptr->delay_time = tstamp; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + (sizeof(XTestDelayInfo)); + if (packed_mode != XTestPACKED_ACTIONS) + { + /* + * if input actions are not packed, send the input + * action event to the client + */ + flush_input_actions(); + } + /* + * set the returned delay time to 0 + */ + tchar = 0; + } + else + { + /* + * set the returned delay time to the computed delay time + */ + tchar = tstamp; + } + return(tchar); +} + +/****************************************************************************** + * + * there_is_room + * + * Checks if there is room in the input_action_packet for an input action + * of the size actsize bytes. Returns 1 if there is space, 0 otherwise. + * + */ +static int +there_is_room(actsize) +/* + * the number of bytes of space needed + */ +int actsize; +{ + if ((packet_index + actsize) > XTestACTIONS_SIZE) + { + input_action_event_full = 1; + return(0); + } + else + { + return(1); + } +} + +/****************************************************************************** + * + * XTestStealMotionData + * + * Put motion information from the locator into an input action. + * + * called from x_hil.c + */ +void +XTestStealMotionData(dx, dy, dev_type, mx, my) +/* + * the x and y delta motion of the locator + */ +short dx; +short dy; +/* + * which locator did the moving + */ +int dev_type; +/* + * the x and y position of the locator before the delta motion + */ +short mx; +short my; +{ + /* + * pointer to a XTestMOTION_ACTION input action + */ + XTestMotionInfo *fm; + /* + * time delta from previous event + */ + CARD16 tchar; + + /* + * if the current position of the locator is not the same as + * the logical position, then update the logical position + */ + if ((mx != xtest_mousex) || (my != xtest_mousey)) + { + XTestStealJumpData(mx, my, dev_type); + } + /* + * if the delta motion is outside the range that can + * be held in a motion input action, use a jump input action + */ + if ((dx > XTestMOTION_MAX) || (dx < XTestMOTION_MIN) || + (dy > XTestMOTION_MAX) || (dy < XTestMOTION_MIN)) + { + XTestStealJumpData((xtest_mousex + dx), + (xtest_mousey + dy), dev_type); + } + else + { + /* + * compute the new logical position of the mouse + */ + xtest_mousex += dx; + xtest_mousey += dy; + /* + * Get the time delta from the previous event. If needed, + * the check_time_event routine will put an XTestDELAY_ACTION + * type action in the input action event. + */ + tchar = check_time_event(); + /* + * If there isn't room in the input action event for + * an XTestDELAY_ACTION, then send that event to the + * client and start filling an empty one. + */ + if (!there_is_room(sizeof(XTestMotionInfo))) + { + flush_input_actions(); + /* + * point fm to the correct place in the input action event + */ + } + fm = (XTestMotionInfo *) + &(input_action_packet.actions[packet_index]); + /* + * compute the input action header + */ + fm->header = XTestMOTION_ACTION; + if (dx < 0) + { + fm->header |= XTestX_NEGATIVE; + dx = abs(dx); + } + if (dy < 0) + { + fm->header |= XTestY_NEGATIVE; + dy = abs(dy); + } + fm->header |= XTestPackDeviceID(dev_type); + /* + * compute the motion data byte + */ + fm->motion_data = XTestPackYMotionValue(dy); + fm->motion_data |= XTestPackXMotionValue(dx); + /* + * set the delay time in the input action + */ + fm->delay_time = tchar; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + sizeof(XTestMotionInfo); + if (packed_mode == 0) + { + /* + * if input actions are not packed, send the input + * action event to the client + */ + flush_input_actions(); + } + + } +} + +/****************************************************************************** + * + * XTestStealKeyData + * + * Place this key data in the input_action_packet. + * + */ +Bool +XTestStealKeyData(keycode, keystate, dev_type, locx, locy) +/* + * which key/button moved + */ +CARD8 keycode; +/* + * whether the key/button was pressed or released + */ +char keystate; +/* + * which device caused the input action + */ +int dev_type; +/* + * the x and y coordinates of the locator when the action happenned + */ +short locx; +short locy; +{ + /* + * pointer to key/button motion input action + */ + XTestKeyInfo *kp; + /* + * time delta from previous event + */ + CARD16 tchar; + char keytrans; + + /* + * update the logical position of the locator if the physical position + * of the locator is not the same as the logical position. + */ + if ((locx != xtest_mousex) || (locy != xtest_mousey)) + { + XTestStealJumpData(locx, locy, dev_type); + } + /* + * Get the time delta from the previous event. If needed, + * the check_time_event routine will put an XTestDELAY_ACTION + * type action in the input action event. + */ + tchar = check_time_event(); + if (!there_is_room(sizeof(XTestKeyInfo))) + { + /* + * If there isn't room in the input action event for + * an XTestDELAY_ACTION, then send that event to the + * client and start filling an empty one. + */ + flush_input_actions(); + } + /* + * point kp to the correct place in the input action event + */ + kp = (XTestKeyInfo *) + (&(input_action_packet.actions[packet_index])); + /* + * compute the input action header + */ + kp->header = XTestPackDeviceID(dev_type); + if ((keystate == KeyRelease) || (keystate == ButtonRelease)) + { + keytrans = XTestKEY_UP; + } + else if ((keystate == KeyPress) || (keystate == ButtonPress)) + { + keytrans = XTestKEY_DOWN; + } + else + { + printf("%s: invalid key/button state %d.\n", + XTestEXTENSION_NAME, + keystate); + } + kp->header = kp->header | keytrans | XTestKEY_ACTION; + /* + * set the keycode in the input action + */ + kp->keycode = keycode; + /* + * set the delay time in the input action + */ + kp->delay_time = tchar; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + sizeof(XTestKeyInfo); + /* + * if the command key has been released or input actions are not + * packed, send the input action event to the client + */ + if(((keycode == xtest_command_key) && (keystate == KeyRelease)) || + (packed_mode != XTestPACKED_ACTIONS)) + { + flush_input_actions(); + } + /* return TRUE if the event should be passed on to DIX */ + if (exclusive_steal) + return ((keystate == KeyRelease) && + (keycode == xtest_command_key)); + else + return ((keystate != KeyRelease) || + (keycode != xtest_command_key)); +} + +/****************************************************************************** + * + * parse_fake_input + * + * Parsing routine for a XTestFakeInput request. It will take a request + * and parse its contents into the input action array. Eventually the + * XTestProcessInputAction routine will be called to take input actions + * from the input action array and send them to the server to be handled. + */ +void +parse_fake_input(client, req) +/* + * which client did the XTestFakeInput request + */ +ClientPtr client; +/* + * a pointer to the xTestFakeInputReq structure sent by the client + */ +char *req; +{ + /* + * if set to 1, done processing input actions from the request + */ + int done = 0; + /* + * type of input action + */ + CARD8 action_type; + /* + * device type + */ + CARD8 dev_type; + /* + * pointer to an xTestFakeInputReq structure + */ + xTestFakeInputReq *request; + /* + * holds the index into the action list in the request + */ + int parse_index; + + /* + * get a correct-type pointer to the client-supplied request data + */ + request = (xTestFakeInputReq *) req; + /* + * save the acknowledge requested state for use in + * XTestProcessInputAction + */ + acknowledge = request->ack; + /* + * set up an index into the action list in the request + */ + parse_index = 0; + if (write_index >= ACTION_ARRAY_SIZE) + { + /* + * if the input action array is full, don't add any more + */ + done = 1; + } + while (!done) + { + /* + * get the type of input action in the list + */ + action_type = (request->action_list[parse_index]) + & XTestACTION_TYPE_MASK; + /* + * get the type of device in the list + */ + dev_type = XTestUnpackDeviceID(request->action_list[parse_index]); + /* + * process the input action appropriately + */ + switch (action_type) + { + case XTestKEY_ACTION: + parse_key_fake((XTestKeyInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + sizeof(XTestKeyInfo); + break; + case XTestMOTION_ACTION: + parse_motion_fake((XTestMotionInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + sizeof(XTestMotionInfo); + break; + case XTestJUMP_ACTION: + parse_jump_fake((XTestJumpInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + sizeof(XTestJumpInfo); + break; + case XTestDELAY_ACTION: + if (dev_type == XTestDELAY_DEVICE_ID) + { + parse_delay_fake((XTestDelayInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + + sizeof(XTestDelayInfo); + } + else + { + /* + * An invalid input action header byte has + * been detected, so there are no more + * input actions in this request. + * The intended invalid action header byte + * for this case should have a value of 0. + */ + done = 1; + } + break; + } + if (parse_index >= XTestMAX_ACTION_LIST_SIZE) + { + /* + * entire XTestFakeInput request has been processed + */ + done = 1; + } + if (write_index >= ACTION_ARRAY_SIZE) + { + /* + * no room in the input actions array + */ + done = 1; + } + } + if (write_index > read_index) + { + /* + * there are fake input actions in the input action array + * to be given to the server + */ + playback_on = 1; + playback_client = client; + } +} + +/****************************************************************************** + * + * parse_key_fake + * + * Called from parse_fake_input. + * + * Copy the fake key input action from its packed form into the array of + * pending input events. + */ +static void +parse_key_fake(fkey) +XTestKeyInfo *fkey; +{ + action_array[write_index].type = XTestKEY_ACTION; + action_array[write_index].device = XTestUnpackDeviceID(fkey->header); + action_array[write_index].keycode = fkey->keycode; + action_array[write_index].keystate = fkey->header & XTestKEY_STATE_MASK; + action_array[write_index].delay_time = fkey->delay_time; + write_index++; +} + +/****************************************************************************** + * + * parse_motion_fake + * + * Called from parse_fake_input. + * + * Copy the fake motion input action from its packed form into the array of + * pending input events. + */ +static void +parse_motion_fake(fmotion) +XTestMotionInfo *fmotion; +{ + int dx; + int dy; + + dx = (XTestUnpackXMotionValue(fmotion->motion_data)); + dy = (XTestUnpackYMotionValue(fmotion->motion_data)); + if (((fmotion->header) & XTestX_SIGN_BIT_MASK) == XTestX_NEGATIVE) + { + pmousex -= dx; + } + else + { + pmousex += dx; + } + if (((fmotion->header) & XTestY_SIGN_BIT_MASK) == XTestY_NEGATIVE) + { + pmousey -= dy; + } + else + { + pmousey += dy; + } + action_array[write_index].type = XTestJUMP_ACTION; + action_array[write_index].device = XTestUnpackDeviceID(fmotion->header); + action_array[write_index].x = pmousex; + action_array[write_index].y = pmousey; + action_array[write_index].delay_time = fmotion->delay_time; + write_index++; +} + +/****************************************************************************** + * + * parse_jump_fake + * + * Called from parse_fake_input. + * + * Copy the fake jump input action from its packed form into the array of + * pending input events. + */ +static void +parse_jump_fake(fjump) +XTestJumpInfo *fjump; +{ + pmousex = fjump->jumpx; + pmousey = fjump->jumpy; + action_array[write_index].type = XTestJUMP_ACTION; + action_array[write_index].device = XTestUnpackDeviceID(fjump->header); + action_array[write_index].x = pmousex; + action_array[write_index].y = pmousey; + action_array[write_index].delay_time = fjump->delay_time; + write_index++; +} + +/****************************************************************************** + * + * parse_delay_fake + * + * Called from parse_fake_input. + * + * Copy the fake delay input action from its packed form into the array of + * pending input events. + */ +static void +parse_delay_fake(tevent) +XTestDelayInfo *tevent; +{ + action_array[write_index].type = XTestDELAY_ACTION; + action_array[write_index].delay_time = tevent->delay_time; + write_index++; +} + +/****************************************************************************** + * + * XTestComputeWaitTime + * + * Compute the amount of time the server should wait before sending the + * next monitor event in playback mode. + */ +void +XTestComputeWaitTime(waittime) +struct timeval *waittime; +{ + /* + * The playback_on flag is set to 1 in parse_fake_input. It is set to + * 0 in XTestProcessInputAction if the server has replayed all input + * actions. + */ + if (playback_on) + { + if (!play_clock) + { + /* + * if the playback clock has never been set, + * then do it now + */ + start_play_clock(); + } + /* + * We need to save the waittime the first time through. This + * is a value the server uses, and we have to restore it when + * all of the input actions are processed by the server. + */ + if (!time_saved) + { + saved_sec = waittime->tv_sec; + saved_usec = waittime->tv_usec; + time_saved = 1; + } + if (go_for_next) + { + /* + * if we just processed an input action, figure out + * how long to wait for the next input action + */ + compute_action_time(&rtime); + } + else + { + /* + * else just find out how much more time to wait + * on the current input action + */ + (void)find_residual_time(&rtime); + } + waittime->tv_sec = rtime.tv_sec; + waittime->tv_usec = rtime.tv_usec; + } +} + +/****************************************************************************** + * + * XTestProcessInputAction + * + * If there are any input actions in the input action array, + * then take one out and process it. + * + */ +int +XTestProcessInputAction(readable, waittime) +/* + * This is the value that a 'select' function returned just before this + * routine was called. If the select timed out, this value will be 0. + * + * This extension modifies the select call's timeout value to cause the + * select to time out when the next input action is ready to given to + * the server. This routine is called immediately after the select, to + * give it a chance to process an input action. If we have an input action + * to process and the only reason that the select returned was because it + * timed out, then we change the select value to 1 and return 1 instead of 0. + */ +int readable; +/* + * this is the timeout value that the select was called with + */ +struct timeval *waittime; +{ +int mousex, mousey; + /* + * if playback_on is 0, then the input action array is empty + */ + if (playback_on) + { + restorewait = waittime; + /* + * figure out if we need to wait for the next input action + */ + if (find_residual_time(&rtime) > 0) + { + /* + * still have to wait before processing the current + * input action + */ + go_for_next = 0; + } + else + { + /* + * don't have to wait any longer before processing + * the current input action + */ + go_for_next = 1; + } + /* + * if we have an input action to process and the only reason + * that the select returned was because it timed out, then we + * change the select value to 1 and return 1 instead of 0 + */ + if (readable == 0) + { + readable++; + } + /* + * if we don't need to wait, then get an input action from + * the input action array and process it + */ + if (go_for_next) + { + /* + * There are three possible types of input actions in + * the input action array (motion input actions are + * converted to jump input actions before being put + * into the input action array). Delay input actions + * are processed by the compute_action_time function + * which is called from XTestComputeWaitTime. The + * other two types of input actions are processed here. + */ + if (action_array[read_index].type == XTestJUMP_ACTION) + { + XTestJumpPointer( + action_array[read_index].x, + action_array[read_index].y, + action_array[read_index].device); + mx = action_array[read_index].x; + my = action_array[read_index].y; + } + if (action_array[read_index].type == XTestKEY_ACTION) + { + GetSpritePosition(&mousex, &mousey); + XTestGenerateEvent( + action_array[read_index].device, + action_array[read_index].keycode, + action_array[read_index].keystate, + mousex, + mousey); + } + read_index++; + /* + * if all input actions are processed, then restore + * the server state + */ + if (read_index >= write_index) + { + waittime->tv_sec = saved_sec; + waittime->tv_usec = saved_usec; + time_saved = 0; + playback_on = 0; + if (acknowledge) + { + /* + * if the playback client is waiting + * for an xTestFakeAck event, send + * it to him + */ + send_ack(playback_client); + acknowledge = 0; + } + write_index = 0; + read_index = 0; + playback_client = (ClientPtr) NULL; + play_clock = 0; + } + } + } + return(readable); +} + +/****************************************************************************** + * + * send_ack + * + * send an xTestFakeAck event to the client + */ +static void +send_ack(client) +ClientPtr client; +{ + xTestFakeAckEvent rep; + + /* + * set the serial number of the xTestFakeAck event + */ + rep.sequenceNumber = client->sequence; + rep.type = XTestFakeAckType; + WriteEventsToClient(client, 1, (xEvent *) &rep); +} + +/****************************************************************************** + * + * start_play_clock + * + * start the clock for play back. + */ +static void +start_play_clock() +{ + X_GETTIMEOFDAY(&play_time); + /* + * flag that play_time is valid + */ + play_clock = 1; +} + +/****************************************************************************** + * + * compute_action_time + * + * Set the play clock to the time when the next input action should be put + * into the server's input queue. Fill the rtime structure with values + * for the delta until the time for the next input action. + */ +static void +compute_action_time(rtime) +struct timeval *rtime; +{ + /* + * holds the delay time in milliseconds + */ + unsigned long dtime; + /* + * holds the number of microseconds in the sum of the dtime value + * and the play_time value + */ + unsigned long tot_usec; + /* + * holds the number of seconds and microseconds in the + * dtime value + */ + unsigned long sec; + unsigned long usec; + /* + * holds the current time + */ + struct timeval btime; + + /* + * Put the time from the current input action in dtime + */ + dtime = action_array[read_index].delay_time; + /* + * If the current input action is a delay input action, + * add in the time from the following input action. + */ + if ((action_array[read_index].type == XTestDELAY_ACTION) && + ((read_index + 1) < write_index)) + { + read_index++; + dtime = dtime + action_array[read_index].delay_time; + } + /* + * compute the number of seconds and microseconds in the + * dtime value + */ + sec = dtime / 1000; + usec = (dtime % 1000) * 1000; + /* + * get the current time in btime + */ + X_GETTIMEOFDAY(&btime); + /* + * compute the number of microseconds in the sum of the dtime value + * and the current usec value + */ + tot_usec = btime.tv_usec + usec; + /* + * if it is greater than one second's worth, adjust the seconds + */ + if (tot_usec >= 1000000) + { + tot_usec -= 1000000; + sec++; + } + play_time.tv_usec = tot_usec; + play_time.tv_sec = btime.tv_sec + sec; + /* + * put the time until the next input action in rtime + */ + rtime->tv_sec = sec; + rtime->tv_usec = usec; +} + +/****************************************************************************** + * + * find_residual_time + * + * Find the time interval from the current time to the value in play_time. + * This is the time to wait till putting the next input action into the + * server's input queue. If the time is already up, reset play_time to + * the current time. + */ +static int +find_residual_time(rtime) +struct timeval *rtime; +{ + /* + * if > 0, there is time to wait. If < 0, then don't wait + */ + int wait = 1; + /* + * holds the current time + */ + struct timeval btime; + /* + * holds the current time in seconds and microseconds + */ + unsigned long bsec; + unsigned long busec; + /* + * holds the playback time in seconds and microseconds + */ + unsigned long psec; + unsigned long pusec; + + /* + * get the current time in btime + */ + X_GETTIMEOFDAY(&btime); + /* + * get the current time in seconds and microseconds + */ + bsec = btime.tv_sec; + busec = btime.tv_usec; + /* + * get the playback time in seconds and microseconds + */ + psec = play_time.tv_sec; + pusec = play_time.tv_usec; + /* + * if the current time is already later than the playback time, + * we don't need to wait + */ + if (bsec > psec) + { + wait = -1; + } + else + { + if (bsec == psec) + { + /* + * if the current and playback times have the same + * second value, then compare the microsecond values + */ + if ( busec >= pusec) + { + /* + * if the current time is already later than + * the playback time, we don't need to wait + */ + wait = -1; + } + else + { + rtime->tv_usec = pusec - busec; + rtime->tv_sec = 0; + } + } + else + { + if (busec > pusec) + { + /* + * 'borrow' a second's worth of microseconds + * from the seconds left to wait + */ + rtime->tv_usec = 1000000 - busec + pusec; + psec--; + rtime->tv_sec = psec - bsec; + } + else + { + rtime->tv_sec = psec - bsec; + rtime->tv_usec = pusec - busec; + } + } + } + if (wait < 0) + { + /* + * if don't need to wait, set the playback time + * to the current time + */ + X_GETTIMEOFDAY(&play_time); + /* + * set the time to wait to 0 + */ + rtime->tv_sec = 0; + rtime->tv_usec = 0; + } + return(wait); +} + +/****************************************************************************** + * + * abort_play_back + */ +void +abort_play_back() +{ + /* + * If we were playing back input actions at the time of the abort, + * restore the original wait time for the select in the main wait + * loop of the server + */ + if (playback_on) + { + restorewait->tv_sec = saved_sec; + restorewait->tv_usec = saved_usec; + } + /* + * make the input action array empty + */ + read_index = 0; + write_index = 0; + /* + * we are no longer playing back anything + */ + playback_on = 0; + play_clock = 0; + go_for_next = 1; + /* + * there is no valid wait time saved any more + */ + time_saved = 0; + /* + * there are no valid clients using this extension + */ + playback_client = (ClientPtr) NULL; + current_xtest_client = (ClientPtr) NULL; +} + +/****************************************************************************** + * + * return_input_array_size + * + * Return the number of input actions in the input action array. + */ +void +return_input_array_size(client) +/* + * which client to send the reply to + */ +ClientPtr client; +{ + xTestQueryInputSizeReply rep; + + rep.type = X_Reply; + /* + * set the serial number of the reply + */ + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.size_return = ACTION_ARRAY_SIZE; + WriteReplyToClient(client, + sizeof(xTestQueryInputSizeReply), + (pointer) &rep); +} diff --git a/Xext/xtest1di.c b/Xext/xtest1di.c new file mode 100644 index 000000000..cd8f5e727 --- /dev/null +++ b/Xext/xtest1di.c @@ -0,0 +1,966 @@ +/* $Xorg: xtest1di.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + * File: xtest1di.c + * + * This file contains the device independent parts of the input + * synthesis extension. + */ + +/* + + +Copyright 1986, 1987, 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation + +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 name of Hewlett-Packard not be used in +advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +Hewlett-Packard makes no representations about the +suitability of this software for any purpose. It is provided +"as is" without express or implied warranty. + +This software is not subject to any license of the American +Telephone and Telegraph Company or of the Regents of the +University of California. + +*/ + +/***************************************************************************** + * include files + ****************************************************************************/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "opaque.h" +#define XTestSERVER_SIDE +#include "xtestext1.h" + +/***************************************************************************** + * defines + ****************************************************************************/ + +/***************************************************************************** + * externals + ****************************************************************************/ + +/* + * holds the addresses of the routines that handle byte-swapping of replys + */ +extern void (* ReplySwapVector[256]) (); +/* + * id of client using XTestGetInput + * + * defined in xtest1dd.c + */ +extern ClientPtr current_xtest_client; +/* + * id of client using XTestFakeInput + * + * defined in xtest1dd.c + */ +extern ClientPtr playback_client; + +/***************************************************************************** + * variables + ****************************************************************************/ + +/* + * Holds the request type code for this extension. The request type code + * for this extension may vary depending on how many extensions are installed + * already, so the initial value given below will be added to the base request + * code that is aquired when this extension is installed. + */ +static int XTestReqCode = 0; +/* + * Holds the two event type codes for this extension. The event type codes + * for this extension may vary depending on how many extensions are installed + * already, so the initial values given below will be added to the base event + * code that is aquired when this extension is installed. + */ +int XTestInputActionType = 0; +int XTestFakeAckType = 1; +/* + * true => monitor stealing input + */ +int on_steal_input = FALSE; +/* + * true => monitor alone getting input + */ +int exclusive_steal = FALSE; +/* + * holds the resource type assigned to this extension + */ +static RESTYPE XTestType; +/* + * holds the resource ID for the client currently using XTestGetInput + */ +static XID current_client_id; + +/***************************************************************************** + * function declarations + ****************************************************************************/ + +static int ProcXTestDispatch(); +static int SProcXTestDispatch(); +static void XTestResetProc(); +static int ProcTestFakeInput(); +static int SProcTestFakeInput(); +static int ProcTestGetInput(); +static int SProcTestGetInput(); +static int ProcTestStopInput(); +static int SProcTestStopInput(); +static int ProcTestReset(); +static int SProcTestReset(); +static int ProcTestQueryInputSize(); +static int SProcTestQueryInputSize(); +static void SReplyXTestDispatch(); +static void SEventXTestDispatch(); +void NotImplemented(); + +void abort_play_back(); +void return_input_array_size(); +void steal_input(); +void stop_stealing_input(); +void flush_input_actions(); +void parse_fake_input(); + +static int XTestCurrentClientGone(); + +/***************************************************************************** + * + * XTestExtension1Init + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + * XTestExtension1Init has no events or errors + * (other than the core errors). + */ +void +XTestExtension1Init() +{ + /* + * holds the pointer to the extension entry structure + */ + ExtensionEntry *extEntry; + /* + * This routine adds the extension to the server extension table. + */ + ExtensionEntry *AddExtension(); + + extEntry = AddExtension(XTestEXTENSION_NAME, + XTestEVENT_COUNT, + 0, + ProcXTestDispatch, + SProcXTestDispatch, + XTestResetProc, + StandardMinorOpcode); + if (extEntry) + { + /* + * remember the request code assigned to this extension + */ + XTestReqCode = extEntry->base; + /* + * make an atom saying that this extension is present + */ + (void) MakeAtom(XTestEXTENSION_NAME, + strlen(XTestEXTENSION_NAME), + TRUE); + /* + * remember the event codes assigned to this extension + */ + XTestInputActionType += extEntry->eventBase; + XTestFakeAckType += extEntry->eventBase; + /* + * install the routine to handle byte-swapping the replies + * for this extension in the ReplySwapVector table + */ + ReplySwapVector[XTestReqCode] = SReplyXTestDispatch; + /* + * install the routine to handle byte-swapping the events + * for this extension in the EventSwapVector table + */ + EventSwapVector[XTestInputActionType] = SEventXTestDispatch; + EventSwapVector[XTestFakeAckType] = SEventXTestDispatch; + /* + * get the resource type for this extension + */ + XTestType = CreateNewResourceType(XTestCurrentClientGone); + if (XTestType == 0) + { + FatalError("XTestExtension1Init: CreateNewResourceType failed\n"); + } + } + else + { + FatalError("XTestExtension1Init: AddExtensions failed\n"); + } +} + +/***************************************************************************** + * + * ProcXTestDispatch + * + * + */ +static int +ProcXTestDispatch(client) + register ClientPtr client; +{ + REQUEST(xReq); + if (stuff->data == X_TestFakeInput) + { + return(ProcTestFakeInput(client)); + } + else if (stuff->data == X_TestGetInput) + { + return(ProcTestGetInput(client)); + } + else if (stuff->data == X_TestStopInput) + { + return(ProcTestStopInput(client)); + } + else if (stuff->data == X_TestReset) + { + return(ProcTestReset(client)); + } + else if (stuff->data == X_TestQueryInputSize) + { + return(ProcTestQueryInputSize(client)); + } + else + { + SendErrorToClient(client, + XTestReqCode, + stuff->data, + None, + BadRequest); + return(BadRequest); + } +} + +/***************************************************************************** + * + * SProcXTestDispatch + * + * + */ +static int +SProcXTestDispatch(client) + register ClientPtr client; +{ + REQUEST(xReq); + if (stuff->data == X_TestFakeInput) + { + return(SProcTestFakeInput(client)); + } + else if (stuff->data == X_TestGetInput) + { + return(SProcTestGetInput(client)); + } + else if (stuff->data == X_TestStopInput) + { + return(SProcTestStopInput(client)); + } + else if (stuff->data == X_TestReset) + { + return(SProcTestReset(client)); + } + else if (stuff->data == X_TestQueryInputSize) + { + return(SProcTestQueryInputSize(client)); + } + else + { + SendErrorToClient(client, + XTestReqCode, + stuff->data, + None, + BadRequest); + return(BadRequest); + } +} + +/***************************************************************************** + * + * SProcTestFakeInput + * + * + */ +static int +SProcTestFakeInput(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + /* + * index counter + */ + int i; + /* + * pointer to the next input action in the request + */ + CARD8 *input_action_ptr; + /* + * holds the type of the next input action in the request + */ + int input_action_type; + + REQUEST(xTestFakeInputReq); + /* + * byte-swap the fields in the request + */ + swaps(&stuff->length, n); + swapl(&stuff->ack, n); + /* + * have to parse and then byte-swap the input action list here + */ + for (i = 0; i < XTestMAX_ACTION_LIST_SIZE;) + { + /* + * point to the next input action in the request + */ + input_action_ptr = &(((xTestFakeInputReq *) stuff)->action_list[i]); + /* + * figure out what type of input action it is + */ + input_action_type = (*input_action_ptr) & XTestACTION_TYPE_MASK; + /* + * byte-swap the input action according to it's type + */ + switch (input_action_type) + { + case XTestKEY_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestKeyInfo); + break; + case XTestMOTION_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestMotionInfo); + break; + case XTestJUMP_ACTION: + /* + * byte-swap the jumpx field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n); + /* + * byte-swap the jumpy field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n); + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestJumpInfo); + break; + default: + /* + * if this is a delay input action, then byte-swap it, + * otherwise we have reached the end of the input + * actions in this request + */ + if (XTestUnpackDeviceID(*input_action_ptr) == + XTestDELAY_DEVICE_ID) + { + /* + * byte-swap the delay_time field + */ + swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestDelayInfo); + } + else + { + /* + * if the input action header byte is 0 or + * ill-formed, then there are no more input + * actions in this request + */ + i = XTestMAX_ACTION_LIST_SIZE; + } + break; + } + } + return(ProcTestFakeInput(client)); +} + +/***************************************************************************** + * + * SProcTestGetInput + * + * + */ +static int +SProcTestGetInput(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestGetInputReq); + /* + * byte-swap the fields in the request + */ + swaps(&stuff->length, n); + swapl(&stuff->mode, n); + return(ProcTestGetInput(client)); +} + +/***************************************************************************** + * + * SProcTestStopInput + * + * + */ +static int +SProcTestStopInput(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestStopInputReq); + /* + * byte-swap the length field in the request + */ + swaps(&stuff->length, n); + return(ProcTestStopInput(client)); +} + +/***************************************************************************** + * + * SProcTestReset + * + * + */ +static int +SProcTestReset(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestResetReq); + /* + * byte-swap the length field in the request + */ + swaps(&stuff->length, n); + return(ProcTestReset(client)); +} + +/***************************************************************************** + * + * SProcTestQueryInputSize + * + * + */ +static int +SProcTestQueryInputSize(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestQueryInputSizeReq); + /* + * byte-swap the length field in the request + */ + swaps(&stuff->length, n); + return(ProcTestQueryInputSize(client)); +} + +/***************************************************************************** + * + * ProcTestFakeInput + * + * + */ +static int +ProcTestFakeInput(client) + register ClientPtr client; +{ + REQUEST(xTestFakeInputReq); + REQUEST_SIZE_MATCH(xTestFakeInputReq); + + if (playback_client == NULL) + { + playback_client = client; + current_client_id = FakeClientID(client->index); + AddResource(current_client_id, + XTestType, + 0); + MakeClientGrabImpervious(client); + } + if (playback_client == client) + { + /* + * This extension does not need to clean up any + * server state when a client using this function + * "goes away". The server will just process any + * input actions that have already been sent to it, + * and will then reset its association with a client. + */ + parse_fake_input(client, (char *)stuff); + return(Success); + } + else + { + /* + * this is a request by another client to send fake + * input while the server is still being used + */ + SendErrorToClient(client, + XTestReqCode, + X_TestFakeInput, + None, + BadAccess); + return(BadAccess); + } +} + +/***************************************************************************** + * + * ProcTestGetInput + * + * + */ +static int +ProcTestGetInput(client) + register ClientPtr client; +{ + REQUEST(xTestGetInputReq); + REQUEST_SIZE_MATCH(xTestGetInputReq); + if (on_steal_input) + { + /* + * this is a request by another client to get fake input + * while the server is still sending input to the first client + */ + SendErrorToClient(client, + XTestReqCode, + X_TestGetInput, + None, + BadAccess); + return(BadAccess); + } + else + { + /* + * Set up a resource associated with the client using this + * function so that this extension gets called when the + * client "goes away". This allows this extension to + * clean up the server state. + */ + current_client_id = FakeClientID(client->index); + AddResource(current_client_id, + XTestType, + 0); + /* + * indicate that a client is stealing input + */ + on_steal_input = TRUE; + if ((stuff->mode & XTestEXCLUSIVE) == 0) + { + exclusive_steal = FALSE; + } + else + { + exclusive_steal = TRUE; + } + steal_input(client, stuff->mode); + return(Success); + } +} + +/***************************************************************************** + * + * ProcTestStopInput + * + * + */ +static int +ProcTestStopInput(client) + register ClientPtr client; +{ + REQUEST(xTestStopInputReq); + REQUEST_SIZE_MATCH(xTestStopInputReq); + if (on_steal_input && (current_xtest_client == client)) + { + on_steal_input = FALSE; + exclusive_steal = FALSE; + stop_stealing_input(); + /* + * remove the resource associated with this client + */ + FreeResource(current_client_id, RT_NONE); + return(Success); + } + else + { + /* + * this is a request to stop fake input when fake input has + * never been started or from a client that hasn't started + * fake input + */ + SendErrorToClient(client, + XTestReqCode, + X_TestStopInput, + None, + BadAccess); + return(BadAccess); + } +} + +/***************************************************************************** + * + * ProcTestReset + * + * + */ +static int +ProcTestReset(client) + register ClientPtr client; +{ + REQUEST(xTestResetReq); + REQUEST_SIZE_MATCH(xTestResetReq); + on_steal_input = FALSE; + exclusive_steal = FALSE; + /* + * defined in xtest1dd.c + */ + stop_stealing_input(); + /* + * defined in xtest1dd.c + */ + abort_play_back(); + return(Success); +} + +/***************************************************************************** + * + * ProcTestQueryInputSize + * + * + */ +static int +ProcTestQueryInputSize(client) + register ClientPtr client; +{ + REQUEST(xTestQueryInputSizeReq); + REQUEST_SIZE_MATCH(xTestQueryInputSizeReq); + /* + * defined in xtest1dd.c + */ + return_input_array_size(client); + return(Success); +} + +/***************************************************************************** + * + * XTestResetProc + * + * This function is called by the server when the server has no clients + * connected to it. It must put eveything back the way it was before + * this extension was installed. + */ +static void +XTestResetProc() +{ + /* + * remove the routine to handle byte-swapping the replies + * for this extension in the ReplySwapVector table + */ + ReplySwapVector[XTestReqCode] = NotImplemented; + /* + * remove the routine to handle byte-swapping the events + * for this extension in the EventSwapVector table + */ + EventSwapVector[XTestInputActionType] = NotImplemented; + EventSwapVector[XTestFakeAckType] = NotImplemented; + /* + * reset the variables initialized just once at load time + */ + XTestReqCode = 0; + XTestInputActionType = 0; + XTestFakeAckType = 1; + on_steal_input = FALSE; + exclusive_steal = FALSE; + playback_client = 0; /* Don't really need this but it looks nice */ +} + +/***************************************************************************** + * + * ProcTestQueryInputSize + * + * This routine is called when a client that has asked for input actions + * to be sent to it "goes away". This routine must clean up the + * server state. + */ +/*ARGSUSED*/ +static int +XTestCurrentClientGone(value, id) + pointer value; + XID id; +{ + /* + * defined in xtest1dd.c + */ + on_steal_input = FALSE; + exclusive_steal = FALSE; + /* + * defined in xtestdd.c + */ + playback_client = 0; + abort_play_back(); + return TRUE; +} + +/***************************************************************************** + * + * SReplyXTestDispatch + * + * Swap any replies defined in this extension. + */ +static void +SReplyXTestDispatch(client_ptr, size, reply_ptr) + ClientPtr client_ptr; + int size; + char *reply_ptr; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + /* + * pointer to xTestQueryInputSizeReply + */ + xTestQueryInputSizeReply *rep_ptr; + + /* + * there is only one reply in this extension, so byte-swap it + */ + rep_ptr = (xTestQueryInputSizeReply *) reply_ptr; + swaps(&(rep_ptr->sequenceNumber), n); + swapl(&(rep_ptr->length), n); + swapl(&(rep_ptr->size_return), n); + /* + * now write the swapped reply to the client + */ + WriteToClient(client_ptr, size, reply_ptr); +} + +/***************************************************************************** + * + * SEventXTestDispatch + * + * Swap any events defined in this extension. + */ +static void +SEventXTestDispatch(from, to) + xEvent *from; + xEvent *to; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + /* + * index counter + */ + int i; + /* + * pointer to the next input action in the event + */ + CARD8 *input_action_ptr; + /* + * holds the type of the next input action in the event + */ + int input_action_type; + + + /* + * copy the type information from the "from" event to the "to" event + */ + ((xTestInputActionEvent *) to)->type = + ((xTestInputActionEvent *) from)->type; + /* + * copy the sequence number information from the "from" event to the + * "to" event + */ + ((xTestInputActionEvent *) to)->sequenceNumber = + ((xTestInputActionEvent *) from)->sequenceNumber; + /* + * byte-swap the sequence number in the "to" event + */ + swaps(&(((xTestInputActionEvent *) to)->sequenceNumber), n); + /* + * If the event is an xTestInputActionEvent, then it needs more + * processing. Otherwise, it is an xTestFakeAckEvent, which + * has no other information in it. + */ + if ((((xTestInputActionEvent *) to)->type & 0x7f) == + XTestInputActionType) + { + /* + * copy the input actions from the "from" event + * to the "to" event + */ + for (i = 0; i < XTestACTIONS_SIZE; i++) + { + ((xTestInputActionEvent *) to)->actions[i] = + ((xTestInputActionEvent *) from)->actions[i]; + } + /* + * byte-swap the input actions in the "to" event + */ + for (i = 0; i < XTestACTIONS_SIZE; i++) + { + /* + * point to the next input action in the event + */ + input_action_ptr = &(((xTestInputActionEvent *) to)->actions[i]); + /* + * figure out what type of input action it is + */ + input_action_type = (*input_action_ptr) & + XTestACTION_TYPE_MASK; + /* + * byte-swap the input action according to it's type + */ + switch (input_action_type) + { + case XTestKEY_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestKeyInfo); + break; + case XTestMOTION_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestMotionInfo); + break; + case XTestJUMP_ACTION: + /* + * byte-swap the jumpx field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n); + /* + * byte-swap the jumpy field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n); + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestJumpInfo); + break; + default: + /* + * if this is a delay input action, then + * byte-swap it, otherwise we have reached the + * end of the input actions in this event + */ + if (XTestUnpackDeviceID(*input_action_ptr) == + XTestDELAY_DEVICE_ID) + { + /* + * byte-swap the delay_time field + */ + swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestDelayInfo); + } + else + { + /* + * if the input action header byte is 0 + * or ill-formed, then there are no + * more input actions in this event + */ + i = XTestACTIONS_SIZE; + } + break; + } + } + } +} diff --git a/Xi/allowev.c b/Xi/allowev.c new file mode 100644 index 000000000..db98d8c93 --- /dev/null +++ b/Xi/allowev.c @@ -0,0 +1,139 @@ +/* $Xorg: allowev.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Function to allow frozen events to be routed from extension input devices. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure allows frozen events to be routed. + * + */ + +int +SProcXAllowDeviceEvents(client) + register ClientPtr client; + { + register char n; + + REQUEST(xAllowDeviceEventsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xAllowDeviceEventsReq); + swapl(&stuff->time, n); + return(ProcXAllowDeviceEvents(client)); + } + +/*********************************************************************** + * + * This procedure allows frozen events to be routed. + * + */ + +int +ProcXAllowDeviceEvents(client) + register ClientPtr client; + { + TimeStamp time; + DeviceIntPtr thisdev; + void AllowSome (); + + REQUEST(xAllowDeviceEventsReq); + REQUEST_SIZE_MATCH(xAllowDeviceEventsReq); + + thisdev = LookupDeviceIntRec (stuff->deviceid); + if (thisdev == NULL) + { + SendErrorToClient(client, IReqCode, X_AllowDeviceEvents, 0, BadDevice); + return Success; + } + time = ClientTimeToServerTime(stuff->time); + + switch (stuff->mode) + { + case ReplayThisDevice: + AllowSome(client, time, thisdev, NOT_GRABBED); + break; + case SyncThisDevice: + AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT); + break; + case AsyncThisDevice: + AllowSome(client, time, thisdev, THAWED); + break; + case AsyncOtherDevices: + AllowSome(client, time, thisdev, THAW_OTHERS); + break; + case SyncAll: + AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncAll: + AllowSome(client, time, thisdev, THAWED_BOTH); + break; + default: + SendErrorToClient(client, IReqCode, X_AllowDeviceEvents, 0, + BadValue); + client->errorValue = stuff->mode; + return Success; + } + return Success; + } diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c new file mode 100644 index 000000000..e5dab66c1 --- /dev/null +++ b/Xi/chgdctl.c @@ -0,0 +1,209 @@ +/* $Xorg: chgdctl.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Change Device control attributes for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" /* control constants */ + +extern int IReqCode; +extern int BadDevice, DeviceBusy; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure changes the control attributes for an extension device, + * for clients on machines with a different byte ordering than the server. + * + */ + +int +SProcXChangeDeviceControl(client) + register ClientPtr client; + { + register char n; + + REQUEST(xChangeDeviceControlReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq); + swaps(&stuff->control, n); + return(ProcXChangeDeviceControl(client)); + } + +/*********************************************************************** + * + * Change the control attributes. + * + */ + +ProcXChangeDeviceControl(client) + ClientPtr client; + { + int i, len, status; + DeviceIntPtr dev; + xDeviceResolutionCtl *r; + xChangeDeviceControlReply rep; + AxisInfoPtr a; + CARD32 *resolution; + + REQUEST(xChangeDeviceControlReq); + REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq); + + len = stuff->length - (sizeof(xChangeDeviceControlReq) >>2); + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_ChangeDeviceControl, 0, + BadDevice); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_ChangeDeviceControl; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + switch (stuff->control) + { + case DEVICE_RESOLUTION: + r = (xDeviceResolutionCtl *) &stuff[1]; + if ((len < (sizeof(xDeviceResolutionCtl)>>2)) || + (len != (sizeof(xDeviceResolutionCtl)>>2) + + r->num_valuators)) + { + SendErrorToClient (client, IReqCode, X_ChangeDeviceControl, + 0, BadLength); + return Success; + } + if (!dev->valuator) + { + SendErrorToClient (client, IReqCode, X_ChangeDeviceControl, 0, + BadMatch); + return Success; + } + if ((dev->grab) && !SameClient(dev->grab, client)) + { + rep.status = AlreadyGrabbed; + WriteReplyToClient(client, sizeof(xChangeDeviceControlReply), + &rep); + return Success; + } + resolution = (CARD32 *) (r + 1); + if (r->first_valuator + r->num_valuators > dev->valuator->numAxes) + { + SendErrorToClient (client, IReqCode, X_ChangeDeviceControl, 0, + BadValue); + return Success; + } + status = ChangeDeviceControl(client, dev, r); + if (status == Success) + { + a = &dev->valuator->axes[r->first_valuator]; + for (i=0; inum_valuators; i++) + if (*(resolution+i) < (a+i)->min_resolution || + *(resolution+i) > (a+i)->max_resolution) + { + SendErrorToClient (client, IReqCode, + X_ChangeDeviceControl, 0, BadValue); + return Success; + } + for (i=0; inum_valuators; i++) + (a++)->resolution = *resolution++; + } + else if (status == DeviceBusy) + { + rep.status = DeviceBusy; + WriteReplyToClient(client, sizeof(xChangeDeviceControlReply), + &rep); + return Success; + } + else + { + SendErrorToClient (client, IReqCode, X_ChangeDeviceControl, 0, + BadMatch); + return Success; + } + break; + default: + SendErrorToClient (client, IReqCode, X_ChangeDeviceControl, 0, + BadValue); + return Success; + } + WriteReplyToClient(client, sizeof(xChangeDeviceControlReply), &rep); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the xChangeDeviceControl function, + * if the client and server have a different byte ordering. + * + */ + +SRepXChangeDeviceControl (client, size, rep) + ClientPtr client; + int size; + xChangeDeviceControlReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } + diff --git a/Xi/chgfctl.c b/Xi/chgfctl.c new file mode 100644 index 000000000..0b945de23 --- /dev/null +++ b/Xi/chgfctl.c @@ -0,0 +1,649 @@ +/* $Xorg: chgfctl.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Change feedback control attributes for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" /* control constants */ + +#define DO_ALL (-1) + +extern int IReqCode; +extern int BadDevice; +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure changes the control attributes for an extension device, + * for clients on machines with a different byte ordering than the server. + * + */ + +int +SProcXChangeFeedbackControl(client) + register ClientPtr client; + { + register char n; + + REQUEST(xChangeFeedbackControlReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq); + swapl(&stuff->mask, n); + return(ProcXChangeFeedbackControl(client)); + } + +/*********************************************************************** + * + * Change the control attributes. + * + */ + +ProcXChangeFeedbackControl(client) + ClientPtr client; + { + int len; + DeviceIntPtr dev; + KbdFeedbackPtr k; + PtrFeedbackPtr p; + IntegerFeedbackPtr i; + StringFeedbackPtr s; + BellFeedbackPtr b; + LedFeedbackPtr l; + + REQUEST(xChangeFeedbackControlReq); + REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq); + + len = stuff->length - (sizeof(xChangeFeedbackControlReq) >>2); + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadDevice); + return Success; + } + + switch (stuff->feedbackid) + { + case KbdFeedbackClass: + if (len != (sizeof(xKbdFeedbackCtl)>>2)) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, + 0, BadLength); + return Success; + } + for (k=dev->kbdfeed; k; k=k->next) + if (k->ctrl.id == ((xKbdFeedbackCtl *) &stuff[1])->id) + { + ChangeKbdFeedback (client, dev, stuff->mask, k, &stuff[1]); + return Success; + } + break; + case PtrFeedbackClass: + if (len != (sizeof(xPtrFeedbackCtl)>>2)) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, + 0, BadLength); + return Success; + } + for (p=dev->ptrfeed; p; p=p->next) + if (p->ctrl.id == ((xPtrFeedbackCtl *) &stuff[1])->id) + { + ChangePtrFeedback (client, dev, stuff->mask, p, &stuff[1]); + return Success; + } + break; + case StringFeedbackClass: + { + register char n; + xStringFeedbackCtl *f = ((xStringFeedbackCtl *) &stuff[1]); + if (client->swapped) + { + swaps(&f->num_keysyms,n); + } + if (len != ((sizeof(xStringFeedbackCtl)>>2) + f->num_keysyms)) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, + 0, BadLength); + return Success; + } + for (s=dev->stringfeed; s; s=s->next) + if (s->ctrl.id == ((xStringFeedbackCtl *) &stuff[1])->id) + { + ChangeStringFeedback (client, dev, stuff->mask,s,&stuff[1]); + return Success; + } + break; + } + case IntegerFeedbackClass: + if (len != (sizeof(xIntegerFeedbackCtl)>>2)) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, + 0, BadLength); + return Success; + } + for (i=dev->intfeed; i; i=i->next) + if (i->ctrl.id == ((xIntegerFeedbackCtl *) &stuff[1])->id) + { + ChangeIntegerFeedback (client, dev,stuff->mask,i,&stuff[1]); + return Success; + } + break; + case LedFeedbackClass: + if (len != (sizeof(xLedFeedbackCtl)>>2)) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, + 0, BadLength); + return Success; + } + for (l=dev->leds; l; l=l->next) + if (l->ctrl.id == ((xLedFeedbackCtl *) &stuff[1])->id) + { + ChangeLedFeedback (client, dev, stuff->mask, l, &stuff[1]); + return Success; + } + break; + case BellFeedbackClass: + if (len != (sizeof(xBellFeedbackCtl)>>2)) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, + 0, BadLength); + return Success; + } + for (b=dev->bell; b; b=b->next) + if (b->ctrl.id == ((xBellFeedbackCtl *) &stuff[1])->id) + { + ChangeBellFeedback (client, dev, stuff->mask, b, &stuff[1]); + return Success; + } + break; + default: + break; + } + + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, BadMatch); + return Success; + } + +/****************************************************************************** + * + * This procedure changes KbdFeedbackClass data. + * + */ + +ChangeKbdFeedback (client, dev, mask, k, f) + ClientPtr client; + DeviceIntPtr dev; + unsigned long mask; + KbdFeedbackPtr k; + xKbdFeedbackCtl *f; + { + register char n; + KeybdCtrl kctrl; + int t; + int key = DO_ALL; + + if (client->swapped) + { + swaps(&f->length,n); + swaps(&f->pitch,n); + swaps(&f->duration,n); + swapl(&f->led_mask,n); + swapl(&f->led_values,n); + } + + kctrl = k->ctrl; + if (mask & DvKeyClickPercent) + { + t = f->click; + if (t == -1) + t = defaultKeyboardControl.click; + else if (t < 0 || t > 100) + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + kctrl.click = t; + } + + if (mask & DvPercent) + { + t = f->percent; + if (t == -1) + t = defaultKeyboardControl.bell; + else if (t < 0 || t > 100) + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + kctrl.bell = t; + } + + if (mask & DvPitch) + { + t = f->pitch; + if (t == -1) + t = defaultKeyboardControl.bell_pitch; + else if (t < 0) + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + kctrl.bell_pitch = t; + } + + if (mask & DvDuration) + { + t = f->duration; + if (t == -1) + t = defaultKeyboardControl.bell_duration; + else if (t < 0) + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + kctrl.bell_duration = t; + } + + if (mask & DvLed) + { + kctrl.leds &= ~(f->led_mask); + kctrl.leds |= (f->led_mask & f->led_values); + } + + if (mask & DvKey) + { + key = (KeyCode) f->key; + if (key < 8 || key > 255) + { + client->errorValue = key; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + if (!(mask & DvAutoRepeatMode)) + { + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadMatch); + return Success; + } + } + + if (mask & DvAutoRepeatMode) + { + int index = (key >> 3); + int kmask = (1 << (key & 7)); + t = (CARD8) f->auto_repeat_mode; + if (t == AutoRepeatModeOff) + { + if (key == DO_ALL) + kctrl.autoRepeat = FALSE; + else + kctrl.autoRepeats[index] &= ~kmask; + } + else if (t == AutoRepeatModeOn) + { + if (key == DO_ALL) + kctrl.autoRepeat = TRUE; + else + kctrl.autoRepeats[index] |= kmask; + } + else if (t == AutoRepeatModeDefault) + { + if (key == DO_ALL) + kctrl.autoRepeat = defaultKeyboardControl.autoRepeat; + else + kctrl.autoRepeats[index] &= ~kmask; + kctrl.autoRepeats[index] = + (kctrl.autoRepeats[index] & ~kmask) | + (defaultKeyboardControl.autoRepeats[index] & kmask); + } + else + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + } + + k->ctrl = kctrl; + (*k->CtrlProc)(dev, &k->ctrl); + return Success; + } + +/****************************************************************************** + * + * This procedure changes PtrFeedbackClass data. + * + */ + +ChangePtrFeedback (client, dev, mask, p, f) + ClientPtr client; + DeviceIntPtr dev; + unsigned long mask; + PtrFeedbackPtr p; + xPtrFeedbackCtl *f; + { + register char n; + PtrCtrl pctrl; /* might get BadValue part way through */ + + if (client->swapped) + { + swaps(&f->length,n); + swaps(&f->num,n); + swaps(&f->denom,n); + swaps(&f->thresh,n); + } + + pctrl = p->ctrl; + if (mask & DvAccelNum) + { + int accelNum; + + accelNum = f->num; + if (accelNum == -1) + pctrl.num = defaultPointerControl.num; + else if (accelNum < 0) + { + client->errorValue = accelNum; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + else pctrl.num = accelNum; + } + + if (mask & DvAccelDenom) + { + int accelDenom; + + accelDenom = f->denom; + if (accelDenom == -1) + pctrl.den = defaultPointerControl.den; + else if (accelDenom <= 0) + { + client->errorValue = accelDenom; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + else pctrl.den = accelDenom; + } + + if (mask & DvThreshold) + { + int threshold; + + threshold = f->thresh; + if (threshold == -1) + pctrl.threshold = defaultPointerControl.threshold; + else if (threshold < 0) + { + client->errorValue = threshold; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + else pctrl.threshold = threshold; + } + + p->ctrl = pctrl; + (*p->CtrlProc)(dev, &p->ctrl); + return Success; + } + +/****************************************************************************** + * + * This procedure changes IntegerFeedbackClass data. + * + */ + +ChangeIntegerFeedback (client, dev, mask, i, f) + ClientPtr client; + DeviceIntPtr dev; + unsigned long mask; + IntegerFeedbackPtr i; + xIntegerFeedbackCtl *f; + { + register char n; + + if (client->swapped) + { + swaps(&f->length,n); + swapl(&f->int_to_display,n); + } + + i->ctrl.integer_displayed = f->int_to_display; + (*i->CtrlProc)(dev, &i->ctrl); + return Success; + } + +/****************************************************************************** + * + * This procedure changes StringFeedbackClass data. + * + */ + +ChangeStringFeedback (client, dev, mask, s, f) + ClientPtr client; + DeviceIntPtr dev; + unsigned long mask; + StringFeedbackPtr s; + xStringFeedbackCtl *f; + { + register char n; + register long *p; + int i, j, len; + KeySym *syms, *sup_syms; + + syms = (KeySym *) (f+1); + if (client->swapped) + { + swaps(&f->length,n); /* swapped num_keysyms in calling proc */ + p = (long *) (syms); + for (i=0; inum_keysyms; i++) + { + swapl(p, n); + p++; + } + } + + if (f->num_keysyms > s->ctrl.max_symbols) + { + SendErrorToClient(client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + sup_syms = s->ctrl.symbols_supported; + for (i=0; inum_keysyms; i++) + { + for (j=0; jctrl.num_symbols_supported; j++) + if (*(syms+i) == *(sup_syms+j)) + break; + if (j==s->ctrl.num_symbols_supported) + { + SendErrorToClient(client, IReqCode, X_ChangeFeedbackControl, 0, + BadMatch); + return Success; + } + } + + s->ctrl.num_symbols_displayed = f->num_keysyms; + for (i=0; inum_keysyms; i++) + *(s->ctrl.symbols_displayed+i) = *(syms+i); + (*s->CtrlProc)(dev, &s->ctrl); + return Success; + } + +/****************************************************************************** + * + * This procedure changes BellFeedbackClass data. + * + */ + +ChangeBellFeedback (client, dev, mask, b, f) + ClientPtr client; + DeviceIntPtr dev; + unsigned long mask; + BellFeedbackPtr b; + xBellFeedbackCtl *f; + { + register char n; + int t; + BellCtrl bctrl; /* might get BadValue part way through */ + + if (client->swapped) + { + swaps(&f->length,n); + swaps(&f->pitch,n); + swaps(&f->duration,n); + } + + bctrl = b->ctrl; + if (mask & DvPercent) + { + t = f->percent; + if (t == -1) + t = defaultKeyboardControl.bell; + else if (t < 0 || t > 100) + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + bctrl.percent = t; + } + + if (mask & DvPitch) + { + t = f->pitch; + if (t == -1) + t = defaultKeyboardControl.bell_pitch; + else if (t < 0) + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + bctrl.pitch = t; + } + + if (mask & DvDuration) + { + t = f->duration; + if (t == -1) + t = defaultKeyboardControl.bell_duration; + else if (t < 0) + { + client->errorValue = t; + SendErrorToClient (client, IReqCode, X_ChangeFeedbackControl, 0, + BadValue); + return Success; + } + bctrl.duration = t; + } + b->ctrl = bctrl; + (*b->CtrlProc)(dev, &b->ctrl); + return Success; + } + +/****************************************************************************** + * + * This procedure changes LedFeedbackClass data. + * + */ + +ChangeLedFeedback (client, dev, mask, l, f) + ClientPtr client; + DeviceIntPtr dev; + unsigned long mask; + LedFeedbackPtr l; + xLedFeedbackCtl *f; + { + register char n; + LedCtrl lctrl; /* might get BadValue part way through */ + + if (client->swapped) + { + swaps(&f->length,n); + swapl(&f->led_values,n); + swapl(&f->led_mask,n); + } + + f->led_mask &= l->ctrl.led_mask; /* set only supported leds */ + f->led_values &= l->ctrl.led_mask; /* set only supported leds */ + if (mask & DvLed) + { + lctrl.led_mask = f->led_mask; + lctrl.led_values = f->led_values; + (*l->CtrlProc)(dev, &lctrl); + l->ctrl.led_values &= ~(f->led_mask); /* zero changed leds */ + l->ctrl.led_values |= (f->led_mask & f->led_values);/* OR in set leds*/ + } + + return Success; + } diff --git a/Xi/chgkbd.c b/Xi/chgkbd.c new file mode 100644 index 000000000..f48b4682b --- /dev/null +++ b/Xi/chgkbd.c @@ -0,0 +1,208 @@ +/* $Xorg: chgkbd.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to change the keyboard device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern int ChangeDeviceNotify; +extern Mask ChangeDeviceNotifyMask; +extern InputInfo inputInfo; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure changes the keyboard device. + * + */ + +int +SProcXChangeKeyboardDevice(client) + register ClientPtr client; + { + register char n; + + REQUEST(xChangeKeyboardDeviceReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xChangeKeyboardDeviceReq); + return(ProcXChangeKeyboardDevice(client)); + } + +/*********************************************************************** + * + * This procedure is invoked to swap the request bytes if the server and + * client have a different byte order. + * + */ + +ProcXChangeKeyboardDevice (client) + register ClientPtr client; + { + int i; + DeviceIntPtr xkbd = inputInfo.keyboard; + DeviceIntPtr dev; + FocusClassPtr xf = xkbd->focus; + FocusClassPtr df; + KeyClassPtr k; + xChangeKeyboardDeviceReply rep; + changeDeviceNotify ev; + extern Bool Must_have_memory; + + REQUEST(xChangeKeyboardDeviceReq); + REQUEST_SIZE_MATCH(xChangeKeyboardDeviceReq); + + rep.repType = X_Reply; + rep.RepType = X_ChangeKeyboardDevice; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + rep.status = -1; + SendErrorToClient(client, IReqCode, X_ChangeKeyboardDevice, 0, + BadDevice); + return Success; + } + + k = dev->key; + if (k == NULL) + { + rep.status = -1; + SendErrorToClient(client, IReqCode, X_ChangeKeyboardDevice, 0, + BadMatch); + return Success; + } + + if (((dev->grab) && !SameClient(dev->grab, client)) || + ((xkbd->grab) && !SameClient(xkbd->grab, client))) + rep.status = AlreadyGrabbed; + else if ((dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) || + (xkbd->sync.frozen && + xkbd->sync.other && !SameClient(xkbd->sync.other, client))) + rep.status = GrabFrozen; + else + { + if (ChangeKeyboardDevice (xkbd, dev) != Success) + { + SendErrorToClient(client, IReqCode, X_ChangeKeyboardDevice, 0, + BadDevice); + return Success; + } + if (!dev->focus) + InitFocusClassDeviceStruct (dev); + if (!dev->kbdfeed) + InitKbdFeedbackClassDeviceStruct(dev, (BellProcPtr)NoopDDA, + (KbdCtrlProcPtr)NoopDDA); + df = dev->focus; + df->win = xf->win; + df->revert = xf->revert; + df->time = xf->time; + df->traceGood = xf->traceGood; + if (df->traceSize != xf->traceSize) + { + Must_have_memory = TRUE; /* XXX */ + df->trace = (WindowPtr *) xrealloc(df->trace, + xf->traceSize * sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + df->traceSize = xf->traceSize; + for (i=0; itraceSize; i++) + df->trace[i] = xf->trace[i]; + RegisterOtherDevice (xkbd); + RegisterKeyboardDevice ((DevicePtr)dev); + + ev.type = ChangeDeviceNotify; + ev.deviceid = stuff->deviceid; + ev.time = currentTime.milliseconds; + ev.request = NewKeyboard; + + SendEventToAllWindows (dev, ChangeDeviceNotifyMask, &ev, 1); + SendMappingNotify (MappingKeyboard, k->curKeySyms.minKeyCode, + k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode + 1,client); + + rep.status = 0; + } + + WriteReplyToClient (client, sizeof (xChangeKeyboardDeviceReply), + &rep); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XChangeKeyboardDevice + * function, if the client and server have a different byte ordering. + * + */ + +SRepXChangeKeyboardDevice (client, size, rep) + ClientPtr client; + int size; + xChangeKeyboardDeviceReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/chgkmap.c b/Xi/chgkmap.c new file mode 100644 index 000000000..3e70f2dcf --- /dev/null +++ b/Xi/chgkmap.c @@ -0,0 +1,129 @@ +/* $Xorg: chgkmap.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Change key mapping for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern int DeviceMappingNotify; +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure swaps the request when the client and + * server have different byte orderings. + * + */ + +int +SProcXChangeDeviceKeyMapping(client) + register ClientPtr client; + { + register char n; + register long *p; + register int i, count; + + REQUEST(xChangeDeviceKeyMappingReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeDeviceKeyMappingReq); + p = (long *) &stuff[1]; + count = stuff->keyCodes * stuff->keySymsPerKeyCode; + for (i = 0; i < count; i++) + { + swapl(p, n); + p++; + } + return(ProcXChangeDeviceKeyMapping(client)); + } + +/*********************************************************************** + * + * Change the device key mapping. + * + */ + +ProcXChangeDeviceKeyMapping(client) + register ClientPtr client; + { + int ret; + unsigned len; + DeviceIntPtr dev; + + REQUEST(xChangeDeviceKeyMappingReq); + REQUEST_AT_LEAST_SIZE(xChangeDeviceKeyMappingReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_ChangeDeviceKeyMapping, 0, + BadDevice); + return Success; + } + len = stuff->length - (sizeof(xChangeDeviceKeyMappingReq) >> 2); + + ret = ChangeKeyMapping (client, dev, len, DeviceMappingNotify, + stuff->firstKeyCode, stuff->keyCodes, stuff->keySymsPerKeyCode, + &stuff[1]); + + if (ret != Success) + SendErrorToClient (client, IReqCode, X_ChangeDeviceKeyMapping, 0, + ret); + return Success; + } diff --git a/Xi/chgprop.c b/Xi/chgprop.c new file mode 100644 index 000000000..769bcbbb9 --- /dev/null +++ b/Xi/chgprop.c @@ -0,0 +1,165 @@ +/* $Xorg: chgprop.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Function to modify the dont-propagate-list for an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" +#include "XI.h" +#include "XIproto.h" + +extern int BadMode; +extern int BadClass; +extern int IReqCode; +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure returns the extension version. + * + */ + +int +SProcXChangeDeviceDontPropagateList(client) + register ClientPtr client; + { + register char n; + register long *p; + register int i; + + REQUEST(xChangeDeviceDontPropagateListReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeDeviceDontPropagateListReq); + swapl(&stuff->window, n); + swaps(&stuff->count, n); + p = (long *) &stuff[1]; + for (i=0; icount; i++) + { + swapl(p, n); + p++; + } + return(ProcXChangeDeviceDontPropagateList(client)); + } + +/*********************************************************************** + * + * This procedure changes the dont-propagate list for the specified window. + * + */ + +ProcXChangeDeviceDontPropagateList (client) + register ClientPtr client; + { + int i; + WindowPtr pWin; + struct tmask tmp[EMASKSIZE]; + OtherInputMasks *others; + + REQUEST(xChangeDeviceDontPropagateListReq); + REQUEST_AT_LEAST_SIZE(xChangeDeviceDontPropagateListReq); + + if (stuff->length !=(sizeof(xChangeDeviceDontPropagateListReq)>>2) + + stuff->count) + { + SendErrorToClient (client, IReqCode, X_ChangeDeviceDontPropagateList, 0, + BadLength); + return Success; + } + + pWin = (WindowPtr) LookupWindow (stuff->window, client); + if (!pWin) + { + client->errorValue = stuff->window; + SendErrorToClient(client, IReqCode, X_ChangeDeviceDontPropagateList, 0, + BadWindow); + return Success; + } + + if (stuff->mode != AddToList && stuff->mode != DeleteFromList) + { + client->errorValue = stuff->window; + SendErrorToClient(client, IReqCode, X_ChangeDeviceDontPropagateList, 0, + BadMode); + return Success; + } + + if (CreateMaskFromList (client, (XEventClass *)&stuff[1], + stuff->count, tmp, NULL, X_ChangeDeviceDontPropagateList) != Success) + return Success; + + others = wOtherInputMasks(pWin); + if (!others && stuff->mode == DeleteFromList) + return Success; + for (i=0; imode == DeleteFromList) + tmp[i].mask = (others->dontPropagateMask[i] & ~tmp[i].mask); + else if (others) + tmp[i].mask |= others->dontPropagateMask[i]; + + if (DeviceEventSuppressForWindow (pWin,client,tmp[i].mask,i) != Success) + { + SendErrorToClient ( client, IReqCode, X_ChangeDeviceDontPropagateList, 0, + BadClass); + return Success; + } + } + + return Success; + } diff --git a/Xi/chgptr.c b/Xi/chgptr.c new file mode 100644 index 000000000..8c65c6ec2 --- /dev/null +++ b/Xi/chgptr.c @@ -0,0 +1,252 @@ +/* $Xorg: chgptr.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to change the pointer device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "XI.h" +#include "XIproto.h" +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ + +extern int IReqCode; +extern int BadDevice; +extern int ChangeDeviceNotify; +extern Mask ChangeDeviceNotifyMask; +extern InputInfo inputInfo; +extern ScreenInfo screenInfo; +extern WindowPtr *WindowTable; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure is invoked to swap the request bytes if the server and + * client have a different byte order. + * + */ + +int +SProcXChangePointerDevice(client) + register ClientPtr client; + { + register char n; + + REQUEST(xChangePointerDeviceReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xChangePointerDeviceReq); + return(ProcXChangePointerDevice(client)); + } + +/*********************************************************************** + * + * This procedure changes the device used as the X pointer. + * + */ + +ProcXChangePointerDevice (client) + register ClientPtr client; + { + DeviceIntPtr xptr = inputInfo.pointer; + DeviceIntPtr dev; + ValuatorClassPtr v; + xChangePointerDeviceReply rep; + changeDeviceNotify ev; + + REQUEST(xChangePointerDeviceReq); + REQUEST_SIZE_MATCH(xChangePointerDeviceReq); + + rep.repType = X_Reply; + rep.RepType = X_ChangePointerDevice; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + rep.status = -1; + SendErrorToClient(client, IReqCode, X_ChangePointerDevice, 0, + BadDevice); + return Success; + } + + v = dev->valuator; + if (v == NULL || v->numAxes < 2 || + stuff->xaxis >= v->numAxes || + stuff->yaxis >= v->numAxes) + { + rep.status = -1; + SendErrorToClient(client, IReqCode, X_ChangePointerDevice, 0, BadMatch); + return Success; + } + + if (((dev->grab) && !SameClient(dev->grab, client)) || + ((xptr->grab) && !SameClient(xptr->grab, client))) + rep.status = AlreadyGrabbed; + else if ((dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) || + (xptr->sync.frozen && + xptr->sync.other && !SameClient(xptr->sync.other, client))) + rep.status = GrabFrozen; + else + { + if (ChangePointerDevice ( + xptr, dev, stuff->xaxis, stuff->yaxis) != Success) + { + SendErrorToClient(client, IReqCode, X_ChangePointerDevice, 0, + BadDevice); + return Success; + } + if (dev->focus) + DeleteFocusClassDeviceStruct(dev); + if (!dev->button) + InitButtonClassDeviceStruct (dev, 0, NULL); + if (!dev->ptrfeed) + InitPtrFeedbackClassDeviceStruct(dev, (PtrCtrlProcPtr)NoopDDA); + RegisterOtherDevice (xptr); + RegisterPointerDevice ((DevicePtr)dev); + + ev.type = ChangeDeviceNotify; + ev.deviceid = stuff->deviceid; + ev.time = currentTime.milliseconds; + ev.request = NewPointer; + + SendEventToAllWindows (dev, ChangeDeviceNotifyMask, &ev, 1); + SendMappingNotify (MappingPointer, 0, 0, client); + + rep.status = 0; + } + + WriteReplyToClient (client, sizeof (xChangePointerDeviceReply), + &rep); + return Success; + } + +DeleteFocusClassDeviceStruct(dev) + DeviceIntPtr dev; + { + xfree(dev->focus->trace); + xfree(dev->focus); + dev->focus = NULL; + } + +/*********************************************************************** + * + * Send an event to interested clients in all windows on all screens. + * + */ + +SendEventToAllWindows (dev, mask, ev, count) + DeviceIntPtr dev; + Mask mask; + xEvent *ev; + int count; + { + int i; + WindowPtr pWin, p1; + + for (i=0; iid); + p1 = pWin->firstChild; + FindInterestedChildren (dev, p1, mask, ev, count); + } + } + +/*********************************************************************** + * + * Walk through the window tree, finding all clients that want to know + * about the ChangeDeviceNotify Event. + * + */ + +FindInterestedChildren (dev, p1, mask, ev, count) + DeviceIntPtr dev; + WindowPtr p1; + Mask mask; + xEvent *ev; + int count; + { + WindowPtr p2; + + while (p1) + { + p2 = p1->firstChild; + (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id); + FindInterestedChildren (dev, p2, mask, ev, count); + p1 = p1->nextSib; + } + } + +/*********************************************************************** + * + * This procedure writes the reply for the XChangePointerDevice + * function, if the client and server have a different byte ordering. + * + */ + +SRepXChangePointerDevice (client, size, rep) + ClientPtr client; + int size; + xChangePointerDeviceReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/closedev.c b/Xi/closedev.c new file mode 100644 index 000000000..66fb185cb --- /dev/null +++ b/Xi/closedev.c @@ -0,0 +1,185 @@ +/* $Xorg: closedev.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to close an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include "XI.h" +#include "XIproto.h" + +extern ScreenInfo screenInfo; +extern WindowPtr *WindowTable; +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure closes an input device. + * + */ + +int +SProcXCloseDevice(client) + register ClientPtr client; + { + register char n; + + REQUEST(xCloseDeviceReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCloseDeviceReq); + return(ProcXCloseDevice(client)); + } + +/*********************************************************************** + * + * This procedure closes an input device. + * + */ + +int +ProcXCloseDevice(client) + register ClientPtr client; + { + int i; + WindowPtr pWin, p1; + DeviceIntPtr d; + + REQUEST(xCloseDeviceReq); + REQUEST_SIZE_MATCH(xCloseDeviceReq); + + d = LookupDeviceIntRec (stuff->deviceid); + if (d == NULL) + { + SendErrorToClient(client, IReqCode, X_CloseDevice, 0, BadDevice); + return Success; + } + + if (d->grab && SameClient(d->grab, client)) + (*d->DeactivateGrab)(d); /* release active grab */ + + /* Remove event selections from all windows for events from this device + and selected by this client. + Delete passive grabs from all windows for this device. */ + + for (i=0; ifirstChild; + DeleteEventsFromChildren (d, p1, client); + } + + CloseInputDevice (d, client); + return Success; + } + +/*********************************************************************** + * + * Walk througth the window tree, deleting event selections for this client + * from this device from all windows. + * + */ + +DeleteEventsFromChildren(dev, p1, client) + DeviceIntPtr dev; + WindowPtr p1; + ClientPtr client; + { + WindowPtr p2; + + while (p1) + { + p2 = p1->firstChild; + DeleteDeviceEvents (dev, p1, client); + DeleteEventsFromChildren(dev, p2, client); + p1 = p1->nextSib; + } + } + +/*********************************************************************** + * + * Clear out event selections and passive grabs from a window for the + * specified device. + * + */ + +DeleteDeviceEvents (dev, pWin, client) + DeviceIntPtr dev; + WindowPtr pWin; + ClientPtr client; + { + InputClientsPtr others; + OtherInputMasks *pOthers; + GrabPtr grab, next; + + if (pOthers=wOtherInputMasks(pWin)) + for (others=pOthers->inputClients; others; + others = others->next) + if (SameClient(others,client)) + others->mask[dev->id] = NoEventMask; + + for (grab = wPassiveGrabs(pWin); grab; grab=next) + { + next = grab->next; + if ((grab->device == dev) && + (client->clientAsMask == CLIENT_BITS(grab->resource))) + FreeResource (grab->resource, RT_NONE); + } + } diff --git a/Xi/devbell.c b/Xi/devbell.c new file mode 100644 index 000000000..60e58e147 --- /dev/null +++ b/Xi/devbell.c @@ -0,0 +1,167 @@ +/* $Xorg: devbell.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to change the keyboard device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure is invoked to swap the request bytes if the server and + * client have a different byte order. + * + */ + +int +SProcXDeviceBell(client) + register ClientPtr client; + { + register char n; + + REQUEST(xDeviceBellReq); + swaps(&stuff->length, n); + return(ProcXDeviceBell(client)); + } + +/*********************************************************************** + * + * This procedure rings a bell on an extension device. + * + */ + +ProcXDeviceBell (client) + register ClientPtr client; + { + DeviceIntPtr dev; + KbdFeedbackPtr k; + BellFeedbackPtr b; + int base; + int newpercent; + CARD8 class; + pointer ctrl; + void (*proc)(); + + REQUEST(xDeviceBellReq); + REQUEST_SIZE_MATCH(xDeviceBellReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + client->errorValue = stuff->deviceid; + SendErrorToClient(client, IReqCode, X_DeviceBell, 0, BadDevice); + return Success; + } + + if (stuff->percent < -100 || stuff->percent > 100) + { + client->errorValue = stuff->percent; + SendErrorToClient(client, IReqCode, X_DeviceBell, 0, BadValue); + return Success; + } + if (stuff->feedbackclass == KbdFeedbackClass) + { + for (k=dev->kbdfeed; k; k=k->next) + if (k->ctrl.id == stuff->feedbackid) + break; + if (!k) + { + client->errorValue = stuff->feedbackid; + SendErrorToClient(client, IReqCode, X_DeviceBell, 0, BadValue); + return Success; + } + base = k->ctrl.bell; + proc = k->BellProc; + ctrl = (pointer) &(k->ctrl); + class = KbdFeedbackClass; + } + else if (stuff->feedbackclass == BellFeedbackClass) + { + for (b=dev->bell; b; b=b->next) + if (b->ctrl.id == stuff->feedbackid) + break; + if (!b) + { + client->errorValue = stuff->feedbackid; + SendErrorToClient(client, IReqCode, X_DeviceBell, 0, BadValue); + return Success; + } + base = b->ctrl.percent; + proc = b->BellProc; + ctrl = (pointer) &(b->ctrl); + class = BellFeedbackClass; + } + else + { + client->errorValue = stuff->feedbackclass; + SendErrorToClient(client, IReqCode, X_DeviceBell, 0, BadValue); + return Success; + } + newpercent = (base * stuff->percent) / 100; + if (stuff->percent < 0) + newpercent = base + newpercent; + else + newpercent = base - newpercent + stuff->percent; + (*proc)(newpercent, dev, ctrl, class); + + return Success; + } diff --git a/Xi/exevents.c b/Xi/exevents.c new file mode 100644 index 000000000..7131b3c7a --- /dev/null +++ b/Xi/exevents.c @@ -0,0 +1,1388 @@ +/* $Xorg: exevents.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Routines to register and initialize extension input devices. + * This also contains ProcessOtherEvent, the routine called from DDX + * to route extension events. + * + */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "XI.h" +#include "XIproto.h" +#include "inputstr.h" +#include "windowstr.h" +#include "miscstruct.h" +#include "region.h" + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define Motion_Filter(class) (DevicePointerMotionMask | \ + (class)->state | (class)->motionMask) + +void ActivateKeyboardGrab(); +void DeactivateKeyboardGrab(); +void ProcessOtherEvent(); +void RecalculateDeviceDeliverableEvents(); +static Bool ShouldFreeInputMasks(); +static Bool MakeInputMasks (); +extern int DeviceKeyPress; +extern int DeviceButtonPress; +extern int DeviceValuator; +extern Mask DevicePointerMotionMask; +extern Mask DeviceMappingNotifyMask; +extern Mask DeviceButtonMotionMask; +extern Mask DeviceButtonGrabMask; +extern Mask DeviceOwnerGrabButtonMask; +extern Mask PropagateMask[]; +extern WindowPtr GetSpriteWindow(); +extern InputInfo inputInfo; +extern int RT_INPUTCLIENT; + +/************************************************************************** + * + * Procedures for extension device event routing. + * + */ + +void +RegisterOtherDevice (device) + DevicePtr device; + { + device->processInputProc = ProcessOtherEvent; + device->realInputProc = ProcessOtherEvent; + ((DeviceIntPtr)device)->ActivateGrab = ActivateKeyboardGrab; + ((DeviceIntPtr)device)->DeactivateGrab = DeactivateKeyboardGrab; + } + +extern int DeviceMotionNotify; + +/*ARGSUSED*/ +void +ProcessOtherEvent (xE, other, count) + deviceKeyButtonPointer *xE; + register DeviceIntPtr other; + int count; + { + extern int DeviceKeyRelease; + extern int DeviceButtonRelease; + extern int ProximityIn; + extern int ProximityOut; + register BYTE *kptr; + register int i; + register CARD16 modifiers; + register CARD16 mask; + GrabPtr grab = other->grab; + Bool deactivateDeviceGrab = FALSE; + int key, bit, rootX, rootY; + ButtonClassPtr b = other->button; + KeyClassPtr k = other->key; + ValuatorClassPtr v = other->valuator; + void NoticeEventTime(); + deviceValuator *xV = (deviceValuator *) xE; + + if (xE->type != DeviceValuator) { + GetSpritePosition(&rootX, &rootY); + xE->root_x = rootX; + xE->root_y = rootY; + key = xE->detail; + NoticeEventTime(xE); + xE->state = inputInfo.keyboard->key->state | + inputInfo.pointer->button->state; + bit = 1 << (key & 7); + } + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = (xEventPtr) xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + for (i=1; itype == DeviceValuator) + { + int first = xV->first_valuator; + int *axisvals; + + if (xV->num_valuators && (!v || (xV->num_valuators && (first + xV->num_valuators > v->numAxes)))) + FatalError("Bad valuators reported for device %s\n",other->name); + xV->device_state = 0; + if (k) + xV->device_state |= k->state; + if (b) + xV->device_state |= b->state; + if (v && v->axisVal) + { + axisvals = v->axisVal; + switch (xV->num_valuators) { + case 6: + *(axisvals+first+5) = xV->valuator5; + case 5: + *(axisvals+first+4) = xV->valuator4; + case 4: + *(axisvals+first+3) = xV->valuator3; + case 3: + *(axisvals+first+2) = xV->valuator2; + case 2: + *(axisvals+first+1) = xV->valuator1; + case 1: + *(axisvals+first) = xV->valuator0; + case 0: + default: + break; + } + } + } + + if (xE->type == DeviceKeyPress) + { + modifiers = k->modifierMap[key]; + kptr = &k->down[key >> 3]; + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->type = DeviceKeyRelease; + ProcessOtherEvent(xE, other, count); + xE->type = DeviceKeyPress; + /* release can have side effects, don't fall through */ + ProcessOtherEvent(xE, other, count); + } + return; + } + if (other->valuator) + other->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + k->prev_state = k->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + k->modifierKeyCount[i]++; + k->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(other, xE, 0, count)) + { + other->activatingKey = key; + return; + } + } + else if (xE->type == DeviceKeyRelease) + { + kptr = &k->down[key >> 3]; + if (!(*kptr & bit)) /* guard against duplicates */ + return; + modifiers = k->modifierMap[key]; + if (other->valuator) + other->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + k->prev_state = k->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + if (--k->modifierKeyCount[i] <= 0) + { + k->modifierKeyCount[i] = 0; + k->state &= ~mask; + } + modifiers &= ~mask; + } + } + + if (other->fromPassiveGrab && (key == other->activatingKey)) + deactivateDeviceGrab = TRUE; + } + else if (xE->type == DeviceButtonPress) + { + kptr = &b->down[key >> 3]; + *kptr |= bit; + if (other->valuator) + other->valuator->motionHintWindow = NullWindow; + b->buttonsDown++; + b->motionMask = DeviceButtonMotionMask; + xE->detail = b->map[key]; + if (xE->detail == 0) + return; + if (xE->detail <= 5) + b->state |= (Button1Mask >> 1) << xE->detail; + SetMaskForEvent(Motion_Filter(b),DeviceMotionNotify); + if (!grab) + if (CheckDeviceGrabs(other, xE, 0, count)) + return; + + } + else if (xE->type == DeviceButtonRelease) + { + kptr = &b->down[key >> 3]; + *kptr &= ~bit; + if (other->valuator) + other->valuator->motionHintWindow = NullWindow; + if (!--b->buttonsDown) + b->motionMask = 0; + xE->detail = b->map[key]; + if (xE->detail == 0) + return; + if (xE->detail <= 5) + b->state &= ~((Button1Mask >> 1) << xE->detail); + SetMaskForEvent(Motion_Filter(b),DeviceMotionNotify); + if (!b->state && other->fromPassiveGrab) + deactivateDeviceGrab = TRUE; + } + else if (xE->type == ProximityIn) + other->valuator->mode &= ~OutOfProximity; + else if (xE->type == ProximityOut) + other->valuator->mode |= OutOfProximity; + + if (grab) + DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count); + else if (other->focus) + DeliverFocusedEvent(other, xE, GetSpriteWindow(), count); + else + DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow, + other, count); + + if (deactivateDeviceGrab == TRUE) + (*other->DeactivateGrab)(other); + } + +InitProximityClassDeviceStruct(dev) + DeviceIntPtr dev; + { + register ProximityClassPtr proxc; + + proxc = (ProximityClassPtr)xalloc(sizeof(ProximityClassRec)); + if (!proxc) + return FALSE; + dev->proximity = proxc; + return TRUE; + } + +InitValuatorAxisStruct(dev, axnum, minval, maxval, resolution, min_res, max_res) + DeviceIntPtr dev; + int axnum; + int minval; + int maxval; + int resolution; + { + register AxisInfoPtr ax = dev->valuator->axes + axnum; + + ax->min_value = minval; + ax->max_value = maxval; + ax->resolution = resolution; + ax->min_resolution = min_res; + ax->max_resolution = max_res; + } + +static void FixDeviceStateNotify (dev, ev, k, b, v, first) + DeviceIntPtr dev; + deviceStateNotify *ev; + KeyClassPtr k; + ButtonClassPtr b; + ValuatorClassPtr v; + int first; + { + extern int DeviceStateNotify; + + ev->type = DeviceStateNotify; + ev->deviceid = dev->id; + ev->time = currentTime.milliseconds; + ev->classes_reported = 0; + ev->num_keys = 0; + ev->num_buttons = 0; + ev->num_valuators = 0; + + if (b) { + ev->classes_reported |= (1 << ButtonClass); + ev->num_buttons = b->numButtons; + memmove((char *) &ev->buttons[0], (char *) b->down, 4); + } + else if (k) { + ev->classes_reported |= (1 << KeyClass); + ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode; + memmove((char *) &ev->keys[0], (char *) k->down, 4); + } + if (v) { + int nval = v->numAxes - first; + ev->classes_reported |= (1 << ValuatorClass); + ev->classes_reported |= (dev->valuator->mode << ModeBitsShift); + ev->num_valuators = nval < 3 ? nval : 3; + switch (ev->num_valuators) + { + case 3: + ev->valuator2 = v->axisVal[first+2]; + case 2: + ev->valuator1 = v->axisVal[first+1]; + case 1: + ev->valuator0 = v->axisVal[first]; + break; + } + } + } + +static void FixDeviceValuator (dev, ev, v, first) + DeviceIntPtr dev; + deviceValuator *ev; + ValuatorClassPtr v; + int first; + { + int nval = v->numAxes - first; + + ev->type = DeviceValuator; + ev->deviceid = dev->id; + ev->num_valuators = nval < 3 ? nval : 3; + ev->first_valuator = first; + switch (ev->num_valuators) { + case 3: + ev->valuator2 = v->axisVal[first+2]; + case 2: + ev->valuator1 = v->axisVal[first+1]; + case 1: + ev->valuator0 = v->axisVal[first]; + break; + } + first += ev->num_valuators; + } + +DeviceFocusEvent(dev, type, mode, detail, pWin) + DeviceIntPtr dev; + int type, mode, detail; + register WindowPtr pWin; + { + extern int DeviceFocusIn; + extern int DeviceFocusOut; + extern int DeviceKeyStateNotify; + extern int DeviceButtonStateNotify; + extern int DeviceValuatorStateNotify; + extern Mask DeviceStateNotifyMask; + extern Mask DeviceFocusChangeMask; + deviceFocus event; + + if (type == FocusIn) + type = DeviceFocusIn; + else + type = DeviceFocusOut; + + event.deviceid = dev->id; + event.mode = mode; + event.type = type; + event.detail = detail; + event.window = pWin->drawable.id; + event.time = currentTime.milliseconds; + + (void) + DeliverEventsToWindow(pWin, &event, 1, DeviceFocusChangeMask, NullGrab, + dev->id); + + if ((type == DeviceFocusIn) && + (wOtherInputMasks(pWin)) && + (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask)) + { + int i,j; + int evcount = 1; + deviceStateNotify *ev, *sev; + deviceKeyStateNotify *kev; + deviceButtonStateNotify *bev; + + KeyClassPtr k; + ButtonClassPtr b; + ValuatorClassPtr v; + int nval=0, nkeys=0, nbuttons=0, first=0; + + if ((b=dev->button) != NULL) { + nbuttons = b->numButtons; + if (nbuttons > 32) + evcount++; + } + if ((k=dev->key) != NULL) { + nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode; + if (nkeys > 32) + evcount++; + if (nbuttons > 0) { + evcount++; + } + } + if ((v=dev->valuator) != NULL) { + nval = v->numAxes; + + if (nval > 3) + evcount++; + if (nval > 6) { + if (!(k && b)) + evcount++; + if (nval > 9) + evcount += ((nval - 7) / 3); + } + } + + sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent)); + FixDeviceStateNotify (dev, ev, NULL, NULL, NULL, first); + + if (b != NULL) { + FixDeviceStateNotify (dev, ev++, NULL, b, v, first); + first += 3; + nval -= 3; + if (nbuttons > 32) { + (ev-1)->deviceid |= MORE_EVENTS; + bev = (deviceButtonStateNotify *) ev++; + bev->type = DeviceButtonStateNotify; + bev->deviceid = dev->id; + memmove((char *) &bev->buttons[0], (char *) &b->down[4], 28); + } + if (nval > 0) { + (ev-1)->deviceid |= MORE_EVENTS; + FixDeviceValuator (dev, (deviceValuator *) ev++, v, first); + first += 3; + nval -= 3; + } + } + + if (k != NULL) { + FixDeviceStateNotify (dev, ev++, k, NULL, v, first); + first += 3; + nval -= 3; + if (nkeys > 32) { + (ev-1)->deviceid |= MORE_EVENTS; + kev = (deviceKeyStateNotify *) ev++; + kev->type = DeviceKeyStateNotify; + kev->deviceid = dev->id; + memmove((char *) &kev->keys[0], (char *) &k->down[4], 28); + } + if (nval > 0) { + (ev-1)->deviceid |= MORE_EVENTS; + FixDeviceValuator (dev, (deviceValuator *) ev++, v, first); + first += 3; + nval -= 3; + } + } + + while (nval > 0) { + FixDeviceStateNotify (dev, ev++, NULL, NULL, v, first); + first += 3; + nval -= 3; + if (nval > 0) { + (ev-1)->deviceid |= MORE_EVENTS; + FixDeviceValuator (dev, ev++, v, first); + first += 3; + nval -= 3; + } + } + + (void) DeliverEventsToWindow(pWin, sev, evcount, DeviceStateNotifyMask, + NullGrab, dev->id); + xfree (sev); + } + } + +int +GrabButton(client, dev, this_device_mode, other_devices_mode, modifiers, + modifier_device, button, grabWindow, ownerEvents, rcursor, rconfineTo, + eventMask) + ClientPtr client; + DeviceIntPtr dev; + BYTE this_device_mode; + BYTE other_devices_mode; + CARD16 modifiers; + DeviceIntPtr modifier_device; + CARD8 button; + Window grabWindow; + BOOL ownerEvents; + Cursor rcursor; + Window rconfineTo; + Mask eventMask; + +{ + WindowPtr pWin, confineTo; + CursorPtr cursor; + GrabPtr CreateGrab(); + GrabPtr grab; + + if ((this_device_mode != GrabModeSync) && + (this_device_mode != GrabModeAsync)) + { + client->errorValue = this_device_mode; + return BadValue; + } + if ((other_devices_mode != GrabModeSync) && + (other_devices_mode != GrabModeAsync)) + { + client->errorValue = other_devices_mode; + return BadValue; + } + if ((modifiers != AnyModifier) && + (modifiers & ~AllModifiersMask)) + { + client->errorValue = modifiers; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = LookupWindow(grabWindow, client); + if (!pWin) + return BadWindow; + if (rconfineTo == None) + confineTo = NullWindow; + else + { + confineTo = LookupWindow(rconfineTo, client); + if (!confineTo) + return BadWindow; + } + if (rcursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)LookupIDByType(rcursor, RT_CURSOR); + if (!cursor) + { + client->errorValue = rcursor; + return BadCursor; + } + } + + grab = CreateGrab(client->index, dev, pWin, eventMask, + (Bool)ownerEvents, (Bool) this_device_mode, (Bool)other_devices_mode, + modifier_device, modifiers, DeviceButtonPress, button, confineTo, + cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); + } + +int +GrabKey(client, dev, this_device_mode, other_devices_mode, modifiers, + modifier_device, key, grabWindow, ownerEvents, mask) + ClientPtr client; + DeviceIntPtr dev; + BYTE this_device_mode; + BYTE other_devices_mode; + CARD16 modifiers; + DeviceIntPtr modifier_device; + CARD8 key; + Window grabWindow; + BOOL ownerEvents; + Mask mask; + +{ + WindowPtr pWin; + GrabPtr CreateGrab(); + GrabPtr grab; + KeyClassPtr k = dev->key; + + if (k==NULL) + return BadMatch; + if ((other_devices_mode != GrabModeSync) && + (other_devices_mode != GrabModeAsync)) + { + client->errorValue = other_devices_mode; + return BadValue; + } + if ((this_device_mode != GrabModeSync) && + (this_device_mode != GrabModeAsync)) + { + client->errorValue = this_device_mode; + return BadValue; + } + if (((key > k->curKeySyms.maxKeyCode) || + (key < k->curKeySyms.minKeyCode)) + && (key != AnyKey)) + { + client->errorValue = key; + return BadValue; + } + if ((modifiers != AnyModifier) && + (modifiers & ~AllModifiersMask)) + { + client->errorValue = modifiers; + return BadValue; + } + if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = LookupWindow(grabWindow, client); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, dev, pWin, + mask, ownerEvents, this_device_mode, other_devices_mode, + modifier_device, modifiers, DeviceKeyPress, key, NullWindow, + NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); + } + +extern Mask DevicePointerMotionHintMask; + +int +SelectForWindow(dev, pWin, client, mask, exclusivemasks, validmasks) + DeviceIntPtr dev; + WindowPtr pWin; + ClientPtr client; + Mask mask; + Mask exclusivemasks; + Mask validmasks; +{ + int mskidx = dev->id; + int i, ret; + Mask check; + InputClientsPtr others; + + if (mask & ~validmasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & exclusivemasks); + if (wOtherInputMasks(pWin)) + { + if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) + { /* It is illegal for two different + clients to select on any of the + events for maskcheck. However, + it is OK, for some client to + continue selecting on one of those + events. */ + for (others = wOtherInputMasks(pWin)->inputClients; others; + others = others->next) + { + if (!SameClient(others, client) && (check & + others->mask[mskidx])) + return BadAccess; + } + } + for (others = wOtherInputMasks(pWin)->inputClients; others; + others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask[mskidx]; + others->mask[mskidx] = mask; + if (mask == 0) + { + for (i=0; imask[i] != 0) + break; + if (i == EMASKSIZE) + { + RecalculateDeviceDeliverableEvents(pWin); + if (ShouldFreeInputMasks(pWin, FALSE)) + FreeResource(others->resource, RT_NONE); + return Success; + } + } + goto maskSet; + } + } + } + check = 0; + if ((ret = AddExtensionClient (pWin, client, mask, mskidx)) != Success) + return ret; +maskSet: + if (dev->valuator) + if ((dev->valuator->motionHintWindow == pWin) && + (mask & DevicePointerMotionHintMask) && + !(check & DevicePointerMotionHintMask) && + !dev->grab) + dev->valuator->motionHintWindow = NullWindow; + RecalculateDeviceDeliverableEvents(pWin); + return Success; +} + +int +AddExtensionClient (pWin, client, mask, mskidx) + WindowPtr pWin; + ClientPtr client; + Mask mask; + int mskidx; + { + InputClientsPtr others; + + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (InputClients *) xalloc(sizeof(InputClients)); + if (!others) + return BadAlloc; + if (!pWin->optional->inputMasks && !MakeInputMasks (pWin)) + return BadAlloc; + bzero((char *) &others->mask[0], sizeof(Mask)*EMASKSIZE); + others->mask[mskidx] = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->inputMasks->inputClients; + pWin->optional->inputMasks->inputClients = others; + if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer)pWin)) + return BadAlloc; + return Success; + } + +static Bool +MakeInputMasks (pWin) + WindowPtr pWin; + { + struct _OtherInputMasks *imasks; + + imasks = (struct _OtherInputMasks *) + xalloc (sizeof (struct _OtherInputMasks)); + if (!imasks) + return FALSE; + bzero((char *) imasks, sizeof (struct _OtherInputMasks)); + pWin->optional->inputMasks = imasks; + return TRUE; + } + +void +RecalculateDeviceDeliverableEvents(pWin) + WindowPtr pWin; + { + register InputClientsPtr others; + struct _OtherInputMasks *inputMasks; /* default: NULL */ + register WindowPtr pChild, tmp; + int i; + + pChild = pWin; + while (1) + { + if (inputMasks = wOtherInputMasks(pChild)) + { + for (others = inputMasks->inputClients; others; + others = others->next) + { + for (i=0; iinputEvents[i] |= others->mask[i]; + } + for (i=0; ideliverableEvents[i] = inputMasks->inputEvents[i]; + for (tmp = pChild->parent; tmp; tmp=tmp->parent) + if (wOtherInputMasks(tmp)) + for (i=0; ideliverableEvents[i] |= + (wOtherInputMasks(tmp)->deliverableEvents[i] + & ~inputMasks->dontPropagateMask[i] & PropagateMask[i]); + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + } + +int +InputClientGone(pWin, id) + register WindowPtr pWin; + XID id; + { + register InputClientsPtr other, prev; + if (!wOtherInputMasks(pWin)) + return(Success); + prev = 0; + for (other = wOtherInputMasks(pWin)->inputClients; other; + other = other->next) + { + if (other->resource == id) + { + if (prev) + { + prev->next = other->next; + xfree(other); + } + else if (!(other->next)) + { + if (ShouldFreeInputMasks(pWin, TRUE)) + { + wOtherInputMasks(pWin)->inputClients = other->next; + xfree(wOtherInputMasks(pWin)); + pWin->optional->inputMasks = (OtherInputMasks *) NULL; + CheckWindowOptionalNeed (pWin); + xfree(other); + } + else + { + other->resource = FakeClientID(0); + if (!AddResource(other->resource, RT_INPUTCLIENT, + (pointer)pWin)) + return BadAlloc; + } + } + else + { + wOtherInputMasks(pWin)->inputClients = other->next; + xfree(other); + } + RecalculateDeviceDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on device event list"); + /*NOTREACHED*/ + } + +int +SendEvent (client, d, dest, propagate, ev, mask, count) + ClientPtr client; + DeviceIntPtr d; + Window dest; + Bool propagate; + xEvent *ev; + Mask mask; + { + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + WindowPtr GetCurrentRootWindow(); + WindowPtr spriteWin=GetSpriteWindow(); + + if (dest == PointerWindow) + pWin = spriteWin; + else if (dest == InputFocus) + { + WindowPtr inputFocus; + + if (!d->focus) + inputFocus = spriteWin; + else + inputFocus = d->focus->win; + + if (inputFocus == FollowKeyboardWin) + inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = GetCurrentRootWindow(); + + if (IsParent(inputFocus, spriteWin)) + { + effectiveFocus = inputFocus; + pWin = spriteWin; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = LookupWindow(dest, client); + if (!pWin) + return BadWindow; + if ((propagate != xFalse) && (propagate != xTrue)) + { + client->errorValue = propagate; + return BadValue; + } + ev->u.u.type |= 0x80; + if (propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow( pWin, ev, count, mask, NullGrab, d->id)) + return Success; + if (pWin == effectiveFocus) + return Success; + if (wOtherInputMasks(pWin)) + mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id]; + if (!mask) + break; + } + } + else + (void)(DeliverEventsToWindow( pWin, ev, count, mask, NullGrab, d->id)); + return Success; + } + +int +SetButtonMapping (client, dev, nElts, map) + ClientPtr client; + DeviceIntPtr dev; + int nElts; + BYTE *map; + { + register int i; + ButtonClassPtr b = dev->button; + + if (b == NULL) + return BadMatch; + + if (nElts != b->numButtons) + { + client->errorValue = nElts; + return BadValue; + } + if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue)) + return BadValue; + for (i=0; i < nElts; i++) + if ((b->map[i + 1] != map[i]) && + BitIsOn(b->down, i + 1)) + return MappingBusy; + for (i = 0; i < nElts; i++) + b->map[i + 1] = map[i]; + return Success; + } + +int +SetModifierMapping(client, dev, len, rlen, numKeyPerModifier, inputMap, k) + ClientPtr client; + DeviceIntPtr dev; + int len; + int rlen; + int numKeyPerModifier; + KeyCode *inputMap; + KeyClassPtr *k; +{ + KeyCode *map; + int inputMapLen; + register int i; + + *k = dev->key; + if (*k == NULL) + return BadMatch; + if (len != ((numKeyPerModifier<<1) + rlen)) + return BadLength; + + inputMapLen = 8*numKeyPerModifier; + + /* + * Now enforce the restriction that "all of the non-zero keycodes must be + * in the range specified by min-keycode and max-keycode in the + * connection setup (else a Value error)" + */ + i = inputMapLen; + while (i--) { + if (inputMap[i] + && (inputMap[i] < (*k)->curKeySyms.minKeyCode + || inputMap[i] > (*k)->curKeySyms.maxKeyCode)) { + client->errorValue = inputMap[i]; + return -1; /* BadValue collides with MappingFailed */ + } + } + + /* + * Now enforce the restriction that none of the old or new + * modifier keys may be down while we change the mapping, and + * that the DDX layer likes the choice. + */ + if (!AllModifierKeysAreUp (dev, (*k)->modifierKeyMap, + (int)(*k)->maxKeysPerModifier, inputMap, (int)numKeyPerModifier) + || + !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier, + (*k)->modifierKeyMap, (int)(*k)->maxKeysPerModifier)) { + return MappingBusy; + } else { + for (i = 0; i < inputMapLen; i++) { + if (inputMap[i] && !LegalModifier(inputMap[i], (DevicePtr)dev)) { + return MappingFailed; + } + } + } + + /* + * Now build the keyboard's modifier bitmap from the + * list of keycodes. + */ + if (inputMapLen) { + map = (KeyCode *)xalloc(inputMapLen); + if (!map) + return BadAlloc; + } + if ((*k)->modifierKeyMap) + xfree((*k)->modifierKeyMap); + if (inputMapLen) { + (*k)->modifierKeyMap = map; + memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen); + } else + (*k)->modifierKeyMap = NULL; + + (*k)->maxKeysPerModifier = numKeyPerModifier; + for (i = 0; i < MAP_LENGTH; i++) + (*k)->modifierMap[i] = 0; + for (i = 0; i < inputMapLen; i++) if (inputMap[i]) { + (*k)->modifierMap[inputMap[i]] + |= (1<<(i/ (*k)->maxKeysPerModifier)); + } + + return(MappingSuccess); + } + +int +SendDeviceMappingNotify(request, firstKeyCode, count, dev) + CARD8 request, count; + KeyCode firstKeyCode; + DeviceIntPtr dev; + { + xEvent event; + deviceMappingNotify *ev = (deviceMappingNotify *) &event; + extern int DeviceMappingNotify; + + ev->type = DeviceMappingNotify; + ev->request = request; + ev->deviceid = dev->id; + ev->time = currentTime.milliseconds; + if (request == MappingKeyboard) + { + ev->firstKeyCode = firstKeyCode; + ev->count = count; + } + + SendEventToAllWindows (dev, DeviceMappingNotifyMask, ev, 1); + } + +int +ChangeKeyMapping(client, dev, len, type, firstKeyCode, keyCodes, + keySymsPerKeyCode, map) + ClientPtr client; + DeviceIntPtr dev; + unsigned len; + int type; + KeyCode firstKeyCode; + CARD8 keyCodes; + CARD8 keySymsPerKeyCode; + KeySym *map; +{ + KeySymsRec keysyms; + KeyClassPtr k = dev->key; + + if (k == NULL) + return (BadMatch); + + if (len != (keyCodes * keySymsPerKeyCode)) + return BadLength; + + if ((firstKeyCode < k->curKeySyms.minKeyCode) || + (firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) + { + client->errorValue = firstKeyCode; + return BadValue; + } + if (keySymsPerKeyCode == 0) + { + client->errorValue = 0; + return BadValue; + } + keysyms.minKeyCode = firstKeyCode; + keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; + keysyms.mapWidth = keySymsPerKeyCode; + keysyms.map = map; + if (!SetKeySymsMap(&k->curKeySyms, &keysyms)) + return BadAlloc; + SendDeviceMappingNotify(MappingKeyboard, firstKeyCode, keyCodes, + dev); + return client->noClientException; + } + +void +DeleteWindowFromAnyExtEvents(pWin, freeResources) + WindowPtr pWin; + Bool freeResources; + { + int i; + DeviceIntPtr dev; + InputClientsPtr ic; + struct _OtherInputMasks *inputMasks; + + for (dev=inputInfo.devices; dev; dev=dev->next) + { + if (dev == inputInfo.pointer || + dev == inputInfo.keyboard) + continue; + DeleteDeviceFromAnyExtEvents(pWin, dev); + } + + for (dev=inputInfo.off_devices; dev; dev=dev->next) + DeleteDeviceFromAnyExtEvents(pWin, dev); + + if (freeResources) + while (inputMasks = wOtherInputMasks(pWin)) + { + ic = inputMasks->inputClients; + for (i=0; idontPropagateMask[i] = 0; + FreeResource(ic->resource, RT_NONE); + } + } + +DeleteDeviceFromAnyExtEvents(pWin, dev) + WindowPtr pWin; + DeviceIntPtr dev; + { + WindowPtr parent; + + /* Deactivate any grabs performed on this window, before making + any input focus changes. + Deactivating a device grab should cause focus events. */ + + if (dev->grab && (dev->grab->window == pWin)) + (*dev->DeactivateGrab)(dev); + + /* If the focus window is a root window (ie. has no parent) + then don't delete the focus from it. */ + + if (dev->focus && (pWin==dev->focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (dev->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (dev->focus->revert) + { + case RevertToNone: + DoFocusEvents(dev, pWin, NoneWin, focusEventMode); + dev->focus->win = NoneWin; + dev->focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + dev->focus->traceGood--; + } while (!parent->realized); + DoFocusEvents(dev, pWin, parent, focusEventMode); + dev->focus->win = parent; + dev->focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); + dev->focus->win = PointerRootWin; + dev->focus->traceGood = 0; + break; + case RevertToFollowKeyboard: + if (inputInfo.keyboard->focus->win) { + DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win, + focusEventMode); + dev->focus->win = FollowKeyboardWin; + dev->focus->traceGood = 0; + } else { + DoFocusEvents(dev, pWin, NoneWin, focusEventMode); + dev->focus->win = NoneWin; + dev->focus->traceGood = 0; + } + break; + } + } + + if (dev->valuator) + if (dev->valuator->motionHintWindow == pWin) + dev->valuator->motionHintWindow = NullWindow; + } + +int +MaybeSendDeviceMotionNotifyHint (pEvents, mask) + deviceKeyButtonPointer *pEvents; + Mask mask; + { + DeviceIntPtr dev; + DeviceIntPtr LookupDeviceIntRec (); + + dev = LookupDeviceIntRec (pEvents->deviceid & DEVICE_BITS); + if (pEvents->type == DeviceMotionNotify) + { + if (mask & DevicePointerMotionHintMask) + { + if (WID(dev->valuator->motionHintWindow) == pEvents->event) + { + return 1; /* don't send, but pretend we did */ + } + pEvents->detail = NotifyHint; + } + else + { + pEvents->detail = NotifyNormal; + } + } + return (0); + } + +int +CheckDeviceGrabAndHintWindow (pWin, type, xE, grab, client, deliveryMask) + WindowPtr pWin; + int type; + deviceKeyButtonPointer *xE; + GrabPtr grab; + ClientPtr client; + Mask deliveryMask; + { + DeviceIntPtr dev; + DeviceIntPtr LookupDeviceIntRec (); + + dev = LookupDeviceIntRec (xE->deviceid & DEVICE_BITS); + if (type == DeviceMotionNotify) + dev->valuator->motionHintWindow = pWin; + else if ((type == DeviceButtonPress) && (!grab) && + (deliveryMask & DeviceButtonGrabMask)) + { + GrabRec tempGrab; + + tempGrab.device = dev; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*dev->ActivateGrab)(dev, &tempGrab, currentTime, TRUE); + } + } + +Mask +DeviceEventMaskForClient(dev, pWin, client) + DeviceIntPtr dev; + WindowPtr pWin; + ClientPtr client; + { + register InputClientsPtr other; + + if (!wOtherInputMasks(pWin)) + return 0; + for (other = wOtherInputMasks(pWin)->inputClients; other; + other = other->next) + { + if (SameClient(other, client)) + return other->mask[dev->id]; + } + return 0; + } + +void +MaybeStopDeviceHint(dev, client) + register DeviceIntPtr dev; + ClientPtr client; +{ + WindowPtr pWin; + GrabPtr grab = dev->grab; + pWin = dev->valuator->motionHintWindow; + + if ((grab && SameClient(grab, client) && + ((grab->eventMask & DevicePointerMotionHintMask) || + (grab->ownerEvents && + (DeviceEventMaskForClient(dev, pWin, client) & + DevicePointerMotionHintMask)))) || + (!grab && + (DeviceEventMaskForClient(dev, pWin, client) & + DevicePointerMotionHintMask))) + dev->valuator->motionHintWindow = NullWindow; +} + +int +DeviceEventSuppressForWindow(pWin, client, mask, maskndx) + WindowPtr pWin; + ClientPtr client; + Mask mask; + int maskndx; + { + struct _OtherInputMasks *inputMasks = wOtherInputMasks (pWin); + + if (mask & ~PropagateMask[maskndx]) + { + client->errorValue = mask; + return BadValue; + } + + if (mask == 0) + { + if (inputMasks) + inputMasks->dontPropagateMask[maskndx] = mask; + } + else + { + if (!inputMasks) + AddExtensionClient (pWin, client, 0, 0); + inputMasks = wOtherInputMasks(pWin); + inputMasks->dontPropagateMask[maskndx] = mask; + } + RecalculateDeviceDeliverableEvents(pWin); + if (ShouldFreeInputMasks(pWin, FALSE)) + FreeResource(inputMasks->inputClients->resource, RT_NONE); + return Success; + } + +static Bool +ShouldFreeInputMasks (pWin, ignoreSelectedEvents) + WindowPtr pWin; + Bool ignoreSelectedEvents; + { + int i; + Mask allInputEventMasks = 0; + struct _OtherInputMasks *inputMasks = wOtherInputMasks (pWin); + + for (i=0; idontPropagateMask[i]; + if (!ignoreSelectedEvents) + for (i=0; iinputEvents[i]; + if (allInputEventMasks == 0) + return TRUE; + else + return FALSE; + } diff --git a/Xi/extinit.c b/Xi/extinit.c new file mode 100644 index 000000000..37148ebd2 --- /dev/null +++ b/Xi/extinit.c @@ -0,0 +1,962 @@ +/* $Xorg: extinit.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Dispatch routines and initialization routines for the X input extension. + * + */ + +#define NUMTYPES 15 + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "gcstruct.h" /* pointer for extnsionst.h*/ +#include "extnsionst.h" /* extension entry */ +#include "XI.h" +#include "XIproto.h" + +static Mask lastExtEventMask = 1; +int ExtEventIndex; +Mask ExtValidMasks[EMASKSIZE]; +Mask ExtExclusiveMasks[EMASKSIZE]; + +struct dev_type + { + Atom type; + char *name; + }dev_type [] = {{0,XI_KEYBOARD}, + {0,XI_MOUSE}, + {0,XI_TABLET}, + {0,XI_TOUCHSCREEN}, + {0,XI_TOUCHPAD}, + {0,XI_BARCODE}, + {0,XI_BUTTONBOX}, + {0,XI_KNOB_BOX}, + {0,XI_ONE_KNOB}, + {0,XI_NINE_KNOB}, + {0,XI_TRACKBALL}, + {0,XI_QUADRATURE}, + {0,XI_ID_MODULE}, + {0,XI_SPACEBALL}, + {0,XI_DATAGLOVE}, + {0,XI_EYETRACKER}, + {0,XI_CURSORKEYS}, + {0,XI_FOOTMOUSE}}; + +CARD8 event_base [numInputClasses]; +XExtEventInfo EventInfo[32]; + +/***************************************************************** + * + * Globals referenced elsewhere in the server. + * + */ + +int IReqCode = 0; +int BadDevice = 0; +int BadEvent = 1; +int BadMode = 2; +int DeviceBusy = 3; +int BadClass = 4; + +Mask DevicePointerMotionMask; +Mask DevicePointerMotionHintMask; +Mask DeviceFocusChangeMask; +Mask DeviceStateNotifyMask; +Mask ChangeDeviceNotifyMask; +Mask DeviceMappingNotifyMask; +Mask DeviceOwnerGrabButtonMask; +Mask DeviceButtonGrabMask; +Mask DeviceButtonMotionMask; + +int DeviceValuator; +int DeviceKeyPress; +int DeviceKeyRelease; +int DeviceButtonPress; +int DeviceButtonRelease; +int DeviceMotionNotify; +int DeviceFocusIn; +int DeviceFocusOut; +int ProximityIn; +int ProximityOut; +int DeviceStateNotify; +int DeviceKeyStateNotify; +int DeviceButtonStateNotify; +int DeviceMappingNotify; +int ChangeDeviceNotify; + +int RT_INPUTCLIENT; + +/***************************************************************** + * + * Externs defined elsewhere in the X server. + * + */ + +extern void (* ReplySwapVector[256]) (); +extern void (* EventSwapVector[128]) (); +extern XExtensionVersion AllExtensionVersions[]; +extern InputInfo inputInfo; +Mask PropagateMask[MAX_DEVICES]; + +/***************************************************************** + * + * Declarations of local routines. + * + */ + +int ProcIDispatch(); +int SProcIDispatch(); +void SReplyIDispatch(); +void IResetProc(); +void SEventIDispatch(); +void NotImplemented(); +static XExtensionVersion thisversion = + {XI_Present, + XI_Add_XChangeDeviceControl_Major, + XI_Add_XChangeDeviceControl_Minor}; + +/********************************************************************** + * + * IExtensionInit - initialize the input extension. + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + * This extension has several events and errors. + * + */ + +void +XInputExtensionInit() + { + ExtensionEntry *extEntry, *AddExtension(); + int XShutDownDevice(); + int InputClientGone(); + + extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch, + SProcIDispatch, IResetProc, StandardMinorOpcode); + if (extEntry) + { + IReqCode = extEntry->base; + AllExtensionVersions[IReqCode-128] = thisversion; + MakeDeviceTypeAtoms (); + RT_INPUTCLIENT = CreateNewResourceType(InputClientGone); + FixExtensionEvents (extEntry); + ReplySwapVector[IReqCode] = SReplyIDispatch; + EventSwapVector[DeviceValuator] = SEventIDispatch; + EventSwapVector[DeviceKeyPress] = SEventIDispatch; + EventSwapVector[DeviceKeyRelease] = SEventIDispatch; + EventSwapVector[DeviceButtonPress] = SEventIDispatch; + EventSwapVector[DeviceButtonRelease] = SEventIDispatch; + EventSwapVector[DeviceMotionNotify] = SEventIDispatch; + EventSwapVector[DeviceFocusIn] = SEventIDispatch; + EventSwapVector[DeviceFocusOut] = SEventIDispatch; + EventSwapVector[ProximityIn] = SEventIDispatch; + EventSwapVector[ProximityOut] = SEventIDispatch; + EventSwapVector[DeviceStateNotify] = SEventIDispatch; + EventSwapVector[DeviceKeyStateNotify] = SEventIDispatch; + EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch; + EventSwapVector[DeviceMappingNotify] = SEventIDispatch; + EventSwapVector[ChangeDeviceNotify] = SEventIDispatch; + } + else + { + FatalError("IExtensionInit: AddExtensions failed\n"); + } + } + +/************************************************************************* + * + * ProcIDispatch - main dispatch routine for requests to this extension. + * This routine is used if server and client have the same byte ordering. + * + */ + +int +ProcIDispatch (client) + register ClientPtr client; + { + REQUEST(xReq); + if (stuff->data == X_GetExtensionVersion) + return(ProcXGetExtensionVersion(client)); + if (stuff->data == X_ListInputDevices) + return(ProcXListInputDevices(client)); + else if (stuff->data == X_OpenDevice) + return(ProcXOpenDevice(client)); + else if (stuff->data == X_CloseDevice) + return(ProcXCloseDevice(client)); + else if (stuff->data == X_SetDeviceMode) + return(ProcXSetDeviceMode(client)); + else if (stuff->data == X_SelectExtensionEvent) + return(ProcXSelectExtensionEvent(client)); + else if (stuff->data == X_GetSelectedExtensionEvents) + return(ProcXGetSelectedExtensionEvents(client)); + else if (stuff->data == X_ChangeDeviceDontPropagateList) + return(ProcXChangeDeviceDontPropagateList(client)); + else if (stuff->data == X_GetDeviceDontPropagateList) + return(ProcXGetDeviceDontPropagateList(client)); + else if (stuff->data == X_GetDeviceMotionEvents) + return(ProcXGetDeviceMotionEvents(client)); + else if (stuff->data == X_ChangeKeyboardDevice) + return(ProcXChangeKeyboardDevice(client)); + else if (stuff->data == X_ChangePointerDevice) + return(ProcXChangePointerDevice(client)); + else if (stuff->data == X_GrabDevice) + return(ProcXGrabDevice(client)); + else if (stuff->data == X_UngrabDevice) + return(ProcXUngrabDevice(client)); + else if (stuff->data == X_GrabDeviceKey) + return(ProcXGrabDeviceKey(client)); + else if (stuff->data == X_UngrabDeviceKey) + return(ProcXUngrabDeviceKey(client)); + else if (stuff->data == X_GrabDeviceButton) + return(ProcXGrabDeviceButton(client)); + else if (stuff->data == X_UngrabDeviceButton) + return(ProcXUngrabDeviceButton(client)); + else if (stuff->data == X_AllowDeviceEvents) + return(ProcXAllowDeviceEvents(client)); + else if (stuff->data == X_GetDeviceFocus) + return(ProcXGetDeviceFocus(client)); + else if (stuff->data == X_SetDeviceFocus) + return(ProcXSetDeviceFocus(client)); + else if (stuff->data == X_GetFeedbackControl) + return(ProcXGetFeedbackControl(client)); + else if (stuff->data == X_ChangeFeedbackControl) + return(ProcXChangeFeedbackControl(client)); + else if (stuff->data == X_GetDeviceKeyMapping) + return(ProcXGetDeviceKeyMapping(client)); + else if (stuff->data == X_ChangeDeviceKeyMapping) + return(ProcXChangeDeviceKeyMapping(client)); + else if (stuff->data == X_GetDeviceModifierMapping) + return(ProcXGetDeviceModifierMapping(client)); + else if (stuff->data == X_SetDeviceModifierMapping) + return(ProcXSetDeviceModifierMapping(client)); + else if (stuff->data == X_GetDeviceButtonMapping) + return(ProcXGetDeviceButtonMapping(client)); + else if (stuff->data == X_SetDeviceButtonMapping) + return(ProcXSetDeviceButtonMapping(client)); + else if (stuff->data == X_QueryDeviceState) + return(ProcXQueryDeviceState(client)); + else if (stuff->data == X_SendExtensionEvent) + return(ProcXSendExtensionEvent(client)); + else if (stuff->data == X_DeviceBell) + return(ProcXDeviceBell(client)); + else if (stuff->data == X_SetDeviceValuators) + return(ProcXSetDeviceValuators(client)); + else if (stuff->data == X_GetDeviceControl) + return(ProcXGetDeviceControl(client)); + else if (stuff->data == X_ChangeDeviceControl) + return(ProcXChangeDeviceControl(client)); + else + { + SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest); + } + return(BadRequest); + } + +/******************************************************************************* + * + * SProcXDispatch + * + * Main swapped dispatch routine for requests to this extension. + * This routine is used if server and client do not have the same byte ordering. + * + */ + +int +SProcIDispatch(client) + register ClientPtr client; + { + REQUEST(xReq); + if (stuff->data == X_GetExtensionVersion) + return(SProcXGetExtensionVersion(client)); + if (stuff->data == X_ListInputDevices) + return(SProcXListInputDevices(client)); + else if (stuff->data == X_OpenDevice) + return(SProcXOpenDevice(client)); + else if (stuff->data == X_CloseDevice) + return(SProcXCloseDevice(client)); + else if (stuff->data == X_SetDeviceMode) + return(SProcXSetDeviceMode(client)); + else if (stuff->data == X_SelectExtensionEvent) + return(SProcXSelectExtensionEvent(client)); + else if (stuff->data == X_GetSelectedExtensionEvents) + return(SProcXGetSelectedExtensionEvents(client)); + else if (stuff->data == X_ChangeDeviceDontPropagateList) + return(SProcXChangeDeviceDontPropagateList(client)); + else if (stuff->data == X_GetDeviceDontPropagateList) + return(SProcXGetDeviceDontPropagateList(client)); + else if (stuff->data == X_GetDeviceMotionEvents) + return(SProcXGetDeviceMotionEvents(client)); + else if (stuff->data == X_ChangeKeyboardDevice) + return(SProcXChangeKeyboardDevice(client)); + else if (stuff->data == X_ChangePointerDevice) + return(SProcXChangePointerDevice(client)); + else if (stuff->data == X_GrabDevice) + return(SProcXGrabDevice(client)); + else if (stuff->data == X_UngrabDevice) + return(SProcXUngrabDevice(client)); + else if (stuff->data == X_GrabDeviceKey) + return(SProcXGrabDeviceKey(client)); + else if (stuff->data == X_UngrabDeviceKey) + return(SProcXUngrabDeviceKey(client)); + else if (stuff->data == X_GrabDeviceButton) + return(SProcXGrabDeviceButton(client)); + else if (stuff->data == X_UngrabDeviceButton) + return(SProcXUngrabDeviceButton(client)); + else if (stuff->data == X_AllowDeviceEvents) + return(SProcXAllowDeviceEvents(client)); + else if (stuff->data == X_GetDeviceFocus) + return(SProcXGetDeviceFocus(client)); + else if (stuff->data == X_SetDeviceFocus) + return(SProcXSetDeviceFocus(client)); + else if (stuff->data == X_GetFeedbackControl) + return(SProcXGetFeedbackControl(client)); + else if (stuff->data == X_ChangeFeedbackControl) + return(SProcXChangeFeedbackControl(client)); + else if (stuff->data == X_GetDeviceKeyMapping) + return(SProcXGetDeviceKeyMapping(client)); + else if (stuff->data == X_ChangeDeviceKeyMapping) + return(SProcXChangeDeviceKeyMapping(client)); + else if (stuff->data == X_GetDeviceModifierMapping) + return(SProcXGetDeviceModifierMapping(client)); + else if (stuff->data == X_SetDeviceModifierMapping) + return(SProcXSetDeviceModifierMapping(client)); + else if (stuff->data == X_GetDeviceButtonMapping) + return(SProcXGetDeviceButtonMapping(client)); + else if (stuff->data == X_SetDeviceButtonMapping) + return(SProcXSetDeviceButtonMapping(client)); + else if (stuff->data == X_QueryDeviceState) + return(SProcXQueryDeviceState(client)); + else if (stuff->data == X_SendExtensionEvent) + return(SProcXSendExtensionEvent(client)); + else if (stuff->data == X_DeviceBell) + return(SProcXDeviceBell(client)); + else if (stuff->data == X_SetDeviceValuators) + return(SProcXSetDeviceValuators(client)); + else if (stuff->data == X_GetDeviceControl) + return(SProcXGetDeviceControl(client)); + else if (stuff->data == X_ChangeDeviceControl) + return(SProcXChangeDeviceControl(client)); + else + { + SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest); + } + return(BadRequest); + } + +/********************************************************************** + * + * SReplyIDispatch + * Swap any replies defined in this extension. + * + */ + +void +SReplyIDispatch (client, len, rep) + ClientPtr client; + int len; + xGrabDeviceReply *rep; /* All we look at is the type field */ + { /* This is common to all replies */ + if (rep->RepType == X_GetExtensionVersion) + SRepXGetExtensionVersion (client, len, rep); + else if (rep->RepType == X_ListInputDevices) + SRepXListInputDevices (client, len, rep); + else if (rep->RepType == X_OpenDevice) + SRepXOpenDevice (client, len, rep); + else if (rep->RepType == X_SetDeviceMode) + SRepXSetDeviceMode (client, len, rep); + else if (rep->RepType == X_GetSelectedExtensionEvents) + SRepXGetSelectedExtensionEvents (client, len, rep); + else if (rep->RepType == X_GetDeviceDontPropagateList) + SRepXGetDeviceDontPropagateList (client, len, rep); + else if (rep->RepType == X_GetDeviceMotionEvents) + SRepXGetDeviceMotionEvents (client, len, rep); + else if (rep->RepType == X_ChangeKeyboardDevice) + SRepXChangeKeyboardDevice (client, len, rep); + else if (rep->RepType == X_ChangePointerDevice) + SRepXChangePointerDevice (client, len, rep); + else if (rep->RepType == X_GrabDevice) + SRepXGrabDevice (client, len, rep); + else if (rep->RepType == X_GetDeviceFocus) + SRepXGetDeviceFocus (client, len, rep); + else if (rep->RepType == X_GetFeedbackControl) + SRepXGetFeedbackControl (client, len, rep); + else if (rep->RepType == X_GetDeviceKeyMapping) + SRepXGetDeviceKeyMapping (client, len, rep); + else if (rep->RepType == X_GetDeviceModifierMapping) + SRepXGetDeviceModifierMapping (client, len, rep); + else if (rep->RepType == X_SetDeviceModifierMapping) + SRepXSetDeviceModifierMapping (client, len, rep); + else if (rep->RepType == X_GetDeviceButtonMapping) + SRepXGetDeviceButtonMapping (client, len, rep); + else if (rep->RepType == X_SetDeviceButtonMapping) + SRepXSetDeviceButtonMapping (client, len, rep); + else if (rep->RepType == X_QueryDeviceState) + SRepXQueryDeviceState (client, len, rep); + else if (rep->RepType == X_SetDeviceValuators) + SRepXSetDeviceValuators (client, len, rep); + else if (rep->RepType == X_GetDeviceControl) + SRepXGetDeviceControl (client, len, rep); + else if (rep->RepType == X_ChangeDeviceControl) + SRepXChangeDeviceControl (client, len, rep); + else + { + FatalError("XINPUT confused sending swapped reply"); + } + } + +/***************************************************************************** + * + * SEventIDispatch + * + * Swap any events defined in this extension. + */ +void +SEventIDispatch (from, to) + xEvent *from; + xEvent *to; + { + int type = from->u.u.type & 0177; + + if (type == DeviceValuator) + SEventDeviceValuator (from, to); + else if (type == DeviceKeyPress) + { + SKeyButtonPtrEvent (from, to); + to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; + } + else if (type == DeviceKeyRelease) + { + SKeyButtonPtrEvent (from, to); + to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; + } + else if (type == DeviceButtonPress) + { + SKeyButtonPtrEvent (from, to); + to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; + } + else if (type == DeviceButtonRelease) + { + SKeyButtonPtrEvent (from, to); + to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; + } + else if (type == DeviceMotionNotify) + { + SKeyButtonPtrEvent (from, to); + to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; + } + else if (type == DeviceFocusIn) + SEventFocus (from, to); + else if (type == DeviceFocusOut) + SEventFocus (from, to); + else if (type == ProximityIn) + { + SKeyButtonPtrEvent (from, to); + to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; + } + else if (type == ProximityOut) + { + SKeyButtonPtrEvent (from, to); + to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; + } + else if (type == DeviceStateNotify) + SDeviceStateNotifyEvent (from, to); + else if (type == DeviceKeyStateNotify) + SDeviceKeyStateNotifyEvent (from, to); + else if (type == DeviceButtonStateNotify) + SDeviceButtonStateNotifyEvent (from, to); + else if (type == DeviceMappingNotify) + SDeviceMappingNotifyEvent (from, to); + else if (type == ChangeDeviceNotify) + SChangeDeviceNotifyEvent (from, to); + else + { + FatalError("XInputExtension: Impossible event!\n"); + } + } + +/************************************************************************ + * + * This function swaps the DeviceValuator event. + * + */ + +SEventDeviceValuator (from, to) + deviceValuator *from; + deviceValuator *to; + { + register char n; + register int i; + INT32 *ip B32; + + *to = *from; + swaps(&to->sequenceNumber,n); + swaps(&to->device_state,n); + ip = &to->valuator0; + for (i=0; i<6; i++) + { + swapl((ip+i),n); /* macro - braces are required */ + } + } + +SEventFocus (from, to) + deviceFocus *from; + deviceFocus *to; + { + register char n; + + *to = *from; + swaps(&to->sequenceNumber,n); + swapl(&to->time, n); + swapl(&to->window, n); + } + +SDeviceStateNotifyEvent (from, to) + deviceStateNotify *from; + deviceStateNotify *to; + { + register int i; + register char n; + INT32 *ip B32; + + *to = *from; + swaps(&to->sequenceNumber,n); + swapl(&to->time, n); + ip = &to->valuator0; + for (i=0; i<3; i++) + { + swapl((ip+i),n); /* macro - braces are required */ + } + } + +SDeviceKeyStateNotifyEvent (from, to) + deviceKeyStateNotify *from; + deviceKeyStateNotify *to; + { + register char n; + + *to = *from; + swaps(&to->sequenceNumber,n); + } + +SDeviceButtonStateNotifyEvent (from, to) + deviceButtonStateNotify *from; + deviceButtonStateNotify *to; + { + register char n; + + *to = *from; + swaps(&to->sequenceNumber,n); + } + +SChangeDeviceNotifyEvent (from, to) + changeDeviceNotify *from; + changeDeviceNotify *to; + { + register char n; + + *to = *from; + swaps(&to->sequenceNumber,n); + swapl(&to->time, n); + } + +SDeviceMappingNotifyEvent (from, to) + deviceMappingNotify *from; + deviceMappingNotify *to; + { + register char n; + + *to = *from; + swaps(&to->sequenceNumber,n); + swapl(&to->time, n); + } + +/************************************************************************ + * + * This function sets up extension event types and masks. + * + */ + +FixExtensionEvents (extEntry) + ExtensionEntry *extEntry; + { + Mask mask, GetNextExtEventMask(); + void SetMaskForExtEvent(); + void SetEventInfo(); + void AllowPropagateSuppress(); + void SetExclusiveAccess(); + + DeviceValuator = extEntry->eventBase; + DeviceKeyPress = DeviceValuator + 1; + DeviceKeyRelease = DeviceKeyPress + 1; + DeviceButtonPress = DeviceKeyRelease + 1; + DeviceButtonRelease = DeviceButtonPress + 1; + DeviceMotionNotify = DeviceButtonRelease + 1; + DeviceFocusIn = DeviceMotionNotify + 1; + DeviceFocusOut = DeviceFocusIn + 1; + ProximityIn = DeviceFocusOut + 1; + ProximityOut = ProximityIn + 1; + DeviceStateNotify = ProximityOut + 1; + DeviceMappingNotify = DeviceStateNotify + 1; + ChangeDeviceNotify = DeviceMappingNotify + 1; + DeviceKeyStateNotify = ChangeDeviceNotify + 1; + DeviceButtonStateNotify = DeviceKeyStateNotify + 1; + + event_base[KeyClass] = DeviceKeyPress; + event_base[ButtonClass] = DeviceButtonPress; + event_base[ValuatorClass] = DeviceMotionNotify; + event_base[ProximityClass] = ProximityIn; + event_base[FocusClass] = DeviceFocusIn; + event_base[OtherClass] = DeviceStateNotify; + + BadDevice += extEntry->errorBase; + BadEvent += extEntry->errorBase; + BadMode += extEntry->errorBase; + DeviceBusy += extEntry->errorBase; + BadClass += extEntry->errorBase; + + mask = GetNextExtEventMask (); + SetMaskForExtEvent (mask, DeviceKeyPress); + AllowPropagateSuppress (mask); + + mask = GetNextExtEventMask (); + SetMaskForExtEvent (mask, DeviceKeyRelease); + AllowPropagateSuppress (mask); + + mask = GetNextExtEventMask (); + SetMaskForExtEvent (mask, DeviceButtonPress); + AllowPropagateSuppress (mask); + + mask = GetNextExtEventMask (); + SetMaskForExtEvent (mask, DeviceButtonRelease); + AllowPropagateSuppress (mask); + + mask = GetNextExtEventMask (); + SetMaskForExtEvent (mask, ProximityIn); + SetMaskForExtEvent (mask, ProximityOut); + AllowPropagateSuppress (mask); + + mask = GetNextExtEventMask (); + DeviceStateNotifyMask = mask; + SetMaskForExtEvent (mask, DeviceStateNotify); + + mask = GetNextExtEventMask (); + DevicePointerMotionMask = mask; + SetMaskForExtEvent (mask, DeviceMotionNotify); + AllowPropagateSuppress (mask); + + DevicePointerMotionHintMask = GetNextExtEventMask(); + SetEventInfo (DevicePointerMotionHintMask, _devicePointerMotionHint); + SetEventInfo (GetNextExtEventMask(), _deviceButton1Motion); + SetEventInfo (GetNextExtEventMask(), _deviceButton2Motion); + SetEventInfo (GetNextExtEventMask(), _deviceButton3Motion); + SetEventInfo (GetNextExtEventMask(), _deviceButton4Motion); + SetEventInfo (GetNextExtEventMask(), _deviceButton5Motion); + DeviceButtonMotionMask = GetNextExtEventMask(); + SetEventInfo (DeviceButtonMotionMask, _deviceButtonMotion); + + DeviceFocusChangeMask = GetNextExtEventMask (); + SetMaskForExtEvent (DeviceFocusChangeMask, DeviceFocusIn); + SetMaskForExtEvent (DeviceFocusChangeMask, DeviceFocusOut); + + mask = GetNextExtEventMask (); + SetMaskForExtEvent (mask, DeviceMappingNotify); + DeviceMappingNotifyMask = mask; + + mask = GetNextExtEventMask (); + SetMaskForExtEvent (mask, ChangeDeviceNotify); + ChangeDeviceNotifyMask = mask; + + DeviceButtonGrabMask = GetNextExtEventMask(); + SetEventInfo (DeviceButtonGrabMask, _deviceButtonGrab); + SetExclusiveAccess (DeviceButtonGrabMask); + + DeviceOwnerGrabButtonMask = GetNextExtEventMask(); + SetEventInfo (DeviceOwnerGrabButtonMask, _deviceOwnerGrabButton); + SetEventInfo (0, _noExtensionEvent); + } + +/************************************************************************ + * + * This function restores extension event types and masks to their + * initial state. + * + */ + +RestoreExtensionEvents () + { + int i; + + IReqCode = 0; + + for (i=0; i= LASTEvent) && (EventInfo[i].type < 128)) + SetMaskForEvent(0,EventInfo[i].type); + EventInfo[i].mask = 0; + EventInfo[i].type = 0; + } + ExtEventIndex = 0; + lastExtEventMask = 1; + DeviceValuator = 0; + DeviceKeyPress = 1; + DeviceKeyRelease = 2; + DeviceButtonPress = 3; + DeviceButtonRelease = 4; + DeviceMotionNotify = 5; + DeviceFocusIn = 6; + DeviceFocusOut = 7; + ProximityIn = 8; + ProximityOut = 9; + DeviceStateNotify = 10; + DeviceMappingNotify = 11; + ChangeDeviceNotify = 12; + DeviceKeyStateNotify = 13; + DeviceButtonStateNotify = 13; + + BadDevice = 0; + BadEvent = 1; + BadMode = 2; + DeviceBusy = 3; + BadClass = 4; + + } + +/*********************************************************************** + * + * IResetProc. + * Remove reply-swapping routine. + * Remove event-swapping routine. + * + */ + +void +IResetProc() + { + + ReplySwapVector[IReqCode] = NotImplemented; + EventSwapVector[DeviceValuator] = NotImplemented; + EventSwapVector[DeviceKeyPress] = NotImplemented; + EventSwapVector[DeviceKeyRelease] = NotImplemented; + EventSwapVector[DeviceButtonPress] = NotImplemented; + EventSwapVector[DeviceButtonRelease] = NotImplemented; + EventSwapVector[DeviceMotionNotify] = NotImplemented; + EventSwapVector[DeviceFocusIn] = NotImplemented; + EventSwapVector[DeviceFocusOut] = NotImplemented; + EventSwapVector[ProximityIn] = NotImplemented; + EventSwapVector[ProximityOut] = NotImplemented; + EventSwapVector[DeviceStateNotify] = NotImplemented; + EventSwapVector[DeviceKeyStateNotify] = NotImplemented; + EventSwapVector[DeviceButtonStateNotify] = NotImplemented; + EventSwapVector[DeviceMappingNotify] = NotImplemented; + EventSwapVector[ChangeDeviceNotify] = NotImplemented; + RestoreExtensionEvents (); + } + +/*********************************************************************** + * + * Assign an id and type to an input device. + * + */ + +int +AssignTypeAndName (dev, type, name) + DeviceIntPtr dev; + Atom type; + char *name; + { + dev->type = type; + dev->name = (char *) xalloc(strlen(name)+1); + strcpy (dev->name, name); + } + +/*********************************************************************** + * + * Make device type atoms. + * + */ + +int +MakeDeviceTypeAtoms () + { + int i; + + for (i=0; inext) + { + if (dev->id == id) + { + if (id == inputInfo.pointer->id || id == inputInfo.keyboard->id) + return (NULL); + return (dev); + } + } + return (NULL); + } + +/************************************************************************** + * + * Allow the specified event to be restricted to being selected by one + * client at a time. + * The default is to allow more than one client to select the event. + * + */ + +void +SetExclusiveAccess (mask) + Mask mask; + { + int i; + + for (i=0; i= 128)) + FatalError("MaskForExtensionEvent: bogus event number"); + SetMaskForEvent(mask,event); + } + +/************************************************************************** + * + * Record an event mask where there is no unique corresponding event type. + * We can't call SetMaskForEvent, since that would clobber the existing + * mask for that event. MotionHint and ButtonMotion are examples. + * + * Since extension event types will never be less than 64, we can use + * 0-63 in the EventInfo array as the "type" to be used to look up this + * mask. This means that the corresponding macros such as + * DevicePointerMotionHint must have access to the same constants. + * + */ + +void +SetEventInfo(mask, constant) + Mask mask; + int constant; + { + EventInfo[ExtEventIndex].mask = mask; + EventInfo[ExtEventIndex++].type = constant; + } diff --git a/Xi/getbmap.c b/Xi/getbmap.c new file mode 100644 index 000000000..35c2d5c7d --- /dev/null +++ b/Xi/getbmap.c @@ -0,0 +1,147 @@ +/* $Xorg: getbmap.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to return the version of the extension. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure gets the button mapping for the specified device. + * + */ + +int +SProcXGetDeviceButtonMapping(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetDeviceButtonMappingReq); + swaps(&stuff->length, n); + return(ProcXGetDeviceButtonMapping(client)); + } + +/*********************************************************************** + * + * This procedure gets the button mapping for the specified device. + * + */ + +ProcXGetDeviceButtonMapping (client) + register ClientPtr client; + { + DeviceIntPtr dev; + xGetDeviceButtonMappingReply rep; + ButtonClassPtr b; + + REQUEST(xGetDeviceButtonMappingReq); + REQUEST_SIZE_MATCH(xGetDeviceButtonMappingReq); + + rep.repType = X_Reply; + rep.RepType = X_GetDeviceButtonMapping; + rep.nElts = 0; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_GetDeviceButtonMapping, 0, + BadDevice); + return Success; + } + + b = dev->button; + if (b == NULL) + { + SendErrorToClient(client, IReqCode, X_GetDeviceButtonMapping, 0, + BadMatch); + return Success; + } + rep.nElts = b->numButtons; + rep.length = (rep.nElts + (4-1))/4; + WriteReplyToClient (client, sizeof (xGetDeviceButtonMappingReply), &rep); + (void)WriteToClient(client, rep.nElts, + (char *)&b->map[1]); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XGetDeviceButtonMapping function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetDeviceButtonMapping (client, size, rep) + ClientPtr client; + int size; + xGetDeviceButtonMappingReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/getdctl.c b/Xi/getdctl.c new file mode 100644 index 000000000..684160706 --- /dev/null +++ b/Xi/getdctl.c @@ -0,0 +1,224 @@ +/* $Xorg: getdctl.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Get Device control attributes for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); +void CopySwapDeviceResolution(); + +/*********************************************************************** + * + * This procedure gets the control attributes for an extension device, + * for clients on machines with a different byte ordering than the server. + * + */ + +int +SProcXGetDeviceControl(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetDeviceControlReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetDeviceControlReq); + swaps(&stuff->control, n); + return(ProcXGetDeviceControl(client)); + } + +/*********************************************************************** + * + * Get the state of the specified device control. + * + */ + +ProcXGetDeviceControl(client) + ClientPtr client; + { + int total_length = 0; + char *buf, *savbuf; + register DeviceIntPtr dev; + xGetDeviceControlReply rep; + + REQUEST(xGetDeviceControlReq); + REQUEST_SIZE_MATCH(xGetDeviceControlReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_GetDeviceControl, 0, + BadDevice); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_GetDeviceControl; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + switch (stuff->control) + { + case DEVICE_RESOLUTION: + if (!dev->valuator) + { + SendErrorToClient (client, IReqCode, X_GetDeviceControl, 0, + BadMatch); + return Success; + } + total_length = sizeof (xDeviceResolutionState) + + (3 * sizeof(int) * dev->valuator->numAxes); + break; + default: + SendErrorToClient (client, IReqCode, X_GetDeviceControl, 0, + BadValue); + return Success; + } + + buf = (char *) Xalloc (total_length); + if (!buf) + { + SendErrorToClient(client, IReqCode, X_GetDeviceControl, 0, + BadAlloc); + return Success; + } + savbuf=buf; + + switch (stuff->control) + { + case DEVICE_RESOLUTION: + CopySwapDeviceResolution(client, dev->valuator, buf, + total_length); + break; + default: + break; + } + + rep.length = (total_length+3) >> 2; + WriteReplyToClient(client, sizeof(xGetDeviceControlReply), &rep); + WriteToClient(client, total_length, savbuf); + Xfree (savbuf); + return Success; + } + +/*********************************************************************** + * + * This procedure copies DeviceResolution data, swapping if necessary. + * + */ + +void +CopySwapDeviceResolution (client, v, buf, length) + ClientPtr client; + ValuatorClassPtr v; + char *buf; + int length; + { + register char n; + AxisInfoPtr a; + xDeviceResolutionState *r; + int i, *iptr; + + r = (xDeviceResolutionState *) buf; + r->control = DEVICE_RESOLUTION; + r->length = length; + r->num_valuators = v->numAxes; + buf += sizeof (xDeviceResolutionState); + iptr = (int *) buf; + for (i=0,a=v->axes; inumAxes; i++,a++) + *iptr++ = a->resolution; + for (i=0,a=v->axes; inumAxes; i++,a++) + *iptr++ = a->min_resolution; + for (i=0,a=v->axes; inumAxes; i++,a++) + *iptr++ = a->max_resolution; + if (client->swapped) + { + swaps (&r->control,n); + swaps (&r->length,n); + swapl (&r->num_valuators,n); + iptr = (int *) buf; + for (i=0; i < (3 * v->numAxes); i++,iptr++) + { + swapl (iptr,n); + } + } + } + +/*********************************************************************** + * + * This procedure writes the reply for the xGetDeviceControl function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetDeviceControl (client, size, rep) + ClientPtr client; + int size; + xGetDeviceControlReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } + diff --git a/Xi/getfctl.c b/Xi/getfctl.c new file mode 100644 index 000000000..e06470fbc --- /dev/null +++ b/Xi/getfctl.c @@ -0,0 +1,421 @@ +/* $Xorg: getfctl.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Get feedback control attributes for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); +void CopySwapKbdFeedback(); +void CopySwapPtrFeedback(); +void CopySwapIntegerFeedback(); +void CopySwapStringFeedback(); +void CopySwapLedFeedback(); +void CopySwapBellFeedback(); + +/*********************************************************************** + * + * This procedure gets the control attributes for an extension device, + * for clients on machines with a different byte ordering than the server. + * + */ + +int +SProcXGetFeedbackControl(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetFeedbackControlReq); + swaps(&stuff->length, n); + return(ProcXGetFeedbackControl(client)); + } + +/*********************************************************************** + * + * Get the feedback control state. + * + */ + +ProcXGetFeedbackControl(client) + ClientPtr client; + { + int total_length = 0; + char *buf, *savbuf; + register DeviceIntPtr dev; + KbdFeedbackPtr k; + PtrFeedbackPtr p; + IntegerFeedbackPtr i; + StringFeedbackPtr s; + BellFeedbackPtr b; + LedFeedbackPtr l; + xGetFeedbackControlReply rep; + + REQUEST(xGetFeedbackControlReq); + REQUEST_SIZE_MATCH(xGetFeedbackControlReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_GetFeedbackControl, 0, + BadDevice); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_GetFeedbackControl; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.num_feedbacks = 0; + + for (k=dev->kbdfeed; k; k=k->next) + { + rep.num_feedbacks++; + total_length += sizeof(xKbdFeedbackState); + } + for (p=dev->ptrfeed; p; p=p->next) + { + rep.num_feedbacks++; + total_length += sizeof(xPtrFeedbackState); + } + for (s=dev->stringfeed; s; s=s->next) + { + rep.num_feedbacks++; + total_length += sizeof(xStringFeedbackState) + + (s->ctrl.num_symbols_supported * sizeof (KeySym)); + } + for (i=dev->intfeed; i; i=i->next) + { + rep.num_feedbacks++; + total_length += sizeof(xIntegerFeedbackState); + } + for (l=dev->leds; l; l=l->next) + { + rep.num_feedbacks++; + total_length += sizeof(xLedFeedbackState); + } + for (b=dev->bell; b; b=b->next) + { + rep.num_feedbacks++; + total_length += sizeof(xBellFeedbackState); + } + + if (total_length == 0) + { + SendErrorToClient(client, IReqCode, X_GetFeedbackControl, 0, + BadMatch); + return Success; + } + + buf = (char *) Xalloc (total_length); + if (!buf) + { + SendErrorToClient(client, IReqCode, X_GetFeedbackControl, 0, + BadAlloc); + return Success; + } + savbuf=buf; + + for (k=dev->kbdfeed; k; k=k->next) + CopySwapKbdFeedback (client, k, &buf); + for (p=dev->ptrfeed; p; p=p->next) + CopySwapPtrFeedback (client, p, &buf); + for (s=dev->stringfeed; s; s=s->next) + CopySwapStringFeedback (client, s, &buf); + for (i=dev->intfeed; i; i=i->next) + CopySwapIntegerFeedback (client, i, &buf); + for (l=dev->leds; l; l=l->next) + CopySwapLedFeedback (client, l, &buf); + for (b=dev->bell; b; b=b->next) + CopySwapBellFeedback (client, b, &buf); + + rep.length = (total_length+3) >> 2; + WriteReplyToClient(client, sizeof(xGetFeedbackControlReply), &rep); + WriteToClient(client, total_length, savbuf); + Xfree (savbuf); + return Success; + } + +/*********************************************************************** + * + * This procedure copies KbdFeedbackClass data, swapping if necessary. + * + */ + +void +CopySwapKbdFeedback (client, k, buf) + ClientPtr client; + KbdFeedbackPtr k; + char **buf; + { + int i; + register char n; + xKbdFeedbackState *k2; + + k2 = (xKbdFeedbackState *) *buf; + k2->class = KbdFeedbackClass; + k2->length = sizeof (xKbdFeedbackState); + k2->id = k->ctrl.id; + k2->click = k->ctrl.click; + k2->percent = k->ctrl.bell; + k2->pitch = k->ctrl.bell_pitch; + k2->duration = k->ctrl.bell_duration; + k2->led_mask = k->ctrl.leds; + k2->global_auto_repeat = k->ctrl.autoRepeat; + for (i=0; i<32; i++) + k2->auto_repeats[i] = k->ctrl.autoRepeats[i]; + if (client->swapped) + { + swaps(&k2->length,n); + swaps(&k2->pitch,n); + swaps(&k2->duration,n); + swapl(&k2->led_mask,n); + swapl(&k2->led_values,n); + } + *buf += sizeof (xKbdFeedbackState); + } + +/*********************************************************************** + * + * This procedure copies PtrFeedbackClass data, swapping if necessary. + * + */ + +void +CopySwapPtrFeedback (client, p, buf) + ClientPtr client; + PtrFeedbackPtr p; + char **buf; + { + register char n; + xPtrFeedbackState *p2; + + p2 = (xPtrFeedbackState *) *buf; + p2->class = PtrFeedbackClass; + p2->length = sizeof (xPtrFeedbackState); + p2->id = p->ctrl.id; + p2->accelNum = p->ctrl.num; + p2->accelDenom = p->ctrl.den; + p2->threshold = p->ctrl.threshold; + if (client->swapped) + { + swaps(&p2->length,n); + swaps(&p2->accelNum,n); + swaps(&p2->accelDenom,n); + swaps(&p2->threshold,n); + } + *buf += sizeof (xPtrFeedbackState); + } + +/*********************************************************************** + * + * This procedure copies IntegerFeedbackClass data, swapping if necessary. + * + */ + +void +CopySwapIntegerFeedback (client, i, buf) + ClientPtr client; + IntegerFeedbackPtr i; + char **buf; + { + register char n; + xIntegerFeedbackState *i2; + + i2 = (xIntegerFeedbackState *) *buf; + i2->class = IntegerFeedbackClass; + i2->length = sizeof (xIntegerFeedbackState); + i2->id = i->ctrl.id; + i2->resolution = i->ctrl.resolution; + i2->min_value = i->ctrl.min_value; + i2->max_value = i->ctrl.max_value; + if (client->swapped) + { + swaps(&i2->length,n); + swapl(&i2->resolution,n); + swapl(&i2->min_value,n); + swapl(&i2->max_value,n); + } + *buf += sizeof (xIntegerFeedbackState); + } + +/*********************************************************************** + * + * This procedure copies StringFeedbackClass data, swapping if necessary. + * + */ + +void +CopySwapStringFeedback (client, s, buf) + ClientPtr client; + StringFeedbackPtr s; + char **buf; + { + int i; + register char n; + xStringFeedbackState *s2; + KeySym *kptr; + + s2 = (xStringFeedbackState *) *buf; + s2->class = StringFeedbackClass; + s2->length = sizeof (xStringFeedbackState) + + s->ctrl.num_symbols_supported * sizeof (KeySym); + s2->id = s->ctrl.id; + s2->max_symbols = s->ctrl.max_symbols; + s2->num_syms_supported = s->ctrl.num_symbols_supported; + *buf += sizeof (xStringFeedbackState); + kptr = (KeySym *) (*buf); + for (i=0; ictrl.num_symbols_supported; i++) + *kptr++ = *(s->ctrl.symbols_supported+i); + if (client->swapped) + { + swaps(&s2->length,n); + swaps(&s2->max_symbols,n); + swaps(&s2->num_syms_supported,n); + kptr = (KeySym *) (*buf); + for (i=0; ictrl.num_symbols_supported; i++,kptr++) + { + swapl(kptr,n); + } + } + *buf += (s->ctrl.num_symbols_supported * sizeof (KeySym)); + } + +/*********************************************************************** + * + * This procedure copies LedFeedbackClass data, swapping if necessary. + * + */ + +void +CopySwapLedFeedback (client, l, buf) + ClientPtr client; + LedFeedbackPtr l; + char **buf; + { + register char n; + xLedFeedbackState *l2; + + l2 = (xLedFeedbackState *) *buf; + l2->class = LedFeedbackClass; + l2->length = sizeof (xLedFeedbackState); + l2->id = l->ctrl.id; + l2->led_values = l->ctrl.led_values; + l2->led_mask = l->ctrl.led_mask; + if (client->swapped) + { + swaps(&l2->length,n); + swapl(&l2->led_values,n); + swapl(&l2->led_mask,n); + } + *buf += sizeof (xLedFeedbackState); + } + +/*********************************************************************** + * + * This procedure copies BellFeedbackClass data, swapping if necessary. + * + */ + +void +CopySwapBellFeedback (client, b, buf) + ClientPtr client; + BellFeedbackPtr b; + char **buf; + { + register char n; + xBellFeedbackState *b2; + + b2 = (xBellFeedbackState *) *buf; + b2->class = BellFeedbackClass; + b2->length = sizeof (xBellFeedbackState); + b2->id = b->ctrl.id; + b2->percent = b->ctrl.percent; + b2->pitch = b->ctrl.pitch; + b2->duration = b->ctrl.duration; + if (client->swapped) + { + swaps(&b2->length,n); + swaps(&b2->pitch,n); + swaps(&b2->duration,n); + } + *buf += sizeof (xBellFeedbackState); + } + +/*********************************************************************** + * + * This procedure writes the reply for the xGetFeedbackControl function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetFeedbackControl (client, size, rep) + ClientPtr client; + int size; + xGetFeedbackControlReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_feedbacks, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/getfocus.c b/Xi/getfocus.c new file mode 100644 index 000000000..1e34df413 --- /dev/null +++ b/Xi/getfocus.c @@ -0,0 +1,151 @@ +/* $Xorg: getfocus.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to get the focus for an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "windowstr.h" /* focus struct */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure gets the focus for a device. + * + */ + +int +SProcXGetDeviceFocus(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetDeviceFocusReq); + swaps(&stuff->length, n); + return(ProcXGetDeviceFocus(client)); + } + +/*********************************************************************** + * + * This procedure gets the focus for a device. + * + */ + +int +ProcXGetDeviceFocus(client) + ClientPtr client; + { + DeviceIntPtr dev; + FocusClassPtr focus; + xGetDeviceFocusReply rep; + + REQUEST(xGetDeviceFocusReq); + REQUEST_SIZE_MATCH(xGetDeviceFocusReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL || !dev->focus) + { + SendErrorToClient(client, IReqCode, X_GetDeviceFocus, 0, BadDevice); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_GetDeviceFocus; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + focus = dev->focus; + + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else if (focus->win == FollowKeyboardWin) + rep.focus = FollowKeyboard; + else + rep.focus = focus->win->drawable.id; + + rep.time = focus->time.milliseconds; + rep.revertTo = focus->revert; + WriteReplyToClient (client, sizeof(xGetDeviceFocusReply), &rep); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the GetDeviceFocus function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetDeviceFocus (client, size, rep) + ClientPtr client; + int size; + xGetDeviceFocusReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->focus, n); + swapl(&rep->time, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/getkmap.c b/Xi/getkmap.c new file mode 100644 index 000000000..783dc5506 --- /dev/null +++ b/Xi/getkmap.c @@ -0,0 +1,171 @@ +/* $Xorg: getkmap.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Get the key mapping for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure gets the key mapping for an extension device, + * for clients on machines with a different byte ordering than the server. + * + */ + +int +SProcXGetDeviceKeyMapping(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetDeviceKeyMappingReq); + swaps(&stuff->length, n); + return(ProcXGetDeviceKeyMapping(client)); + } + +/*********************************************************************** + * + * Get the device key mapping. + * + */ + +ProcXGetDeviceKeyMapping(client) + register ClientPtr client; + { + extern void CopySwap32Write(); + xGetDeviceKeyMappingReply rep; + DeviceIntPtr dev; + KeySymsPtr k; + + REQUEST(xGetDeviceKeyMappingReq); + REQUEST_SIZE_MATCH(xGetDeviceKeyMappingReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_GetDeviceKeyMapping, 0, + BadDevice); + return Success; + } + + if (dev->key == NULL) + { + SendErrorToClient (client, IReqCode, X_GetDeviceKeyMapping, 0, + BadMatch); + return Success; + } + k = &dev->key->curKeySyms; + + if ((stuff->firstKeyCode < k->minKeyCode) || + (stuff->firstKeyCode > k->maxKeyCode)) + { + client->errorValue = stuff->firstKeyCode; + SendErrorToClient (client, IReqCode, X_GetDeviceKeyMapping, 0, + BadValue); + return Success; + } + + if (stuff->firstKeyCode + stuff->count > k->maxKeyCode + 1) + { + client->errorValue = stuff->count; + SendErrorToClient (client, IReqCode, X_GetDeviceKeyMapping, 0, + BadValue); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_GetDeviceKeyMapping; + rep.sequenceNumber = client->sequence; + rep.keySymsPerKeyCode = k->mapWidth; + rep.length = (k->mapWidth * stuff->count); /* KeySyms are 4 bytes */ + WriteReplyToClient(client, sizeof(xGetDeviceKeyMappingReply), &rep); + + client->pSwapReplyFunc = CopySwap32Write; + WriteSwappedDataToClient( + client, + k->mapWidth * stuff->count * sizeof(KeySym), + &k->map[(stuff->firstKeyCode - k->minKeyCode) * + k->mapWidth]); + + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XGetDeviceKeyMapping function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetDeviceKeyMapping (client, size, rep) + ClientPtr client; + int size; + xGetDeviceKeyMappingReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } + diff --git a/Xi/getmmap.c b/Xi/getmmap.c new file mode 100644 index 000000000..93b5748c0 --- /dev/null +++ b/Xi/getmmap.c @@ -0,0 +1,151 @@ +/* $Xorg: getmmap.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Get the modifier mapping for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" /* Request macro */ + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure gets the modifier mapping for an extension device, + * for clients on machines with a different byte ordering than the server. + * + */ + +int +SProcXGetDeviceModifierMapping(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetDeviceModifierMappingReq); + swaps(&stuff->length, n); + return(ProcXGetDeviceModifierMapping(client)); + } + +/*********************************************************************** + * + * Get the device Modifier mapping. + * + */ + +ProcXGetDeviceModifierMapping(client) + ClientPtr client; + { + CARD8 maxkeys; + DeviceIntPtr dev; + xGetDeviceModifierMappingReply rep; + KeyClassPtr kp; + + REQUEST(xGetDeviceModifierMappingReq); + REQUEST_SIZE_MATCH(xGetDeviceModifierMappingReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_GetDeviceModifierMapping, 0, + BadDevice); + return Success; + } + + kp = dev->key; + if (kp == NULL) + { + SendErrorToClient (client, IReqCode, X_GetDeviceModifierMapping, 0, + BadMatch); + return Success; + } + maxkeys = kp->maxKeysPerModifier; + + rep.repType = X_Reply; + rep.RepType = X_GetDeviceModifierMapping; + rep.numKeyPerModifier = maxkeys; + rep.sequenceNumber = client->sequence; + /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ + rep.length = 2*maxkeys; + + WriteReplyToClient(client, sizeof(xGetDeviceModifierMappingReply), &rep); + + /* Reply with the (modified by DDX) map that SetModifierMapping passed in */ + WriteToClient(client, 8*maxkeys, (char *)kp->modifierKeyMap); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XGetDeviceModifierMapping function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetDeviceModifierMapping (client, size, rep) + ClientPtr client; + int size; + xGetDeviceModifierMappingReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/getprop.c b/Xi/getprop.c new file mode 100644 index 000000000..ee53b87cb --- /dev/null +++ b/Xi/getprop.c @@ -0,0 +1,207 @@ +/* $Xorg: getprop.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Function to return the dont-propagate-list for an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structs */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern void (* ReplySwapVector[256]) (); +extern XExtEventInfo EventInfo[]; +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle a request from a client with a different byte order. + * + */ + +int +SProcXGetDeviceDontPropagateList(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetDeviceDontPropagateListReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetDeviceDontPropagateListReq); + swapl(&stuff->window, n); + return(ProcXGetDeviceDontPropagateList(client)); + } + +/*********************************************************************** + * + * This procedure lists the input devices available to the server. + * + */ + +ProcXGetDeviceDontPropagateList (client) + register ClientPtr client; + { + CARD16 count = 0; + int i; + XEventClass *buf, *tbuf; + WindowPtr pWin; + xGetDeviceDontPropagateListReply rep; + XEventClass *ClassFromMask (); + void Swap32Write(); + OtherInputMasks *others; + + REQUEST(xGetDeviceDontPropagateListReq); + REQUEST_SIZE_MATCH(xGetDeviceDontPropagateListReq); + + rep.repType = X_Reply; + rep.RepType = X_GetDeviceDontPropagateList; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.count = 0; + + pWin = (WindowPtr) LookupWindow (stuff->window, client); + if (!pWin) + { + client->errorValue = stuff->window; + SendErrorToClient(client, IReqCode, X_GetDeviceDontPropagateList, 0, + BadWindow); + return Success; + } + + if (others = wOtherInputMasks(pWin)) + { + for (i=0; idontPropagateMask[i], i, + &count, COUNT); + if (count) + { + rep.count = count; + buf = (XEventClass *) Xalloc (rep.count * sizeof(XEventClass)); + rep.length = (rep.count * sizeof (XEventClass) + 3) >> 2; + + tbuf = buf; + for (i=0; idontPropagateMask[i], i, + NULL, CREATE); + } + } + + WriteReplyToClient (client, sizeof (xGetDeviceDontPropagateListReply), + &rep); + + if (count) + { + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient( client, count * sizeof(XEventClass), buf); + Xfree (buf); + } + return Success; + } + +/*********************************************************************** + * + * This procedure gets a list of event classes from a mask word. + * A single mask may translate to more than one event class. + * + */ + +XEventClass +*ClassFromMask (buf, mask, maskndx, count, mode) + XEventClass *buf; + Mask mask; + int maskndx; + CARD16 *count; + int mode; + { + int i,j; + int id = maskndx; + Mask tmask = 0x80000000; + extern int ExtEventIndex; + + for (i=0; i<32; i++,tmask>>=1) + if (tmask & mask) + { + for (j=0; jsequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->count, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/getselev.c b/Xi/getselev.c new file mode 100644 index 000000000..8ac16d1d0 --- /dev/null +++ b/Xi/getselev.c @@ -0,0 +1,189 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/* $Xorg: getselev.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/*********************************************************************** + * + * Extension function to get the current selected events for a given window. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "XI.h" +#include "XIproto.h" +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window struct */ + +extern int IReqCode; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure gets the current selected extension events. + * + */ + +int +SProcXGetSelectedExtensionEvents(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetSelectedExtensionEventsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetSelectedExtensionEventsReq); + swapl(&stuff->window, n); + return(ProcXGetSelectedExtensionEvents(client)); + } + +/*********************************************************************** + * + * This procedure gets the current device select mask, + * if the client and server have a different byte ordering. + * + */ + +int +ProcXGetSelectedExtensionEvents(client) + register ClientPtr client; + { + int i; + int total_length = 0; + xGetSelectedExtensionEventsReply rep; + WindowPtr pWin; + XEventClass *buf; + XEventClass *tclient; + XEventClass *aclient; + XEventClass *ClassFromMask (); + void Swap32Write(); + OtherInputMasks *pOthers; + InputClientsPtr others; + + REQUEST(xGetSelectedExtensionEventsReq); + REQUEST_SIZE_MATCH(xGetSelectedExtensionEventsReq); + + rep.repType = X_Reply; + rep.RepType = X_GetSelectedExtensionEvents; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.this_client_count = 0; + rep.all_clients_count = 0; + + if (!(pWin = LookupWindow(stuff->window, client))) + { + SendErrorToClient(client, IReqCode, X_GetSelectedExtensionEvents, 0, + BadWindow); + return Success; + } + + if (pOthers=wOtherInputMasks(pWin)) + { + for (others = pOthers->inputClients; others; others=others->next) + for (i=0; imask[i], i, + &rep.all_clients_count, COUNT); + + for (others = pOthers->inputClients; others; others=others->next) + if (SameClient(others, client)) + { + for (i=0; imask[i], i, + &rep.this_client_count, COUNT); + break; + } + + total_length = (rep.all_clients_count + rep.this_client_count) * + sizeof (XEventClass); + rep.length = (total_length + 3) >> 2; + buf = (XEventClass *) Xalloc (total_length); + + tclient = buf; + aclient = buf + rep.this_client_count; + if (others) + for (i=0; imask[i], i, NULL, CREATE); + + for (others = pOthers->inputClients; others; others=others->next) + for (i=0; imask[i], i, NULL, CREATE); + } + + WriteReplyToClient (client, sizeof(xGetSelectedExtensionEventsReply), &rep); + + if (total_length) + { + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient( client, total_length, buf); + Xfree (buf); + } + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XGetSelectedExtensionEvents function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetSelectedExtensionEvents (client, size, rep) + ClientPtr client; + int size; + xGetSelectedExtensionEventsReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->this_client_count, n); + swaps(&rep->all_clients_count, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/getvers.c b/Xi/getvers.c new file mode 100644 index 000000000..8628a2851 --- /dev/null +++ b/Xi/getvers.c @@ -0,0 +1,148 @@ +/* $Xorg: getvers.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to return the version of the extension. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); +XExtensionVersion AllExtensionVersions[128]; + +/*********************************************************************** + * + * Handle a request from a client with a different byte order than us. + * + */ + +int +SProcXGetExtensionVersion(client) + register ClientPtr client; + { + register char n; + + REQUEST(xGetExtensionVersionReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xGetExtensionVersionReq); + swaps(&stuff->nbytes, n); + return(ProcXGetExtensionVersion(client)); + } + +/*********************************************************************** + * + * This procedure lists the input devices available to the server. + * + */ + +ProcXGetExtensionVersion (client) + register ClientPtr client; + { + xGetExtensionVersionReply rep; + + REQUEST(xGetExtensionVersionReq); + REQUEST_AT_LEAST_SIZE(xGetExtensionVersionReq); + + if (stuff->length != (sizeof(xGetExtensionVersionReq) + + stuff->nbytes + 3)>>2) + { + SendErrorToClient(client, IReqCode, X_GetExtensionVersion, 0, + BadLength); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_GetExtensionVersion; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.major_version = 0; + rep.minor_version = 0; + + rep.present = TRUE; + if (rep.present) + { + rep.major_version = + AllExtensionVersions[IReqCode-128].major_version; + rep.minor_version = + AllExtensionVersions[IReqCode-128].minor_version; + } + WriteReplyToClient (client, sizeof (xGetExtensionVersionReply), &rep); + + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XGetExtensionVersion function, + * if the client and server have a different byte ordering. + * + */ + +SRepXGetExtensionVersion (client, size, rep) + ClientPtr client; + int size; + xGetExtensionVersionReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->major_version, n); + swaps(&rep->minor_version, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/grabdev.c b/Xi/grabdev.c new file mode 100644 index 000000000..cb2370adf --- /dev/null +++ b/Xi/grabdev.c @@ -0,0 +1,225 @@ +/* $Xorg: grabdev.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to grab an extension device. + * + */ + + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern int BadClass; +extern XExtEventInfo EventInfo[]; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Swap the request if the requestor has a different byte order than us. + * + */ + +int +SProcXGrabDevice(client) + register ClientPtr client; + { + register char n; + register long *p; + register int i; + + REQUEST(xGrabDeviceReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xGrabDeviceReq); + swapl(&stuff->grabWindow, n); + swapl(&stuff->time, n); + swaps(&stuff->event_count, n); + p = (long *) &stuff[1]; + for (i=0; ievent_count; i++) + { + swapl(p, n); + p++; + } + + return(ProcXGrabDevice(client)); + } + +/*********************************************************************** + * + * Grab an extension device. + * + */ + +int +ProcXGrabDevice(client) + ClientPtr client; + { + int error; + xGrabDeviceReply rep; + DeviceIntPtr dev; + struct tmask tmp[EMASKSIZE]; + + REQUEST(xGrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xGrabDeviceReq); + + if (stuff->length !=(sizeof(xGrabDeviceReq)>>2) + stuff->event_count) + { + SendErrorToClient (client, IReqCode, X_GrabDevice, 0, BadLength); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_GrabDevice; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_GrabDevice, 0, BadDevice); + return Success; + } + + if (CreateMaskFromList (client, (XEventClass *)&stuff[1], + stuff->event_count, tmp, dev, X_GrabDevice) != Success) + return Success; + + error = GrabDevice (client, dev, stuff->this_device_mode, + stuff->other_devices_mode, stuff->grabWindow, stuff->ownerEvents, + stuff->time, tmp[stuff->deviceid].mask, &rep.status); + + if (error != Success) + { + SendErrorToClient(client, IReqCode, X_GrabDevice, 0, error); + return Success; + } + WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep); + return Success; + } + + +/*********************************************************************** + * + * This procedure creates an event mask from a list of XEventClasses. + * + */ + +int +CreateMaskFromList (client, list, count, mask, dev, req) + ClientPtr client; + XEventClass *list; + int count; + struct tmask mask[]; + DeviceIntPtr dev; + int req; + { + int i,j; + int device; + DeviceIntPtr tdev; + extern int ExtEventIndex; + + for (i=0; i> 8; + if (device > 255) + { + SendErrorToClient(client, IReqCode, req, 0, BadClass); + return BadClass; + } + tdev = LookupDeviceIntRec (device); + if (tdev==NULL || (dev != NULL && tdev != dev)) + { + SendErrorToClient(client, IReqCode, req, 0, BadClass); + return BadClass; + } + + for (j=0; jsequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/grabdevb.c b/Xi/grabdevb.c new file mode 100644 index 000000000..ddc44c12d --- /dev/null +++ b/Xi/grabdevb.c @@ -0,0 +1,163 @@ +/* $Xorg: grabdevb.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to grab a button on an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle requests from clients with a different byte order. + * + */ + +int +SProcXGrabDeviceButton(client) + register ClientPtr client; + { + register char n; + register long *p; + register int i; + + REQUEST(xGrabDeviceButtonReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xGrabDeviceButtonReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + swaps(&stuff->event_count, n); + p = (long *) &stuff[1]; + for (i=0; ievent_count; i++) + { + swapl(p, n); + p++; + } + + return(ProcXGrabDeviceButton(client)); + } + +/*********************************************************************** + * + * Grab a button on an extension device. + * + */ + +int +ProcXGrabDeviceButton(client) + ClientPtr client; + { + int ret; + DeviceIntPtr dev; + DeviceIntPtr mdev; + XEventClass *class; + struct tmask tmp[EMASKSIZE]; + + REQUEST(xGrabDeviceButtonReq); + REQUEST_AT_LEAST_SIZE(xGrabDeviceButtonReq); + + if (stuff->length !=(sizeof(xGrabDeviceButtonReq)>>2) + stuff->event_count) + { + SendErrorToClient (client, IReqCode, X_GrabDeviceButton, 0, BadLength); + return Success; + } + + dev = LookupDeviceIntRec (stuff->grabbed_device); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0, + BadDevice); + return Success; + } + if (stuff->modifier_device != UseXKeyboard) + { + mdev = LookupDeviceIntRec (stuff->modifier_device); + if (mdev == NULL) + { + SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0, + BadDevice); + return Success; + } + if (mdev->key == NULL) + { + SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0, + BadMatch); + return Success; + } + } + else + mdev = (DeviceIntPtr) LookupKeyboardDevice(); + + class = (XEventClass *) (&stuff[1]); /* first word of values */ + + if ((ret = CreateMaskFromList (client, class, + stuff->event_count, tmp, dev, X_GrabDeviceButton)) != Success) + return Success; + ret = GrabButton(client, dev, stuff->this_device_mode, + stuff->other_devices_mode, stuff->modifiers, mdev, stuff->button, + stuff->grabWindow, stuff->ownerEvents, NullCursor, NullWindow, + tmp[stuff->grabbed_device].mask); + + if (ret != Success) + SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0, ret); + return(Success); + } diff --git a/Xi/grabdevk.c b/Xi/grabdevk.c new file mode 100644 index 000000000..6db6b8d09 --- /dev/null +++ b/Xi/grabdevk.c @@ -0,0 +1,169 @@ +/* $Xorg: grabdevk.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to grab a key on an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadClass; +extern int BadDevice; +extern InputInfo inputInfo; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle requests from clients with a different byte order. + * + */ + +int +SProcXGrabDeviceKey(client) + register ClientPtr client; + { + register char n; + register long *p; + register int i; + + REQUEST(xGrabDeviceKeyReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xGrabDeviceKeyReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + swaps(&stuff->event_count, n); + p = (long *) &stuff[1]; + for (i=0; ievent_count; i++) + { + swapl(p, n); + p++; + } + return(ProcXGrabDeviceKey(client)); + } + +/*********************************************************************** + * + * Grab a key on an extension device. + * + */ + +int +ProcXGrabDeviceKey(client) + ClientPtr client; + { + int ret; + DeviceIntPtr dev; + DeviceIntPtr mdev; + XEventClass *class; + struct tmask tmp[EMASKSIZE]; + + REQUEST(xGrabDeviceKeyReq); + REQUEST_AT_LEAST_SIZE(xGrabDeviceKeyReq); + + if (stuff->length !=(sizeof(xGrabDeviceKeyReq)>>2) + stuff->event_count) + { + SendErrorToClient (client, IReqCode, X_GrabDeviceKey, 0, BadLength); + return Success; + } + + dev = LookupDeviceIntRec (stuff->grabbed_device); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_GrabDeviceKey, 0, + BadDevice); + return Success; + } + + if (stuff->modifier_device != UseXKeyboard) + { + mdev = LookupDeviceIntRec (stuff->modifier_device); + if (mdev == NULL) + { + SendErrorToClient(client, IReqCode, X_GrabDeviceKey, 0, + BadDevice); + return Success; + } + if (mdev->key == NULL) + { + SendErrorToClient(client, IReqCode, X_GrabDeviceKey, 0, + BadMatch); + return Success; + } + } + else + mdev = (DeviceIntPtr) LookupKeyboardDevice(); + + class = (XEventClass *) (&stuff[1]); /* first word of values */ + + if ((ret = CreateMaskFromList (client, class, + stuff->event_count, tmp, dev, X_GrabDeviceKey)) != Success) + return Success; + + ret = GrabKey(client, dev, stuff->this_device_mode, + stuff->other_devices_mode, stuff->modifiers, mdev, stuff->key, + stuff->grabWindow, stuff->ownerEvents, tmp[stuff->grabbed_device].mask); + + if (ret != Success) + { + SendErrorToClient(client, IReqCode, X_GrabDeviceKey, 0, ret); + return Success; + } + + return Success; + } diff --git a/Xi/gtmotion.c b/Xi/gtmotion.c new file mode 100644 index 000000000..65a4e0a19 --- /dev/null +++ b/Xi/gtmotion.c @@ -0,0 +1,206 @@ +/* $Xorg: gtmotion.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to get the motion history from an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Swap the request if server and client have different byte ordering. + * + */ + +int +SProcXGetDeviceMotionEvents(client) +register ClientPtr client; + { + register char n; + + REQUEST(xGetDeviceMotionEventsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetDeviceMotionEventsReq); + swapl(&stuff->start, n); + swapl(&stuff->stop, n); + return(ProcXGetDeviceMotionEvents(client)); + } + +/**************************************************************************** + * + * Get the motion history for an extension pointer devices. + * + */ + +int +ProcXGetDeviceMotionEvents(client) + ClientPtr client; +{ + INT32 *coords = NULL, *bufptr; + xGetDeviceMotionEventsReply rep; + int i, j, num_events, axes, size, tsize; + unsigned long nEvents; + DeviceIntPtr dev; + TimeStamp start, stop; + void XSwapTimeCoordWrite(); + int length = 0; + ValuatorClassPtr v; + + REQUEST(xGetDeviceMotionEventsReq); + + REQUEST_SIZE_MATCH(xGetDeviceMotionEventsReq); + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_GetDeviceMotionEvents, 0, + BadDevice); + return Success; + } + v = dev->valuator; + if (v==NULL || v->numAxes == 0) + { + SendErrorToClient(client, IReqCode, X_GetDeviceMotionEvents, 0, + BadMatch); + return Success; + } + if (dev->valuator->motionHintWindow) + MaybeStopDeviceHint(dev, client); + axes = v->numAxes; + rep.repType = X_Reply; + rep.RepType = X_GetDeviceMotionEvents; + rep.sequenceNumber = client->sequence; + rep.nEvents = 0; + rep.axes = axes; + rep.mode = v->mode & DeviceMode; + rep.length = 0; + start = ClientTimeToServerTime(stuff->start); + stop = ClientTimeToServerTime(stuff->stop); + if (CompareTimeStamps(start, stop) == LATER || + CompareTimeStamps(start, currentTime) == LATER) + { + WriteReplyToClient(client, sizeof(xGetDeviceMotionEventsReply), &rep); + return Success; + } + if (CompareTimeStamps(stop, currentTime) == LATER) + stop = currentTime; + num_events = v->numMotionEvents; + if (num_events) + { + size = sizeof(Time) + (axes * sizeof (INT32)); + tsize = num_events * size; + coords = (INT32 *) ALLOCATE_LOCAL(tsize); + if (!coords) + { + SendErrorToClient(client, IReqCode, X_GetDeviceMotionEvents, 0, + BadAlloc); + return Success; + } + rep.nEvents = (v->GetMotionProc) ( + dev, (xTimecoord *)coords, /* XXX */ + start.milliseconds, stop.milliseconds, (ScreenPtr)NULL); + } + if (rep.nEvents > 0) + { + length = (rep.nEvents * size +3) >> 2; + rep.length = length; + } + nEvents = rep.nEvents; + WriteReplyToClient(client, sizeof(xGetDeviceMotionEventsReply), &rep); + if (nEvents) + { + if (client->swapped) + { + register char n; + + bufptr = coords; + for (i=0; isequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->nEvents, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/listdev.c b/Xi/listdev.c new file mode 100644 index 000000000..ff6155f19 --- /dev/null +++ b/Xi/listdev.c @@ -0,0 +1,409 @@ +/* $Xorg: listdev.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to list the available input devices. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +#define VPC 20 /* Max # valuators per chunk */ +extern InputInfo inputInfo; +extern int IReqCode; +extern int BadDevice; +extern void (*ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +void CopySwapKeyClass (); +void CopySwapButtonClass (); +int CopySwapValuatorClass (); +void SizeDeviceInfo (); +void ListDeviceInfo (); +void AddOtherInputDevices (); +void CopyDeviceName (); +void CopySwapDevice (); + +/*********************************************************************** + * + * This procedure lists the input devices available to the server. + * + */ + +int +SProcXListInputDevices(client) + register ClientPtr client; + { + register char n; + + REQUEST(xListInputDevicesReq); + swaps(&stuff->length, n); + return(ProcXListInputDevices(client)); + } + +/*********************************************************************** + * + * This procedure lists the input devices available to the server. + * + */ + +ProcXListInputDevices (client) + register ClientPtr client; + { + xListInputDevicesReply rep; + int numdevs; + int namesize = 1; /* need 1 extra byte for strcpy */ + int size = 0; + int total_length; + char *devbuf; + char *classbuf; + char *namebuf; + char *savbuf; + xDeviceInfo *dev; + DeviceIntPtr d; + + REQUEST(xListInputDevicesReq); + REQUEST_SIZE_MATCH(xListInputDevicesReq); + + rep.repType = X_Reply; + rep.RepType = X_ListInputDevices; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + AddOtherInputDevices (); + numdevs = inputInfo.numDevices; + + for (d=inputInfo.devices; d; d=d->next) + SizeDeviceInfo (d, &namesize, &size); + for (d=inputInfo.off_devices; d; d=d->next) + SizeDeviceInfo (d, &namesize, &size); + + total_length = numdevs * sizeof (xDeviceInfo) + size + namesize; + devbuf = (char *) Xalloc (total_length); + classbuf = devbuf + (numdevs * sizeof (xDeviceInfo)); + namebuf = classbuf + size; + savbuf = devbuf; + + dev = (xDeviceInfoPtr) devbuf; + for (d=inputInfo.devices; d; d=d->next,dev++) + ListDeviceInfo (client, d, dev, &devbuf, &classbuf, &namebuf); + for (d=inputInfo.off_devices; d; d=d->next,dev++) + ListDeviceInfo (client, d, dev, &devbuf, &classbuf, &namebuf); + + rep.ndevices = numdevs; + rep.length = (total_length + 3) >> 2; + WriteReplyToClient (client, sizeof (xListInputDevicesReply), &rep); + WriteToClient(client, total_length, savbuf); + Xfree (savbuf); + return Success; + } + +/*********************************************************************** + * + * This procedure calculates the size of the information to be returned + * for an input device. + * + */ + +void +SizeDeviceInfo (d, namesize, size) + DeviceIntPtr d; + int *namesize; + int *size; + { + int chunks; + + *namesize += 1; + if (d->name) + *namesize += strlen (d->name); + if (d->key != NULL) + *size += sizeof (xKeyInfo); + if (d->button != NULL) + *size += sizeof (xButtonInfo); + if (d->valuator != NULL) + { + chunks = ((int) d->valuator->numAxes + 19) / VPC; + *size += (chunks * sizeof(xValuatorInfo) + + d->valuator->numAxes * sizeof(xAxisInfo)); + } + } + +/*********************************************************************** + * + * This procedure lists information to be returned for an input device. + * + */ + +void +ListDeviceInfo (client, d, dev, devbuf, classbuf, namebuf) + ClientPtr client; + DeviceIntPtr d; + xDeviceInfoPtr dev; + char **devbuf; + char **classbuf; + char **namebuf; + { + CopyDeviceName (namebuf, d->name); + CopySwapDevice (client, d, 0, devbuf); + if (d->key != NULL) + { + CopySwapKeyClass(client, d->key, classbuf); + dev->num_classes++; + } + if (d->button != NULL) + { + CopySwapButtonClass(client, d->button, classbuf); + dev->num_classes++; + } + if (d->valuator != NULL) + { + dev->num_classes += CopySwapValuatorClass(client, d->valuator, classbuf); + } + } + +/*********************************************************************** + * + * This procedure copies data to the DeviceInfo struct, swapping if necessary. + * + * We need the extra byte in the allocated buffer, because the trailing null + * hammers one extra byte, which is overwritten by the next name except for + * the last name copied. + * + */ + +void +CopyDeviceName (namebuf, name) + char **namebuf; + char *name; + { + char *nameptr = (char *) *namebuf; + + if (name) + { + *nameptr++ = strlen (name); + strcpy (nameptr, name); + *namebuf += (strlen (name)+1); + } + else + { + *nameptr++ = 0; + *namebuf += 1; + } + } + +/*********************************************************************** + * + * This procedure copies data to the DeviceInfo struct, swapping if necessary. + * + */ + +void +CopySwapDevice (client, d, num_classes, buf) + register ClientPtr client; + DeviceIntPtr d; + int num_classes; + char **buf; + { + register char n; + xDeviceInfoPtr dev; + + dev = (xDeviceInfoPtr) *buf; + + dev->id = d->id; + dev->type = d->type; + dev->num_classes = num_classes; + if (d == inputInfo.keyboard) + dev->use = IsXKeyboard; + else if (d == inputInfo.pointer) + dev->use = IsXPointer; + else + dev->use = IsXExtensionDevice; + if (client->swapped) + { + swapl(&dev->type, n); /* macro - braces are required */ + } + *buf += sizeof (xDeviceInfo); + } + +/*********************************************************************** + * + * This procedure copies KeyClass information, swapping if necessary. + * + */ + +void +CopySwapKeyClass (client, k, buf) + register ClientPtr client; + KeyClassPtr k; + char **buf; + { + register char n; + xKeyInfoPtr k2; + + k2 = (xKeyInfoPtr) *buf; + k2->class = KeyClass; + k2->length = sizeof (xKeyInfo); + k2->min_keycode = k->curKeySyms.minKeyCode; + k2->max_keycode = k->curKeySyms.maxKeyCode; + k2->num_keys = k2->max_keycode - k2->min_keycode + 1; + if (client->swapped) + { + swaps(&k2->num_keys,n); + } + *buf += sizeof (xKeyInfo); + } + +/*********************************************************************** + * + * This procedure copies ButtonClass information, swapping if necessary. + * + */ + +void +CopySwapButtonClass (client, b, buf) + register ClientPtr client; + ButtonClassPtr b; + char **buf; + { + register char n; + xButtonInfoPtr b2; + + b2 = (xButtonInfoPtr) *buf; + b2->class = ButtonClass; + b2->length = sizeof (xButtonInfo); + b2->num_buttons = b->numButtons; + if (client->swapped) + { + swaps(&b2->num_buttons,n); /* macro - braces are required */ + } + *buf += sizeof (xButtonInfo); + } + +/*********************************************************************** + * + * This procedure copies ValuatorClass information, swapping if necessary. + * + * Devices may have up to 255 valuators. The length of a ValuatorClass is + * defined to be sizeof(ValuatorClassInfo) + num_axes * sizeof (xAxisInfo). + * The maximum length is therefore (8 + 255 * 12) = 3068. However, the + * length field is one byte. If a device has more than 20 valuators, we + * must therefore return multiple valuator classes to the client. + * + */ + +int +CopySwapValuatorClass (client, v, buf) + register ClientPtr client; + ValuatorClassPtr v; + char **buf; +{ + int i, j, axes, t_axes; + register char n; + xValuatorInfoPtr v2; + AxisInfo *a; + xAxisInfoPtr a2; + + for (i=0,axes=v->numAxes; i < ((v->numAxes+19)/VPC); i++, axes-=VPC) { + t_axes = axes < VPC ? axes : VPC; + if (t_axes < 0) + t_axes = v->numAxes % VPC; + v2 = (xValuatorInfoPtr) *buf; + v2->class = ValuatorClass; + v2->length = sizeof (xValuatorInfo) + t_axes * sizeof (xAxisInfo); + v2->num_axes = t_axes; + v2->mode = v->mode & DeviceMode; + v2->motion_buffer_size = v->numMotionEvents; + if (client->swapped) + { + swapl(&v2->motion_buffer_size,n); + } + *buf += sizeof (xValuatorInfo); + a = v->axes + (VPC * i); + a2 = (xAxisInfoPtr) *buf; + for (j=0; jmin_value = a->min_value; + a2->max_value = a->max_value; + a2->resolution = a->resolution; + if (client->swapped) { + swapl(&a2->min_value,n); + swapl(&a2->max_value,n); + swapl(&a2->resolution,n); + } + a2++; + a++; + *buf += sizeof (xAxisInfo); + } + } + return (i); +} + +/*********************************************************************** + * + * This procedure writes the reply for the XListInputDevices function, + * if the client and server have a different byte ordering. + * + */ + +SRepXListInputDevices (client, size, rep) + ClientPtr client; + int size; + xListInputDevicesReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/opendev.c b/Xi/opendev.c new file mode 100644 index 000000000..30d6293f0 --- /dev/null +++ b/Xi/opendev.c @@ -0,0 +1,199 @@ +/* $Xorg: opendev.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to open an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "XI.h" +#include "XIproto.h" +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ + +extern int IReqCode; +extern int BadDevice; +extern CARD8 event_base []; +extern InputInfo inputInfo; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure swaps the request if the server and client have different + * byte orderings. + * + */ + +int +SProcXOpenDevice(client) + register ClientPtr client; + { + register char n; + + REQUEST(xOpenDeviceReq); + swaps(&stuff->length, n); + return(ProcXOpenDevice(client)); + } + +/*********************************************************************** + * + * This procedure causes the server to open an input device. + * + */ + +int +ProcXOpenDevice(client) + register ClientPtr client; + { + xInputClassInfo evbase [numInputClasses]; + Bool enableit = FALSE; + int j=0; + int status = Success; + xOpenDeviceReply rep; + DeviceIntPtr dev; + void OpenInputDevice(); + + REQUEST(xOpenDeviceReq); + REQUEST_SIZE_MATCH(xOpenDeviceReq); + + if (stuff->deviceid == inputInfo.pointer->id || + stuff->deviceid == inputInfo.keyboard->id) + { + SendErrorToClient(client, IReqCode, X_OpenDevice, 0, BadDevice); + return Success; + } + + if ((dev = LookupDeviceIntRec(stuff->deviceid)) == NULL) /* not open */ + { + for (dev=inputInfo.off_devices; dev; dev=dev->next) + if (dev->id == stuff->deviceid) + break; + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_OpenDevice, 0, BadDevice); + return Success; + } + enableit = TRUE; + } + + OpenInputDevice (dev, client, &status); + if (status != Success) + { + SendErrorToClient(client, IReqCode, X_OpenDevice, 0, status); + return Success; + } + if (enableit && dev->inited && dev->startup) + (void)EnableDevice(dev); + + rep.repType = X_Reply; + rep.RepType = X_OpenDevice; + rep.sequenceNumber = client->sequence; + if (dev->key != NULL) + { + evbase[j].class = KeyClass; + evbase[j++].event_type_base = event_base[KeyClass]; + } + if (dev->button != NULL) + { + evbase[j].class = ButtonClass; + evbase[j++].event_type_base = event_base[ButtonClass]; + } + if (dev->valuator != NULL) + { + evbase[j].class = ValuatorClass; + evbase[j++].event_type_base = event_base[ValuatorClass]; + } + if (dev->kbdfeed != NULL || dev->ptrfeed != NULL || dev->leds != NULL || + dev->intfeed != NULL || dev->bell != NULL || dev->stringfeed != NULL) + { + evbase[j].class = FeedbackClass; + evbase[j++].event_type_base = event_base[FeedbackClass]; + } + if (dev->focus != NULL) + { + evbase[j].class = FocusClass; + evbase[j++].event_type_base = event_base[FocusClass]; + } + if (dev->proximity != NULL) + { + evbase[j].class = ProximityClass; + evbase[j++].event_type_base = event_base[ProximityClass]; + } + evbase[j].class = OtherClass; + evbase[j++].event_type_base = event_base[OtherClass]; + rep.length = (j * sizeof (xInputClassInfo) + 3) >> 2; + rep.num_classes = j; + WriteReplyToClient (client, sizeof (xOpenDeviceReply), &rep); + WriteToClient(client, j * sizeof (xInputClassInfo), (char *)evbase); + return (Success); + } + +/*********************************************************************** + * + * This procedure writes the reply for the XOpenDevice function, + * if the client and server have a different byte ordering. + * + */ + +SRepXOpenDevice (client, size, rep) + ClientPtr client; + int size; + xOpenDeviceReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/queryst.c b/Xi/queryst.c new file mode 100644 index 000000000..66319b2f3 --- /dev/null +++ b/Xi/queryst.c @@ -0,0 +1,208 @@ +/* $Xorg: queryst.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ +/* + +Copyright 1998, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/*********************************************************************** + * + * Request to query the state of an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure allows a client to query the state of a device. + * + */ + +int +SProcXQueryDeviceState(client) + register ClientPtr client; + { + register char n; + + REQUEST(xQueryDeviceStateReq); + swaps(&stuff->length, n); + return(ProcXQueryDeviceState(client)); + } + +/*********************************************************************** + * + * This procedure allows frozen events to be routed. + * + */ + +int +ProcXQueryDeviceState(client) + register ClientPtr client; + { + register char n; + int i; + int num_classes = 0; + int total_length = 0; + char *buf, *savbuf; + KeyClassPtr k; + xKeyState *tk; + ButtonClassPtr b; + xButtonState *tb; + ValuatorClassPtr v; + xValuatorState *tv; + xQueryDeviceStateReply rep; + DeviceIntPtr dev; + int *values; + + REQUEST(xQueryDeviceStateReq); + REQUEST_SIZE_MATCH(xQueryDeviceStateReq); + + rep.repType = X_Reply; + rep.RepType = X_QueryDeviceState; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_QueryDeviceState, 0, + BadDevice); + return Success; + } + + v = dev->valuator; + if (v != NULL && v->motionHintWindow != NULL) + MaybeStopDeviceHint(dev, client); + + k = dev->key; + if (k != NULL) + { + total_length += sizeof (xKeyState); + num_classes++; + } + + b = dev->button; + if (b != NULL) + { + total_length += sizeof (xButtonState); + num_classes++; + } + + if (v != NULL) + { + total_length += (sizeof(xValuatorState) + + (v->numAxes * sizeof(int))); + num_classes++; + } + buf = (char *) Xalloc (total_length); + if (!buf) + { + SendErrorToClient(client, IReqCode, X_QueryDeviceState, 0, + BadAlloc); + return Success; + } + savbuf = buf; + + if (k != NULL) + { + tk = (xKeyState *) buf; + tk->class = KeyClass; + tk->length = sizeof (xKeyState); + tk->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode + 1; + for (i = 0; i<32; i++) + tk->keys[i] = k->down[i]; + buf += sizeof (xKeyState); + } + + if (b != NULL) + { + tb = (xButtonState *) buf; + tb->class = ButtonClass; + tb->length = sizeof (xButtonState); + tb->num_buttons = b->numButtons; + for (i = 0; i<32; i++) + tb->buttons[i] = b->down[i]; + buf += sizeof (xButtonState); + } + + if (v != NULL) + { + tv = (xValuatorState *) buf; + tv->class = ValuatorClass; + tv->length = sizeof (xValuatorState); + tv->num_valuators = v->numAxes; + tv->mode = v->mode; + buf += sizeof(xValuatorState); + for (i=0, values=v->axisVal; inumAxes; i++) + { + *((int *) buf) = *values++; + if (client->swapped) + { + swapl ((int *) buf, n);/* macro - braces needed */ + } + buf += sizeof(int); + } + } + + rep.num_classes = num_classes; + rep.length = (total_length + 3) >> 2; + WriteReplyToClient (client, sizeof(xQueryDeviceStateReply), &rep); + if (total_length > 0) + WriteToClient (client, total_length, savbuf); + Xfree (savbuf); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XQueryDeviceState function, + * if the client and server have a different byte ordering. + * + */ + +SRepXQueryDeviceState (client, size, rep) + ClientPtr client; + int size; + xQueryDeviceStateReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/selectev.c b/Xi/selectev.c new file mode 100644 index 000000000..510062993 --- /dev/null +++ b/Xi/selectev.c @@ -0,0 +1,150 @@ +/* $Xorg: selectev.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to select input from an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES + +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern Mask ExtExclusiveMasks[]; +extern Mask ExtValidMasks[]; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle requests from clients with a different byte order. + * + */ + +int +SProcXSelectExtensionEvent (client) +register ClientPtr client; + { + register char n; + register long *p; + register int i; + + REQUEST(xSelectExtensionEventReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSelectExtensionEventReq); + swapl(&stuff->window, n); + swaps(&stuff->count, n); + p = (long *) &stuff[1]; + for (i=0; icount; i++) + { + swapl(p, n); + p++; + } + return(ProcXSelectExtensionEvent(client)); + } + +/*********************************************************************** + * + * This procedure selects input from an extension device. + * + */ + +int +ProcXSelectExtensionEvent (client) + register ClientPtr client; + { + int ret; + int i; + WindowPtr pWin; + struct tmask tmp[EMASKSIZE]; + + REQUEST(xSelectExtensionEventReq); + REQUEST_AT_LEAST_SIZE(xSelectExtensionEventReq); + + if (stuff->length !=(sizeof(xSelectExtensionEventReq)>>2) + stuff->count) + { + SendErrorToClient (client, IReqCode, X_SelectExtensionEvent, 0, + BadLength); + return Success; + } + + pWin = (WindowPtr) LookupWindow (stuff->window, client); + if (!pWin) + { + client->errorValue = stuff->window; + SendErrorToClient(client, IReqCode, X_SelectExtensionEvent, 0, + BadWindow); + return Success; + } + + if ((ret = CreateMaskFromList (client, (XEventClass *)&stuff[1], + stuff->count, tmp, NULL, X_SelectExtensionEvent)) != Success) + return Success; + + for (i=0; ilength, n); + REQUEST_AT_LEAST_SIZE(xSendExtensionEventReq); + swapl(&stuff->destination, n); + swaps(&stuff->count, n); + eventP = (xEvent *) &stuff[1]; + for (i=0; inum_events; i++,eventP++) + { + proc = EventSwapVector[eventP->u.u.type & 0177]; + if (proc == NotImplemented) /* no swapping proc; invalid event type? */ + return (BadValue); + (*proc)(eventP, &eventT); + *eventP = eventT; + } + + p = (long *) (((xEvent *) &stuff[1]) + stuff->num_events); + for (i=0; icount; i++) + { + swapl(p, n); + p++; + } + return(ProcXSendExtensionEvent(client)); + } + +/*********************************************************************** + * + * Send an event to some client, as if it had come from an extension input + * device. + * + */ + +ProcXSendExtensionEvent (client) + register ClientPtr client; + { + int ret; + extern int lastEvent; /* Defined in extension.c */ + DeviceIntPtr dev; + xEvent *first; + XEventClass *list; + struct tmask tmp[EMASKSIZE]; + + REQUEST(xSendExtensionEventReq); + REQUEST_AT_LEAST_SIZE(xSendExtensionEventReq); + + if (stuff->length !=(sizeof(xSendExtensionEventReq)>>2) + stuff->count + + (stuff->num_events * (sizeof (xEvent) >> 2))) + { + SendErrorToClient (client, IReqCode, X_SendExtensionEvent, 0, + BadLength); + return Success; + } + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_SendExtensionEvent, 0, + BadDevice); + return Success; + } + + /* The client's event type must be one defined by an extension. */ + + first = ((xEvent *) &stuff[1]); + if ( ! ((EXTENSION_EVENT_BASE <= first->u.u.type) && + (first->u.u.type < lastEvent)) ) + { + client->errorValue = first->u.u.type; + SendErrorToClient(client, IReqCode, X_SendExtensionEvent, 0, + BadValue); + return Success; + } + + list = (XEventClass *) (first + stuff->num_events); + if ((ret = CreateMaskFromList (client, list, stuff->count, tmp, dev, + X_SendExtensionEvent)) != Success) + return Success; + + ret = (SendEvent (client, dev, stuff->destination, + stuff->propagate, &stuff[1], tmp[stuff->deviceid].mask, + stuff->num_events)); + + if (ret != Success) + SendErrorToClient(client, IReqCode, X_SendExtensionEvent, 0, ret); + + return Success; + } diff --git a/Xi/setbmap.c b/Xi/setbmap.c new file mode 100644 index 000000000..b5335de05 --- /dev/null +++ b/Xi/setbmap.c @@ -0,0 +1,163 @@ +/* $Xorg: setbmap.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to change the button mapping of an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#define IsOn(ptr, bit) \ + (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) + +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern int DeviceMappingNotify; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure changes the button mapping. + * + */ + +int +SProcXSetDeviceButtonMapping(client) + register ClientPtr client; + { + register char n; + + REQUEST(xSetDeviceButtonMappingReq); + swaps(&stuff->length, n); + return(ProcXSetDeviceButtonMapping(client)); + } + +/*********************************************************************** + * + * This procedure lists the input devices available to the server. + * + */ + +ProcXSetDeviceButtonMapping (client) + register ClientPtr client; + { + int ret; + xSetDeviceButtonMappingReply rep; + DeviceIntPtr dev; + + REQUEST(xSetDeviceButtonMappingReq); + REQUEST_AT_LEAST_SIZE(xSetDeviceButtonMappingReq); + + if (stuff->length != (sizeof(xSetDeviceButtonMappingReq) + + stuff->map_length + 3)>>2) + { + SendErrorToClient(client, IReqCode, X_SetDeviceButtonMapping, 0, + BadLength); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_SetDeviceButtonMapping; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.status = MappingSuccess; + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_SetDeviceButtonMapping, 0, + BadDevice); + return Success; + } + + ret = SetButtonMapping (client, dev, stuff->map_length, &stuff[1]); + + if (ret == BadValue || ret == BadMatch) + { + SendErrorToClient(client, IReqCode, X_SetDeviceButtonMapping, 0, + ret); + return Success; + } + else + { + rep.status = ret; + WriteReplyToClient(client, sizeof(xSetDeviceButtonMappingReply), &rep); + } + + if (ret != MappingBusy) + SendDeviceMappingNotify(MappingPointer, 0, 0, dev); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XSetDeviceButtonMapping function, + * if the client and server have a different byte ordering. + * + */ + +SRepXSetDeviceButtonMapping (client, size, rep) + ClientPtr client; + int size; + xSetDeviceButtonMappingReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/setdval.c b/Xi/setdval.c new file mode 100644 index 000000000..533b1ef5b --- /dev/null +++ b/Xi/setdval.c @@ -0,0 +1,167 @@ +/* $Xorg: setdval.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to change the mode of an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "XI.h" +#include "XIproto.h" +#include "inputstr.h" /* DeviceIntPtr */ + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle a request from a client with a different byte order. + * + */ + +int +SProcXSetDeviceValuators(client) + register ClientPtr client; + { + register char n; + + REQUEST(xSetDeviceValuatorsReq); + swaps(&stuff->length, n); + return(ProcXSetDeviceValuators(client)); + } + +/*********************************************************************** + * + * This procedure sets the value of valuators on an extension input device. + * + */ + +int +ProcXSetDeviceValuators(client) + register ClientPtr client; + { + DeviceIntPtr dev; + xSetDeviceValuatorsReply rep; + + REQUEST(xSetDeviceValuatorsReq); + REQUEST_AT_LEAST_SIZE(xSetDeviceValuatorsReq); + + rep.repType = X_Reply; + rep.RepType = X_SetDeviceValuators; + rep.length = 0; + rep.status = Success; + rep.sequenceNumber = client->sequence; + + if (stuff->length !=(sizeof(xSetDeviceValuatorsReq)>>2) + + stuff->num_valuators) + { + SendErrorToClient (client, IReqCode, X_SetDeviceValuators, 0, + BadLength); + return Success; + } + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_SetDeviceValuators, 0, + BadDevice); + return Success; + } + if (dev->valuator == NULL) + { + SendErrorToClient(client, IReqCode, X_SetDeviceValuators, 0, + BadMatch); + return Success; + } + + if (stuff->first_valuator + stuff->num_valuators > dev->valuator->numAxes) + { + SendErrorToClient(client, IReqCode, X_SetDeviceValuators, 0, + BadValue); + return Success; + } + + if ((dev->grab) && !SameClient(dev->grab, client)) + rep.status = AlreadyGrabbed; + else + rep.status = SetDeviceValuators (client, dev, (int *) &stuff[1], + stuff->first_valuator, stuff->num_valuators); + + if (rep.status != Success && rep.status != AlreadyGrabbed) + SendErrorToClient(client, IReqCode, X_SetDeviceValuators, 0, + rep.status); + else + WriteReplyToClient (client, sizeof (xSetDeviceValuatorsReply), &rep); + + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XSetDeviceValuators function, + * if the client and server have a different byte ordering. + * + */ + +SRepXSetDeviceValuators (client, size, rep) + ClientPtr client; + int size; + xSetDeviceValuatorsReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/setfocus.c b/Xi/setfocus.c new file mode 100644 index 000000000..afa5de15b --- /dev/null +++ b/Xi/setfocus.c @@ -0,0 +1,119 @@ +/* $Xorg: setfocus.c,v 1.4 2001/02/09 02:04:34 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to set the focus for an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "windowstr.h" /* focus struct */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern InputInfo inputInfo; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure sets the focus for a device. + * + */ + +int +SProcXSetDeviceFocus(client) + register ClientPtr client; + { + register char n; + + REQUEST(xSetDeviceFocusReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetDeviceFocusReq); + swapl(&stuff->focus, n); + swapl(&stuff->time, n); + return(ProcXSetDeviceFocus(client)); + } + +/*********************************************************************** + * + * This procedure sets the focus for a device. + * + */ + +int +ProcXSetDeviceFocus(client) + register ClientPtr client; + { + int ret; + register DeviceIntPtr dev; + + REQUEST(xSetDeviceFocusReq); + REQUEST_SIZE_MATCH(xSetDeviceFocusReq); + + dev = LookupDeviceIntRec (stuff->device); + if (dev==NULL || !dev->focus) + { + SendErrorToClient(client, IReqCode, X_SetDeviceFocus, 0, BadDevice); + return Success; + } + + ret = SetInputFocus (client, dev, stuff->focus, stuff->revertTo, + stuff->time, TRUE); + if (ret != Success) + SendErrorToClient(client, IReqCode, X_SetDeviceFocus, 0, ret); + + return Success; + } diff --git a/Xi/setmmap.c b/Xi/setmmap.c new file mode 100644 index 000000000..16f3373a8 --- /dev/null +++ b/Xi/setmmap.c @@ -0,0 +1,157 @@ +/* $Xorg: setmmap.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/******************************************************************** + * + * Set modifier mapping for an extension device. + * + */ + +#define NEED_EVENTS /* for inputstr.h */ +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "XI.h" +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern int DeviceMappingNotify; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * This procedure sets the modifier mapping for an extension device, + * for clients on machines with a different byte ordering than the server. + * + */ + +int +SProcXSetDeviceModifierMapping(client) + register ClientPtr client; + { + register char n; + + REQUEST(xSetDeviceModifierMappingReq); + swaps(&stuff->length, n); + return(ProcXSetDeviceModifierMapping(client)); + } + +/*********************************************************************** + * + * Set the device Modifier mapping. + * + */ + +ProcXSetDeviceModifierMapping(client) + ClientPtr client; + { + int ret; + xSetDeviceModifierMappingReply rep; + DeviceIntPtr dev; + KeyClassPtr kp; + + REQUEST(xSetDeviceModifierMappingReq); + REQUEST_AT_LEAST_SIZE(xSetDeviceModifierMappingReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_SetDeviceModifierMapping, 0, + BadDevice); + return Success; + } + + rep.repType = X_Reply; + rep.RepType = X_SetDeviceModifierMapping; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + ret = SetModifierMapping(client, dev, stuff->length, + (sizeof (xSetDeviceModifierMappingReq)>>2), stuff->numKeyPerModifier, + &stuff[1], &kp); + + if (ret==MappingSuccess || ret==MappingBusy || ret==MappingFailed) + { + rep.success = ret; + if (ret == MappingSuccess) + SendDeviceMappingNotify(MappingModifier, 0, 0, dev); + WriteReplyToClient(client, sizeof(xSetDeviceModifierMappingReply),&rep); + } + else + { + if (ret==-1) + ret=BadValue; + SendErrorToClient (client, IReqCode, X_SetDeviceModifierMapping, 0,ret); + } + + + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XSetDeviceModifierMapping function, + * if the client and server have a different byte ordering. + * + */ + +SRepXSetDeviceModifierMapping (client, size, rep) + ClientPtr client; + int size; + xSetDeviceModifierMappingReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } + diff --git a/Xi/setmode.c b/Xi/setmode.c new file mode 100644 index 000000000..f2458f4e6 --- /dev/null +++ b/Xi/setmode.c @@ -0,0 +1,151 @@ +/* $Xorg: setmode.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to change the mode of an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "XI.h" +#include "XIproto.h" +#include "inputstr.h" /* DeviceIntPtr */ + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle a request from a client with a different byte order. + * + */ + +int +SProcXSetDeviceMode(client) + register ClientPtr client; + { + register char n; + + REQUEST(xSetDeviceModeReq); + swaps(&stuff->length, n); + return(ProcXSetDeviceMode(client)); + } + +/*********************************************************************** + * + * This procedure sets the mode of a device. + * + */ + +int +ProcXSetDeviceMode(client) + register ClientPtr client; + { + DeviceIntPtr dev; + xSetDeviceModeReply rep; + + REQUEST(xSetDeviceModeReq); + REQUEST_SIZE_MATCH(xSetDeviceModeReq); + + rep.repType = X_Reply; + rep.RepType = X_SetDeviceMode; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient (client, IReqCode, X_SetDeviceMode, 0, BadDevice); + return Success; + } + if (dev->valuator == NULL) + { + SendErrorToClient(client, IReqCode, X_SetDeviceMode, 0, BadMatch); + return Success; + } + if ((dev->grab) && !SameClient(dev->grab, client)) + rep.status = AlreadyGrabbed; + else + rep.status = SetDeviceMode (client, dev, stuff->mode); + + if (rep.status == Success) + dev->valuator->mode = stuff->mode; + else if (rep.status != AlreadyGrabbed) + { + SendErrorToClient(client, IReqCode, X_SetDeviceMode, 0, rep.status); + return Success; + } + + WriteReplyToClient (client, sizeof (xSetDeviceModeReply), &rep); + return Success; + } + +/*********************************************************************** + * + * This procedure writes the reply for the XSetDeviceMode function, + * if the client and server have a different byte ordering. + * + */ + +SRepXSetDeviceMode (client, size, rep) + ClientPtr client; + int size; + xSetDeviceModeReply *rep; + { + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); + } diff --git a/Xi/stubs.c b/Xi/stubs.c new file mode 100644 index 000000000..9c9269719 --- /dev/null +++ b/Xi/stubs.c @@ -0,0 +1,307 @@ +/* $Xorg: stubs.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/* + * stubs.c -- stub routines for the X server side of the XINPUT + * extension. This file is mainly to be used only as documentation. + * There is not much code here, and you can't get a working XINPUT + * server just using this. + * The Xvfb server uses this file so it will compile with the same + * object files as the real X server for a platform that has XINPUT. + * Xnest could do the same thing. + */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "XI.h" +#include "XIproto.h" + +/*********************************************************************** + * + * Caller: ProcXChangeKeyboardDevice + * + * This procedure does the implementation-dependent portion of the work + * needed to change the keyboard device. + * + * The X keyboard device has a FocusRec. If the device that has been + * made into the new X keyboard did not have a FocusRec, + * ProcXChangeKeyboardDevice will allocate one for it. + * + * If you do not want clients to be able to focus the old X keyboard + * device, call DeleteFocusClassDeviceStruct to free the FocusRec. + * + * If you support input devices with keys that you do not want to be + * used as the X keyboard, you need to check for them here and return + * a BadDevice error. + * + * The default implementation is to do nothing (assume you do want + * clients to be able to focus the old X keyboard). The commented-out + * sample code shows what you might do if you don't want the default. + * + */ + +int +ChangeKeyboardDevice (old_dev, new_dev) + DeviceIntPtr old_dev; + DeviceIntPtr new_dev; + { + /*********************************************************************** + DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c * + **********************************************************************/ + } + + +/*********************************************************************** + * + * Caller: ProcXChangePointerDevice + * + * This procedure does the implementation-dependent portion of the work + * needed to change the pointer device. + * + * The X pointer device does not have a FocusRec. If the device that + * has been made into the new X pointer had a FocusRec, + * ProcXChangePointerDevice will free it. + * + * If you want clients to be able to focus the old pointer device that + * has now become accessible through the input extension, you need to + * add a FocusRec to it here. + * + * The XChangePointerDevice protocol request also allows the client + * to choose which axes of the new pointer device are used to move + * the X cursor in the X- and Y- directions. If the axes are different + * than the default ones, you need to keep track of that here. + * + * If you support input devices with valuators that you do not want to be + * used as the X pointer, you need to check for them here and return a + * BadDevice error. + * + * The default implementation is to do nothing (assume you don't want + * clients to be able to focus the old X pointer). The commented-out + * sample code shows what you might do if you don't want the default. + * + */ + +int +ChangePointerDevice (old_dev, new_dev, x, y) + DeviceIntPtr old_dev, new_dev; + unsigned char x, y; + { + /*********************************************************************** + InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr* + + x_axis = x; * keep track of new x-axis* + y_axis = y; * keep track of new y-axis* + if (x_axis != 0 || y_axis != 1) + axes_changed = TRUE; * remember axes have changed* + else + axes_changed = FALSE; + *************************************************************************/ + } + +/*********************************************************************** + * + * Caller: ProcXCloseDevice + * + * Take care of implementation-dependent details of closing a device. + * Some implementations may actually close the device, others may just + * remove this clients interest in that device. + * + * The default implementation is to do nothing (assume all input devices + * are initialized during X server initialization and kept open). + * + */ + +void +CloseInputDevice (d, client) + DeviceIntPtr d; + ClientPtr client; + { + } + +/*********************************************************************** + * + * Caller: ProcXListInputDevices + * + * This is the implementation-dependent routine to initialize an input + * device to the point that information about it can be listed. + * Some implementations open all input devices when the server is first + * initialized, and never close them. Other implementations open only + * the X pointer and keyboard devices during server initialization, + * and only open other input devices when some client makes an + * XOpenDevice request. If some other process has the device open, the + * server may not be able to get information about the device to list it. + * + * This procedure should be used by implementations that do not initialize + * all input devices at server startup. It should do device-dependent + * initialization for any devices not previously initialized, and call + * AddInputDevice for each of those devices so that a DeviceIntRec will be + * created for them. + * + * The default implementation is to do nothing (assume all input devices + * are initialized during X server initialization and kept open). + * The commented-out sample code shows what you might do if you don't want + * the default. + * + */ + +void +AddOtherInputDevices () + { + DeviceIntPtr dev; + DeviceProc deviceProc; + pointer private; + + /********************************************************************** + for each uninitialized device, do something like: + + dev = (DeviceIntPtr) AddInputDevice(deviceProc, TRUE); + dev->public.devicePrivate = private; + RegisterOtherDevice(dev); + dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success); + ************************************************************************/ + + } + +/*********************************************************************** + * + * Caller: ProcXOpenDevice + * + * This is the implementation-dependent routine to open an input device. + * Some implementations open all input devices when the server is first + * initialized, and never close them. Other implementations open only + * the X pointer and keyboard devices during server initialization, + * and only open other input devices when some client makes an + * XOpenDevice request. This entry point is for the latter type of + * implementation. + * + * If the physical device is not already open, do it here. In this case, + * you need to keep track of the fact that one or more clients has the + * device open, and physically close it when the last client that has + * it open does an XCloseDevice. + * + * The default implementation is to do nothing (assume all input devices + * are opened during X server initialization and kept open). + * + */ + +void +OpenInputDevice (dev, client, status) + DeviceIntPtr dev; + ClientPtr client; + int *status; + { + } + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + */ + +int +SetDeviceMode (client, dev, mode) + register ClientPtr client; + DeviceIntPtr dev; + int mode; + { + return BadMatch; + } + +/**************************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + */ + +int +SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators) + register ClientPtr client; + DeviceIntPtr dev; + int *valuators; + int first_valuator; + int num_valuators; + { + return BadMatch; + } + +/**************************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + */ + +int +ChangeDeviceControl (client, dev, control) + register ClientPtr client; + DeviceIntPtr dev; + xDeviceCtl *control; + { + switch (control->control) + { + case DEVICE_RESOLUTION: + return (BadMatch); + default: + return (BadMatch); + } + } diff --git a/Xi/ungrdev.c b/Xi/ungrdev.c new file mode 100644 index 000000000..90a01a4bc --- /dev/null +++ b/Xi/ungrdev.c @@ -0,0 +1,118 @@ +/* $Xorg: ungrdev.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to release a grab of an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XIproto.h" + +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle requests from a client with a different byte order. + * + */ + +int +SProcXUngrabDevice(client) +register ClientPtr client; + { + register char n; + + REQUEST(xUngrabDeviceReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xUngrabDeviceReq); + swapl(&stuff->time, n); + return(ProcXUngrabDevice(client)); + } + +/*********************************************************************** + * + * Release a grab of an extension device. + * + */ + +int +ProcXUngrabDevice(client) +register ClientPtr client; + { + DeviceIntPtr dev; + GrabPtr grab; + TimeStamp time; + + REQUEST(xUngrabDeviceReq); + REQUEST_SIZE_MATCH(xUngrabDeviceReq); + + dev = LookupDeviceIntRec (stuff->deviceid); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDevice, 0, BadDevice); + return Success; + } + grab = dev->grab; + + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, dev->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*dev->DeactivateGrab)(dev); + return Success; + } diff --git a/Xi/ungrdevb.c b/Xi/ungrdevb.c new file mode 100644 index 000000000..917efda9c --- /dev/null +++ b/Xi/ungrdevb.c @@ -0,0 +1,172 @@ +/* $Xorg: ungrdevb.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to release a grab of a button on an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XI.h" +#include "XIproto.h" + +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +extern int IReqCode; +extern int BadDevice; +extern int DeviceButtonPress; +extern void (* ReplySwapVector[256]) (); +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle requests from a client with a different byte order. + * + */ + +int +SProcXUngrabDeviceButton(client) + register ClientPtr client; + { + register char n; + + REQUEST(xUngrabDeviceButtonReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xUngrabDeviceButtonReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return(ProcXUngrabDeviceButton(client)); + } + +/*********************************************************************** + * + * Release a grab of a button on an extension device. + * + */ + +int +ProcXUngrabDeviceButton(client) + ClientPtr client; + { + DeviceIntPtr dev; + DeviceIntPtr mdev; + WindowPtr pWin; + GrabRec temporaryGrab; + + REQUEST(xUngrabDeviceButtonReq); + REQUEST_SIZE_MATCH(xUngrabDeviceButtonReq); + + dev = LookupDeviceIntRec (stuff->grabbed_device); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, + BadDevice); + return Success; + } + if (dev->button == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, + BadMatch); + return Success; + } + + if (stuff->modifier_device != UseXKeyboard) + { + mdev = LookupDeviceIntRec (stuff->modifier_device); + if (mdev == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, + BadDevice); + return Success; + } + if (mdev->key == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, + BadMatch); + return Success; + } + } + else + mdev = (DeviceIntPtr) LookupKeyboardDevice(); + + pWin = LookupWindow(stuff->grabWindow, client); + if (!pWin) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, + BadWindow); + return Success; + } + + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, + BadValue); + return Success; + } + + temporaryGrab.resource = client->clientAsMask; + temporaryGrab.device = dev; + temporaryGrab.window = pWin; + temporaryGrab.type = DeviceButtonPress; + temporaryGrab.modifierDevice = mdev; + temporaryGrab.modifiersDetail.exact = stuff->modifiers; + temporaryGrab.modifiersDetail.pMask = NULL; + temporaryGrab.detail.exact = stuff->button; + temporaryGrab.detail.pMask = NULL; + + DeletePassiveGrabFromList(&temporaryGrab); + return Success; + } diff --git a/Xi/ungrdevk.c b/Xi/ungrdevk.c new file mode 100644 index 000000000..26c75f365 --- /dev/null +++ b/Xi/ungrdevk.c @@ -0,0 +1,178 @@ +/* $Xorg: ungrdevk.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + 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 name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD 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. + +********************************************************/ + +/*********************************************************************** + * + * Request to release a grab of a key on an extension device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "X.h" /* for inputstr.h */ +#include "Xproto.h" /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "XI.h" +#include "XIproto.h" + +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +extern int IReqCode; +extern int BadDevice; +extern void (* ReplySwapVector[256]) (); +extern int DeviceKeyPress; +DeviceIntPtr LookupDeviceIntRec(); + +/*********************************************************************** + * + * Handle requests from a client with a different byte order. + * + */ + +int +SProcXUngrabDeviceKey(client) + register ClientPtr client; + { + register char n; + + REQUEST(xUngrabDeviceKeyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xUngrabDeviceKeyReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return(ProcXUngrabDeviceKey(client)); + } + +/*********************************************************************** + * + * Release a grab of a key on an extension device. + * + */ + +int +ProcXUngrabDeviceKey(client) + ClientPtr client; + { + DeviceIntPtr dev; + DeviceIntPtr mdev; + WindowPtr pWin; + GrabRec temporaryGrab; + + REQUEST(xUngrabDeviceKeyReq); + REQUEST_SIZE_MATCH(xUngrabDeviceKeyReq); + + dev = LookupDeviceIntRec (stuff->grabbed_device); + if (dev == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, + BadDevice); + return Success; + } + if (dev->key == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, BadMatch); + return Success; + } + + if (stuff->modifier_device != UseXKeyboard) + { + mdev = LookupDeviceIntRec (stuff->modifier_device); + if (mdev == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, + BadDevice); + return Success; + } + if (mdev->key == NULL) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, + BadMatch); + return Success; + } + } + else + mdev = (DeviceIntPtr) LookupKeyboardDevice(); + + pWin = LookupWindow(stuff->grabWindow, client); + if (!pWin) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, + BadWindow); + return Success; + } + if (((stuff->key > dev->key->curKeySyms.maxKeyCode) || + (stuff->key < dev->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, + BadValue); + return Success; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, + BadValue); + return Success; + } + + temporaryGrab.resource = client->clientAsMask; + temporaryGrab.device = dev; + temporaryGrab.window = pWin; + temporaryGrab.type = DeviceKeyPress; + temporaryGrab.modifierDevice = mdev; + temporaryGrab.modifiersDetail.exact = stuff->modifiers; + temporaryGrab.modifiersDetail.pMask = NULL; + temporaryGrab.detail.exact = stuff->key; + temporaryGrab.detail.pMask = NULL; + + DeletePassiveGrabFromList(&temporaryGrab); + return Success; + } diff --git a/XpConfig/C/print/Xprinters b/XpConfig/C/print/Xprinters new file mode 100644 index 000000000..9290636fb --- /dev/null +++ b/XpConfig/C/print/Xprinters @@ -0,0 +1,43 @@ +######################################################################## +# +# $Xorg: Xprinters,v 1.3 2000/08/17 19:48:02 cpqbld Exp $ +# +# X*printers sample configuration file +# +# +# This file belongs in /usr/lib/X11/X*printers, where the "*" is the +# display number of the server. For example, if the server is +# invoked using the command X :0, then the X0printers file is used. +######################################################################## + +######################################################################## +# Use lpstat to augment the list of printers managed by the +# server. (This is the default behavior if the X*printers file does +# not exist, or if an "Augment_Printer_List" line is not specified.) +######################################################################## +#Augment_Printer_List %(default)% + +######################################################################## +# Use the specified command pipeline to augment the list of printers +# managed by the server. +######################################################################## +#Augment_Printer_List lpstat -a | cut -d " " -f 1 # equivalent to default + +######################################################################## +# Do not augment the list of printers managed by the server. +######################################################################## +#Augment_Printer_List %none% + +######################################################################## +# Add individual printers to the list of printers managed by the +# server. These are aliases, determined by driver name. +######################################################################## + + +# EXAMPLES +# +# Printer xppspr +# Printer xppclpr +# Printer xppclmonopr +# Printer xprasterpr + diff --git a/XpConfig/C/print/attributes/document b/XpConfig/C/print/attributes/document new file mode 100644 index 000000000..e0be64553 --- /dev/null +++ b/XpConfig/C/print/attributes/document @@ -0,0 +1,38 @@ +# $Xorg: document,v 1.3 2000/08/17 19:48:03 cpqbld Exp $ +# Document DPA-Object initial attribute values + +# Attribute IDs must be qualified by using one of the following +# (listed in order of precedence): +# +# printer-name +# Set this attribute for a specific printer. +# Example: "dj_1.plex: duplex" +# +# printer-model +# Set this attribute for all printers of a specific model. +# Example: "HPDJ1600C.plex: duplex" +# +# '*' +# Set this attribute for all printers. +# Example: "*.plex: duplex" + + +*content-orientation: portrait +*copy-count: 1 +*default-medium: iso-a4 +*default-printer-resolution: 300 +*document-format: {Postscript 2} +*plex: duplex + + +# EXAMPLES +# +# *content-orientation: landscape +# *copy-count: 3 +# *default-input-tray: main +# *default-medium: iso-a4 +# *default-printer-resolution: 600 +# *document-format: {PCL 5} +# *plex: simplex +# *xp-listfonts-modes: xp-list-internal-printer-fonts + diff --git a/XpConfig/C/print/attributes/job b/XpConfig/C/print/attributes/job new file mode 100644 index 000000000..aa1911dcd --- /dev/null +++ b/XpConfig/C/print/attributes/job @@ -0,0 +1,25 @@ +# $Xorg: job,v 1.3 2000/08/17 19:48:03 cpqbld Exp $ +# Job DPA-Object initial attribute values + +# Attribute IDs must be qualified by using one of the following +# (listed in order of precedence): +# +# printer-name +# Set this attribute for a specific printer. +# Example: "laser_1.job-priority: 1" +# +# printer-model +# Set this attribute for all printers of a specific model. +# Example: "HPDJ1600C.job-priority: 1" +# +# '*' +# Set this attribute for all printers. +# Example: "*.job-priority: 1" + +*notification-profile: {} + +# EXAMPLES +# +# *job-name: Example Job Name +# *notification-profile: {{event-report-job-completed} electronic-mail} +# *xp-spooler-command-options: -onb diff --git a/XpConfig/C/print/attributes/printer b/XpConfig/C/print/attributes/printer new file mode 100644 index 000000000..a49afa5f0 --- /dev/null +++ b/XpConfig/C/print/attributes/printer @@ -0,0 +1,80 @@ +# $Xorg: printer,v 1.3 2000/08/17 19:48:03 cpqbld Exp $ +# Printer DPA-Object initial attribute values + +# Attribute IDs must be qualified by using one of the following +# (listed in order of precedence): +# +# printer-name +# Set this attribute for a specific printer. +# Example: "dj_1.document-formats-ready: {pcl 5}" +# +# printer-model +# Set this attribute for all printers of a specific model. +# Example: "HPDJ1600C.document-formats-ready: {pcl 5}" +# +# '*' +# Set this attribute for all printers. +# Example: "*.document-formats-ready: {pcl 5}" + + +*xp-ddx-identifier: XP-POSTSCRIPT + + +# IMPORTANT EXAMPLES +# +# The following are examples of how a printer name is bound +# to a model-config file and ddx driver. +# +# Warning: most X-Servers have a hard limit on the number of ddx +# drivers (ie, screens) they can support at runtime (usually 3 or +# 4). Whatever the number of printers, they cannot create a +# dependency for more than the limit on ddx drivers. Assuming +# "Xprinters" listed all four xp*pr printers below, X-Servers +# with a limit of 3 would not work. +# +# xppspr.xp-model-identifier: HPDJ1600C +# xppspr.xp-ddx-identifier: XP-POSTSCRIPT +# xppspr.document-formats-ready: { PostScript 2 } +# +# xppclpr.xp-model-identifier: HPDJ1600C +# xppclpr.xp-ddx-identifier: XP-PCL-COLOR +# xppclpr.document-formats-ready: { PCL 5 } +# +# xppclmonopr.xp-model-identifier: HPDJ1600C +# xppclmonopr.xp-ddx-identifier: XP-PCL-MONO +# xppclmonopr.document-formats-ready: { PCL 5 } +# +# xprasterpr.xp-model-identifier: HPDJ1600C +# xprasterpr.xp-ddx-identifier: XP-RASTER + + +# MORE EXAMPLES of items often configured in this file +# +# *descriptor: This printer has not been given a name +# *dt-pdm-command: dtpdm +# *input-trays-medium: {top na-letter} {bottom iso-a4} +# *xp-model-identifier: HPDJ1600C +# *xp-spooler-command: /opt/mystuff/bin/mylp -p %printer-name% -c %copy-count% \ +# -j %job-name% -o %options% + + +# USUALLY SET BY THE ddx driver +# +# *content-orientations-supported: portrait landscape reverse-portrait reverse-landscape + + +# USUALLY SET BY THE model-config FILE +# +# *document-formats-supported: {PCL 5} +# *medium-source-sizes-supported: \ +# { top {iso-a4 FALSE {10 200 10 287}} {iso-a5 FALSE {10 138 10 200}} } \ +# { bottom {iso-a4 FALSE {10 200 10 287}} {iso-a5 FALSE {10 138 10 200}} } +# *plexes-supported: simplex duplex tumble +# *printer-model: Hewlett-Packard LaserJet IV +# *printer-resolutions-supported: 300 +# *xp-ddx-identifier: XP-PCL-COLOR +# *xp-embedded-formats-supported: {PCL 5} {HPGL 2} +# *xp-listfonts-modes-supported: xp-list-internal-printer-fonts +# *xp-raw-formats-supported: {PCL 5} +# *xp-setup-proviso: xp-setup-optional + diff --git a/XpConfig/C/print/ddx-config/raster/pcl b/XpConfig/C/print/ddx-config/raster/pcl new file mode 100644 index 000000000..15d33e7b3 --- /dev/null +++ b/XpConfig/C/print/ddx-config/raster/pcl @@ -0,0 +1,39 @@ +# $Xorg: pcl,v 1.3 2000/08/17 19:48:03 cpqbld Exp $ +# This is the file which you should customize to include the printers that +# will print through the raster driver. The early part of this file +# specifies some commn useful defaults. You can override them when +# you list your printers in the second part of this file. This file is +# an X Resource file. To learn more about this file format, consult +# the functional specification. + +# Note that the reference printer for CDEnext is the HP DeskJet 1600C. +# This driver may work for other printers, but the reference printer +# is the only officially supported printer. + + +# DEFAULTS +# ======== + +# The attributes below apply to all printers unless the section below +# specifies something different for the printer. + +# Default printer attributes +# -------------------------- +# Printer attributes control the choices that users will see in the +# setup dialog for those printers. + +# The attributes below apply to all printes unless the section below +# specifies something different for the printer. + +*.media-ready: na-letter-white +*.descriptor: Printer supported by CDEnext DtPrint System. +*.printer-model: HPDJ1600C + +# Printer Specifics + +# Use this section to override the defaults listed above or to override the +# printer attributes described in the model file. +# The lines describing "laser" are just a sample to help you get started. + +# laser.printer-name: laser +# laser.spooler-name: laser diff --git a/XpConfig/C/print/ddx-config/raster/postscript b/XpConfig/C/print/ddx-config/raster/postscript new file mode 100644 index 000000000..e69de29bb diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00051.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00051.pmf new file mode 100644 index 000000000..09cc489a5 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00051.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00052.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00052.pmf new file mode 100644 index 000000000..b21a9a2a8 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00052.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00053.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00053.pmf new file mode 100644 index 000000000..485b874c5 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00053.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00054.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00054.pmf new file mode 100644 index 000000000..524934c71 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00054.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00055.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00055.pmf new file mode 100644 index 000000000..2ef9bc52c Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00055.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00056.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00056.pmf new file mode 100644 index 000000000..3d69311ef Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00056.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00057.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00057.pmf new file mode 100644 index 000000000..3833d4f54 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00057.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00058.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00058.pmf new file mode 100644 index 000000000..289a95e5c Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00058.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00059.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00059.pmf new file mode 100644 index 000000000..a5984bed1 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00059.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00060.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00060.pmf new file mode 100644 index 000000000..df27cd71e Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00060.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00061.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00061.pmf new file mode 100644 index 000000000..fb2b5a433 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00061.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00062.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00062.pmf new file mode 100644 index 000000000..f0e58c435 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00062.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00063.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00063.pmf new file mode 100644 index 000000000..8821ff155 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00063.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00064.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00064.pmf new file mode 100644 index 000000000..e5980fc0e Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00064.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00065.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00065.pmf new file mode 100644 index 000000000..d9a151d7f Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00065.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00066.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00066.pmf new file mode 100644 index 000000000..d14fca56f Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00066.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00067.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00067.pmf new file mode 100644 index 000000000..7a341506f Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00067.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00068.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00068.pmf new file mode 100644 index 000000000..c20e39a21 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00068.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00069.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00069.pmf new file mode 100644 index 000000000..4a4a35281 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00069.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00070.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00070.pmf new file mode 100644 index 000000000..8d97d4339 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00070.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00071.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00071.pmf new file mode 100644 index 000000000..19844c9c6 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00071.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00072.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00072.pmf new file mode 100644 index 000000000..5415c3f44 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00072.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00073.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00073.pmf new file mode 100644 index 000000000..038dfdb46 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00073.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00074.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00074.pmf new file mode 100644 index 000000000..382a78575 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00074.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00075.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00075.pmf new file mode 100644 index 000000000..1c7edf653 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00075.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00076.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00076.pmf new file mode 100644 index 000000000..2f077f40f Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00076.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00077.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00077.pmf new file mode 100644 index 000000000..1ce190d51 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00077.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00079.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00079.pmf new file mode 100644 index 000000000..45d6906ba Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00079.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00080.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00080.pmf new file mode 100644 index 000000000..b991b5edb Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00080.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00081.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00081.pmf new file mode 100644 index 000000000..1935a9f00 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00081.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00082.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00082.pmf new file mode 100644 index 000000000..2000dc057 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00082.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00083.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00083.pmf new file mode 100644 index 000000000..90f0e45a8 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00083.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00084.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00084.pmf new file mode 100644 index 000000000..52ba39b96 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00084.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00085.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00085.pmf new file mode 100644 index 000000000..f5c9053af Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00085.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00086.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00086.pmf new file mode 100644 index 000000000..b7586ca61 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00086.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00087.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00087.pmf new file mode 100644 index 000000000..82f054999 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00087.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00088.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00088.pmf new file mode 100644 index 000000000..591c96b59 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00088.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00089.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00089.pmf new file mode 100644 index 000000000..c8160954a Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00089.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00090.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00090.pmf new file mode 100644 index 000000000..895cfe26a Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00090.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00091.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00091.pmf new file mode 100644 index 000000000..3bdcae4ba Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00091.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00092.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00092.pmf new file mode 100644 index 000000000..a56d47504 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00092.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00093.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00093.pmf new file mode 100644 index 000000000..c85f3b4de Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00093.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00094.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00094.pmf new file mode 100644 index 000000000..875bf1df8 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/9nb00094.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/README b/XpConfig/C/print/models/HPDJ1600C/fonts/README new file mode 100644 index 000000000..cccc2be32 --- /dev/null +++ b/XpConfig/C/print/models/HPDJ1600C/fonts/README @@ -0,0 +1,197 @@ +$Xorg: README,v 1.3 2000/08/17 19:48:04 cpqbld Exp $ + +This directory contains "printer metric files" for the X Print +Server suitable for the DeskJet 1600C printer. The following +*.pmf files were generated by the Hewlett-Packard Company. + + 9nb00051.pmf + 9nb00052.pmf + 9nb00053.pmf + 9nb00054.pmf + 9nb00055.pmf + 9nb00056.pmf + 9nb00057.pmf + 9nb00058.pmf + 9nb00059.pmf + 9nb00060.pmf + 9nb00061.pmf + 9nb00062.pmf + 9nb00063.pmf + 9nb00064.pmf + 9nb00065.pmf + 9nb00066.pmf + 9nb00067.pmf + 9nb00068.pmf + 9nb00069.pmf + 9nb00070.pmf + 9nb00071.pmf + 9nb00072.pmf + 9nb00073.pmf + 9nb00074.pmf + 9nb00075.pmf + 9nb00076.pmf + 9nb00077.pmf + 9nb00079.pmf + 9nb00080.pmf + 9nb00081.pmf + 9nb00082.pmf + 9nb00083.pmf + 9nb00084.pmf + 9nb00085.pmf + 9nb00086.pmf + 9nb00087.pmf + 9nb00088.pmf + 9nb00089.pmf + 9nb00090.pmf + 9nb00091.pmf + 9nb00092.pmf + 9nb00093.pmf + 9nb00094.pmf + lpr0ye1a.pmf + +For reasons of not supporting iso8859.1 and hp-roman8, the following +DeskJet 1600C printer fonts were not converted to *.pmf files. + + 9nb00078.pmf + 9nb00095.pmf + lpr0ylga.pmf + lpr0ypca.pmf + lpr0ypda.pmf + lpr0ypma.pmf + lpr0yr8a.pmf + +Output from the conversion utility is as follows: + + Creating iso8859 1 pmf for 9nb00051.tfm as iso8859.1/9nb00051.pmf + -COMPUGRAPHIC-Albertus-Extra Bold-r-Normal--8782-2500-2540-2540-P-42480-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00052.tfm as iso8859.1/9nb00052.pmf + -COMPUGRAPHIC-Albertus-Semi Bold-r-Normal--8782-2500-2540-2540-P-37640-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00053.tfm as iso8859.1/9nb00053.pmf + -COMPUGRAPHIC-Antique Olive-Bold-r-Normal--8782-2500-2540-2540-P-50490-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00054.tfm as iso8859.1/9nb00054.pmf + -COMPUGRAPHIC-Antique Olive-Medium-i-Normal--8782-2500-2540-2540-P-46140-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00055.tfm as iso8859.1/9nb00055.pmf + -COMPUGRAPHIC-Antique Olive-Medium-r-Normal--8782-2500-2540-2540-P-46380-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00056.tfm as iso8859.1/9nb00056.pmf + -Monotype-Arial-Bold-r-Normal--2048-2500-589-589-P-9800-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00057.tfm as iso8859.1/9nb00057.pmf + -Monotype-Arial-Medium-i-Normal--2048-2500-589-589-P-9040-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00058.tfm as iso8859.1/9nb00058.pmf + -Monotype-Arial-Bold-i-Normal--2048-2500-589-589-P-9800-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00059.tfm as iso8859.1/9nb00059.pmf + -Monotype-Arial-Medium-r-Normal--2048-2500-589-589-P-9040-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00060.tfm as iso8859.1/9nb00060.pmf + -COMPUGRAPHIC-Clarendon-Bold-r-Condensed--8782-2500-2540-2540-P-35080-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00061.tfm as iso8859.1/9nb00061.pmf + -COMPUGRAPHIC-Courier-Bold-r-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00062.tfm as iso8859.1/9nb00062.pmf + -COMPUGRAPHIC-Courier-Medium-i-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00063.tfm as iso8859.1/9nb00063.pmf + -COMPUGRAPHIC-Courier-Bold-i-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00064.tfm as iso8859.1/9nb00064.pmf + -COMPUGRAPHIC-Courier-Medium-r-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00065.tfm as iso8859.1/9nb00065.pmf + -COMPUGRAPHIC-Garamond-Bold-r-Normal--8782-2500-2540-2540-P-38730-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00066.tfm as iso8859.1/9nb00066.pmf + -COMPUGRAPHIC-Garamond-Medium-i-Normal--8782-2500-2540-2540-P-34280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00067.tfm as iso8859.1/9nb00067.pmf + -COMPUGRAPHIC-Garamond-Bold-i-Normal--8782-2500-2540-2540-P-37020-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00068.tfm as iso8859.1/9nb00068.pmf + -COMPUGRAPHIC-Garamond-Medium-r-Normal--8782-2500-2540-2540-P-36560-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00069.tfm as iso8859.1/9nb00069.pmf + -COMPUGRAPHIC-Letter Gothic-Bold-r-Normal--8782-2500-2540-2540-M-44090-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00070.tfm as iso8859.1/9nb00070.pmf + -COMPUGRAPHIC-Letter Gothic-Medium-i-Normal--8782-2500-2540-2540-M-44090-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00071.tfm as iso8859.1/9nb00071.pmf + -COMPUGRAPHIC-Letter Gothic-Medium-r-Normal--8782-2500-2540-2540-M-44090-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00072.tfm as iso8859.1/9nb00072.pmf + -COMPUGRAPHIC-Marigold-Medium-r-Normal--8782-2500-2540-2540-P-21890-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00073.tfm as iso8859.1/9nb00073.pmf + -COMPUGRAPHIC-Omega-Bold-r-Normal--8782-2500-2540-2540-P-38600-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00074.tfm as iso8859.1/9nb00074.pmf + -COMPUGRAPHIC-Omega-Medium-i-Normal--8782-2500-2540-2540-P-37980-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00075.tfm as iso8859.1/9nb00075.pmf + -COMPUGRAPHIC-Omega-Bold-i-Normal--8782-2500-2540-2540-P-38560-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00076.tfm as iso8859.1/9nb00076.pmf + -COMPUGRAPHIC-Omega-Medium-r-Normal--8782-2500-2540-2540-P-37770-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00077.tfm as iso8859.1/9nb00077.pmf + -COMPUGRAPHIC-Coronet-Medium-i-Normal--8782-2500-2540-2540-P-22870-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00079.tfm as iso8859.1/9nb00079.pmf + -Monotype-Times New Roman-Bold-r-Normal--2048-2500-589-589-P-8740-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00080.tfm as iso8859.1/9nb00080.pmf + -Monotype-Times New Roman-Medium-i-Normal--2048-2500-589-589-P-8230-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00081.tfm as iso8859.1/9nb00081.pmf + -Monotype-Times New Roman-Bold-i-Normal--2048-2500-589-589-P-8440-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00082.tfm as iso8859.1/9nb00082.pmf + -Monotype-Times New Roman-Medium-r-Normal--2048-2500-589-589-P-8210-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00083.tfm as iso8859.1/9nb00083.pmf + -COMPUGRAPHIC-Times-Bold-r-Normal--8782-2500-2540-2540-P-38200-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00084.tfm as iso8859.1/9nb00084.pmf + -COMPUGRAPHIC-Times-Medium-i-Normal--8782-2500-2540-2540-P-36000-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00085.tfm as iso8859.1/9nb00085.pmf + -COMPUGRAPHIC-Times-Bold-i-Normal--8782-2500-2540-2540-P-36900-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00086.tfm as iso8859.1/9nb00086.pmf + -COMPUGRAPHIC-Times-Medium-r-Normal--8782-2500-2540-2540-P-36080-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00087.tfm as iso8859.1/9nb00087.pmf + -COMPUGRAPHIC-Univers-Medium-i-Condensed--8782-2500-2540-2540-P-29970-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00088.tfm as iso8859.1/9nb00088.pmf + -COMPUGRAPHIC-Univers-Bold-r-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00089.tfm as iso8859.1/9nb00089.pmf + -COMPUGRAPHIC-Univers-Medium-r-Condensed--8782-2500-2540-2540-P-29970-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00090.tfm as iso8859.1/9nb00090.pmf + -COMPUGRAPHIC-Univers-Bold-r-Condensed--8782-2500-2540-2540-P-33030-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00091.tfm as iso8859.1/9nb00091.pmf + -COMPUGRAPHIC-Univers-Bold-i-Condensed--8782-2500-2540-2540-P-33030-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00092.tfm as iso8859.1/9nb00092.pmf + -COMPUGRAPHIC-Univers-Medium-i-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00093.tfm as iso8859.1/9nb00093.pmf + -COMPUGRAPHIC-Univers-Bold-i-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00094.tfm as iso8859.1/9nb00094.pmf + -COMPUGRAPHIC-Univers-Medium-r-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for lpr0ye1a.tfm as iso8859.1/lpr0ye1a.pmf + -HP-Line Printer-Medium-r-Normal--35-85-300-300-M-180-iso8859-1 + ------------------------------------ + diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/fonts.alias b/XpConfig/C/print/models/HPDJ1600C/fonts/fonts.alias new file mode 100644 index 000000000..e69de29bb diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/fonts.dir b/XpConfig/C/print/models/HPDJ1600C/fonts/fonts.dir new file mode 100644 index 000000000..da702ccc1 --- /dev/null +++ b/XpConfig/C/print/models/HPDJ1600C/fonts/fonts.dir @@ -0,0 +1,45 @@ +44 +lpr0ye1a.pmf -hp-line printer-medium-r-normal--35-85-300-300-m-180-iso8859-1 +9nb00080.pmf -monotype-times new roman-medium-i-normal--2048-2500-589-589-p-8230-iso8859-1 +9nb00092.pmf -compugraphic-univers-medium-i-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00081.pmf -monotype-times new roman-bold-i-normal--2048-2500-589-589-p-8440-iso8859-1 +9nb00093.pmf -compugraphic-univers-bold-i-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00082.pmf -monotype-times new roman-medium-r-normal--2048-2500-589-589-p-8210-iso8859-1 +9nb00090.pmf -compugraphic-univers-bold-r-condensed--8782-2500-2540-2540-p-33030-iso8859-1 +9nb00083.pmf -compugraphic-times-bold-r-normal--8782-2500-2540-2540-p-38200-iso8859-1 +9nb00091.pmf -compugraphic-univers-bold-i-condensed--8782-2500-2540-2540-p-33030-iso8859-1 +9nb00084.pmf -compugraphic-times-medium-i-normal--8782-2500-2540-2540-p-36000-iso8859-1 +9nb00085.pmf -compugraphic-times-bold-i-normal--8782-2500-2540-2540-p-36900-iso8859-1 +9nb00086.pmf -compugraphic-times-medium-r-normal--8782-2500-2540-2540-p-36080-iso8859-1 +9nb00094.pmf -compugraphic-univers-medium-r-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00087.pmf -compugraphic-univers-medium-i-condensed--8782-2500-2540-2540-p-29970-iso8859-1 +9nb00088.pmf -compugraphic-univers-bold-r-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00089.pmf -compugraphic-univers-medium-r-condensed--8782-2500-2540-2540-p-29970-iso8859-1 +9nb00058.pmf -monotype-arial-bold-i-normal--2048-2500-589-589-p-9800-iso8859-1 +9nb00059.pmf -monotype-arial-medium-r-normal--2048-2500-589-589-p-9040-iso8859-1 +9nb00068.pmf -compugraphic-garamond-medium-r-normal--8782-2500-2540-2540-p-36560-iso8859-1 +9nb00069.pmf -compugraphic-letter gothic-bold-r-normal--8782-2500-2540-2540-m-44090-iso8859-1 +9nb00079.pmf -monotype-times new roman-bold-r-normal--2048-2500-589-589-p-8740-iso8859-1 +9nb00052.pmf -compugraphic-albertus-semi bold-r-normal--8782-2500-2540-2540-p-37640-iso8859-1 +9nb00064.pmf -compugraphic-courier-medium-r-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00076.pmf -compugraphic-omega-medium-r-normal--8782-2500-2540-2540-p-37770-iso8859-1 +9nb00053.pmf -compugraphic-antique olive-bold-r-normal--8782-2500-2540-2540-p-50490-iso8859-1 +9nb00065.pmf -compugraphic-garamond-bold-r-normal--8782-2500-2540-2540-p-38730-iso8859-1 +9nb00077.pmf -compugraphic-coronet-medium-i-normal--8782-2500-2540-2540-p-22870-iso8859-1 +9nb00066.pmf -compugraphic-garamond-medium-i-normal--8782-2500-2540-2540-p-34280-iso8859-1 +9nb00074.pmf -compugraphic-omega-medium-i-normal--8782-2500-2540-2540-p-37980-iso8859-1 +9nb00051.pmf -compugraphic-albertus-extra bold-r-normal--8782-2500-2540-2540-p-42480-iso8859-1 +9nb00067.pmf -compugraphic-garamond-bold-i-normal--8782-2500-2540-2540-p-37020-iso8859-1 +9nb00075.pmf -compugraphic-omega-bold-i-normal--8782-2500-2540-2540-p-38560-iso8859-1 +9nb00056.pmf -monotype-arial-bold-r-normal--2048-2500-589-589-p-9800-iso8859-1 +9nb00060.pmf -compugraphic-clarendon-bold-r-condensed--8782-2500-2540-2540-p-35080-iso8859-1 +9nb00072.pmf -compugraphic-marigold-medium-r-normal--8782-2500-2540-2540-p-21890-iso8859-1 +9nb00057.pmf -monotype-arial-medium-i-normal--2048-2500-589-589-p-9040-iso8859-1 +9nb00061.pmf -compugraphic-courier-bold-r-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00073.pmf -compugraphic-omega-bold-r-normal--8782-2500-2540-2540-p-38600-iso8859-1 +9nb00054.pmf -compugraphic-antique olive-medium-i-normal--8782-2500-2540-2540-p-46140-iso8859-1 +9nb00062.pmf -compugraphic-courier-medium-i-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00070.pmf -compugraphic-letter gothic-medium-i-normal--8782-2500-2540-2540-m-44090-iso8859-1 +9nb00055.pmf -compugraphic-antique olive-medium-r-normal--8782-2500-2540-2540-p-46380-iso8859-1 +9nb00063.pmf -compugraphic-courier-bold-i-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00071.pmf -compugraphic-letter gothic-medium-r-normal--8782-2500-2540-2540-m-44090-iso8859-1 diff --git a/XpConfig/C/print/models/HPDJ1600C/fonts/lpr0ye1a.pmf b/XpConfig/C/print/models/HPDJ1600C/fonts/lpr0ye1a.pmf new file mode 100644 index 000000000..483748893 Binary files /dev/null and b/XpConfig/C/print/models/HPDJ1600C/fonts/lpr0ye1a.pmf differ diff --git a/XpConfig/C/print/models/HPDJ1600C/model-config b/XpConfig/C/print/models/HPDJ1600C/model-config new file mode 100644 index 000000000..f3bd8af3a --- /dev/null +++ b/XpConfig/C/print/models/HPDJ1600C/model-config @@ -0,0 +1,44 @@ +# $Xorg: model-config,v 1.3 2000/08/17 19:48:04 cpqbld Exp $ +# This is the configuration file for the HP DeskJet 1600C printer. +# +# The CDEnext SI supports two 1600C drivers XP-PCL-MONO and +# XP-PCL-COLOR, which work with this configuration file. +# +# Attribute IDs must be qualified using either the printer-model +# identifier or an asterisk ('*'). For example, if "HPDJ1600C" is the +# printer-model, then to initialize the 'plexes-supported' attribute +# to 'simplex', use: "HPDJ1600C.plexes-supported: simplex". For the +# asterisk, use: "*.plexes-supported: simplex". If the same attribute +# is specified using each method, the printer-model qualified entry +# takes precedence. + +HPDJ1600C.printer-model: "Hewlett-Packard DeskJet 1600C" +HPDJ1600C.printer-resolutions-supported: 300 +HPDJ1600C.content-orientations-supported: portrait landscape +HPDJ1600C.document-formats-supported: {PCL 5} {PostScript 2} +HPDJ1600C.plexes-supported: simplex duplex +HPDJ1600C.xp-ddx-identifier: XP-PCL-COLOR +HPDJ1600C.xp-embedded-formats-supported: { PCL 5 } { PostScript 2 } +HPDJ1600C.xp-setup-proviso: setup-optional + +# 1/4" unprintable margins +HPDJ1600C.medium-source-sizes-supported:\ +{ '' \ + {na-letter FALSE {6.35 209.55 6.35 273.05}}\ + {executive FALSE {6.35 177.75 6.35 260.35}}\ + {na-legal FALSE {6.35 209.55 6.35 349.25}}\ + {iso-a3 FALSE {6.35 290.65 6.35 413.35}}\ + {iso-a4 FALSE {6.35 203.65 6.35 290.65}}\ + {jis-b4 FALSE {6.35 251.65 6.35 367.65}}\ + {jis-b5 FALSE {6.35 175.65 6.35 250.65}}\ + {monarch-envelope FALSE {6.35 91.94 6.35 184.15}}\ + {iso-designated-long FALSE {6.35 103.65 6.35 213.65}}\ + {iso-c5 FALSE {6.35 155.65 6.35 222.65}}\ + {na-number-10-envelope FALSE {6.35 98.45 6.35 234.95}}\ + {hp-tabloid FALSE {6.35 273.05 6.35 425.45}}\ + {ledger FALSE {6.35 273.05 6.35 425.45}}\ + {b FALSE {6.35 273.05 6.35 425.45}}\ + {hp-japanese-postcard FALSE {6 94 6 142 }}\ + {hp-japanese-doublepostcard FALSE {6 142 6 194 }}\ +} + diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00051.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00051.pmf new file mode 100644 index 000000000..09cc489a5 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00051.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00052.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00052.pmf new file mode 100644 index 000000000..b21a9a2a8 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00052.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00053.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00053.pmf new file mode 100644 index 000000000..485b874c5 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00053.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00054.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00054.pmf new file mode 100644 index 000000000..524934c71 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00054.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00055.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00055.pmf new file mode 100644 index 000000000..2ef9bc52c Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00055.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00056.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00056.pmf new file mode 100644 index 000000000..3d69311ef Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00056.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00057.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00057.pmf new file mode 100644 index 000000000..3833d4f54 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00057.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00058.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00058.pmf new file mode 100644 index 000000000..289a95e5c Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00058.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00059.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00059.pmf new file mode 100644 index 000000000..a5984bed1 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00059.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00060.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00060.pmf new file mode 100644 index 000000000..df27cd71e Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00060.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00061.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00061.pmf new file mode 100644 index 000000000..fb2b5a433 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00061.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00062.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00062.pmf new file mode 100644 index 000000000..f0e58c435 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00062.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00063.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00063.pmf new file mode 100644 index 000000000..8821ff155 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00063.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00064.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00064.pmf new file mode 100644 index 000000000..e5980fc0e Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00064.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00065.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00065.pmf new file mode 100644 index 000000000..d9a151d7f Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00065.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00066.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00066.pmf new file mode 100644 index 000000000..d14fca56f Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00066.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00067.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00067.pmf new file mode 100644 index 000000000..7a341506f Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00067.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00068.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00068.pmf new file mode 100644 index 000000000..c20e39a21 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00068.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00069.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00069.pmf new file mode 100644 index 000000000..4a4a35281 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00069.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00070.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00070.pmf new file mode 100644 index 000000000..8d97d4339 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00070.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00071.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00071.pmf new file mode 100644 index 000000000..19844c9c6 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00071.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00072.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00072.pmf new file mode 100644 index 000000000..5415c3f44 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00072.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00073.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00073.pmf new file mode 100644 index 000000000..038dfdb46 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00073.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00074.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00074.pmf new file mode 100644 index 000000000..382a78575 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00074.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00075.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00075.pmf new file mode 100644 index 000000000..1c7edf653 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00075.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00076.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00076.pmf new file mode 100644 index 000000000..2f077f40f Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00076.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00077.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00077.pmf new file mode 100644 index 000000000..1ce190d51 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00077.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00079.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00079.pmf new file mode 100644 index 000000000..45d6906ba Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00079.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00080.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00080.pmf new file mode 100644 index 000000000..b991b5edb Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00080.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00081.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00081.pmf new file mode 100644 index 000000000..1935a9f00 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00081.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00082.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00082.pmf new file mode 100644 index 000000000..2000dc057 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00082.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00083.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00083.pmf new file mode 100644 index 000000000..90f0e45a8 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00083.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00084.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00084.pmf new file mode 100644 index 000000000..52ba39b96 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00084.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00085.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00085.pmf new file mode 100644 index 000000000..f5c9053af Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00085.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00086.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00086.pmf new file mode 100644 index 000000000..b7586ca61 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00086.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00087.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00087.pmf new file mode 100644 index 000000000..82f054999 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00087.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00088.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00088.pmf new file mode 100644 index 000000000..591c96b59 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00088.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00089.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00089.pmf new file mode 100644 index 000000000..c8160954a Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00089.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00090.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00090.pmf new file mode 100644 index 000000000..895cfe26a Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00090.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00091.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00091.pmf new file mode 100644 index 000000000..3bdcae4ba Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00091.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00092.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00092.pmf new file mode 100644 index 000000000..a56d47504 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00092.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00093.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00093.pmf new file mode 100644 index 000000000..c85f3b4de Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00093.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/9nb00094.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00094.pmf new file mode 100644 index 000000000..875bf1df8 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/9nb00094.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/README b/XpConfig/C/print/models/HPLJ4family/fonts/README new file mode 100644 index 000000000..2c9821834 --- /dev/null +++ b/XpConfig/C/print/models/HPLJ4family/fonts/README @@ -0,0 +1,203 @@ +$Xorg: README,v 1.3 2000/08/17 19:48:04 cpqbld Exp $ + +This directory contains "printer metric files" for the X Print +Server suitable for the LaserJet 4 family of printers - 4, 4L, +4M, 4ML, 4MP, 4P, 4Si, 4Si-MX. The following *.pmf files were +generated by the Hewlett-Packard Company. + + 9nb00051.pmf + 9nb00052.pmf + 9nb00053.pmf + 9nb00054.pmf + 9nb00055.pmf + * 9nb00056.pmf + * 9nb00057.pmf + * 9nb00058.pmf + * 9nb00059.pmf + * 9nb00060.pmf + 9nb00061.pmf + 9nb00062.pmf + 9nb00063.pmf + 9nb00064.pmf + * 9nb00065.pmf + * 9nb00066.pmf + * 9nb00067.pmf + * 9nb00068.pmf + 9nb00069.pmf + 9nb00070.pmf + 9nb00071.pmf + * 9nb00072.pmf + * 9nb00073.pmf + * 9nb00074.pmf + * 9nb00075.pmf + * 9nb00076.pmf + 9nb00077.pmf + * 9nb00079.pmf + * 9nb00080.pmf + * 9nb00081.pmf + * 9nb00082.pmf + 9nb00083.pmf + 9nb00084.pmf + 9nb00085.pmf + 9nb00086.pmf + 9nb00087.pmf + 9nb00088.pmf + 9nb00089.pmf + 9nb00090.pmf + 9nb00091.pmf + 9nb00092.pmf + 9nb00093.pmf + 9nb00094.pmf + lpr0ye1a.pmf + + + * note - the marked fonts are NOT supported by the 4L printer. If + making extensive use of the 4L, you may want to create a special + 4L model-config area and exclude these fonts. + +For reasons of not supporting iso8859.1 and hp-roman8, the following +Laserjet 4 printer fonts were not converted to *.pmf files. + + 9nb00078.pmf + 9nb00095.pmf + lpr0ylga.pmf + lpr0ypca.pmf + lpr0ypda.pmf + lpr0ypma.pmf + lpr0yr8a.pmf + +Output from the conversion utility is as follows: + + Creating iso8859 1 pmf for 9nb00051.tfm as iso8859.1/9nb00051.pmf + -COMPUGRAPHIC-Albertus-Extra Bold-r-Normal--8782-2500-2540-2540-P-42480-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00052.tfm as iso8859.1/9nb00052.pmf + -COMPUGRAPHIC-Albertus-Semi Bold-r-Normal--8782-2500-2540-2540-P-37640-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00053.tfm as iso8859.1/9nb00053.pmf + -COMPUGRAPHIC-Antique Olive-Bold-r-Normal--8782-2500-2540-2540-P-50490-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00054.tfm as iso8859.1/9nb00054.pmf + -COMPUGRAPHIC-Antique Olive-Medium-i-Normal--8782-2500-2540-2540-P-46140-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00055.tfm as iso8859.1/9nb00055.pmf + -COMPUGRAPHIC-Antique Olive-Medium-r-Normal--8782-2500-2540-2540-P-46380-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00056.tfm as iso8859.1/9nb00056.pmf + -Monotype-Arial-Bold-r-Normal--2048-2500-589-589-P-9800-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00057.tfm as iso8859.1/9nb00057.pmf + -Monotype-Arial-Medium-i-Normal--2048-2500-589-589-P-9040-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00058.tfm as iso8859.1/9nb00058.pmf + -Monotype-Arial-Bold-i-Normal--2048-2500-589-589-P-9800-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00059.tfm as iso8859.1/9nb00059.pmf + -Monotype-Arial-Medium-r-Normal--2048-2500-589-589-P-9040-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00060.tfm as iso8859.1/9nb00060.pmf + -COMPUGRAPHIC-Clarendon-Bold-r-Condensed--8782-2500-2540-2540-P-35080-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00061.tfm as iso8859.1/9nb00061.pmf + -COMPUGRAPHIC-Courier-Bold-r-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00062.tfm as iso8859.1/9nb00062.pmf + -COMPUGRAPHIC-Courier-Medium-i-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00063.tfm as iso8859.1/9nb00063.pmf + -COMPUGRAPHIC-Courier-Bold-i-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00064.tfm as iso8859.1/9nb00064.pmf + -COMPUGRAPHIC-Courier-Medium-r-Normal--8782-2500-2540-2540-M-52910-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00065.tfm as iso8859.1/9nb00065.pmf + -COMPUGRAPHIC-Garamond-Bold-r-Normal--8782-2500-2540-2540-P-38730-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00066.tfm as iso8859.1/9nb00066.pmf + -COMPUGRAPHIC-Garamond-Medium-i-Normal--8782-2500-2540-2540-P-34280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00067.tfm as iso8859.1/9nb00067.pmf + -COMPUGRAPHIC-Garamond-Bold-i-Normal--8782-2500-2540-2540-P-37020-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00068.tfm as iso8859.1/9nb00068.pmf + -COMPUGRAPHIC-Garamond-Medium-r-Normal--8782-2500-2540-2540-P-36560-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00069.tfm as iso8859.1/9nb00069.pmf + -COMPUGRAPHIC-Letter Gothic-Bold-r-Normal--8782-2500-2540-2540-M-44090-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00070.tfm as iso8859.1/9nb00070.pmf + -COMPUGRAPHIC-Letter Gothic-Medium-i-Normal--8782-2500-2540-2540-M-44090-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00071.tfm as iso8859.1/9nb00071.pmf + -COMPUGRAPHIC-Letter Gothic-Medium-r-Normal--8782-2500-2540-2540-M-44090-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00072.tfm as iso8859.1/9nb00072.pmf + -COMPUGRAPHIC-Marigold-Medium-r-Normal--8782-2500-2540-2540-P-21890-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00073.tfm as iso8859.1/9nb00073.pmf + -COMPUGRAPHIC-Omega-Bold-r-Normal--8782-2500-2540-2540-P-38600-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00074.tfm as iso8859.1/9nb00074.pmf + -COMPUGRAPHIC-Omega-Medium-i-Normal--8782-2500-2540-2540-P-37980-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00075.tfm as iso8859.1/9nb00075.pmf + -COMPUGRAPHIC-Omega-Bold-i-Normal--8782-2500-2540-2540-P-38560-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00076.tfm as iso8859.1/9nb00076.pmf + -COMPUGRAPHIC-Omega-Medium-r-Normal--8782-2500-2540-2540-P-37770-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00077.tfm as iso8859.1/9nb00077.pmf + -COMPUGRAPHIC-Coronet-Medium-i-Normal--8782-2500-2540-2540-P-22870-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00079.tfm as iso8859.1/9nb00079.pmf + -Monotype-Times New Roman-Bold-r-Normal--2048-2500-589-589-P-8740-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00080.tfm as iso8859.1/9nb00080.pmf + -Monotype-Times New Roman-Medium-i-Normal--2048-2500-589-589-P-8230-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00081.tfm as iso8859.1/9nb00081.pmf + -Monotype-Times New Roman-Bold-i-Normal--2048-2500-589-589-P-8440-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00082.tfm as iso8859.1/9nb00082.pmf + -Monotype-Times New Roman-Medium-r-Normal--2048-2500-589-589-P-8210-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00083.tfm as iso8859.1/9nb00083.pmf + -COMPUGRAPHIC-Times-Bold-r-Normal--8782-2500-2540-2540-P-38200-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00084.tfm as iso8859.1/9nb00084.pmf + -COMPUGRAPHIC-Times-Medium-i-Normal--8782-2500-2540-2540-P-36000-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00085.tfm as iso8859.1/9nb00085.pmf + -COMPUGRAPHIC-Times-Bold-i-Normal--8782-2500-2540-2540-P-36900-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00086.tfm as iso8859.1/9nb00086.pmf + -COMPUGRAPHIC-Times-Medium-r-Normal--8782-2500-2540-2540-P-36080-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00087.tfm as iso8859.1/9nb00087.pmf + -COMPUGRAPHIC-Univers-Medium-i-Condensed--8782-2500-2540-2540-P-29970-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00088.tfm as iso8859.1/9nb00088.pmf + -COMPUGRAPHIC-Univers-Bold-r-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00089.tfm as iso8859.1/9nb00089.pmf + -COMPUGRAPHIC-Univers-Medium-r-Condensed--8782-2500-2540-2540-P-29970-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00090.tfm as iso8859.1/9nb00090.pmf + -COMPUGRAPHIC-Univers-Bold-r-Condensed--8782-2500-2540-2540-P-33030-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00091.tfm as iso8859.1/9nb00091.pmf + -COMPUGRAPHIC-Univers-Bold-i-Condensed--8782-2500-2540-2540-P-33030-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00092.tfm as iso8859.1/9nb00092.pmf + -COMPUGRAPHIC-Univers-Medium-i-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00093.tfm as iso8859.1/9nb00093.pmf + -COMPUGRAPHIC-Univers-Bold-i-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for 9nb00094.tfm as iso8859.1/9nb00094.pmf + -COMPUGRAPHIC-Univers-Medium-r-Normal--8782-2500-2540-2540-P-41280-iso8859-1 + ------------------------------------ + Creating iso8859 1 pmf for lpr0ye1a.tfm as iso8859.1/lpr0ye1a.pmf + -HP-Line Printer-Medium-r-Normal--35-85-300-300-M-180-iso8859-1 + ------------------------------------ + diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/fonts.alias b/XpConfig/C/print/models/HPLJ4family/fonts/fonts.alias new file mode 100644 index 000000000..e69de29bb diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/fonts.dir b/XpConfig/C/print/models/HPLJ4family/fonts/fonts.dir new file mode 100644 index 000000000..da702ccc1 --- /dev/null +++ b/XpConfig/C/print/models/HPLJ4family/fonts/fonts.dir @@ -0,0 +1,45 @@ +44 +lpr0ye1a.pmf -hp-line printer-medium-r-normal--35-85-300-300-m-180-iso8859-1 +9nb00080.pmf -monotype-times new roman-medium-i-normal--2048-2500-589-589-p-8230-iso8859-1 +9nb00092.pmf -compugraphic-univers-medium-i-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00081.pmf -monotype-times new roman-bold-i-normal--2048-2500-589-589-p-8440-iso8859-1 +9nb00093.pmf -compugraphic-univers-bold-i-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00082.pmf -monotype-times new roman-medium-r-normal--2048-2500-589-589-p-8210-iso8859-1 +9nb00090.pmf -compugraphic-univers-bold-r-condensed--8782-2500-2540-2540-p-33030-iso8859-1 +9nb00083.pmf -compugraphic-times-bold-r-normal--8782-2500-2540-2540-p-38200-iso8859-1 +9nb00091.pmf -compugraphic-univers-bold-i-condensed--8782-2500-2540-2540-p-33030-iso8859-1 +9nb00084.pmf -compugraphic-times-medium-i-normal--8782-2500-2540-2540-p-36000-iso8859-1 +9nb00085.pmf -compugraphic-times-bold-i-normal--8782-2500-2540-2540-p-36900-iso8859-1 +9nb00086.pmf -compugraphic-times-medium-r-normal--8782-2500-2540-2540-p-36080-iso8859-1 +9nb00094.pmf -compugraphic-univers-medium-r-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00087.pmf -compugraphic-univers-medium-i-condensed--8782-2500-2540-2540-p-29970-iso8859-1 +9nb00088.pmf -compugraphic-univers-bold-r-normal--8782-2500-2540-2540-p-41280-iso8859-1 +9nb00089.pmf -compugraphic-univers-medium-r-condensed--8782-2500-2540-2540-p-29970-iso8859-1 +9nb00058.pmf -monotype-arial-bold-i-normal--2048-2500-589-589-p-9800-iso8859-1 +9nb00059.pmf -monotype-arial-medium-r-normal--2048-2500-589-589-p-9040-iso8859-1 +9nb00068.pmf -compugraphic-garamond-medium-r-normal--8782-2500-2540-2540-p-36560-iso8859-1 +9nb00069.pmf -compugraphic-letter gothic-bold-r-normal--8782-2500-2540-2540-m-44090-iso8859-1 +9nb00079.pmf -monotype-times new roman-bold-r-normal--2048-2500-589-589-p-8740-iso8859-1 +9nb00052.pmf -compugraphic-albertus-semi bold-r-normal--8782-2500-2540-2540-p-37640-iso8859-1 +9nb00064.pmf -compugraphic-courier-medium-r-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00076.pmf -compugraphic-omega-medium-r-normal--8782-2500-2540-2540-p-37770-iso8859-1 +9nb00053.pmf -compugraphic-antique olive-bold-r-normal--8782-2500-2540-2540-p-50490-iso8859-1 +9nb00065.pmf -compugraphic-garamond-bold-r-normal--8782-2500-2540-2540-p-38730-iso8859-1 +9nb00077.pmf -compugraphic-coronet-medium-i-normal--8782-2500-2540-2540-p-22870-iso8859-1 +9nb00066.pmf -compugraphic-garamond-medium-i-normal--8782-2500-2540-2540-p-34280-iso8859-1 +9nb00074.pmf -compugraphic-omega-medium-i-normal--8782-2500-2540-2540-p-37980-iso8859-1 +9nb00051.pmf -compugraphic-albertus-extra bold-r-normal--8782-2500-2540-2540-p-42480-iso8859-1 +9nb00067.pmf -compugraphic-garamond-bold-i-normal--8782-2500-2540-2540-p-37020-iso8859-1 +9nb00075.pmf -compugraphic-omega-bold-i-normal--8782-2500-2540-2540-p-38560-iso8859-1 +9nb00056.pmf -monotype-arial-bold-r-normal--2048-2500-589-589-p-9800-iso8859-1 +9nb00060.pmf -compugraphic-clarendon-bold-r-condensed--8782-2500-2540-2540-p-35080-iso8859-1 +9nb00072.pmf -compugraphic-marigold-medium-r-normal--8782-2500-2540-2540-p-21890-iso8859-1 +9nb00057.pmf -monotype-arial-medium-i-normal--2048-2500-589-589-p-9040-iso8859-1 +9nb00061.pmf -compugraphic-courier-bold-r-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00073.pmf -compugraphic-omega-bold-r-normal--8782-2500-2540-2540-p-38600-iso8859-1 +9nb00054.pmf -compugraphic-antique olive-medium-i-normal--8782-2500-2540-2540-p-46140-iso8859-1 +9nb00062.pmf -compugraphic-courier-medium-i-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00070.pmf -compugraphic-letter gothic-medium-i-normal--8782-2500-2540-2540-m-44090-iso8859-1 +9nb00055.pmf -compugraphic-antique olive-medium-r-normal--8782-2500-2540-2540-p-46380-iso8859-1 +9nb00063.pmf -compugraphic-courier-bold-i-normal--8782-2500-2540-2540-m-52910-iso8859-1 +9nb00071.pmf -compugraphic-letter gothic-medium-r-normal--8782-2500-2540-2540-m-44090-iso8859-1 diff --git a/XpConfig/C/print/models/HPLJ4family/fonts/lpr0ye1a.pmf b/XpConfig/C/print/models/HPLJ4family/fonts/lpr0ye1a.pmf new file mode 100644 index 000000000..483748893 Binary files /dev/null and b/XpConfig/C/print/models/HPLJ4family/fonts/lpr0ye1a.pmf differ diff --git a/XpConfig/C/print/models/HPLJ4family/model-config b/XpConfig/C/print/models/HPLJ4family/model-config new file mode 100644 index 000000000..f69e25718 --- /dev/null +++ b/XpConfig/C/print/models/HPLJ4family/model-config @@ -0,0 +1,44 @@ +# $Xorg: model-config,v 1.3 2000/08/17 19:48:04 cpqbld Exp $ +# This is the configuration file for the HP LaserJet 4 Printers. +# +# Though not a deliverable for the CDEnext SI, the XP-PCL-MONO +# driver should be able to support the LaserJet 4 printers. +# +# Attribute IDs must be qualified using either the printer-model +# identifier or an asterisk ('*'). For example, if "HPLJ4family" is the +# printer-model, then to initialize the 'plexes-supported' attribute +# to 'simplex', use: "HPLJ4family.plexes-supported: simplex". For the +# asterisk, use: "*.plexes-supported: simplex". If the same attribute +# is specified using each method, the printer-model qualified entry +# takes precedence. + +HPLJ4family.printer-model: "Hewlett-Packard LaserJet 4 Series" +HPLJ4family.printer-resolutions-supported: 300 600 +HPLJ4family.content-orientations-supported: portrait landscape +HPLJ4family.document-formats-supported: {PCL 5} {PostScript 2} +HPLJ4family.plexes-supported: simplex duplex +HPLJ4family.xp-ddx-identifier: XP-PCL-MONO +HPLJ4family.xp-embedded-formats-supported: { PCL 5 } { PostScript 2 } +HPLJ4family.xp-setup-proviso: setup-optional + +# 1/4" unprintable margins +HPLJ4family.medium-source-sizes-supported:\ +{ '' \ + {na-letter FALSE {6.35 209.55 6.35 273.05}}\ + {executive FALSE {6.35 177.75 6.35 260.35}}\ + {na-legal FALSE {6.35 209.55 6.35 349.25}}\ + {iso-a3 FALSE {6.35 290.65 6.35 413.35}}\ + {iso-a4 FALSE {6.35 203.65 6.35 290.65}}\ + {jis-b4 FALSE {6.35 251.65 6.35 367.65}}\ + {jis-b5 FALSE {6.35 175.65 6.35 250.65}}\ + {monarch-envelope FALSE {6.35 91.94 6.35 184.15}}\ + {iso-designated-long FALSE {6.35 103.65 6.35 213.65}}\ + {iso-c5 FALSE {6.35 155.65 6.35 222.65}}\ + {na-number-10-envelope FALSE {6.35 98.45 6.35 234.95}}\ + {hp-tabloid FALSE {6.35 273.05 6.35 425.45}}\ + {ledger FALSE {6.35 273.05 6.35 425.45}}\ + {b FALSE {6.35 273.05 6.35 425.45}}\ + {hp-japanese-postcard FALSE {6 94 6 142 }}\ + {hp-japanese-doublepostcard FALSE {6 142 6 194 }}\ +} + diff --git a/XpConfig/C/print/models/SPSPARC2/model-config b/XpConfig/C/print/models/SPSPARC2/model-config new file mode 100644 index 000000000..959e9ff7b --- /dev/null +++ b/XpConfig/C/print/models/SPSPARC2/model-config @@ -0,0 +1,13 @@ +# $Xorg: model-config,v 1.3 2000/08/17 19:48:04 cpqbld Exp $ +SPSPARC2.printer-model: "SunPics SPARCprinter II" +SPSPARC2.printer-resolutions-supported: 300 +SPSPARC2.content-orientations-supported: portrait landscape +SPSPARC2.document-formats-supported: {PostScript 2} +SPSPARC2.plexes-supported: simplex +SPSPARC2.xp-ddx-identifier: XP-POSTSCRIPT +SPSPARC2.xp-embedded-formats-supported: { PostScript 2 } +*xp-setup-proviso: setup-optional +SPSPARC2.medium-source-sizes-supported: \ + { '' {na-letter FALSE {6.35 209.55 6.35 273.05}} \ + {na-legal FALSE {6.35 209.55 6.35 349.25}} \ + {iso-a4 FALSE {6.35 203.65 6.35 290.65}}} diff --git a/Xprint/AttrValid.c b/Xprint/AttrValid.c new file mode 100644 index 000000000..1303701af --- /dev/null +++ b/Xprint/AttrValid.c @@ -0,0 +1,702 @@ +/* $Xorg: AttrValid.c,v 1.4 2001/03/14 18:43:17 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +#include + +#define _XP_PRINT_SERVER_ +#include "extensions/Printstr.h" +#undef _XP_PRINT_SERVER_ + +#include "AttrValid.h" + +/* + * default medium-source-sizes supported = na-letter w/.25" margins + */ +static XpOidMediumDiscreteSize DefaultMediumSize = { + xpoid_val_medium_size_na_letter, xFalse, {6.35, 209.55, 6.35, 273.05} +}; +static XpOidMediumDiscreteSizeList DefaultMediumSizeList = { + &DefaultMediumSize, 1 +}; +static XpOidMediumSourceSize DefaultMediumSourceSize = { + xpoid_unspecified, XpOidMediumSS_DISCRETE, &DefaultMediumSizeList +}; +static XpOidMediumSS DefaultMediumSS = { + &DefaultMediumSourceSize, 1 +}; + +/* + * if 'valid_oid_list' is NULL any oid found is considered valid + */ +XpOid +XpGetOidAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oid_list) +{ + XpOid value_oid; + + value_oid = XpOidFromString(XpGetStringAttr(pContext, pool, oid)); + if((const XpOidList*)NULL == valid_oid_list + || + XpOidListHasOid(valid_oid_list, value_oid)) + { + return value_oid; + } + else + { + return xpoid_none; + } +} + +void +XpPutOidAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + XpOid value_oid) +{ + XpPutStringAttr(pContext, pool, oid, XpOidString(value_oid)); +} + +void +XpValidateOidAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oids, + XpOid default_oid) +{ + XpOid value_oid; + value_oid = XpGetOidAttr(pContext, pool, oid, valid_oids); + XpPutOidAttr(pContext, pool, oid, + value_oid == xpoid_none ? default_oid : value_oid); +} + +/* + * if 'valid_card_list' is NULL any cardinal found is considered valid + */ +unsigned long +XpGetCardAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_card_list) +{ + unsigned long value_card; + + if(XpOidParseUnsignedValue(XpGetStringAttr(pContext, pool, oid), + (const char**)NULL, + &value_card)) + { + if((const XpOidCardList*)NULL == valid_card_list + || + XpOidCardListHasCard(valid_card_list, value_card)) + { + return value_card; + } + } + return 0; +} + +void +XpPutCardAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + unsigned long value_card) +{ + if(value_card > 0) + { + char value_out[16]; + sprintf(value_out, "%lu", value_card); + XpPutStringAttr(pContext, pool, oid, value_out); + } + else + XpPutStringAttr(pContext, pool, oid, (const char*)NULL); +} + +void +XpValidateCardAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_cards, + unsigned long default_card) +{ + unsigned long value_card; + value_card = XpGetCardAttr(pContext, pool, oid, valid_cards); + XpPutCardAttr(pContext, pool, oid, + value_card == 0 ? default_card : value_card); +} + +XpOidList* +XpGetListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oid_list) +{ + return XpOidListNew(XpGetStringAttr(pContext, pool, oid), valid_oid_list); +} + +void +XpPutListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* list) +{ + char* value_out; + + value_out = XpOidListString(list); + XpPutStringAttr(pContext, pool, oid, value_out); + XpOidFree(value_out); +} + +void +XpValidateListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oids, + const XpOidList* default_oids) +{ + XpOidList* list = XpGetListAttr(pContext, pool, oid, valid_oids); + if(XpOidListCount(list) == 0) + XpPutListAttr(pContext, pool, oid, default_oids); + else + XpPutListAttr(pContext, pool, oid, list); + XpOidListDelete(list); +} + +XpOidCardList* +XpGetCardListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_card_list) +{ + return XpOidCardListNew(XpGetStringAttr(pContext, pool, oid), + valid_card_list); +} + +void +XpPutCardListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* list) +{ + char* value_out; + + value_out = XpOidCardListString(list); + XpPutStringAttr(pContext, pool, oid, value_out); + XpOidFree(value_out); +} + +void +XpValidateCardListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_cards, + const XpOidCardList* default_cards) +{ + XpOidCardList* list = XpGetCardListAttr(pContext, pool, oid, valid_cards); + if(XpOidCardListCount(list) == 0 && (XpOidCardList*)NULL != default_cards) + XpPutCardListAttr(pContext, pool, oid, default_cards); + else + XpPutCardListAttr(pContext, pool, oid, list); + XpOidCardListDelete(list); +} + +XpOidDocFmtList* +XpGetDocFmtListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidDocFmtList* valid_fmt_list) +{ + return XpOidDocFmtListNew(XpGetStringAttr(pContext, pool, oid), + valid_fmt_list); +} + +void +XpPutDocFmtListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidDocFmtList* list) +{ + char* value_out; + + value_out = XpOidDocFmtListString(list); + XpPutStringAttr(pContext, pool, oid, value_out); + XpOidFree(value_out); +} + +void +XpValidateDocFmtListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidDocFmtList* valid_fmts, + const XpOidDocFmtList* default_fmts) +{ + XpOidDocFmtList* list; + + list = XpGetDocFmtListAttr(pContext, pool, oid, valid_fmts); + if(XpOidDocFmtListCount(list) == 0 + && + (XpOidDocFmtList*)NULL != default_fmts) + { + XpPutDocFmtListAttr(pContext, pool, oid, default_fmts); + } + else + { + XpPutDocFmtListAttr(pContext, pool, oid, list); + } + XpOidDocFmtListDelete(list); +} + +XpOidMediumSS* +XpGetMediumSSAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_trays, + const XpOidList* valid_sizes) +{ + return XpOidMediumSSNew(XpGetStringAttr(pContext, pool, oid), + valid_trays, valid_sizes); +} + +void +XpPutMediumSSAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidMediumSS* msss) +{ + char* value_out; + + value_out = XpOidMediumSSString(msss); + XpPutStringAttr(pContext, pool, oid, value_out); + XpOidFree(value_out); +} + +const XpOidMediumSS* +XpGetDefaultMediumSS() +{ + return &DefaultMediumSS; +} + +XpOidTrayMediumList* +XpGetTrayMediumListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_trays, + const XpOidMediumSS* msss) +{ + return XpOidTrayMediumListNew(XpGetStringAttr(pContext, pool, oid), + valid_trays, msss); +} + +void +XpPutTrayMediumListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidTrayMediumList* tm) +{ + char* value_out; + + value_out = XpOidTrayMediumListString(tm); + XpPutStringAttr(pContext, pool, oid, value_out); + XpOidFree(value_out); +} + +void +XpValidatePrinterMediaAttrs(XpContextPtr pContext, + const XpOidList* valid_trays, + const XpOidList* valid_sizes) +{ + const XpOidMediumSS* msss; + XpOidMediumSS* pool_msss; + XpOidTrayMediumList* tm; + + pool_msss = XpGetMediumSSAttr(pContext, XPPrinterAttr, + xpoid_att_medium_source_sizes_supported, + valid_trays, valid_sizes); + if(0 == XpOidMediumSSCount(pool_msss)) + msss = XpGetDefaultMediumSS(); + else + msss = pool_msss; + XpPutMediumSSAttr(pContext, XPPrinterAttr, + xpoid_att_medium_source_sizes_supported, msss); + + tm = XpGetTrayMediumListAttr(pContext, XPPrinterAttr, + xpoid_att_input_trays_medium, + valid_trays, msss); + XpPutTrayMediumListAttr(pContext, XPPrinterAttr, + xpoid_att_input_trays_medium, tm); + + XpOidMediumSSDelete(pool_msss); + XpOidTrayMediumListDelete(tm); +} + + +void +XpValidatePrinterPool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr) +{ + /* + * content-orientations-supported + */ + XpValidateListAttr(pContext, XPPrinterAttr, + xpoid_att_content_orientations_supported, + vpr->valid_content_orientations_supported, + vpr->default_content_orientations_supported); + /* + * document-formats-supported + */ + XpValidateDocFmtListAttr(pContext, XPPrinterAttr, + xpoid_att_document_formats_supported, + vpr->valid_document_formats_supported, + vpr->default_document_formats_supported); + /* + * plexes-supported + */ + XpValidateListAttr(pContext, XPPrinterAttr, xpoid_att_plexes_supported, + vpr->valid_plexes_supported, + vpr->default_plexes_supported); + /* + * printer-resolutions-supported + */ + XpValidateCardListAttr(pContext, XPPrinterAttr, + xpoid_att_printer_resolutions_supported, + vpr->valid_printer_resolutions_supported, + vpr->default_printer_resolutions_supported); + /* + * xp-embedded-formats-supported + */ + XpValidateDocFmtListAttr(pContext, XPPrinterAttr, + xpoid_att_xp_embedded_formats_supported, + vpr->valid_xp_embedded_formats_supported, + vpr->default_xp_embedded_formats_supported); + /* + * xp-listfonts-modes-supported + */ + XpValidateListAttr(pContext, XPPrinterAttr, + xpoid_att_xp_listfonts_modes_supported, + vpr->valid_xp_listfonts_modes_supported, + vpr->default_xp_listfonts_modes_supported); + /* + * xp-raw-formats-supported + */ + XpValidateDocFmtListAttr(pContext, XPPrinterAttr, + xpoid_att_xp_raw_formats_supported, + vpr->valid_xp_raw_formats_supported, + vpr->default_xp_raw_formats_supported); + /* + * xp-setup-proviso + */ + XpValidateOidAttr(pContext, XPPrinterAttr, xpoid_att_xp_setup_proviso, + vpr->valid_xp_setup_proviso, xpoid_none); + /* + * medium-source-sizes-supported + * input-trays-mdeium + */ + XpValidatePrinterMediaAttrs(pContext, + vpr->valid_input_trays, + vpr->valid_medium_sizes); + /* + * available-compressions-supported + */ + XpValidateListAttr(pContext, XPPrinterAttr, + xpoid_att_available_compressions_supported, + vpr->valid_available_compressions_supported, + vpr->default_available_compressions_supported); +} + + +void +XpValidateNotificationProfile(XpContextPtr pContext) +{ + const char* value_in; + const char* value_out; + + value_in = XpGetStringAttr(pContext, XPJobAttr, + xpoid_att_notification_profile); + value_out = XpOidNotifyString(XpOidNotifyParse(value_in)); + XpPutStringAttr(pContext, XPJobAttr, + xpoid_att_notification_profile, value_out); +} + +void +XpValidateJobPool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr) +{ + /* + * Note: the 'vpr' argument is unused in this + * implementation; it is reserved for future use + */ + XpOidList* job_attrs_supported; + /* + * only validate attributes found in job-attributes-supported + */ + job_attrs_supported = XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_job_attributes_supported, + (const XpOidList*)NULL); + /* + * notification-profile + */ + if(XpOidListHasOid(job_attrs_supported, xpoid_att_notification_profile)) + { + XpValidateNotificationProfile(pContext); + } + /* + * clean up + */ + XpOidListDelete(job_attrs_supported); +} + + +static void +XpValidateDocOrPagePool(XpContextPtr pContext, + XPAttributes pool, /* XPDocAttr or XPPageAttr */ + const XpOidList* attrs_supported, + const XpValidatePoolsRec* vpr) +{ + /* + * content-orientation + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_content_orientation)) + { + XpOidList* content_orientations_supported; + content_orientations_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_content_orientations_supported, + vpr->valid_content_orientations_supported); + XpValidateOidAttr(pContext, pool, xpoid_att_content_orientation, + content_orientations_supported, xpoid_none); + XpOidListDelete(content_orientations_supported); + } + /* + * copy-count + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_copy_count)) + XpValidateCardAttr(pContext, pool, xpoid_att_copy_count, + (const XpOidCardList*)NULL, 0); + /* + * default-printer-resolution + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_default_printer_resolution)) + { + XpOidCardList* printer_resolutions_supported; + printer_resolutions_supported = + XpGetCardListAttr(pContext, XPPrinterAttr, + xpoid_att_printer_resolutions_supported, + vpr->valid_printer_resolutions_supported); + XpValidateCardAttr(pContext, pool, + xpoid_att_default_printer_resolution, + printer_resolutions_supported, 0); + XpOidCardListDelete(printer_resolutions_supported); + } + /* + * default-input-tray + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_default_input_tray)) + { + XpOidTrayMediumList* input_trays_medium; + const char* value_in; + XpOid value_tray; + + input_trays_medium = + XpGetTrayMediumListAttr(pContext, XPPrinterAttr, + xpoid_att_input_trays_medium, + (const XpOidList*)NULL, + (const XpOidMediumSS*)NULL); + value_in = + XpGetStringAttr(pContext, pool, xpoid_att_default_input_tray); + value_tray = XpOidFromString(value_in); + if(!XpOidTrayMediumListHasTray(input_trays_medium, value_tray)) + value_tray = xpoid_none; + XpPutOidAttr(pContext, pool, xpoid_att_default_input_tray, value_tray); + XpOidTrayMediumListDelete(input_trays_medium); + } + /* + * default-medium + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_default_medium)) + { + XpOidMediumSS* msss; + const char* value_in; + XpOid value_size; + + msss = XpGetMediumSSAttr(pContext, XPPrinterAttr, + xpoid_att_medium_source_sizes_supported, + (const XpOidList*)NULL, + (const XpOidList*)NULL); + value_in = XpGetStringAttr(pContext, pool, xpoid_att_default_medium); + value_size = XpOidFromString(value_in); + if(!XpOidMediumSSHasSize(msss, value_size)) + value_size = xpoid_none; + XpPutOidAttr(pContext, pool, xpoid_att_default_medium, value_size); + XpOidMediumSSDelete(msss); + } + /* + * document-format + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_document_format)) + { + XpOidDocFmtList* document_formats_supported; + const char* value_in; + XpOidDocFmt* document_format; + const char* value_out; + + document_formats_supported = + XpGetDocFmtListAttr(pContext, XPPrinterAttr, + xpoid_att_document_formats_supported, + vpr->valid_document_formats_supported); + value_in = XpGetStringAttr(pContext, pool, xpoid_att_document_format); + document_format = XpOidDocFmtNew(value_in); + if(XpOidDocFmtListHasFmt(document_formats_supported, document_format)) + value_out = XpOidDocFmtString(document_format); + else + value_out = XpOidDocFmtString(vpr->default_document_format); + XpOidDocFmtListDelete(document_formats_supported); + XpOidDocFmtDelete(document_format); + XpPutStringAttr(pContext, pool, xpoid_att_document_format, value_out); + XpOidFree(value_out); + } + /* + * plex + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_plex)) + { + XpOidList* plexes_supported; + plexes_supported = + XpGetListAttr(pContext, XPPrinterAttr, xpoid_att_plexes_supported, + vpr->valid_plexes_supported); + XpValidateOidAttr(pContext, pool, xpoid_att_plex, + plexes_supported, xpoid_none); + XpOidListDelete(plexes_supported); + } + /* + * xp-listfonts-modes + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_xp_listfonts_modes)) + { + XpOidList* xp_listfonts_modes_supported; + xp_listfonts_modes_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_xp_listfonts_modes_supported, + vpr->valid_xp_listfonts_modes_supported); + XpValidateListAttr(pContext, pool, xpoid_att_xp_listfonts_modes, + xp_listfonts_modes_supported, + (const XpOidList*)NULL); + XpOidListDelete(xp_listfonts_modes_supported); + } + /* + * available-compressions + */ + if(XpOidListHasOid(attrs_supported, xpoid_att_available_compression)) + { + XpOidList* available_compressions_supported; + available_compressions_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_available_compressions_supported, + vpr->valid_available_compressions_supported); + XpValidateOidAttr(pContext, pool, xpoid_att_available_compression, + available_compressions_supported, xpoid_none); + XpOidListDelete(available_compressions_supported); + } +} + +void +XpValidateDocumentPool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr) +{ + XpOidList* document_attrs_supported; + /* + * only validate attributes found in document-attributes-supported + */ + document_attrs_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_document_attributes_supported, + (const XpOidList*)NULL); + /* + * validate + */ + XpValidateDocOrPagePool(pContext, XPDocAttr, + document_attrs_supported, vpr); + /* + * clean up + */ + XpOidListDelete(document_attrs_supported); +} + +void +XpValidatePagePool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr) +{ + XpOidList* page_attrs_supported; + /* + * only validate attributes found in xp-page-attributes-supported + */ + page_attrs_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_xp_page_attributes_supported, + (const XpOidList*)NULL); + /* + * validate + */ + XpValidateDocOrPagePool(pContext, XPPageAttr, + page_attrs_supported, vpr); + /* + * clean up + */ + XpOidListDelete(page_attrs_supported); +} + +void +XpValidateAttributePool(XpContextPtr pContext, + XPAttributes pool, + const XpValidatePoolsRec* vpr) +{ + switch(pool) + { + case XPPrinterAttr: + XpValidatePrinterPool(pContext, vpr); + break; + + case XPDocAttr: + XpValidateDocumentPool(pContext, vpr); + break; + + case XPJobAttr: + XpValidateJobPool(pContext, vpr); + break; + + case XPPageAttr: + XpValidatePagePool(pContext, vpr); + break; + + default: + break; + } +} diff --git a/Xprint/AttrValid.h b/Xprint/AttrValid.h new file mode 100644 index 000000000..dab3c2def --- /dev/null +++ b/Xprint/AttrValid.h @@ -0,0 +1,208 @@ +/* $Xorg: AttrValid.h,v 1.4 2001/03/14 18:43:40 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#ifndef _Xp_AttrValid_h +#define _Xp_AttrValid_h + +#include "Oid.h" +#include "attributes.h" + +#define XpNumber(a) (sizeof(a) / sizeof(*(a))) + +/* + * Attribute pool validation valid values and defaults + */ +typedef struct +{ + XpOidList* valid_content_orientations_supported; + XpOidList* default_content_orientations_supported; + + XpOidDocFmtList* valid_document_formats_supported; + XpOidDocFmtList* default_document_formats_supported; + + XpOidList* valid_input_trays; + XpOidList* valid_medium_sizes; + + XpOidList* valid_plexes_supported; + XpOidList* default_plexes_supported; + + XpOidCardList* valid_printer_resolutions_supported; + XpOidCardList* default_printer_resolutions_supported; + + XpOidDocFmtList* valid_xp_embedded_formats_supported; + XpOidDocFmtList* default_xp_embedded_formats_supported; + + XpOidList* valid_xp_listfonts_modes_supported; + XpOidList* default_xp_listfonts_modes_supported; + + XpOidDocFmtList* valid_xp_raw_formats_supported; + XpOidDocFmtList* default_xp_raw_formats_supported; + + XpOidList* valid_xp_setup_proviso; + + XpOidDocFmt* default_document_format; + XpOidList* valid_available_compressions_supported; + XpOidList* default_available_compressions_supported; + +} XpValidatePoolsRec; + +/* + * XpOid resource access + */ +#define XpGetStringAttr(pContext, pool, oid) \ + (const char*)XpGetOneAttribute(pContext, pool, (char*)XpOidString(oid)) +#define XpPutStringAttr(pContext, pool, oid, value) \ + XpPutOneAttribute(pContext, pool, XpOidString(oid), value) +/* + * XpOid-valued attribute access + */ +XpOid XpGetOidAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oid_list); +void XpPutOidAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + XpOid value_oid); +void XpValidateOidAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oids, + XpOid default_oid); +/* + * cardinal-valued attribute access + */ +unsigned long XpGetCardAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_card_list); +void XpPutCardAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + unsigned long value_card); +void XpValidateCardAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_cards, + unsigned long default_card); +/* + * XpOidList-valued attribute access + */ +XpOidList* XpGetListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oid_list); +void XpPutListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* list); +void XpValidateListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_oids, + const XpOidList* default_oids); +/* + * XpOidCardList-valued attribute access + */ +XpOidCardList* XpGetCardListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_card_list); +void XpPutCardListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* list); +void XpValidateCardListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidCardList* valid_cards, + const XpOidCardList* default_cards); +/* + * XpOidDocFmtList-valued attribute access + */ +XpOidDocFmtList* XpGetDocFmtListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidDocFmtList* valid_fmt_list); +void XpPutDocFmtListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidDocFmtList* list); +void XpValidateDocFmtListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidDocFmtList* valid_fmts, + const XpOidDocFmtList* default_fmts); +/* + * XpOidMediumSS-valued attribute access + */ +XpOidMediumSS* XpGetMediumSSAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_trays, + const XpOidList* valid_sizes); +void XpPutMediumSSAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidMediumSS* msss); +const XpOidMediumSS* XpGetDefaultMediumSS(); + +/* + * XpOidTrayMediumList-valued attribute access + */ +XpOidTrayMediumList* XpGetTrayMediumListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidList* valid_trays, + const XpOidMediumSS* msss); +void XpPutTrayMediumListAttr(XpContextPtr pContext, + XPAttributes pool, + XpOid oid, + const XpOidTrayMediumList* tm); +/* + * Attribute pool validation + */ +void XpValidateAttributePool(XpContextPtr pContext, + XPAttributes pool, + const XpValidatePoolsRec* vpr); +void XpValidatePrinterPool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr); +void XpValidateJobPool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr); +void XpValidateDocumentPool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr); +void XpValidatePagePool(XpContextPtr pContext, + const XpValidatePoolsRec* vpr); + + +#endif /* _Xp_AttrValid_h - don't add anything after this line */ diff --git a/Xprint/DiPrint.h b/Xprint/DiPrint.h new file mode 100644 index 000000000..a4b969141 --- /dev/null +++ b/Xprint/DiPrint.h @@ -0,0 +1,54 @@ +/* $Xorg: DiPrint.h,v 1.3 2000/08/17 19:48:04 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/* + * The XpDiListEntry struct is the type of each element of the array + * handed back to the extension code to handle a GetPrinterList request. + * We don't use the printerDb directly because of the desire to handle + * multiple locales. Creating this new array for each GetPrinterList + * request will allow us to build it with the description in the locale of + * the requesting client. + */ +typedef struct _diListEntry { + char *name; + char *description; + char *localeName; + unsigned long rootWinId; +} XpDiListEntry; + +extern void XpDiFreePrinterList(XpDiListEntry **list); + +extern XpDiListEntry **XpDiGetPrinterList( + int nameLen, + char *name, + int localeLen, + char *locale); diff --git a/Xprint/Init.c b/Xprint/Init.c new file mode 100644 index 000000000..06757fa77 --- /dev/null +++ b/Xprint/Init.c @@ -0,0 +1,1805 @@ +/* $Xorg: Init.c,v 1.5 2001/03/07 17:31:33 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: printer/Init.c +** * +** * Contents: +** * The InitOutput routine here would presumably +** * be called from the normal server's InitOutput +** * after all display screens have been added. +** * There is are ifdef'd routines suitable for +** * use in building a printer-only server. Turn +** * on the "PRINTER_ONLY_SERVER" define if this is +** * to be the only ddx-level driver. +** * +** * Copyright: Copyright 1993,1995 Hewlett-Packard Company +** * +** ********************************************************* +** +********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __hpux +#include +#endif + +#include "X.h" +#define NEED_EVENTS 1 +#include "Xproto.h" +#include + +#include "screenint.h" +#include "input.h" +#include "cursor.h" +#include "misc.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "inputstr.h" + +#include "gcstruct.h" +#include "fonts/fontstruct.h" +#include "errno.h" + +#define _XP_PRINT_SERVER_ +#include "Printstr.h" +#undef _XP_PRINT_SERVER_ + +typedef char *XPointer; +#define Status int +#include + +#include "DiPrint.h" +#include "AttrValid.h" +#include "attributes.h" + +extern char *display; /* display number as a string */ + +#if 0 +/* extern char *Xalloc(); */ +extern void Xfree(); +/* extern char *Xrealloc(); */ +#else +#include "os.h" +#endif + +extern char *getenv(); +extern void XpAddPrinterAttribute(); +extern char *XpGetConfigDir(); +extern XpContextPtr XpContextOfClient(); + +/* +extern int GiveUp(); +*/ + +extern WindowPtr *WindowTable; /* declared in dix:globals.c */ + + +#if NeedFunctionPrototypes + +static void GetDriverFromPrinterName( + char *printerName, + char **driverName, + Bool (**initScreenFunc)()); +static void GenericScreenInit( + int index, + ScreenPtr pScreen, + int argc, + char **argv); +static Bool InitPrintDrivers( + int index, + ScreenPtr pScreen, + int argc, + char **argv); + +#else + +static void GetDriverFromPrinterName(); +static void GenericScreenInit(); +static Bool InitPrintDrivers(); + +#endif + + +/* + * The following two defines are used to build the name "X*printers", where + * the "*" is replaced by the display number. This is used to construct + * the name of the default printers configuration file if the -XpFile + * command line option was not specified. + */ +#define XNPRINTERSFILEPREFIX "/X" +#define XNPRINTERSFILESUFFIX "printers" +#define XPRINTERSFILENAME "Xprinters" + +#define MODELDIRNAME "/models" +#define FONTDIRNAME "/fonts" + +/* + * The string LIST_QUEUES is fed to a shell to generate an ordered + * list of available printers on the system. These string definitions + * are taken from the file PrintSubSys.C within the code for the + * dtprintinfo program. + */ +#ifdef AIXV4 +const char *LIST_QUEUES = "lsallq | grep -v '^bsh$' | sort"; +#else +#ifdef hpux +const char *LIST_QUEUES = "LANG=C lpstat -v | " + "awk '" + " $2 == \"for\" " + " { " + " x = match($3, /:/); " + " print substr($3, 1, x-1)" + " }' | sort"; +#else +#ifdef __osf__ + const char *LIST_QUEUES = "LANG=C lpstat -v | " + "nawk '" + " $2 == \"for\" " + " { print $4 }' " + " | sort"; +#else +#ifdef __uxp__ +const char *LIST_QUEUES = "LANG=C lpstat -v | " + "nawk '" + " $4 == \"for\" " + " { " + " x = match($5, /:/); " + " print substr($5, 1, x-1)" + " }' | sort"; +#else +#if defined(CSRG_BASED) || defined(linux) +const char *LIST_QUEUES = "LANG=C lpc status | grep -v '^\t' | " + "sed -e /:/s/// | sort"; +#else +const char *LIST_QUEUES = "LANG=C lpstat -v | " + "nawk '" + " $2 == \"for\" " + " { " + " x = match($3, /:/); " + " print substr($3, 1, x-1)" + " }' | sort"; +#endif +#endif +#endif +#endif +#endif + +#ifdef XPRASTERDDX + +static +PixmapFormatRec RasterPixmapFormats[] = { + 1, 1, BITMAP_SCANLINE_PAD +}; +#define NUMRASTFORMATS (sizeof RasterPixmapFormats)/(sizeof RasterPixmapFormats[0]) + +extern Bool InitializeRasterDriver(); +extern XpValidatePoolsRec RasterValidatePoolsRec; /* From RasterAttVal.c */ + +#endif + +#ifdef XPPCLDDX + +static +PixmapFormatRec ColorPclPixmapFormats[] = { + 1, 1, BITMAP_SCANLINE_PAD, + 8, 8, BITMAP_SCANLINE_PAD, + 24,32, BITMAP_SCANLINE_PAD +}; + +#define NUMCPCLFORMATS (sizeof ColorPclPixmapFormats)/(sizeof ColorPclPixmapFormats[0]) + +extern Bool InitializeColorPclDriver(); +extern XpValidatePoolsRec PclValidatePoolsRec; + +#endif + +#ifdef XPMONOPCLDDX + +static +PixmapFormatRec MonoPclPixmapFormats[] = { + 1, 1, BITMAP_SCANLINE_PAD +}; + +#define NUMMPCLFORMATS (sizeof MonoPclPixmapFormats)/(sizeof MonoPclPixmapFormats[0]) + +extern Bool InitializeMonoPclDriver(); +extern XpValidatePoolsRec PclValidatePoolsRec; + +#endif + +#ifdef XPPSDDX + +static +PixmapFormatRec PSPixmapFormats[] = { + 1, 1, BITMAP_SCANLINE_PAD, + 8, 8, BITMAP_SCANLINE_PAD, + 24,32, BITMAP_SCANLINE_PAD +}; + +#define NUMPSFORMATS (sizeof PSPixmapFormats)/(sizeof PSPixmapFormats[0]) + +extern Bool InitializePsDriver(); +extern XpValidatePoolsRec PsValidatePoolsRec; + +#endif + + +typedef Bool (*pBFunc)(); +typedef void (*pVFunc)(); +/* + * The driverInitArray contains an entry for each driver the + * server knows about. Each element contains pointers to pixmap formats, the + * driver's initialization routine, and pointers to the driver's + * attribute validation rec, and/or a driver function which + * returns the maximum medium width&height, and maximum resolution + * given a printer name. Either the validation rec OR the dimension + * function can be NULL. If the function is non-NULL then it + * will be called, and will be passed the (possibly NULL) validation rec. + * If the function is NULL, then XpGetMaxWidthHeightRes() is called. + */ +typedef struct _driverInitRec { + char *driverName; + pBFunc initFunc; + XpValidatePoolsRec *pValRec; + pVFunc dimensionsFunc; + PixmapFormatRec *pFmts; + int numFmts; +} driverInitRec; + +static driverInitRec driverInits[] = { +#ifdef XPRASTERDDX + { + "XP-RASTER", + InitializeRasterDriver, + &RasterValidatePoolsRec, + (pVFunc) NULL, + RasterPixmapFormats, + NUMRASTFORMATS + }, +#endif +#ifdef XPPCLDDX + { + "XP-PCL-COLOR", + InitializeColorPclDriver, + &PclValidatePoolsRec, + (pVFunc) NULL, + ColorPclPixmapFormats, + NUMCPCLFORMATS + }, +#endif +#ifdef XPMONOPCLDDX + { + "XP-PCL-MONO", + InitializeMonoPclDriver, + &PclValidatePoolsRec, + (pVFunc) NULL, + MonoPclPixmapFormats, + NUMMPCLFORMATS + }, +#endif +#ifdef XPPSDDX + { + "XP-POSTSCRIPT", + InitializePsDriver, + &PsValidatePoolsRec, + (pVFunc) NULL, + PSPixmapFormats, + NUMPSFORMATS + }, +#endif +}; + + +/* + * The printerDb variable points to a list of PrinterDbEntry structs + * which map printer names with screen numbers and driver names. + */ +typedef struct _printerDbEntry { + struct _printerDbEntry *next; + char *name; + char *qualifier; + int screenNum; + char *driverName; +} PrinterDbEntry, *PrinterDbPtr; + +static PrinterDbPtr printerDb = (PrinterDbPtr)NULL; + +/* + * The nameMap is a list used in initializing the attribute store + * for each printer. The list is freed once the printerDb is built + * and the attribute stores for all printers have been initialized. + */ +typedef struct _nameMapEntry { + struct _nameMapEntry *next; + char *name; + char *qualifier; +} NameMapEntry, *NameMapPtr; + +static NameMapPtr nameMap = (NameMapPtr)NULL; + +/* + * The driverMap is a list which provides the mapping between driver names + * and screen numbers. It is built and used + * by RehashPrinterList to correctly fill in the screenNum field in the + * printerDb entries. The list is freed before RehashPrinterList terminates. + */ +typedef struct _driverMapping { + struct _driverMapping *next; + char *driverName; + int screenNum; +} DriverMapEntry, *DriverMapPtr; + +static const char configFilePath[] = +"/etc/dt/config/print:/usr/dt/config/print"; + +static const char printServerConfigDir[] = "XPSERVERCONFIGDIR"; + +static int printScreenPrivIndex, + printWindowPrivIndex, + printGCPrivIndex; +static unsigned long printGeneration = 0; +static char *configFileName = (char *)NULL; +static Bool freeDefaultFontPath = FALSE; +static char *origFontPath = (char *)NULL; + +/* + * XprintOptions checks argv[i] to see if it is our command line + * option specifying a configuration file name. It returns the index + * of the next option to process. + */ +int +XprintOptions(argc, argv, i) + int argc; + char **argv; + int i; +{ + extern void ddxUseMsg(); + if(strcmp(argv[i], "-XpFile") == 0) + { + if ((i + 1) >= argc) { + ddxUseMsg (); + return i + 2; + } + configFileName = argv[i + 1]; + return i + 2; + } + else + return i; +} + +/************************************************************ + * GetInitFunc -- + * + * This routine is called from the InitPrintDrivers function. + * Given the name of a driver, return a pointer to the driver's + * initialization function. + * + * Results: + * Returns a pointer to the initialization function for the driver. + * + * + ************************************************************/ + +/* +typedef Bool (*pIFunc)(); +static pIFunc +GetInitFunc(driverName) +*/ + +static Bool (* +GetInitFunc(driverName))() + char *driverName; +{ + driverInitRec *pInitRec; + int numDrivers = sizeof(driverInits)/sizeof(driverInitRec); + int i; + + for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++) + { + if( !strcmp( driverName, pInitRec->driverName ) ) + return pInitRec->initFunc; + } + + return (Bool(*)())NULL; +} + +static void +GetDimFuncAndRec( + char *driverName, + XpValidatePoolsRec **pValRec, + pVFunc *dimensionsFunc) +{ + driverInitRec *pInitRec; + int numDrivers = sizeof(driverInits)/sizeof(driverInitRec); + int i; + + for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++) + { + if( !strcmp( driverName, pInitRec->driverName ) ) + { + *dimensionsFunc = pInitRec->dimensionsFunc; + *pValRec = pInitRec->pValRec; + return ; + } + } + + *dimensionsFunc = (pVFunc)NULL; + *pValRec = (XpValidatePoolsRec *)NULL; + return; +} + +static void +FreePrinterDb() +{ + PrinterDbPtr pCurEntry, pNextEntry; + + for(pCurEntry = printerDb, pNextEntry = (PrinterDbPtr)NULL; + pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pNextEntry) + { + pNextEntry = pCurEntry->next; + if(pCurEntry->name != (char *)NULL) + xfree(pCurEntry->name); + /* + * We don't free the driver name, because it's expected to simply + * be a pointer into the xrm database. + */ + xfree(pCurEntry); + } + printerDb = (PrinterDbPtr)NULL; +} + +/* + * AddPrinterDbName allocates an entry in the printerDb list, and + * initializes the "name". It returns TRUE if the element was + * successfully added, and FALSE if an allocation error ocurred. + * XXX AddPrinterDbName needs to check for (and not add) duplicate names. + */ +static Bool +AddPrinterDbName(name) + char *name; +{ + PrinterDbPtr pEntry = (PrinterDbPtr)xalloc(sizeof(PrinterDbEntry)); + + if(pEntry == (PrinterDbPtr)NULL) return FALSE; + pEntry->name = strdup(name); + pEntry->qualifier = (char *)NULL; + + if(printerDb == (PrinterDbPtr)NULL) + { + pEntry->next = (PrinterDbPtr)NULL; + printerDb = pEntry; + } + else + { + pEntry->next = printerDb; + printerDb = pEntry; + } + return TRUE; +} + +static void +AugmentPrinterDb(command) + char *command; +{ + FILE *fp; + char name[256]; + + fp = popen(command, "r"); + /* XXX is a 256 character limit overly restrictive for printer names? */ + while(fgets(name, 256, fp) != (char *)NULL && strlen(name)) + { + name[strlen(name) - 1] = (char)'\0'; /* strip the \n */ + AddPrinterDbName(name); + } + pclose(fp); +} + +/* + * FreeNameMap frees all remaining memory associated with the nameMap. + */ +static void +FreeNameMap() +{ + NameMapPtr pEntry, pTmp; + + for(pEntry = nameMap, pTmp = (NameMapPtr)NULL; + pEntry != (NameMapPtr)NULL; + pEntry = pTmp) + { + if(pEntry->name != (char *)NULL) + xfree(pEntry->name); + if(pEntry->qualifier != (char *)NULL) + xfree(pEntry->qualifier); + pTmp = pEntry->next; + xfree(pEntry); + } + nameMap = (NameMapPtr)NULL; +} + +/* + * AddNameMap adds an element to the nameMap linked list. + */ +static Bool +AddNameMap(name, qualifier) + char *name; + char *qualifier; +{ + NameMapPtr pEntry; + + if((pEntry = (NameMapPtr)xalloc(sizeof(NameMapEntry))) == (NameMapPtr)NULL) + return FALSE; + pEntry->name = name; + pEntry->qualifier = qualifier; + pEntry->next = nameMap; + nameMap = pEntry; + return TRUE; +} + +/* + * MergeNameMap - puts the "map" names (aka qualifiers, aliases) into + * the printerDb. This should be called once, after both the printerDb + * and nameMap lists are complete. When/if MergeNameMap finds a map for + * an entry in the printerDb, the qualifier is _moved_ (not copied) to + * the printerDb. This means that the qualifier pointer in the nameMap + * is NULLed out. + */ +static void +MergeNameMap() +{ + NameMapPtr pMap; + PrinterDbPtr pDb; + + for(pMap = nameMap; pMap != (NameMapPtr)NULL; pMap = pMap->next) + { + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(!strcmp(pMap->name, pDb->name)) + { + pDb->qualifier = pMap->qualifier; + pMap->qualifier = (char *)NULL; + } + } + } +} + +/* + * CreatePrinterAttrs causes the attribute stores to be built for + * each printer in the printerDb. + */ +static void +CreatePrinterAttrs() +{ + PrinterDbPtr pDb; + + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + XpBuildAttributeStore(pDb->name, (pDb->qualifier)? + pDb->qualifier : pDb->name); + } +} + +#ifdef XPPSDDX +#define defaultDriver "XP-POSTSCRIPT" +#else +#ifdef XPPCLDDX +#define defaultDriver "XP-PCL-COLOR" +#else +#ifdef XPMONOPCLDDX +#define defaultDriver "XP-PCL-MONO" +#else +#define defaultDriver "XP-RASTER" +#endif +#endif +#endif + +/* + * StoreDriverNames - queries the attribute store for the ddx-identifier. + * if the ddx-identifier is not in the attribute database, then a default + * ddx-identifier is store in both the attribute store for the printer, + * and in the printerDb. + * The ddx-identifier is stored in the printerDb for use in initializing + * the screens. + */ +static void +StoreDriverNames() +{ + PrinterDbPtr pEntry; + + for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; + pEntry = pEntry->next) + { + pEntry->driverName = (char*)XpGetPrinterAttribute(pEntry->name, + "xp-ddx-identifier"); + if(pEntry->driverName == (char *)NULL || + strlen(pEntry->driverName) == 0 || + GetInitFunc(pEntry->driverName) == (Bool(*)())NULL) + { + if (pEntry->driverName && (strlen(pEntry->driverName) != 0)) { + ErrorF("Xp Extension: Can't load driver %s\n", + pEntry->driverName); + ErrorF(" init function missing\n"); + } + + pEntry->driverName = defaultDriver; + XpAddPrinterAttribute(pEntry->name, + (pEntry->qualifier != (char *)NULL)? + pEntry->qualifier : pEntry->name, + "*xp-ddx-identifier", pEntry->driverName); + } + } +} + +char * +MbStrchr( + char *str, + int ch) +{ + size_t mbCurMax = MB_CUR_MAX; + wchar_t targetChar, curChar; + char tmpChar; + int i, numBytes, byteLen; + + if(mbCurMax <= 1) return strchr(str, ch); + + tmpChar = (char)ch; + mbtowc(&targetChar, &tmpChar, mbCurMax); + for(i = 0, numBytes = 0, byteLen = strlen(str); i < byteLen; i += numBytes) + { + numBytes = mbtowc(&curChar, &str[i], mbCurMax); + if(curChar == targetChar) return &str[i]; + } + return (char *)NULL; +} + +/* + * GetConfigFileName - Looks for a "Xprinters" file in + * $(XPRINTDIR)/$LANG/print, and then in $(XPRINTDIR)/C/print. If it + * finds such a file, it returns the path to the file. The returned + * string must be freed by the caller. + */ +static char * +GetConfigFileName() +{ + /* + * We need to find the system-wide file, if one exists. This + * file can be in either $(XPRINTDIR)/$LANG/print, or in + * $(PRINTDIR)/C/print, and the file itself is named "Xprinters". + */ + char *dirName, *filePath; + + /* + * Check for a LANG-specific file. + */ + if(dirName = XpGetConfigDir(TRUE)) + { + filePath = (char *)xalloc(strlen(dirName) + + strlen(XPRINTERSFILENAME) + 2); + + if(filePath == (char *)NULL) + { + xfree(dirName); + return (char *)NULL; + } + + sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME); + xfree(dirName); + if(access(filePath, R_OK) == 0) + return filePath; + + xfree(filePath); + } + + if(dirName = XpGetConfigDir(FALSE)) + { + filePath = (char *)xalloc(strlen(dirName) + + strlen(XPRINTERSFILENAME) + 2); + if(filePath == (char *)NULL) + { + xfree(dirName); + return (char *)NULL; + } + sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME); + xfree(dirName); + if(access(filePath, R_OK) == 0) + return filePath; + xfree(filePath); + } + return (char *)NULL; +} + +/* + * BuildPrinterDb - reads the config file if it exists, and if necessary + * executes a command such as lpstat to generate a list of printers. + * XXX + * XXX BuildPrinterDb must be rewritten to allow 16-bit characters in + * XXX printer names. The will involve replacing the use of strtok() and its + * XXX related functions. + * XXX At the same time, BuildPrinterDb and it's support routines should have + * XXX allocation error checking added. + * XXX + */ +static PrinterDbPtr +BuildPrinterDb() +{ + char *printerList, *augmentCmd = (char *)NULL; + Bool defaultAugment = TRUE, freeConfigFileName; + + if(configFileName && access(configFileName, R_OK) != 0) + { + ErrorF("Xp Extension: Can't open file %s\n", configFileName); + } + if(!configFileName && (configFileName = GetConfigFileName())) + freeConfigFileName = TRUE; + else + freeConfigFileName = FALSE; + + if(configFileName != (char *)NULL && access(configFileName, R_OK) == 0) + { + char line[256]; + FILE *fp = fopen(configFileName, "r"); + + while(fgets(line, 256, fp) != (char *)NULL) + { + char *tok, *ptr; + if((tok = strtok(line, " \t\012")) != (char *)NULL) + { + if(tok[0] == (char)'#') continue; + if(strcmp(tok, "Printer") == 0) + { + while((tok = strtok((char *)NULL, " \t")) != (char *)NULL) + { + if(ptr = MbStrchr(tok, '\012')) + *ptr = (char)'\0'; + AddPrinterDbName(tok); + } + } + else if(strcmp(tok, "Map") == 0) + { + char *name, *qualifier; + + if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL) + continue; + name = strdup(tok); + if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL) + { + xfree(name); + continue; + } + qualifier = strdup(tok); + AddNameMap(name, qualifier); + } + else if(strcmp(tok, "Augment_Printer_List") == 0) + { + if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL) + continue; + + if(strcmp(tok, "%default%") == 0) + continue; + defaultAugment = FALSE; + if(strcmp(tok, "%none%") == 0) + continue; + AugmentPrinterDb(tok); + } + else + break; /* XXX Generate an error? */ + } + } + fclose(fp); + } + + if(defaultAugment == TRUE) + { + AugmentPrinterDb(LIST_QUEUES); + } + + MergeNameMap(); + FreeNameMap(); + + /* Create the attribute stores for all printers */ + CreatePrinterAttrs(); + + /* + * Find the drivers for each printers, and store the driver names + * in the printerDb + */ + StoreDriverNames(); + + if(freeConfigFileName) + { + xfree(configFileName); + configFileName = (char *)NULL; + } + + return printerDb; +} + +static void +FreeDriverMap(driverMap) + DriverMapPtr driverMap; +{ + DriverMapPtr pCurEntry, pNextEntry; + + for(pCurEntry = driverMap, pNextEntry = (DriverMapPtr)NULL; + pCurEntry != (DriverMapPtr)NULL; pCurEntry = pNextEntry) + { + pNextEntry = pCurEntry->next; + if(pCurEntry->driverName != (char *)NULL) + xfree(pCurEntry->driverName); + xfree(pCurEntry); + } +} + +/* + * XpRehashPrinterList rebuilds the list of printers known to the + * server. It first walks the printerDb to build a table mapping + * driver names and screen numbers, since this is not an easy mapping + * to change in the sample server. The normal configuration files are + * then read & parsed to create the new list of printers. Printers + * which require drivers other than those already initialized are + * deleted from the printerDb. This leaves attribute stores in place + * for inaccessible printers, but those stores will be cleaned up in + * the next rehash or server recycle. + */ +int +XpRehashPrinterList() +{ + PrinterDbPtr pEntry, pPrev; + DriverMapPtr driverMap = (DriverMapPtr)NULL, pDrvEnt; + int result; + + /* Build driverMap */ + for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next) + { + for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL; + pDrvEnt = pDrvEnt->next) + { + if(!strcmp(pEntry->driverName, pDrvEnt->driverName)) + break; + } + + if(pDrvEnt != (DriverMapPtr)NULL) + continue; + + if((pDrvEnt = (DriverMapPtr)xalloc(sizeof(DriverMapEntry))) == + (DriverMapPtr)NULL) + { + FreeDriverMap(driverMap); + return BadAlloc; + } + pDrvEnt->driverName = strdup(pEntry->driverName); + pDrvEnt->screenNum = pEntry->screenNum; + pDrvEnt->next = driverMap; + driverMap = pDrvEnt; + } + + /* Free the old printerDb */ + FreePrinterDb(); + + /* Free/Rehash attribute stores */ + if((result = XpRehashAttributes()) != Success) + return result; + + /* Build a new printerDb */ + if(BuildPrinterDb() == (PrinterDbPtr)NULL) + return BadAlloc; + + /* Walk PrinterDb & either store screenNum, or delete printerDb entry */ + for(pEntry = printerDb, pPrev = (PrinterDbPtr)NULL; + pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next) + { + for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL; + pDrvEnt = pDrvEnt->next) + { + if(!strcmp(printerDb->driverName, pDrvEnt->driverName)) + break; + } + + /* + * Either store the screen number, or delete the printerDb entry. + * Deleting the entry leaves orphaned attribute stores, but they'll + * get cleaned up at the next rehash or server recycle. + */ + if(pDrvEnt != (DriverMapPtr)NULL) + { + pEntry->screenNum = pDrvEnt->screenNum; + pPrev = pEntry; + } + else { + if(pPrev) + pPrev->next = pEntry->next; + else + pPrev = pEntry->next; + if(pEntry->name != (char *)NULL) + xfree(pEntry->name); + xfree(pEntry); + pEntry = pPrev; + } + } + + FreeDriverMap(driverMap); + + return Success; +} + +/* + * ValidateFontDir looks for a valid font directory for the specified + * printer model within the specified configuration directory. It returns + * the directory name, or NULL if no valid font directory was found. + * It is the caller's responsibility to free the returned font directory + * name. + */ +static char * +ValidateFontDir( + char *configDir, + char *modelName) +{ + char *pathName; + + if(!configDir || !modelName) + return (char *)NULL; + + pathName = (char *)xalloc(strlen(configDir) + strlen(MODELDIRNAME) + + strlen(modelName) + strlen(FONTDIRNAME) + + strlen("fonts.dir") + 5); + if(!pathName) + return (char *)NULL; + sprintf(pathName, "%s/%s/%s/%s/%s", configDir, MODELDIRNAME, modelName, + FONTDIRNAME, "fonts.dir"); + if(access(pathName, R_OK) != 0) + { + xfree(pathName); + return (char *)NULL; + } + pathName[strlen(pathName) - 9] = (char)'\0'; /* erase fonts.dir */ + return pathName; +} + +/* + * FindFontDir returns a pointer to the path name of the font directory + * for the specified printer model name, if such a directory exists. + * The directory contents are superficially checked for validity. + * The caller must free the returned char *. + * + * We first look in the locale-specific model-config directory, and + * then fall back to the C language model-config directory. + */ +static char * +FindFontDir( + char *modelName) +{ + char *configDir, *fontDir; + + if(!modelName || !strlen(modelName)) + return (char *)NULL; + + configDir = XpGetConfigDir(TRUE); + if(fontDir = ValidateFontDir(configDir, modelName)) + { + xfree(configDir); + return fontDir; + } + + if(configDir) + xfree(configDir); + configDir = XpGetConfigDir(FALSE); + fontDir = ValidateFontDir(configDir, modelName); + + xfree(configDir); + + return fontDir; +} + +/* + * AddToFontPath adds the specified font path element to the global + * defaultFontPath string. It adds the keyword "PRINTER:" to the front + * of the path to denote that this is a printer-specific font path + * element. + */ +static char PATH_PREFIX[] = "PRINTER:"; +static int PATH_PREFIX_LEN = sizeof(PATH_PREFIX) - 1; /* same as strlen() */ + +static void +AddToFontPath( + char *pathName) +{ + char *newPath; + Bool freeOldPath; + + if(defaultFontPath == origFontPath) + freeOldPath = FALSE; + else + freeOldPath = TRUE; + + newPath = (char *)xalloc(strlen(defaultFontPath) + strlen(pathName) + + PATH_PREFIX_LEN + 2); + + sprintf(newPath, "%s%s,%s", PATH_PREFIX, pathName, defaultFontPath); + + if(freeOldPath) + xfree(defaultFontPath); + + defaultFontPath = newPath; + return; +} + +/* + * AugmentFontPath adds printer-model-specific font path elements to + * the front of the font path global variable "defaultFontPath" (dix/globals.c). + * We can't call SetFontPath() because the font code has not yet been + * initialized when InitOutput is called (from whence this routine is called). + * + * This utilizes the static variables origFontPath and + * freeDefaultFontPath to track the original contents of defaultFontPath, + * and to properly free the modified version upon server recycle. + */ +static void +AugmentFontPath() +{ + char *newPath, *modelID, **allIDs = (char **)NULL; + PrinterDbPtr pDb, pDbEntry; + int numModels, i; + + if(!origFontPath) + origFontPath = defaultFontPath; + + if(freeDefaultFontPath) + { + xfree(defaultFontPath); + defaultFontPath = origFontPath; + freeDefaultFontPath = FALSE; + } + + /* + * Build a list of printer models to check for internal fonts. + */ + for(pDbEntry = printerDb, numModels = 0; + pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next) + { + modelID = + (char*)XpGetPrinterAttribute(pDbEntry->name, + "xp-model-identifier"); + + if(modelID && strlen(modelID) != 0) + { + /* look for current model in the list of allIDs */ + for(i = 0; i < numModels; i++) + { + if(!strcmp(modelID, allIDs[i])) + { + modelID = (char *)NULL; + break; + } + } + } + + /* + * If this printer's model-identifier isn't in the allIDs list, + * then add it to allIDs. + */ + if(modelID && strlen(modelID) != 0) + { + allIDs = (char **)xrealloc(allIDs, (numModels+2) * sizeof(char *)); + if(allIDs == (char **)NULL) + return; + allIDs[numModels] = modelID; + allIDs[numModels + 1] = (char *)NULL; + numModels++; + } + } + + /* for each model, check for a valid font directory, and add it to + * the front of defaultFontPath. + */ + for(i = 0; allIDs != (char **)NULL && allIDs[i] != (char *)NULL; i ++) + { + char *fontDir; + if(fontDir = FindFontDir(allIDs[i])) + { + AddToFontPath(fontDir); + xfree(fontDir); + freeDefaultFontPath = TRUE; + } + } + + if(allIDs) + xfree(allIDs); + + return; +} + +/* + * XpClientIsBitmapClient is called by the font code to find out if + * a particular client should be granted access to bitmap fonts. + * This function works by + * calling XpContextOfClient (in Xserver/Xext/xprint.c) to determine + * the context associated with the client, and then queries the context's + * attributes to determine whether the bitmap fonts should be visible. + * It looks at the value of the xp-listfonts-mode document/page attribute to + * see if xp-list-glyph-fonts has been left out of the mode list. Only + * if the xp-listfonts-mode attribute exists, and it does not contain + * xp-list-glyph-fonts does this function return FALSE. In any other + * case the funtion returns TRUE, indicating that the bitmap fonts + * should be visible to the client. + */ +Bool +XpClientIsBitmapClient( + ClientPtr client) +{ + XpContextPtr pContext; + char *mode; + + if(!(pContext = XpContextOfClient(client))) + return TRUE; + + /* + * Check the page attributes, and if it's not defined there, then + * check the document attributes. + */ + mode = XpGetOneAttribute(pContext, XPPageAttr, "xp-listfonts-mode"); + if(!mode || !strlen(mode)) + { + mode = XpGetOneAttribute(pContext, XPDocAttr, "xp-listfonts-mode"); + if(!mode || !strlen(mode)) + return TRUE; + } + + if(!strstr(mode, "xp-list-glyph-fonts")) + return FALSE; + + return TRUE; +} +/* + * XpClientIsPrintClient is called by the font code to find out if + * a particular client has set a context which references a printer + * which utilizes a particular font path. This function works by + * calling XpContextOfClient (in Xserver/Xext/xprint.c) to determine + * the context associated with the client, and then looks up the + * font directory for the context. The font directory is then compared + * with the directory specified in the FontPathElement which is passed in. + */ +Bool +XpClientIsPrintClient( + ClientPtr client, + FontPathElementPtr fpe) +{ + XpContextPtr pContext; + char *modelID, *fontDir; + + if(!(pContext = XpContextOfClient(client))) + return FALSE; + + if (!fpe) + return TRUE; + + modelID = XpGetOneAttribute(pContext, XPPrinterAttr, "xp-model-identifier"); + if(!modelID || !strlen(modelID)) + return FALSE; + + if(!(fontDir = FindFontDir(modelID))) + return FALSE; + + /* + * The grunge here is to ignore the PATH_PREFIX at the front of the + * fpe->name. + */ + if(fpe->name_length < PATH_PREFIX_LEN || + (strlen(fontDir) != (fpe->name_length - PATH_PREFIX_LEN)) || + strncmp(fontDir, fpe->name + PATH_PREFIX_LEN, + fpe->name_length - PATH_PREFIX_LEN)) + { + xfree(fontDir); + return FALSE; + } + xfree(fontDir); + return TRUE; +} + +static void +AddFormats(pScreenInfo, driverName) + ScreenInfo *pScreenInfo; + char *driverName; +{ + int i, j; + driverInitRec *pInitRec; + int numDrivers = sizeof(driverInits)/sizeof(driverInitRec); + PixmapFormatRec *formats; + int numfmts; + + for (pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++) + { + if ( !strcmp( driverName, pInitRec->driverName ) ) + break; + } + if (i >= numDrivers) + return; + formats = pInitRec->pFmts; + numfmts = pInitRec->numFmts; + for (i = 0; i < numfmts && pScreenInfo->numPixmapFormats < MAXFORMATS; i++) + { + for (j = 0; j < pScreenInfo->numPixmapFormats; j++) { + if (pScreenInfo->formats[j].depth == formats[i].depth && + pScreenInfo->formats[j].bitsPerPixel == formats[i].bitsPerPixel && + pScreenInfo->formats[j].scanlinePad == formats[i].scanlinePad) + break; + } + if (j == pScreenInfo->numPixmapFormats) { + pScreenInfo->formats[j] = formats[i]; + pScreenInfo->numPixmapFormats++; + } + } +} + +/************************************************************ + * PrinterInitOutput -- + * This routine is to be called from a ddx's InitOutput + * during the server startup initialization, and when + * the server is to be reset. The routine creates the + * screens associated with configured printers by calling + * dix:AddScreen. The configuration information comes from a + * database read from the X*printers file. + * + * Results: + * The array of ScreenRec pointers referenced by + * pScreenInfo->screen is increased by the addition + * of the printer screen(s), as is the value of + * pScreenInfo->numScreens. This is done via calls + * to AddScreen() in dix. + * + ************************************************************/ + +void +PrinterInitOutput(pScreenInfo, argc, argv) + ScreenInfo *pScreenInfo; + int argc; + char **argv; +{ + PrinterDbPtr pDb, pDbEntry; + int driverCount = 0, i; + char **driverNames; + char *configDir; + + /* + * this little test is just a warning at startup to make sure + * that the config directory exists. + * + * what this ugly looking if says is that if both ways of + * calling configDir works and both directories don't exist, + * then print an error saying we can't find the non-lang one. + */ + if (((configDir = XpGetConfigDir(TRUE)) != NULL) && + (access(configDir, F_OK) == 0)) + { + xfree(configDir); + } + else if (((configDir = XpGetConfigDir(FALSE)) != NULL) && + (access(configDir, F_OK) == 0)) + { + xfree(configDir); + } + else { + ErrorF("Xp Extension: could not find config dir %s\n", + configDir ? configDir : XPRINTDIR); + + if (configDir) xfree(configDir); + } + + if(printerDb != (PrinterDbPtr)NULL) + FreePrinterDb(); + + /* + * Calling BuildPrinterDb serves to build the printer database, + * and to initialize the attribute store for each printer. + * The driver can, if it so desires, modify the attribute + * store at a later time. + */ + if((pDb = BuildPrinterDb()) == (PrinterDbPtr)NULL) return; + + /* + * We now have to decide how many screens to initialize, and call + * AddScreen for each one. The printerDb must be properly initialized + * for at least one screen's worth of printers prior to calling AddScreen + * because InitPrintDrivers reads the printerDb to determine which + * driver(s) to init on a particular screen. + * We put each driver's printers on a different + * screen, and call AddScreen for each screen/driver pair. + */ + /* count the number of printers */ + for(pDbEntry = pDb, driverCount = 0; pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next, driverCount++) + ; + /* + * Allocate memory for the worst case - a driver per printer + */ + driverNames = (char **)xalloc(sizeof(char *) * driverCount); + + /* + * Assign the driver for the first printer to the first screen + */ + pDb->screenNum = screenInfo.numScreens; + driverNames[0] = pDb->driverName; + driverCount = 1; + AddFormats(pScreenInfo, pDb->driverName); + + /* + * For each printer, look to see if its driver is already assigned + * to a screen, and if so copy that screen number into the printerDb. + * Otherwise, assign a new screen number to the driver for this + * printer. + */ + for(pDbEntry = pDb; pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next) + { + Bool foundMatch; + + for(i = 0, foundMatch = FALSE; i < driverCount; i++) + { + if(!strcmp(driverNames[i], pDbEntry->driverName)) + { + foundMatch = TRUE; + pDbEntry->screenNum = screenInfo.numScreens + i; + break; + } + } + if(foundMatch == FALSE) + { + driverNames[driverCount] = pDbEntry->driverName; + pDbEntry->screenNum = screenInfo.numScreens + driverCount; + AddFormats(pScreenInfo, pDbEntry->driverName); + driverCount++; + } + } + + for(i = 0; i < driverCount; i++) + { + int curScreen = screenInfo.numScreens; + if(AddScreen(InitPrintDrivers, argc, argv) < 0) + { + PrinterDbPtr pPrev; + /* + * AddScreen failed, so we pull the associated printers + * from the list. + */ + ErrorF("Xp Extension: Could not add screen for driver %s\n", + driverNames[i]); + for(pPrev = pDbEntry = printerDb; pDbEntry != (PrinterDbPtr)NULL; + pDbEntry = pDbEntry->next) + { + if(pDbEntry->screenNum == curScreen) + { + if(pPrev == printerDb) + { + printerDb = pDbEntry->next; + pPrev = printerDb; + } + else + pPrev->next = pDbEntry->next; + + xfree(pDbEntry->name); + xfree(pDbEntry); + pDbEntry = pPrev; + } + else + { + if(pDbEntry->screenNum > curScreen) + pDbEntry->screenNum--; + pPrev = pDbEntry; + } + } + } + } + + xfree(driverNames); + + AugmentFontPath(); + + if(pScreenInfo->numScreens > MAXSCREENS) + { + ErrorF("The number of printer screens requested "); + ErrorF("exceeds the allowable limit of %d screens.\n", MAXSCREENS); + ErrorF("Please reduce the number of requested printers in your "); + ErrorF("\nX%sprinters file.", display); + ErrorF("Server exiting...\n"); + exit(-1); + } +} + +/* + * InitPrintDrivers is called from dix:AddScreen. It in turn calls the + * driver initialization routine for any and all drivers which are + * implicated in supporting printers on the particular screen number + * specified by the "index" parameter. The printerDb variable is used + * to determine which printers are to be associated with a particular + * screen. + */ +static Bool +InitPrintDrivers(index, pScreen, argc, argv) + int index; + ScreenPtr pScreen; + int argc; + char **argv; +{ + PrinterDbPtr pDb, pDb2; + + GenericScreenInit(index, pScreen, argc, argv); + + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(pDb->screenNum == index) + { + Bool callInit = TRUE; + for(pDb2 = printerDb; pDb2 != pDb; pDb2 = pDb2->next) + { + if(!strcmp(pDb->driverName, pDb2->driverName)) + { + callInit = FALSE; + break; + } + } + if(callInit == TRUE) + { + Bool (*initFunc)(); + initFunc = GetInitFunc(pDb->driverName); + if(initFunc(index, pScreen, argc, argv) == FALSE) + { + /* XXX - What do I do if the driver's init fails? */ + } + } + } + } + return TRUE; +} + +void +_XpVoidNoop() +{ + return; +} + +Bool +_XpBoolNoop() +{ + return TRUE; +} + +/* + * GenericScreenInit - The common initializations required by all + * printer screens and drivers. It sets the screen's cursor functions + * to Noops, and computes the maximum screen (i.e. medium) dimensions. + */ + +static void +GenericScreenInit( index, pScreen, argc, argv ) + int index; + ScreenPtr pScreen; + int argc; + char **argv; +{ + int i; + float fWidth, fHeight, maxWidth, maxHeight; + unsigned short width, height; + PrinterDbPtr pDb, pDb2; + int res, maxRes; + + /* + * Set the cursor ops to no-op functions. + */ + pScreen->DisplayCursor = (DisplayCursorProcPtr)_XpBoolNoop; + pScreen->RealizeCursor = (RealizeCursorProcPtr)_XpBoolNoop; + pScreen->UnrealizeCursor = (UnrealizeCursorProcPtr)_XpBoolNoop; + pScreen->SetCursorPosition = (SetCursorPositionProcPtr)_XpBoolNoop; + pScreen->ConstrainCursor = (ConstrainCursorProcPtr)_XpVoidNoop; + pScreen->CursorLimits = (CursorLimitsProcPtr)_XpVoidNoop; + pScreen->RecolorCursor = (RecolorCursorProcPtr)_XpVoidNoop; + + /* + * Find the largest paper size for all the printers on the given + * screen. + */ + maxRes = 0; + maxWidth = maxHeight = 0.0; + for( pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(pDb->screenNum == index) + { + + XpValidatePoolsRec *pValRec; + pVFunc dimensionsFunc; + + GetDimFuncAndRec(pDb->driverName, &pValRec, &dimensionsFunc); + if(dimensionsFunc != (pVFunc)NULL) + dimensionsFunc(pDb->name, pValRec, &fWidth, &fHeight, &res); + else + XpGetMaxWidthHeightRes(pDb->name, pValRec, &fWidth, + &fHeight, &res); + if( res > maxRes ) + maxRes = res; + if( fWidth > maxWidth ) + maxWidth = fWidth; + if( fHeight > maxHeight ) + maxHeight = fHeight; + } + } + + width = (unsigned short) (maxWidth * maxRes / 25.4); + height = (unsigned short) (maxHeight * maxRes / 25.4); + pScreen->width = pScreen->height = ( width > height ) ? width : + height; + + pScreen->mmWidth = pScreen->mmHeight = ( maxWidth > maxHeight ) ? + (unsigned short)(maxWidth + 0.5) : + (unsigned short)(maxHeight + 0.5); +} + +/* + * QualifyName - takes an unqualified file name such as X6printers and + * a colon-separated list of directory path names such as + * /etc/opt/dt:/opt/dt/config. + * + * Returns a fully qualified file path name such as /etc/opt/dt/X6printers. + * The returned value is malloc'd, and the caller is responsible for + * freeing the associated memory. + */ +static char * +QualifyName(fileName, searchPath) + char *fileName; + char *searchPath; +{ + char * curPath = searchPath; + char * nextPath; + char * chance; + FILE *pFile; + + if (fileName == NULL || searchPath == NULL) + return NULL; + + while (1) { + if ((nextPath = strchr(curPath, ':')) != NULL) + *nextPath = 0; + + chance = (char *)xalloc(strlen(curPath) + strlen(fileName) + 2); + sprintf(chance,"%s/%s",curPath,fileName); + + /* see if we can read from the file */ + if((pFile = fopen(chance, "r")) != (FILE *)NULL) + { + fclose(pFile); + /* ... restore the colon, .... */ + if (nextPath) + *nextPath = ':'; + + return chance; + } + + xfree(chance); + + if (nextPath == NULL) /* End of path list? */ + break; + + /* try the next path */ + curPath = nextPath + 1; + } + return NULL; +} + +/* + * FillPrinterListEntry fills in a single XpDiListEntry element with data + * derived from the supplied PrinterDbPtr element. + * + * XXX A smarter (i.e. future) version of this routine might inspect the + * XXX "locale" parameter and attempt to match the "description" and + * XXX "localeName" elements of the XpDiListEntry to the specified locale. + */ +static void +FillPrinterListEntry(pEntry, pDb, localeLen, locale) + XpDiListEntry *pEntry; + PrinterDbPtr pDb; + int localeLen; + char *locale; +{ + static char *localeStr = (char *)NULL; + + if(localeStr == (char *)NULL) + localeStr = strdup(setlocale(LC_ALL, (const char *)NULL)); + + pEntry->name = pDb->name; + pEntry->description = + (char*)XpGetPrinterAttribute(pDb->name, "descriptor"); + pEntry->localeName = localeStr; + pEntry->rootWinId = WindowTable[pDb->screenNum]->drawable.id; +} + +/* + * GetPrinterListInfo fills in the XpDiListEntry struct pointed to by the + * parameter pEntry with the information regarding the printer specified + * by the name and nameLen parameters. The pointers placed in the + * XpDiListEntry structure MUST NOT be freed by the caller. They are + * pointers into existing long-lived databases. + * + */ +static Bool +GetPrinterListInfo(pEntry, nameLen, name, localeLen, locale) + XpDiListEntry *pEntry; + int nameLen; + char *name; + int localeLen; + char *locale; +{ + PrinterDbPtr pDb, pDb2; + + for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next) + { + if(strlen(pDb->name) == nameLen && !strncmp(pDb->name, name, nameLen)) + { + FillPrinterListEntry(pEntry, pDb, localeLen, locale); + return TRUE; + } + } + return FALSE; +} + +/* + * XpDiFreePrinterList is the approved method of releasing memory used + * for a printer list. + */ +void +XpDiFreePrinterList(list) + XpDiListEntry **list; +{ + int i; + + for(i = 0; list[i] != (XpDiListEntry *)NULL; i++) + xfree(list[i]); + xfree(list); +} + +/* + * XpDiGetPrinterList returns a pointer to a NULL-terminated array of + * XpDiListEntry pointers. Each entry structure contains the name, + * description, root window, and locale of a printer. The call returns + * either a list of all printers configured on the server, or it returns + * the information for one specific printer depending on the values passed + * in. Non-NULL values passed in indicate that only the information for + * the one specific printer is desired, while NULL values indicate that + * the information for all printers is desired. + */ +XpDiListEntry ** +XpDiGetPrinterList(nameLen, name, localeLen, locale) + int nameLen; + char *name; + int localeLen; + char *locale; +{ + XpDiListEntry **pList; + + if(!nameLen || name == (char *)NULL) + { + int i; + PrinterDbPtr pDb, pDb2; + + for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL; + pDb = pDb->next, i++) + ; + + if((pList = (XpDiListEntry **)xalloc((i+1) * sizeof(XpDiListEntry *))) + == (XpDiListEntry **)NULL) + return pList; + + pList[i] = (XpDiListEntry *)NULL; + for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL; + pDb = pDb->next, i++) + { + if((pList[i] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry)))== + (XpDiListEntry *)NULL) + { + XpDiFreePrinterList(pList); + return (XpDiListEntry **)NULL; + } + FillPrinterListEntry(pList[i], pDb, localeLen, locale); + } + } + else + { + if((pList = (XpDiListEntry **)xalloc(2 * sizeof(XpDiListEntry *))) == + (XpDiListEntry **)NULL) + return pList; + + if((pList[0] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry))) == + (XpDiListEntry *)NULL) + { + xfree(pList); + return (XpDiListEntry **)NULL; + } + pList[1] = (XpDiListEntry *)NULL; + if(GetPrinterListInfo(pList[0], nameLen, name, localeLen, locale) == + FALSE) + { + xfree(pList[0]); + pList[0] = (XpDiListEntry *)NULL; + } + } + return pList; +} + +WindowPtr +XpDiValidatePrinter(printerName, printerNameLen) + char *printerName; + int printerNameLen; +{ + PrinterDbPtr pCurEntry; + WindowPtr pWin; + + for(pCurEntry = printerDb; + pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next) + { + if(strlen(pCurEntry->name) == printerNameLen && + !strncmp(pCurEntry->name, printerName, printerNameLen)) + return WindowTable[pCurEntry->screenNum]; + } + return (WindowPtr)NULL; +} + +/* + * XpDiGetDriverName takes a screen index and a printer name, and returns + * a pointer to the name of the driver to be used for the specified printer + * on the specified screen. + */ +char * +XpDiGetDriverName(index, printerName) + int index; + char *printerName; +{ + + PrinterDbPtr pCurEntry; + + for(pCurEntry = printerDb; + pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next) + { + if(pCurEntry->screenNum == index && + !strcmp(pCurEntry->name, printerName)) + return pCurEntry->driverName; + } + + return (char *)NULL; /* XXX Should we supply a default driverName? */ +} diff --git a/Xprint/Oid.c b/Xprint/Oid.c new file mode 100644 index 000000000..3fe926c00 --- /dev/null +++ b/Xprint/Oid.c @@ -0,0 +1,3177 @@ +/* $Xorg: Oid.c,v 1.3 2000/08/17 19:48:06 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +#include +#include +#include +#include "Oid.h" +#include /* for memmove */ + +/* + * XpOidNotify value strings + */ +#define NOTIFY_EMAIL_STR "{{event-report-job-completed} electronic-mail}" +#define NOTIFY_NONE_STR "{}" + +#define SafeStrLen(s) ((s) ? strlen((s)) : 0) + +/* + * entry type for the object identifier string map + */ +typedef struct _XpOidStringMapEntry +{ + const char* string; + int length; + int msg_set; + int msg_number; + const char* default_message; + +} XpOidStringMapEntry; + +/* + * include the auto-generated static XpOidStringMap + */ +#include "OidStrs.h" + +/* + * XpOid static function declarations + */ +static XpOid XpOidParse(const char* value_string, + const char** ptr_return); +/* + * XpOidList static function declarations + */ +static XpOidList* XpOidListParse(const char* value_string, + const XpOidList* valid_oids, + const char** ptr_return, int i); + +/* + * XpOidList static function declarations + */ +static XpOidCardList* XpOidCardListParse(const char* value_string, + const XpOidCardList* valid_cards, + const char** ptr_return, int i); + +/* + * XpOidMediumSourceSize static function declarations + */ +static XpOidMediumSS* MediumSSParse(const char* value_string, + const XpOidList* valid_trays, + const XpOidList* valid_medium_sizes, + const char** ptr_return, int i); +static XpOidMediumContinuousSize* MediumContinuousSizeParse(const char*, + const char**); +static void MediumContinuousSizeDelete(XpOidMediumContinuousSize* me); +static XpOidMediumDiscreteSizeList* MediumDiscreteSizeListParse(const char*, + const XpOidList*, + const char**, + int i); +static void MediumDiscreteSizeListDelete(XpOidMediumDiscreteSizeList* list); + +static BOOL ParseArea(const char* value_string, + const char** ptr_return, + XpOidArea* area_return); +static BOOL ParseRealRange(const char* value_string, + const char** ptr_return, + XpOidRealRange* range_return); + +/* + * XpOidTrayMediumList static function declarations + */ +static XpOidTrayMediumList* TrayMediumListParse(const char* value_string, + const XpOidList* valid_trays, + const char** ptr_return, + int i); +static void TrayMediumListValidate(XpOidTrayMediumList* me, + const XpOidMediumSS* msss); + +/* + * XpOidDocFmt + */ +static BOOL XpOidDocFmtNext(XpOidDocFmt* doc_fmt, + const char* value_string, + const char** ptr_return); + +/* + * XpOidDocFmtListParse + */ +static XpOidDocFmtList* XpOidDocFmtListParse(const char* value_string, + const XpOidDocFmtList* valid_fmts, + const char** ptr_return, int i); + +/* + * misc. parsing static function declarations + */ +static BOOL ParseBoolValue(const char* value_string, + const char** ptr_return, + BOOL* bool_return); +static BOOL ParseRealValue(const char* value_string, + const char** ptr_return, + float* real_return); +static BOOL ParseSeqEnd( + const char* value_string, + const char** ptr_return); +static BOOL ParseSeqStart( + const char* value_string, + const char** ptr_return); +static BOOL ParseUnspecifiedValue( + const char* value_string, + const char** ptr_return); +static int SpanToken( + const char* string); +static int SpanWhitespace( + const char* string); + +/* + * String comparison function. + */ +#ifdef HAVE_STRCASECMP +# define StrnCaseCmp(s1, s2, len) strncasecmp(s1, s2, len) +#else +static int StrnCaseCmp(const char *s1, const char *s2, size_t len); +#endif + +/* + * ------------------------------------------------------------------------ + * Name: XpOidString + * + * Description: + * + * Obtain the string representation of an XpOid. + * + * Example: XpOidString(xpoid_copy_count) returns "copy-count". + * + * Return value: + * + * A const pointer to the string. + */ +const char* +XpOidString(XpOid xp_oid) +{ + /* + * XpOid enum values are index values into the string map + */ + return XpOidStringMap[xp_oid].string; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidStringLength + * + * Description: + * + * Obtain the length of the string representation for a given + * XpOid. + * + * Return value: + * + * The string length in bytes. + * + */ +int +XpOidStringLength(XpOid xp_oid) +{ + /* + * XpOid enum values are index values into the string map + */ + return XpOidStringMap[xp_oid].length; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidFromString + * + * Description: + * + * Obtains the XpOid given a string representation of an XpOid. + * + * Example: XpOidFromString("copy-count") returns 'xpoid_copy_count'. + * + * Return value: + * + * The XpOid if successful. 'xpoid_none' if the string pointed to by + * 'value is not recognized or if 'value' is NULL. + */ +XpOid +XpOidFromString(const char* value) +{ + if(value == (const char*)NULL) + return xpoid_none; + else + return XpOidParse(value, (const char**)NULL); +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidParse + * + * Description: + * + * Parse the next whitespace-delimited string from 'value_string' + * updating 'ptr_return' to point to the next unparsed location in + * 'value_string'. 'ptr_return' can be NULL. + * + * Return value: + * + * The corresponding XpOid for the parsed name string. + * A return value of xpoid_none is returned if the parsed name + * was not a valid oid or if no name was found. + * + */ +static XpOid +XpOidParse(const char* value_string, + const char** ptr_return) +{ + const char* ptr; + int length; + int i; + /* + * skip leading whitespace + */ + ptr = value_string + SpanWhitespace(value_string); + /* + * get the whitespace-delimited token length + */ + length = SpanToken(ptr); + /* + * match the oid string in the map + */ + for(i = 0; i < XpOidStringMapCount; i++) + if(length == XpOidStringMap[i].length) + if(strncmp(ptr, XpOidStringMap[i].string, length) == 0) + break; + if(i == XpOidStringMapCount) + i = xpoid_none; + /* + * update the return pointer and return + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr+length; + return i; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidListNew + * + * Description: + * + * Creates a new XpOidList initialized from a whitespace-delimited + * list of recognized string representations of oids. The returned + * list will contain only oids found within the passed 'valid_oids' + * XpOidList. + * + * Note: One may notice that in order to create an XpOidList with + * this function, an XpOidList is needed; the 'valid_oids' list + * is often an statically initialized structure. XpOidListInit + * can also be used. + * + * Return value: + * + * NULL if the passed 'value_string' is NULL. + * + * If the list indicated by 'value_string' is empty or contains only + * unrecognized oid string representations, a new XpOidList + * containing zero elements is returned. + * + * If 'valid_oids' is NULL all oids are considered valid. + * + */ +XpOidList* +XpOidListNew(const char* value_string, + const XpOidList* valid_oids) +{ + if(value_string == (const char*)NULL) + return (XpOidList*)NULL; + else + { + const char* ptr; + return XpOidListParse(value_string, valid_oids, &ptr, 0); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidListDelete + * + * Description: + * + * Frees the memory allocated for 'list'. + * + * Return value: + * + * None. + * + */ +void +XpOidListDelete(XpOidList* list) +{ + if(list != (XpOidList*)NULL) + { + XpOidFree((char*)list->list); + XpOidFree((char*)list); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidListParse + * + * Description: + * + * This function recursively parses the whitespace-delimited list of + * oid string representations passed via 'value_string'. Oids are + * only added to the resulting list if they are found within the + * passed 'valid_oids' XpOidList. + * + * 'ptr_return' points to a char* variable allocated by the + * caller, and is really only of use during recursion (upon return to + * the original caller, it will point to the end of value_string). + * + * 'value_string' and 'ptr_return' *cannot* be NULL. + * + * Return value: + * + * A newly allocated and initialized XpOidList. + * + * If the list indicated by 'value_string' is empty or contains only + * unrecognized oid string representations, a new XpOidList + * containing zero elements is returned. + * + * If 'valid_oids' is NULL all oids are considered valid. + * + */ +static XpOidList* +XpOidListParse(const char* value_string, + const XpOidList* valid_oids, + const char** ptr_return, + int i) +{ + XpOid oid; + XpOidList* list; + /* + * parse the next valid oid out of the value string + */ + ptr_return = &value_string; + while(1) + { + if(**ptr_return == '\0') + { + /* + * end of value string; stop parsing + */ + oid = xpoid_none; + break; + } + /* + * parse the next oid from the value + */ + oid = XpOidParse(*ptr_return, ptr_return); + if(xpoid_none == oid) + { + /* + * unrecognized oid; keep parsing + */ + continue; + } + if((const XpOidList*)NULL == valid_oids + || + XpOidListHasOid(valid_oids, oid)) + { + /* + * valid oid found; stop parsing + */ + break; + } + } + + if(oid == xpoid_none) + { + /* + * end of value string; allocate the list structure + */ + list = (XpOidList*)XpOidCalloc(1, sizeof(XpOidList)); + list->count = i; + list->list = (XpOid*)XpOidCalloc(i, sizeof(XpOid)); + } + else + { + /* + * recurse + */ + list = XpOidListParse(*ptr_return, valid_oids, ptr_return, i+1); + /* + * set the oid in the list + */ + list->list[i] = oid; + } + /* + * return + */ + return list; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidListHasOid + * + * Description: + * + * Determines if 'oid' is an element of 'list'. + * + * Return value: + * + * xTrue if the oid is found in the list. + * + * xFalse if the oid is not in the list, or if 'list' is NULL. + * + */ +BOOL +XpOidListHasOid(const XpOidList* list, XpOid oid) +{ + int i; + if(list != (XpOidList*)NULL) + for(i = 0; i < list->count; i++) + if(list->list[i] == oid) + return xTrue; + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidListGetIndex + * + * Description: + * + * Returns the array index of 'oid' in 'list' + * + * Return value: + * + * The index of 'oid' in list. + * + * -1 if the oid is not in the list, or if 'list' is NULL. + * + */ +int +XpOidListGetIndex(const XpOidList* list, XpOid oid) +{ + int i; + if(list != (XpOidList*)NULL) + for(i = 0; i < list->count; i++) + if(list->list[i] == oid) + return i; + return -1; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidListString + * + * Description: + * + * Creates a string representation of an XpOidList structure. + * + * Return value: + * + * A newly allocated + * + */ +char* +XpOidListString(const XpOidList* me) +{ + int i; + int length; + char* str; + char* ptr; + /* + * allocate enough memory for the oid string representations, + * including intervening whitespace + */ + for(i = 0, length = 0; i < XpOidListCount(me); i++) + length += XpOidStringLength(XpOidListGetOid(me, i)) + 1; + str = XpOidMalloc(length+1); + /* + * format the list + */ + for(i = 0, ptr = str; i < XpOidListCount(me); i++) +#if defined(sun) && !defined(SVR4) + { + sprintf(ptr, "%s ", XpOidString(XpOidListGetOid(me, i))); + ptr += strlen(ptr); + } +#else + ptr += sprintf(ptr, "%s ", XpOidString(XpOidListGetOid(me, i))); +#endif + /* + * chop trailing whitespace or terminate empty string + */ + str[length] = '\0'; + /* + * return + */ + return str; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListNew + * + * Description: + * + * Creates a new instance of an empty XpOidLinkedList. + * + * Return value: + * + * The new XpOidLinkedList. + * + */ +XpOidLinkedList* +XpOidLinkedListNew() +{ + return (XpOidLinkedList*)XpOidCalloc(1, sizeof(XpOidLinkedList)); +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListDelete + * + * Description: + * + * Frees the memory allocated for a XpOidLinkedList. + * + * Return value: + * + * None. + * + */ +void +XpOidLinkedListDelete(XpOidLinkedList* me) +{ + if(me != (XpOidLinkedList*)NULL) + { + while(me->head) + { + me->current = me->head; + me->head = me->current->next; + XpOidFree((char*)me->current); + } + XpOidFree((char*)me); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListGetOid + * + * Description: + * + * Retrieves the oid at position 'i' (zero-based) in the + * XpOidLinkedList 'me'. + * + * Return value: + * + * The oid at position 'i'. + * + * xpoid_none if the oid was not found, or the list is empty (or if + * the list contains xpoid_none at position 'i'). + */ +XpOid +XpOidLinkedListGetOid(XpOidLinkedList* me, int i) +{ + if(me == (XpOidLinkedList*)NULL || i < 0 || i >= me->count) + { + return xpoid_none; + } + else + { + me->current = me->head; + while(i--) me->current = me->current->next; + return me->current->oid; + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListAddOid + * + * Description: + * + * Adds an oid to the end of an XpOidLinkedList. + * + * Return value: + * + * None. + * + */ +void +XpOidLinkedListAddOid(XpOidLinkedList* me, XpOid oid) +{ + me->current = (XpOidNode)XpOidCalloc(1, sizeof(struct XpOidNodeStruct)); + me->current->oid = oid; + ++me->count; + if(me->tail) + { + me->tail->next = me->current; + me->tail = me->current; + } + else + me->head = me->tail = me->current; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListGetIndex + * + * Description: + * + * Returns the position of an oid in a XpOidLinkedList. + * + * Return value: + * + * The zero-based position of 'oid' in the list. + * + * -1 if the oid is not in the list, or if 'me' is NULL. + * + */ +int +XpOidLinkedListGetIndex(XpOidLinkedList* me, XpOid oid) +{ + if((XpOidLinkedList*)NULL != me) + { + int i = 0; + me->current = me->head; + while(me->current) + if(me->current->oid == oid) + { + return i; + } + else + { + ++i; + me->current = me->current->next; + } + } + return -1; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListHasOid + * + * Description: + * + * Determines if an oid is an element of a XpOidLinkedList. + * + * Return value: + * + * xTrue if the oid is found in the list. + * + * xFalse if the oid is not in the list, or if 'me' is NULL. + */ +BOOL +XpOidLinkedListHasOid(XpOidLinkedList* me, + XpOid oid) +{ + if((XpOidLinkedList*)NULL != me) + { + me->current = me->head; + while(me->current) + if(me->current->oid == oid) + return xTrue; + else + me->current = me->current->next; + } + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListFirstOid + * + * Description: + * + * Positions the XpOidLinkedList 'current' pointer to the first entry + * in the list. + * + * Return value: + * + * The first oid in the list, or xpoid_none if the list NULL or + * empty. + */ +XpOid +XpOidLinkedListFirstOid(XpOidLinkedList* me) +{ + if((XpOidLinkedList*)NULL != me && (me->current = me->head)) + return me->current->oid; + else + return xpoid_none; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidLinkedListNextOid + * + * Description: + * + * Positions the XpOidLinkedList 'current' pointer to the next entry + * in the list. + * + * Return value: + * + * The next oid, or xpoid_none if the end of the list has been + * reached. + */ +XpOid +XpOidLinkedListNextOid(XpOidLinkedList* me) +{ + if(me->current ? me->current = me->current->next : xFalse) + return me->current->oid; + else + return xpoid_none; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidMediumSSNew + * + * Description: + * + * Creates a new XpOidMediumSS initialized from a string value + * specified using the medium-source-sizes syntax. See + * MediumSSParse() below for parsing details. + * + * Return value: + * + * NULL if the passed 'value_string' is NULL, or if a syntax error is + * encountered while parsing the medium-source-sizes value. + * + */ +XpOidMediumSS* +XpOidMediumSSNew(const char* value_string, + const XpOidList* valid_trays, + const XpOidList* valid_medium_sizes) +{ + if(value_string == (const char*)NULL) + return (XpOidMediumSS*)NULL; + else + { + const char* ptr = value_string + SpanWhitespace(value_string); + if(*ptr == '\0') + return (XpOidMediumSS*)NULL; + else + return MediumSSParse(ptr, valid_trays, valid_medium_sizes, + &ptr, 0); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: MediumSSParse + * + * Description: + * + * 'ptr_return' *cannot* be NULL. + * + * + * Return value: + * + * + * + */ +static XpOidMediumSS* +MediumSSParse(const char* value_string, + const XpOidList* valid_trays, + const XpOidList* valid_medium_sizes, + const char** ptr_return, + int i) +{ + XpOidMediumSS* medium_ss; + XpOidMediumSourceSize mss; + /* + * check for the start of a new MediumSourceSize sequence + */ + if(ParseSeqStart(value_string, ptr_return)) + { + /* + * check for an unspecified tray value + */ + if(ParseUnspecifiedValue(*ptr_return, ptr_return)) + mss.input_tray = xpoid_unspecified; + else + { + const char* tray_str; + *ptr_return += SpanWhitespace(*ptr_return); + tray_str = *ptr_return; + /* + * parse out the input tray + */ + mss.input_tray = XpOidParse(*ptr_return, ptr_return); + if((const XpOidList*)NULL != valid_trays + && + !XpOidListHasOid(valid_trays, mss.input_tray) + ) + mss.input_tray = xpoid_none; + if(xpoid_none == mss.input_tray) + { + char* invalid_tray_str; + int len = *ptr_return - tray_str; + if(len > 0) + { + invalid_tray_str = XpOidMalloc(len+1); + strncpy(invalid_tray_str, tray_str, len); + invalid_tray_str[len] = '\0'; + ErrorF("%s\nInvalid tray (%s) found. Will attempt to continue parsing.\n", + XPMSG_WARN_MSS, invalid_tray_str); + XpOidFree(invalid_tray_str); + } + } + } + /* + * attempt to parse a Continuous MediumSize sequence + */ + mss.ms.continuous_size = + MediumContinuousSizeParse(*ptr_return, ptr_return); + if(mss.ms.continuous_size != (XpOidMediumContinuousSize*)NULL) + { + mss.mstag = XpOidMediumSS_CONTINUOUS; + } + else + { + /* + * not continuous, try Discrete MediumSize + */ + mss.ms.discrete = + MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes, + ptr_return, 0); + if(mss.ms.discrete == (XpOidMediumDiscreteSizeList*)NULL) + { + const char* tray_str; + /* + * syntax error (MediumDiscreteSizeListParse reports error) + */ + switch(mss.input_tray) + { + case xpoid_none: + tray_str = "an invalid"; + break; + case xpoid_unspecified: + tray_str = "default (tray specifier omitted)"; + break; + default: + tray_str = XpOidString(mss.input_tray); + break; + } + ErrorF("%s\nError occurred while parsing medium sizes for %s tray.\n", + XPMSG_WARN_MSS, tray_str); + return NULL; + } + mss.mstag = XpOidMediumSS_DISCRETE; + } + /* + * parse out the MediumSourceSize sequence end + */ + if(!ParseSeqEnd(*ptr_return, ptr_return)) + { + /* + * syntax error + */ + ErrorF("%s\nSequence End expected. Unparsed data: %s\n", + XPMSG_WARN_MSS, *ptr_return); + return NULL; + } + /* + * recurse to parse the next MediumSourceSize sequence + */ + medium_ss = MediumSSParse(*ptr_return, + valid_trays, valid_medium_sizes, + ptr_return, + xpoid_none == mss.input_tray ? i : i+1); + if(medium_ss == (XpOidMediumSS*)NULL + || + xpoid_none == mss.input_tray) + { + /* + * syntax error or invalid tray - clean up + */ + switch(mss.mstag) + { + case XpOidMediumSS_CONTINUOUS: + MediumContinuousSizeDelete(mss.ms.continuous_size); + break; + case XpOidMediumSS_DISCRETE: + MediumDiscreteSizeListDelete(mss.ms.discrete); + break; + } + if(medium_ss == (XpOidMediumSS*)NULL) + /* + * syntax error - return + */ + return NULL; + } + if(xpoid_none != mss.input_tray) + { + /* + * copy the current MediumSourceSize into the array + */ + memmove((medium_ss->mss)+i, &mss, sizeof(XpOidMediumSourceSize)); + } + } + else + { + /* + * MediumSourceSize sequence start not found + */ + if(**ptr_return == '\0') + { + if(0 == i) + { + ErrorF("%s\nNo valid trays found.\n", XPMSG_WARN_MSS); + return NULL; + } + /* + * end of value string; allocate the MediumSS structure + */ + medium_ss = (XpOidMediumSS*)XpOidCalloc(1, sizeof(XpOidMediumSS)); + medium_ss->count = i; + medium_ss->mss = (XpOidMediumSourceSize*) + XpOidCalloc(i, sizeof(XpOidMediumSourceSize)); + } + else + { + /* + * syntax error + */ + ErrorF("%s\nSequence Start expected.\nunparsed data: %s\n", + XPMSG_WARN_MSS, *ptr_return); + return NULL; + } + } + return medium_ss; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidMediumSSDelete + * + * Description: + * + * + * + * Return value: + * + * + * + */ +void +XpOidMediumSSDelete(XpOidMediumSS* me) +{ + if(me != (XpOidMediumSS*)NULL) + { + int i; + for(i = 0; i < me->count; i++) + { + switch((me->mss)[i].mstag) + { + case XpOidMediumSS_CONTINUOUS: + MediumContinuousSizeDelete((me->mss)[i].ms.continuous_size); + break; + case XpOidMediumSS_DISCRETE: + MediumDiscreteSizeListDelete((me->mss)[i].ms.discrete); + break; + } + } + XpOidFree((char*)me); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidMediumSSHasSize + * + * Description: + * + * + * + * Return value: + * + * + * + */ +BOOL +XpOidMediumSSHasSize(XpOidMediumSS* me, XpOid page_size) +{ + int i_mss, i_ds; + XpOidMediumDiscreteSizeList* ds_list; + + if(me != (XpOidMediumSS*)NULL && page_size != xpoid_none) + for(i_mss = 0; i_mss < me->count; i_mss++) + { + switch((me->mss)[i_mss].mstag) + { + case XpOidMediumSS_DISCRETE: + ds_list = (me->mss)[i_mss].ms.discrete; + for(i_ds = 0; i_ds < ds_list->count; i_ds++) + if(page_size == (ds_list->list)[i_ds].page_size) + return xTrue; + break; + + case XpOidMediumSS_CONTINUOUS: + /* + * unsupported + */ + break; + } + } + /* + * return + */ + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidMediumSSString + * + * Description: + * + * Creates a string representation of an XpOidMediumSS structure. + * + * Return value: + * + * A newly allocated + * + */ +char* XpOidMediumSSString(const XpOidMediumSS* me) +{ + int itray, isize; + int valid_size_count; + int length; + char* str; + char* ptr; + XpOidMediumDiscreteSize* ds; + char buf[128]; + /* + * determine the size of the string representation + */ + for(itray = 0, length = 0; itray < XpOidMediumSSCount(me); itray++) + { + if(xpoid_none == me->mss[itray].input_tray + || + XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag) + { + /* + * skip invalid tray or unsupported continuous size spec + */ + continue; + } + for(isize = 0, valid_size_count = 0; + isize < me->mss[itray].ms.discrete->count; + isize++) + { + ds = me->mss[itray].ms.discrete->list+isize; + if(ds->page_size == xpoid_none) + continue; + ++valid_size_count; + length += XpOidStringLength(ds->page_size); + length += ds->long_edge_feeds ? 4 : 5; /* "True" or "False" */ +#if defined(sun) && !defined(SVR4) + sprintf(buf, "{%.4f %.4f %.4f %.4f}", + ds->assured_reproduction_area.minimum_x, + ds->assured_reproduction_area.maximum_x, + ds->assured_reproduction_area.minimum_y, + ds->assured_reproduction_area.maximum_y); + length += strlen(buf); +#else + length += sprintf(buf, "{%.4f %.4f %.4f %.4f}", + ds->assured_reproduction_area.minimum_x, + ds->assured_reproduction_area.maximum_x, + ds->assured_reproduction_area.minimum_y, + ds->assured_reproduction_area.maximum_y); +#endif + length += 5; /* "{ } " */ + } + if(valid_size_count == 0) + { + /* + * no valid sizes, skip + */ + continue; + } + if(xpoid_unspecified == me->mss[itray].input_tray) + length += 2; /* "''" */ + else + length += XpOidStringLength(me->mss[itray].input_tray); + length += 4; /* "{ } " */ + } + /* + * allocate + */ + str = XpOidMalloc(length+1); + /* + * format + */ + for(itray = 0, ptr = str; itray < XpOidMediumSSCount(me); itray++) + { + if(xpoid_none == me->mss[itray].input_tray + || + XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag) + { + /* + * skip invalid tray or unsupported continuous size spec + */ + continue; + } + /* + * check to ensure all of the specified sizes are valid + */ + for(isize = 0, valid_size_count = 0; + isize < me->mss[itray].ms.discrete->count; + isize++) + { + ds = me->mss[itray].ms.discrete->list+isize; + if(ds->page_size != xpoid_none) + ++valid_size_count; + } + if(valid_size_count == 0) + { + /* + * no valid sizes, skip + */ + continue; + } + + if(xpoid_unspecified == me->mss[itray].input_tray) + { +#if defined(sun) && !defined(SVR4) + sprintf(ptr, "{'' "); + ptr += strlen(ptr); +#else + ptr += sprintf(ptr, "{'' "); +#endif + } + else + { +#if defined(sun) && !defined(SVR4) + sprintf(ptr, "{%s ", XpOidString(me->mss[itray].input_tray)); + ptr += strlen(ptr); +#else + ptr += sprintf(ptr, "{%s ", + XpOidString(me->mss[itray].input_tray)); +#endif + } + for(isize = 0; isize < me->mss[itray].ms.discrete->count; isize++) + { + ds = me->mss[itray].ms.discrete->list+isize; + if(ds->page_size != xpoid_none) +#if defined(sun) && !defined(SVR4) + { + sprintf(ptr, "{%s %s {%.4f %.4f %.4f %.4f}} ", + XpOidString(ds->page_size), + ds->long_edge_feeds ? "True" : "False", + ds->assured_reproduction_area.minimum_x, + ds->assured_reproduction_area.maximum_x, + ds->assured_reproduction_area.minimum_y, + ds->assured_reproduction_area.maximum_y); + ptr += strlen(ptr); + } +#else + ptr += sprintf(ptr, "{%s %s {%.4f %.4f %.4f %.4f}} ", + XpOidString(ds->page_size), + ds->long_edge_feeds ? "True" : "False", + ds->assured_reproduction_area.minimum_x, + ds->assured_reproduction_area.maximum_x, + ds->assured_reproduction_area.minimum_y, + ds->assured_reproduction_area.maximum_y); +#endif + } +#if defined(sun) && !defined(SVR4) + sprintf(ptr, "} "); + ptr += strlen(ptr); +#else + ptr += sprintf(ptr, "} "); +#endif + } + /* + * chop trailing whitespace or terminate empty string + */ + str[length] = '\0'; + /* + * return + */ + return str; +} + +/* + * ------------------------------------------------------------------------ + * Name: MediumContinuousSizeParse + * + * Description: + * + * 'ptr_return' *cannot* be NULL. + * + * + * Return value: + * + * + * + */ +static XpOidMediumContinuousSize* +MediumContinuousSizeParse(const char* value_string, + const char** ptr_return) +{ + const char* first_nonws_ptr; + XpOidMediumContinuousSize* mcs = NULL; + /* + * skip leading whitespace + */ + first_nonws_ptr = value_string + SpanWhitespace(value_string); + /* + * parse out the MediumSize sequence start char + */ + if(!ParseSeqStart(first_nonws_ptr, ptr_return)) + goto MediumContinuousSizeParse_error; + /* + * peek ahead to see if it looks like we actually have a continuous + * size spec (looking for the sequence start char on the 1st range spec) + */ + if(!ParseSeqStart(*ptr_return, (const char**)NULL)) + goto MediumContinuousSizeParse_error; + /* + * Ok, let's go for it + */ + mcs = (XpOidMediumContinuousSize*) + XpOidCalloc(1, sizeof(XpOidMediumContinuousSize)); + /* + * "range across the feed direction" + */ + if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_across_feed)) + goto MediumContinuousSizeParse_error; + /* + * "increment across the feed direction" (optional, default 0) + */ + if(!ParseUnspecifiedValue(*ptr_return, ptr_return)) + if(!ParseRealValue(*ptr_return, ptr_return, + &mcs->increment_across_feed)) + goto MediumContinuousSizeParse_error; + /* + * "range in the feed direction" + */ + if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_in_feed)) + goto MediumContinuousSizeParse_error; + /* + * "increment in the feed direction" (optional, default 0) + */ + if(!ParseUnspecifiedValue(*ptr_return, ptr_return)) + if(!ParseRealValue(*ptr_return, ptr_return, + &mcs->increment_in_feed)) + goto MediumContinuousSizeParse_error; + /* + * "long edge feeds" flag (default TRUE) + */ + if(ParseUnspecifiedValue(*ptr_return, ptr_return)) + mcs->long_edge_feeds = xTrue; + else + if(!ParseBoolValue(*ptr_return, ptr_return, &mcs->long_edge_feeds)) + goto MediumContinuousSizeParse_error; + /* + * "generic assured reproduction area" + */ + if(!ParseArea(*ptr_return, ptr_return, &mcs->assured_reproduction_area)) + goto MediumContinuousSizeParse_error; + /* + * parse out the MediumSize sequence end character + */ + if(!ParseSeqEnd(*ptr_return, ptr_return)) + goto MediumContinuousSizeParse_error; + /* + * return + */ + return mcs; + + + MediumContinuousSizeParse_error: + /* + * syntax error - don't log since this function may be called + * as a lookahead + */ + *ptr_return = first_nonws_ptr; + XpOidFree((char*)mcs); + return NULL; +} + +/* + * ------------------------------------------------------------------------ + * Name: MediumContinuousSizeDelete + * + * Description: + * + * 'ptr_return' *cannot* be NULL. + * + * + * Return value: + * + * + * + */ +static void +MediumContinuousSizeDelete(XpOidMediumContinuousSize* me) +{ + XpOidFree((char*)me); +} + +/* + * ------------------------------------------------------------------------ + * Name: MediumDiscreteSizeListParse + * + * Description: + * + * 'ptr_return' *cannot* be NULL. + * + * Return value: + * + * + * + */ +static XpOidMediumDiscreteSizeList* +MediumDiscreteSizeListParse(const char* value_string, + const XpOidList* valid_medium_sizes, + const char** ptr_return, + int i) +{ + XpOidMediumDiscreteSizeList* list; + XpOidMediumDiscreteSize mds; + /* + * check for the start of a new MediumSize sequence + */ + if(ParseSeqStart(value_string, ptr_return)) + { + /* + * "page size" + */ + mds.page_size = XpOidParse(*ptr_return, ptr_return); + if((const XpOidList*)NULL != valid_medium_sizes + && + !XpOidListHasOid(valid_medium_sizes, mds.page_size) + ) + mds.page_size = xpoid_none; + /* + * "long edge feeds" flag (default TRUE) + */ + if(ParseUnspecifiedValue(*ptr_return, ptr_return)) + mds.long_edge_feeds = xTrue; + else + if(!ParseBoolValue(*ptr_return, ptr_return, + &mds.long_edge_feeds)) + { + /* + * syntax error + */ + ErrorF("%s\nBoolean expected.\nunparsed data: %s\n", + XPMSG_WARN_MSS, *ptr_return); + return (XpOidMediumDiscreteSizeList*)NULL; + } + /* + * "assured reproduction area" + */ + if(!ParseArea(*ptr_return, ptr_return, + &mds.assured_reproduction_area)) + { + /* + * syntax error + */ + ErrorF("%s\nArea specification error.\nunparsed data: %s\n", + XPMSG_WARN_MSS, *ptr_return); + return (XpOidMediumDiscreteSizeList*)NULL; + } + /* + * parse out the MediumSize sequence end character + */ + if(!ParseSeqEnd(*ptr_return, ptr_return)) + { + ErrorF("%s\nSequence End expected. Unparsed data: %s\n", + XPMSG_WARN_MSS, *ptr_return); + return (XpOidMediumDiscreteSizeList*)NULL; + } + /* + * recurse to parse the next Discrete MediumSize sequence + */ + if(mds.page_size == xpoid_none) + { + list = MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes, + ptr_return, i); + } + else + { + list = MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes, + ptr_return, i+1); + if(list != (XpOidMediumDiscreteSizeList*)NULL) + { + /* + * copy the current discrete MediumSize into the list + */ + memmove((list->list)+i, &mds, sizeof(XpOidMediumDiscreteSize)); + } + } + } + else + { + /* + * MediumSize sequence start not found; end of the discrete sizes + * list + */ + if(0 == i) + { + ErrorF("%s\nNo valid medium sizes found for tray.\n", + XPMSG_WARN_MSS); + return (XpOidMediumDiscreteSizeList*)NULL; + } + list = (XpOidMediumDiscreteSizeList*) + XpOidCalloc(1, sizeof(XpOidMediumDiscreteSizeList)); + list->count = i; + list->list = (XpOidMediumDiscreteSize*) + XpOidCalloc(i, sizeof(XpOidMediumDiscreteSize)); + } + return list; +} + +/* + * ------------------------------------------------------------------------ + * Name: MediumDiscreteSizeListDelete + * + * Description: + * + * + * + * Return value: + * + * + * + */ +static void +MediumDiscreteSizeListDelete(XpOidMediumDiscreteSizeList* list) +{ + if(list != (XpOidMediumDiscreteSizeList*)NULL) + { + XpOidFree((char*)list->list); + XpOidFree((char*)list); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidTrayMediumListNew + * + * Description: + * + * Only need the valid trays; validation requires bumping up against + * msss using TrayMediumListValidate; this needs valid trays + * because of unspecified trays ion msss, but + * TrayMediumListValidate will take care of invalid sizes... + * + * Return value: + * + * + * + */ +XpOidTrayMediumList* +XpOidTrayMediumListNew(const char* value_string, + const XpOidList* valid_trays, + const XpOidMediumSS* msss) +{ + if(value_string == (const char*)NULL) + return (XpOidTrayMediumList*)NULL; + else + { + const char* ptr; + XpOidTrayMediumList* me; + me = TrayMediumListParse(value_string, valid_trays, &ptr, 0); + if((XpOidTrayMediumList*)NULL != me) + TrayMediumListValidate(me, msss); + return me; + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidTrayMediumListDelete + * + * Description: + * + * + * + * Return value: + * + * + * + */ +void +XpOidTrayMediumListDelete(XpOidTrayMediumList* list) +{ + if(list != (XpOidTrayMediumList*)NULL) + { + XpOidFree((char*)list->list); + XpOidFree((char*)list); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: TrayMediumListParse + * + * Description: + * + * 'ptr_return' *cannot* be NULL. + * + * Return value: + * + * + * + */ +static XpOidTrayMediumList* +TrayMediumListParse(const char* value_string, + const XpOidList* valid_trays, + const char** ptr_return, int i) +{ + XpOidTrayMedium tm; + XpOidTrayMediumList* list; + /* + * check for the start of a new InputTrayMedium sequence + */ + if(ParseSeqStart(value_string, ptr_return)) + { + /* + * "input tray" + */ + tm.input_tray = XpOidParse(*ptr_return, ptr_return); + if((XpOidList*)NULL != valid_trays + && + !XpOidListHasOid(valid_trays, tm.input_tray) + ) + tm.input_tray = xpoid_none; + /* + * "medium" + */ + tm.medium = XpOidParse(*ptr_return, ptr_return); + /* + * parse out the InputTrayMedium sequence end character + */ + if(!ParseSeqEnd(*ptr_return, ptr_return)) + { + ErrorF("%s\n", XPMSG_WARN_ITM); + return NULL; + } + /* + * recurse to parse the next InputTrayMedium sequence + */ + list = TrayMediumListParse(*ptr_return, valid_trays, ptr_return, i+1); + if(list != (XpOidTrayMediumList*)NULL) + { + /* + * copy the current InputTrayMedium into the list + */ + memmove((list->list)+i, &tm, sizeof(XpOidTrayMedium)); + } + } + else + { + /* + * InputTrayMedium sequence start not found + */ + if(**ptr_return == '\0') + { + /* + * end of the list + */ + list = (XpOidTrayMediumList*) + XpOidCalloc(1, sizeof(XpOidTrayMediumList)); + list->count = i; + list->list = (XpOidTrayMedium*) + XpOidCalloc(i, sizeof(XpOidTrayMedium)); + } + else + { + /* + * syntax error + */ + ErrorF("%s\n", XPMSG_WARN_ITM); + return NULL; + } + } + /* + * return + */ + return list; +} + +/* + * ------------------------------------------------------------------------ + * Name: TrayMediumListValidate + * + * Description: + * + * Validate the input-trays-medium list based on a passed + * medium-source-sizes-supported structure. The validated + * input-trays-medium list will have the same number of entries upon + * return from this function. Invalid entries are indicated by + * setting the tray specification to xpoid_none. + * + * Return value: + * + * None. + * + */ +static void +TrayMediumListValidate(XpOidTrayMediumList* me, + const XpOidMediumSS* msss) +{ + int i_mss, i_ds, i_itm; + XpOidMediumDiscreteSizeList* ds_list; + int tray_count; + XpOid current_tray, current_medium; + XpOidMediumDiscreteSizeList* unspecified_tray_ds; + XpOidMediumDiscreteSizeList* tray_ds; + + if(msss == (XpOidMediumSS*)NULL + || + me == (XpOidTrayMediumList*)NULL) + { + return; + } + /* + * loop through the input trays medium list + */ + for(i_itm = 0; i_itm < XpOidTrayMediumListCount(me); i_itm++) + { + current_tray = XpOidTrayMediumListTray(me, i_itm); + if(current_tray == xpoid_none) + continue; + current_medium = XpOidTrayMediumListMedium(me, i_itm); + if(current_medium == xpoid_none) + { + /* + * no medium; invalidate this entry + */ + me->list[i_itm].input_tray = xpoid_none; + continue; + } + /* + * loop through the MediumSourceSizes, looking for an appropriate + * discrete sizes spec for the current tray + */ + unspecified_tray_ds = (XpOidMediumDiscreteSizeList*)NULL; + tray_ds = (XpOidMediumDiscreteSizeList*)NULL; + for(i_mss = 0; + i_mss < msss->count && + tray_ds == (XpOidMediumDiscreteSizeList*)NULL; + i_mss++) + { + switch((msss->mss)[i_mss].mstag) + { + case XpOidMediumSS_DISCRETE: + if((msss->mss)[i_mss].input_tray == current_tray) + tray_ds = (msss->mss)[i_mss].ms.discrete; + else if((msss->mss)[i_mss].input_tray == xpoid_unspecified) + unspecified_tray_ds = (msss->mss)[i_mss].ms.discrete; + break; + + case XpOidMediumSS_CONTINUOUS: + /* + * unsupported + */ + break; + } + } + /* + * if the tray was not matched, use the unspecified tray size + * list + */ + if(tray_ds == (XpOidMediumDiscreteSizeList*)NULL) + if(unspecified_tray_ds == (XpOidMediumDiscreteSizeList*)NULL) + { + /* + * not even an unspecified tray, invalidate this + * input-trays-medium entry. + */ + me->list[i_itm].input_tray = xpoid_none; + continue; + } + else + tray_ds = unspecified_tray_ds; + /* + * loop through the discrete sizes list, looking for a size that + * matches the medium for the current input tray + */ + for(i_ds = 0; i_ds < tray_ds->count; i_ds++) + { + /* + * check to see if the current input tray's medium size + * matches the current discrete size + * + * Note: in the CDEnext SI, medium identifiers coincide with + * medium-size identifiers. If the DP-Medium object is + * ever implemented, this check would need to be + * changed so that the input tray's medium size is + * obtained from the indicated Medium object, and not + * inferred from the medium identifier itself. + */ + if((tray_ds->list)[i_ds].page_size == current_medium) + { + /* + * The current input tray's medium size matches the + * current discrete medium size. + */ + break; + } + } + if(i_ds == tray_ds->count) + { + /* + * The current input tray's medium size was not found in the + * discrete size list; mark the input tray medium entry + * invalid + */ + me->list[i_itm].input_tray = xpoid_none; + } + + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidTrayMediumListString + * + * Description: + * + * Creates a string representation of an XpOidTrayMediumList structure. + * + * Return value: + * + * A newly allocated + * + */ +char* XpOidTrayMediumListString(const XpOidTrayMediumList* me) +{ + int i; + int length; + char* str; + char* ptr; + XpOid tray; + /* + * allocate enough memory for the string representation, + * including intervening delimiters and whitespace + */ + for(i = 0, length = 0; i < XpOidTrayMediumListCount(me); i++) + { + tray = XpOidTrayMediumListTray(me, i); + if(xpoid_none != tray) + { + length += XpOidStringLength(tray); + length += XpOidStringLength(XpOidTrayMediumListMedium(me, i)); + length += 4; + } + } + str = XpOidMalloc(length+1); + /* + * format the list + */ + for(i = 0, ptr = str; i < XpOidTrayMediumListCount(me); i++) + { + tray = XpOidTrayMediumListTray(me, i); + if(xpoid_none != tray) + { +#if defined(sun) && !defined(SVR4) + sprintf(ptr, "{%s %s} ", + XpOidString(tray), + XpOidString(XpOidTrayMediumListMedium(me, i))); + ptr += strlen(ptr); +#else + ptr += sprintf(ptr, "{%s %s} ", + XpOidString(tray), + XpOidString(XpOidTrayMediumListMedium(me, i))); +#endif + } + } + /* + * chop trailing whitespace or terminate empty string + */ + str[length] = '\0'; + /* + * return + */ + return str; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidTrayMediumListHasTray + * + * Description: + * + * Determines if 'tray' is found in 'list'. + * + * Return value: + * + * xTrue if the tray is found in the list. + * + * xFalse if the tray is not in the list, or if 'list' is NULL. + * + */ +BOOL +XpOidTrayMediumListHasTray(const XpOidTrayMediumList* list, XpOid tray) +{ + int i; + if(list != (XpOidTrayMediumList*)NULL && tray != xpoid_none) + for(i = 0; i < list->count; i++) + if(XpOidTrayMediumListTray(list, i) == tray) + return xTrue; + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: ParseArea + * + * Description: + * + * Skips leading whitespace and parses out and returns a XpOidArea. + * + * Return value: + * + * xTrue if the XpOidArea was successfully parsed. ptr_return is + * updated to point to location where the parsing ended. + * + * xFalse if a XpOidArea was not found; ptr_return is updated + * to point to the first non-whitespace char in value_string. + * + */ +static BOOL +ParseArea(const char* value_string, + const char** ptr_return, + XpOidArea* area_return) +{ + const char* first_nonws_ptr; + const char* ptr; + /* + * skip leading whitespace + */ + first_nonws_ptr = value_string + SpanWhitespace(value_string); + /* + * parse out the area sequence start + */ + if(!ParseSeqStart(first_nonws_ptr, &ptr)) + goto ParseArea_error; + /* + * parse the minimum x value + */ + if(!ParseRealValue(ptr, &ptr, + area_return ? &area_return->minimum_x : NULL)) + goto ParseArea_error; + /* + * parse the maximum x value + */ + if(!ParseRealValue(ptr, &ptr, + area_return ? &area_return->maximum_x : NULL)) + goto ParseArea_error; + /* + * parse the minimum y value + */ + if(!ParseRealValue(ptr, &ptr, + area_return ? &area_return->minimum_y : NULL)) + goto ParseArea_error; + /* + * parse the maximum y value + */ + if(!ParseRealValue(ptr, &ptr, + area_return ? &area_return->maximum_y : NULL)) + goto ParseArea_error; + /* + * parse out the area sequence end + */ + if(!ParseSeqEnd(ptr, &ptr)) + goto ParseArea_error; + /* + * update the return pointer + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr; + /* + * return + */ + return xTrue; + + + ParseArea_error: + /* + * syntax error + */ + if(ptr_return != (const char**)NULL) + *ptr_return = first_nonws_ptr; + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: ParseRealRange + * + * Description: + * + * Skips leading whitespace and parses out and returns a + * XpOidRealRange. + * + * Return value: + * + * xTrue if the XpOidRealRange was successfully + * parsed. ptr_return is updated to point to location where the + * parsing ended. + * + * xFalse if a XpOidRealRange was not found; ptr_return is + * updated to point to the first non-whitespace char in value_string. + * + */ +static BOOL +ParseRealRange(const char* value_string, + const char** ptr_return, + XpOidRealRange* range_return) +{ + const char* first_nonws_ptr; + const char* ptr; + /* + * skip leading whitespace + */ + first_nonws_ptr = value_string + SpanWhitespace(value_string); + /* + * parse out the range sequence start + */ + if(!ParseSeqStart(first_nonws_ptr, &ptr)) + goto ParseRealRange_error; + /* + * parse the lower bound + */ + if(!ParseRealValue(ptr, &ptr, + range_return ? &range_return->lower_bound : NULL)) + goto ParseRealRange_error; + /* + * parse the upper bound + */ + if(!ParseRealValue(ptr, &ptr, + range_return ? &range_return->upper_bound : NULL)) + goto ParseRealRange_error; + /* + * parse out the range sequence end + */ + if(!ParseSeqEnd(ptr, &ptr)) + goto ParseRealRange_error; + /* + * update the return pointer + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr; + /* + * return + */ + return xTrue; + + + ParseRealRange_error: + /* + * syntax error + */ + if(ptr_return != (const char**)NULL) + *ptr_return = first_nonws_ptr; + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidNotifyParse + * + * Description: + * + * + * Return value: + * + * + */ +XpOidNotify XpOidNotifyParse(const char* value_string) +{ + const char* ptr = value_string; + + if(value_string == (const char*)NULL) + return XPOID_NOTIFY_NONE; + /* + * look for an event handling profile sequence start + */ + if(!ParseSeqStart(value_string, &ptr)) + { + if('\0' == *ptr) + /* + * empty value is valid + */ + return XPOID_NOTIFY_NONE; + else + return XPOID_NOTIFY_UNSUPPORTED; + } + /* + * look for an event set sequence start + */ + if(!ParseSeqStart(ptr, &ptr)) + { + /* + * check for an empty event handling profile + */ + if(ParseSeqEnd(ptr, &ptr)) + { + ptr += SpanWhitespace(ptr); + if(*ptr == '\0') + /* + * valid empty event handling profile sequence + */ + return XPOID_NOTIFY_NONE; + } + return XPOID_NOTIFY_UNSUPPORTED; + } + /* + * the only event in the set should be report job completed + */ + if(xpoid_val_event_report_job_completed != XpOidParse(ptr, &ptr)) + return XPOID_NOTIFY_UNSUPPORTED; + /* + * event set sequence end + */ + if(!ParseSeqEnd(ptr, &ptr)) + return XPOID_NOTIFY_UNSUPPORTED; + /* + * delivery method of electronic mail + */ + if(xpoid_val_delivery_method_electronic_mail != XpOidParse(ptr, &ptr)) + return XPOID_NOTIFY_UNSUPPORTED; + /* + * event handling profile sequence end + */ + if(!ParseSeqEnd(ptr, &ptr)) + return XPOID_NOTIFY_UNSUPPORTED; + /* + * end of value + */ + ptr += SpanWhitespace(ptr); + if('\0' == *ptr) + /* + * valid supported notification profile + */ + return XPOID_NOTIFY_EMAIL; + else + return XPOID_NOTIFY_UNSUPPORTED; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidNotifyString + * + * Description: + * + * + * Return value: + * + * + */ +const char* XpOidNotifyString(XpOidNotify notify) +{ + switch(notify) + { + case XPOID_NOTIFY_UNSUPPORTED: + return (const char*)NULL; + break; + case XPOID_NOTIFY_NONE: + return NOTIFY_NONE_STR; + break; + case XPOID_NOTIFY_EMAIL: + return NOTIFY_EMAIL_STR; + break; + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtNew + * + * Description: + * + * + * Return value: + * + * + */ +XpOidDocFmt* +XpOidDocFmtNew(const char* value_string) +{ + XpOidDocFmt* doc_fmt; + const char* ptr; + + if((const char*)NULL == value_string) + return (XpOidDocFmt*)NULL; + ptr = value_string + SpanWhitespace(value_string); + if('\0' == *ptr) + return (XpOidDocFmt*)NULL; + /* + * get the document format from the value string + */ + doc_fmt = (XpOidDocFmt*)XpOidCalloc(1, sizeof(XpOidDocFmt)); + if(xTrue == XpOidDocFmtNext(doc_fmt, ptr, &ptr)) + { + /* + * verify that the document format is the only value specified + */ + ptr += SpanWhitespace(ptr); + if('\0' == *ptr) + /* + * valid document-format value + */ + return doc_fmt; + } + /* + * invalid + */ + XpOidDocFmtDelete(doc_fmt); + ErrorF("%s\n", XPMSG_WARN_DOC_FMT); + return (XpOidDocFmt*)NULL; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtDelete + * + * Description: + * + * + * Return value: + * + * + */ +void +XpOidDocFmtDelete(XpOidDocFmt* doc_fmt) +{ + if((XpOidDocFmt*)NULL != doc_fmt) + { + XpOidFree(doc_fmt->format); + XpOidFree(doc_fmt->variant); + XpOidFree(doc_fmt->version); + XpOidFree(doc_fmt); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtString + * + * Description: + * + * + * Return value: + * + * + */ +char* +XpOidDocFmtString(XpOidDocFmt* doc_fmt) +{ + if((XpOidDocFmt*)NULL != doc_fmt) + { + if((char*)NULL != doc_fmt->format) + { + char* str = XpOidMalloc(1+SafeStrLen(doc_fmt->format)+ + 1+SafeStrLen(doc_fmt->variant)+ + 1+SafeStrLen(doc_fmt->version)+ + 1+1); + sprintf(str, "{%s %s %s}", doc_fmt->format, + (char*)NULL != doc_fmt->variant ? doc_fmt->variant : "", + (char*)NULL != doc_fmt->version ? doc_fmt->version : ""); + return str; + } + } + return (char*)NULL; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtNext + * + * Description: + * + * Assumes non-NULL value string. + * + * Return value: + * + * + */ +static BOOL +XpOidDocFmtNext(XpOidDocFmt* doc_fmt, + const char* value_string, + const char** ptr_return) +{ + const char* ptr; + const char* first_nonws_ptr; + const char* format; + const char* variant; + const char* version; + int format_len; + int variant_len; + int version_len; + /* + * skip leading whitespace + */ + ptr = value_string + SpanWhitespace(value_string); + first_nonws_ptr = ptr; + /* + * sequence start + */ + if(!ParseSeqStart(ptr, &ptr)) + goto XpOidDocFmtNext_error; + /* + * skip whitepace to the start of the document format, and save the + * location + */ + ptr += SpanWhitespace(ptr); + format = ptr; + /* + * document format + */ + if(0 == (format_len = SpanToken(ptr))) + goto XpOidDocFmtNext_error; + ptr += format_len; + /* + * optional variant + */ + ptr += SpanWhitespace(ptr); + variant = ptr; + if(0 != (variant_len = SpanToken(ptr))) + { + ptr += variant_len; + /* + * optional version + */ + ptr += SpanWhitespace(ptr); + version = ptr; + version_len = SpanToken(ptr); + ptr += version_len; + } + else + version_len = 0; + /* + * sequence end + */ + if(!ParseSeqEnd(ptr, &ptr)) + goto XpOidDocFmtNext_error; + /* + * update return pointer + */ + if((const char**)NULL != ptr_return) + *ptr_return = ptr; + /* + * update the passed document format struct + */ + memset(doc_fmt, 0, sizeof(XpOidDocFmt)); + doc_fmt->format = XpOidMalloc(format_len+1); + strncpy(doc_fmt->format, format, format_len); + doc_fmt->format[format_len] = '\0'; + if(0 < variant_len) + { + doc_fmt->variant = XpOidMalloc(variant_len+1); + strncpy(doc_fmt->variant, variant, variant_len); + doc_fmt->variant[variant_len] = '\0'; + if(0 < version_len) + { + doc_fmt->version = XpOidMalloc(version_len+1); + strncpy(doc_fmt->version, version, version_len); + doc_fmt->version[version_len] = '\0'; + } + } + return xTrue; + + XpOidDocFmtNext_error: + if((const char**)NULL != ptr_return) + *ptr_return = first_nonws_ptr; + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtListNew + * + * Description: + * + * + * Return value: + * + * + */ +XpOidDocFmtList* +XpOidDocFmtListNew(const char* value_string, + const XpOidDocFmtList* valid_fmts) +{ + if((char*)NULL != value_string) + { + const char* ptr; + return XpOidDocFmtListParse(value_string, valid_fmts, &ptr, 0); + } + return (XpOidDocFmtList*)NULL; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtListDelete + * + * Description: + * + * + * Return value: + * + * + */ +void +XpOidDocFmtListDelete(XpOidDocFmtList* list) +{ + if((XpOidDocFmtList*)NULL != list) + { + int i; + for(i = 0; i < list->count; i++) + { + XpOidFree(list->list[i].format); + XpOidFree(list->list[i].variant); + XpOidFree(list->list[i].version); + } + XpOidFree(list->list); + XpOidFree(list); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtListString + * + * Description: + * + * Assumes the passed structure is valid. + * + * Return value: + * + * + */ +char* +XpOidDocFmtListString(const XpOidDocFmtList* list) +{ + if((XpOidDocFmtList*)NULL != list) + { + if(0 < list->count) + { + int i; + int str_len; + char* str; + char* ptr; + /* + * allocate the return string + */ + for(i = 0, str_len = 0; i < list->count; i++) + { + str_len += + 1 + SafeStrLen(list->list[i].format) + + 1 + SafeStrLen(list->list[i].variant) + + 1 + SafeStrLen(list->list[i].version) + 2; + } + str = XpOidMalloc(str_len+1); + /* + * print the list into the string and return it + */ + ptr = str; + for(i = 0; i < list->count; i++) + { + XpOidDocFmt* df = &list->list[i]; + +#if defined(sun) && !defined(SVR4) + sprintf(ptr, "{%s %s %s} ", + df->format, + (char*)NULL != df->variant ? df->variant : "", + (char*)NULL != df->version ? df->version : ""); + ptr += strlen(ptr); +#else + ptr += + sprintf(ptr, "{%s %s %s} ", + df->format, + (char*)NULL != df->variant ? df->variant : "", + (char*)NULL != df->version ? df->version : ""); +#endif + } + return str; + } + } + return (char*)NULL; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtListParse + * + * Description: + * + * Assumes the passed value_string and ptr_return are non-NULL. + * + * Return value: + * + * + */ +static XpOidDocFmtList* +XpOidDocFmtListParse(const char* value_string, + const XpOidDocFmtList* valid_fmts, + const char** ptr_return, + int i) +{ + XpOidDocFmt doc_fmt; + XpOidDocFmtList* list; + BOOL status; + /* + * get the next document-format from the value string, skipping + * values not found in the passed list of valid formats + */ + *ptr_return = value_string; + while((status = XpOidDocFmtNext(&doc_fmt, *ptr_return, ptr_return)) + && + (const XpOidDocFmtList*)NULL != valid_fmts + && + !XpOidDocFmtListHasFmt(valid_fmts, &doc_fmt) + ); + + if(xFalse == status) + { + if('\0' == **ptr_return) + { + if(0 == i) + { + /* + * empty value string + */ + return (XpOidDocFmtList*)NULL; + } + else + { + /* + * done parsing; allocate the list and return + */ + list = + (XpOidDocFmtList*)XpOidCalloc(1, sizeof(XpOidDocFmtList)); + list->count = i; + list->list = (XpOidDocFmt*)XpOidCalloc(i, sizeof(XpOidDocFmt)); + return list; + } + } + else + { + /* + * invalid document format + */ + ErrorF("%s\n", XPMSG_WARN_DOCFMT_LIST); + return (XpOidDocFmtList*)NULL; + } + } + else + { + /* + * recurse to parse remaining document formats + */ + list = XpOidDocFmtListParse(*ptr_return, valid_fmts, ptr_return, i+1); + if((XpOidDocFmtList*)NULL != list) + { + /* + * add this doc fmt to the list + */ + list->list[i].format = doc_fmt.format; + list->list[i].variant = doc_fmt.variant; + list->list[i].version = doc_fmt.version; + } + return list; + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidDocFmtListHasFmt + * + * Description: + * + * Assumes the passed structure is valid. + * + * Return value: + * + * + */ +BOOL +XpOidDocFmtListHasFmt(const XpOidDocFmtList* list, + const XpOidDocFmt* fmt) +{ + int i; + if(list != (XpOidDocFmtList*)NULL + && + fmt != (XpOidDocFmt*)NULL + && + fmt->format != (char*)NULL + ) + { + for(i = 0; i < list->count; i++) + { + /* + * formats must match + */ + if(strcmp(fmt->format, list->list[i].format) != 0) + continue; + /* + * variants must both be NULL or match + */ + if(fmt->variant == (char*)NULL) + if(list->list[i].variant == (char*)NULL) + return xTrue; + else + continue; + if(list->list[i].variant == (char*)NULL) + continue; + if(strcmp(fmt->variant, list->list[i].variant) != 0) + continue; + /* + * versions must both be NULL or match + */ + if(fmt->version == (char*)NULL) + if(list->list[i].version == (char*)NULL) + return xTrue; + else + continue; + if(list->list[i].version == (char*)NULL) + continue; + if(strcmp(fmt->version, list->list[i].version) == 0) + return xTrue; + } + } + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidCardListNew + * + * Description: + * + * + * Return value: + * + * + */ +XpOidCardList* +XpOidCardListNew(const char* value_string, const XpOidCardList* valid_cards) +{ + if((const char*)NULL != value_string) + { + const char* ptr; + + return XpOidCardListParse(value_string, valid_cards, &ptr, 0); + } + else + return (XpOidCardList*)NULL; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidCardListDelete + * + * Description: + * + * + * Return value: + * + * + */ +void +XpOidCardListDelete(XpOidCardList* list) +{ + if((XpOidCardList*)NULL != list) + { + XpOidFree(list->list); + XpOidFree(list); + } +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidCardListString + * + * Description: + * + * + * Return value: + * + * + */ +char* +XpOidCardListString(const XpOidCardList* list) +{ + if((XpOidCardList*)NULL != list) + { + char buf[48]; + int str_len; + char* str; + int i; + char* ptr; + /* + * allocate the output string + */ + for(i = 0, str_len = 0; i < list->count; i++) +#if defined(sun) && !defined(SVR4) + { + sprintf(buf, "%lu", list->list[i]) + 1; + str_len += strlen(buf); + } +#else + str_len += sprintf(buf, "%lu", list->list[i]) + 1; +#endif + str = XpOidMalloc(str_len+1); + /* + * write the list to the string + */ + for(i = 0, ptr = str; i < list->count; i++) +#if defined(sun) && !defined(SVR4) + { + sprintf(ptr, "%lu ", list->list[i]); + ptr += strlen(ptr); + } +#else + ptr += sprintf(ptr, "%lu ", list->list[i]); +#endif + return str; + } + else + return (char*)NULL; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidCardListHasCard + * + * Description: + * + * Determines if 'card' is an element of 'list'. + * + * Return value: + * + * xTrue if the card is found in the list. + * + * xFalse if the card is not in the list, or if 'list' is NULL. + * + */ +BOOL +XpOidCardListHasCard(const XpOidCardList* list, unsigned long card) +{ + int i; + if(list != (XpOidCardList*)NULL) + for(i = 0; i < list->count; i++) + if(list->list[i] == card) + return xTrue; + return xFalse; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidCardListParse + * + * Description: + * + * Assumes the passed value_string and ptr_return are non-NULL. + * + * Return value: + * + * + */ +static XpOidCardList* +XpOidCardListParse(const char* value_string, + const XpOidCardList* valid_cards, + const char** ptr_return, + int i) +{ + unsigned long card; + XpOidCardList* list; + BOOL status; + + /* + * get the next card from the value string, skipping values not + * found in the passed list of valid cards + */ + *ptr_return = value_string; + while((status = XpOidParseUnsignedValue(*ptr_return, ptr_return, &card)) + && + (const XpOidCardList*)NULL != valid_cards + && + !XpOidCardListHasCard(valid_cards, card) + ); + + if(xFalse == status) + { + if('\0' == **ptr_return) + { + if(0 == i) + { + /* + * empty value string + */ + return (XpOidCardList*)NULL; + } + else + { + /* + * done parsing; allocate the list and return + */ + list = (XpOidCardList*)XpOidCalloc(1, sizeof(XpOidCardList)); + list->count = i; + list->list = + (unsigned long*)XpOidCalloc(i, sizeof(unsigned long)); + return list; + } + } + else + { + /* + * parsing error + */ + ErrorF("%s\n", XPMSG_WARN_CARD_LIST); + return (XpOidCardList*)NULL; + } + } + else + { + /* + * recurse to parse remaining cardinal values + */ + list = XpOidCardListParse(*ptr_return, valid_cards, ptr_return, i+1); + if((XpOidCardList*)NULL != list) + { + /* + * add this value to the list + */ + list->list[i] = card; + } + return list; + } +} + +/* + * ------------------------------------------------------------------------ + * Name: ParseBoolValue + * + * Description: + * + * + * Return value: + * + * + */ +static BOOL +ParseBoolValue(const char* value_string, + const char** ptr_return, + BOOL* bool_return) +{ + const char* ptr; + int length; + BOOL status; + /* + * skip leading whitespace + */ + ptr = value_string + SpanWhitespace(value_string); + /* + * get the whitespace-delimited token length + */ + length = SpanToken(ptr); + /* + * determine if true or false or bad + */ + if(StrnCaseCmp(ptr, "TRUE", length) == 0) + { + if(bool_return != (BOOL*)NULL) + *bool_return = xTrue; + status = xTrue; + } + else if(StrnCaseCmp(ptr, "FALSE", length) == 0) + { + if(bool_return != (BOOL*)NULL) + *bool_return = xFalse; + status = xTrue; + } + else + { + /* + * syntax error + */ + status = xFalse; + } + /* + * update the return pointer and return + */ + if(ptr_return != (const char**)NULL) + *ptr_return = status ? ptr+length : ptr; + return status; +} + +/* + * ------------------------------------------------------------------------ + * Name: XpOidParseUnsignedValue + * + * Description: + * + * Skips leading whitespace and parses out and returns a unsigned number. + * + * Return value: + * + * xTrue if a unsigned number was successfully parsed. ptr_return is + * updated to point to location where the unsigned number parsing + * ended. + * + * xFalse if a unsigned number was not found; ptr_return is updated + * to point to the first non-whitespace char in value_string. + * + */ +BOOL +XpOidParseUnsignedValue(const char* value_string, + const char** ptr_return, + unsigned long* unsigned_return) +{ + long value; + BOOL status; + const char* first_nonws_ptr; + const char* ptr; + /* + * skip leading whitespace + */ + first_nonws_ptr = value_string + SpanWhitespace(value_string); + value = strtol(first_nonws_ptr, (char**)(&ptr), 0); + if(ptr == first_nonws_ptr || value < 0) + status = xFalse; + else + status = xTrue; + /* + * update return parms + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr; + if(unsigned_return != (unsigned long*)NULL) + *unsigned_return = (unsigned long)value; + /* + * return + */ + return status; +} + +/* + * ------------------------------------------------------------------------ + * Name: ParseRealValue + * + * Description: + * + * Skips leading whitespace and parses out and returns a real number. + * + * Return value: + * + * xTrue if a real number was successfully parsed. ptr_return is + * updated to point to location where the real number parsing + * ended. + * + * xFalse if a real number was not found; ptr_return is updated + * to point to the first non-whitespace char in value_string. + * + */ +static BOOL +ParseRealValue(const char* value_string, + const char** ptr_return, + float* real_return) +{ + float real_value; + BOOL status; + const char* first_nonws_ptr; + const char* ptr; + /* + * skip leading whitespace + */ + first_nonws_ptr = value_string + SpanWhitespace(value_string); + real_value = (float)strtod(first_nonws_ptr, (char**)(&ptr)); + if(ptr == first_nonws_ptr) + status = xFalse; + else + status = xTrue; + /* + * update return parms + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr; + if(real_return != (float*)NULL) + *real_return = real_value; + /* + * return + */ + return status; +} + +/* + * ------------------------------------------------------------------------ + * Name: ParseSeqEnd + * + * Description: + * + * Description: + * + * Skips leading whitespace and parses out the sequence end + * character '}'. + * + * Return value: + * + * xTrue if the sequence end character was parsed; ptr_return is + * updated to point to the first char following the sequence end + * character. + * + * xFalse if the sequence end character was not found; ptr_return is + * updated to point to the first non-whitespace char in value_string. + * + */ +static BOOL +ParseSeqEnd(const char* value_string, + const char** ptr_return) +{ + const char* ptr; + BOOL status; + /* + * skip leading whitespace + */ + ptr = value_string + SpanWhitespace(value_string); + /* + * parse out the sequence end character + */ + if(*ptr == '}') + { + status = xTrue; + ++ptr; + } + else + status = xFalse; + /* + * update the return pointer + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr; + /* + * return + */ + return status; +} + +/* + * ------------------------------------------------------------------------ + * Name: ParseSeqStart + * + * Description: + * + * Skips leading whitespace and parses out the sequence start + * character '{'. + * + * Return value: + * + * xTrue if the sequence start character was parsed; ptr_return is + * updated to point to the first char following the sequence start + * character. + * + * xFalse if the sequence start character was not found; ptr_return is + * updated to point to the first non-whitespace char in value_string. + * + */ +static BOOL +ParseSeqStart(const char* value_string, + const char** ptr_return) +{ + const char* ptr; + BOOL status; + /* + * skip leading whitespace + */ + ptr = value_string + SpanWhitespace(value_string); + /* + * parse out the sequence start character + */ + if(*ptr == '{') + { + status = xTrue; + ++ptr; + } + else + status = xFalse; + /* + * update the return pointer + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr; + /* + * return + */ + return status; +} + +/* + * ------------------------------------------------------------------------ + * Name: ParseUnspecifiedValue + * + * Description: + * + * Skips leading whitespace and parses out an unspecified optional + * value (i.e. matching '' or "" - skips all data between the set of + * quotes). + * + * Return value: + * + * xTrue if an unspecified value was parsed; ptr_return is updated to + * point to the first char following the trailing quote. + * + * xFalse if an unspecified value was not found; ptr_return is updated + * to point to the first non-whitespace char in value_string. + * + */ +static BOOL +ParseUnspecifiedValue(const char* value_string, + const char** ptr_return) +{ + BOOL status; + const char* ptr; + /* + * skip leading whitespace + */ + ptr = value_string + SpanWhitespace(value_string); + /* + * parse out an unspecified optional value ('' or "") + */ + if(*ptr == '\'' || *ptr == '"') + { + char delim[2]; + + if(ptr_return != (const char**)NULL) + { + delim[0] = *ptr; + delim[1] = '\0'; + /* + * skip over the matching delimiter + */ + ++ptr; + ptr += strcspn(ptr, delim); + if(*ptr != '\0') + ++ptr; + } + status = xTrue; + } + else + status = xFalse; + /* + * update the return pointer + */ + if(ptr_return != (const char**)NULL) + *ptr_return = ptr; + /* + * return + */ + return status; +} + +/* + * ------------------------------------------------------------------------ + * Name: SpanToken + * + * Description: + * + * Returns the length of the initial segment of the passed string + * that consists entirely of non-whitespace and non-sequence + * delimiter characters. + * + * + */ +static int +SpanToken(const char* string) +{ + const char* ptr; + for(ptr = string; + *ptr != '\0' && !isspace(*ptr) && *ptr != '{' && *ptr != '}'; + ++ptr); + return ptr - string; +} + +/* + * ------------------------------------------------------------------------ + * Name: SpanWhitespace + * + * Description: + * + * Returns the length of the initial segment of the passed string + * that consists entirely of whitespace characters. + * + * + */ +static int +SpanWhitespace(const char* string) +{ + const char* ptr; + for(ptr = string; *ptr != '\0' && isspace(*ptr); ++ptr); + return ptr - string; +} + +#ifndef HAVE_STRCASECMP +/* + * ------------------------------------------------------------------------ + * Name: StrnCaseCmp + * + * Description: + * + * Implements strncasecmp() for those platforms that need it. + * + * + */ +static int +StrnCaseCmp(const char *s1, const char *s2, size_t len) +{ + char c1, c2; + int result; + + while (len--) + { + c1 = *s1++; + c2 = *s2++; + result = tolower(c1) - tolower(c2); + + if (result != 0) + return result; + } + + return 0; +} +#endif diff --git a/Xprint/Oid.h b/Xprint/Oid.h new file mode 100644 index 000000000..70bd8d3e5 --- /dev/null +++ b/Xprint/Oid.h @@ -0,0 +1,289 @@ +/* $Xorg: Oid.h,v 1.3 2000/08/17 19:48:06 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#ifndef _Xp_Oid_h +#define _Xp_Oid_h + +#include + +/* + * include the auto-generated XpOid enum definition + */ +#include "OidDefs.h" + +/* + * messages + */ +#define XPMSG_WARN_MSS "Syntax error parsing medium-source-sizes" +#define XPMSG_WARN_ITM "Syntax error parsing input-trays-medium" +#define XPMSG_WARN_DOC_FMT "Syntax error parsing document format" +#define XPMSG_WARN_DOCFMT_LIST "Syntax error parsing document format list" +#define XPMSG_WARN_CARD_LIST "Syntax error parsing cardinal list" + +/* + * macros for memory allocation + */ +#define XpOidMalloc(size) ((char*)Xalloc((unsigned long)(size))) +#define XpOidCalloc(count, size) \ + ((char*)Xcalloc((unsigned long)((count)*(size)))) +#define XpOidFree(mem) (Xfree((unsigned long*)(mem))) + +/* + * list of object identifiers + */ +typedef struct _XpOidList +{ + XpOid* list; + int count; +} XpOidList; + +/* + * linked list of object identifiers + */ +typedef struct XpOidNodeStruct +{ + XpOid oid; + struct XpOidNodeStruct* next; +} *XpOidNode; + +typedef struct _XpOidLinkedList +{ + XpOidNode head; + XpOidNode tail; + XpOidNode current; + int count; +} XpOidLinkedList; + +/* + * XpOidMediumSourceSize and related definitions + */ +typedef struct +{ + float minimum_x; + float maximum_x; + float minimum_y; + float maximum_y; +} XpOidArea; + +typedef struct +{ + float lower_bound; + float upper_bound; +} XpOidRealRange; + +typedef struct +{ + XpOidRealRange range_across_feed; + float increment_across_feed; + XpOidRealRange range_in_feed; + float increment_in_feed; + BOOL long_edge_feeds; + XpOidArea assured_reproduction_area; +} XpOidMediumContinuousSize; + +typedef struct +{ + XpOid page_size; + BOOL long_edge_feeds; + XpOidArea assured_reproduction_area; +} XpOidMediumDiscreteSize; + +typedef struct +{ + XpOidMediumDiscreteSize* list; + int count; +} XpOidMediumDiscreteSizeList; + +typedef struct +{ + XpOid input_tray; /* may be set to xpoid_none or xpoid_unspecified */ + enum { XpOidMediumSS_DISCRETE, XpOidMediumSS_CONTINUOUS } mstag; + union + { + XpOidMediumDiscreteSizeList* discrete; + XpOidMediumContinuousSize* continuous_size; + } ms; /* "ms" is short for medium-size */ + +} XpOidMediumSourceSize; + +typedef struct +{ + XpOidMediumSourceSize* mss; + int count; +} XpOidMediumSS; + + +typedef struct +{ + XpOid input_tray; /* may be set to xpoid_none */ + XpOid medium; +} XpOidTrayMedium; + +typedef struct +{ + XpOidTrayMedium* list; + int count; +} XpOidTrayMediumList; + +typedef enum { + XPOID_NOTIFY_UNSUPPORTED, + XPOID_NOTIFY_NONE, + XPOID_NOTIFY_EMAIL +} XpOidNotify; + +typedef struct +{ + unsigned long *list; + int count; +} XpOidCardList; + +typedef struct +{ + char* format; + char* variant; + char* version; +} XpOidDocFmt; + +typedef struct +{ + XpOidDocFmt* list; + int count; +} XpOidDocFmtList; + + +/* + * XpOid public methods + */ +const char* XpOidString(XpOid); +int XpOidStringLength(XpOid); +XpOid XpOidFromString(const char* value); + +/* + * XpOidList public methods + */ +XpOidList* XpOidListNew(const char* value_string, + const XpOidList* valid_oids); +#define XpOidListInit(l, a, c) { (l)->list = (a); (l)->count = (c); } +void XpOidListDelete(XpOidList*); +#define XpOidListCount(l) ((l) ? (l)->count : 0) +#define XpOidListGetOid(l, i) ((l) ? (l)->list[(i)] : xpoid_none) +int XpOidListGetIndex(const XpOidList* list, XpOid oid); +BOOL XpOidListHasOid(const XpOidList* list, XpOid oid); +char* XpOidListString(const XpOidList*); + + +/* + * XpOidLinkedList public methods + */ +XpOidLinkedList* XpOidLinkedListNew(); +void XpOidLinkedListDelete(XpOidLinkedList*); +#define XpOidLinkedListCount(l) ((l) ? (l)->count : 0) +XpOid XpOidLinkedListGetOid(XpOidLinkedList* list, int i); +void XpOidLinkedListAddOid(XpOidLinkedList* list, XpOid oid); +int XpOidLinkedListGetIndex(XpOidLinkedList* list, XpOid oid); +BOOL XpOidLinkedListHasOid(XpOidLinkedList* list, + XpOid oid); +XpOid XpOidLinkedListFirstOid(XpOidLinkedList* list); +XpOid XpOidLinkedListNextOid(XpOidLinkedList* list); + +/* + * XpOidMediumSourceSize public methods + */ +XpOidMediumSS* XpOidMediumSSNew(const char* value_string, + const XpOidList* valid_trays, + const XpOidList* valid_medium_sizes); +void XpOidMediumSSDelete(XpOidMediumSS*); +#define XpOidMediumSSCount(me) ((me) ? (me)->count : 0) +BOOL XpOidMediumSSHasSize(XpOidMediumSS*, XpOid medium_size); +char* XpOidMediumSSString(const XpOidMediumSS*); + +/* + * XpOidTrayMediumList public methods + */ +XpOidTrayMediumList* XpOidTrayMediumListNew(const char* value_string, + const XpOidList* valid_trays, + const XpOidMediumSS* msss); +void XpOidTrayMediumListDelete(XpOidTrayMediumList* me); +#define XpOidTrayMediumListCount(me) ((me) ? (me)->count : 0) +#define XpOidTrayMediumListTray(me, i) \ + ((me) ? (me)->list[(i)].input_tray : xpoid_none) +#define XpOidTrayMediumListMedium(me, i) \ + ((me) ? (me)->list[(i)].medium : xpoid_none) +char* XpOidTrayMediumListString(const XpOidTrayMediumList*); + +/* + * XpOidNotify public methods + */ +XpOidNotify XpOidNotifyParse(const char* value_string); +const char* XpOidNotifyString(XpOidNotify notify); + +/* + * XpOidDocFmt public methods + */ +XpOidDocFmt* XpOidDocFmtNew(const char* value_string); +void XpOidDocFmtDelete(XpOidDocFmt*); +char* XpOidDocFmtString(XpOidDocFmt*); + +/* + * XpOidDocFmtList public methods + */ +XpOidDocFmtList* XpOidDocFmtListNew(const char* value_string, + const XpOidDocFmtList* valid_fmts); +void XpOidDocFmtListDelete(XpOidDocFmtList*); +char* XpOidDocFmtListString(const XpOidDocFmtList*); +#define XpOidDocFmtListCount(me) ((me) ? (me)->count : 0) +#define XpOidDocFmtListGetDocFmt(me, i) \ + ((me) ? &(me)->list[(i)] : (XpDocFmt*)NULL) +BOOL XpOidDocFmtListHasFmt(const XpOidDocFmtList* list, + const XpOidDocFmt* fmt); +/* + * XpOidCardList public methods + */ +XpOidCardList* XpOidCardListNew(const char* value_string, + const XpOidCardList* valid_cards); +#define XpOidCardListInit(l, a, c) { (l)->list = (a); (l)->count = (c); } +void XpOidCardListDelete(XpOidCardList*); +char* XpOidCardListString(const XpOidCardList*); +#define XpOidCardListCount(me) ((me) ? (me)->count : 0) +#define XpOidCardListGetCard(me, i) ((me) ? (me)->list[(i)] : 0) +BOOL XpOidCardListHasCard(const XpOidCardList*, unsigned long); + +/* + * misc parsing functions + */ +BOOL XpOidParseUnsignedValue(const char* value_string, + const char** ptr_return, + unsigned long* unsigned_return); + + +#endif /* _Xp_Oid_h - don't add anything after this line */ diff --git a/Xprint/OidDefs.h b/Xprint/OidDefs.h new file mode 100644 index 000000000..03e530cb2 --- /dev/null +++ b/Xprint/OidDefs.h @@ -0,0 +1,163 @@ +/* $Xorg: OidDefs.h,v 1.4 2001/03/14 18:45:13 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/* This is an automatically-generated file. Do not edit. */ + +typedef enum { + xpoid_none, + xpoid_unspecified, + xpoid_att_descriptor, + xpoid_att_content_orientation, + xpoid_att_copy_count, + xpoid_att_default_printer_resolution, + xpoid_att_default_input_tray, + xpoid_att_default_medium, + xpoid_att_document_format, + xpoid_att_plex, + xpoid_att_xp_listfonts_modes, + xpoid_att_job_name, + xpoid_att_job_owner, + xpoid_att_notification_profile, + xpoid_att_xp_setup_state, + xpoid_att_xp_spooler_command_options, + xpoid_att_content_orientations_supported, + xpoid_att_document_formats_supported, + xpoid_att_dt_pdm_command, + xpoid_att_input_trays_medium, + xpoid_att_medium_source_sizes_supported, + xpoid_att_plexes_supported, + xpoid_att_printer_model, + xpoid_att_printer_name, + xpoid_att_printer_resolutions_supported, + xpoid_att_xp_embedded_formats_supported, + xpoid_att_xp_listfonts_modes_supported, + xpoid_att_xp_page_attributes_supported, + xpoid_att_xp_raw_formats_supported, + xpoid_att_xp_setup_proviso, + xpoid_att_document_attributes_supported, + xpoid_att_job_attributes_supported, + xpoid_att_locale, + xpoid_att_multiple_documents_supported, + xpoid_att_available_compression, + xpoid_att_available_compressions_supported, + xpoid_val_content_orientation_portrait, + xpoid_val_content_orientation_landscape, + xpoid_val_content_orientation_reverse_portrait, + xpoid_val_content_orientation_reverse_landscape, + xpoid_val_medium_size_iso_a0, + xpoid_val_medium_size_iso_a1, + xpoid_val_medium_size_iso_a2, + xpoid_val_medium_size_iso_a3, + xpoid_val_medium_size_iso_a4, + xpoid_val_medium_size_iso_a5, + xpoid_val_medium_size_iso_a6, + xpoid_val_medium_size_iso_a7, + xpoid_val_medium_size_iso_a8, + xpoid_val_medium_size_iso_a9, + xpoid_val_medium_size_iso_a10, + xpoid_val_medium_size_iso_b0, + xpoid_val_medium_size_iso_b1, + xpoid_val_medium_size_iso_b2, + xpoid_val_medium_size_iso_b3, + xpoid_val_medium_size_iso_b4, + xpoid_val_medium_size_iso_b5, + xpoid_val_medium_size_iso_b6, + xpoid_val_medium_size_iso_b7, + xpoid_val_medium_size_iso_b8, + xpoid_val_medium_size_iso_b9, + xpoid_val_medium_size_iso_b10, + xpoid_val_medium_size_na_letter, + xpoid_val_medium_size_na_legal, + xpoid_val_medium_size_executive, + xpoid_val_medium_size_folio, + xpoid_val_medium_size_invoice, + xpoid_val_medium_size_ledger, + xpoid_val_medium_size_quarto, + xpoid_val_medium_size_iso_c3, + xpoid_val_medium_size_iso_c4, + xpoid_val_medium_size_iso_c5, + xpoid_val_medium_size_iso_c6, + xpoid_val_medium_size_iso_designated_long, + xpoid_val_medium_size_na_10x13_envelope, + xpoid_val_medium_size_na_9x12_envelope, + xpoid_val_medium_size_na_number_10_envelope, + xpoid_val_medium_size_na_7x9_envelope, + xpoid_val_medium_size_na_9x11_envelope, + xpoid_val_medium_size_na_10x14_envelope, + xpoid_val_medium_size_na_number_9_envelope, + xpoid_val_medium_size_na_6x9_envelope, + xpoid_val_medium_size_na_10x15_envelope, + xpoid_val_medium_size_monarch_envelope, + xpoid_val_medium_size_a, + xpoid_val_medium_size_b, + xpoid_val_medium_size_c, + xpoid_val_medium_size_d, + xpoid_val_medium_size_e, + xpoid_val_medium_size_jis_b0, + xpoid_val_medium_size_jis_b1, + xpoid_val_medium_size_jis_b2, + xpoid_val_medium_size_jis_b3, + xpoid_val_medium_size_jis_b4, + xpoid_val_medium_size_jis_b5, + xpoid_val_medium_size_jis_b6, + xpoid_val_medium_size_jis_b7, + xpoid_val_medium_size_jis_b8, + xpoid_val_medium_size_jis_b9, + xpoid_val_medium_size_jis_b10, + xpoid_val_plex_simplex, + xpoid_val_plex_duplex, + xpoid_val_plex_tumble, + xpoid_val_input_tray_top, + xpoid_val_input_tray_middle, + xpoid_val_input_tray_bottom, + xpoid_val_input_tray_envelope, + xpoid_val_input_tray_manual, + xpoid_val_input_tray_large_capacity, + xpoid_val_input_tray_main, + xpoid_val_input_tray_side, + xpoid_val_event_report_job_completed, + xpoid_val_delivery_method_electronic_mail, + xpoid_val_xp_setup_mandatory, + xpoid_val_xp_setup_optional, + xpoid_val_xp_setup_ok, + xpoid_val_xp_setup_incomplete, + xpoid_val_xp_list_glyph_fonts, + xpoid_val_xp_list_internal_printer_fonts, + xpoid_val_available_compressions_0, + xpoid_val_available_compressions_01, + xpoid_val_available_compressions_02, + xpoid_val_available_compressions_03, + xpoid_val_available_compressions_012, + xpoid_val_available_compressions_013, + xpoid_val_available_compressions_023, + xpoid_val_available_compressions_0123 +} XpOid; diff --git a/Xprint/OidStrs.h b/Xprint/OidStrs.h new file mode 100644 index 000000000..81119378c --- /dev/null +++ b/Xprint/OidStrs.h @@ -0,0 +1,165 @@ +/* $Xorg: OidStrs.h,v 1.4 2001/03/14 18:45:40 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/* This is an automatically-generated file. Do not edit. */ + +static int XpOidStringMapCount = 127; + +static const XpOidStringMapEntry XpOidStringMap[] = { + { "", 0 }, + { "", 0 }, + { "descriptor", 10 }, + { "content-orientation", 19 }, + { "copy-count", 10 }, + { "default-printer-resolution", 26 }, + { "default-input-tray", 18 }, + { "default-medium", 14 }, + { "document-format", 15 }, + { "plex", 4 }, + { "xp-listfonts-modes", 18 }, + { "job-name", 8 }, + { "job-owner", 9 }, + { "notification-profile", 20 }, + { "xp-setup-state", 14 }, + { "xp-spooler-command-options", 26 }, + { "content-orientations-supported", 30 }, + { "document-formats-supported", 26 }, + { "dt-pdm-command", 14 }, + { "input-trays-medium", 18 }, + { "medium-source-sizes-supported", 29 }, + { "plexes-supported", 16 }, + { "printer-model", 13 }, + { "printer-name", 12 }, + { "printer-resolutions-supported", 29 }, + { "xp-embedded-formats-supported", 29 }, + { "xp-listfonts-modes-supported", 28 }, + { "xp-page-attributes-supported", 28 }, + { "xp-raw-formats-supported", 24 }, + { "xp-setup-proviso", 16 }, + { "document-attributes-supported", 29 }, + { "job-attributes-supported", 24 }, + { "locale", 6 }, + { "multiple-documents-supported", 28 }, + { "available-compression", 21 }, + { "available-compressions-supported", 32 }, + { "portrait", 8 }, + { "landscape", 9 }, + { "reverse-portrait", 16 }, + { "reverse-landscape", 17 }, + { "iso-a0", 6 }, + { "iso-a1", 6 }, + { "iso-a2", 6 }, + { "iso-a3", 6 }, + { "iso-a4", 6 }, + { "iso-a5", 6 }, + { "iso-a6", 6 }, + { "iso-a7", 6 }, + { "iso-a8", 6 }, + { "iso-a9", 6 }, + { "iso-a10", 7 }, + { "iso-b0", 6 }, + { "iso-b1", 6 }, + { "iso-b2", 6 }, + { "iso-b3", 6 }, + { "iso-b4", 6 }, + { "iso-b5", 6 }, + { "iso-b6", 6 }, + { "iso-b7", 6 }, + { "iso-b8", 6 }, + { "iso-b9", 6 }, + { "iso-b10", 7 }, + { "na-letter", 9 }, + { "na-legal", 8 }, + { "executive", 9 }, + { "folio", 5 }, + { "invoice", 7 }, + { "ledger", 6 }, + { "quarto", 6 }, + { "iso-c3", 6 }, + { "iso-c4", 6 }, + { "iso-c5", 6 }, + { "iso-c6", 6 }, + { "iso-designated-long", 19 }, + { "na-10x13-envelope", 17 }, + { "na-9x12-envelope", 16 }, + { "na-number-10-envelope", 21 }, + { "na-7x9-envelope", 15 }, + { "na-9x11-envelope", 16 }, + { "na-10x14-envelope", 17 }, + { "na-number-9-envelope", 20 }, + { "na-6x9-envelope", 15 }, + { "na-10x15-envelope", 17 }, + { "monarch-envelope", 16 }, + { "a", 1 }, + { "b", 1 }, + { "c", 1 }, + { "d", 1 }, + { "e", 1 }, + { "jis-b0", 6 }, + { "jis-b1", 6 }, + { "jis-b2", 6 }, + { "jis-b3", 6 }, + { "jis-b4", 6 }, + { "jis-b5", 6 }, + { "jis-b6", 6 }, + { "jis-b7", 6 }, + { "jis-b8", 6 }, + { "jis-b9", 6 }, + { "jis-b10", 7 }, + { "simplex", 7 }, + { "duplex", 6 }, + { "tumble", 6 }, + { "top", 3 }, + { "middle", 6 }, + { "bottom", 6 }, + { "envelope", 8 }, + { "manual", 6 }, + { "large-capacity", 14 }, + { "main", 4 }, + { "side", 4 }, + { "event-report-job-completed", 26 }, + { "electronic-mail", 15 }, + { "xp-setup-mandatory", 18 }, + { "xp-setup-optional", 17 }, + { "xp-setup-ok", 11 }, + { "xp-setup-incomplete", 19 }, + { "xp-list-glyph-fonts", 19 }, + { "xp-list-internal-printer-fonts", 30 }, + { "0", 1 }, + { "01", 2 }, + { "02", 2 }, + { "03", 2 }, + { "012", 3 }, + { "013", 3 }, + { "023", 3 }, + { "0123", 4 } +}; diff --git a/Xprint/Util.c b/Xprint/Util.c new file mode 100644 index 000000000..efc196f82 --- /dev/null +++ b/Xprint/Util.c @@ -0,0 +1,360 @@ +/* $Xorg: Util.c,v 1.3 2000/08/17 19:48:06 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +#include "Xos.h" /* for unistd.h and string.h */ +#include +#include +#include +#include "dixstruct.h" +#include "scrnintstr.h" +#include "misc.h" + +#define _XP_PRINT_SERVER_ +#include "extensions/Print.h" +#include "extensions/Printstr.h" +#undef _XP_PRINT_SERVER_ + +#define IN_FILE_STRING "%(InFile)%" +#define OUT_FILE_STRING "%(OutFile)%" + +/* + * ReplaceAnyString returns a string combining the input strings. + * It replaces all occurances of 'target' with the supplied + * 'replacement'. + * The original input string will generally be freed, + * and the caller is responsible for freeing whatever string is returned. + */ +char * +ReplaceAnyString( + char *string, + char *target, + char *replacement) +{ + char *pKeyString; + + if(replacement != (char *)NULL) + { + while((pKeyString = strstr(string, target)) != (char *)NULL) + { + char *newString; + + newString = (char *)xalloc(strlen(string) + strlen(replacement) - + strlen(target) + 1); + strncpy(newString, string, pKeyString - string); + newString[pKeyString - string] = '\0'; + strcat(newString, replacement); + strcat(newString, pKeyString + strlen(target)); + xfree(string); + string = newString; + } + } + + return string; +} + +/* + * ReplaceFileString returns a string combining the input strings. + * It replaces all occurances of IN_FILE_STRING with the supplied + * inFileName, and all occurances of OUT_FILE_STRING with the + * supplied outFileName. The original input string will generally be freed, + * and the caller is responsible for freeing whatever string is returned. + */ +char * +ReplaceFileString(string, inFileName, outFileName) + char *string; + char *inFileName; + char *outFileName; +{ + char *pKeyString, + *pInFileString = IN_FILE_STRING, + *pOutFileString = OUT_FILE_STRING; + + if(inFileName != (char *)NULL) + { + while((pKeyString = strstr(string, pInFileString)) != + (char *)NULL) + { + char *newString; + + newString = (char *)xalloc(strlen(string) + + strlen(inFileName) + 1); + strncpy(newString, string, pKeyString - string); + newString[pKeyString - string] = '\0'; + strcat(newString, inFileName); + strcat(newString, pKeyString + strlen(pInFileString)); + xfree(string); + string = newString; + } + } + + if(outFileName != (char *)NULL) + { + while((pKeyString = strstr(string, pOutFileString)) != + (char *)NULL) + { + char *newString; + + newString = (char *)xalloc(strlen(string) + + strlen(outFileName) + 1); + strncpy(newString, string, pKeyString - string); + newString[pKeyString - string] = '\0'; + strcat(newString, outFileName); + strcat(newString, pKeyString + strlen(pOutFileString)); + xfree(string); + string = newString; + } + } + return string; +} + +/* + * ExecCommand takes two character pointers - the command to execute, + * and the "argv" style NULL-terminated vector of arguments for the command. + * We wait for the command to terminate before continuing to ensure that + * we don't delete the job file before the spooler has made a copy. + */ +void +ExecCommand(pCommand, argVector) + char *pCommand; + char **argVector; +{ + pid_t childPid; + int status; + + if((childPid = fork()) == 0) + { + execv(pCommand, argVector); + } + else + { + (void) waitpid(childPid, &status, 0); + } + return; +} + +/* + * TransferBytes reads numBytes of data from pSrcFile and writes them + * to pDstFile. It returns the number of bytes actually transfered, + * which will be numBytes if it's successful. Neither pSrcFile nor + * pDstFile are rewound or their pointers otherwise modified prior to + * beginning the transfer. + */ +int +TransferBytes(pSrcFile, pDstFile, numBytes) + FILE *pSrcFile, + *pDstFile; + int numBytes; +{ + char buf[10240]; + int bytesWritten = 0, bytesToXfer; + + for(bytesToXfer = min(sizeof(buf)*sizeof(char), numBytes); + bytesToXfer > 0; + bytesToXfer = min(sizeof(buf)*sizeof(char), numBytes - bytesWritten)) + { + if(fread((void *)buf, (size_t) 1, bytesToXfer, pSrcFile) < bytesToXfer) + return bytesWritten; + if(fwrite((void *)buf, (size_t) 1, bytesToXfer, pDstFile) < bytesToXfer) + return bytesWritten; + bytesWritten += bytesToXfer; + } + return bytesWritten; +} + +/* + * CopyContentsAndDelete - does the work of copying and deleting the + * pre, no, and post raster files as well as the raster file itself. + */ +Bool +CopyContentsAndDelete(ppSrcFile, pSrcFileName, pDstFile) + FILE **ppSrcFile, + *pDstFile; + char **pSrcFileName; +{ + struct stat statBuf; + + if(stat(*pSrcFileName, &statBuf) < 0) + return FALSE; + rewind(*ppSrcFile); + if(TransferBytes(*ppSrcFile, pDstFile, + (int)statBuf.st_size) != (int)statBuf.st_size) + return FALSE; + fclose(*ppSrcFile); + *ppSrcFile = (FILE *)NULL; + unlink(*pSrcFileName); + xfree(*pSrcFileName); + *pSrcFileName = (char *)NULL; + + return TRUE; +} + + +#define QUADPAD(x) ((((x)+3)>>2)<<2) + +int +XpSendDocumentData( + ClientPtr client, + FILE *fp, + int fileLen, + int maxBufSize) +{ + xPrintGetDocumentDataReply *pRep; + int bytesWritten, bytesToWrite; + int result = Success; + + if(client->clientGone) + return Success; + + pRep = (xPrintGetDocumentDataReply *)xalloc(sz_xPrintGetDocumentDataReply+ + QUADPAD(maxBufSize)); + + for(bytesToWrite = min(maxBufSize, fileLen), + bytesWritten = 0; + bytesToWrite > 0; + bytesToWrite = min(maxBufSize, fileLen - bytesWritten)) + { + pRep->type = X_Reply; + pRep->sequenceNumber = client->sequence; + pRep->length = (QUADPAD(bytesToWrite)) >> 2; + pRep->dataLen = bytesToWrite; + + if(fread((void *)(pRep + 1), (size_t) 1, bytesToWrite, fp) < + bytesToWrite) + { + result = BadAlloc; /* XXX poor error choice? */ + pRep->statusCode = 2; /* XXX Is this the right value??? */ + } + else + pRep->statusCode = 0; /* XXX Ignored??? */ + + pRep->finishedFlag = FALSE; + + if (client->swapped) { + int n; + long l; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, l); + swapl(&pRep->statusCode, l); /* XXX Why are these longs??? */ + swapl(&pRep->finishedFlag, l); /* XXX Why are these longs??? */ + swapl(&pRep->dataLen, l); + } + + (void)WriteToClient(client, + sz_xPrintGetDocumentDataReply + bytesToWrite, + (char *)pRep); + bytesWritten += bytesToWrite; + } + + xfree(pRep); + return result; +} + +/* + * XpFinishDocData - send a DocumentData reply with the "finishedFlag" + * field set to TRUE. This routine should be called from the EndJob + * function of a driver after the driver has sent all required + * document data (presumably via XpSendDocumentData). + */ +int +XpFinishDocData( + ClientPtr client) +{ + xPrintGetDocumentDataReply rep; + + if(client->clientGone) + return Success; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.dataLen = 0; + rep.finishedFlag = TRUE; + rep.statusCode = 0; + + if (client->swapped) { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.statusCode, l); /* XXX Why are these longs??? */ + swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */ + swapl(&rep.dataLen, l); + } + + (void)WriteToClient(client, sz_xPrintGetDocumentDataReply, (char *)&rep); + return Success; +} + +static +char *XpDirName(char *fname) +{ + char *fn, *ptr; + + fn = (char *)xalloc(strlen(fname) + 1); + if (fn) { + strcpy(fn, fname); + ptr = strrchr(fn, '/'); + if (!ptr) { + ptr = fn; + *ptr++ = '.'; + } else if (ptr == fn) + ptr++; + *ptr = '\0'; + } + return fn; +} + +Bool +XpOpenTmpFile( + char *mode, + char **fname, + FILE **stream) +{ + char *fn = NULL; + + /* note that there is a small race condition here... */ + if (!(*fname = tempnam(NULL, NULL)) || + !(fn = XpDirName(*fname)) || + access(fn, W_OK) || + !(*stream = fopen(*fname, mode))) + { + xfree(fn); + xfree(*fname); + *fname = NULL; + *stream = NULL; + return FALSE; + } + xfree(fn); + return TRUE; +} diff --git a/Xprint/ValTree.c b/Xprint/ValTree.c new file mode 100644 index 000000000..73aa27a36 --- /dev/null +++ b/Xprint/ValTree.c @@ -0,0 +1,187 @@ +/* $Xorg: ValTree.c,v 1.3 2000/08/17 19:48:06 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +#include "X.h" +#include "scrnintstr.h" +#include "validate.h" +#include "windowstr.h" +#include "mi.h" +#include "regionstr.h" +#include "mivalidate.h" + +/* + * XpValidateTree - a validateTree routine which ignores overlapping + * top-level windows when computing the clip lists for such windows. + * This can be used by any driver which maintains a separate memory + * store for each top-level window (with its respective children). + * If the pParent is not the root window, then miValidateTree + * is used unmodified. + * + * The strategy if pParent is the root is to save off the + * current values of pParent->firstChild and pParent->lastChild, + * replacing both with the single child of interest. We save off + * pChild->prevSib and pChild->nextSib, and replace them with NullWindow. + * We save off pParent->clipList, and replace it with + * pParent->winSize - pChild->winSize. We then call miValidateTree + * to do the needed ComputeClips on the pChild's heirarchy. + * pParent's clipList is then recomputed based on the sizes + * of its children, and the saved pointers are restored. + * The trees associated with the siblings of pChild must be descended + * and cleaned of any marks (i.e. the valdata pointer freed, and set to NULL), + * and pParent' AfterValidate structure's exposed field must be updated. + */ +/*ARGSUSED*/ +int +XpValidateTree (pParent, pChild, kind) + WindowPtr pParent; /* Parent to validate */ + WindowPtr pChild; /* First child of pParent that was + * affected */ + VTKind kind; /* What kind of configuration caused call */ +{ + RegionRec origPrntClip; /* orig clipList for parent */ + RegionRec childClip; /* The new borderClip for the current + * child */ + RegionRec tmpPrntClip; /* parent clipList - child borderClip */ + RegionRec exposed; /* For intermediate calculations */ + register ScreenPtr pScreen; + register WindowPtr pWin; + Bool overlap; + int viewvals; + Bool forward; + + WindowPtr origFirstChild, origLastChild, origPrevSib, origNextSib; + + /* + * If we're validating something other than a top-level window, + * then just invoke miValidateTree. + */ + if(pParent->parent != NullWindow) + return miValidateTree(pParent, pChild, kind); + + /* + * If it's a stack change of top levels then it's a no-op for + * this scheme, so we just clean up any marks on windows and return. + */ + if(kind == VTStack) + { + CleanMarks(pParent); + return 1; + } + + pScreen = pParent->drawable.pScreen; + if (pChild == NullWindow) + pChild = pParent->firstChild; + + /* Save off the existing window heirarchy */ + origFirstChild = pParent->firstChild; + origLastChild = pParent->lastChild; + origPrevSib = pChild->prevSib; + origNextSib = pChild->nextSib; + pParent->firstChild = pChild; + pParent->lastChild = pChild; + pChild->prevSib = NullWindow; + pChild->nextSib = NullWindow; + + /* + * Set pParent's clipList to be its winSize minus the pChild's + * borderSize. + */ + origPrntClip = pParent->clipList; + REGION_INIT(pScreen, &tmpPrntClip, NullBox, 0); + REGION_SUBRACT(pScreen, &tmpPrntClip, &pParent->winSize, + &pChild->borderSize); + pParent->clipList = tmpPrntClip; + + /* + * Call miValidateTree on the pruned tree. + */ + (void) miValidateTree(pParent, pChild, kind); + + /* Restore the saved heirarchy */ + pChild->prevSib = origPrevSib; + pChild->nextSib = origNextSib; + pParent->firstChild = origFirstChild; + pParent->lastChild = origLastChild; + + /* + * Compute pParent's clipList by taking its winSize and subracting + * the borderSize of each of its children. + */ + for(pWin = pParent->firstChild, + REGION_COPY(pScreen, &pParent->clipList, &pParent->winSize); + pWin != NullWindow; + pWin = pWin->nextSib) + { + REGION_SUBTRACT(pScreen, &pParent->clipList, &pParent->clipList, + &pWin->borderSize); + } + + /* + * Compute pParent's AfterValidate structure by subracting the original + * clipList from the newly computed clipList. + */ + REGION_INIT(pScreen, &pParent->valdata->after.exposed, NullBox, 0); + REGION_SUBTRACT(pScreen, &pParent->valdata->after.exposed, + &pParent->clipList, &origPrntClip); + + /* + * Remove the marks from all but pParent and pChild's heirarchy. + * i.e. from all of pChild's siblings and their children. + */ + for(pWin = pParent->firstChild; pWin != NullWindow; pWin = pWin->nextSib) + { + WindowPtr pCurChild = pWin; + + if(pCurChild == pChild) + continue; + + while (1) + { + if(pCurChild->valdata) + { + xfree(pCurChild->valdata); + pCurChild->valdata = (ValidatePtr)NULL; + } + + if (pCurChild->firstChild) + { + pCurChild = pCurChild->firstChild; + continue; + } + while (!pCurChild->nextSib && (pCurChild != pWin)) + pCurChild = pCurChild->parent; + if (pCurChild == pWin) + break; + pCurChild = pCurChild->nextSib; + } + } +} diff --git a/Xprint/attributes.c b/Xprint/attributes.c new file mode 100644 index 000000000..7348d6402 --- /dev/null +++ b/Xprint/attributes.c @@ -0,0 +1,1575 @@ +/* $Xorg: attributes.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: attributes.c +** * +** * Contents: +** * Implementation of the attribute store for Xp. +** * +** * Copyright: Copyright 1995 Hewlett-Packard Company +** * +** ********************************************************* +** +********************************************************************/ + +#include +#include +#include +#include +#include + +#include + +#define _XP_PRINT_SERVER_ +#include "extensions/Printstr.h" +#undef _XP_PRINT_SERVER_ + +#include "Xrm.c" + +static XrmDatabase CopyDb(XrmDatabase inDb); + +extern XrmDatabase XpSpoolerGetServerAttributes(); + +static int attrGeneration = 0; + +typedef struct { + XrmDatabase *pDb; + char *qualifier; + char *modelId; +} DbEnumStruct; + +typedef struct { + char *stringDb; + int nextPos; + int space; +} StringDbStruct; + +typedef struct _printerAttrs { + struct _printerAttrs *next; + char *name; + char *qualifier; + XrmDatabase printerAttrs; + XrmDatabase docAttrs; + XrmDatabase jobAttrs; +} PrAttrs, *PrAttrPtr; + +static PrAttrPtr attrList = (PrAttrPtr)NULL; + +typedef struct _systemAttrs { + XrmDatabase doc; + XrmDatabase job; + XrmDatabase printers; + XrmDatabase server; +} SysAttrs, *SysAttrsPtr; + +SysAttrs systemAttributes; + +/* + * attrCtxtPrivIndex hold the attribute store's context private index. + * This index is allocated at the time the attribute store is initialized. + */ +static int attrCtxtPrivIndex; + +/* + * The ContextAttrs structure descibes the context private space reserved + * by the attribute store. + */ +typedef struct _contextAttrs { + XrmDatabase printerAttrs; + XrmDatabase docAttrs; + XrmDatabase jobAttrs; + XrmDatabase pageAttrs; +} ContextAttrs, *ContextAttrPtr; + +/* + * XPDIR is relative to (i.e. is a subdir of) XPRINTDIR/$LANG. + */ +static const char XPDIR[] = "/print"; +/* + * The following files/directories define or are within subdirectories of the + * above-defined XPDIR. + */ +static const char XPPRINTERATTRFILE[] = "/attributes/printer"; +static const char XPJOBATTRFILE[] = "/attributes/job"; +static const char XPDOCATTRFILE[] = "/attributes/document"; +static const char XPMODELDIR[] = "/models"; + +static char NULL_STRING[] = "\0"; + +/* + * XpGetConfigDir returns a string containing the path name of the print + * server configuration directory. If the useLocale parameter is False + * the it returns the path to the "/C" directory. If the useLocale + * parameter is True it returns the path to the directory associated with + * $LANG. It makes no attempt to ensure that the directory actually exists. + */ +char * +XpGetConfigDir(useLocale) + Bool useLocale; +{ + char *dirName, *langName, *langDir, *configDir; + Bool freeLangDir = False; + + if(useLocale == False) langDir = "/C"; + else + { + if((langName = getenv("LANG")) == (char *)NULL) + return (char *)NULL; + else + { + if(strcmp(langName, "C") == 0) + return (char *)NULL; + langDir = (char *)xalloc(strlen(langName) + 2); + sprintf(langDir, "/%s", langName); + freeLangDir = True; + } + } + + /* + * If the XPCONFIGDIR environment variable is not set, then use the + * compile-time constant XPRINTDIR. XPRINTDIR is passed in on the + * compile command line, and is defined in $(TOP)/config/cf/Project.tmpl. + */ + if((configDir = getenv("XPCONFIGDIR")) == (char *)NULL) + configDir = XPRINTDIR; + + dirName = (char *)xalloc(strlen(configDir) + strlen(XPDIR) + + strlen(langDir) + 1); + sprintf(dirName, "%s%s%s", configDir, langDir, XPDIR); + + if(freeLangDir == True) + xfree(langDir); + + return dirName; +} + +/* + * GetMergedDatabase reads and merges xrmdb files from the top-level printer + * config directory, and from the directory associated with the current + * locale (if other than the top-level). + */ +static XrmDatabase +GetMergedDatabase(attrName) + char *attrName; +{ + char *dirName, *fileName; + XrmDatabase db; + + if((dirName = XpGetConfigDir(False)) == (char *)NULL) + return (XrmDatabase)NULL; + if((fileName = (char *)xalloc(strlen(dirName) + strlen(attrName) + 1)) == + (char *)NULL) + return (XrmDatabase)NULL; + sprintf(fileName, "%s%s", dirName, attrName); + db = XrmGetFileDatabase(fileName); + xfree(fileName); + xfree(dirName); + + if((dirName = XpGetConfigDir(True)) == (char *)NULL) + return db; + if((fileName = (char *)xalloc(strlen(dirName) + strlen(attrName) + 1)) == + (char *)NULL) + return db; + sprintf(fileName, "%s%s", dirName, attrName); + (void)XrmCombineFileDatabase(fileName, &db, True); + xfree(fileName); + xfree(dirName); + + return db; +} + +/* + * BuildSystemAttributes reads the on-disk configuration files for printers, + * initial job, and initial document attributes. The resulting xrm + * databases are then dissected as needed for each printer. + * It also allocates a contextPrivate space for the attributes, + * reserving space to store pointers to the attribute stores for + * the context. + */ +static void +BuildSystemAttributes() +{ + if(systemAttributes.printers != (XrmDatabase)NULL) + XrmDestroyDatabase(systemAttributes.printers); + systemAttributes.printers = GetMergedDatabase(XPPRINTERATTRFILE); + if(systemAttributes.job != (XrmDatabase)NULL) + XrmDestroyDatabase(systemAttributes.job); + systemAttributes.job = GetMergedDatabase(XPJOBATTRFILE); + if(systemAttributes.doc != (XrmDatabase)NULL) + XrmDestroyDatabase(systemAttributes.doc); + systemAttributes.doc = GetMergedDatabase(XPDOCATTRFILE); + if(systemAttributes.server != (XrmDatabase)NULL) + XrmDestroyDatabase(systemAttributes.server); + systemAttributes.server = XpSpoolerGetServerAttributes(); + return; +} + +/* + * AddDbEntry is called by XrmEnumerateDatabase, and adds the supplied + * database entry to the database pointed to within the "DbEnumStruct" + * passed as the client_data (aka "closure"). + */ +static Bool +AddDbEntry(sourceDB, bindings, quarks, type, value, client_data) + XrmDatabase *sourceDB; + XrmBindingList bindings; + XrmQuarkList quarks; + XrmRepresentation *type; + XrmValue *value; + XPointer client_data; +{ + DbEnumStruct *pEnumStruct = (DbEnumStruct *)client_data; + XrmName xrm_name[5]; + XrmClass xrm_class[5]; + XrmBinding xrm_bind[3]; + XrmValue realVal; + XrmRepresentation rep_type; + + xrm_name[0] = XrmStringToQuark (pEnumStruct->qualifier); + xrm_class[0] = XrmStringToQuark (pEnumStruct->modelId); + + for(;*quarks; quarks++) + xrm_name[1] = xrm_class[1] = *quarks; + + xrm_name[2] = (XrmQuark)NULL; + xrm_class[2] = (XrmQuark)NULL; + + if(XrmQGetResource (*sourceDB, xrm_name, xrm_class, &rep_type, &realVal)) + { + xrm_bind[0] = XrmBindLoosely; + + xrm_name[0] = xrm_name[1]; + xrm_name[1] = NULLQUARK; + + XrmQPutStringResource(pEnumStruct->pDb, xrm_bind, xrm_name, + (char *)realVal.addr); + } + + return FALSE; +} + +/* + * BuildPrinterAttrs - builds and returns an XrmDatabase for the printer + * of the specified name/qualifier, if we have enough information. + * If we don't have a model-config + * file, then just enumerate the systemAttributes->printers database, + * otherwise read in the model-config database and merge into it the + * systemAttributes->printers database. This database is then enumerated + * with the printer qualifier (and the model name as class if we have it), and + * the resulting elements are stored into the database for this particular + * printer. + */ +static XrmDatabase +BuildPrinterAttrs(printerName, qualifierName) + char *printerName; + char *qualifierName; +{ + XrmDatabase printerDB = (XrmDatabase)NULL; + + if(systemAttributes.printers != (XrmDatabase)NULL) + { + char *dirName, *fileName; + XrmDatabase modelDB = (XrmDatabase)NULL; + XrmName xrm_name[5], xrm_class[2]; + XrmRepresentation rep_type; + XrmValue value; + DbEnumStruct enumStruct; + Bool freeModelDB = False; + /* + * Build the initial db based on the model-config files + */ + xrm_name[0] = XrmStringToQuark (qualifierName); + xrm_name[1] = XrmStringToQuark ("xp-model-identifier"); + xrm_name[2] = (XrmQuark)NULL; + XrmQGetResource (systemAttributes.printers, xrm_name, xrm_name, + &rep_type, &value); + + if(value.addr != (XPointer)NULL) + { + fileName = (char *)xalloc(strlen(XPMODELDIR) + + strlen((char *)value.addr) + + strlen("model-config") + 3); + sprintf(fileName, "%s/%s/%s", XPMODELDIR, value.addr, + "model-config"); + modelDB = GetMergedDatabase(fileName); + xfree(fileName); + if(modelDB != (XrmDatabase)NULL) + { + XrmDatabase tempDB = (XrmDatabase)NULL; + /* + * have to make a temp copy because MergeDatabase destroys + * the "source" database. Merge in the printers DB + */ + tempDB = CopyDb(systemAttributes.printers); + XrmMergeDatabases(tempDB, &modelDB); + freeModelDB = True; + } + } + + /* + * Check to see if we knew the name AND found a database file + */ + if(modelDB == (XrmDatabase)NULL) + modelDB = systemAttributes.printers; + + xrm_name[0] = XrmStringToQuark (qualifierName); + xrm_name[1] = (XrmQuark)NULL; + xrm_class[0] = XrmStringToQuark((char *)value.addr); + xrm_class[1] = (XrmQuark)NULL; + enumStruct.pDb = &printerDB; + enumStruct.qualifier = (char *)qualifierName; + enumStruct.modelId = (char *)value.addr; + XrmEnumerateDatabase(modelDB, xrm_name, xrm_class, XrmEnumAllLevels, + AddDbEntry, (XPointer) &enumStruct); + + if(freeModelDB == True) XrmDestroyDatabase(modelDB); + } + XrmPutStringResource(&printerDB, "*printer-name", printerName); + XrmPutStringResource(&printerDB, "*qualifier", qualifierName); + return printerDB; +} + +/* + * BuildABase - builds an XrmDatabase by enumerating the supplied sourceBase + * database for elements relevant for the printer named by printerName, + * and deriving a class for printerName from the model declared in the + * systemAttributes.printers database. If no model is defined for this + * printer then the printerName is used as the class as well. + * + * This is used to build the initial value document and initial value + * job attribute databases for each printer by searching the system + * level doc and job databases. + */ +static XrmDatabase +BuildABase(printerName, qualifierName, sourceBase) + char *printerName; + char *qualifierName; + XrmDatabase sourceBase; +{ + XrmDatabase builtDB = (XrmDatabase)NULL; + + if(sourceBase != (XrmDatabase)NULL) + { + XrmName xrm_name[5], xrm_class[2]; + XrmRepresentation rep_type; + XrmValue value; + DbEnumStruct enumStruct; + + /* + * Retrieve the model name for use as the class. + */ + xrm_name[0] = XrmStringToQuark (printerName); + xrm_name[1] = XrmStringToQuark ("xp-model-identifier"); + xrm_name[2] = (XrmQuark)NULL; + XrmQGetResource (systemAttributes.printers, xrm_name, xrm_name, + &rep_type, &value); + /* + * if we have a model name then use it as the class, otherwise + * just use the printer name as the class as well as the name. + */ + if(value.addr != (XPointer)NULL) + xrm_class[0] = XrmStringToQuark((char *)value.addr); + else + xrm_class[0] = xrm_name[0]; + xrm_class[1] = (XrmQuark)NULL; + + xrm_name[1] = (XrmQuark)NULL; + + enumStruct.pDb = &builtDB; + enumStruct.qualifier = (char *)qualifierName; + enumStruct.modelId = (char *)value.addr; + XrmEnumerateDatabase(sourceBase, xrm_name, xrm_class, XrmEnumAllLevels, + AddDbEntry, (XPointer) &enumStruct); + } + + XrmPutStringResource(&builtDB, "*qualifier", qualifierName); + + return builtDB; +} + +/* + * FreeAttrList is called upon server recycle, and frees the printer + * databases stored in the global attrList. + */ +static void +FreeAttrList() +{ + PrAttrPtr pAttr, pNext; + + for(pAttr = attrList, pNext = attrList; + pAttr != (PrAttrPtr)NULL; + pAttr = pNext) + { + pNext = pAttr->next; + if(pAttr->printerAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pAttr->printerAttrs); + if(pAttr->docAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pAttr->docAttrs); + if(pAttr->jobAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pAttr->jobAttrs); + xfree(pAttr->name); + xfree(pAttr->qualifier); + xfree(pAttr); + } + attrList = (PrAttrPtr)NULL; +} + +/* + * XpRehashAttributes - frees the per-printer attribute list and + * calls BuildSystemAttributes to rebuild the overall attribute + * store. It is expected that a caller of this will follow it + * by calling XpBuildAttributeStore for a new list of printers. + */ +int +XpRehashAttributes() +{ + if(attrList != (PrAttrPtr)NULL) + FreeAttrList(); + BuildSystemAttributes(); + return Success; +} + +/* + * XpBuildAttributeStore - creates the attribute database associated + * with the specified printer. The first time this is called it + * calls BuildSystemAttributes to create the system-level databases. + */ +void +XpBuildAttributeStore(printerName, qualifierName) + char *printerName; + char *qualifierName; +{ + PrAttrPtr pAttr; + + if((pAttr = (PrAttrPtr)xalloc(sizeof(PrAttrs))) == (PrAttrPtr)NULL) + return; + + if(attrGeneration != serverGeneration) + { + if(attrList != (PrAttrPtr)NULL) + FreeAttrList(); + attrCtxtPrivIndex = XpAllocateContextPrivateIndex(); + XpAllocateContextPrivate(attrCtxtPrivIndex, sizeof(ContextAttrs)); + BuildSystemAttributes(); + + attrGeneration = serverGeneration; + } + + if(attrList == (PrAttrPtr)NULL) + { + pAttr->next = (PrAttrPtr)NULL; + attrList = pAttr; + } + else + { + pAttr->next = attrList; + attrList = pAttr; + } + + pAttr->name = strdup(printerName); + pAttr->qualifier = strdup(qualifierName); + pAttr->printerAttrs = BuildPrinterAttrs(printerName, qualifierName); + pAttr->docAttrs = BuildABase(printerName, qualifierName, + systemAttributes.doc); + pAttr->jobAttrs = BuildABase(printerName, qualifierName, + systemAttributes.job); +} + + +static Bool +StoreEntry(sourceDB, bindings, quarks, type, value, client_data) + XrmDatabase *sourceDB; + XrmBindingList bindings; + XrmQuarkList quarks; + XrmRepresentation *type; + XrmValue *value; + XPointer client_data; +{ + XrmDatabase *outDb = (XrmDatabase *)client_data; + + XrmQPutStringResource(outDb, bindings, quarks, (char *)value->addr); + + return FALSE; +} + +/* + * XpCopyDb - makes a copy of the specified XrmDatabase and returns + * the copy. + */ +static XrmDatabase +CopyDb(inDb) + XrmDatabase inDb; +{ + XrmDatabase outDb = (XrmDatabase)NULL; + XrmQuark empty = NULLQUARK; + + (void)XrmEnumerateDatabase(inDb, &empty, &empty, XrmEnumAllLevels, + StoreEntry, (XPointer) &outDb); + return outDb; +} + +/* + * XpInitAttributes - initializes the attribute store for the specified + * context. It does this by making copies of the printer, doc, and job + * attributes databases for the printer associated with the context. + */ +void +XpInitAttributes( pContext ) + XpContextPtr pContext; +{ + ContextAttrPtr pCtxtAttrs; + PrAttrPtr pPrAttr = attrList; + + /* Initialize all the pointers to NULL */ + pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr; + (void)memset((void *)pCtxtAttrs, 0, (size_t) sizeof(ContextAttrs)); + + for(pPrAttr = attrList; pPrAttr != (PrAttrPtr)NULL; pPrAttr = pPrAttr->next) + if(!strcmp(pPrAttr->name, pContext->printerName)) break; + + if(pPrAttr != (PrAttrPtr)NULL) + { + pCtxtAttrs->printerAttrs = CopyDb(pPrAttr->printerAttrs); + pCtxtAttrs->docAttrs = CopyDb(pPrAttr->docAttrs); + pCtxtAttrs->jobAttrs = CopyDb(pPrAttr->jobAttrs); + } +} + +void +XpDestroyAttributes( pContext ) + XpContextPtr pContext; +{ + ContextAttrPtr pCtxtAttrs; + + pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr; + + if(pCtxtAttrs->printerAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->printerAttrs); + if(pCtxtAttrs->docAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->docAttrs); + if(pCtxtAttrs->jobAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->jobAttrs); + if(pCtxtAttrs->pageAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->pageAttrs); +} + +/* + * XpGetOneAttribute returns the string value of the specified attribute + * in the specified class for the specified print context. If the attribute + * doesn't exist in the database for this context, or if the class database + * doesn't exist for this context, then NULL is returned. The caller must + * not free the returned string, as the returned pointer points into the + * database. This function can also return a value from the server attributes, + * in which case the pContext parameter is ignored. + */ +char * +XpGetOneAttribute( pContext, class, attributeName ) + XpContextPtr pContext; + XPAttributes class; + char *attributeName; +{ + ContextAttrPtr pCtxtAttrs; + XrmDatabase db = (XrmDatabase)NULL; + char *retVal; + XrmName xrm_name[3]; + XrmRepresentation rep_type; + XrmValue value; + + if(class == XPServerAttr) + { + if(systemAttributes.server == (XrmDatabase)NULL) + return NULL_STRING; + + xrm_name[0] = XrmStringToQuark (attributeName); + xrm_name[1] = (XrmQuark)NULL; + XrmQGetResource(systemAttributes.server, xrm_name, xrm_name, + &rep_type, &value); + + if(value.addr == (char *)NULL) + return NULL_STRING; + return (char *)value.addr; + } + else + { + pCtxtAttrs=(ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr; + switch(class) + { + case XPPrinterAttr: + db = pCtxtAttrs->printerAttrs; + break; + case XPDocAttr: + db = pCtxtAttrs->docAttrs; + break; + case XPJobAttr: + db = pCtxtAttrs->jobAttrs; + break; + case XPPageAttr: + db = pCtxtAttrs->pageAttrs; + break; + default: + break; + } + } + if(db == (XrmDatabase)NULL) + return NULL_STRING; + + xrm_name[0] = XrmStringToQuark ("qualifier"); + xrm_name[1] = (XrmQuark)NULL; + XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value); + + xrm_name[0] = XrmStringToQuark (value.addr); + xrm_name[1] = XrmStringToQuark (attributeName); + xrm_name[2] = (XrmQuark)NULL; + if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) + return (char *)value.addr; + else + return NULL_STRING; +} + +/* + * XpPutOneAttribute updates one attribute for the specified + * context and class. This function is intended for use by the attribute + * validation module which updates the XrmDatabases directly. This + * function does not recognize XPServerAttr. + */ +void +XpPutOneAttribute( pContext, class, attributeName, value ) + +XpContextPtr pContext; +XPAttributes class; +const char* attributeName; +const char* value; +{ + ContextAttrPtr pCtxtAttrs; + XrmDatabase db; + XrmBinding bindings[1]; + XrmQuark quarks[2]; + + pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr; + switch(class) + { + case XPPrinterAttr: + db = pCtxtAttrs->printerAttrs; + break; + case XPDocAttr: + db = pCtxtAttrs->docAttrs; + break; + case XPJobAttr: + db = pCtxtAttrs->jobAttrs; + break; + case XPPageAttr: + db = pCtxtAttrs->pageAttrs; + break; + default: + return; + } + bindings[0] = XrmBindLoosely; + quarks[0] = XrmStringToQuark(attributeName); + quarks[1] = (XrmQuark)NULL; + XrmQPutStringResource(&db, bindings, quarks, value ? value : ""); +} + + + +/******************************************************************************* + * + * The following routines: ExpandSpace, PutString, PutByte, and AppendEntry + * form the functional core of the GetAttributes routine. Xrm does not + * supply a routine to form a string database from an XrmDatabase, except + * by writing the database to a file. This code avoids the file system + * overhead, but is a bit clunky in its memory management. + * + ******************************************************************************/ + +/* + * ExpandSpace expands the memory allocated for the string database in + * the StringDbStruct passed in, and updates the "space" field of the + * struct to indicate the new amount of space available. + */ +static Bool +ExpandSpace(pStr) + StringDbStruct *pStr; +{ + char *newSpace; + + if((newSpace = (char *)xrealloc(pStr->stringDb, pStr->nextPos + pStr->space + + 1024)) == (char *)NULL) + return False; + pStr->space += 1024; + pStr->stringDb = newSpace; + return True; +} + +/* + * PutString puts the contents of a null-terminated string into the string + * database in the StringDbStruct passed in. If there is insufficient room + * for the string, ExpandSpace is called, and the nextPos and space fields + * are updated. + */ +static void +PutString(pStr, pString) + StringDbStruct *pStr; + char *pString; +{ + int len = strlen(pString); + + if(len >= pStr->space) + if(!ExpandSpace(pStr)) + return; + strcpy(&pStr->stringDb[pStr->nextPos], pString); + pStr->nextPos += len; + pStr->space -= len; +} + +/* + * PutByte puts a single byte value in to the string database in the passed-in + * StringDbStruct. ExpandSpace is called if there is insufficient room for + * the byte, and the nextPos and space fields are updated. + */ +static void +PutByte(pStr, byte) + StringDbStruct *pStr; + char byte; +{ + if(pStr->space <= 1) + if(!ExpandSpace(pStr)) + return; + pStr->stringDb[pStr->nextPos] = byte; + pStr->nextPos++; + pStr->space--; +} + +/* + * AppendEntry is called by XrmEnumerateDatabase, and serves to append + * a database entry onto a string database. The passed-in "closure" + * struct contains a pointer to the string, and a count of the remaining + * bytes. If there are insufficient remaining bytes then the struct + * is realloced, and the count of the space remaining is updated. + * Database elements of types other than String are ignored! + * This code is based directly on that in "DumpEntry" in Xrm.c. + */ +static Bool +AppendEntry(db, bindings, quarks, type, value, data) + XrmDatabase *db; + XrmBindingList bindings; + XrmQuarkList quarks; + XrmRepresentation *type; + XrmValuePtr value; + XPointer data; +{ + StringDbStruct *pEnumStr = (StringDbStruct *)data; + Bool firstNameSeen; + unsigned int i; + char *s, c; + + if (*type != XrmQString) + return; + + for (firstNameSeen = False; *quarks; bindings++, quarks++) { + if (*bindings == XrmBindLoosely) { + PutString(pEnumStr, "*"); + } else if (firstNameSeen) { + PutString(pEnumStr, "."); + } + firstNameSeen = True; + PutString(pEnumStr, XrmQuarkToString(*quarks)); + } + s = value->addr; + i = value->size; + PutString(pEnumStr, ":\t"); + if(i) i--; + + if (i && (*s == ' ' || *s == '\t')) + PutByte(pEnumStr, '\\'); /* preserve leading whitespace */ + + while (i--) { + c = *s++; + if (c == '\n') { + if (i) + PutString(pEnumStr, "\\n\\\n"); + else + PutString(pEnumStr, "\\n"); + } else if (c == '\\') + PutString(pEnumStr, "\\\\"); + else if ((c < ' ' && c != '\t') || + ((unsigned char)c >= 0x7f && (unsigned char)c < 0xa0)) + { + char temp[4]; + (void) sprintf(temp, "\\%03o", (unsigned char)c); + PutString(pEnumStr, temp); + } + else + PutByte(pEnumStr, c); + } + PutByte(pEnumStr, '\n'); + pEnumStr->stringDb[pEnumStr->nextPos] = (char)'\0'; + return False; +} + +/* + * XpGetAttributes returns a string database version of the Xrm database + * for the specified context and class. This function can also return the + * contents of the server attributes, in which case the pContext parameter + * is ignored. + * + * The caller is responsible for freeing the returned string, + * unlike XpGetOneAttribute, where the caller must not free the string. + */ +char * +XpGetAttributes( pContext, class ) + XpContextPtr pContext; + XPAttributes class; +{ + ContextAttrPtr pCtxtAttrs; + XrmDatabase db = (XrmDatabase)NULL; + char *retVal; + StringDbStruct enumStruct; + XrmQuark empty = NULLQUARK; + + if(class == XPServerAttr) + db = systemAttributes.server; + else + { + pCtxtAttrs=(ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr; + switch(class) + { + case XPServerAttr: + db = systemAttributes.server; + break; + case XPPrinterAttr: + db = pCtxtAttrs->printerAttrs; + break; + case XPDocAttr: + db = pCtxtAttrs->docAttrs; + break; + case XPJobAttr: + db = pCtxtAttrs->jobAttrs; + break; + case XPPageAttr: + db = pCtxtAttrs->pageAttrs; + break; + default: + break; + } + } + if(db == (XrmDatabase)NULL) + { + char *retval = (char *)xalloc(1); + retval[0] = (char)'\0'; + return retval; + } + + if((enumStruct.stringDb = (char *)xalloc(1024)) == (char *)NULL) + return (char *)NULL; + enumStruct.stringDb[0] = (char)'\0'; + enumStruct.nextPos = 0; + enumStruct.space = 1024; + (void)XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels, + AppendEntry, (XPointer) &enumStruct); + + return enumStruct.stringDb; +} + +int +XpAugmentAttributes( pContext, class, attributes ) + XpContextPtr pContext; + XPAttributes class; + char *attributes; +{ + XrmDatabase db; + ContextAttrPtr pCtxtAttrs; + + db = XrmGetStringDatabase(attributes); + if(db == (XrmDatabase)NULL) return BadAlloc; + + pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr; + switch(class) + { + case XPPrinterAttr: + XrmMergeDatabases(db, &pCtxtAttrs->printerAttrs); + break; + case XPDocAttr: + XrmMergeDatabases(db, &pCtxtAttrs->docAttrs); + break; + case XPJobAttr: + XrmMergeDatabases(db, &pCtxtAttrs->jobAttrs); + break; + case XPPageAttr: + XrmMergeDatabases(db, &pCtxtAttrs->pageAttrs); + break; + default: + break; + } + return Success; +} + +/* + * XpSetAttributes - sets the attribute stores for a specified context. + */ +int +XpSetAttributes( pContext, class, attributes ) + XpContextPtr pContext; + XPAttributes class; + char *attributes; +{ + XrmDatabase db; + ContextAttrPtr pCtxtAttrs; + + db = XrmGetStringDatabase(attributes); + if(db == (XrmDatabase)NULL) return BadAlloc; + + pCtxtAttrs=(ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr; + switch(class) + { + case XPPrinterAttr: + if(pCtxtAttrs->printerAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->printerAttrs); + pCtxtAttrs->printerAttrs = db; + break; + case XPDocAttr: + if(pCtxtAttrs->docAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->docAttrs); + pCtxtAttrs->docAttrs = db; + break; + case XPJobAttr: + if(pCtxtAttrs->jobAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->jobAttrs); + pCtxtAttrs->jobAttrs = db; + break; + case XPPageAttr: + if(pCtxtAttrs->pageAttrs != (XrmDatabase)NULL) + XrmDestroyDatabase(pCtxtAttrs->pageAttrs); + pCtxtAttrs->pageAttrs = db; + break; + default: + break; + } + return Success; +} + +void +XpAddPrinterAttribute(printerName, printerQualifier, attributeName, + attributeValue) + char *printerName; + char *printerQualifier; + char *attributeName; + char *attributeValue; +{ + PrAttrPtr pAttr; + + for(pAttr = attrList; pAttr != (PrAttrPtr)NULL; pAttr = pAttr->next) + { + if(!strcmp(printerQualifier, pAttr->qualifier)) + { + XrmPutStringResource(&pAttr->printerAttrs, attributeName, + attributeValue); + break; + } + } +} + +const char * +XpGetPrinterAttribute(const char *printerName, + const char *attribute) +{ + PrAttrPtr pAttr; + XrmValue value; + char *type; + + for(pAttr = attrList; pAttr != (PrAttrPtr)NULL; pAttr = pAttr->next) + { + if(!strcmp(printerName, pAttr->qualifier)) + { + char *attrStr; + + attrStr = (char *)xalloc(strlen(printerName) + strlen(attribute) + + 2); + sprintf(attrStr, "%s.%s", printerName, attribute); + XrmGetResource(pAttr->printerAttrs, attrStr, attrStr, + &type, &value); + xfree(attrStr); + break; + } + } + if(value.addr != (XPointer)NULL && strlen(value.addr) != 0) + return value.addr; + else + return ""; +} + +/******************************************************************************* + * + * The following routines are not attribute routines, but are rather + * spooler interface functions. They should presumably move to + * a SpoolerIf.c of some similarly named file. + * + ******************************************************************************/ +#include + +static char serverAttrStr[] = "*document-attributes-supported: copy-count\n\ +*job-attributes-supported: job-name job-owner\ + notification-profile xp-spooler-command-options\n\ +*multiple-documents-supported: False"; + +XrmDatabase +XpSpoolerGetServerAttributes() +{ + char *totalAttrs, *localeName; + XrmDatabase db; + + localeName = setlocale(LC_CTYPE, (char *)NULL); + if(!localeName || strlen(localeName) == 0) + localeName = "C"; + + if((totalAttrs = (char *)xalloc(strlen(serverAttrStr) + strlen(localeName) + + 11)) == (char *)NULL) + return (XrmDatabase)NULL; + sprintf(totalAttrs, "%s\n%s\t%s", serverAttrStr, "*locale:", localeName); + + db = XrmGetStringDatabase(totalAttrs); + xfree(totalAttrs); + return db; +} + +/* + * ExecuteCommand takes two pointers - the command to execute, + * and the "argv" style NULL-terminated vector of arguments for the command. + * We wait for the command to terminate before continuing to ensure that + * we don't delete the job file before the spooler has made a copy. + */ +static void +ExecCommand(pCommand, argVector) + char *pCommand; + char **argVector; +{ + pid_t childPid; + int status; + + if((childPid = fork()) == 0) + { + /* return BadAlloc? */ + if (execv(pCommand, argVector) == -1) { + FatalError("unable to exec '%s'", pCommand); + } + } + else + { + (void) waitpid(childPid, &status, 0); + } + return; +} + +/* + * SendFileToCommand takes three character pointers - the file name, + * the command to execute, + * and the "argv" style NULL-terminated vector of arguments for the command. + * The command is exec'd, and the file contents are sent to the command + * via stdin. + * + * WARNING: This function will try to adopt the userId of the supplied + * user name prior to exec'ing the supplied command. + */ +static void +SendFileToCommand( + char *fileName, + char *pCommand, + char **argVector, + char *userName) +{ + pid_t childPid; + int pipefd[2]; + int status; + struct stat statBuf; + FILE *fp, *outPipe; + + if(pipe(pipefd)) + return; + + if(stat(fileName, &statBuf) < 0 || (int)statBuf.st_size == 0) + { + close(pipefd[0]); + close(pipefd[1]); + return; + } + + fp = fopen(fileName, "r"); + if(fp == (FILE *)NULL) + { + close(pipefd[0]); + close(pipefd[1]); + return; + } + + if((childPid = fork()) == 0) + { + close(pipefd[1]); + close(0); + dup(pipefd[0]); + close(pipefd[0]); + + /* + * If a user name is specified, try to set our uid to match that + * user name. This is to allow e.g. a banner page to show the + * name of the printing user rather than the user who started + * the print server. + */ + if(userName) + { + uid_t myUid; + + if((myUid = geteuid()) == (uid_t)0) + { + struct passwd *pPasswd; + + if((pPasswd = getpwnam(userName))) + { + setuid((uid_t)pPasswd->pw_uid); + } + } + } + /* return BadAlloc? */ + if (execv(pCommand, argVector) == -1) { + FatalError("unable to exec '%s'", pCommand); + } + } + else + { + int res; + + (void) close(pipefd[0]); + + outPipe = fdopen(pipefd[1], "w"); + (void) TransferBytes(fp, outPipe, (int)statBuf.st_size); + + (void) fclose(outPipe); + (void) fclose(fp); + + (void) waitpid(childPid, &status, 0); + } + return; +} + +/* + * ReplaceAllKeywords causes all the predefined keywords (e.g. %options%) + * to be replaced with the appropriate values derived from the attribute + * store for the supplied print context. The ReplaceAnyString utility + * routine is used to perform the actual replacements. + */ +extern char *ReplaceAnyString(char *, char *, char *); + +static char * +ReplaceAllKeywords( + XpContextPtr pContext, + char *command) +{ + char *cmdOpt; + + cmdOpt = XpGetOneAttribute(pContext, XPPrinterAttr, + "xp-spooler-printer-name"); + if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0) + command = ReplaceAnyString(command, "%printer-name%", cmdOpt); + else + command = ReplaceAnyString(command, "%printer-name%", + pContext->printerName); + + cmdOpt = XpGetOneAttribute(pContext, XPDocAttr, "copy-count"); + if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0) + command = ReplaceAnyString(command, "%copy-count%", cmdOpt); + else + command = ReplaceAnyString(command, "%copy-count%", "1"); + + cmdOpt = XpGetOneAttribute(pContext, XPJobAttr, "job-name"); + if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0) + command = ReplaceAnyString(command, "%job-name%", cmdOpt); + else + command = ReplaceAnyString(command, "%job-name%", ""); + + cmdOpt = XpGetOneAttribute(pContext, XPJobAttr, "job-owner"); + if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0) + command = ReplaceAnyString(command, "%job-owner%", cmdOpt); + else + command = ReplaceAnyString(command, "%job-owner%", ""); + + cmdOpt = XpGetOneAttribute(pContext, XPJobAttr, + "xp-spooler-command-options"); + if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0) + command = ReplaceAnyString(command, "%options%", cmdOpt); + else + command = ReplaceAnyString(command, "%options%", ""); + + return command; +} + +#if defined(CSRG_BASED) || defined(linux) || (defined(sun) && !defined(SVR4)) || (defined(SVR4) && !defined(sun) && !defined(USL)) +#define iswspace(c) (isascii(c) && isspace(toascii(c))) +#endif + +/* + * GetToken - takes in a string and returns a malloc'd copy of the + * first non-white-space sequence of characters in the string. + * It returns the number of _bytes_ (NOT characters) parsed through + * the inStr to get to the end of the returned token. + */ +static int +GetToken( + char *inStr, + char **outStr) +{ + size_t mbCurMax = MB_CUR_MAX; + wchar_t curChar; + int i, numBytes, byteLen = strlen(inStr); + char *tok; + + /* + * read through any leading white space. + */ + for(i = 0, numBytes = 0; i < byteLen; i += numBytes) + { + numBytes = mbtowc(&curChar, &inStr[i], mbCurMax); + if(!iswspace(curChar)) + break; + } + tok = inStr + i; + + /* + * find the end of the token. + */ + byteLen = strlen(tok); + for(i = 0, numBytes = 0; i < byteLen; i += numBytes) + { + numBytes = mbtowc(&curChar, &tok[i], mbCurMax); + if(iswspace(curChar)) + break; + } + + if((*outStr = (char *)xalloc(i + 1)) == (char *)NULL) + return 0; + strncpy(*outStr, tok, i); + (*outStr)[i] = (char)'\0'; + return (tok + i) - inStr; +} + +static void +FreeVector( + char **vector) +{ + int i; + + if(vector == (char **)NULL) return; + + for(i = 0; vector[i] != (char *)NULL; i++) + xfree(vector[i]); + xfree(vector); +} + + +/* + * AddVector appends the pAddition arg vector to the pTarget arg vector. + * If the pTarget cannot be realloc'd, then pTarget is set to NULL. + */ +static void +AddVector( + char ***pTarget, + char **pAddition) +{ + int numTarget, numAdd, i; + + for(numTarget = 0; (*pTarget)[numTarget] != (char *)NULL; numTarget++) + ; + for(numAdd = 0; pAddition[numAdd] != (char *)NULL; numAdd++) + ; + + *pTarget = (char **)xrealloc((void *)*pTarget, (numTarget + numAdd + 1) * + sizeof(char *)); + if(*pTarget == (char **)NULL) + return; + for(i = 0; i < numAdd; i++) + (*pTarget)[numTarget + i] = pAddition[i]; + + (*pTarget)[numTarget + numAdd] = (char *)NULL; +} + +static char ** +BuildArgVector( + char *argString, + XpContextPtr pContext) +{ + char **pVector; + char *curTok; + int numChars, i; + static int beenHere = 0; /* prevent recursion on embedded %options% + */ + + pVector = (char **)xalloc(sizeof(char *)); + pVector[0] = (char *)NULL; + for(i = 0; (numChars = GetToken(argString, &curTok)) != 0; + i++, argString += numChars) + { + if(beenHere || strcmp(curTok, "%options%")) + { + if(curTok[0] == (char)'\0') + { + xfree(curTok); + } + else + { + pVector = (char **)xrealloc((void *)pVector, + (i + 2)*sizeof(char *)); + if(pVector == (char **)NULL) + return (char **)NULL; + pVector[i] = curTok; + pVector[i + 1] = (char *)NULL; + } + } + else if(!beenHere) + { + char **optionsVec; + + curTok = ReplaceAllKeywords(pContext, curTok); + beenHere = 1; + optionsVec = BuildArgVector(curTok, pContext); + xfree(curTok); + beenHere = 0; + AddVector(&pVector, optionsVec); + xfree(optionsVec); + } + } + if(numChars == 0 && curTok != (char *)NULL) + xfree(curTok); + return pVector; +} + +/* + * VectorizeCommand takes a string and breaks it into a command name and + * an array of character pointers suitable for handing to execv. The + * array is NULL-terminated. + * The returned char * is the command name, and should be freed when no + * longer needed. The array elements returned in the pVector parameter + * should be individually freed, and the array itself should also be + * freed when no longer needed. + */ +static char * +VectorizeCommand( + char *command, + char ***pVector, + XpContextPtr pContext) +{ + char *cmdName, *curTok; + int i, numChars; + + if(command == (char *)NULL) + return (char *)NULL; + + numChars = GetToken(command, &cmdName); + + if(cmdName == (char *)NULL) + return (char *)NULL; + + *pVector = BuildArgVector(command, pContext); + + return cmdName; +} + +#ifdef hpux +static char DEFAULT_SPOOL_COMMAND[] = "/usr/bin/lp -d %printer-name% -o raw -n %copy-count% -t %job-name% %options%"; +#else +static char DEFAULT_SPOOL_COMMAND[] = "/usr/bin/lp -d %printer-name% -n %copy-count% -t %job-name% %options%"; +#endif + +int +XpSubmitJob(fileName, pContext) + char *fileName; + XpContextPtr pContext; +{ + char **vector, *cmdNam, *cmdOpt, *command, *userName; + int i; + + command = XpGetOneAttribute(pContext, XPPrinterAttr, "xp-spooler-command"); + if(command == (char *)NULL || strlen(command) == 0) + command = strdup(DEFAULT_SPOOL_COMMAND); + else + command = strdup(command); + if(command == (char *)NULL) + return BadAlloc; + + cmdNam = VectorizeCommand(command, &vector, pContext); + xfree(command); + + if(cmdNam == (char *)NULL) + return BadAlloc; + + for(i = 0; vector[i] != (char *)NULL; i++) + { + vector[i] = ReplaceAllKeywords(pContext, vector[i]); + if(vector[i] == (char *)NULL) + { + xfree(cmdNam); + for(i = 0; vector[i] != (char *)NULL; i++) + xfree(vector[i]); + xfree(vector); + return BadAlloc; + } + } + + userName = XpGetOneAttribute(pContext, XPJobAttr, "job-owner"); + if(userName != (char *)NULL && strlen(userName) == 0) + userName = (char *)NULL; + + SendFileToCommand(fileName, cmdNam, vector, userName); + + FreeVector(vector); + xfree(cmdNam); +} + +/* + * SearchInputTrays() + * + * Given a tray, return the medium in the tray. Conversely, given a + * medium, return a tray in which it can be found. In either case, + * return NULL if the given tray or medium cannot be found. + */ +#define TRAY 0 +#define MEDIUM 1 + +static char * +SearchInputTrays(XpContextPtr pCon, + int which, + char *val) +{ + char *inputTraysMedium, tray[80], medium[80], *copy; + char *pS, *pE, *pLast; + + inputTraysMedium = XpGetOneAttribute( pCon, XPPrinterAttr, + "input-trays-medium" ); + + copy = strdup( inputTraysMedium ); + pS = copy; + pLast = copy + strlen( copy ); + + while( pS < pLast ) + { + while( *pS && *pS != '{' ) + pS++; + + pE = ++pS; + while( *pE && *pE != '}' ) + pE++; + *pE = '\0'; + + sscanf( pS, "%s %s", tray, medium ); + + if( which == MEDIUM && !strcmp( val, medium ) ) + { + xfree( copy ); + return strdup( tray ); + } + + if( which == TRAY && !strcmp( val, tray ) ) + { + xfree( copy ); + return strdup( medium ); + } + + pS = pE + 1; + } + + xfree( copy ); + return strdup( NULL_STRING ); +} + +/* + * XpGetTrayMediumFromContext() + * + * Given a print context, hit the input-trays-medium, + * default-input-tray and default-medium attributes to find the + * appropriate tray to use, and the medium in that tray. + */ +void +XpGetTrayMediumFromContext(XpContextPtr pCon, + char **medium, + char **tray) +{ + char *defMedium, *defTray; + char *t, *m; + char *pS, *pE, *pLast; + + defMedium = XpGetOneAttribute( pCon, XPPageAttr, + "default-medium" ); + if( *defMedium == '\0' ) + defMedium = XpGetOneAttribute( pCon, XPDocAttr, + "default-medium" ); + + defTray = XpGetOneAttribute( pCon, XPPageAttr, + "default-input-tray" ); + if( *defTray == '\0' ) + defTray = XpGetOneAttribute( pCon, XPDocAttr, + "default-input-tray" ); + + /* + * First, check to see if the default tray has the default medium + * installed. This is the ideal case. + */ + m = SearchInputTrays( pCon, TRAY, defTray ); + if( !strcmp( m, defMedium ) ) + { + xfree( m ); + *tray = strdup( defTray ); + *medium = strdup( defMedium ); + return; + } + + /* + * If the default tray doesn't have the default medium, search for + * a tray which has the default medium. + */ + t = SearchInputTrays( pCon, MEDIUM, defMedium ); + if( t ) + { + *tray = t; + *medium = strdup( defMedium ); + return; + } + + /* + * If all else fails, just return the default tray, and whatever + * medium happens to be there. Note that we simply return + * whatever is in the attribute store. Any further correction is + * left up to the DDX driver. + */ + *tray = strdup( defTray ); + *medium = m; + xfree( t ); +} diff --git a/Xprint/attributes.h b/Xprint/attributes.h new file mode 100644 index 000000000..59ccb9c63 --- /dev/null +++ b/Xprint/attributes.h @@ -0,0 +1,78 @@ +/* $Xorg: attributes.h,v 1.4 2001/03/14 18:42:44 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "Oid.h" + +/* + * attributes.c + */ +void XpInitAttributes(XpContextPtr pContext); +char *XpGetOneAttribute(XpContextPtr pContext, + XPAttributes class, + char *attributeName); +void XpPutOneAttribute(XpContextPtr pContext, + XPAttributes class, + const char* attributeName, + const char* value); +char *XpGetAttributes(XpContextPtr pContext, + XPAttributes class); +int XpAugmentAttributes(XpContextPtr pContext, + XPAttributes class, + char *attributes); +int XpSetAttributes(XpContextPtr pContext, + XPAttributes class, + char *attributes); +const char *XpGetPrinterAttribute(const char *printerName, + const char *attribute); +void XpGetTrayMediumFromContext(XpContextPtr pCon, + char **medium, + char **tray); + +/* + * mediaSizes.c + */ +int XpGetResolution(XpContextPtr pContext); +XpOid XpGetContentOrientation(XpContextPtr pContext); +XpOid XpGetAvailableCompression(XpContextPtr pContext); +XpOid XpGetPlex(XpContextPtr pContext); +XpOid XpGetPageSize(XpContextPtr pContext, + XpOid* pTray, + const XpOidMediumSS* msss); +void XpGetMediumMillimeters(XpOid page_size, + float *width, + float *height); +void XpGetMediumDimensions(XpContextPtr pContext, + unsigned short *width, + unsigned short *height); +void XpGetReproductionArea(XpContextPtr pContext, + xRectangle *pRect); diff --git a/Xprint/ddxInit.c b/Xprint/ddxInit.c new file mode 100644 index 000000000..3f8cefbe8 --- /dev/null +++ b/Xprint/ddxInit.c @@ -0,0 +1,364 @@ +/* $Xorg: ddxInit.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "Xos.h" + +static void Exit(); +void _XpVoidNoop(); + +/*- + *----------------------------------------------------------------------- + * InitOutput -- + * If this is built as a print-only server, then we must supply + * an InitOutput routine. If a normal server's real ddx InitOutput + * is used, then it should call PrinterInitOutput if it so desires. + * The ddx-level hook is needed to allow the printer stuff to + * create additional screens. An extension can't reliably do + * this for two reasons: + * + * 1) If InitOutput doesn't create any screens, then main() + * exits before calling InitExtensions(). + * + * 2) Other extensions may rely on knowing about all screens + * when they initialize, and we can't guarantee the order + * of extension initialization. + * + * Results: + * ScreenInfo filled in, and PrinterInitOutput is called to create + * the screens associated with printers. + * + * Side Effects: + * None + * + *----------------------------------------------------------------------- + */ + +void +InitOutput(pScreenInfo, argc, argv) + ScreenInfo *pScreenInfo; + int argc; + char **argv; +{ + int i; + + pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + + pScreenInfo->numPixmapFormats = 0; /* get them in PrinterInitOutput */ + screenInfo.numVideoScreens = 0; +#ifdef PRINT_ONLY_SERVER + PrinterInitOutput(pScreenInfo, argc, argv); +#endif +} + +static void +BellProc(volume, pDev) + int volume; + DeviceIntPtr pDev; +{ + return; +} + +static void +KeyControlProc(pDev, ctrl) + DeviceIntPtr pDev; + KeybdCtrl *ctrl; +{ + return; +} + +static KeySym printKeyMap[256]; +static CARD8 printModMap[256]; + +static int +KeyboardProc(pKbd, what, argc, argv) + DevicePtr pKbd; + int what; + int argc; + char *argv[]; +{ + KeySymsRec keySyms; + + keySyms.minKeyCode = 8; + keySyms.maxKeyCode = 8; + keySyms.mapWidth = 1; + keySyms.map = printKeyMap; + + switch(what) + { + case DEVICE_INIT: + InitKeyboardDeviceStruct(pKbd, &keySyms, printModMap, + (BellProcPtr)BellProc, + KeyControlProc); + break; + case DEVICE_ON: + break; + case DEVICE_OFF: + break; + case DEVICE_CLOSE: + break; + } + return Success; +} + +#include "../mi/mipointer.h" +static int +PointerProc(pPtr, what, argc, argv) + DevicePtr pPtr; + int what; + int argc; + char *argv[]; +{ +#define NUM_BUTTONS 1 + CARD8 map[NUM_BUTTONS]; + + switch(what) + { + case DEVICE_INIT: + { + map[0] = 0; + InitPointerDeviceStruct(pPtr, map, NUM_BUTTONS, + miPointerGetMotionEvents, + (PtrCtrlProcPtr)_XpVoidNoop, + miPointerGetMotionBufferSize()); + break; + } + case DEVICE_ON: + break; + case DEVICE_OFF: + break; + case DEVICE_CLOSE: + break; + } + return Success; +} + +void +InitInput(argc, argv) + int argc; + char **argv; +{ + DevicePtr ptr, kbd; + + ptr = AddInputDevice((DeviceProc)PointerProc, TRUE); + kbd = AddInputDevice((DeviceProc)KeyboardProc, TRUE); + RegisterPointerDevice(ptr); + RegisterKeyboardDevice(kbd); + return; +} + + +Bool +LegalModifier(key, dev) + unsigned int key; + DevicePtr dev; +{ + return TRUE; +} + +void +ProcessInputEvents() +{ +} + +#ifdef DDXOSINIT +void +OsVendorInit() +{ +} +#endif + +#ifdef DDXTIME +CARD32 +GetTimeInMillis() +{ + struct timeval tp; + + X_GETTIMEOFDAY(&tp); + return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} +#endif + +/**************************************** +* ddxUseMsg() +* +* Called my usemsg from os/utils/c +* +*****************************************/ + +void ddxUseMsg() +{ + /* Right now, let's just do nothing */ +} + +static void Exit (code) + int code; +{ + exit (code); +} + +void AbortDDX () +{ +} + +void ddxGiveUp() /* Called by GiveUp() */ +{ +} + +int +ddxProcessArgument (argc, argv, i) + int argc; + char *argv[]; + int i; + +{ +#ifdef PRINT_ONLY_SERVER + return XprintOptions(argc, argv, i) - i; +#else + return(0); +#endif +} + +#ifdef XINPUT + +#include "XI.h" +#include "XIproto.h" + +extern int BadDevice; + +ChangePointerDevice (old_dev, new_dev, x, y) + DeviceIntPtr old_dev; + DeviceIntPtr new_dev; + unsigned char x,y; +{ + return (BadDevice); +} + +int +ChangeDeviceControl (client, dev, control) + register ClientPtr client; + DeviceIntPtr dev; + xDeviceCtl *control; +{ + return BadMatch; +} + +OpenInputDevice (dev, client, status) + DeviceIntPtr dev; + ClientPtr client; + int *status; +{ + return; +} + +AddOtherInputDevices () +{ + return; +} + +CloseInputDevice (dev, client) + DeviceIntPtr dev; + ClientPtr client; +{ + return; +} + +ChangeKeyboardDevice (old_dev, new_dev) + DeviceIntPtr old_dev; + DeviceIntPtr new_dev; +{ + return (Success); +} + +SetDeviceMode (client, dev, mode) + register ClientPtr client; + DeviceIntPtr dev; + int mode; +{ + return BadMatch; +} + +SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators) + register ClientPtr client; + DeviceIntPtr dev; + int *valuators; + int first_valuator; + int num_valuators; +{ + return BadMatch; +} + + +#endif /* XINPUT */ + +#ifdef XTESTEXT1 + +void +XTestJumpPointer(x, y, dev) + int x, y, dev; +{ + return; +} + +void +XTestGetPointerPos(x, y) +{ + return; +} + +void +XTestGenerateEvent(dev, keycode, keystate, x, y) + int dev, keycode, keystate, x, y; +{ + return; +} + +#endif /* XTESTEXT1 */ + +#ifdef AIXV3 +/* + * This is just to get the server to link on AIX, where some bits + * that should be in os/ are instead in hw/ibm. + */ +int SelectWaitTime = 10000; /* usec */ +#endif diff --git a/Xprint/mediaSizes.c b/Xprint/mediaSizes.c new file mode 100644 index 000000000..eaff20a88 --- /dev/null +++ b/Xprint/mediaSizes.c @@ -0,0 +1,777 @@ +/* $Xorg: mediaSizes.c,v 1.4 2001/03/14 18:44:37 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: mediaSizes.c +** * +** * Contents: +** * Routines to return the sizes associated +** * with particular media and particular printers. +** * +** * Created: 2/19/96 +** * +** * Copyright: Copyright 1993,1995 Hewlett-Packard Company +** * +** ********************************************************* +** +********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "X.h" +#include "dixstruct.h" +#include "screenint.h" +#include "misc.h" +#include "scrnintstr.h" +#include "fontstruct.h" + +#define _XP_PRINT_SERVER_ +#include "Printstr.h" +#undef _XP_PRINT_SERVER_ + +#include "DiPrint.h" +#include "AttrValid.h" + +extern XpContextPtr XpContextOfClient(); + +typedef struct { + XpOid page_size; + float width; + float height; +} PageDimensionsRec; + +static PageDimensionsRec PageDimensions[] = +{ + {xpoid_val_medium_size_na_letter, 215.9, 279.4}, + {xpoid_val_medium_size_na_legal, 215.9, 355.6}, + {xpoid_val_medium_size_executive, 184.15, 266.7}, + {xpoid_val_medium_size_folio, 210.82, 330.2}, + {xpoid_val_medium_size_invoice, 139.7, 215.9}, + {xpoid_val_medium_size_ledger, 279.4, 431.8}, + {xpoid_val_medium_size_quarto, 215.9, 275.082}, + {xpoid_val_medium_size_a, 215.9, 279.4}, + {xpoid_val_medium_size_b, 279.4, 431.8}, + {xpoid_val_medium_size_c, 431.8, 558.8}, + {xpoid_val_medium_size_d, 558.8, 863.6}, + {xpoid_val_medium_size_e, 863.6, 1117.6}, + {xpoid_val_medium_size_na_6x9_envelope, 152.4, 228.6}, + {xpoid_val_medium_size_na_10x15_envelope, 254, 381}, + {xpoid_val_medium_size_monarch_envelope, 98.298, 190.5}, + {xpoid_val_medium_size_na_10x13_envelope, 254, 330.2}, + {xpoid_val_medium_size_na_9x12_envelope, 228.6, 304.8}, + {xpoid_val_medium_size_na_number_10_envelope, 104.775, 241.3}, + {xpoid_val_medium_size_na_7x9_envelope, 177.8, 228.6}, + {xpoid_val_medium_size_na_9x11_envelope, 228.6, 279.4}, + {xpoid_val_medium_size_na_10x14_envelope, 254, 355.6}, + {xpoid_val_medium_size_na_number_9_envelope, 98.425, 225.425}, + {xpoid_val_medium_size_iso_a0, 841, 1189}, + {xpoid_val_medium_size_iso_a1, 594, 841}, + {xpoid_val_medium_size_iso_a2, 420, 594}, + {xpoid_val_medium_size_iso_a3, 297, 420}, + {xpoid_val_medium_size_iso_a4, 210, 297}, + {xpoid_val_medium_size_iso_a5, 148, 210}, + {xpoid_val_medium_size_iso_a6, 105, 148}, + {xpoid_val_medium_size_iso_a7, 74, 105}, + {xpoid_val_medium_size_iso_a8, 52, 74}, + {xpoid_val_medium_size_iso_a9, 37, 52}, + {xpoid_val_medium_size_iso_a10, 26, 37}, + {xpoid_val_medium_size_iso_b0, 1000, 1414}, + {xpoid_val_medium_size_iso_b1, 707, 1000}, + {xpoid_val_medium_size_iso_b2, 500, 707}, + {xpoid_val_medium_size_iso_b3, 353, 500}, + {xpoid_val_medium_size_iso_b4, 250, 353}, + {xpoid_val_medium_size_iso_b5, 176, 250}, + {xpoid_val_medium_size_iso_b6, 125, 176}, + {xpoid_val_medium_size_iso_b7, 88, 125}, + {xpoid_val_medium_size_iso_b8, 62, 88}, + {xpoid_val_medium_size_iso_b9, 44, 62}, + {xpoid_val_medium_size_iso_b10, 31, 44}, + {xpoid_val_medium_size_jis_b0, 1030, 1456}, + {xpoid_val_medium_size_jis_b1, 728, 1030}, + {xpoid_val_medium_size_jis_b2, 515, 728}, + {xpoid_val_medium_size_jis_b3, 364, 515}, + {xpoid_val_medium_size_jis_b4, 257, 364}, + {xpoid_val_medium_size_jis_b5, 182, 257}, + {xpoid_val_medium_size_jis_b6, 128, 182}, + {xpoid_val_medium_size_jis_b7, 91, 128}, + {xpoid_val_medium_size_jis_b8, 64, 91}, + {xpoid_val_medium_size_jis_b9, 45, 64}, + {xpoid_val_medium_size_jis_b10, 32, 45}, + {xpoid_val_medium_size_iso_c3, 324, 458}, + {xpoid_val_medium_size_iso_c4, 229, 324}, + {xpoid_val_medium_size_iso_c5, 162, 229}, + {xpoid_val_medium_size_iso_c6, 114, 162}, + {xpoid_val_medium_size_iso_designated_long, 110, 220} +}; + +/* + * XpGetResolution returns an integer representing the printer resolution + * in dots-per-inch for the specified print context. + * + * Note: This routine assumes the values found in the passed context's + * attributes pools have been validated. + */ +int +XpGetResolution( + XpContextPtr pContext) +{ + unsigned long resolution; + + resolution = XpGetCardAttr(pContext, XPPageAttr, + xpoid_att_default_printer_resolution, + (XpOidCardList*)NULL); + if(0 == resolution) + resolution = XpGetCardAttr(pContext, XPDocAttr, + xpoid_att_default_printer_resolution, + (XpOidCardList*)NULL); + if(0 == resolution) + { + XpOidCardList* resolutions_supported; + /* + * default-printer-resolution not specified; default to 1st entry + * in printer-resolutions-supported. + */ + resolutions_supported = + XpGetCardListAttr(pContext, XPPrinterAttr, + xpoid_att_printer_resolutions_supported, + (XpOidCardList*)NULL); + resolution = XpOidCardListGetCard(resolutions_supported, 0); + XpOidCardListDelete(resolutions_supported); + } + return (int)resolution; +} + +/* + * XpGetContentOrientation determines the content-orientation as + * determined by the passed context. The page and document pools are + * queried in turn for a specified content-orientation attribute. If none + * is found the first content-orientation in the + * content-orientations-supported printer attribute is taken as the + * default. + * + * Note: This routine assumes the values found in the passed context's + * attributes pools have been validated. + */ +XpOid +XpGetContentOrientation( + XpContextPtr pContext) +{ + XpOid orientation; + + orientation = XpGetOidAttr(pContext, XPPageAttr, + xpoid_att_content_orientation, + (XpOidList*)NULL); + if(xpoid_none == orientation) + orientation = XpGetOidAttr(pContext, XPDocAttr, + xpoid_att_content_orientation, + (XpOidList*)NULL); + if(xpoid_none == orientation) + { + XpOidList* content_orientations_supported; + + content_orientations_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_content_orientations_supported, + (XpOidList*)NULL); + orientation = XpOidListGetOid(content_orientations_supported, 0); + XpOidListDelete(content_orientations_supported); + } + return orientation; +} + +/* + * XpGetAvailableCompression determines the available-compression as + * determined by the passed context. The page and document pools are + * queried in turn for a specified content-orientation attribute. If none + * is found the first available-compression in the + * avaiable-compressions-supported printer attribute is taken as the + * default. + * + * Note: This routine assumes the values found in the passed context's + * attributes pools have been validated. + */ +XpOid +XpGetAvailableCompression( + XpContextPtr pContext) +{ + XpOid compression; + + compression = XpGetOidAttr(pContext, XPPageAttr, + xpoid_att_available_compression, + (XpOidList*)NULL); + if(xpoid_none == compression) + compression = XpGetOidAttr(pContext, XPDocAttr, + xpoid_att_available_compression, + (XpOidList*)NULL); + if(xpoid_none == compression) + { + XpOidList* available_compressions_supported; + + available_compressions_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_available_compressions_supported, + (XpOidList*)NULL); + compression = XpOidListGetOid(available_compressions_supported, 0); + XpOidListDelete(available_compressions_supported); + } + return compression; +} + +/* + * XpGetPlex determines the plex as determined by the passed context. The page + * and document pools are queried in turn for a specified plex attribute. If + * none is found the first plex in the plexes-supported printer attribute is + * taken as the default. + * + * Note: This routine assumes the values found in the passed context's + * attributes pools have been validated. + */ +XpOid +XpGetPlex( + XpContextPtr pContext) +{ + XpOid plex; + + plex = XpGetOidAttr(pContext, XPPageAttr, xpoid_att_plex, + (XpOidList*)NULL); + if(xpoid_none == plex) + plex = XpGetOidAttr(pContext, XPDocAttr, xpoid_att_plex, + (XpOidList*)NULL); + if(xpoid_none == plex) + { + XpOidList* plexes_supported; + + plexes_supported = + XpGetListAttr(pContext, XPPrinterAttr, + xpoid_att_plexes_supported, + (XpOidList*)NULL); + plex = XpOidListGetOid(plexes_supported, 0); + XpOidListDelete(plexes_supported); + } + return plex; +} + +/* + * XpGetPageSize returns the XpOid of the current page size (medium names + * are page sizes in this implementation) as indicated by the passed + * context. + * + * The relevant input-tray is returned in pTray. This parm must not be + * NULL. If the input-tray is not indicated or irrelevant, xpoid_none + * will be returned. + * + * This function optionally takes a XpOidMediumSS representation of the + * medium-source-sizes-supported attribute in order to avoid parsing the + * string value twice for calling functions that need to parse m-s-s-s + * anyway (e.g. XpGetReproductionArea). If the caller has no other reason + * to parse medium-source-sizes-supported, it is recommended that NULL be + * passed. This function will obtain medium-source-sizes-supported if it + * needs to. + * + * Note: This routine assumes the values found in the passed context's + * attributes pools have been validated. + */ +XpOid +XpGetPageSize(XpContextPtr pContext, + XpOid* pTray, + const XpOidMediumSS* msss) +{ + XpOid medium; + /* + * check to see if default-medium is specified + */ + medium = XpGetOidAttr(pContext, XPPageAttr, xpoid_att_default_medium, + (const XpOidList*)NULL); + if(medium == xpoid_none) + { + /* + * default-medium not in page pool; try the document pool + */ + medium = XpGetOidAttr(pContext, XPDocAttr, xpoid_att_default_medium, + (const XpOidList*)NULL); + } + if(medium == xpoid_none) + { + /* + * default-medium not specified; try default-input-tray + */ + *pTray = XpGetOidAttr(pContext, XPPageAttr, + xpoid_att_default_input_tray, + (const XpOidList*)NULL); + if(*pTray == xpoid_none) + { + /* + * default-input-tray not in page pool; try the document pool + */ + *pTray = XpGetOidAttr(pContext, XPDocAttr, + xpoid_att_default_input_tray, + (const XpOidList*)NULL); + } + if(*pTray != xpoid_none) + { + /* + * default-input-tray found; get corresponding medium from + * input-trays-medium + */ + XpOidTrayMediumList* input_trays_medium; + int i; + + input_trays_medium = + XpGetTrayMediumListAttr(pContext, XPPrinterAttr, + xpoid_att_input_trays_medium, + (const XpOidList*)NULL, + (const XpOidMediumSS*)NULL); + for(i = 0; i < XpOidTrayMediumListCount(input_trays_medium); i++) + { + if(*pTray == XpOidTrayMediumListTray(input_trays_medium, i)) + { + medium = XpOidTrayMediumListMedium(input_trays_medium, i); + break; + } + } + XpOidTrayMediumListDelete(input_trays_medium); + } + } + else + *pTray = xpoid_none; + + if(medium == xpoid_none) + { + XpOidMediumSS* local_msss = (XpOidMediumSS*)NULL; + int i_mss, i_ds; + XpOidMediumDiscreteSizeList* ds_list; + /* + * no medium specified; use 1st page size found in + * medium-source-sizes-supported + */ + if((XpOidMediumSS*)NULL == msss) + msss = local_msss = + XpGetMediumSSAttr(pContext, XPPrinterAttr, + xpoid_att_medium_source_sizes_supported, + (const XpOidList*)NULL, + (const XpOidList*)NULL); + for(i_mss = 0; + i_mss < XpOidMediumSSCount(msss) && xpoid_none == medium; + i_mss++) + { + if(XpOidMediumSS_DISCRETE == (msss->mss)[i_mss].mstag + && + xpoid_none != (msss->mss)[i_mss].input_tray) + { + ds_list = (msss->mss)[i_mss].ms.discrete; + for(i_ds = 0; i_ds < ds_list->count; i_ds++) + { + if(xpoid_none != (ds_list->list)[i_ds].page_size) + { + medium = (ds_list->list)[i_ds].page_size; + break; + } + } + } + } + XpOidMediumSSDelete(local_msss); + } + return medium; +} + +/* + * XpGetMediumMillimeters returns into the supplied float pointers the + * width and height in millimeters of the passed page size identifier. + */ +void +XpGetMediumMillimeters( + XpOid page_size, + float *width, /* return */ + float *height) /* return */ +{ + int i; + + *width = *height = 0; + for(i = 0; i < XpNumber(PageDimensions); i++) + { + if(page_size == PageDimensions[i].page_size) + { + *width = PageDimensions[i].width; + *height = PageDimensions[i].height; + return; + } + } +} + +/* + * Converts a millimeter specification into pixels given a resolution in + * DPI. + */ +static float +MmToPixels(float mm, int resolution) +{ + float f; + + f = mm * resolution; + f /= 25.4; + return f; +} + +/* + * XpGetMediumDimensions returns into the supplied short pointers the + * width and height in pixels of the medium associated with the specified + * print context. It obtains the page size associated with the current + * medium by calling XpGetPageSize. It passes XpGetMediumMillimeters the + * page size, and converts the returned millimeter dimensions into pixels + * using the resolution returned by XpGetResolution. + * + * Note: This routine assumes the values found in the passed context's + * attributes pools have been validated. + */ +void +XpGetMediumDimensions( + XpContextPtr pContext, + unsigned short *width, /* return */ + unsigned short *height) /* return */ +{ + XpOid page_size; + XpOid tray; + XpOid orientation; + + int resolution; + float w_mm, h_mm; + + page_size = XpGetPageSize(pContext, &tray, (XpOidMediumSS*)NULL); + if(page_size == xpoid_none) + { + /* + * fail-safe: if the pools have been validated, this defaulting logic + * isn't needed. + */ + page_size = xpoid_val_medium_size_na_letter; + } + XpGetMediumMillimeters(page_size, &w_mm, &h_mm); + resolution = XpGetResolution(pContext); + orientation = XpGetContentOrientation(pContext); + switch(orientation) + { + case xpoid_val_content_orientation_landscape: + case xpoid_val_content_orientation_reverse_landscape: + /* + * transpose width and height + */ + *height = MmToPixels(w_mm, resolution); + *width = MmToPixels(h_mm, resolution); + break; + + default: + *width = MmToPixels(w_mm, resolution); + *height = MmToPixels(h_mm, resolution); + break; + } +} + +/* + * XRectangleFromXpOidArea converts an XpOidArea area specification + * into an XRectangle. The passed resolution is used to convert from + * millimeters (XpOidArea) into pixels (XRectangle). + */ +static void +XRectangleFromXpOidArea( + xRectangle *pRect, + const XpOidArea* repro, + int resolution, + XpOid orientation) +{ + switch(orientation) + { + case xpoid_val_content_orientation_landscape: + case xpoid_val_content_orientation_reverse_landscape: + /* + * transpose x and y, width and height + */ + pRect->y = MmToPixels(repro->minimum_x, resolution); + pRect->x = MmToPixels(repro->minimum_y, resolution); + pRect->height = + MmToPixels(repro->maximum_x - repro->minimum_x, resolution); + pRect->width = + MmToPixels(repro->maximum_y - repro->minimum_y, resolution); + break; + + default: + pRect->x = MmToPixels(repro->minimum_x, resolution); + pRect->y = MmToPixels(repro->minimum_y, resolution); + pRect->width = + MmToPixels(repro->maximum_x - repro->minimum_x, resolution); + pRect->height = + MmToPixels(repro->maximum_y - repro->minimum_y, resolution); + break; + } +} + +/* + * XpGetReproductionArea queries the current pool attribute values in + * order to determine the reproduction area for the currently selected + * medium. + * + * First the current page size (equivalent to current medium) and tray + * (if specified) is retrieved via XpGetPageSize. The value of the + * medium-source-sizes-supported attribute is interrogated until a matching + * entry for the current page size and tray is found. The reproduction + * area defined for the current entry is converted into an XRectangle + * using XRectangleFromXpOidArea and returned to the caller. + * + * Note: This routine assumes the values found in the passed context's + * attributes pools have been validated. + */ +void +XpGetReproductionArea(XpContextPtr pContext, + xRectangle *pRect) +{ + XpOid page_size; + XpOid tray; + XpOidMediumSS* msss; + int i_mss, i_ds; + XpOidMediumDiscreteSizeList* ds_list; + XpOidArea* repro; + BOOL done; + int resolution; + XpOid orientation; + /* + * find the appropriate assured reproduction area for the current + * tray and page size in the medium-source-sizes-supported attribute. + */ + msss = XpGetMediumSSAttr(pContext, XPPrinterAttr, + xpoid_att_medium_source_sizes_supported, + (const XpOidList*)NULL, + (const XpOidList*)NULL); + page_size = XpGetPageSize(pContext, &tray, msss); + resolution = XpGetResolution(pContext); + orientation = XpGetContentOrientation(pContext); + + memset(pRect, 0, sizeof(xRectangle)); + + if(xpoid_none == tray) + { + /* + * no tray specified; use 1st matching page size + */ + for(i_mss = 0, done = xFalse; + i_mss < XpOidMediumSSCount(msss) && !done; + i_mss++) + { + if(XpOidMediumSS_DISCRETE == (msss->mss)[i_mss].mstag + && + xpoid_none != (msss->mss)[i_mss].input_tray) + { + ds_list = (msss->mss)[i_mss].ms.discrete; + for(i_ds = 0; i_ds < ds_list->count; i_ds++) + { + if(page_size == (ds_list->list)[i_ds].page_size) + { + repro = + &(ds_list->list)[i_ds].assured_reproduction_area; + XRectangleFromXpOidArea(pRect, repro, + resolution, orientation); + done = xTrue; + break; + } + } + } + } + } + else + { + /* + * tray && page size specified; find matching entry + */ + for(i_mss = 0, done = xFalse; + i_mss < XpOidMediumSSCount(msss) && !done; + i_mss++) + { + if(XpOidMediumSS_DISCRETE == (msss->mss)[i_mss].mstag + && + xpoid_none != (msss->mss)[i_mss].input_tray + && + (tray == (msss->mss)[i_mss].input_tray + || + xpoid_unspecified == (msss->mss)[i_mss].input_tray) + ) + { + ds_list = (msss->mss)[i_mss].ms.discrete; + for(i_ds = 0; i_ds < ds_list->count; i_ds++) + { + if(page_size == (ds_list->list)[i_ds].page_size) + { + repro = + &(ds_list->list)[i_ds].assured_reproduction_area; + XRectangleFromXpOidArea(pRect, repro, + resolution, orientation); + if(xpoid_unspecified != (msss->mss)[i_mss].input_tray) + { + /* + * exact match on tray takes precendence over + * unspecified tray entry in m-s-s-s + */ + done = xTrue; + } + break; + } + } + } + } + } + XpOidMediumSSDelete(msss); +} + +/* + * XpGetMaxWidthHeightRes returns into the supplied width and height + * unsigned short pointers the dimensions in millimeters of the largest + * supported media for a specific printer. It looks at the + * medium-source-sizes-supported attribute (if it exists) to determine + * the list of possible media, and calls XpGetMediumMillimeters to get the + * dimensions for each medium. If the m-s-s-s attribute is not defined, + * then the dimensions for the na-letter medium is returned. + * + * This function also returns the largest resolution in DPI defined in + * printer-resolutions-supported. If printer-resolutions-supported is not + * specified, the default is obtained from the passed XpValidatePoolsRec. + * + * The passed XpValidatePoolsRec is also used to determine valid values + * when parsing attribute values. + */ +void +XpGetMaxWidthHeightRes( + const char *printer_name, + const XpValidatePoolsRec* vpr, + float *width, + float *height, + int* resolution) +{ + const char* value; + const char* attr_str; + XpOidMediumSS* pool_msss; + const XpOidMediumSS* msss; + int i_mss, i_ds; + XpOidMediumDiscreteSizeList* ds_list; + float w, h; + XpOidCardList* pool_resolutions_supported; + const XpOidCardList* resolutions_supported; + int i; + int res; + /* + * get the max medium width and height + */ + attr_str = XpOidString(xpoid_att_medium_source_sizes_supported); + value = XpGetPrinterAttribute(printer_name, attr_str); + pool_msss = XpOidMediumSSNew(value, + vpr->valid_input_trays, + vpr->valid_medium_sizes); + if(0 == XpOidMediumSSCount(pool_msss)) + msss = XpGetDefaultMediumSS(); + else + msss = pool_msss; + *width = *height = 0; + for(i_mss = 0; i_mss < XpOidMediumSSCount(msss); i_mss++) + { + if(XpOidMediumSS_DISCRETE == (msss->mss)[i_mss].mstag + && + xpoid_none != (msss->mss)[i_mss].input_tray) + { + ds_list = (msss->mss)[i_mss].ms.discrete; + for(i_ds = 0; i_ds < ds_list->count; i_ds++) + { + if(xpoid_none != (ds_list->list)[i_ds].page_size) + { + XpGetMediumMillimeters((ds_list->list)[i_ds].page_size, + &w, &h); + if(w > *width) *width = w; + if(h > *height) *height = h; + } + } + } + } + XpOidMediumSSDelete(pool_msss); + /* + * get the maximum resolution + */ + attr_str = XpOidString(xpoid_att_printer_resolutions_supported); + value = XpGetPrinterAttribute(printer_name, attr_str); + pool_resolutions_supported = + XpOidCardListNew(value, vpr->valid_printer_resolutions_supported); + if(0 == XpOidCardListCount(pool_resolutions_supported)) + resolutions_supported = vpr->default_printer_resolutions_supported; + else + resolutions_supported = pool_resolutions_supported; + *resolution = 0; + for(i = 0; i < XpOidCardListCount(resolutions_supported); i++) + { + res = XpOidCardListGetCard(resolutions_supported, i); + if(res > *resolution) *resolution = res; + } + XpOidCardListDelete(pool_resolutions_supported); +} + +FontResolutionPtr +XpGetClientResolutions(client, num) + ClientPtr client; + int *num; +{ + static struct _FontResolution res; + int resolution = XpGetResolution(XpContextOfClient(client)); + + res.x_resolution = resolution; + res.y_resolution = resolution; + + res.point_size = 120; + + *num = 1; + + return &res; +} + + +void XpSetFontResFunc(client) + ClientPtr client; +{ + client->fontResFunc = XpGetClientResolutions; +} + + +void XpUnsetFontResFunc(client) + ClientPtr client; +{ + client->fontResFunc = NULL; +} diff --git a/Xprint/pcl/Pcl.h b/Xprint/pcl/Pcl.h new file mode 100644 index 000000000..0f744eafe --- /dev/null +++ b/Xprint/pcl/Pcl.h @@ -0,0 +1,580 @@ +/* $Xorg: Pcl.h,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: Pcl.h +** * +** * Contents: defines and includes for the Pcl driver +** * for a printing X server. +** * +** * Created: 1/30/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#ifndef _PCL_H_ +#define _PCL_H_ + +#include +#include "scrnintstr.h" + +/* +#include "X.h" +#include "Xproto.h" +#include "Xatom.h" +#include "misc.h" +#include "screenint.h" +#include "colormapst.h" +#include "windowstr.h" +#include "propertyst.h" +#include "servermd.h" */ /* needed for IMAGE_BUFSIZE */ + +#include "PclDef.h" +#include "Pclmap.h" +#include "PclSFonts.h" + +#define _XP_PRINT_SERVER_ +#include "Print.h" +#include "extensions/Printstr.h" +#undef _XP_PRINT_SERVER_ + +#include "miscstruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" + +/* + * Some sleazes to force the XrmDB stuff into the server + */ +typedef char *XPointer; +#define Status int +#define True 1 +#define False 0 +#include "misc.h" +#include +#include "../Xresource.h" + +/****** + * externally visible variables from PclInit.c + ******/ +extern int PclScreenPrivateIndex, PclWindowPrivateIndex; +extern int PclContextPrivateIndex; +extern int PclPixmapPrivateIndex; +extern int PclGCPrivateIndex; + +/* + * This structure defines a mapping from an X colormap ID to a list of + * print contexts which use the colormap. + */ +typedef struct _pclcontextlist { + XpContextPtr context; + struct _pclcontextlist *next; +} PclContextList, *PclContextListPtr; + +typedef struct _pclcmaptocontexts { + long colormapId; + PclContextListPtr contexts; + struct _pclcmaptocontexts *next; +} PclCmapToContexts; + +typedef struct { + PclCmapToContexts *colormaps; + CloseScreenProcPtr CloseScreen; +} PclScreenPrivRec, *PclScreenPrivPtr; + +/* + * This structure defines a mapping from an X colormap ID to a PCL + * palette ID. + */ +typedef struct _palettemap { + long colormapId; + int paletteId; + int downloaded; + struct _palettemap *next; +} PclPaletteMap, *PclPaletteMapPtr; + +typedef struct { + char *jobFileName; + FILE *pJobFile; + char *pageFileName; + FILE *pPageFile; + GC lastGC; + unsigned char *dash; + int validGC; + ClientPtr getDocClient; + int getDocBufSize; + PclSoftFontInfoPtr pSoftFontInfo; + PclPaletteMapPtr palettes; + int currentPalette; + int nextPaletteId; + PclPaletteMap staticGrayPalette; + PclPaletteMap trueColorPalette; + PclPaletteMap specialTrueColorPalette; + unsigned char *ctbl; + int ctbldim; + int isRaw; +#ifdef XP_PCL_LJ3 + unsigned int fcount; + unsigned int fcount_max; + char *figures; +#endif /* XP_PCL_LJ3 */ +} PclContextPrivRec, *PclContextPrivPtr; + +typedef struct { + int validContext; + XpContextPtr context; +} PclWindowPrivRec, *PclWindowPrivPtr; + +typedef struct { + unsigned freeCompClip; + RegionPtr pCompositeClip; + unsigned long stippleFg, stippleBg; +} PclGCPrivRec, *PclGCPrivPtr; + +typedef struct { + XpContextPtr context; + char *tempFileName; + FILE *tempFile; + GC lastGC; + int validGC; +} PclPixmapPrivRec, *PclPixmapPrivPtr; + +/****** + * Defined functions + ******/ +#define SEND_PCL(f,c) fwrite( c, sizeof( char ), strlen( c ), f ) +#define SEND_PCL_COUNT(f,c,n) fwrite( c, sizeof( char ), n, f ) + +#ifndef XP_PCL_LJ3 +#define SAVE_PCL(f,p,c) SEND_PCL(f,c) +#define SAVE_PCL_COUNT(f,p,c,n) SEND_PCL_COUNT(f,c,n) +#define MACRO_START(f,p) SEND_PCL(f, "\033&f1Y\033&f0X") +#define MACRO_END(f) SEND_PCL(f, "\033&f1X") +#else +#define SAVE_PCL(f,p,c) PclSpoolFigs(p, c, strlen(c)) +#define SAVE_PCL_COUNT(f,p,c,n) PclSpoolFigs(p, c, n) +#define MACRO_START(f,p) p->fcount = 0 +#define MACRO_END(f) /* do nothing */ +#endif /* XP_PCL_LJ3 */ + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/****** + * Functions in PclArc.c + ******/ +extern void PclPolyArc( + DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs); +extern void PclPolyFillArc( + DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs); + +/****** + * Functions in PclArea.c + ******/ +extern void PclPutImage( + DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage); +extern RegionPtr PclCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty); +RegionPtr PclCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long plane); + + +/****** + * Functions in PclAttr.c + ******/ +extern char *PclGetAttributes( + XpContextPtr pCon, + XPAttributes pool ); +extern char *PclGetOneAttribute( + XpContextPtr pCon, + XPAttributes pool, + char *attr ); +extern int PclAugmentAttributes( + XpContextPtr pCon, + XPAttributes pool, + char *attrs ); +extern int PclSetAttributes( + XpContextPtr pCon, + XPAttributes pool, + char *attrs ); + +/****** + * Functions in PclColor.c + ******/ +extern Bool PclCreateDefColormap(ScreenPtr pScreen); +extern Bool PclCreateColormap(ColormapPtr pColor); +extern void PclDestroyColormap(ColormapPtr pColor); +extern void PclInstallColormap(ColormapPtr pColor); +extern void PclUninstallColormap(ColormapPtr pColor); +extern int PclListInstalledColormaps(ScreenPtr pScreen, + XID *pCmapList); +extern void PclStoreColors(ColormapPtr pColor, + int ndef, + xColorItem *pdefs); +extern void PclResolveColor(unsigned short *pRed, + unsigned short *pGreen, + unsigned short *pBlue, + VisualPtr pVisual); +extern int PclUpdateColormap(DrawablePtr pDrawable, + XpContextPtr pCon, + GCPtr gc, + FILE *outFile); + +/****** + * Functions in PclCursor.c + ******/ +extern void PclConstrainCursor( + ScreenPtr pScreen, + BoxPtr pBox); +extern void PclCursorLimits( + ScreenPtr pScreen, + CursorPtr pCursor, + BoxPtr pHotBox, + BoxPtr pTopLeftbox); +extern Bool PclDisplayCursor( + ScreenPtr pScreen, + CursorPtr pCursor); +extern Bool PclRealizeCursor( + ScreenPtr pScreen, + CursorPtr pCursor); +extern Bool PclUnrealizeCursor( + ScreenPtr pScreen, + CursorPtr pCursor); +extern void PclRecolorCursor( + ScreenPtr pScreen, + CursorPtr pCursor, + Bool displayed); +extern Bool PclSetCursorPosition( + ScreenPtr pScreen, + int x, + int y, + Bool generateEvent); + +/****** + * Functions in PclGC.c + ******/ +extern Bool PclCreateGC(GCPtr pGC); +extern void PclDestroyGC(GCPtr pGC); +extern int PclUpdateDrawableGC( + GCPtr pGC, + DrawablePtr pDrawable, + FILE **outFile); +extern void PclValidateGC( + GCPtr pGC, + Mask changes, + DrawablePtr pDrawable); +extern void PclSetDrawablePrivateStuff( + DrawablePtr pDrawable, + GC gc ); +extern int PclGetDrawablePrivateStuff( + DrawablePtr pDrawable, + GC *gc, + unsigned long *valid, + FILE **file ); + +/****** + * Functions in PclInit.c + ******/ +extern Bool InitializePclDriver( + int ndx, + ScreenPtr pScreen, + int argc, + char **argv); +static Bool PclDestroyContext( XpContextPtr pCon ); +extern XpContextPtr PclGetContextFromWindow( WindowPtr win ); + +/****** + * Functions in PclLine.c + ******/ +extern void PclPolyLine( + DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int nPoints, + xPoint *pPoints); +extern void PclPolySegment( + DrawablePtr pDrawable, + GCPtr pGC, + int nSegments, + xSegment *pSegments); + +/****** + * Functions in PclMisc.c + ******/ +extern void PclQueryBestSize( + int class, + short *pwidth, + short *pheight, + ScreenPtr pScreen); +extern char *GetPropString(WindowPtr pWin, char *propName); +extern int SystemCmd(char *cmdStr); +extern int PclGetMediumDimensions( + XpContextPtr pCon, + CARD16 *pWidth, + CARD16 *pHeight); +extern int PclGetReproducibleArea( + XpContextPtr pCon, + xRectangle *pRect); + +/****** + * Functions in PclPixel.c + ******/ +extern void PclPolyPoint( + DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int nPoints, + xPoint *pPoints); +extern void PclPushPixels( + GCPtr pGC, + PixmapPtr pBitmap, + DrawablePtr pDrawable, + int width, + int height, + int x, + int y); + +/****** + * Functions in PclPixmap.c + ******/ +extern PixmapPtr PclCreatePixmap( + ScreenPtr pScreen, + int width, + int height, + int depth); +extern Bool PclDestroyPixmap(PixmapPtr pPixmap); + +/****** + * Functions in PclPolygon.c + ******/ +extern void PclPolyRectangle( + DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects); +extern void PclFillPolygon( + DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int nPoints, + DDXPointPtr pPoints); +extern void PclPolyFillRect( + DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects); + +/****** + * Functions in PclSpans.c + ******/ +extern void PclFillSpans( + DrawablePtr pDrawable, + GCPtr pGC, + int nSpans, + DDXPointPtr pPoints, + int *pWidths, + int fSorted); +extern void PclSetSpans( + DrawablePtr pDrawable, + GCPtr pGC, + char *pSrc, + DDXPointPtr pPoints, + int *pWidths, + int nSpans, + int fSorted); + +/****** + * Functions in PclText.c + ******/ +extern int PclPolyText8( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *string); +extern int PclPolyText16( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *string); +extern void PclImageText8( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *string); +extern void PclImageText16( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *string); +extern void PclImageGlyphBlt( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nGlyphs, + CharInfoPtr *pCharInfo, + pointer pGlyphBase); +extern void PclPolyGlyphBlt( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nGlyphs, + CharInfoPtr *pCharInfo, + pointer pGlyphBase); + +/****** + * Functions in PclWindow.c + ******/ +extern Bool PclCreateWindow(register WindowPtr pWin); +extern Bool PclDestroyWindow(WindowPtr pWin); +extern Bool PclMapWindow(WindowPtr pWindow); +extern Bool PclPositionWindow( + register WindowPtr pWin, + int x, + int y); +extern Bool PclUnmapWindow(WindowPtr pWindow); +extern Bool PclUnmapWindow(WindowPtr pWindow); +extern void PclCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +extern Bool PclChangeWindowAttributes( + register WindowPtr pWin, + register unsigned long mask); +extern void PclPaintWindow( + WindowPtr pWin, + RegionPtr pRegion, + int what); + +/****** + * Functions in PclFonts.c + ******/ +extern Bool PclRealizeFont( + ScreenPtr pscr, + FontPtr pFont); +extern Bool PclUnrealizeFont( + ScreenPtr pscr, + FontPtr pFont); + +/****** + * Functions in PclPrint.c + ******/ +extern int PclStartJob( + XpContextPtr pCon, + Bool sendClientData, + ClientPtr client); +extern int PclEndJob( + XpContextPtr pCon, + Bool cancel); +extern int PclStartPage( + XpContextPtr pCon, + WindowPtr pWin); +extern int PclEndPage( + XpContextPtr pCon, + WindowPtr pWin); +extern int PclStartDoc(XpContextPtr pCon, + XPDocumentType type); +extern int PclEndDoc( + XpContextPtr pCon, + Bool cancel); +extern int PclDocumentData( + XpContextPtr pCon, + DrawablePtr pDraw, + char *pData, + int len_data, + char *pFmt, + int len_fmt, + char *pOpt, + int len_opt, + ClientPtr client); +extern int PclGetDocumentData( + XpContextPtr pCon, + ClientPtr client, + int maxBufferSize); + + +#endif /* _PCL_H_ */ + + + + + + + + + diff --git a/Xprint/pcl/PclArc.c b/Xprint/pcl/PclArc.c new file mode 100644 index 000000000..ffdf32907 --- /dev/null +++ b/Xprint/pcl/PclArc.c @@ -0,0 +1,264 @@ +/* $Xorg: PclArc.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclArc.c +** * +** * Contents: +** * Arc-drawing code for the PCL DDX driver +** * +** * Created: 10/23/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include +#include +#include + +#include "Pcl.h" +#include "gcstruct.h" +#include "windowstr.h" + +static void +PclDoArc( pDrawable, pGC, nArcs, pArcs, DoIt ) + DrawablePtr pDrawable; + GCPtr pGC; + int nArcs; + xArc *pArcs; + void (*DoIt)(); +{ + char t[80]; + FILE *outFile; + int nbox, i; + BoxPtr pbox; + BoxRec r; + RegionPtr drawRegion, region, transClip; + short fudge; + int xoffset, yoffset; + XpContextPtr pCon; + PclContextPrivPtr pConPriv; + xRectangle repro; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + fudge = 3 * pGC->lineWidth; + + pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + XpGetReproductionArea( pCon, &repro ); + + /* + * Generate the PCL code to draw the collection of arcs, by + * defining it as a macro which uses the HP-GL/2 arc drawing + * function. + */ + + xoffset = pDrawable->x; + yoffset = pDrawable->y; + + for( i = 0; i < nArcs; i++ ) + { + xArc Arc = pArcs[i]; + double b, X, Y, ratio; + double angle1; + + MACRO_START( outFile, pConPriv ); + SAVE_PCL( outFile, pConPriv, "\033%0B" ); + + /* Calculate the start of the arc */ + if( ( Arc.angle1 / 64 ) % 360 == 90 ) + { + X = 0; + Y = -Arc.height / 2.0; + } + else if( ( Arc.angle1 / 64 ) % 360 == 270 ) + { + X = 0; + Y = Arc.height / 2.0; + } + else + { + /* Convert the angle to radians */ + angle1 = ( Arc.angle1 / 64.0 ) * 3.141592654 / 180.0; + + b = (Arc.height / 2.0); + X = b * cos( angle1 ); + Y = -b * sin( angle1 ); + } + + /* Change the coordinate system to scale the ellipse */ + ratio = (double)Arc.height / (double)Arc.width; + + sprintf( t, "SC%.2f,%.2f,%d,%d;", + (repro.x - Arc.width / 2 - xoffset - Arc.x) * ratio, + (repro.x - Arc.width / 2 - xoffset - Arc.x + + repro.width) * ratio, + repro.y - Arc.height / 2 - yoffset - Arc.y + repro.height, + repro.y - Arc.height / 2 - yoffset - Arc.y); + SAVE_PCL( outFile, pConPriv, t ); + + DoIt( outFile, pConPriv, X, Y, Arc ); + + /* Build the bounding box */ + r.x1 = -Arc.width / 2 - fudge; + r.y1 = -Arc.height / 2 - fudge; + r.x2 = Arc.width / 2 + fudge; + r.y2 = Arc.height / 2 + fudge; + drawRegion = miRegionCreate( &r, 0 ); + + SAVE_PCL( outFile, pConPriv, "\033%0A" ); + MACRO_END( outFile ); + + /* + * Intersect the bounding box with the clip region. + */ + region = miRegionCreate( NULL, 0 ); + transClip = miRegionCreate( NULL, 0 ); + miRegionCopy( transClip, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + miTranslateRegion( transClip, -(xoffset + Arc.x + Arc.width / 2), + -(yoffset + Arc.y + Arc.height / 2) ); + miIntersect( region, drawRegion, transClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the collection of arcs to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, ratio); + + /* + * Restore the coordinate system + */ + sprintf( t, "\033%%0BSC%d,%d,%d,%d;\033%%0A", repro.x, + repro.x + repro.width, repro.y + repro.height, + repro.y ); + SEND_PCL( outFile, t ); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + miRegionDestroy( transClip ); + } +} + +/* + * Draw a simple non-filled arc, centered on the origin and starting + * at the given point. + */ +static void +DrawArc(FILE *outFile, + PclContextPrivPtr pConPriv, + double X, + double Y, + xArc A) +{ + char t[80]; + + sprintf( t, "PU%d,%d;PD;AA0,0,%.2f;", (int)X, (int)Y, + (float)A.angle2 / -64.0 ); + SAVE_PCL(outFile, pConPriv, t); +} + +void +PclPolyArc( pDrawable, pGC, nArcs, pArcs ) + DrawablePtr pDrawable; + GCPtr pGC; + int nArcs; + xArc *pArcs; +{ + PclDoArc( pDrawable, pGC, nArcs, pArcs, DrawArc ); +} + +/* + * Draw a filled wedge, from the origin, to the given point, through + * the appropriate angle, and back to the origin. + */ +static void +DoWedge(FILE *outFile, + PclContextPrivPtr pConPriv, + double X, + double Y, + xArc A) +{ + char t[80]; + + sprintf( t, "PU0,0;WG%.2f,%.2f,%.2f;", sqrt( X * X + Y * Y ), + (float)A.angle1 / -64.0, + (float)A.angle2 / -64.0 ); + SAVE_PCL(outFile, pConPriv, t); +} + +static void +DoChord(FILE *outFile, + PclContextPrivPtr pConPriv, + double X, + double Y, + xArc A) +{ + char t[80]; + + sprintf( t, "PU%d,%d;PM0;AA0,0,%.2f;PA%d,%d;PM2;FP;", (int)X, (int)Y, + (float)A.angle2 / -64.0 , (int)X, (int)Y ); + SAVE_PCL(outFile, pConPriv, t); +} + + +void +PclPolyFillArc( pDrawable, pGC, nArcs, pArcs ) + DrawablePtr pDrawable; + GCPtr pGC; + int nArcs; + xArc *pArcs; +{ + switch( pGC->arcMode ) + { + case ArcChord: + PclDoArc( pDrawable, pGC, nArcs, pArcs, DoChord ); + break; + case ArcPieSlice: + PclDoArc( pDrawable, pGC, nArcs, pArcs, DoWedge ); + break; + } +} diff --git a/Xprint/pcl/PclArea.c b/Xprint/pcl/PclArea.c new file mode 100644 index 000000000..da3107d5a --- /dev/null +++ b/Xprint/pcl/PclArea.c @@ -0,0 +1,487 @@ +/* $Xorg: PclArea.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclArea.c +** * +** * Contents: +** * Image and Area functions for the PCL DDX driver +** * +** * Created: 10/23/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include +#include +#include +#include "Pcl.h" +#include "pixmapstr.h" +#include "region.h" + +#include "cfb.h" + +void +PclPutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage) +{ + PixmapPtr pPixmap; + unsigned long oldFg, oldBg; + XID gcv[3]; + unsigned long oldPlanemask; + unsigned long i; + long bytesPer; + + if( ( w == 0 ) || ( h == 0 ) ) + return; + + if( format != XYPixmap ) + { + pPixmap = GetScratchPixmapHeader( pDrawable->pScreen, + w+leftPad, h, depth, + BitsPerPixel( depth ), + PixmapBytePad( w + leftPad, + depth ), (pointer)pImage ); + if( !pPixmap ) + return; + + if( format == ZPixmap ) + (void)(*pGC->ops->CopyArea)( (DrawablePtr)pPixmap, pDrawable, pGC, + leftPad, 0, w, h, x, y ); + else + (void)(*pGC->ops->CopyPlane)( (DrawablePtr)pPixmap, pDrawable, pGC, + leftPad, 0, w, h, x, y, 1 ); + FreeScratchPixmapHeader( pPixmap ); + } + else + { + pPixmap = GetScratchPixmapHeader( pDrawable->pScreen, + w+leftPad, h, depth, + BitsPerPixel( depth ), + PixmapBytePad( w + leftPad, + depth ), (pointer)pImage ); + + if( !pPixmap ) + return; + + depth = pGC->depth; + oldPlanemask = pGC->planemask; + oldFg = pGC->fgPixel; + oldBg = pGC->bgPixel; + gcv[0] = ~0L; + gcv[1] = 0; + DoChangeGC( pGC, GCForeground | GCBackground, gcv, 0 ); + bytesPer = (long)h * BitmapBytePad( w + leftPad ); + + for( i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer ) + { + if( i & oldPlanemask ) + { + extern void cfbPutImage(), cfb32PutImage(); + gcv[0] = i; + DoChangeGC( pGC, GCPlaneMask, gcv, 0 ); + ValidateGC( pDrawable, pGC ); + if (pPixmap->drawable.depth <= 8 ) + cfbPutImage( (DrawablePtr)pPixmap, pGC, 1, x, y, w, h, + leftPad, XYBitmap, pImage ); + else if (pPixmap->drawable.depth <= 32 ) + cfb32PutImage( (DrawablePtr)pPixmap, pGC, 1, x, y, w, h, + leftPad, XYBitmap, pImage ); + } + } + gcv[0] = oldPlanemask; + gcv[1] = oldFg; + gcv[2] = oldBg; + DoChangeGC( pGC, GCPlaneMask | GCForeground | GCBackground, + gcv, 0 ); + + PclCopyArea( (DrawablePtr)pPixmap, pDrawable, pGC, leftPad, + 0, w, h, x, y ); + FreeScratchPixmapHeader( pPixmap ); + } +} + +/* + * PclMonoPixmapFragment() + * + * Given a 1-bit-deep pixmap, send the appropriate part of it to the + * output file as a PCL raster graphics command. + */ +static void +PclMonoPixmapFragment(FILE *outFile, + PixmapPtr pix, + short x1, + short y1, + short x2, + short y2, + short dstx, + short dsty) +{ + char *bits, t[80], *row; + int h, w, i; + + /* + * Create a storage area large enough to hold the entire pixmap, + * then use mfbGetImage to get the appropriate bits. + */ + h = y2 - y1; + w = BitmapBytePad( x2 - x1 ); + + bits = (char *)xalloc( h * w ); + mfbGetImage( (DrawablePtr)pix, x1, y1, x2 - x1, h, + XYPixmap, ~0, bits ); + + /* + * Move the cursor to the appropriate place on the page. We have + * to jump into HP-GL/2 to do this correctly, then go back to PCL + * for the actual drawing. + */ + sprintf( t, "\033%%0BPU%d,%d;\033%%1A", dstx, dsty ); + SEND_PCL( outFile, t ); + + /* + * Now, wrap the raster in the appropriate PCL code. Right now, + * it's going to go down the wire without any compression. That + * will have to be good enough for the sample implementation. + */ + sprintf( t, "\033*t300R\033*r%dT\033*r%dS\033*r1A\033*b0M", + h, x2 - x1 ); + SEND_PCL( outFile, t ); + + sprintf( t, "\033*b%dW", w ); + for( row = bits, i = 0; i <= h; i++, row += w ) + { + SEND_PCL( outFile, t ); + SEND_PCL_COUNT( outFile, row, w ); + } + + SEND_PCL( outFile, "\033*rC" ); + + /* + * Clean things up a bit + */ + xfree( bits ); +} + +static void +PclColorPixmapFragment(FILE *outFile, + PixmapPtr pix, + short x1, + short y1, + short x2, + short y2, + short dstx, + short dsty) +{ + char *bits, t[80], *row; + int h, w, i; + extern void cfbGetImage(), cfb32GetImage(); + + /* + * Create a storage area large enough to hold the entire pixmap, + * then use cfbGetImage to get the appropriate bits. + */ + h = y2 - y1; + w = PixmapBytePad( x2 - x1, pix->drawable.depth ); + + bits = (char *)xalloc( h * w ); + if (pix->drawable.depth <= 8) + cfbGetImage( (DrawablePtr)pix, x1, y1, x2 - x1, h, + ZPixmap, ~0, bits ); + else if (pix->drawable.depth <= 32) + cfb32GetImage( (DrawablePtr)pix, x1, y1, x2 - x1, h, + ZPixmap, ~0, bits ); + + /* + * Move the cursor to the appropriate place on the page. We have + * to jump into HP-GL/2 to do this correctly, then go back to PCL + * for the actual drawing. + */ + sprintf( t, "\033%%0BPU%d,%d;\033%%1A", dstx, dsty ); + SEND_PCL( outFile, t ); + + /* + * Now, wrap the raster in the appropriate PCL code. Right now, + * it's going to go down the wire without any compression. That + * will have to be good enough for the sample implementation. + */ + sprintf( t, "\033*t300R\033*r%dt%ds1A\033*b0M", + h, x2 - x1 ); + SEND_PCL( outFile, t ); + + sprintf( t, "\033*b%dW", w ); + for( row = bits, i = 0; i < h; i++, row += w ) + { + SEND_PCL( outFile, t ); + SEND_PCL_COUNT( outFile, row, w ); + } + + SEND_PCL( outFile, "\033*rC" ); + + /* + * Clean things up a bit + */ + xfree( bits ); +} + +RegionPtr +PclCopyArea(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty) +{ + PixmapPtr pixSrc = (PixmapPtr)pSrc; + char t[80]; + FILE *srcFile, *dstFile; + GC srcGC, dstGC; + unsigned long valid; + struct stat statBuf; + XpContextPtr pCon; + xRectangle repro; + PclPixmapPrivPtr pPriv; + RegionPtr drawRegion, region, whole, ret; + BoxRec box; + BoxPtr prect; + int nrect; + void (*doFragment)(FILE *, PixmapPtr, short, short, short, short, + short, short ); + extern RegionPtr mfbCopyArea(), cfbCopyArea(), cfb32CopyArea(); + + /* + * Since we don't store any information on a per-window basis, we + * can't copy from a window. + */ + if( pSrc->type == DRAWABLE_WINDOW ) + return NULL; + + /* + * If we're copying from a pixmap to a pixmap, we just use the + * mfb/cfb code to do the work. + */ + if( pDst->type == DRAWABLE_PIXMAP ) + { + if( pSrc->depth == 1 ) + return mfbCopyArea( pSrc, pDst, pGC, srcx, srcy, width, + height, dstx, dsty ); + else if( pSrc->depth <= 8 ) + return cfbCopyArea( pSrc, pDst, pGC, srcx, srcy, width, + height, dstx, dsty ); + else if( pSrc->depth <= 32 ) + return cfb32CopyArea( pSrc, pDst, pGC, srcx, srcy, width, + height, dstx, dsty ); + } + +/* + PclGetDrawablePrivateStuff( pSrc, &srcGC, &valid, &srcFile ); +*/ + PclGetDrawablePrivateStuff( pDst, &dstGC, &valid, &dstFile ); + + /* + * If we're copying to a window, we have to do some actual + * drawing, instead of just handing it off to mfb or cfb. Start + * by determining the region that will be drawn. + */ + box.x1 = srcx; + box.y1 = srcy; + box.x2 = srcx + width; + box.y2 = srcy + height; + drawRegion = miRegionCreate( &box, 0 ); + miTranslateRegion( drawRegion, dstx, dsty ); + + region = miRegionCreate( NULL, 0 ); + miIntersect( region, drawRegion, + ((PclGCPrivPtr) + (pGC->devPrivates[PclGCPrivateIndex].ptr)) + ->pCompositeClip ); + + /* + * Now select the operation to be performed on each box in the + * region. + */ + if( pSrc->depth == 1 ) + doFragment = PclMonoPixmapFragment; + else + doFragment = PclColorPixmapFragment; + + /* + * Actually draw each section of the bitmap. + */ + nrect = REGION_NUM_RECTS( region ); + prect = REGION_RECTS( region ); + + while( nrect ) + { + (*doFragment)( dstFile, (PixmapPtr)pSrc, prect->x1 - dstx, + prect->y1 - dsty, prect->x2 - dstx, + prect->y2 - dsty, prect->x1, prect->y1 ); + + nrect--; + prect++; + } + + /* + * Update the destination's GC to the source's GC. + */ +/* + PclSetDrawablePrivateGC( pDst, srcGC ); +*/ + + /* + * Determine the region that needs to be returned. This is the + * region of the source that falls outside the boundary of the + * pixmap. + */ + box.x1 = 0; + box.y1 = 0; + box.x2 = pixSrc->drawable.width; + box.y2 = pixSrc->drawable.height; + whole = miRegionCreate( &box, 0 ); + ret = miRegionCreate( NULL, 0 ); + + miTranslateRegion( drawRegion, -dstx, -dsty ); + miSubtract( ret, drawRegion, whole ); + + /* + * Clean up the regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + miRegionDestroy( whole ); + + if( miRegionNotEmpty( ret ) ) + return ret; + else + { + miRegionDestroy( ret ); + return NULL; + } +} + +RegionPtr +PclCopyPlane(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long plane) +{ + RegionPtr reg; + GCPtr scratchGC; + PixmapPtr scratchPix; + extern RegionPtr mfbCopyPlane(), cfbCopyPlane(), cfb32CopyPlane(); + + /* + * Since we don't store PCL on a per-window basis, there's no good + * way to copy from a window. + */ + if( pSrc->type == DRAWABLE_WINDOW ) + return NULL; + + /* + * Copying from a pixmap to a pixmap is already implemented by + * mfb/cfb. + */ + if( pSrc->type == DRAWABLE_PIXMAP && + pDst->type == DRAWABLE_PIXMAP ) + { + if( pDst->depth == 1 ) + return mfbCopyPlane( pSrc, pDst, pGC, srcx, srcy, width, + height, dstx, dsty, plane ); + else if( pDst->depth <= 8 ) + return cfbCopyPlane( pSrc, pDst, pGC, srcx, srcy, width, + height, dstx, dsty, plane ); + else if( pDst->depth <= 32 ) + return cfb32CopyPlane( pSrc, pDst, pGC, srcx, srcy, width, + height, dstx, dsty, plane ); + } + + /* + * We can use the mfb/cfbCopyPlane function to do the work of grabbing + * the plane and converting it to the desired visual. Once that's + * done, we already know how to do a CopyArea. + */ + scratchPix = (*pDst->pScreen->CreatePixmap)( pDst->pScreen, width, + height, pDst->depth ); + + scratchGC = GetScratchGC( pDst->depth, pDst->pScreen ); + CopyGC( pGC, scratchGC, ~0L ); + + if( pDst->depth == 1 ) + { + mfbValidateGC( scratchGC, ~0L, (DrawablePtr)scratchPix ); + mfbCopyPlane( pSrc, (DrawablePtr)scratchPix, scratchGC, + srcx, srcy, width, height, 0, 0, plane ); + } + else if( pDst->depth <= 8 ) + { + cfbValidateGC( scratchGC, ~0L, (DrawablePtr)scratchPix ); + cfbCopyPlane( pSrc, (DrawablePtr)scratchPix, scratchGC, + srcx, srcy, width, height, 0, 0, plane ); + } + else if( pDst->depth <= 32 ) + { + cfb32ValidateGC( scratchGC, ~0L, (DrawablePtr)scratchPix ); + cfb32CopyPlane( pSrc, (DrawablePtr)scratchPix, scratchGC, + srcx, srcy, width, height, 0, 0, plane ); + } + + reg = PclCopyArea( (DrawablePtr)scratchPix, pDst, pGC, 0, 0, width, + height, dstx, dsty ); + + FreeScratchGC( scratchGC ); + + (*pDst->pScreen->DestroyPixmap)( scratchPix ); + + return reg; +} + diff --git a/Xprint/pcl/PclAttVal.c b/Xprint/pcl/PclAttVal.c new file mode 100644 index 000000000..88fcf23b5 --- /dev/null +++ b/Xprint/pcl/PclAttVal.c @@ -0,0 +1,203 @@ +/* + * $Xorg: PclAttVal.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ + */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "Pcl.h" +#include "AttrValid.h" + +/* + * define valid values and defaults for Printer pool + */ +static XpOid ValidContentOrientationsOids[] = { + xpoid_val_content_orientation_portrait, + xpoid_val_content_orientation_landscape, + xpoid_val_content_orientation_reverse_portrait, + xpoid_val_content_orientation_reverse_landscape +}; +static XpOidList ValidContentOrientations = { + ValidContentOrientationsOids, XpNumber(ValidContentOrientationsOids) +}; + +static XpOid DefaultContentOrientationsOids[] = { + xpoid_val_content_orientation_portrait, + xpoid_val_content_orientation_landscape +}; +static XpOidList DefaultContentOrientations = { + DefaultContentOrientationsOids, XpNumber(DefaultContentOrientationsOids) +}; + +static XpOid ValidPlexesOids[] = { + xpoid_val_plex_simplex, xpoid_val_plex_duplex, xpoid_val_plex_tumble +}; +static XpOidList ValidPlexes = { + ValidPlexesOids, XpNumber(ValidPlexesOids) +}; + +static XpOid DefaultPlexesOids[] = { + xpoid_val_plex_simplex +}; +static XpOidList DefaultPlexes = { + DefaultPlexesOids, XpNumber(DefaultPlexesOids) +}; + +static unsigned long ValidPrinterResolutionsCards[] = { + 300 +}; +static XpOidCardList ValidPrinterResolutions = { + ValidPrinterResolutionsCards, XpNumber(ValidPrinterResolutionsCards) +}; + +static unsigned long DefaultPrinterResolutionsCards[] = { + 300 +}; +static XpOidCardList DefaultPrinterResolutions = { + DefaultPrinterResolutionsCards, XpNumber(DefaultPrinterResolutionsCards) +}; + +static XpOid ValidListfontsModesOids[] = { + xpoid_val_xp_list_internal_printer_fonts, xpoid_val_xp_list_glyph_fonts +}; +static XpOidList ValidListfontsModes = { + ValidListfontsModesOids, XpNumber(ValidListfontsModesOids) +}; + +static XpOid DefaultListfontsModesOids[] = { + xpoid_val_xp_list_glyph_fonts +}; +static XpOidList DefaultListfontsModes = { + DefaultListfontsModesOids, XpNumber(DefaultListfontsModesOids) +}; + +static XpOid ValidSetupProvisoOids[] = { + xpoid_val_xp_setup_mandatory, xpoid_val_xp_setup_optional +}; +static XpOidList ValidSetupProviso = { + + + ValidSetupProvisoOids, XpNumber(ValidSetupProvisoOids) +}; + +static XpOidDocFmt ValidDocFormatsSupportedFmts[] = { + { "PCL", "5", NULL }, +}; +static XpOidDocFmtList ValidDocFormatsSupported = { + ValidDocFormatsSupportedFmts, XpNumber(ValidDocFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultDocFormatsSupportedFmts[] = { + { "PCL", "5", NULL } +}; +static XpOidDocFmtList DefaultDocFormatsSupported = { + DefaultDocFormatsSupportedFmts, XpNumber(DefaultDocFormatsSupportedFmts) +}; + +static XpOidDocFmt ValidEmbeddedFormatsSupportedFmts[] = { + { "HPGL", "2", NULL }, +}; +static XpOidDocFmtList ValidEmbeddedFormatsSupported = { + ValidEmbeddedFormatsSupportedFmts, XpNumber(ValidEmbeddedFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultEmbeddedFormatsSupportedFmts[] = { + { "HPGL", "2", NULL } +}; +static XpOidDocFmtList DefaultEmbeddedFormatsSupported = { + DefaultEmbeddedFormatsSupportedFmts, XpNumber(DefaultEmbeddedFormatsSupportedFmts) +}; + +static XpOidDocFmt ValidRawFormatsSupportedFmts[] = { + { "PCL", "5", NULL }, + { "Postscript", "2", NULL }, + { "ASCII", NULL, NULL } + +}; +static XpOidDocFmtList ValidRawFormatsSupported = { + ValidRawFormatsSupportedFmts, XpNumber(ValidRawFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultRawFormatsSupportedFmts[] = { + { "PCL", "5", NULL } +}; +static XpOidDocFmtList DefaultRawFormatsSupported = { + DefaultRawFormatsSupportedFmts, XpNumber(DefaultRawFormatsSupportedFmts) +}; + +static XpOid ValidInputTraysOids[] = { + xpoid_val_input_tray_manual, + xpoid_val_input_tray_main, + xpoid_val_input_tray_envelope, + xpoid_val_input_tray_large_capacity, + xpoid_val_input_tray_bottom +}; +static XpOidList ValidInputTrays = { + ValidInputTraysOids, XpNumber(ValidInputTraysOids) +}; + +static XpOid ValidMediumSizesOids[] = { + xpoid_val_medium_size_iso_a3, + xpoid_val_medium_size_iso_a4, + xpoid_val_medium_size_na_letter, + xpoid_val_medium_size_na_legal, + xpoid_val_medium_size_executive, + xpoid_val_medium_size_ledger, + xpoid_val_medium_size_iso_c5, + xpoid_val_medium_size_iso_designated_long, + xpoid_val_medium_size_na_number_10_envelope, + xpoid_val_medium_size_monarch_envelope, + xpoid_val_medium_size_jis_b5, +}; +static XpOidList ValidMediumSizes = { + ValidMediumSizesOids, XpNumber(ValidMediumSizesOids) +}; + +static XpOidDocFmt DefaultDocumentFormat = { + "PCL", "5", NULL +}; + + +/* + * init struct for XpValidate*Pool + */ +XpValidatePoolsRec PclValidatePoolsRec = { + &ValidContentOrientations, &DefaultContentOrientations, + &ValidDocFormatsSupported, &DefaultDocFormatsSupported, + &ValidInputTrays, &ValidMediumSizes, + &ValidPlexes, &DefaultPlexes, + &ValidPrinterResolutions, &DefaultPrinterResolutions, + &ValidEmbeddedFormatsSupported, &DefaultEmbeddedFormatsSupported, + &ValidListfontsModes, &DefaultListfontsModes, + &ValidRawFormatsSupported, &DefaultRawFormatsSupported, + &ValidSetupProviso, + &DefaultDocumentFormat +}; diff --git a/Xprint/pcl/PclAttr.c b/Xprint/pcl/PclAttr.c new file mode 100644 index 000000000..2612a821f --- /dev/null +++ b/Xprint/pcl/PclAttr.c @@ -0,0 +1,83 @@ +/* $Xorg: PclAttr.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclAttr.c +** * +** * Contents: +** * Attribute-handling functions for the PCL driver +** * +** * Created: 2/2/96 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "Pcl.h" +#include "attributes.h" + +char * +PclGetAttributes( + XpContextPtr pCon, + XPAttributes pool ) +{ + return XpGetAttributes( pCon, pool ); +} + +char * +PclGetOneAttribute( + XpContextPtr pCon, + XPAttributes pool, + char *attr ) +{ + return XpGetOneAttribute( pCon, pool, attr ); +} +int +PclAugmentAttributes( + XpContextPtr pCon, + XPAttributes pool, + char *attrs ) +{ + return XpAugmentAttributes( pCon, pool, attrs ); +} + +int +PclSetAttributes( + XpContextPtr pCon, + XPAttributes pool, + char *attrs ) +{ + return XpSetAttributes( pCon, pool, attrs ); +} diff --git a/Xprint/pcl/PclColor.c b/Xprint/pcl/PclColor.c new file mode 100644 index 000000000..cd3d2cc12 --- /dev/null +++ b/Xprint/pcl/PclColor.c @@ -0,0 +1,860 @@ +/* $Xorg: PclColor.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclColorInit.c +** * +** * Contents: +** * Colormap handing code of Pcl driver for the +** * print server. +** * +** * Created: 4/8/96 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include +#include +#include +#include +#include +#include + +#include "colormapst.h" +#include "windowstr.h" +#include "resource.h" + +#include "Pcl.h" + +PclPaletteMapPtr PclFindPaletteMap(PclContextPrivPtr cPriv, + ColormapPtr cmap, + GCPtr gc); + +unsigned char *PclReadMap(char *, int *); + +void PclLookUp( ColormapPtr cmap, + PclContextPrivPtr cPriv, + unsigned short *r, + unsigned short *g, + unsigned short *b); + +static void lookup(unsigned char *src, + unsigned char *dst, + int num, + unsigned char *map, + int dim); +static void trilinear(unsigned char *p, + unsigned char *out, + unsigned char *d, + int dim, + unsigned char def); + + +/* + * This seems to be (and is) a duplication of effort; one would think + * that cfbCreateDefColormap would be sufficient. It almost is. The + * only change made in this function is that the black and white pixels + * are allocated with three separate variables for red, green and blue + * values, instead of the single variable in cfbCreateDefColormap. The + * single variable leads to the one value being corrected by + * ResolveColor three times, which leads to incorrect colors. + */ + +Bool +PclCreateDefColormap(ScreenPtr pScreen) +{ + unsigned short wp_red = ~0, wp_green = ~0, wp_blue = ~0; + unsigned short bp_red = 0, bp_green = 0, bp_blue = 0; + VisualPtr pVisual; + ColormapPtr cmap; + Pixel wp, bp; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + + if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap, + (pVisual->class & DynamicClass) ? AllocNone : AllocAll, + 0) + != Success) + return FALSE; + wp = pScreen->whitePixel; + bp = pScreen->blackPixel; + if ((AllocColor(cmap, &wp_red, &wp_green, &wp_blue, &wp, 0) != + Success) || + (AllocColor(cmap, &bp_red, &bp_green, &bp_blue, &bp, 0) != + Success)) + return FALSE; + + pScreen->whitePixel = wp; + pScreen->blackPixel = bp; + + (*pScreen->InstallColormap)(cmap); + return TRUE; +} + +/* + * Add colormap to list of colormaps on screen + */ +Bool +PclCreateColormap(ColormapPtr pColor) +{ + PclCmapToContexts *new; + PclScreenPrivPtr sPriv; + + sPriv = (PclScreenPrivPtr)pColor->pScreen + ->devPrivates[PclScreenPrivateIndex].ptr; + + /* + * Use existing code to initialize the values in the colormap + */ + cfbInitializeColormap( pColor ); + + /* + * Set up the mapping between the color map and the context + */ + new = (PclCmapToContexts *)xalloc( sizeof( PclCmapToContexts ) ); + + if( new ) + { + new->colormapId = pColor->mid; + new->contexts = NULL; + new->next = sPriv->colormaps; + sPriv->colormaps = new; + + return TRUE; + } + else + return FALSE; +} + +void +PclDestroyColormap(ColormapPtr pColor) +{ + PclScreenPrivPtr sPriv; + PclCmapToContexts *pCmap, *tCmap; + PclContextListPtr con, tCon; + PclContextPrivPtr cPriv; + PclPaletteMapPtr pPal; + char t[80]; + + /* + * At DestroyContext time, colormaps may be destroyed twice, so if the + * pointer is NULL, just crash out. + */ + if( !pColor ) + return; + + /* + * Find the colormap <-> contexts mapping + */ + sPriv = (PclScreenPrivPtr)pColor->pScreen + ->devPrivates[PclScreenPrivateIndex].ptr; + pCmap = sPriv->colormaps; + while( pCmap ) + { + if( pCmap->colormapId == pColor->mid ) + break; + tCmap = pCmap; + pCmap = pCmap->next; + } + + /* + * For each context, delete the palette in the printer and + * free the mapping. + */ + if( pCmap ) + { + con = pCmap->contexts; + while( con ) + { + cPriv = con->context->devPrivates[PclContextPrivateIndex].ptr; + + pPal = cPriv->palettes; + while( pPal ) + { + if( pPal->colormapId == pColor->mid ) + break; + pPal = pPal->next; + } + + if( cPriv->pPageFile ) + { + sprintf( t, "\033&p%dI\033*p2C", pPal->paletteId ); + SEND_PCL( cPriv->pPageFile, t ); + } + + tCon = con; + con = con->next; + xfree( tCon ); + } + + /* + * Delete the colormap<->contexts mapping + */ + if( sPriv->colormaps == pCmap ) + /* Delete from the front */ + sPriv->colormaps = pCmap->next; + else + /* Delete from the middle */ + tCmap->next = pCmap->next; + free( pCmap ); + } +} + +void +PclInstallColormap(ColormapPtr pColor) +{ +} + +void +PclUninstallColormap(ColormapPtr pColor) +{ +} + +int +PclListInstalledColormaps(ScreenPtr pScreen, + XID *pCmapList) +{ + return 0; +} + +void +PclStoreColors(ColormapPtr pColor, + int ndef, + xColorItem *pdefs) +{ + PclCmapToContexts *p; + PclScreenPrivPtr sPriv; + PclContextListPtr con; + PclContextPrivPtr cPriv; + PclPaletteMapPtr pMap; + char t[80], t2[30]; + int i; + + sPriv = (PclScreenPrivPtr)pColor->pScreen + ->devPrivates[PclScreenPrivateIndex].ptr; + p = sPriv->colormaps; + while( p ) + { + if( p->colormapId == pColor->mid ) + break; + p = p->next; + } + + if( p ) + { + con = p->contexts; + while( con ) + { + /* + * For each context, get the palette ID and update the + * appropriate palette. + */ + cPriv = con->context + ->devPrivates[PclContextPrivateIndex].ptr; + pMap = PclFindPaletteMap( cPriv, pColor, NULL ); + + /* + * Update the palette + */ + sprintf( t, "\033&p%dS", pMap->paletteId ); + SEND_PCL( cPriv->pPageFile, t ); + + if( pColor->class == PseudoColor ) + { + unsigned short r, g, b; + unsigned int pID; + for( i = 0; i < ndef; i++ ) + { + pID = pdefs[i].pixel; + if ( pColor->red[i].fShared ) + { + r = pColor->red[pID].co.shco.red->color; + g = pColor->red[pID].co.shco.green->color; + b = pColor->red[pID].co.shco.blue->color; + } + else + { + r = pColor->red[pID].co.local.red; + g = pColor->red[pID].co.local.green; + b = pColor->red[pID].co.local.blue; + } + + if( pdefs[i].flags & DoRed ) + r = pdefs[i].red; + if( pdefs[i].flags & DoGreen ) + g = pdefs[i].green; + if( pdefs[i].flags & DoBlue ) + b = pdefs[i].blue; + PclLookUp(pColor, cPriv, &r, &g, &b); + sprintf( t, "\033*v%ua%ub%uc%dI", r, g, b, pID); + SEND_PCL( cPriv->pPageFile, t ); + } + } + + sprintf( t, "\033&p%dS", cPriv->currentPalette ); + SEND_PCL( cPriv->pPageFile, t ); + + con = con->next; + } + } +} + +void +PclResolveColor(unsigned short *pRed, + unsigned short *pGreen, + unsigned short *pBlue, + VisualPtr pVisual) +{ + /* + * We need to map the X color range of [0,65535] to the PCL color + * range of [0,32767]. + */ + *pRed >>= 1; + *pGreen >>= 1; + *pBlue >>= 1; +} + +PclPaletteMapPtr +PclFindPaletteMap(PclContextPrivPtr cPriv, + ColormapPtr cmap, + GCPtr gc) +{ + PclPaletteMapPtr p = cPriv->palettes, new; + + /* + * If the colormap is static, grab one of the special palettes. If we come + * into this from StoreColors, there will be no GC, but by definition we're + * looking at a dynamic color map, so the special colors will not be + * needed. + */ + if( gc ) + { + if( cmap->pVisual->class == StaticGray ) + return &( cPriv->staticGrayPalette ); + else if( cmap->pVisual->class == TrueColor ) + { + if( gc->fillStyle == FillTiled && !( gc->tileIsPixel ) ) + return &( cPriv->specialTrueColorPalette ); + else + return &( cPriv->trueColorPalette ); + } + } + + + /* Look for the colormap ID <-> palette ID mapping */ + while( p ) + { + if( p->colormapId == cmap->mid ) + return p; + p = p->next; + } + + /* If the colormap isn't already there, make an entry for it */ + new = (PclPaletteMapPtr)xalloc( sizeof( PclPaletteMap ) ); + new->colormapId = cmap->mid; + new->paletteId = cPriv->nextPaletteId++; + new->downloaded = 0; + new->next = cPriv->palettes; + cPriv->palettes = new; + return new; +} + +int +PclUpdateColormap(DrawablePtr pDrawable, + XpContextPtr pCon, + GCPtr gc, + FILE *outFile) +{ + PclScreenPrivPtr sPriv; + + PclContextPrivPtr cPriv; + PclPaletteMapPtr pMap; + PclCmapToContexts *pCmap, *tCmap; + PclContextListPtr new; + char t[80]; + Colormap c; + ColormapPtr cmap; + WindowPtr win = (WindowPtr)pDrawable; + unsigned short r, g, b, rr, gg, bb; + int i; + + cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr; + + c = wColormap( win ); + cmap = (ColormapPtr)LookupIDByType( c, RT_COLORMAP ); + pMap = PclFindPaletteMap( cPriv, cmap, gc ); + + if( cPriv->currentPalette == pMap->paletteId ) + /* + * If the requested colormap is already active, nothing needs to + * be done. + */ + return; + + /* + * Now we activate the palette in the printer + */ + sprintf( t, "\033&p%dS", pMap->paletteId ); + SEND_PCL( outFile, t ); + cPriv->currentPalette = pMap->paletteId; + + if( pMap->downloaded == 0 ) + /* + * If the requested colormap has not been downloaded to the + * printer, we need to do that before activating it. + */ + { + /* + * Add the colormap to the screen-level colormap<->context mapping. + */ + sPriv = (PclScreenPrivPtr)cmap->pScreen + ->devPrivates[PclScreenPrivateIndex].ptr; + pCmap = sPriv->colormaps; + while( pCmap ) + { + if( pCmap->colormapId == cmap->mid ) + break; + tCmap = pCmap; + pCmap = pCmap->next; + } + new = (PclContextListPtr)xalloc( sizeof( PclContextList ) ); + new->context = pCon; + new->next = pCmap->contexts; + pCmap->contexts = new; + + /* + * XXX Download the colormap + */ + if( cmap->class == StaticGray ) + { +#ifdef XP_PCL_COLOR + sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1, 1, 1, 1, 1 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 12 ); + + /* Send the white reference point... */ + sprintf( t, "%c%c%c%c%c%c", 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* ... and the black reference point */ + sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* Now program the two colors */ + sprintf( t, "\033*v0a0b0c%dI", cmap->pScreen->blackPixel ); + SEND_PCL( cPriv->pPageFile, t ); + sprintf( t, "\033*v32767a32767b32767c%dI", + cmap->pScreen->whitePixel ); + SEND_PCL( cPriv->pPageFile, t ); +#endif /* XP_PCL_COLOR */ + } + else if( cmap->class == PseudoColor ) + { + sprintf( t, + "\033*v18W%c%c%c%c%c%c", + 0, 1, cmap->pVisual->nplanes, 16, 16, 16 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 12 ); + + /* Send the white reference point... */ + if ( cPriv->ctbl != NULL ) + sprintf( t, "%c%c%c%c%c%c", 0x00, 0xff, 0x00, 0xff, + 0x00, 0xff ); + else + sprintf( t, "%c%c%c%c%c%c", 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* ... and the black reference point */ + sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + for(i = 0; i < cmap->pVisual->ColormapEntries; i++ ) + { + if( cmap->red[i].fShared ) + { + r = cmap->red[i].co.shco.red->color; + g = cmap->red[i].co.shco.green->color; + b = cmap->red[i].co.shco.blue->color; + } + else + { + r = cmap->red[i].co.local.red; + g = cmap->red[i].co.local.green; + b = cmap->red[i].co.local.blue; + } + PclLookUp(cmap, cPriv, &r, &g, &b); + sprintf( t, "\033*v%ua%ub%uc%dI", r, g, b, i ); + SEND_PCL( outFile, t ); + } + } + else if( cmap->class == TrueColor ) + { + unsigned short lim; + + if( gc->fillStyle == FillTiled && !( gc->tileIsPixel ) ) + { + if( cPriv->ctbl != NULL ) + { + /* Send the "special" colormap for 24-bit fills */ + sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1, + 8, + cmap->pVisual->bitsPerRGBValue, + cmap->pVisual->bitsPerRGBValue, + cmap->pVisual->bitsPerRGBValue ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 12 ); + + /* Send the white reference point... */ + sprintf( t, "%c%c%c%c%c%c", + 0x00, 0xff, + 0x00, 0xff, + 0x00, 0xff ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* ... and the black reference point */ + sprintf( t, "%c%c%c%c%c%c", + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* Now send the color entries, RRRGGGBB */ + i=0; + for( r = 0; r < 8; r++ ) + for( g = 0; g < 8; g ++ ) + for( b = 0; b < 4; b++ ) + { + rr = (r * 0xff)/7; + gg = (g * 0xff)/7; + bb = (b * 0xff)/3; + PclLookUp(cmap, cPriv, &rr, &gg, &bb); + sprintf( t, "\033*v%ua%ub%uc%dI", + rr, gg, bb, i ); + SEND_PCL( outFile, t ); + i++; + } + } + else + { + /* Send the "special" colormap for 24-bit fills */ + sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1, + 8, + cmap->pVisual->bitsPerRGBValue, + cmap->pVisual->bitsPerRGBValue, + cmap->pVisual->bitsPerRGBValue ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 12 ); + + /* Send the white reference point... */ + sprintf( t, "%c%c%c%c%c%c", + 0x00, 0x07, + 0x00, 0x07, + 0x00, 0x03 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* ... and the black reference point */ + sprintf( t, "%c%c%c%c%c%c", + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* Now send the color entries, RRRGGGBB */ + i=0; + for( r = 0; r < 8; r++ ) + for( g = 0; g < 8; g ++ ) + for( b = 0; b < 4; b++ ) + { + sprintf( t, "\033*v%ua%ub%uc%dI", + r, g, b, i ); + SEND_PCL( outFile, t ); + i++; + } + } + + } + else + { + lim = (1 << cmap->pVisual->bitsPerRGBValue) - 1; + + /* Send the "special" colormap for 24-bit fills */ + sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 3, + cmap->pVisual->nplanes, + cmap->pVisual->bitsPerRGBValue, + cmap->pVisual->bitsPerRGBValue, + cmap->pVisual->bitsPerRGBValue ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 12 ); + + /* Send the white reference point... */ + sprintf( t, "%c%c%c%c%c%c", + (lim >> 8) & 0xff, lim & 0xff, + (lim >> 8) & 0xff, lim & 0xff, + (lim >> 8) & 0xff, lim & 0xff); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + + /* ... and the black reference point */ + sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 ); + SEND_PCL_COUNT( cPriv->pPageFile, t, 6 ); + } + + } + pMap->downloaded = 1; + } + +} + +void PclLookUp( + ColormapPtr cmap, + PclContextPrivPtr cPriv, + unsigned short *r, + unsigned short *g, + unsigned short *b +) +{ + unsigned char cdata[3]; + + if( cmap->class == PseudoColor ) + { + if( cPriv->ctbl != NULL ) + { + cdata[0] = *r >> 8; + cdata[1] = *g >> 8; + cdata[2] = *b >> 8; + lookup(cdata, cdata, 1, cPriv->ctbl, cPriv->ctbldim); + *r = cdata[0]; + *g = cdata[1]; + *b = cdata[2]; + } + else + { + *r >>= 1; + *g >>= 1; + *b >>= 1; + } + } + else if( cmap->class == TrueColor ) + { + if( cPriv->ctbl != NULL ) + { + cdata[0] = *r; + cdata[1] = *g; + cdata[2] = *b; + lookup(cdata, cdata, 1, cPriv->ctbl, cPriv->ctbldim); + *r = cdata[0]; + *g = cdata[1]; + *b = cdata[2]; + } + } + return; +} + +unsigned char *PclReadMap(char *name, int *dim) +{ + FILE *fp; + unsigned char *data; + long size; + + if ((fp=fopen(name, "r")) == NULL) { + return(NULL); + } + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + + /* Could do this with a lookup table, if the constraint is that the + 3 map dimensions must be equal. */ + switch (size) { + case 8*8*8*3: + *dim = 8; + break; + case 16*16*16*3: + *dim = 16; + break; + case 17*17*17*3: + *dim = 17; + break; + case 65*65*65*3: + *dim = 65; + break; + default: + fclose(fp); + return(NULL); + } + + if ((data = (unsigned char *) xalloc(sizeof(char) * size)) == NULL) { + fclose(fp); + return(NULL); + } + + fseek(fp, 0, SEEK_SET); + + if (fread(data, sizeof(char), size, fp) != size) { + fclose(fp); + free(data); + return(NULL); + } + + fclose(fp); + return(data); +} + +/************************************************************************ + * + * Here is the mapper. + * + ************************************************************************/ + +#define SCL(x) ((x)*(dim-1)/255) +/* Interleaved-map lookup */ +static void lookup(unsigned char *src, unsigned char *dst, int num, unsigned char *map, int dim) +{ + int i; + unsigned char *p1, *p2, *p3; + int shift, offset; + +#define _INTERPOLATE +#ifndef _INTERPOLATE + for (i=0; i>8)) + +static void trilinear(unsigned char *p, unsigned char *out, unsigned char *d, int dim, unsigned char def) +{ +#define DENS(X, Y, Z, ch) d[((X*dim+Y)*dim+Z)*3+ch] + + int x0, y0, z0, + x1, y1, z1, + i; + unsigned char *dp, + fx, fy, fz, + d000, d001, d010, d011, + d100, d101, d110, d111, + dx00, dx01, dx10, dx11, + dxy0, dxy1, dxyz; + float scale; + + scale = 255.0 / (dim-1); + + x0 = p[0] / scale; + y0 = p[1] / scale; + z0 = p[2] / scale; + + /* Fractions should range from 0-1.0 (fixed point 8-256) */ + fx = (((int) (p[0] - x0 * scale)) << 8) / 255; + fy = (((int) (p[1] - y0 * scale)) << 8) / 255; + fz = (((int) (p[2] - z0 * scale)) << 8) / 255; + + x1 = x0 + 1; + y1 = y0 + 1; + z1 = z0 + 1; + + for (i=0; i<3; i++) { + + if (x0 >= 0 && x1 < dim && + y0 >= 0 && y1 < dim && + z0 >= 0 && z1 < dim) { + dp = &DENS(x0, y0, z0, i); + d000 = dp[0]; + d100 = dp[3]; + dp += dim*3; + d010 = dp[0]; + d110 = dp[3]; + dp += dim*dim*3; + d011 = dp[0]; + d111 = dp[3]; + dp -= dim*3; + d001 = dp[0]; + d101 = dp[3]; + } else { +# define INRANGE(X, Y, Z) \ + ((X) >= 0 && (X) < dim && \ + (Y) >= 0 && (Y) < dim && \ + (Z) >= 0 && (Z) < dim) + + d000 = INRANGE(x0, y0, z0) ? DENS(x0, y0, z0, i) : def; + d001 = INRANGE(x0, y0, z1) ? DENS(x0, y0, z1, i) : def; + d010 = INRANGE(x0, y1, z0) ? DENS(x0, y1, z0, i) : def; + d011 = INRANGE(x0, y1, z1) ? DENS(x0, y1, z1, i) : def; + + d100 = INRANGE(x1, y0, z0) ? DENS(x1, y0, z0, i) : def; + d101 = INRANGE(x1, y0, z1) ? DENS(x1, y0, z1, i) : def; + d110 = INRANGE(x1, y1, z0) ? DENS(x1, y1, z0, i) : def; + d111 = INRANGE(x1, y1, z1) ? DENS(x1, y1, z1, i) : def; + } + + dx00 = LERP(fx, d000, d100); + dx01 = LERP(fx, d001, d101); + dx10 = LERP(fx, d010, d110); + dx11 = LERP(fx, d011, d111); + + dxy0 = LERP(fy, dx00, dx10); + dxy1 = LERP(fy, dx01, dx11); + + out[i] = LERP(fz, dxy0, dxy1); + } +} + diff --git a/Xprint/pcl/PclCursor.c b/Xprint/pcl/PclCursor.c new file mode 100644 index 000000000..88a76f6bf --- /dev/null +++ b/Xprint/pcl/PclCursor.c @@ -0,0 +1,110 @@ +/* $Xorg: PclCursor.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclCursor.c +** * +** * Contents: +** * Cursor-handling code for the PCL DDX driver +** * +** * Created: 1/18/96 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include + +#include "Pcl.h" +#include "gcstruct.h" +#include "windowstr.h" + +void +PclConstrainCursor( pScreen, pBox ) + ScreenPtr pScreen; + BoxPtr pBox; +{ +} + +void +PclCursorLimits( pScreen, pCursor, pHotBox, pTopLeftBox ) + ScreenPtr pScreen; + CursorPtr pCursor; + BoxPtr pHotBox; + BoxPtr pTopLeftBox; +{ +} + +Bool +PclDisplayCursor( pScreen, pCursor ) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + return True; +} + +Bool +PclRealizeCursor( pScreen, pCursor ) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + return True; +} + +Bool +PclUnrealizeCursor( pScreen, pCursor ) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + return True; +} + +void +PclRecolorCursor( pScreen, pCursor, displayed ) + ScreenPtr pScreen; + CursorPtr pCursor; + Bool displayed; +{ +} + +Bool +PclSetCursorPosition( pScreen, x, y, generateEvent ) + ScreenPtr pScreen; + int x; + int y; + Bool generateEvent; +{ + return True; +} diff --git a/Xprint/pcl/PclDef.h b/Xprint/pcl/PclDef.h new file mode 100644 index 000000000..2638748b2 --- /dev/null +++ b/Xprint/pcl/PclDef.h @@ -0,0 +1,64 @@ +/* $Xorg: PclDef.h,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclDef.h +** * +** * Contents: extran defines and includes for the Pcl driver +** * for a printing X server. +** * +** * Created: 7/31/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#ifndef _PCLDEF_H_ +#define _PCLDEF_H_ + +#define DT_PRINT_JOB_HEADER "DT_PRINT_JOB_HEADER" +#define DT_PRINT_JOB_TRAILER "DT_PRINT_JOB_TRAILER" +#define DT_PRINT_JOB_COMMAND "DT_PRINT_JOB_COMMAND" +#define DT_PRINT_JOB_EXEC_COMMAND "DT_PRINT_JOB_EXEC_COMMAND" +#define DT_PRINT_JOB_EXEC_OPTIONS "DT_PRINT_JOB_EXEC_OPTION" +#define DT_PRINT_PAGE_HEADER "DT_PRINT_PAGE_HEADER" +#define DT_PRINT_PAGE_TRAILER "DT_PRINT_PAGE_TRAILER" +#define DT_PRINT_PAGE_COMMAND "DT_PRINT_PAGE_COMMAND" + +#define DT_IN_FILE_STRING "%(InFile)%" +#define DT_OUT_FILE_STRING "%(OutFile)%" +#define DT_ALLOWED_COMMANDS_FILE "printCommands" + +#endif /* _PCLDEF_H_ */ diff --git a/Xprint/pcl/PclFonts.c b/Xprint/pcl/PclFonts.c new file mode 100644 index 000000000..ef4554a12 --- /dev/null +++ b/Xprint/pcl/PclFonts.c @@ -0,0 +1,69 @@ +/* $Xorg: PclFonts.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclFonts.c +** * +** * Contents: +** * Font code for Pcl driver. +** * +** * Created: 2/03/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "miscstruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "scrnintstr.h" + +#include "Pcl.h" + +Bool +PclRealizeFont( + ScreenPtr pscr, + FontPtr pFont) +{ + return TRUE; +} + +Bool +PclUnrealizeFont( + ScreenPtr pscr, + FontPtr pFont) +{ + return TRUE; +} diff --git a/Xprint/pcl/PclGC.c b/Xprint/pcl/PclGC.c new file mode 100644 index 000000000..7f0039e1f --- /dev/null +++ b/Xprint/pcl/PclGC.c @@ -0,0 +1,1064 @@ +/* $Xorg: PclGC.c,v 1.4 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclGC.c +** * +** * Contents: +** * Graphics Context handling for the PCL driver +** * +** * Created: 10/11/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "gcstruct.h" + +#include "Pcl.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "windowstr.h" +#include "migc.h" +#include "scrnintstr.h" +#include "resource.h" + +static GCOps PclGCOps = +{ + PclFillSpans, + PclSetSpans, + PclPutImage, + PclCopyArea, + PclCopyPlane, + PclPolyPoint, + PclPolyLine, + PclPolySegment, + PclPolyRectangle, + PclPolyArc, + PclFillPolygon, + PclPolyFillRect, + PclPolyFillArc, + PclPolyText8, + PclPolyText16, + PclImageText8, + PclImageText16, + PclImageGlyphBlt, + PclPolyGlyphBlt, + PclPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +} +; + + +static GCFuncs PclGCFuncs = +{ + PclValidateGC, + miChangeGC, + miCopyGC, + PclDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip, +} +; + +Bool +PclCreateGC( pGC ) + GCPtr pGC; +{ + PclGCPrivPtr pPriv = pGC->devPrivates[PclGCPrivateIndex].ptr; + + if( pGC->depth == 1 ) + { + if( mfbCreateGC( pGC ) == FALSE ) + return FALSE; + } + else if( pGC->depth <= 32 ) + { +#if PSZ == 8 + if( cfbCreateGC( pGC ) == FALSE ) +#else + if( cfb32CreateGC( pGC ) == FALSE ) +#endif + return FALSE; + } + else + return FALSE; + + pGC->clientClip = NULL; + pGC->clientClipType = CT_NONE; + + pGC->ops = &PclGCOps; + pGC->funcs = &PclGCFuncs; + + pPriv->pCompositeClip = NULL; + pPriv->freeCompClip = FALSE; + + return TRUE; +} + +void +PclDestroyGC(GCPtr pGC) +{ + PclGCPrivPtr pPriv = pGC->devPrivates[PclGCPrivateIndex].ptr; + extern int mfbGCPrivateIndex; + + /* Handle the mfb and cfb, which share a GC private struct */ + miRegisterGCPrivateIndex( mfbGCPrivateIndex ); + miDestroyGC( pGC ); + + if( pPriv->freeCompClip == TRUE ) + REGION_DESTROY( pGC->pScreen, pPriv->pCompositeClip ); +} + + +int +PclGetDrawablePrivateStuff( pDrawable, gc, valid, file ) + DrawablePtr pDrawable; + GC *gc; + unsigned long *valid; + FILE **file; +{ + XpContextPtr pCon; + PclPixmapPrivPtr pPriv; + PclContextPrivPtr cPriv; + + switch( pDrawable->type ) + { + case DRAWABLE_PIXMAP: + /* + * If we ever get here, something is wrong. + */ + return FALSE; + + case DRAWABLE_WINDOW: + pCon = PclGetContextFromWindow( (WindowPtr)pDrawable ); + + if( pCon == NULL ) + return FALSE; + else + { + cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr; + *gc = cPriv->lastGC; + *valid = cPriv->validGC; + *file = cPriv->pPageFile; + return TRUE; + } + + default: + return FALSE; + } +} + +void +PclSetDrawablePrivateGC( pDrawable, gc ) + DrawablePtr pDrawable; + GC gc; +{ + PixmapPtr pix; + XpContextPtr pCon; + PclPixmapPrivPtr pixPriv; + PclContextPrivPtr pPriv; + int i; + + switch( pDrawable->type ) + { + case DRAWABLE_PIXMAP: + pix = (PixmapPtr)pDrawable; + pixPriv = pix->devPrivates[PclPixmapPrivateIndex].ptr; + + pixPriv->lastGC = gc; + pixPriv->validGC = 1; + break; + + case DRAWABLE_WINDOW: + pCon = PclGetContextFromWindow( (WindowPtr)pDrawable ); + pPriv = ((PclContextPrivPtr) + (pCon->devPrivates[PclContextPrivateIndex].ptr)); + + pPriv->validGC = 1; + pPriv->lastGC = gc; + + /* + * Store the dash list separately, to avoid having it freed + * out from under us. + */ + if( pPriv->dash != NULL ) + xfree( pPriv->dash ); + if( gc.numInDashList != 0 ) + { + pPriv->dash = (unsigned char *)xalloc( sizeof( unsigned char ) + * gc.numInDashList ); + for( i = 0; i < gc.numInDashList; i++ ) + pPriv->dash[i] = gc.dash[i]; + } + else + pPriv->dash = NULL; + + + /* + * Store the dash list separately, to avoid having it freed + * out from under us. + */ + if( pPriv->dash != NULL ) + xfree( pPriv->dash ); + if( gc.numInDashList != 0 ) + { + pPriv->dash = (unsigned char *)xalloc( sizeof( unsigned char ) + * gc.numInDashList ); + for( i = 0; i < gc.numInDashList; i++ ) + pPriv->dash[i] = gc.dash[i]; + } + else + pPriv->dash = NULL; + + break; + } +} + +static void +PclSendPattern(char *bits, + int sz, + int depth, + int h, + int w, + int patNum, + FILE *outFile) +{ + char t[80], *row, *mod; + int w2; + int i, j; + + SEND_PCL( outFile, "\033%0A" ); + + if( depth == 1 ) + { + /* Each row must be word-aligned */ + w2 = ( w / 8 ) + ( ( w%8 ) ? 1 : 0 ); +/* + if( w2 % 2 ) + w2++; +*/ + + sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 ); + SEND_PCL( outFile, t ); + + sprintf( t, "%c%c%c%c%c%c%c%c", 0, 0, 1, 0, h>>8, h&0xff, w>>8, + w&0xff ); + SEND_PCL_COUNT( outFile, t, 8 ); + + for( row = bits, i = 0; i < h; i++, row += BitmapBytePad( w ) ) + SEND_PCL_COUNT( outFile, row, w2 ); + } + else if( depth == 8 ) + { + w2 = ( w % 2 ) ? w + 1 : w; + + sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 ); + SEND_PCL( outFile, t ); + + sprintf( t, "%c%c%c%c%c%c%c%c", 1, 0, 8, 0, h>>8, h&0xff, + w>>8, w&0xff ); + SEND_PCL_COUNT( outFile, t, 8 ); + + for( row = bits, i = 0; i < h; i++, + row += PixmapBytePad( w, 8 ) ) + SEND_PCL_COUNT( outFile, row, w2 ); + } + else + { + w2 = ( w % 2 ) ? w + 1 : w; + + sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 ); + SEND_PCL( outFile, t ); + + sprintf( t, "%c%c%c%c%c%c%c%c", 1, 0, 8, 0, h>>8, h&0xff, + w>>8, w&0xff ); + SEND_PCL_COUNT( outFile, t, 8 ); + + mod = (char *)xalloc( w2 ); + + for( row = bits, i = 0; i < h; i++, + row += PixmapBytePad( w, 24 ) ) + { + char r, g, b; + for( j = 0; j < w2; j++ ) { + r = ((row[j*4+1] >> 5) & 0x7) << 5; + g = ((row[j*4+2] >> 5) & 0x7) << 2; + b = ((row[j*4+3] >> 6) & 0x3); + mod[j] = r | g | b; + } + SEND_PCL_COUNT( outFile, mod, w2 ); + } + + xfree( mod ); + } + + SEND_PCL( outFile, "\033%0B" ); +} + +int +PclUpdateDrawableGC( pGC, pDrawable, outFile ) + GCPtr pGC; + DrawablePtr pDrawable; + FILE **outFile; +{ + Mask drawableMask, changeMask = 0; + GC dGC; + unsigned long valid; + int i; + XpContextPtr pCon; + PclContextPrivPtr cPriv; + Colormap c; + ColormapPtr cmap; + PclGCPrivPtr gcPriv = (PclGCPrivPtr) + (pGC->devPrivates[PclGCPrivateIndex].ptr); + + if( !PclGetDrawablePrivateStuff( pDrawable, &dGC, &valid, outFile ) ) + return FALSE; + + pCon = PclGetContextFromWindow( (WindowPtr)pDrawable ); + cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr; + + /* + * Here's where we update the colormap. Since there can be + * different colormaps installed on each window, we need to check + * before each drawing request that the correct palette is active in + * the printer. This is as good a place as any. + */ + if( !PclUpdateColormap( pDrawable, pCon, pGC, *outFile ) ) + return FALSE; + + /* + * If the drawable's last GC is NULL, this means that this is + * the first time the drawable is being used. Therefore, we need + * to emit PCL for all the GC fields. + */ + if( valid == 0 ) + changeMask = ~0; + + /* + * If we have two different GC structures, there is no alternative + * but to scan through them both to determine the changeMask. + */ + else + { + if( dGC.alu != pGC->alu ) + changeMask |= GCFunction; + if( dGC.fgPixel != pGC->fgPixel ) + changeMask |= GCForeground; + if( dGC.bgPixel != pGC->bgPixel ) + changeMask |= GCBackground; + if( dGC.lineWidth != pGC->lineWidth ) + changeMask |= GCLineWidth; + if( dGC.lineStyle != pGC->lineStyle ) + changeMask |= GCLineStyle; + if( dGC.capStyle != pGC->capStyle ) + changeMask |= GCCapStyle; + if( dGC.joinStyle != pGC->joinStyle ) + changeMask |= GCJoinStyle; + if( dGC.fillStyle != pGC->fillStyle ) + changeMask |= GCFillStyle; + if( dGC.tile.pixmap != pGC->tile.pixmap ) + changeMask |= GCTile; + if( dGC.stipple != pGC->stipple ) + changeMask |= GCStipple; + if( dGC.patOrg.x != pGC->patOrg.x ) + changeMask |= GCTileStipXOrigin; + if( dGC.patOrg.y != pGC->patOrg.y ) + changeMask |= GCTileStipYOrigin; + + if( dGC.numInDashList == pGC->numInDashList ) + for( i = 0; i < dGC.numInDashList; i++ ) + if( cPriv->dash[i] != pGC->dash[i] ) + { + changeMask |= GCDashList; + break; + } + else + changeMask |= GCDashList; + } + + /* + * Once the changeMask has been determined, we scan it and emit + * the appropriate PCL code to set the drawing attributes. + */ + + /* Must be in HP-GL/2 mode to set attributes */ + SEND_PCL( *outFile, "\033%0B" ); + + if( changeMask & GCFunction ) + { +#ifdef XP_PCL_COLOR + + if( pGC->alu == GXclear ) + SEND_PCL( *outFile, "SP0;" ); + else + SEND_PCL( *outFile, "SP1;" ); +#else + if( pGC->alu == GXclear ) + SEND_PCL( *outFile, "SP0;" ); + else + SEND_PCL( *outFile, "SP1;" ); +#endif /* XP_PCL_COLOR */ + } + +#if 0 + if( changeMask & GCFunction ) + { + int rop = -1; + char t[10]; + + switch( pGC->alu ) + { + case GXclear: + rop = 1; + break; + case GXand: + rop = 136; + break; + case GXandReverse: + rop = 68; + break; + case GXcopy: + rop = 204; + break; + case GXandInverted: + rop = 34; + break; + case GXnoop: + rop = 170; + break; + case GXxor: + rop = 238; + break; + case GXor: + rop = 238; + break; + case GXnor: + rop = 17; + break; + case GXequiv: + rop = 153; + break; + case GXinvert: + rop = 85; + break; + case GXorReverse: + rop = 221; + break; + case GXcopyInverted: + rop = 51; + break; + case GXorInverted: + rop = 187; + break; + case GXnand: + rop = 119; + break; + case GXset: + rop = 0; + break; + } + if( rop != -1 ) + { + sprintf( t, "MC1,%d;", rop ); + SEND_PCL( *outFile, t ); +#endif + + if( changeMask & GCForeground ) + switch( pGC->fgPixel ) + { + case 1: + SEND_PCL( *outFile, "SP1;" ); + break; + default: + SEND_PCL( *outFile, "SP0;" ); + break; + } + + if( changeMask & GCForeground ) + { + char t[40]; + +#ifdef XP_PCL_COLOR + c = wColormap( ((WindowPtr)pDrawable) ); + cmap = (ColormapPtr)LookupIDByType( c, RT_COLORMAP ); + + if( cmap->class == TrueColor ) + { + if( pGC->fillStyle != FillTiled || pGC->tileIsPixel ) { + unsigned short r, g, b; + + r = (pGC->fgPixel & cmap->pVisual->redMask) + >> (cmap->pVisual->offsetRed ); + g = (pGC->fgPixel & cmap->pVisual->greenMask) + >> (cmap->pVisual->offsetGreen); + b = (pGC->fgPixel & cmap->pVisual->blueMask) + >> (cmap->pVisual->offsetBlue); + + PclLookUp(cmap, cPriv, &r, &g, &b); + sprintf( t, "\033%%0A\033*v%ua%ub%uc0I\033%%0B", r, g, b); + SEND_PCL( *outFile, t ); + } + } + else /* PseudoColor or StaticGray */ + { + sprintf( t, "SP%d;", pGC->fgPixel ); + SEND_PCL( *outFile, t ); + } +#else + ScreenPtr screen; + screen = pDrawable->pScreen; + if ( pGC->fgPixel == screen->whitePixel ) + SEND_PCL( *outFile, "SP0;"); + else + SEND_PCL( *outFile, "SP1;"); +#endif /* XP_PCL_COLOR */ + } + + if( changeMask & GCJoinStyle ) + switch( pGC->joinStyle ) + { + case JoinMiter: + SEND_PCL( *outFile, "LA2,1;" ); + break; + case JoinRound: + SEND_PCL( *outFile, "LA2,4;" ); + break; + case JoinBevel: + SEND_PCL( *outFile, "LA2,5;" ); + break; + } + + if( changeMask & GCCapStyle ) + switch( pGC->capStyle ) + { + case CapNotLast: + case CapButt: + SEND_PCL( *outFile, "LA1,1;" ); + break; + case CapRound: + SEND_PCL( *outFile, "LA1,4;" ); + break; + case CapProjecting: + SEND_PCL( *outFile, "LA1,2;" ); + break; + } + + if( changeMask & GCLineWidth ) + { + float penWidth, pixelsPerMM; + ScreenPtr screen; + char temp[30]; + + if( pGC->lineWidth == 0 || pGC->lineWidth == 1 ) + /* A pen width of 0.0 mm gives a one-pixel-wide line */ + penWidth = 0.0; + else + { + screen = pDrawable->pScreen; + pixelsPerMM = (float)screen->width / (float)screen->mmWidth; + + penWidth = pGC->lineWidth / pixelsPerMM; + } + sprintf( temp, "PW%g;", penWidth ); + SEND_PCL( *outFile, temp ); + } + + if( changeMask & GCLineStyle ) + { + int i, num = pGC->numInDashList; + double total; + char t[30]; + + switch( pGC->lineStyle ) + { + case LineSolid: + SEND_PCL( *outFile, "LT;" ); + break; + case LineOnOffDash: + /* + * Calculate the pattern length of the dashes, in pixels, + * then convert to mm + */ + for( i = 0, total = 0.0; i < 20 && i < num; i++ ) + total += pGC->dash[i]; + if( num % 2 ) + for( i = num; i < 20 && i < num + num; i++ ) + total += pGC->dash[i-num]; + + total *= ( (double)pDrawable->pScreen->mmWidth / + (double)pDrawable->pScreen->width ); + + sprintf( t, "LT8,%f,1;", total ); + SEND_PCL( *outFile, t ); + break; + } + } + + + if( changeMask & GCFillStyle ) + switch( pGC->fillStyle ) + { + case FillSolid: + SEND_PCL( *outFile, "FT1;TR0;CF;" ); + break; + case FillTiled: + SEND_PCL( *outFile, "FT22,100;TR0;CF2,0;" ); + break; + case FillOpaqueStippled: + SEND_PCL( *outFile, "FT22,101;TR0;CF2,0;" ); + if( pGC->fgPixel != gcPriv->stippleFg || + pGC->bgPixel != gcPriv->stippleBg ) + changeMask |= GCStipple; + break; + case FillStippled: + SEND_PCL( *outFile, "FT22,102;TR1;CF2,0;" ); + break; + } + + if( changeMask & GCTile && !pGC->tileIsPixel ) + { + char t[80], *bits, *row, *mod; + int h, w, w2, sz; + int i, j; + + h = pGC->tile.pixmap->drawable.height; + w = pGC->tile.pixmap->drawable.width; + + if( pGC->tile.pixmap->drawable.depth == 1 ) + { + sz = h * BitmapBytePad( w ); + + bits = (char *)xalloc( sz ); + mfbGetImage(pGC->tile.pixmap, 0, 0, w, h, XYPixmap, ~0, bits); + PclSendPattern( bits, sz, 1, h, w, 100, *outFile ); + xfree( bits ); + } + else if( pGC->tile.pixmap->drawable.depth == 8 ) + { + sz = h * PixmapBytePad( w, 8 ); + bits = (char *)xalloc( sz ); + cfbGetImage(pGC->tile.pixmap, 0, 0, w, h, ZPixmap, ~0, bits); + PclSendPattern( bits, sz, 8, h, w, 100, *outFile ); + xfree( bits ); + } +#if PSZ == 32 + else + { + sz = h * PixmapBytePad( w, 24 ); + + bits = (char *)xalloc( sz ); + cfb32GetImage(pGC->tile.pixmap, 0, 0, w, h, ZPixmap, ~0, bits); + PclSendPattern( bits, sz, 24, h, w, 100, *outFile ); + xfree( bits ); + } +#endif + } + + if( changeMask & ( GCTileStipXOrigin | GCTileStipYOrigin ) ) + { + char t[30]; + + sprintf( t, "AC%d,%d;", pGC->patOrg.x, pGC->patOrg.y ); + SEND_PCL( *outFile, t ); + } + + /* + * We have to resend the stipple pattern either when the stipple itself + * changes, or if we're in FillOpaqueStippled mode and either the + * foreground or the background color changes. + */ + if( changeMask & GCStipple || + ( pGC->fillStyle == FillOpaqueStippled && + ( pGC->fgPixel != gcPriv->stippleFg || + pGC->bgPixel != gcPriv->stippleBg ) ) ) + { + int h, w, i, sz, w2; + char *bits, *row, t[30]; + PixmapPtr scratchPix; + GCPtr scratchGC; + + if( pGC->stipple != NULL ) + { + SEND_PCL( *outFile, "\033%0A" ); + + h = pGC->stipple->drawable.height; + w = pGC->stipple->drawable.width; + sz = h * BitmapBytePad( w ); + + bits = (char *)xalloc( sz ); + mfbGetImage( pGC->stipple, 0, 0, w, h, XYPixmap, ~0, bits ); + + w2 = ( w / 8 ) + ( ( w%8 ) ? 1 : 0 ); + /* + * XXX The PCL docs say that I need to word-align each + * XXX row, but I get garbage when I do... + */ + /* + if( w2 % 2 ) + w2++; + */ + + sprintf( t, "\033*c102g%dW", h * w2 + 8 ); + SEND_PCL( *outFile, t ); + + sprintf( t, "%c%c%c%c%c%c%c%c", 0, 0, 1, 0, h>>8, h&0xff, w>>8, + w&0xff ); + SEND_PCL_COUNT( *outFile, t, 8 ); + + for( row = bits, i = 0; i < h; i++, row += BitmapBytePad( w ) ) + SEND_PCL_COUNT( *outFile, row, w2 ); + + SEND_PCL( *outFile, "\033%0B" ); + + xfree( bits ); + + /* + * Also do the opaque stipple, as a tile + */ + if( pGC->depth != 1 ) + sz = h * PixmapBytePad( w, pGC->depth ); + bits = (char *)xalloc( sz ); + + scratchPix = + (*pGC->pScreen->CreatePixmap)( pGC->pScreen, + w, h, pGC->depth ); + scratchGC = GetScratchGC( pGC->depth, pGC->pScreen ); + CopyGC( pGC, scratchGC, ~0L ); + + if( pGC->depth == 1 ) + { + mfbValidateGC( scratchGC, ~0L, + (DrawablePtr)scratchPix ); + mfbCopyPlane( pGC->stipple, + (DrawablePtr)scratchPix, scratchGC, 0, + 0, w, h, 0, 0, 1 ); + mfbGetImage( scratchPix, 0, 0, w, h, XYPixmap, ~0, + bits ); + } + else if( pGC->depth <= 32 ) + { +#if PSZ == 8 + cfbValidateGC( scratchGC, ~0L, + (DrawablePtr)scratchPix ); + cfbCopyPlane( pGC->stipple, + (DrawablePtr)scratchPix, scratchGC, 0, + 0, w, h, 0, 0, 1 ); + cfbGetImage( scratchPix, 0, 0, w, h, ZPixmap, ~0, + bits ); +#else + cfb32ValidateGC( scratchGC, ~0L, + (DrawablePtr)scratchPix ); + cfb32CopyPlane( pGC->stipple, + (DrawablePtr)scratchPix, scratchGC, 0, + 0, w, h, 0, 0, 1 ); + cfb32GetImage( scratchPix, 0, 0, w, h, ZPixmap, ~0, + bits ); +#endif + } + PclSendPattern( bits, sz, pGC->depth, h, w, 101, *outFile ); + FreeScratchGC( scratchGC ); + (*pGC->pScreen->DestroyPixmap)( scratchPix ); + xfree( bits ); + } + } + + if( changeMask & ( GCTileStipXOrigin | GCTileStipYOrigin ) ) + { + char t[30]; + + sprintf( t, "AC%d,%d;", pGC->patOrg.x, pGC->patOrg.y ); + SEND_PCL( *outFile, t ); + } + + if( changeMask & GCDashList ) + { + int num = pGC->numInDashList; + double total; + char dashes[20]; + char t[100], t2[20]; + + /* Make up the doubled dash list, if necessary */ + for( i = 0; i < 20 && i < num; i++ ) + dashes[i] = pGC->dash[i]; + + if( num % 2 ) + { + for( i = num; i < 20 && i < num + num; i++ ) + dashes[i] = dashes[i-num]; + if( ( num *= 2 ) > 20 ) + num = 20; + } + + /* Add up dash lengths to get percentage */ + for( i = 0, total = 0; i < num; i++ ) + total += dashes[i]; + + /* Build up the HP-GL/2 for the dash list */ + strcpy( t, "UL8" ); + for( i = 0; i < num; i++ ) + { + sprintf( t2, ",%d", + (int)( ( (double)dashes[i] / total * 100.0 ) + 0.5 ) ); + strcat( t, t2 ); + } + strcat( t, ";" ); + SEND_PCL( *outFile, t ); + } + + + /* Go back to PCL mode */ + SEND_PCL( *outFile, "\033%0A" ); + + /* + * Update the drawable's private information, which includes + * erasing the drawable's private changeMask, since all the + * changes have been made. + */ + if( changeMask ) + PclSetDrawablePrivateGC( pDrawable, *pGC ); + + return TRUE; +} + +/* + * PclComputeCompositeClip() + * + * I'd like to use the miComputeCompositeClip function, but it sticks + * things into the mi GC privates, where the PCL driver can't get at + * it. So, rather than mess around with the mi code, I ripped it out + * and made the appropriate changes here. + */ + + +void +PclComputeCompositeClip(pGC, pDrawable) + GCPtr pGC; + DrawablePtr pDrawable; +{ + ScreenPtr pScreen = pGC->pScreen; + PclGCPrivPtr devPriv = (PclGCPrivPtr) + (pGC->devPrivates[PclGCPrivateIndex].ptr); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDrawable; + RegionPtr pregWin; + Bool freeTmpClip, freeCompClip; + + if (pGC->subWindowMode == IncludeInferiors) + { + pregWin = NotClippedByChildren(pWin); + freeTmpClip = TRUE; + } + else + { + pregWin = &pWin->clipList; + freeTmpClip = FALSE; + } + freeCompClip = devPriv->freeCompClip; + + /* + * if there is no client clip, we can get by with just keeping the + * pointer we got, and remembering whether or not should destroy (or + * maybe re-use) it later. this way, we avoid unnecessary copying of + * regions. (this wins especially if many clients clip by children + * and have no client clip.) + */ + if (pGC->clientClipType == CT_NONE) + { + if (freeCompClip) + REGION_DESTROY(pScreen, devPriv->pCompositeClip); + devPriv->pCompositeClip = pregWin; + devPriv->freeCompClip = freeTmpClip; + } + else + { + /* + * we need one 'real' region to put into the composite clip. if + * pregWin the current composite clip are real, we can get rid of + * one. if pregWin is real and the current composite clip isn't, + * use pregWin for the composite clip. if the current composite + * clip is real and pregWin isn't, use the current composite + * clip. if neither is real, create a new region. + */ + + REGION_TRANSLATE(pScreen, pGC->clientClip, + pDrawable->x + pGC->clipOrg.x, + pDrawable->y + pGC->clipOrg.y); + + if (freeCompClip) + { + REGION_INTERSECT(pGC->pScreen, devPriv->pCompositeClip, + pregWin, pGC->clientClip); + if (freeTmpClip) + REGION_DESTROY(pScreen, pregWin); + } + else if (freeTmpClip) + { + REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip); + devPriv->pCompositeClip = pregWin; + } + else + { + devPriv->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); + REGION_INTERSECT(pScreen, devPriv->pCompositeClip, + pregWin, pGC->clientClip); + } + devPriv->freeCompClip = TRUE; + REGION_TRANSLATE(pScreen, pGC->clientClip, + -(pDrawable->x + pGC->clipOrg.x), + -(pDrawable->y + pGC->clipOrg.y)); + } + } /* end of composite clip for a window */ + else + { + BoxRec pixbounds; + + /* XXX should we translate by drawable.x/y here ? */ + pixbounds.x1 = 0; + pixbounds.y1 = 0; + pixbounds.x2 = pDrawable->width; + pixbounds.y2 = pDrawable->height; + + if (devPriv->freeCompClip) + { + REGION_RESET(pScreen, devPriv->pCompositeClip, &pixbounds); + } + else + { + devPriv->freeCompClip = TRUE; + devPriv->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1); + } + + if (pGC->clientClipType == CT_REGION) + { + REGION_TRANSLATE(pScreen, devPriv->pCompositeClip, + -pGC->clipOrg.x, -pGC->clipOrg.y); + REGION_INTERSECT(pScreen, devPriv->pCompositeClip, + devPriv->pCompositeClip, pGC->clientClip); + REGION_TRANSLATE(pScreen, devPriv->pCompositeClip, + pGC->clipOrg.x, pGC->clipOrg.y); + } + } /* end of composite clip for pixmap */ +} + +/* + * PclValidateGC() + * + * Unlike many screen GCValidate routines, this function should not need + * to mess with setting the drawing functions. Different drawing + * functions are usually needed to optimize such things as drawing + * wide or dashed lines; this functionality will be handled primarily + * by the printer itself, while the necessary PCL code to set the + * attributes will be done in PclUpdateDrawableGC(). + */ + +/*ARGSUSED*/ +void +PclValidateGC( pGC, changes, pDrawable ) + GCPtr pGC; + Mask changes; + DrawablePtr pDrawable; +{ + XpContextPtr pCon; + PclContextPrivPtr pConPriv; + extern int mfbGCPrivateIndex; + extern int cfbGCPrivateIndex; + + /* + * Pixmaps should be handled by their respective validation + * functions. + */ + if( pDrawable->type == DRAWABLE_PIXMAP ) + { + if( pDrawable->depth == 1 ) + { + miRegisterGCPrivateIndex( mfbGCPrivateIndex ); + mfbValidateGC( pGC, ~0, pDrawable ); + } + else if( pDrawable->depth <= 32 ) + { +#if PSZ == 8 + miRegisterGCPrivateIndex( cfbGCPrivateIndex ); + cfbValidateGC( pGC, ~0, pDrawable ); +#else + miRegisterGCPrivateIndex( cfbGCPrivateIndex ); + cfb32ValidateGC( pGC, ~0, pDrawable ); +#endif + } + return; + } + + /* + * Reset the drawing operations + */ + pGC->ops = &PclGCOps; + + /* + * Validate the information, and correct it if necessary. + */ + + /* + * If necessary, compute the composite clip region. (Code ripped + * from migc.c) + */ + if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || + (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) + ) + { + PclComputeCompositeClip(pGC, pDrawable); + } + + /* + * PCL does not directly support the DoubleDash line style, nor is + * there an easy way to simulate it, so we'll just change it to a + * LineOnOffDash, which is supported by PCL. + */ + if( ( changes & GCLineStyle ) && ( pGC->lineStyle == LineDoubleDash ) ) + pGC->lineStyle = LineOnOffDash; + + /* + * Update the drawable's changeMask to reflect the changes made to the GC. + */ +/* + PclSetDrawablePrivateGC( pDrawable, *pGC, changes ); +*/ +} + diff --git a/Xprint/pcl/PclInit.c b/Xprint/pcl/PclInit.c new file mode 100644 index 000000000..791a33dfe --- /dev/null +++ b/Xprint/pcl/PclInit.c @@ -0,0 +1,658 @@ +/* $Xorg: PclInit.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclInit.c +** * +** * Contents: +** * Initialization code of Pcl driver for the print server. +** * +** * Created: 1/30/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include +#include +#include + +#include "Pcl.h" +#include "AttrValid.h" + +#include "cfb.h" + +#include "attributes.h" +#include "windowstr.h" + +#define MODELDIRNAME "/models" +extern char *XpGetConfigDir(); + +static void AllocatePclPrivates( + ScreenPtr pScreen); +static int PclInitContext(XpContextPtr pCon); + +extern Bool _XpBoolNoop(); +extern void _XpVoidNoop(); + +extern unsigned char *PclReadMap(char *, int *); + +int PclScreenPrivateIndex; +int PclContextPrivateIndex; +int PclPixmapPrivateIndex; +int PclWindowPrivateIndex; +int PclGCPrivateIndex; + +#ifdef XP_PCL_COLOR +/* + * The supported visuals on this screen + */ +static VisualRec Visuals[] = +{ + { 1, StaticGray, 1, 2, 1, 0, 0, 0, 0, 0, 0 }, + { 2, PseudoColor, 8, 256, 8, 0, 0, 0, 0, 0, 0 }, + { 3, TrueColor, 8, 256, 24, 0xFF0000, 0xFF00, 0xFF, 16, 8, 0 } +}; + +/* + * The supported depths on this screen + */ +static DepthRec Depths[] = +{ + { 1, 1, NULL }, + { 8, 1, NULL }, + { 24, 1, NULL } +}; +#else +/* + * The supported visuals on this screen + */ +static VisualRec Visuals[] = +{ + { 1, StaticGray, 1, 2, 1, 0, 0, 0, 0, 0, 0} +}; + +/* + * The supported depths on this screen + */ +static DepthRec Depths[] = +{ + { 1, 1, NULL } +}; +#endif /* XP_PCL_COLOR */ + + +#define NUM_VISUALS(visuals) (sizeof(visuals) / sizeof(VisualRec)) +#define NUM_DEPTHS(depths) (sizeof(depths) / sizeof(DepthRec)) + +Bool +PclCloseScreen(int index, + ScreenPtr pScreen) +{ + Bool status = Success; + PclScreenPrivPtr pPriv = pScreen->devPrivates[PclScreenPrivateIndex].ptr; + +/* + if( pPriv->CloseScreen != (Bool (*)())NULL ) + { + pScreen->CloseScreen = pPriv->CloseScreen; + status = pScreen->CloseScreen( index, pScreen ); + pScreen->CloseScreen = PclCloseScreen; + } +*/ + + /* + * Finish cleaning up cfb (code taken from cfbCloseScreen) + */ +#ifdef XP_PCL_COLOR +#ifdef CFB_NEED_SCREEN_PRIVATE + xfree( pScreen->devPrivates[cfbScreenPrivateIndex].ptr ); +#else + xfree( pScreen->devPrivate ); +#endif +#endif + + xfree( pPriv ); + + return status; +} + +Bool +InitializePclDriver(ndx, pScreen, argc, argv) + int ndx; + ScreenPtr pScreen; + int argc; + char **argv; +{ + int maxRes, xRes, yRes, maxWidth, maxHeight, maxDim, numBytes; + int i; + PclScreenPrivPtr pPriv; + char **printerNames; + int numPrinters; + + /* + * Register this driver's InitContext function with the print + * extension. This is a bit sleazy, as the extension hasn't yet + * been initialized, but the extensionneeds to know this, and this + * seems the best time to provide the information. + */ +#ifdef XP_PCL_COLOR + XpRegisterInitFunc( pScreen, "XP-PCL-COLOR", PclInitContext ); +#elif XP_PCL_MONO + XpRegisterInitFunc( pScreen, "XP-PCL-MONO", PclInitContext ); +#else + XpRegisterInitFunc( pScreen, "XP-PCL-LJ3", PclInitContext ); +#endif /* XP_PCL_MONO */ + + /* + * Create and fill in the devPrivate for the PCL driver. + */ + AllocatePclPrivates(pScreen); + + pPriv = + (PclScreenPrivPtr)pScreen->devPrivates[PclScreenPrivateIndex].ptr; + + maxDim = MAX( pScreen->height, pScreen->width ); + xRes = pScreen->width / ( pScreen->mmWidth / 25.4 ); + yRes = pScreen->height / ( pScreen->mmHeight / 25.4 ); + maxRes = MAX( xRes, yRes ); + +#ifdef XP_PCL_COLOR + cfbScreenInit( pScreen, NULL, maxDim, maxDim, maxRes, maxRes, + maxRes ); + /* + * Clean up the fields that we stomp (code taken from cfbCloseScreen) + */ + for( i = 0; i < pScreen->numDepths; i++ ) + xfree( pScreen->allowedDepths[i].vids ); + xfree( pScreen->allowedDepths ); + xfree( pScreen->visuals ); +#else + mfbScreenInit( pScreen, NULL, maxDim, maxDim, maxRes, maxRes, + maxRes ); +#endif /* XP_PCL_COLOR */ + + pScreen->defColormap = FakeClientID(0); + pScreen->blackPixel = 1; + pScreen->whitePixel = 0; + +/* + pPriv->CloseScreen = pScreen->CloseScreen; +*/ + pScreen->CloseScreen = PclCloseScreen; + + pScreen->QueryBestSize = (QueryBestSizeProcPtr)PclQueryBestSize; + pScreen->SaveScreen = _XpBoolNoop; + pScreen->GetImage = _XpVoidNoop; + pScreen->GetSpans = _XpVoidNoop; + pScreen->CreateWindow = PclCreateWindow; + pScreen->DestroyWindow = PclDestroyWindow; +/* + pScreen->PositionWindow = PclPositionWindow; +*/ + pScreen->ChangeWindowAttributes = PclChangeWindowAttributes; +/* + pScreen->RealizeWindow = PclMapWindow; + pScreen->UnrealizeWindow = PclUnmapWindow; +*/ + pScreen->PaintWindowBackground = PclPaintWindow; + pScreen->PaintWindowBorder = PclPaintWindow; + pScreen->CopyWindow = PclCopyWindow; /* XXX Hard routine to write! */ + + pScreen->CreatePixmap = PclCreatePixmap; + pScreen->DestroyPixmap = PclDestroyPixmap; + pScreen->RealizeFont = PclRealizeFont; + pScreen->UnrealizeFont = PclUnrealizeFont; + pScreen->CreateGC = PclCreateGC; + + pScreen->CreateColormap = PclCreateColormap; + pScreen->DestroyColormap = PclDestroyColormap; + pScreen->InstallColormap = (InstallColormapProcPtr)NoopDDA; + pScreen->UninstallColormap = (UninstallColormapProcPtr)NoopDDA; + pScreen->ListInstalledColormaps = PclListInstalledColormaps; + pScreen->StoreColors = PclStoreColors; +/* + pScreen->ResolveColor = PclResolveColor; +*/ + + pScreen->BitmapToRegion = mfbPixmapToRegion; + + pScreen->ConstrainCursor = PclConstrainCursor; + pScreen->CursorLimits = PclCursorLimits; + pScreen->DisplayCursor = PclDisplayCursor; + pScreen->RealizeCursor = PclRealizeCursor; + pScreen->UnrealizeCursor = PclUnrealizeCursor; + pScreen->RecolorCursor = PclRecolorCursor; + pScreen->SetCursorPosition = PclSetCursorPosition; + + pScreen->visuals = Visuals; + pScreen->numVisuals = NUM_VISUALS( Visuals ); + pScreen->allowedDepths = Depths; + pScreen->numDepths = NUM_DEPTHS( Depths ); + + for( i = 0; i < NUM_DEPTHS( Depths ); i++ ) + { + pScreen->allowedDepths[i].vids = + (VisualID *)xalloc( sizeof(VisualID ) ); + pScreen->allowedDepths[i].vids[0] = i + 1; + } + +#ifdef XP_PCL_COLOR + pScreen->rootVisual = 2; + pScreen->rootDepth = 8; +#else + pScreen->rootVisual = 1; + pScreen->rootDepth = 1; +#endif /* XP_PCL_COLOR */ + + pPriv->colormaps = NULL; + PclCreateDefColormap( pScreen ); + + return TRUE; +} + +static void +AllocatePclPrivates( + ScreenPtr pScreen) +{ + static int PclGeneration = -1; + + if(PclGeneration != serverGeneration) + { + PclScreenPrivateIndex = AllocateScreenPrivateIndex(); + + PclWindowPrivateIndex = AllocateWindowPrivateIndex(); + AllocateWindowPrivate( pScreen, PclWindowPrivateIndex, + sizeof( PclWindowPrivRec ) ); + + PclContextPrivateIndex = XpAllocateContextPrivateIndex(); + XpAllocateContextPrivate( PclContextPrivateIndex, + sizeof( PclContextPrivRec ) ); + + PclGCPrivateIndex = AllocateGCPrivateIndex(); + AllocateGCPrivate( pScreen, PclGCPrivateIndex, + sizeof( PclGCPrivRec ) ); + + PclPixmapPrivateIndex = AllocatePixmapPrivateIndex(); + AllocatePixmapPrivate( pScreen, PclPixmapPrivateIndex, + sizeof( PclPixmapPrivRec ) ); + + PclGeneration = serverGeneration; + } + + pScreen->devPrivates[PclScreenPrivateIndex].ptr = (pointer)xalloc( + sizeof(PclScreenPrivRec)); +} + +/* + * PclInitContext + * + * Establish the appropriate values for a PrintContext used with the PCL + * driver. + */ + +static char DOC_ATT_SUPP[]="document-attributes-supported"; +static char DOC_ATT_VAL[]="document-format"; +static char JOB_ATT_SUPP[]="job-attributes-supported"; +static char JOB_ATT_VAL[]=""; +static char PAGE_ATT_SUPP[]="xp-page-attributes-supported"; +static char PAGE_ATT_VAL[]="content-orientation default-printer-resolution \ +default-input-tray default-medium plex"; + +static int +PclInitContext( pCon ) + XpContextPtr pCon; +{ + XpDriverFuncsPtr pFuncs; + PclContextPrivPtr pConPriv; + char *server, *attrStr; + char *modelID; + char *configDir; + char *pathName; + extern XpValidatePoolsRec PclValidatePoolsRec; + int i, j; + float width, height; + XpOidMediumDiscreteSizeList* ds_list; + XpOidArea* repro; + XpOid page_size; + XpOidMediumSS* m; + + /* + * Initialize the attribute store for this printer. + */ + XpInitAttributes( pCon ); + + /* + * Initialize the function pointers + */ + pFuncs = &( pCon->funcs ); + pFuncs->StartJob = PclStartJob; + pFuncs->EndJob = PclEndJob; + pFuncs->StartDoc = (int (*)())PclStartDoc; + pFuncs->EndDoc = PclEndDoc; + pFuncs->StartPage = PclStartPage; + pFuncs->EndPage = PclEndPage; + pFuncs->PutDocumentData = PclDocumentData; + pFuncs->GetDocumentData = PclGetDocumentData; + pFuncs->GetAttributes = (char *(*)())PclGetAttributes; + pFuncs->SetAttributes = (int (*)())PclSetAttributes; + pFuncs->AugmentAttributes = (int (*)())PclAugmentAttributes; + pFuncs->GetOneAttribute = (char *(*)())PclGetOneAttribute; + pFuncs->DestroyContext = PclDestroyContext; + pFuncs->GetMediumDimensions = PclGetMediumDimensions; + pFuncs->GetReproducibleArea = PclGetReproducibleArea; + + + /* + * Set up the context privates + */ + pConPriv = + (PclContextPrivPtr)pCon->devPrivates[PclContextPrivateIndex].ptr; + + pConPriv->jobFileName = (char *)NULL; + pConPriv->pageFileName = (char *)NULL; + pConPriv->pJobFile = (FILE *)NULL; + pConPriv->pPageFile = (FILE *)NULL; + pConPriv->dash = NULL; + pConPriv->validGC = 0; + + pConPriv->getDocClient = (ClientPtr)NULL; + pConPriv->getDocBufSize = 0; + modelID = XpGetOneAttribute(pCon, XPPrinterAttr, "xp-model-identifier"); + if ( (configDir = XpGetConfigDir(False)) != (char *) NULL ) { + pathName = (char *)xalloc(strlen(configDir) + strlen(MODELDIRNAME) + + strlen(modelID) + strlen("color.map") + 4); + if (pathName) { + sprintf(pathName, "%s/%s/%s/%s", configDir, MODELDIRNAME, modelID, + "color.map"); + pConPriv->ctbl = PclReadMap(pathName, &pConPriv->ctbldim); + xfree(pathName); + + } else + pConPriv->ctbl = NULL; + } else + pConPriv->ctbl = NULL; + +#ifdef XP_PCL_LJ3 + /* + * Initialize the spooling buffer for saving the figures temporary + * (LaserJet IIIs printers don't support the macro function which + * includes some HP-GL/2 commands.) + */ + pConPriv->fcount = 0; + if ( !(pConPriv->figures = (char *)xalloc(1024)) ) + pConPriv->fcount_max = 0; + else + pConPriv->fcount_max = 1024; +#endif /* XP_PCL_LJ3 */ + + /* + * document-attributes-supported + */ + server = XpGetOneAttribute( pCon, XPServerAttr, DOC_ATT_SUPP ); + if( ( attrStr = (char *)xalloc(strlen(server) + strlen(DOC_ATT_SUPP) + + strlen(DOC_ATT_VAL) + + strlen(PAGE_ATT_VAL) + 6 ) ) + == (char *)NULL ) + return BadAlloc; + sprintf( attrStr, "*%s:\t%s %s %s", DOC_ATT_SUPP, server, + DOC_ATT_VAL, PAGE_ATT_VAL ); + XpAugmentAttributes( pCon, XPPrinterAttr, attrStr ); + xfree( attrStr ); + + /* + * job-attributes-supported + */ + server = XpGetOneAttribute( pCon, XPServerAttr, JOB_ATT_SUPP ); + if( ( attrStr = (char *)xalloc(strlen(server) + strlen(JOB_ATT_SUPP) + + strlen(JOB_ATT_VAL) + 4 ) ) + == (char *)NULL ) + return BadAlloc; + sprintf( attrStr, "*%s:\t%s %s", JOB_ATT_SUPP, server, JOB_ATT_VAL ); + XpAugmentAttributes( pCon, XPPrinterAttr, attrStr ); + xfree( attrStr ); + + /* + * xp-page-attributes-supported + */ + server = XpGetOneAttribute( pCon, XPServerAttr, PAGE_ATT_SUPP ); + if( ( attrStr = (char *)xalloc(strlen(server) + strlen(PAGE_ATT_SUPP) + + strlen(PAGE_ATT_VAL) + 4 ) ) + == (char *)NULL ) + return BadAlloc; + sprintf( attrStr, "*%s:\t%s %s", PAGE_ATT_SUPP, server, PAGE_ATT_VAL ); + XpAugmentAttributes( pCon, XPPrinterAttr, attrStr ); + xfree( attrStr ); + + /* + * Validate the attribute pools + */ + XpValidateAttributePool( pCon, XPPrinterAttr, &PclValidatePoolsRec ); + + /* + * Munge the reproducible areas to reflect the fact that PCL will not let + * me move the right or left margins closer than .25" to the edge of the + * paper. + */ + m = XpGetMediumSSAttr( pCon, XPPrinterAttr, + xpoid_att_medium_source_sizes_supported, + (const XpOidList*) NULL, + (const XpOidList*) NULL ); + for( i = 0; i < XpOidMediumSSCount( m ); i++ ) + { + if( XpOidMediumSS_DISCRETE == (m->mss)[i].mstag ) + { + ds_list = (m->mss)[i].ms.discrete; + for( j = 0; j < ds_list->count; j++ ) + { + repro = &(ds_list->list)[j].assured_reproduction_area; + page_size = (ds_list->list)[j].page_size; + XpGetMediumMillimeters( page_size, &width, &height ); + + if( repro->minimum_x < 6.35 ) + repro->minimum_x = 6.35; + if( width - repro->maximum_x < 6.35 ) + repro->maximum_x = width - 6.35; + } + } + } + XpPutMediumSSAttr( pCon, XPPrinterAttr, + xpoid_att_medium_source_sizes_supported, m ); + XpOidMediumSSDelete( m ); + + /* + * Finish validating the attribute pools + */ + + XpValidateAttributePool( pCon, XPDocAttr, &PclValidatePoolsRec ); + XpValidateAttributePool( pCon, XPJobAttr, &PclValidatePoolsRec ); + XpValidateAttributePool( pCon, XPPageAttr, &PclValidatePoolsRec ); + + /* + * Clear out the colormap storage + */ + pConPriv->palettes = NULL; + + return Success; +} + +static Bool +PclDestroyContext( pCon ) + XpContextPtr pCon; +{ + PclContextPrivPtr pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + PclPaletteMapPtr p, t; + PclCmapToContexts *pCmap; + ScreenPtr screen; + PclScreenPrivPtr sPriv; + PclContextListPtr con, prevCon, temp; + + + /* + * Clean up the temporary files + */ + if( pConPriv->pPageFile != (FILE *)NULL ) + { + fclose( pConPriv->pPageFile ); + pConPriv->pPageFile = (FILE *)NULL; + } + if( pConPriv->pageFileName != (char *)NULL ) + { + unlink( pConPriv->pageFileName ); + xfree( pConPriv->pageFileName ); + pConPriv->pageFileName = (char *)NULL; + } + + if( pConPriv->pJobFile != (FILE *)NULL ) + { + fclose( pConPriv->pJobFile ); + pConPriv->pJobFile = NULL; + } + if( pConPriv->jobFileName != (char *)NULL ) + { + unlink( pConPriv->jobFileName ); + xfree( pConPriv->jobFileName ); + pConPriv->jobFileName = (char *)NULL; + } + + xfree( pConPriv->dash ); + xfree(pConPriv->ctbl); + pConPriv->ctbl = NULL; +#ifdef XP_PCL_LJ3 + xfree( pConPriv->figures ); +#endif /* XP_PCL_LJ3 */ + + /* + * Destroy the colormap<->palette mappings + */ + p = pConPriv->palettes; + while( p ) + { + t = p; + p = p->next; + xfree( t ); + } + pConPriv->palettes = NULL; + + /* + * Remove the context from the screen-level colormap<->contexts mappings + */ + screen = screenInfo.screens[pCon->screenNum]; + sPriv = (PclScreenPrivPtr)screen->devPrivates[PclScreenPrivateIndex].ptr; + pCmap = sPriv->colormaps; + while( pCmap ) + { + con = pCmap->contexts; + prevCon = NULL; + + while( con ) + { + if( con->context->contextID == pCon->contextID ) + { + if( prevCon ) + { + temp = con; + prevCon->next = con = con->next; + } + else + { + temp = pCmap->contexts; + pCmap->contexts = con = con->next; + } + xfree( temp ); + } + else + con = con->next; + } + + pCmap = pCmap->next; + } + + XpDestroyAttributes(pCon); + + return Success; +} + +XpContextPtr +PclGetContextFromWindow( win ) + WindowPtr win; +{ + PclWindowPrivPtr pPriv; + + while( win ) + { + pPriv = + (PclWindowPrivPtr)win->devPrivates[PclWindowPrivateIndex].ptr; + if( pPriv->validContext ) + return pPriv->context; + + win = win->parent; + } + + return NULL; +} diff --git a/Xprint/pcl/PclLine.c b/Xprint/pcl/PclLine.c new file mode 100644 index 000000000..271bdfb16 --- /dev/null +++ b/Xprint/pcl/PclLine.c @@ -0,0 +1,314 @@ +/* $Xorg: PclLine.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclLine.c +** * +** * Contents: +** * Line drawing routines for the PCL driver +** * +** * Created: 10/11/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "Pcl.h" +#include "gcstruct.h" +#include "windowstr.h" + +/* + * PclPolyLine() + * PclPolySegment() + * + * Generates PCL code to draw a polyline, or a collection of distinct + * line segments, clipped by the current clip region. Since PCL + * supports clipping to a rectangle, and the clip region is + * represented as a collection of visible rectangles, we can draw and + * clip the line by repeatedly drawing the complete line, clipped to + * each rectangle in the clip region. + * + * Since each box in the clipping region generates approximately 30 + * bytes of PCL code, we have to have a way to avoid having a large + * number of boxes. The worst problem the case where the clipping + * region is a collection of one-pixel-high boxes, perhaps arising + * from a bitmap clip mask, or a region defined by a non-rectangular + * polygon. + * + * To alleviate this problem, we create a second clipping region, + * which consists of the union of the bounding boxes of each line + * segment. (Each bounding box is also increased by some amount + * related to the current line width to allow for non-zero-width + * lines, and for the various end and join styles.) This region is + * intersected with the "real" clipping region to get the region used + * to actually clip the polyline. This should result in a significant + * reduction in the number of clip rectangles, as the region-handling + * code should consolidate many of the fragments of one-pixel-high + * rectangles into larger rectangles. + */ + +void +PclPolyLine( pDrawable, pGC, mode, nPoints, pPoints ) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int nPoints; + xPoint *pPoints; +{ + char t[80], window[80]; + FILE *outFile; + int xoffset, yoffset; + int nbox; + BoxPtr pbox; + xRectangle *drawRects, *r; + RegionPtr drawRegion, region; + short fudge; + int i; + XpContextPtr pCon; + PclContextPrivPtr pConPriv; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + + /* + * Allocate the storage required to deal with the clipping + * regions. + */ + region = miRegionCreate( NULL, 0 ); + drawRects = (xRectangle *) + xalloc( ( nPoints - 1 ) * sizeof( xRectangle ) ); + + /* + * Calculate the "fudge factor" based on the line width. + * Multiplying by three seems to be a good first guess. + * XXX I need to think of a way to test this. + */ + fudge = 3 * pGC->lineWidth + 1; + + /* + * Generate the PCL code to draw the polyline, by defining it as a + * macro which uses the HP-GL/2 line drawing function. + */ + + MACRO_START( outFile, pConPriv ); + SAVE_PCL( outFile, pConPriv, "\033%0B" ); + + sprintf( t, "PU%d,%dPD\n", pPoints[0].x + pDrawable->x, + pPoints[0].y + pDrawable->y ); + SAVE_PCL( outFile, pConPriv, t ); /* Move to the start of the polyline */ + + switch( mode ) + { + case CoordModeOrigin: + xoffset = pDrawable->x; + yoffset = pDrawable->y; + SAVE_PCL( outFile, pConPriv, "PA" ); + break; + case CoordModePrevious: + xoffset = yoffset = 0; + SAVE_PCL( outFile, pConPriv, "PR" ); + break; + } + + /* + * Build the "drawing region" as we build the PCL to draw the + * line. + */ + for(i = 1, r = drawRects; i < nPoints; i++, r++ ) + { + if( i != 1 ) + SAVE_PCL( outFile, pConPriv, "," ); + + sprintf( t, "%d,%d", pPoints[i].x + xoffset, + pPoints[i].y + yoffset ); + SAVE_PCL( outFile, pConPriv, t ); + + r->x = MIN( pPoints[i-1].x, pPoints[i].x ) + xoffset - fudge; + r->y = MIN( pPoints[i-1].y, pPoints[i].y ) + yoffset - fudge; + r->width = abs( pPoints[i-1].x - pPoints[i].x ) + 2 * fudge; + r->height = abs( pPoints[i-1].y - pPoints[i].y ) + 2 * fudge; + } + SAVE_PCL( outFile, pConPriv, ";\033%0A" ); /* End the macro */ + MACRO_END( outFile ); + + /* + * Convert the collection of rectangles into a proper region, then + * intersect it with the clip region. + */ + drawRegion = miRectsToRegion( nPoints - 1, drawRects, CT_UNSORTED ); + if( mode == CoordModePrevious ) + miTranslateRegion( drawRegion, pPoints[0].x, pPoints[0].y ); + miIntersect( region, drawRegion, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the entire polyline to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, 1.0); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + xfree( drawRects ); +} + +void +PclPolySegment( pDrawable, pGC, nSegments, pSegments ) + DrawablePtr pDrawable; + GCPtr pGC; + int nSegments; + xSegment *pSegments; +{ + FILE *outFile, *dummy; + char t[80]; + int xoffset, yoffset; + int nbox, i; + unsigned long valid; + BoxPtr pbox; + xRectangle *drawRects, *r; + RegionPtr drawRegion, region; + short fudge; + XpContextPtr pCon; + PclContextPrivPtr pConPriv; + GC cacheGC; + + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + + /* + * Allocate the storage for the temporary regions. + */ + region = miRegionCreate( NULL, 0 ); + drawRects = (xRectangle *) + xalloc( nSegments * sizeof( xRectangle ) ); + + /* + * Calculate the fudge factor, based on the line width + */ + fudge = pGC->lineWidth * 3 + 1; + + /* + * Turn off line joining. + */ + SEND_PCL( outFile, "\033%0BLA2,6;\033%0A" ); + + /* + * Generate the PCL code to draw the segments, by defining them as + * a macro which uses the HP-GL/2 line drawing function. + * + * XXX I wonder if this should be implemented using the Encoded + * XXX Polyline function. Since I'm only sending it once, it's not + * XXX necessarily too important. + */ + + MACRO_START( outFile, pConPriv ); + SAVE_PCL( outFile, pConPriv, "\033%0B" ); + + xoffset = pDrawable->x; + yoffset = pDrawable->y; + + for( i = 0, r = drawRects; i < nSegments; i++, r++ ) + { + r->x = MIN( pSegments[i].x1, pSegments[i].x2 ) + xoffset; + r->y = MIN( pSegments[i].y1, pSegments[i].y2 ) + yoffset; + r->width = abs( pSegments[i].x1 - pSegments[i].x2 ); + r->height = abs( pSegments[i].y1 - pSegments[i].y2 ); + + sprintf( t, "PU%d,%d;PD%d,%d;", pSegments[i].x1 + xoffset, + pSegments[i].y1 + yoffset, pSegments[i].x2 + + xoffset, pSegments[i].y2 + yoffset ); + SAVE_PCL( outFile, pConPriv, t ); + + r->x -= fudge; + r->y -= fudge; + r->width += 2 * fudge; + r->height += 2 * fudge; + } + SAVE_PCL( outFile, pConPriv, "\033%0A" ); + MACRO_END ( outFile ); + + /* + * Convert the collection of rectangles into a proper region, then + * intersect it with the clip region. + */ + drawRegion = miRectsToRegion( nSegments, drawRects, CT_UNSORTED ); + miIntersect( region, drawRegion, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the entire set of segments to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, 1.0); + + /* + * Now we need to reset the line join mode to whatever it was at before. + * The easiest way is to force the cached GC's joinstyle to be different + * from the current GC's joinstyle, then re-update the GC. This way, we + * don't have to duplicate code unnecessarily. + */ + PclGetDrawablePrivateStuff( pDrawable, &cacheGC, &valid, &dummy ); + cacheGC.joinStyle = !cacheGC.joinStyle; + PclSetDrawablePrivateGC( pDrawable, cacheGC ); + PclUpdateDrawableGC( pGC, pDrawable, &outFile ); + + /* + * Clean up + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + xfree( drawRects ); +} + diff --git a/Xprint/pcl/PclMisc.c b/Xprint/pcl/PclMisc.c new file mode 100644 index 000000000..867393a46 --- /dev/null +++ b/Xprint/pcl/PclMisc.c @@ -0,0 +1,293 @@ +/* $Xorg: PclMisc.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclMisc.c +** * +** * Contents: +** * Miscellaneous code for Pcl driver. +** * +** * Created: 2/01/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "Xos.h" /* for SIGCLD on pre-POSIX systems */ +#include +#include "Pcl.h" + +#include "cursor.h" +#include "resource.h" + +#include "windowstr.h" +#include "propertyst.h" + + +/*ARGSUSED*/ +void +PclQueryBestSize( + int type, + short *pwidth, + short *pheight, + ScreenPtr pScreen) +{ + unsigned width, highBit; + + switch(type) + { + case CursorShape: + *pwidth = 0; + *pheight = 0; + break; + case TileShape: + case StippleShape: + width = *pwidth; + if (!width) break; + /* Return the nearest power of two >= what they gave us */ + highBit = 0x80000000; + /* Find the highest 1 bit in the given width */ + while(!(highBit & width)) + highBit >>= 1; + /* If greater than that then return the next power of two */ + if((highBit - 1) & width) + highBit <<= 1; + *pwidth = highBit; + /* height is a don't-care */ + break; + } +} + +/* + * GetPropString searches the window heirarchy from pWin up looking for + * a property by the name of propName. If found, returns the property's + * value. If not, it returns NULL. + */ +char * +GetPropString( + WindowPtr pWin, + char *propName) +{ + Atom atom; + PropertyPtr pProp = (PropertyPtr)NULL; + char *retVal; + + atom = MakeAtom(propName, strlen(propName), FALSE); + if(atom != BAD_RESOURCE) + { + WindowPtr pPropWin; + int n; + + /* + * The atom has been defined, but it might only exist as a + * property on an unrelated window. + */ + for(pPropWin = pWin; pPropWin != (WindowPtr)NULL; + pPropWin = pPropWin->parent) + { + for(pProp = (PropertyPtr)(wUserProps(pPropWin)); + pProp != (PropertyPtr)NULL; + pProp = pProp->next) + { + if (pProp->propertyName == atom) + break; + } + if(pProp != (PropertyPtr)NULL) + break; + } + if(pProp == (PropertyPtr)NULL) + return (char *)NULL; + + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + retVal = (char *)xalloc(n + 1); + (void)memcpy((void *)retVal, (void *)pProp->data, n); + retVal[n] = '\0'; + + return retVal; + } + + return (char *)NULL; +} + +#include + +/* ARGSUSED */ +static void SigchldHndlr ( + int dummy) +{ + int status, w; + struct sigaction act; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SigchldHndlr; + + w = wait (&status); + + /* + * Is this really necessary? + */ + sigaction(SIGCHLD, &act, (struct sigaction *)NULL); +} + +/* + * SystemCmd provides a wrapper for the 'system' library call. The call + * appears to be sensitive to the handling of SIGCHLD, so this wrapper + * sets the status to SIG_DFL, and then resets the established handler + * after system returns. + */ +int +SystemCmd(char *cmdStr) +{ + int status; + struct sigaction newAct, oldAct; + sigfillset(&newAct.sa_mask); + newAct.sa_flags = 0; + newAct.sa_handler = SIG_DFL; + sigfillset(&oldAct.sa_mask); + oldAct.sa_flags = 0; + oldAct.sa_handler = SigchldHndlr; + + /* + * get the old handler, and set the action to IGN + */ + sigaction(SIGCHLD, &newAct, &oldAct); + + status = system (cmdStr); + + sigaction(SIGCHLD, &oldAct, (struct sigaction *)NULL); + return status; +} + + +/* + * PclGetMediumDimensions is installed in the GetMediumDimensions field + * of each Pcl-initialized context. + */ +int +PclGetMediumDimensions(XpContextPtr pCon, + CARD16 *width, + CARD16 *height) +{ + XpGetMediumDimensions(pCon, width, height); + return Success; +} + +/* + * PclGetReproducibleArea is installed in the GetReproducibleArea field + * of each Pcl-initialized context. + */ +int +PclGetReproducibleArea(XpContextPtr pCon, + xRectangle *pRect) +{ + XpGetReproductionArea(pCon, pRect); + return Success; +} + +#ifdef XP_PCL_LJ3 +/* + * PclSpoolFigs spooled the rendering PCL/HP-GL2 commands into the + * temporary buffer pointed by figures pointer in pcl private context. + * LaserJet IIIs printers don't support the macro function which + * includes some HP-GL/2 commands. + */ +void +PclSpoolFigs(PclContextPrivPtr pConPriv, char *t, int n) +{ +char *ptr; + + ptr = pConPriv->figures; + while ( ( pConPriv->fcount + n) > pConPriv->fcount_max ) { + ptr = (char *)xrealloc(ptr, 1024 + pConPriv->fcount_max); + if ( !ptr ) + return; + pConPriv->figures = ptr; + pConPriv->fcount_max += 1024; + } + ptr += pConPriv->fcount; + pConPriv->fcount += n; + memcpy(ptr, t, n); +} +#endif /* XP_PCL_LJ3 */ + +/* + * PclSendData: + * For XP-PCL-COLOR/XP-PCL-MONO, it executes the macro stored before + * in the clipped area. + * For XP-PCL-LJ3, it draws the spooled figures in the clipped area. + */ +PclSendData( + FILE *outFile, + PclContextPrivPtr pConPriv, + BoxPtr pbox, + int nbox, + double ratio +) +{ +char *ptr; +int n; +char t[80]; + +#ifdef XP_PCL_LJ3 + ptr = pConPriv->figures; + n = pConPriv->fcount; +#else + ptr = "\033&f3X"; + n = 5; +#endif /* XP_PCL_LJ3 */ + + while( nbox ) + { + /* + * Set the HP-GL/2 input window to the current + * rectangle in the clip region, then send the code to + * execute the macro defined above. + */ + if (ratio == 1.0) + sprintf( t, "\033%%0BIW%d,%d,%d,%d;\033%%0A", + pbox->x1, pbox->y1, + pbox->x2, pbox->y2 ); + else + sprintf( t, "\033%%0BIW%g,%d,%g,%d;\033%%0A", + ratio * pbox->x1, pbox->y1, + ratio * pbox->x2, pbox->y2 ); + + SEND_PCL( outFile, t ); + SEND_PCL_COUNT( outFile, ptr, n); + + nbox--; + pbox++; + } +} diff --git a/Xprint/pcl/PclPixel.c b/Xprint/pcl/PclPixel.c new file mode 100644 index 000000000..23ec464e5 --- /dev/null +++ b/Xprint/pcl/PclPixel.c @@ -0,0 +1,154 @@ +/* $Xorg: PclPixel.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclPixel.c +** * +** * Contents: +** * Pixel-drawing code for the PCL DDX driver +** * +** * Created: 10/23/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include + +#include "windowstr.h" +#include "gcstruct.h" + +#include "Pcl.h" + +void +PclPolyPoint( pDrawable, pGC, mode, nPoints, pPoints ) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int nPoints; + xPoint *pPoints; +{ + char t[80], *command; + FILE *outFile; + int xoffset, yoffset; + BoxRec box; + int xloc, yloc, i; + XpContextPtr pCon; + PclContextPrivPtr cPriv; + PclPixmapPrivPtr pPriv; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + xoffset = pDrawable->x; + yoffset = pDrawable->y; + + /* + * Enter HP-GL/2 and change the line style to one in which only + * the vertices of the specified polyline are drawn. We must also + * temporarily change the line width so that only a single pixel + * is drawn. Then move to the first possible location. + */ + xloc = pPoints[0].x + pDrawable->x; + yloc = pPoints[0].y + pDrawable->y; + + sprintf( t, "\27%0BPW0,0;LT0;PU;PA%d,%d", xloc, yloc ); + SEND_PCL( outFile, t ); + + /* + * Check each point against the clip region. If it is outside the + * region, don't send the PCL to the printer. + */ + + for( i = 0; i < nPoints; i++ ) + { + if( miPointInRegion( pGC->clientClip, xloc, yloc, &box ) ) + { + sprintf( t, ",%d,%d", xloc, yloc ); + SEND_PCL( outFile, t ); + } + + if( mode == CoordModeOrigin ) + { + xloc = pPoints[i+1].x + xoffset; + yloc = pPoints[i+1].y + yoffset; + } + else + { + xloc += pPoints[i+1].x; + yloc += pPoints[i+1].y; + } + } + + /* + * Change the line style and width back to what they were before + * this routine was called. No, this isn't pretty... + */ + if( pDrawable->type == DRAWABLE_WINDOW ) + { + pCon = PclGetContextFromWindow( (WindowPtr)pDrawable ); + cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr; +/* + cPriv->changeMask = GCLineWidth | GCLineStyle; +*/ + } + else + { + pPriv = + ((PixmapPtr)pDrawable)->devPrivates[PclPixmapPrivateIndex].ptr; +/* + pPriv->changeMask = GCLineWidth | GCLineStyle; +*/ + } + + PclUpdateDrawableGC( pGC, pDrawable, &outFile ); + + /* + * Go back to PCL + */ + SEND_PCL( outFile, "\27%0A" ); +} + +void +PclPushPixels( pGC, pBitmap, pDrawable, width, height, x, y ) + GCPtr pGC; + PixmapPtr pBitmap; + DrawablePtr pDrawable; + int width; + int height; + int x; + int y; +{ +} diff --git a/Xprint/pcl/PclPixmap.c b/Xprint/pcl/PclPixmap.c new file mode 100644 index 000000000..fe8d169b1 --- /dev/null +++ b/Xprint/pcl/PclPixmap.c @@ -0,0 +1,80 @@ +/* $Xorg: PclPixmap.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclPixmap.c +** * +** * Contents: +** * Pixmap handling code for the PCL DDX driver +** * +** * Created: 2/19/96 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "Pcl.h" +/*#include "cfb.h"*/ +/* #include "mfb.h" */ +#include "pixmapstr.h" + +PixmapPtr +PclCreatePixmap(ScreenPtr pScreen, + int width, + int height, + int depth) +{ +extern PixmapPtr mfbCreatePixmap(), cfbCreatePixmap(), cfb32CreatePixmap(); + + if( depth == 1 ) + return mfbCreatePixmap( pScreen, width, height, depth ); + else if( depth <= 8 ) + return cfbCreatePixmap( pScreen, width, height, depth ); + else if( depth <= 32 ) + return cfb32CreatePixmap( pScreen, width, height, depth ); +} + + +Bool +PclDestroyPixmap(PixmapPtr pPixmap) +{ +extern Bool mfbDestroyPixmap(), cfbDestroyPixmap(), cfb32DestroyPixmap(); + if( pPixmap->drawable.depth == 1 ) + return mfbDestroyPixmap( pPixmap ); + else if( pPixmap->drawable.depth <= 8 ) + return cfbDestroyPixmap( pPixmap ); + else if( pPixmap->drawable.depth <= 32 ) + return cfb32DestroyPixmap( pPixmap ); +} diff --git a/Xprint/pcl/PclPolygon.c b/Xprint/pcl/PclPolygon.c new file mode 100644 index 000000000..badbdf18a --- /dev/null +++ b/Xprint/pcl/PclPolygon.c @@ -0,0 +1,354 @@ +/* $Xorg: PclPolygon.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclPolygon.c +** * +** * Contents: +** * Draws Polygons and Rectangles for the PCL DDX +** * +** * Created: 10/23/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + + +#include "Pcl.h" +#include "gcstruct.h" +#include "windowstr.h" + +void +PclPolyRectangle( pDrawable, pGC, nRects, pRects ) + DrawablePtr pDrawable; + GCPtr pGC; + int nRects; + xRectangle *pRects; +{ + char t[80]; + FILE *outFile; + int nbox, i; + BoxPtr pbox; + xRectangle *drawRects, *r; + RegionPtr drawRegion, region; + short fudge; + int xoffset, yoffset; + XpContextPtr pCon; + PclContextPrivPtr pConPriv; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + + /* + * Allocate the storage required to deal with the clipping + * regions. + */ + region = miRegionCreate( NULL, 0 ); + drawRects = (xRectangle *)xalloc( nRects * sizeof( xRectangle ) ); + + fudge = 3 * pGC->lineWidth + 1; + + /* + * Generate the PCL code to draw the rectangles, by defining them + * as a macro which uses the HP-GL/2 rectangle drawing function. + */ + MACRO_START( outFile, pConPriv ); + SAVE_PCL( outFile, pConPriv, "\033%0B" ); + + xoffset = pDrawable->x; + yoffset = pDrawable->y; + + for( i = 0, r = drawRects; i < nRects; i++, r++ ) + { + xRectangle rect = pRects[i]; + + /* Draw the rectangle */ + sprintf( t, "PU%d,%d;ER%d,%d;", rect.x + xoffset, + rect.y + yoffset, rect.width, rect.height ); + SAVE_PCL( outFile, pConPriv, t ); + + /* Build the bounding box */ + r->x = MIN( rect.x, rect.x + rect.width ) + xoffset - + fudge; + r->y = MIN( rect.y, rect.y + rect.height ) + yoffset - + fudge; + r->width = rect.width + 2 * fudge; + r->height = rect.height + 2 * fudge; + } + SAVE_PCL( outFile, pConPriv, ";\033%0A" ); /* End the macro */ + MACRO_END( outFile ); + + /* + * Convert the collection of rectangles to a proper region, then + * intersect it with the clip region. + */ + drawRegion = miRectsToRegion( nRects, drawRects, CT_UNSORTED ); + + miIntersect( region, drawRegion, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the set of rectangles to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, 1.0); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + xfree( drawRects ); +} + +void +PclFillPolygon( pDrawable, pGC, shape, mode, nPoints, pPoints ) + DrawablePtr pDrawable; + GCPtr pGC; + int shape; + int mode; + int nPoints; + DDXPointPtr pPoints; +{ + char t[80]; + FILE *outFile; + int nbox, i; + BoxPtr pbox; + BoxRec box; + xRectangle *drawRects, *r; + RegionPtr drawRegion, region; + int xoffset, yoffset; + int xtop, xbottom, yleft, yright; + int fillRule; + XpContextPtr pCon; + PclContextPrivPtr pConPriv; + char *command; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + + /* + * Generate the PCL code to draw the filled polygon, by defining + * it as a macro which uses the HP-GL/2 polygon drawing function. + */ + MACRO_START( outFile, pConPriv ); + SAVE_PCL( outFile, pConPriv, "\033%0B" ); + + if( mode == CoordModeOrigin ) + { + xoffset = pDrawable->x; + yoffset = pDrawable->y; + command = "PA"; + } + else + { + xoffset = yoffset = 0; + command = "PR"; + } + + /* Begin the polygon */ + sprintf( t, "PU%d,%d;PM0;%s", pPoints[0].x + xoffset, pPoints[0].y + + yoffset, command ); + SAVE_PCL( outFile, pConPriv, t ); + + /* Seed the bounding box */ + xtop = xbottom = pPoints[0].x + xoffset; + yleft = yright = pPoints[0].y + yoffset; + + /* Add the rest of the points to the polygon */ + for( i = 1; i < nPoints; i++ ) + { + if( i != 1 ) + SAVE_PCL( outFile, pConPriv, "," ); + + sprintf( t, "%d,%d", pPoints[i].x + xoffset, pPoints[i].y + + yoffset ); + SAVE_PCL( outFile, pConPriv, t ); + + /* Update the bounding box */ + xtop = MIN( xtop, pPoints[i].x + xoffset ); + xbottom = MAX( xbottom, pPoints[i].x + xoffset ); + yleft = MIN( yleft, pPoints[i].y + yoffset ); + yright = MAX( yright, pPoints[i].y + yoffset ); + } + + /* Close the polygon and the macro */ + + if( pGC->fillRule == EvenOddRule ) + fillRule = 0; + else + fillRule = 1; + + sprintf( t, ";PM2;FP%d;\033%%0A", fillRule ); + SAVE_PCL( outFile, pConPriv, t ); + MACRO_END ( outFile ); + + /* + * Build the bounding region from the bounding box of the polygon + */ + box.x1 = xtop; + box.y1 = yleft; + box.x2 = xbottom; + box.y2 = yright; + drawRegion = miRegionCreate( &box, 0 ); + + if( mode == CoordModePrevious ) + miTranslateRegion( drawRegion, pPoints[0].x, pPoints[0].y ); + + region = miRegionCreate( NULL, 0 ); + + miIntersect( region, drawRegion, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the polygon to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, 1.0); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); +} + +void +PclPolyFillRect( pDrawable, pGC, nRects, pRects ) + DrawablePtr pDrawable; + GCPtr pGC; + int nRects; + xRectangle *pRects; +{ + char t[80]; + FILE *outFile; + int nbox, i; + BoxPtr pbox; + xRectangle *drawRects, *r; + RegionPtr drawRegion, region; + int xoffset, yoffset; + short fudge; + XpContextPtr pCon; + PclContextPrivPtr pConPriv; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + + /* + * Allocate the storage required to deal with the clipping + * regions. + */ + region = miRegionCreate( NULL, 0 ); + drawRects = (xRectangle *)xalloc( nRects * sizeof( xRectangle ) ); + + + fudge = 3 * pGC->lineWidth + 1; + + /* + * Generate the PCL code to draw the filled rectangles, by + * defining them as a macro which uses the HP-GL/2 rectangle + * drawing function. + */ + MACRO_START( outFile, pConPriv ); + SAVE_PCL( outFile, pConPriv, "\033%0B" ); + + xoffset = pDrawable->x; + yoffset = pDrawable->y; + + for( i = 0, r = drawRects; i < nRects; i++, r++ ) + { + xRectangle rect = pRects[i]; + + /* Draw the rectangle */ + sprintf( t, "PU%d,%d;RR%d,%d;", rect.x + xoffset, rect.y + + yoffset, rect.width, rect.height ); + SAVE_PCL( outFile, pConPriv, t ); + + /* Build the bounding box */ + r->x = MIN( rect.x, rect.x + rect.width ) + xoffset - fudge; + r->y = MIN( rect.y, rect.y + rect.height ) + yoffset - + fudge; + r->width = rect.width + 2 * fudge; + r->height = rect.height + 2 * fudge; + } + SAVE_PCL( outFile, pConPriv, ";\033%0A" ); /* End the macro */ + MACRO_END( outFile ); + + /* + * Convert the collection of rectangles to a proper region, then + * intersect it with the clip region. + */ + drawRegion = miRectsToRegion( nRects, drawRects, CT_UNSORTED ); + miIntersect( region, drawRegion, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the set of rectangles to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, 1.0); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + xfree( drawRects ); +} + diff --git a/Xprint/pcl/PclPrint.c b/Xprint/pcl/PclPrint.c new file mode 100644 index 000000000..2bfd92d15 --- /dev/null +++ b/Xprint/pcl/PclPrint.c @@ -0,0 +1,718 @@ +/* $Xorg: PclPrint.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclPrint.c +** * +** * Contents: Print extension code of Pcl driver +** * +** * Created: 2/03/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define NEED_EVENTS +#include "Xproto.h" +#undef NEED_EVENTS + +#include "Pcl.h" + +#include "windowstr.h" +#include "attributes.h" +#include "AttrValid.h" +#include "Oid.h" + +extern PclSoftFontInfoPtr PclCreateSoftFontInfo(); +extern void PclDestroySoftFontInfo(PclSoftFontInfoPtr); + +int +PclStartJob( pCon, sendClientData, client ) + XpContextPtr pCon; + Bool sendClientData; + ClientPtr client; + +{ + PclContextPrivPtr pConPriv = + (PclContextPrivPtr)pCon->devPrivates[PclContextPrivateIndex].ptr; + char *jobHeader; + char s[40]; + PclPaletteMap *pal; + + /* + * Check for existing page file, and delete it if it exists. + */ + if(pConPriv->pageFileName != (char *)NULL) + { + if(pConPriv->pPageFile != (FILE *)NULL) + { + fclose(pConPriv->pPageFile); + pConPriv->pPageFile = (FILE *)NULL; + } + unlink(pConPriv->pageFileName); + xfree(pConPriv->pageFileName); + pConPriv->pageFileName = (char *)NULL; + } + + /* + * Create a temporary file to store the printer output. + */ + if (!XpOpenTmpFile("w+", &pConPriv->jobFileName, &pConPriv->pJobFile)) + return BadAlloc; + + /* + * Create/Initialize the SoftFontInfo structure + */ + pConPriv->pSoftFontInfo = PclCreateSoftFontInfo(); + + /* + * Set up the colormap handling + */ + pConPriv->palettes = NULL; + pConPriv->nextPaletteId = 4; + pConPriv->currentPalette = 0; + + pal = &( pConPriv->staticGrayPalette ); + pal->paletteId = 1; + pal->downloaded = 0; + + pal = &( pConPriv->trueColorPalette ); + pal->paletteId = 2; + pal->downloaded = 0; + + pal = &( pConPriv->specialTrueColorPalette ); + pal->paletteId = 3; + pal->downloaded = 0; + + return Success; +} + +int +PclEndJob( pCon, cancel ) + XpContextPtr pCon; + Bool cancel; +{ + PclContextPrivPtr priv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + +#ifdef CCP_DEBUG + FILE *xpoutput; +#endif + FILE *fp; + int retVal; + char *fileName, *trailer; + struct stat statBuf; + int n; + PclPaletteMapPtr p, t; + + trailer = "\033%-12345X@PJL RESET\n"; + + if( cancel == True ) + { + if( priv->getDocClient != (ClientPtr)NULL ) { + XpFinishDocData( priv->getDocClient ); + + priv->getDocClient == NULL; + priv->getDocBufSize = 0; + } + + return Success; + } + + if( priv->getDocClient != (ClientPtr)NULL && priv->getDocBufSize > 0 ) + { + /* + * We need to stash the trailer information somewhere... + */ + if (!XpOpenTmpFile("w+", &fileName, &fp)) + return BadAlloc; + +#ifndef XP_PCL_LJ3 + SEND_PCL( fp, trailer ); + rewind( fp ); + + retVal = XpSendDocumentData( priv->getDocClient, fp, + strlen( trailer ), + priv->getDocBufSize ); +#endif /* XP_PCL_LJ3 */ + + fclose( fp ); + unlink( fileName ); + xfree( fileName ); + + if( priv->getDocClient != (ClientPtr)NULL ) { + XpFinishDocData( priv->getDocClient ); + + priv->getDocClient == NULL; + priv->getDocBufSize = 0; + } + + return retVal; + } + +#ifndef XP_PCL_LJ3 + SEND_PCL( priv->pJobFile, trailer ); +#endif /* XP_PCL_LJ3 */ + + /* + * Submit the job to the spooler + */ + fflush( priv->pJobFile ); + + /* + * Dump the job file to another output file, for testing + * purposes. + */ + rewind( priv->pJobFile ); + n = stat( priv->jobFileName, &statBuf ); + +#ifdef CCP_DEBUG + unlink( "/users/prince/XpOutput" ); + xpoutput = fopen( "/users/prince/XpOutput", "w" ); + + rewind( priv->pJobFile ); + n = TransferBytes( priv->pJobFile, xpoutput, + (int)statBuf.st_size ); + fclose( xpoutput ); +#endif + + XpSubmitJob( priv->jobFileName, pCon ); + fclose( priv->pJobFile ); + unlink( priv->jobFileName ); + xfree( priv->jobFileName ); + priv->jobFileName = NULL; + + PclDestroySoftFontInfo(priv->pSoftFontInfo); + priv->pSoftFontInfo = (PclSoftFontInfoPtr) NULL; + + /* + * Clear out the colormap cache + */ + p = priv->palettes; + while( p ) + { + p->downloaded = 0; + p = p->next; + } + + return Success; +} + +/* StartPage + * + * If page file exists + * close page file + * set page file pointer = NULL + * unlink page file + * Create a new page file + * Send the page header information to the page file + * ClearArea the window and all descendant windows + */ +int +PclStartPage( pCon, pWin ) + XpContextPtr pCon; + WindowPtr pWin; +{ + register WindowPtr pChild; + PclContextPrivPtr pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + PclWindowPrivPtr pWinPriv = + (PclWindowPrivPtr)pWin->devPrivates[PclWindowPrivateIndex].ptr; + xRectangle repro; + char t[80]; + XpOid orient, plex, tray, medium; + unsigned short wid, ht; + int dir, plexNum, num; + xEvent event; + + /* + * Put a pointer to the context in the window private structure + */ + pWinPriv->validContext = 1; + pWinPriv->context = pCon; + + /* + * Clear out the old page file, if necessary + */ + if(pConPriv->pPageFile != (FILE *)NULL) + { + fclose(pConPriv->pPageFile); + pConPriv->pPageFile = (FILE *)NULL; + } + if(pConPriv->pageFileName != (char *)NULL) + { + unlink(pConPriv->pageFileName); + pConPriv->pageFileName = (char *)NULL; + } + + /* + * Make up a new page file. + */ + if (!XpOpenTmpFile("w+", &pConPriv->pageFileName, &pConPriv->pPageFile)) + return BadAlloc; + + /* + * Reset the GC cached in the context private struct. + */ + pConPriv->validGC = 0; + + /* + * Set the page orientation + */ + orient = XpGetContentOrientation( pCon ); + switch( orient ) + { + case xpoid_val_content_orientation_landscape: + dir = 1; + break; + case xpoid_val_content_orientation_reverse_portrait: + dir = 2; + break; + case xpoid_val_content_orientation_reverse_landscape: + dir = 3; + break; + case xpoid_val_content_orientation_portrait: + default: + dir = 0; + break; + } + sprintf( t, "\033&l%dO", dir ); + SEND_PCL( pConPriv->pPageFile, t ); + + /* + * Set the duplexing method. Since PCL wants to think of it in + * terms of the "binding edge," and the attribute store thinks in + * "duplex/tumble," this is a little complicated. + * + * Actually, this has no bearing on the output, since the HP1600C + * will only print on one side of the paper, and ignore all + * requests to enable duplexing. But, in an attempt to keep this + * driver somewhat generic, we'll enable it anyway. + */ + plex = XpGetPlex( pCon ); + + if( plex == xpoid_val_plex_duplex ) + { + if( dir == 0 || dir == 2 ) + plexNum = 1; + else + plexNum = 2; + } + else if( plex == xpoid_val_plex_tumble ) + { + if( dir == 0 || dir == 2 ) + plexNum = 2; + else + plexNum = 1; + } + else + plexNum = 0; + sprintf( t, "\033&l%dS", plexNum ); + SEND_PCL( pConPriv->pPageFile, t ); + + /* + * Set the input tray or medium. If XpGetPageSize gives us a valid medium, + * we can just send that to the printer, and let the printer handle the + * details. Otherwise, we select the tray returned from XpGetPageSize, + * which will be either a tray that should contain the correct medium + * (possibly with operator intervention), or the default tray from the + * config files. + */ + medium = XpGetPageSize( pCon, &tray, NULL ); + if( medium != xpoid_none ) + { + switch( medium ) + { + case xpoid_val_medium_size_na_legal: + num = 3; + break; + case xpoid_val_medium_size_iso_a3: + num = 27; + break; + case xpoid_val_medium_size_iso_a4: + num = 26; + break; + case xpoid_val_medium_size_executive: + num = 1; + break; + case xpoid_val_medium_size_ledger: + num = 6; + break; + case xpoid_val_medium_size_monarch_envelope: + num = 80; + break; + case xpoid_val_medium_size_na_number_10_envelope: + num = 81; + break; + case xpoid_val_medium_size_iso_designated_long: + num = 90; + break; + case xpoid_val_medium_size_iso_c5: + num = 91; + break; + case xpoid_val_medium_size_iso_b5: + num = 100; + break; + case xpoid_val_medium_size_jis_b5: + num = 45; + break; + case xpoid_val_medium_size_na_letter: + default: + num = 2; + break; + } + sprintf( t, "\033&l%dA", num ); + SEND_PCL( pConPriv->pPageFile, t ); + } + else + { + switch( tray ) + { + case xpoid_val_input_tray_manual: + num = 2; + break; + case xpoid_val_input_tray_envelope: + num = 3; + break; + case xpoid_val_input_tray_large_capacity: + num = 5; + break; + case xpoid_val_input_tray_bottom: + num = 4; + break; + case xpoid_val_input_tray_main: + default: + num = 1; + break; + } + sprintf( t, "\033&l%dH", num ); + SEND_PCL( pConPriv->pPageFile, t ); + } + + /* + * Set the scaling factors so that the HP-GL/2 coordinate system + * matches the X coordinate system, both in axis orientation and + * in unit<->pixel conversion. + */ + XpGetReproductionArea( pCon, &repro ); + + sprintf( t, "\033&l0E\033*p%dx%dY", repro.x - 75, repro.y ); + SEND_PCL( pConPriv->pPageFile, t ); + + sprintf( t, "\033*c%dx%dY\033*c0T", (int)(repro.width / 300.0 * 720.0), + (int)(repro.height / 300.0 * 720.0) ); + SEND_PCL( pConPriv->pPageFile, t ); + + sprintf( t, "\033%%0BSC%d,%d,%d,%d;\033%%0A", repro.x, repro.x + + repro.width, repro.y + repro.height, repro.y ); + SEND_PCL( pConPriv->pPageFile, t ); + + return Success; +} + +/* + * When sending the generated PCL code back to the client, we send everything + * that we have generated so far for the job. After sending the data, we clean + * out the job file, to avoid repeatedly sending the same data. + */ + +static int +SendDocData( PclContextPrivPtr pPriv ) +{ + struct stat statBuf; + int ret; + + rewind( pPriv->pJobFile ); + if( stat( pPriv->jobFileName, &statBuf ) < 0 ) + return BadAlloc; + + ret = XpSendDocumentData( pPriv->getDocClient, pPriv->pJobFile, + (int)statBuf.st_size, pPriv->getDocBufSize ); + + /* + * Clean out the job file + */ + fclose( pPriv->pJobFile ); + unlink( pPriv->jobFileName ); + + xfree(pPriv->jobFileName); + + if (!XpOpenTmpFile("w+", &pPriv->jobFileName, &pPriv->pJobFile)) + return BadAlloc; + + return ret; +} + +/* + * EndPage: + * + * Write page trailer to page file + * Write page file to job file + */ +int +PclEndPage( pCon, pWin ) + XpContextPtr pCon; + WindowPtr pWin; +{ + PclContextPrivPtr pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + PclWindowPrivPtr pWinPriv = + (PclWindowPrivPtr)pWin->devPrivates[PclWindowPrivateIndex].ptr; + + struct stat statBuf; + + /* + * Send the page trailer to the page file. + */ + SEND_PCL( pConPriv->pPageFile, "\014" ); + fflush( pConPriv->pPageFile ); + + /* + * Write the page file contents to the job file, or to the + * whatever client has called GetDocumentData. + * + * pWinPriv->pPageFile must first be set to the start of the page file. + */ + rewind(pConPriv->pPageFile); + if(stat(pConPriv->pageFileName, &statBuf) < 0) + return BadAlloc; + + if(TransferBytes(pConPriv->pPageFile, pConPriv->pJobFile, + (int)statBuf.st_size) != (int)statBuf.st_size) + return BadAlloc; + + if( pConPriv->getDocClient != (ClientPtr)NULL && + pConPriv->getDocBufSize > 0 ) + { + return SendDocData( pConPriv ); + } + + return Success; +} + +/* + * The PclStartDoc() and PclEndDoc() functions serve basically as NOOP + * placeholders. This driver doesn't deal with the notion of multiple + * documents per page. + */ + +int +PclStartDoc(XpContextPtr pCon, + XPDocumentType type) +{ + PclContextPrivPtr pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + +#ifndef XP_PCL_LJ3 + /* + * Set the printer resolution for the page. Since we can only + * render color at 300dpi, we just hard-code this. + */ + SEND_PCL( pConPriv->pJobFile, + "\033%-12345X@PJL SET RESOLUTION = 300\r\n" ); +#endif /* XP_PCL_LJ3 */ + + /* + * Initialize HP-GL/2 + */ + SEND_PCL( pConPriv->pJobFile, "\033E\033%0BIN,SP1,TR0;\033%0A" ); + + /* + * Stash the type of the document (used by PutDocumentData operation) + */ + pConPriv->isRaw = (type == XPDocRaw); + + return Success; +} + +int +PclEndDoc( pCon, cancel ) + XpContextPtr pCon; + Bool cancel; +{ + /* + * XXX What should I do if I get cancel == TRUE? + */ + return Success; +} + +/* + * PclDocumentData() + * + * Hand any pre-generated PDL down to the spool files, formatting it + * as necessary to fit the given window. + * + */ + +#define DOC_PCL 1 +#define DOC_HPGL 2 + +int +PclDocumentData( pCon, pDraw, pData, len_data, pFmt, len_fmt, pOpt, len_opt, client) + XpContextPtr pCon; + DrawablePtr pDraw; + char *pData; + int len_data; + char *pFmt; + int len_fmt; + char *pOpt; + int len_opt; + ClientPtr client; +{ + int type; + PclContextPrivPtr pPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + XpOidDocFmtList *formats; + XpOidDocFmt *f; + char t[80]; + xRectangle repro; + + /* + * Verify the input format + */ + formats = XpGetDocFmtListAttr( pCon, XPPrinterAttr, + (pPriv->isRaw) ? + xpoid_att_xp_raw_formats_supported : + xpoid_att_xp_embedded_formats_supported, + NULL ); + f = XpOidDocFmtNew( pFmt ); + if( !XpOidDocFmtListHasFmt( formats, f ) ) + { + XpOidDocFmtListDelete( formats ); + XpOidDocFmtDelete( f ); + return BadMatch; + } + XpOidDocFmtListDelete( formats ); + + if( !(pPriv->isRaw) ) + { + if( !strcmp( f->format, "PCL" ) ) + type = DOC_PCL; + else if( !strcmp( f->format, "HPGL" ) ) + type = DOC_HPGL; + else + { + XpOidDocFmtDelete( f ); + return BadMatch; + } + + switch( type ) + { + case DOC_HPGL: + /* + * Move the picture frame to the appropriate place on the page, + * then assume that the embedded code will scale it properly. + */ + sprintf( t, "\033&l0E\033*p%dx%dY", + pDraw->x - 75, + pDraw->y ); + SEND_PCL( pPriv->pPageFile, t ); + + sprintf( t, "\033*c%dx%dY\033*coT", + (int)( pDraw->width / 300.0 * 720.0 ), + (int)( pDraw->height / 300.0 * 720.0 ) ); + SEND_PCL( pPriv->pPageFile, t ); + break; + } + } + + + /* + * Send the data down the pipe + */ + SEND_PCL_COUNT( pPriv->pPageFile, pData, len_data ); + + /* + * If it's not a raw document, clean up the embedding + */ + if( !(pPriv->isRaw) ) + switch( type ) + { + case DOC_HPGL: + /* + * Reset the picture frame + */ + XpGetReproductionArea( pCon, &repro ); + + sprintf( t, "\033&l0E\033*p%dx%dY", repro.x - 75, repro.y ); + SEND_PCL( pPriv->pPageFile, t ); + + sprintf( t, "\033*c%dx%dY\033*c0T", + (int)(repro.width / 300.0 * 720.0), + (int)(repro.height / 300.0 * 720.0) ); + SEND_PCL( pPriv->pPageFile, t ); + + sprintf( t, "\033%%0BSC%d,%d,%d,%d;\033%%0A", repro.x, repro.x + + repro.width, repro.y + repro.height, repro.y ); + SEND_PCL( pPriv->pPageFile, t ); + break; + } + + XpOidDocFmtDelete( f ); + return Success; +} + +/* + * + * PclGetDocumentData() + * + * This function allows the driver to send the generated PCL back to + * the client. + * + * XXX This function is barely spec'ed, much less implemented! + */ + +int +PclGetDocumentData( pCon, client, maxBufferSize ) + XpContextPtr pCon; + ClientPtr client; + int maxBufferSize; +{ + PclContextPrivPtr pPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + + pPriv->getDocClient = client; + pPriv->getDocBufSize = maxBufferSize; + + return Success; +} diff --git a/Xprint/pcl/PclSFonts.c b/Xprint/pcl/PclSFonts.c new file mode 100644 index 000000000..9f19a2387 --- /dev/null +++ b/Xprint/pcl/PclSFonts.c @@ -0,0 +1,431 @@ +/* $Xorg: PclSFonts.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclSFonts.c +** * +** * Contents: +** * Send Soft Font Download data to the specified +** * file pointer. +** * +** * Created: 3/4/96 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + + +#include +#include "Pcl.h" + +static char tmp1; +static short tmp2; +#define Put1byte(fp, x) tmp1=x; fwrite((char *)&tmp1, 1, 1, fp) +#define Put2bytes(fp, x) tmp2=x; fwrite((char *)&tmp2, 2, 1, fp) + +#define ESC 0x1b +#define SYMBOL_SET 277 +#define MAX_CINDEX 255 + +static unsigned int PclDownloadChar(FILE *,PclCharDataPtr,unsigned short,unsigned char); +static unsigned int PclDownloadHeader(FILE *, PclFontDescPtr, unsigned short); + +#ifdef PCL_FONT_COMPRESS +static unsigned char *compress_bitmap_data(PclCharDataPtr, unsigned int *); +#endif /* PCL_FONT_COMPRESS */ + +/* -*- PclDownloadSoftFont8 -*- + * Send the Character Definition Command for 8-bit font + * **************************************************************************/ +void +PclDownloadSoftFont8( + FILE *fp, + PclSoftFontInfoPtr pSoftFontInfo, + PclFontHead8Ptr pfh, + PclCharDataPtr pcd, + unsigned char *code, + int flag +) +{ + /* + * Check whether the font header has already been downloaded. + * If not, download it. + */ + + if ( !pfh->fid ) { + pfh->fid = pSoftFontInfo->cur_max_fid++; + PclDownloadHeader(fp, &(pfh->fd), pfh->fid); + } + pfh->index[*code] = *code; + PclDownloadChar(fp, pcd, pfh->fid, pfh->index[*code]); + +} + +/* -*- PclDownloadSoftFont16 -*- + * Send the Character Definition Command for 16 bit font + * **************************************************************************/ +void +PclDownloadSoftFont16( + FILE *fp, + PclSoftFontInfoPtr pSoftFontInfo, + PclFontHead16Ptr pfh, + PclCharDataPtr pcd, + unsigned char row, + unsigned char col, + int flag +) +{ + /* + * Check whether the font header is already downloaded. + * If not, download it. + */ + + if ( !pfh->cur_cindex ) { + pfh->cur_fid = pSoftFontInfo->cur_max_fid++; + PclDownloadHeader(fp, &(pfh->fd), pfh->cur_fid); + } + pfh->index[row][col].fid = pfh->cur_fid; + pfh->index[row][col].cindex = pfh->cur_cindex++; + if ( pfh->cur_cindex > MAX_CINDEX ) + pfh->cur_cindex = 0; + + PclDownloadChar(fp, pcd, pfh->index[row][col].fid, pfh->index[row][col].cindex); +} + +/* -*- PclCreateSoftFontInfo -*- + * Create and Initialize the structure for storing the information + * of the downloaded soft font. + * **************************************************************************/ +PclSoftFontInfoPtr +PclCreateSoftFontInfo( +) +{ +PclSoftFontInfoPtr pSoftFontInfo; + + pSoftFontInfo = (PclSoftFontInfoPtr)xalloc(sizeof(PclSoftFontInfoRec)); + if ( pSoftFontInfo == (PclSoftFontInfoPtr) NULL) + return (PclSoftFontInfoPtr) NULL; + pSoftFontInfo->phead8 = (PclFontHead8Ptr)NULL; + pSoftFontInfo->phead16 = (PclFontHead16Ptr)NULL; + pSoftFontInfo->pinfont = (PclInternalFontPtr)NULL; + pSoftFontInfo->cur_max_fid = 1; + return pSoftFontInfo; +} + +/* -*- PclDestroySoftFontInfo -*- + * Destroy the soft font information structure + * **************************************************************************/ +void +PclDestroySoftFontInfo( PclSoftFontInfoPtr pSoftFontInfo ) +{ +PclFontHead8Ptr pfh8, pfh8_next; +PclFontHead16Ptr pfh16, pfh16_next; +PclInternalFontPtr pin, pin_next; +unsigned char nindex_row, nindex_col; +int i, j; + + if ( pSoftFontInfo == (PclSoftFontInfoPtr) NULL ) + return; + + pfh8 = pSoftFontInfo->phead8; + while (pfh8 != (PclFontHead8Ptr) NULL) { + xfree(pfh8->fontname); + xfree(pfh8->index); + pfh8_next = pfh8->next; + xfree(pfh8); + pfh8 = pfh8_next; + } + + pfh16 = pSoftFontInfo->phead16; + while (pfh16 != (PclFontHead16Ptr) NULL) { + xfree(pfh16->fontname); + nindex_col = pfh16->lastCol - pfh16->firstCol + 1; + nindex_row = pfh16->lastRow - pfh16->firstRow + 1; + for (i=0; iindex[i]); + xfree(pfh16->index); + pfh16_next = pfh16->next; + xfree(pfh16); + pfh16 = pfh16_next; + } + + pin = pSoftFontInfo->pinfont; + while (pin != (PclInternalFontPtr) NULL) { + xfree(pin->fontname); + pin_next = pin->next; + xfree(pin); + pin = pin_next; + } + + xfree(pSoftFontInfo); +} + +/* -*- PclDownloadHeader -*- + * Send the Font Header Commnad. + * Format 0 : Font Header for Pcl Bitmapped Fonts + * Format 20 : Font Header for Resolution Specified Bitmapped Fonts + * **************************************************************************/ +static unsigned int +PclDownloadHeader( + FILE *fp, + PclFontDescPtr fd, + unsigned short fid +) +{ +int nbytes; + +#ifdef XP_PCL_LJ3 + nbytes = 64; +#else + nbytes = 68; +#endif /* XP_PCL_LJ3 */ + /* + * Font ID Command : Esc *c#D + * (Default = 0, Range = 0 - 32767) + */ + fprintf(fp, "%c*c%dD", ESC, fid); + + /* + * Font Header Commnad : Esc )s#W[font header data] + * (Default = 0, Range = 0 - 32767) + */ + fprintf(fp, "%c)s%dW", ESC, nbytes); + + Put2bytes(fp, nbytes); /* Font Description Size */ +#ifdef XP_PCL_LJ3 + Put1byte(fp, 0); /* Header Format */ +#else + Put1byte(fp, 20); /* Header Format */ +#endif /* XP_PCL_LJ3 */ + Put1byte(fp, 2); /* Font Type */ + Put2bytes(fp, 0); /* Style MSB */ + Put2bytes(fp, fd->ascent); /* BaseLine Position */ + Put2bytes(fp, fd->cellwidth); /* Cell Width */ + Put2bytes(fp, fd->cellheight); /* Cell Height */ + Put1byte(fp, 0); /* Orienation */ + Put1byte(fp, fd->spacing); /* Spacing */ + Put2bytes(fp, SYMBOL_SET); /* Symbol Set */ + Put2bytes(fp, fd->pitch*4); /* font pitch */ + Put2bytes(fp, fd->cellheight * 4); /* Height */ + Put2bytes(fp, 0); /* x-Height */ + Put1byte(fp, 0); /* width type (normal) */ + Put1byte(fp, 0); /* Style LSB */ + Put1byte(fp, 0); /* Stroke Weight */ + Put1byte(fp, 5); /* Typeface LSB */ + Put1byte(fp, 0); /* Typeface MSB */ + Put1byte(fp, 0); /* Serif Style */ + Put1byte(fp, 0); /* Quality */ + Put1byte(fp, 0); /* Placement */ + Put1byte(fp, 0); /* Underline Position */ + Put1byte(fp, 0); /* Underline Thickness */ + Put2bytes(fp, fd->cellheight*1.2); /* Text Height */ + Put2bytes(fp, fd->cellwidth * 4); /* Text Width */ + Put2bytes(fp, 0); /* First Code */ + Put2bytes(fp, 255); /* Last Code */ + Put1byte(fp, 0); /* Pitch Extend */ + Put1byte(fp, 0); /* Height Extend */ + Put2bytes(fp, 0); /* Cap Height */ + Put2bytes(fp, 0); /* Font Number 1 */ + Put2bytes(fp, 0); /* Font Number 2 */ + Put2bytes(fp, 0); /* Font Name */ + Put2bytes(fp, 0); /* Font Name */ + Put2bytes(fp, 0); /* Font Name */ + Put2bytes(fp, 0); /* Font Name */ + Put2bytes(fp, 0); /* Font Name */ + Put2bytes(fp, 0); /* Font Name */ + Put2bytes(fp, 0); /* Font Name */ + Put2bytes(fp, 0); /* Font Name */ + +#ifdef XP_PCL_LJ3 + return 64; +#else + Put2bytes(fp, 300); /* X Resolution */ + Put2bytes(fp, 300); /* Y Resolution */ + return 68; +#endif /* XP_PCL_LJ3 */ + +} + +/* -*- PclDownloadCharacter -*- + * Send the Character Definition Command. + * **************************************************************************/ +static unsigned int +PclDownloadChar( + FILE *fp, + PclCharDataPtr cd, + unsigned short fid, + unsigned char code +) +{ +unsigned int nbytes, n; +unsigned char *raster; + + /* + * Font ID Command : Esc *c#D + * (Default = 0, Range = 0 - 32767) + * Character Code Command : Esc *c#E + * (Default = 0, Range = 0 - 65535) + */ + fprintf(fp, "%c*c%dd%dE", ESC, fid, code); + + /* + * Character Definition Command : Esc (s#W[character descriptor and data] + * (Default = N/A, Range = 0 - 32767) + */ + + nbytes = n = cd->height * ((cd->width + 7) / 8); +#ifdef PCL_FONT_COMPRESS + raster = compress_bitmap_data(cd, &nbytes); +#else + raster = (unsigned char *)NULL; +#endif /* PCL_FONT_COMPRESS */ + fprintf(fp, "%c(s%dW", ESC, nbytes + 16); + + Put1byte(fp, 4); /* Format */ + Put1byte(fp, 0); /* Continuation */ + Put1byte(fp, 14); /* Descriptor Size */ + if (raster) { /* Class */ + Put1byte(fp, 2); + } else { + Put1byte(fp, 1); /* Class */ + } + Put2bytes(fp, 0); /* Orientation */ + Put2bytes(fp, cd->h_offset); /* left offset */ + Put2bytes(fp, cd->v_offset); /* top offset */ + Put2bytes(fp, cd->width); /* character width */ + Put2bytes(fp, cd->height); /* character height */ + Put2bytes(fp, cd->font_pitch*4); /* delta X */ + + /* + * Raster Character Data + */ + if (raster) { + fwrite(raster, nbytes, 1, fp); + xfree(raster); + } else + fwrite(cd->raster_top, nbytes, 1, fp); + + return n + 16; +} + + +#ifdef PCL_FONT_COMPRESS +/* -*- compress_bitmap_data -*- + * Compress Bitmap data + * **************************************************************************/ +static unsigned char * +compress_bitmap_data( + PclCharDataPtr cd, + unsigned int *nbytes +) +{ +unsigned int byte_width; +unsigned char *raster, *rptr_s, *rptr_e, *rptr_end; +unsigned char *tmp_s, *tmp_ptr; +unsigned char *p; +unsigned char cur, pixel; +unsigned int num; + +int i, j, k, w; + + byte_width = (cd->width + 7) / 8; + *nbytes = cd->height * byte_width; + + /* Create buffer for storing compress bitmap glyph */ + raster = (unsigned char *)xalloc(*nbytes); + rptr_s = raster; + rptr_e = raster; + rptr_end = raster + *nbytes; + + tmp_s = (unsigned char *)xalloc(cd->width * 8 + 2); + + p = cd->raster_top; + for (i=0; iheight; i++) { + tmp_ptr = tmp_s; + *tmp_ptr++ = 0; + if ( (*p>>7)&0x1 == 1 ) { + *tmp_ptr++ = 0; + cur = 1; + } else { + cur = 0; + } + num = 0; + for (j=0, w=0; jwidth; k++, w++) { + pixel = (*p>>(7-k))&0x1; + if ( pixel == cur ) { + num++; + } else { + cur = pixel; + while (num > 255) { + *tmp_ptr++ = 255; + *tmp_ptr++ = 0; + num -= 255; + } + *tmp_ptr++ = num; + num = 1; + } + } + } + if ( pixel == cur ) { + while (num > 255) { + *tmp_ptr++ = 255; + *tmp_ptr++ = 0; + num -= 255; + } + *tmp_ptr++ = num&0xff; + } else + *tmp_ptr++ = num; + + if ( ((rptr_e - rptr_s) == (tmp_ptr - tmp_s)) && + !memcmp(rptr_s+1, tmp_s+1, (tmp_ptr - tmp_s) - 1) ) + *rptr_s += 1; + else { + if ( rptr_e + (tmp_ptr - tmp_s) > rptr_end ) { + xfree(raster); + xfree(tmp_s); + return (unsigned char *)NULL; + } + memcpy (rptr_e, tmp_s, tmp_ptr - tmp_s); + rptr_s = rptr_e; + rptr_e = rptr_s + (tmp_ptr - tmp_s); + } + } + xfree(tmp_s); + *nbytes = rptr_e - raster; + + return raster; +} +#endif /* PCL_FONT_COMPRESS */ diff --git a/Xprint/pcl/PclSFonts.h b/Xprint/pcl/PclSFonts.h new file mode 100644 index 000000000..5992c12af --- /dev/null +++ b/Xprint/pcl/PclSFonts.h @@ -0,0 +1,112 @@ +/* $Xorg: PclSFonts.h,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +#ifndef _PCLFONTS_H +#define _PCLFONTS_H + +/* -*-H-*- +****************************************************************************** +****************************************************************************** +* +* File: PclFonts.h +* Description: Send Soft Font Download data to the specified file pointer. +* +* +****************************************************************************** +****************************************************************************** +*/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + + +typedef struct { + unsigned char fid; /* sfont font ID */ + unsigned char cindex; /* character indext */ +} PclFontMapRec, PclFontMapPtr; + +typedef struct { + int h_offset; + int v_offset; + unsigned int width; + unsigned int height; + int font_pitch; + unsigned char *raster_top; +} PclCharDataRec, *PclCharDataPtr; + +typedef struct { + unsigned char spacing; + unsigned int pitch; + unsigned int cellheight; + unsigned int cellwidth; + int ascent; + int descent; +} PclFontDescRec, *PclFontDescPtr; + +typedef struct _PclFontHead8Rec { + char *fontname; + PclFontDescRec fd; + unsigned short fid; + unsigned char *index; + struct _PclFontHead8Rec *next; +} PclFontHead8Rec, *PclFontHead8Ptr; + +typedef struct _PclFontHead16Rec { + char *fontname; + PclFontDescRec fd; + unsigned short cur_fid; + unsigned char cur_cindex; + PclFontMapRec **index; + unsigned short firstCol; + unsigned short lastCol; + unsigned short firstRow; + unsigned short lastRow; + struct _PclFontHead16Rec *next; +} PclFontHead16Rec, *PclFontHead16Ptr; + +typedef struct _PclInternalFontRec { + char *fontname; + float pitch; + float height; + char *pcl_font_name; + char *spacing; + struct _PclInternalFontRec *next; +} PclInternalFontRec, *PclInternalFontPtr; + +typedef struct { + PclFontHead8Ptr phead8; + PclFontHead16Ptr phead16; + PclInternalFontPtr pinfont; + unsigned char cur_max_fid; +} PclSoftFontInfoRec, *PclSoftFontInfoPtr; + +#define MONOSPACE 0 +#define PROPSPACE 1 + +#endif /* _PCLFONTS_H */ diff --git a/Xprint/pcl/PclSpans.c b/Xprint/pcl/PclSpans.c new file mode 100644 index 000000000..38d1b7b01 --- /dev/null +++ b/Xprint/pcl/PclSpans.c @@ -0,0 +1,136 @@ +/* $Xorg: PclSpans.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclSpans.c +** * +** * Contents: +** * Code to set and fill spans in the PCL DDX +** * +** * Created: 10/23/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + + +#include "Pcl.h" +#include "gcstruct.h" +#include "windowstr.h" + +void +PclFillSpans( pDrawable, pGC, nSpans, pPoints, pWidths, fSorted ) + DrawablePtr pDrawable; + GCPtr pGC; + int nSpans; + DDXPointPtr pPoints; + int *pWidths; + int fSorted; +{ + char t[80]; + FILE *outFile; + int xoffset, yoffset; + xRectangle *rects, *r; + RegionPtr fillRegion, region; + int i; + int nbox; + BoxPtr pbox; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return; + + /* + * Build a region out of the spans + */ + rects = (xRectangle *)xalloc( nSpans * sizeof( xRectangle ) ); + xoffset = pDrawable->x; + yoffset = pDrawable->y; + + for( i = 0, r = rects; i < nSpans; i++, r++ ) + { + r->x = pPoints[i].x + xoffset; + r->y = pPoints[i].y + yoffset; + r->width = pWidths[i]; + r->height = 1; + } + fillRegion = miRectsToRegion( nSpans, rects, ( fSorted ) ? + CT_YSORTED : CT_UNSORTED ); + + /* + * Intersect this region with the clip region. Whatever's left, + * should be filled. + */ + miIntersect( region, fillRegion, pGC->clientClip ); + + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + /* Enter HP-GL/2 */ + SEND_PCL( outFile, "\27%0B" ); + + while( nbox ) + { + sprintf( t, "PU%d,%d;RR%d,%d;", pbox->x1, pbox->y1, + pbox->x2, pbox->y2 ); + SEND_PCL( outFile, t ); + + nbox--; + pbox++; + } + + /* Go back to PCL */ + SEND_PCL( outFile, "\27%0A" ); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( fillRegion ); + miRegionDestroy( region ); + xfree( rects ); +} + +void +PclSetSpans( pDrawable, pGC, pSrc, pPoints, pWidths, nSpans, fSorted ) + DrawablePtr pDrawable; + GCPtr pGC; + char *pSrc; + DDXPointPtr pPoints; + int *pWidths; + int nSpans; + int fSorted; +{ +} + + diff --git a/Xprint/pcl/PclText.c b/Xprint/pcl/PclText.c new file mode 100644 index 000000000..d01baabfa --- /dev/null +++ b/Xprint/pcl/PclText.c @@ -0,0 +1,937 @@ +/* $Xorg: PclText.c,v 1.5 2001/03/06 16:28:48 pookie Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclText.c +** * +** * Contents: +** * Character-drawing routines for the PCL DDX +** * +** * Created: 10/23/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#ifdef DO_TWO_BYTE_PCL +#include "iconv.h" +#endif /* DO_TWO_BYTE_PCL */ +#include "gcstruct.h" +#include "windowstr.h" + +#include "Pcl.h" +#include "migc.h" +#include "Xatom.h" + +#include "PclSFonts.h" + +static PclFontHead8Ptr makeFontHeader8 (FontPtr, PclSoftFontInfoPtr); +static PclFontHead16Ptr makeFontHeader16(FontPtr, PclSoftFontInfoPtr); +static PclInternalFontPtr makeInternalFont(FontPtr, PclSoftFontInfoPtr); +static void fillFontDescData(FontPtr, PclFontDescPtr, unsigned int); +static PclCharDataPtr fillCharDescData(PclCharDataPtr, CharInfoPtr); +static void output_text(FILE *, PclContextPrivPtr, unsigned char); +static char * getFontName(FontPtr); +static char isInternal(FontPtr); +static void selectInternalFont(FILE *, PclInternalFontPtr, int); +static void selectSize(FILE *, PclContextPrivPtr, PclInternalFontPtr); +static char t[80]; + +#ifdef DO_TWO_BYTE_PCL +static void code_conv(PclSoftFontInfoPtr, FontPtr, char *, char *); +#endif /* DO_TWO_BYTE_PCL */ + +#define ESC 0x1b +#define PER 0x25 +#define ETX 0x3 +#define ETX_ALT 0x2a +#define DOWNLOAD_FONT 0 +#define INTERNAL_FONT 1 + +int +PclPolyText8( pDrawable, pGC, x, y, count, string ) + DrawablePtr pDrawable; + GCPtr pGC; + int x; + int y; + int count; + char *string; +{ +XpContextPtr pCon; +PclContextPrivPtr pConPriv; +unsigned long n, i; +int w; +CharInfoPtr charinfo[255], *chinfo; + +FILE *outFile; +PclSoftFontInfoPtr pSoftFontInfo; +PclFontHead8Ptr pfh8 = (PclFontHead8Ptr)NULL; +PclInternalFontPtr pin = (PclInternalFontPtr)NULL; +PclCharDataRec cd; +unsigned char *p; +unsigned char last_fid; +int max_ascent, max_descent; + +int nbox; +BoxPtr pbox; +BoxRec box; +RegionPtr drawRegion, region; +char font_type; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return x; + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)string, + Linear8Bit, &n, charinfo); + if ( n == 0 ) + return x; + + pCon = PclGetContextFromWindow( (WindowPtr)pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + pSoftFontInfo = pConPriv->pSoftFontInfo; + font_type = isInternal(pGC->font); + if ( font_type == DOWNLOAD_FONT ) { + /* + * Create Soft Font Header Information + */ + pfh8 = makeFontHeader8(pGC->font, pSoftFontInfo); + if (!pfh8) + return x; + + /* + * exec Soft Font Downloading + */ + p = (unsigned char *)string; + for (i=0, chinfo=charinfo; iindex[*p] ) { + fillCharDescData(&cd, *chinfo); + PclDownloadSoftFont8(pConPriv->pJobFile, pSoftFontInfo, + pfh8, &cd, p); + xfree(cd.raster_top); + } + } + + /* + * print characters + */ + MACRO_START( outFile, pConPriv ); + sprintf(t, "\033%%0B;PU%d,%dPD;TD1;DT%c,1;", + x + pDrawable->x, y + pDrawable->y + pGC->font->info.fontAscent, + ETX); + SAVE_PCL( outFile, pConPriv, t ); + SAVE_PCL_COUNT( outFile, pConPriv, "FI0;SS;LB", 9 ); + + last_fid = 0; + w = 0; + max_ascent = charinfo[0]->metrics.ascent; + max_descent = charinfo[0]->metrics.descent; + p = (unsigned char *)string; + for (i=0, chinfo=charinfo; ifid ) { + sprintf(t, "%c;FI%d;SS;LB", ETX, pfh8->fid); + SAVE_PCL( outFile, pConPriv, t ); + + last_fid = pfh8->fid; + } + + output_text(outFile, pConPriv, pfh8->index[*p]); + + w += (*chinfo)->metrics.characterWidth; + max_ascent = MAX(max_ascent, (*chinfo)->metrics.ascent); + max_descent = MAX(max_descent, (*chinfo)->metrics.descent); + } + + sprintf(t, "%c", ETX); + SAVE_PCL_COUNT( outFile, pConPriv, t, 1 ); + sprintf(t, "TD0;\033%%1A"); + SAVE_PCL( outFile, pConPriv, t ); + MACRO_END( outFile ); + + } else { + char *internalFont; + int pixel_size; + int fid = 0; + + pin = makeInternalFont(pGC->font, pSoftFontInfo); + if (!pin) + return x; + + selectInternalFont(outFile, pin, fid); + + /* + * print characters + */ + MACRO_START( outFile, pConPriv ); + sprintf(t, "\033%%0B;PU%d,%dPD;TD1;DT%c,1;", + x + pDrawable->x, y + pDrawable->y + pGC->font->info.fontAscent, + ETX); + SAVE_PCL( outFile, pConPriv, t ); + selectSize(outFile, pConPriv, pin); + SAVE_PCL_COUNT( outFile, pConPriv, "FI0;SS;LB", 9 ); + + w = 0; + max_ascent = charinfo[0]->metrics.ascent; + max_descent = charinfo[0]->metrics.descent; + p = (unsigned char *)string; + for (i=0, chinfo=charinfo; imetrics.characterWidth; + max_ascent = MAX(max_ascent, (*chinfo)->metrics.ascent); + max_descent = MAX(max_descent, (*chinfo)->metrics.descent); + } + sprintf(t, "%c", ETX); + SAVE_PCL_COUNT( outFile, pConPriv, t, 1 ); + sprintf(t, "TD0;\033%%1A"); + SAVE_PCL( outFile, pConPriv, t ); + MACRO_END( outFile ); + } + + /* + * Convert the collection of rectangles into a proper region, then + * intersect it with the clip region. + */ + box.x1 = x + pDrawable->x; + box.y1 = y - max_ascent + pDrawable->y + pGC->font->info.fontAscent; + box.x2 = x + w + pDrawable->x; + box.y2 = y + max_descent + pDrawable->y + pGC->font->info.fontAscent; + + drawRegion = miRegionCreate( &box, 0 ); + region = miRegionCreate( NULL, 0 ); + miIntersect( region, drawRegion, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the entire polyline to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, 1.0); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + + return x+w; +} + +int +PclPolyText16( pDrawable, pGC, x, y, count, string ) + DrawablePtr pDrawable; + GCPtr pGC; + int x; + int y; + int count; + unsigned short *string; +{ +XpContextPtr pCon; +PclContextPrivPtr pConPriv; +unsigned long n, i; +int w; +CharInfoPtr charinfo[255], *chinfo; + +FILE *outFile; +PclSoftFontInfoPtr pSoftFontInfo; +PclFontHead16Ptr pfh16 = (PclFontHead16Ptr)NULL; +PclInternalFontPtr pin = (PclInternalFontPtr)NULL; +PclCharDataRec cd; +FontInfoPtr pfi; +unsigned char row, col; +char *p; +unsigned char last_fid; +int max_ascent, max_descent; +unsigned short def; + +int nbox; +BoxPtr pbox; +BoxRec box; +RegionPtr drawRegion, region; +char font_type; + + if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) + return x; + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)string, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, charinfo); + + pCon = PclGetContextFromWindow( (WindowPtr)pDrawable ); + pConPriv = (PclContextPrivPtr) + pCon->devPrivates[PclContextPrivateIndex].ptr; + pSoftFontInfo = pConPriv->pSoftFontInfo; + + font_type = isInternal(pGC->font); + if ( font_type == DOWNLOAD_FONT ) { + /* + * Create Soft Font Header Information + */ + pfh16 = makeFontHeader16(pGC->font, pSoftFontInfo); + if (!pfh16) + return x; + + /* + * exec Soft Font Downloading + */ + pfi = (FontInfoRec *)&pGC->font->info; + p = (char *)string; + for (i=0, p=(char *)string, chinfo=charinfo; ifirstRow <= row) && (row <= pfi->lastRow) + && (pfi->firstCol <= col) && (col <= pfi->lastCol) ) { + row = row - pfi->firstRow; + col = col - pfi->firstCol; + } else { + def = pfi->defaultCh; + row = (def>>8)&0xff - pfi->firstRow; + col = def&0xff - pfi->firstCol; + } + if ( !pfh16->index[row][col].fid ) { + fillCharDescData(&cd, *chinfo); + PclDownloadSoftFont16(pConPriv->pJobFile, pSoftFontInfo, + pfh16, &cd, row, col); + xfree(cd.raster_top); + } + } + + /* + * print characters + */ + MACRO_START( outFile, pConPriv ); + sprintf(t, "\033%%0B;PU%d,%dPD;TD1;DT%c,1;", + x + pDrawable->x, y + pDrawable->y + pGC->font->info.fontAscent, + ETX); + SAVE_PCL( outFile, pConPriv, t ); + SAVE_PCL_COUNT( outFile, pConPriv, "FI0;SS;LB", 9 ); + + last_fid = 0; + + w = 0; + max_ascent = charinfo[0]->metrics.ascent; + max_descent = charinfo[0]->metrics.descent; + for (i=0, p=(char *)string, chinfo=charinfo; ifirstRow <= row) && (row <= pfi->lastRow) + && (pfi->firstCol <= col) && (col <= pfi->lastCol) ) { + row = row - pfi->firstRow; + col = col - pfi->firstCol; + } else { + def = pfi->defaultCh; + row = (def>>8)&0xff - pfi->firstRow; + col = def&0xff - pfi->firstCol; + } + if ( last_fid != pfh16->index[row][col].fid ) { + sprintf(t, "%cFI%d;SS;LB", + ETX, pfh16->index[row][col].fid); + SAVE_PCL( outFile, pConPriv, t ); + last_fid = pfh16->index[row][col].fid; + } + + output_text(outFile, pConPriv, pfh16->index[row][col].cindex); + + w += (*chinfo)->metrics.characterWidth; + max_ascent = MAX(max_ascent, (*chinfo)->metrics.ascent); + max_descent = MAX(max_descent, (*chinfo)->metrics.descent); + } + sprintf(t, "%c", ETX); + SAVE_PCL_COUNT( outFile, pConPriv, t, 1 ); + sprintf(t, "TD0;\033%%1A"); + SAVE_PCL( outFile, pConPriv, t ); + MACRO_END( outFile ); + + } else { +#ifdef DO_TWO_BYTE_PCL + char *internalFont; + int pixel_size; + int fid = 0; + + pin = makeInternalFont(pGC->font, pSoftFontInfo); + if (!pin) + return x; + + selectInternalFont(outFile, pin, fid); + fprintf(outFile, "%c&t31P", ESC); + + /* + * print characters + */ + MACRO_START( outFile, pConPriv ); + sprintf(t, "\033%%0B;PU%d,%dPD;TD1;DT%c,1;", + x + pDrawable->x, y + pDrawable->y + pGC->font->info.fontAscent, + ETX); + SAVE_PCL( outFile, pConPriv, t ); + sprintf(t, "TD0;\033%%1A"); + SAVE_PCL( outFile, pConPriv, t ); + + w = 0; + last_fid = 0; + max_ascent = charinfo[0]->metrics.ascent; + max_descent = charinfo[0]->metrics.descent; + for (i=0, p=(char *)string, chinfo=charinfo; ifont, (char *)p, tobuf); + fprintf(outFile, "%c%c", tobuf[0], tobuf[1]); + + w += (*chinfo)->metrics.characterWidth; + max_ascent = MAX(max_ascent, (*chinfo)->metrics.ascent); + max_descent = MAX(max_descent, (*chinfo)->metrics.descent); + } + MACRO_END( outFile ); +#else + return x; +#endif /* DO_TWO_BYTE_PCL */ + } + + /* + * Convert the collection of rectangles into a proper region, then + * intersect it with the clip region. + */ + box.x1 = x + pDrawable->x; + box.y1 = y - max_ascent + pDrawable->y + pGC->font->info.fontAscent; + box.x2 = x + w + pDrawable->x; + box.y2 = y + max_descent + pDrawable->y + pGC->font->info.fontAscent; + + drawRegion = miRegionCreate( &box, 0 ); + region = miRegionCreate( NULL, 0 ); + miIntersect( region, drawRegion, + ((PclGCPrivPtr)pGC->devPrivates[PclGCPrivateIndex].ptr) + ->pCompositeClip ); + + /* + * For each rectangle in the clip region, set the HP-GL/2 "input + * window" and render the entire polyline to it. + */ + pbox = REGION_RECTS( region ); + nbox = REGION_NUM_RECTS( region ); + + PclSendData(outFile, pConPriv, pbox, nbox, 1.0); + + /* + * Clean up the temporary regions + */ + miRegionDestroy( drawRegion ); + miRegionDestroy( region ); + + return x+w; +} + +void +PclImageText8( pDrawable, pGC, x, y, count, string ) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + char *string; +{ +} + +void +PclImageText16( pDrawable, pGC, x, y, count, string ) + DrawablePtr pDrawable; + GCPtr pGC; + int x; + int y; + int count; + unsigned short *string; +{ +} + +void +PclImageGlyphBlt( pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase ) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nGlyphs; + CharInfoPtr *pCharInfo; + pointer pGlyphBase; +{ +} + +void +PclPolyGlyphBlt( pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase ) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nGlyphs; + CharInfoPtr *pCharInfo; + pointer pGlyphBase; +{ +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static PclFontHead8Ptr +makeFontHeader8(FontPtr pfont, PclSoftFontInfoPtr pSoftFontInfo) +{ +PclFontHead8Ptr phead8 = pSoftFontInfo->phead8; +PclFontHead8Ptr pfh8 = phead8; +PclFontHead8Ptr prev = (PclFontHead8Ptr)NULL; +FontInfoPtr pfi; +char *fontname; +unsigned char nindex; +int i, j; +unsigned long n; +CharInfoPtr charinfo[1]; +unsigned int space_width; + + if (pSoftFontInfo == (PclSoftFontInfoPtr) NULL) + return (PclFontHead8Ptr)NULL; + + /* + * Verify it has already been created, if so, return it. + */ + if ( (fontname = getFontName(pfont)) == (char *)NULL) + return (PclFontHead8Ptr)NULL; + + while (pfh8 != (PclFontHead8Ptr) NULL) { + if (!strcmp(pfh8->fontname, fontname)) + return pfh8; + prev = pfh8; + pfh8 = pfh8->next; + } + + /* + * Create Font Header Information + */ + pfh8 = (PclFontHead8Ptr)xalloc(sizeof(PclFontHead8Rec)); + if (pfh8 == (PclFontHead8Ptr)NULL) + return (PclFontHead8Ptr)NULL; + + pfi = (FontInfoRec *)&pfont->info; + GetGlyphs(pfont, 1, (unsigned char *)&pfi->defaultCh, + Linear8Bit, &n, charinfo); + if ( n ) + space_width = charinfo[0]->metrics.characterWidth; + else + space_width = FONTMAXBOUNDS(pfont,characterWidth); + + fillFontDescData(pfont, &(pfh8->fd), space_width); + pfh8->fid = 0; + pfh8->fontname = (char *)xalloc(strlen(fontname) + 1); + if (pfh8->fontname == (char *)NULL) { + xfree(pfh8); + return (PclFontHead8Ptr) NULL; + } + strcpy(pfh8->fontname, fontname); + + nindex = 0xff; + pfh8->index = (unsigned char *)xalloc(nindex); + if ( pfh8->index == (unsigned char *) NULL ) { + xfree(pfh8->fontname); + xfree(pfh8); + return (PclFontHead8Ptr) NULL; + } + + for (i=0; i<=nindex; i++) + pfh8->index[i] = 0x0; + + pfh8->next = (PclFontHead8Ptr)NULL; + + if ( prev == (PclFontHead8Ptr) NULL) + pSoftFontInfo->phead8 = pfh8; + else + prev->next = pfh8; + + return pfh8; +} + +static PclFontHead16Ptr +makeFontHeader16(FontPtr pfont, PclSoftFontInfoPtr pSoftFontInfo) +{ +PclFontHead16Ptr phead16 = pSoftFontInfo->phead16; +PclFontHead16Ptr pfh16 = phead16; +PclFontHead16Ptr prev = (PclFontHead16Ptr)NULL; +PclFontMapRec ** index; +FontInfoPtr pfi; +char *fontname; +unsigned char nindex_row, nindex_col; +int i, j; +unsigned long n; +CharInfoPtr charinfo[1]; +unsigned int space_width; + + if (pSoftFontInfo == (PclSoftFontInfoPtr) NULL) + return (PclFontHead16Ptr)NULL; + + /* + * Verify it has already been created, if so, return it. + */ + if ( (fontname = getFontName(pfont)) == (char *)NULL) + return (PclFontHead16Ptr)NULL; + + while (pfh16 != (PclFontHead16Ptr) NULL) { + if (!strcmp(pfh16->fontname, fontname)) + return pfh16; + prev = pfh16; + pfh16 = pfh16->next; + } + + /* + * Create Font Header Information + */ + pfh16 = (PclFontHead16Ptr)xalloc(sizeof(PclFontHead16Rec)); + if (pfh16 == (PclFontHead16Ptr)NULL) + return (PclFontHead16Ptr)NULL; + + pfi = (FontInfoRec *)&pfont->info; + GetGlyphs(pfont, 1, (unsigned char *)&pfi->defaultCh, + (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit, + &n, charinfo); + + if ( n ) + space_width = charinfo[0]->metrics.characterWidth; + else + space_width = FONTMAXBOUNDS(pfont,characterWidth); + + fillFontDescData(pfont, &(pfh16->fd), space_width); + pfh16->cur_fid = 0; + pfh16->cur_cindex = 0; + pfh16->fontname = (char *)xalloc(strlen(fontname) + 1); + if (pfh16->fontname == (char *)NULL) { + xfree(pfh16); + return (PclFontHead16Ptr) NULL; + } + strcpy(pfh16->fontname, fontname); + + pfi = (FontInfoRec *)&pfont->info; + nindex_col = pfi->lastCol - pfi->firstCol + 1; + nindex_row = pfi->lastRow - pfi->firstRow + 1; + index = (PclFontMapRec **)xalloc(sizeof(PclFontMapRec *)*nindex_row); + if (index == (PclFontMapRec **)NULL) { + xfree(pfh16->fontname); + xfree(pfh16); + return (PclFontHead16Ptr) NULL; + } + for (i=0; ifontname); + xfree(pfh16); + return (PclFontHead16Ptr) NULL; + } + for (j=0; j<=nindex_col; j++) + index[i][j].fid = 0x0; + } + + pfh16->index = index; + pfh16->firstCol = pfi->firstCol; + pfh16->lastCol = pfi->lastCol; + pfh16->firstRow = pfi->firstRow; + pfh16->lastRow = pfi->lastRow; + pfh16->next = (PclFontHead16Ptr)NULL; + + if ( prev == (PclFontHead16Ptr) NULL) + pSoftFontInfo->phead16 = pfh16; + else + prev->next = pfh16; + + return pfh16; +} + +static PclInternalFontPtr +makeInternalFont(FontPtr pfont, PclSoftFontInfoPtr pSoftFontInfo) +{ +PclInternalFontPtr pinfont = pSoftFontInfo->pinfont; +PclInternalFontPtr pin = pinfont; +PclInternalFontPtr prev = (PclInternalFontPtr)NULL; +FontPropPtr props; +FontInfoPtr pfi; +char *fontname; +Atom xa_pcl_font_name, xa_res, xa_ave_width, xa_spacing; +int res, width; +int mask; +int i; + + if (pSoftFontInfo == (PclSoftFontInfoPtr) NULL) + return (PclInternalFontPtr)NULL; + + /* + * Verify it has already been created, if so, return it. + */ + if ( (fontname = getFontName(pfont)) == (char *)NULL) + return (PclInternalFontPtr)NULL; + + while (pin != (PclInternalFontPtr) NULL) { + if (!strcmp(pin->fontname, fontname)) + return pin; + prev = pin; + pin = pin->next; + } + + /* + * Create Internal Font Information + */ + pin = (PclInternalFontPtr)xalloc(sizeof(PclInternalFontRec)); + if (pin == (PclInternalFontPtr)NULL) + return (PclInternalFontPtr)NULL; + + pin->fontname = (char *)xalloc(strlen(fontname) + 1); + if (pin->fontname == (char *)NULL) { + xfree(pin); + return (PclInternalFontPtr) NULL; + } + strcpy(pin->fontname, fontname); + + xa_pcl_font_name = MakeAtom("PCL_FONT_NAME", strlen("PCL_FONT_NAME"), TRUE); + xa_res = MakeAtom("RESOLUTION_X", strlen("RESOLUTION_X"), TRUE); + xa_ave_width = MakeAtom("AVERAGE_WIDTH", strlen("AVERAGE_WIDTH"), TRUE); + xa_spacing = MakeAtom("SPACING", strlen("SPACING"), TRUE); + pfi = (FontInfoRec *)&pfont->info; + props = pfi->props; + + mask = 0; + for (i=0; inprops; i++, props++) { + if ( props->name == xa_pcl_font_name ) { + pin->pcl_font_name = NameForAtom(props->value); + mask |= 0x1; + } else if ( props->name == XA_POINT_SIZE ) { + pin->height = (float) props->value / 10.0; + mask |= 0x2; + } else if ( props->name == xa_res ) { + res = (int) props->value; + mask |= 0x4; + } else if ( props->name == xa_ave_width ) { + width = (int) props->value / 10; + mask |= 0x8; + } else if ( props->name == xa_spacing ) { + pin->spacing = NameForAtom(props->value); + mask |= 0x10; + } + } + if ( mask != 0x1f ) { + xfree(pin->fontname); + xfree(pin); + return (PclInternalFontPtr) NULL; + } + + if ( *pin->spacing != 'P' || *pin->spacing != 'p' ) + pin->pitch = (float) 300.0 / width; /* Hard-Code: Resolution is 300 */ + + pin->next = (PclInternalFontPtr)NULL; + if ( prev == (PclInternalFontPtr) NULL) + pSoftFontInfo->pinfont = pin; + else + prev->next = pin; + + return pin; +} + +static void +fillFontDescData(FontPtr pfont, PclFontDescPtr pfd, unsigned int space) +{ +FontInfoPtr pfi; + + pfi = (FontInfoRec *)&pfont->info; + + if ( (pfi->maxbounds.leftSideBearing == pfi->minbounds.leftSideBearing) + && (pfi->maxbounds.rightSideBearing == pfi->minbounds.rightSideBearing) + && (pfi->maxbounds.characterWidth == pfi->minbounds.characterWidth) + && (pfi->maxbounds.ascent == pfi->minbounds.ascent) + && (pfi->maxbounds.descent == pfi->minbounds.descent) + ) + pfd->spacing = MONOSPACE; + else + pfd->spacing = PROPSPACE; + + pfd->pitch = space; + pfd->cellheight = FONTMAXBOUNDS(pfont,ascent) + + FONTMAXBOUNDS(pfont,descent); + pfd->cellwidth = FONTMAXBOUNDS(pfont,rightSideBearing) + - FONTMINBOUNDS(pfont,leftSideBearing); + pfd->ascent = FONTMAXBOUNDS(pfont,ascent); /*FONTASCENT(pfont);*/ + pfd->descent = FONTMAXBOUNDS(pfont,descent); /*FONTDESCENT(pfont);*/ +} + +static PclCharDataPtr +fillCharDescData(PclCharDataPtr pcd, CharInfoPtr pci) +{ +unsigned int byte_width; +unsigned char *p; +register int nbyGlyphWidth; +unsigned char *pglyph, *pg; +int i, j; + + pcd->h_offset = pci->metrics.leftSideBearing; + pcd->v_offset = pci->metrics.ascent; + pcd->width = pci->metrics.rightSideBearing + - pci->metrics.leftSideBearing; + pcd->height = pci->metrics.ascent + pci->metrics.descent; + pcd->font_pitch = pci->metrics.characterWidth; + + byte_width = (pcd->width + 7)/8; + pcd->raster_top = (unsigned char *)xalloc(byte_width * pcd->height); + if (pcd->raster_top == (unsigned char *)NULL) + return (PclCharDataPtr)NULL; + + p = pcd->raster_top; + nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci); + pglyph = FONTGLYPHBITS(pglyphBase, pci); + for (i=0; iheight; i++) { + pg = pglyph + nbyGlyphWidth * i; + for (j=0; jinfo; + props = pfi->props; + fontname = (char *) NULL; + for (i=0; inprops; i++, props++) { + if ( props->name == XA_FONT ) { + fontname = (char *)NameForAtom(props->value); + break; + } + } + return fontname; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* Internal Font Selection */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static char +isInternal(FontPtr pfont) +{ +int i; +FontInfoPtr pfi; +FontPropPtr props; +Atom dest; + + dest = MakeAtom("PRINTER_RESIDENT_FONT", strlen("PRINTER_RESIDENT_FONT"), TRUE); + + pfi = (FontInfoRec *)&pfont->info; + props = pfi->props; + for (i=0; inprops; i++, props++) { + if ( props->name == dest && props->value == 2 ) + return INTERNAL_FONT; + } + return DOWNLOAD_FONT; +} + +static void +selectInternalFont(FILE *outFile, PclInternalFontPtr pin, int fid) +{ + fprintf(outFile, "%c*c%dD", ESC, fid); + if ( *pin->spacing == 'P' || *pin->spacing == 'p' ) + fprintf(outFile, pin->pcl_font_name, pin->height); + else + fprintf(outFile, pin->pcl_font_name, pin->pitch); + fprintf(outFile, "%c*c6F", ESC); +} + +static void +selectSize(FILE *outFile, + PclContextPrivPtr pConPriv, + PclInternalFontPtr pin) +{ + if ( *pin->spacing == 'P' || *pin->spacing == 'p' ) { + sprintf(t, "SD4,%f;", pin->height); + SAVE_PCL( outFile, pConPriv, t ); + } else { + sprintf(t, "SD3,%f;", pin->pitch); + SAVE_PCL( outFile, pConPriv, t ); + } + return; +} + +#ifdef DO_TWO_BYTE_PCL +static void +code_conv( + PclSoftFontInfoPtr pSoftFontInfo, + FontPtr pfont, + char *from, + char *to +) +{ +iconv_t cd; +char frombuf[9], *fromptr; +size_t inbyte = 5, outbyte=2; + + fromptr = frombuf; + frombuf[0] = 0x1b; /* Esc */ + frombuf[1] = 0x24; /* $ */ + frombuf[2] = 0x42; /* B */ + frombuf[3] = *from; + frombuf[4] = *(from+1); + frombuf[5] = 0x1b; /* Esc */ + frombuf[6] = 0x28; /* ( */ + frombuf[7] = 0x4a; /* J */ + frombuf[8] = 0x0; + if ((cd = iconv_open("sjis", "jis")) == (iconv_t)(-1)) { + *to = (unsigned char)NULL; + return; + } + + if ( iconv(cd, &fromptr, &inbyte, &to, &outbyte) == -1 ) + *to = (unsigned char)NULL; + + iconv_close(cd); + return; +} +#endif /* DO_TWO_BYTE_PCL */ diff --git a/Xprint/pcl/PclWindow.c b/Xprint/pcl/PclWindow.c new file mode 100644 index 000000000..7c830b897 --- /dev/null +++ b/Xprint/pcl/PclWindow.c @@ -0,0 +1,450 @@ +/* $Xorg: PclWindow.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/******************************************************************* +** +** ********************************************************* +** * +** * File: PclWindow.c +** * +** * Contents: +** * Window code for Pcl driver. +** * +** * Created: 2/02/95 +** * +** ********************************************************* +** +********************************************************************/ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + + +#include +#include +#include + +#include "mistruct.h" +#include "regionstr.h" +#include "windowstr.h" +#include "gcstruct.h" + +#include "Pcl.h" + +extern WindowPtr *WindowTable; + +/* + * The following list of strings defines the properties which will be + * placed on the screen's root window if the property was defined in + * the start-up configuration resource database. + */ +static /* const */ char *propStrings[] = { + DT_PRINT_JOB_HEADER, + DT_PRINT_JOB_TRAILER, + DT_PRINT_JOB_COMMAND, /* old-obsolete */ + DT_PRINT_JOB_EXEC_COMMAND, + DT_PRINT_JOB_EXEC_OPTIONS, + DT_PRINT_PAGE_HEADER, + DT_PRINT_PAGE_TRAILER, + DT_PRINT_PAGE_COMMAND, + (char *)NULL +}; + + +/* + * PclCreateWindow - watch for the creation of the root window. + * When it's created, register the screen with the print extension, + * and put the default command/header properties on it. + */ +/*ARGSUSED*/ + +Bool +PclCreateWindow( + register WindowPtr pWin) +{ + PclWindowPrivPtr pPriv; + +#if 0 + Bool status = Success; + ScreenPtr pScreen = pWin->drawable.pScreen; + PclScreenPrivPtr pScreenPriv = (PclScreenPrivPtr) + pScreen->devPrivates[PclScreenPrivateIndex].ptr; + PclWindowPrivPtr pWinPriv = (PclWindowPrivPtr) + pWin->devPrivates[PclWindowPrivateIndex].ptr; + + /* + * Initialize this window's private struct. + */ + pWinPriv->jobFileName = (char *)NULL; + pWinPriv->pJobFile = (FILE *)NULL; + pWinPriv->pageFileName = (char *)NULL; + pWinPriv->pPageFile = (FILE *)NULL; + + if(pWin->parent == (WindowPtr)NULL) /* root window? */ + { + Atom propName; /* type = XA_STRING */ + char *propVal; + int i; + XrmDatabase rmdb = pScreenPriv->resDB; + + /* + * Put the defaults spec'd in the config files in properties on this + * screen's root window. + */ + for(i = 0; propStrings[i] != (char *)NULL; i++) + { + if((propVal = _DtPrintGetPrinterResource(pWin, rmdb, + propStrings[i])) != + (char *)NULL) + { + propName = MakeAtom(propStrings[i], strlen(propStrings[i]), + TRUE); + ChangeWindowProperty(pWin, propName, XA_STRING, 8, + PropModeReplace, strlen(propVal), + (pointer)propVal, FALSE); + xfree(propVal); + } + } + } + + return status; +#endif + + /* + * Invalidate the window's private print context. + */ + pPriv = (PclWindowPrivPtr)pWin->devPrivates[PclWindowPrivateIndex].ptr; + pPriv->validContext = 0; + + return TRUE; +} + + +/*ARGSUSED*/ +Bool PclMapWindow( + WindowPtr pWindow) +{ + return TRUE; +} + +/*ARGSUSED*/ +Bool +PclPositionWindow( + register WindowPtr pWin, + int x, + int y) +{ + return TRUE; +} + +/*ARGSUSED*/ +Bool +PclUnmapWindow( + WindowPtr pWindow) +{ + return TRUE; +} + +/*ARGSUSED*/ +void +PclCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ +} + +/*ARGSUSED*/ +Bool +PclChangeWindowAttributes( + register WindowPtr pWin, + register unsigned long mask) +{ + if( pWin->backingStore != NotUseful ) + { + pWin->backingStore = NotUseful; + mask |= CWBackingStore; + } + + return TRUE; +} + + +/* + * This function is largely ripped from miPaintWindow, but modified so + * that the background is not painted to the root window, and so that + * the backing store is not referenced. + */ +void +PclPaintWindow( + WindowPtr pWin, + RegionPtr pRegion, + int what) +{ + int status; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + pointer gcval[7]; + pointer newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + + gcmask = 0; + + /* + * We don't want to paint a window that has no place to put the + * PCL output. + */ + if( PclGetContextFromWindow( pWin ) == (XpContextPtr)NULL ) + return; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground) + (pWin->parent, pRegion, what); + return; + case BackgroundPixel: + newValues[FOREGROUND] = (pointer)pWin->background.pixel; + newValues[FILLSTYLE] = (pointer)FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE] = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE] = (pointer)FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | + GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND] = (pointer)pWin->border.pixel; + newValues[FILLSTYLE] = (pointer)FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE] = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE] = (pointer)FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin + | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(pRegion) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION] = (pointer)GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX] = (pointer)(long)pBgWin->drawable.x; + newValues[ABSY] = (pointer)(long)pBgWin->drawable.y; + } + else + { + newValues[ABSX] = (pointer)0; + newValues[ABSY] = (pointer)0; + } + +/* + * XXX Backing store is turned off for the PCL driver + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, + GuaranteeVisBack); + */ + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if ((pointer)(long) pGC->alu != newValues[FUNCTION]) { + gcmask |= index; + gcval[i++] = newValues[FUNCTION]; + } + break; + case GCTileStipXOrigin: + if ((pointer)(long) pGC->patOrg.x != newValues[ABSX]) { + gcmask |= index; + gcval[i++] = newValues[ABSX]; + } + break; + case GCTileStipYOrigin: + if ((pointer)(long) pGC->patOrg.y != newValues[ABSY]) { + gcmask |= index; + gcval[i++] = newValues[ABSY]; + } + break; + case GCClipMask: + if ((pointer) pGC->clientClipType != (pointer)CT_NONE) { + gcmask |= index; + gcval[i++] = (pointer)CT_NONE; + } + break; + case GCSubwindowMode: + if ((pointer) pGC->subWindowMode != newValues[SUBWINDOW]) { + gcmask |= index; + gcval[i++] = newValues[SUBWINDOW]; + } + break; + case GCTile: + if (pGC->tileIsPixel || + (pointer) pGC->tile.pixmap != newValues[TILE]) + { + gcmask |= index; + gcval[i++] = newValues[TILE]; + } + break; + case GCFillStyle: + if ((pointer) pGC->fillStyle != newValues[FILLSTYLE]) { + gcmask |= index; + gcval[i++] = newValues[FILLSTYLE]; + } + break; + case GCForeground: + if ((pointer) pGC->fgPixel != newValues[FOREGROUND]) { + gcmask |= index; + gcval[i++] = newValues[FOREGROUND]; + } + break; + } + } + + if (gcmask) + DoChangeGC(pGC, gcmask, (XID *)gcval, 1); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(pRegion); + pbox = REGION_RECTS(pRegion); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + +/* + * XXX Backing store is turned off for the PCL driver + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, + GuaranteeNothing); + */ + + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + +} + +/*ARGSUSED*/ +Bool +PclDestroyWindow( + WindowPtr pWin) +{ + return TRUE; +} + diff --git a/Xprint/pcl/Pclmap.h b/Xprint/pcl/Pclmap.h new file mode 100644 index 000000000..ecec35776 --- /dev/null +++ b/Xprint/pcl/Pclmap.h @@ -0,0 +1,195 @@ +/* $Xorg: Pclmap.h,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#ifndef _PCLMAP_H_ +#define _PCLMAP_H_ + +#ifdef XP_PCL_COLOR +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define NAME(subname) PclCr##subname +#define CATNAME(prefix,subname) prefix##Color##subname +#else +#define NAME(subname) PclCr/**/subname +#define CATNAME(prefix,subname) prefix/**/Color/**/subname +#endif +#endif /* XP_PCL_COLOR */ + +#ifdef XP_PCL_MONO +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define NAME(subname) PclMn##subname +#define CATNAME(prefix,subname) prefix##Mono##subname +#else +#define NAME(subname) PclMn/**/subname +#define CATNAME(prefix,subname) prefix/**/Mono/**/subname +#endif +#endif /* XP_PCL_MONO */ + +#ifdef XP_PCL_LJ3 +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define NAME(subname) PclLj3##subname +#define CATNAME(prefix,subname) prefix##Lj3##subname +#else +#define NAME(subname) PclLj3/**/subname +#define CATNAME(prefix,subname) prefix/**/Lj3/**/subname +#endif +#endif /* XP_PCL_LJ3 */ + +/* PclInit.c */ +#define InitializePclDriver CATNAME(Initialize, PclDriver) +#define PclCloseScreen NAME(CloseScreen) +#define PclGetContextFromWindow NAME(GetContextFromWindow) +#define PclScreenPrivateIndex NAME(ScreenPrivateIndex) +#define PclWindowPrivateIndex NAME(WindowPrivateIndex) +#define PclContextPrivateIndex NAME(ContextPrivateIndex) +#define PclPixmapPrivateIndex NAME(PixmapPrivateIndex) +#define PclGCPrivateIndex NAME(GCPrivateIndex) + +/* PclPrint.c */ +#define PclStartJob NAME(StartJob) +#define PclEndJob NAME(EndJob) +#define PclStartPage NAME(StartPage) +#define PclEndPage NAME(EndPage) +#define PclStartDoc NAME(StartDoc) +#define PclEndDoc NAME(EndDoc) +#define PclDocumentData NAME(DocumentData) +#define PclGetDocumentData NAME(GetDocumentData) + +/* PclWindow.c */ +#define PclCreateWindow NAME(CreateWindow) +#define PclMapWindow NAME(MapWindow) +#define PclPositionWindow NAME(PositionWindow) +#define PclUnmapWindow NAME(UnmapWindow) +#define PclCopyWindow NAME(CopyWindow) +#define PclChangeWindowAttributes NAME(ChangeWindowAttributes) +#define PclPaintWindow NAME(PaintWindow) +#define PclDestroyWindow NAME(DestroyWindow) + +/* PclGC.c */ +#define PclCreateGC NAME(CreateGC) +#define PclDestroyGC NAME(DestroyGC) +#define PclGetDrawablePrivateStuff NAME(GetDrawablePrivateStuff) +#define PclSetDrawablePrivateGC NAME(SetDrawablePrivateGC) +#define PclSendPattern NAME(SendPattern) +#define PclUpdateDrawableGC NAME(UpdateDrawableGC) +#define PclComputeCompositeClip NAME(ComputeCompositeClip) +#define PclValidateGC NAME(ValidateGC) + +/* PclAttr.c */ +#define PclGetAttributes NAME(GetAttributes) +#define PclGetOneAttribute NAME(GetOneAttribute) +#define PclAugmentAttributes NAME(AugmentAttributes) +#define PclSetAttributes NAME(SetAttributes) + +/* PclColor.c */ +#define PclLookUp NAME(LookUp) +#define PclCreateDefColormap NAME(CreateDefColormap) +#define PclCreateColormap NAME(CreateColormap) +#define PclDestroyColormap NAME(DestroyColormap) +#define PclInstallColormap NAME(InstallColormap) +#define PclUninstallColormap NAME(UninstallColormap) +#define PclListInstalledColormaps NAME(ListInstalledColormaps) +#define PclStoreColors NAME(StoreColors) +#define PclResolveColor NAME(ResolveColor) +#define PclFindPaletteMap NAME(FindPaletteMap) +#define PclUpdateColormap NAME(UpdateColormap) +#define PclReadMap NAME(ReadMap) + +/* PclPixmap.c */ +#define PclCreatePixmap NAME(CreatePixmap) +#define PclDestroyPixmap NAME(DestroyPixmap) + +/* PclArc.c */ +#define PclDoArc NAME(DoArc) +#define PclPolyArc NAME(PolyArc) +#define PclPolyFillArc NAME(PolyFillArc) + +/* PclArea.c */ +#define PclPutImage NAME(PutImage) +#define PclCopyArea NAME(CopyArea) +#define PclCopyPlane NAME(CopyPlane) + +/* PclLine */ +#define PclPolyLine NAME(PolyLine) +#define PclPolySegment NAME(PolySegment) + +/* PclPixel.c */ +#define PclPolyPoint NAME(PolyPoint) +#define PclPushPixels NAME(PushPixels) + +/* PclPolygon.c */ +#define PclPolyRectangle NAME(PolyRectangle) +#define PclFillPolygon NAME(FillPolygon) +#define PclPolyFillRect NAME(PolyFillRect) + +/* PclSpans.c */ +#define PclFillSpans NAME(FillSpans) +#define PclSetSpans NAME(SetSpans) + +/* PclText.c */ +#define PclPolyText8 NAME(PolyText8) +#define PclPolyText16 NAME(PolyText16) +#define PclImageText8 NAME(ImageText8) +#define PclImageText16 NAME(ImageText16) +#define PclImageGlyphBlt NAME(ImageGlyphBlt) +#define PclPolyGlyphBlt NAME(PolyGlyphBlt) +#define PclPolyGlyphBlt NAME(PolyGlyphBlt) + +/* PclFonts.c */ +#define PclRealizeFont NAME(RealizeFont) +#define PclUnrealizeFont NAME(UnrealizeFont) + +/* PclSFonts.c */ +#define PclDownloadSoftFont8 NAME(DownloadSoftFont8) +#define PclDownloadSoftFont16 NAME(DownloadSoftFont16) +#define PclCreateSoftFontInfo NAME(CreateSoftFontInfo) +#define PclDestroySoftFontInfo NAME(DestroySoftFontInfo) + +/* PclMisc.c */ +#define PclQueryBestSize NAME(QueryBestSize) +#define GetPropString NAME(GetPropString) +#define SystemCmd NAME(SystemCmd) +#define PclGetMediumDimensions NAME(GetMediumDimensions) +#define PclGetReproducibleArea NAME(GetReproducibleArea) +#define PclSpoolFigs NAME(SpoolFigs) +#define PclSendData NAME(SendData) + +/* PclCursor.c */ +#define PclConstrainCursor NAME(ConstrainCursor) +#define PclCursorLimits NAME(CursorLimits) +#define PclDisplayCursor NAME(DisplayCursor) +#define PclRealizeCursor NAME(RealizeCursor) +#define PclUnrealizeCursor NAME(UnrealizeCursor) +#define PclRecolorCursor NAME(RecolorCursor) +#define PclSetCursorPosition NAME(SetCursorPosition) + +#endif /* _PCLMAP_H_ */ diff --git a/Xprint/ps/Ps.h b/Xprint/ps/Ps.h new file mode 100644 index 000000000..942e8f9f8 --- /dev/null +++ b/Xprint/ps/Ps.h @@ -0,0 +1,520 @@ +/* $Xorg: Ps.h,v 1.5 2001/02/09 02:04:35 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: Ps.h +** * +** * Contents: defines and includes for the Ps driver +** * for a printing X server. +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#ifndef _PS_H_ +#define _PS_H_ + +#include + +#ifdef abs +#undef abs /* this is because of a non-Spec1170ness in misc.h */ +#endif +#include +#include "scrnintstr.h" +#include "dix.h" + +/* +#include "X.h" +#include "Xproto.h" +#include "Xatom.h" +#include "misc.h" +#include "screenint.h" +#include "colormapst.h" +#include "windowstr.h" +#include "propertyst.h" +#include "servermd.h"*/ /* needed for IMAGE_BUFSIZE */ + +#include "PsDef.h" +#include "psout.h" + +#define _XP_PRINT_SERVER_ +#include "Print.h" +#include "extensions/Printstr.h" +#undef _XP_PRINT_SERVER_ + +#include "miscstruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" + +/* + * Some sleazes to force the XrmDB stuff into the server + */ +typedef char *XPointer; +#define Status int +#define True 1 +#define False 0 +#include "misc.h" +#include +#include "../Xresource.h" + +/* + * Public index variables from PsInit.c + */ + +extern int PsScreenPrivateIndex; +extern int PsWindowPrivateIndex; +extern int PsContextPrivateIndex; +extern int PsPixmapPrivateIndex; +extern int PsGCPrivateIndex; + +/* + * Display list structures + */ + +#define DPY_BLOCKSIZE 4096 + +typedef struct +{ + int mode; + int nPoints; + xPoint *pPoints; +} PsPolyPointsRec; + +typedef struct +{ + int nSegments; + xSegment *pSegments; +} PsSegmentsRec; + +typedef struct +{ + int nRects; + xRectangle *pRects; +} PsRectanglesRec; + +typedef struct +{ + int nArcs; + xArc *pArcs; +} PsArcsRec; + +typedef struct +{ + int x; + int y; + int count; + char *string; +} PsText8Rec; + +typedef struct +{ + int x; + int y; + int count; + unsigned short *string; +} PsText16Rec; + +typedef struct +{ + int depth; + int x; + int y; + int w; + int h; + int leftPad; + int format; + int res; /* image resolution */ + char *pData; +} PsImageRec; + +typedef struct +{ + int x; + int y; + int w; + int h; +} PsFrameRec; + +typedef enum +{ + PolyPointCmd, + PolyLineCmd, + PolySegmentCmd, + PolyRectangleCmd, + FillPolygonCmd, + PolyFillRectCmd, + PolyArcCmd, + PolyFillArcCmd, + Text8Cmd, + Text16Cmd, + TextI8Cmd, + TextI16Cmd, + PutImageCmd, + BeginFrameCmd, + EndFrameCmd +} DisplayElmType; + +typedef struct _DisplayElmRec +{ + DisplayElmType type; + GCPtr gc; + union + { + PsPolyPointsRec polyPts; + PsSegmentsRec segments; + PsRectanglesRec rects; + PsArcsRec arcs; + PsText8Rec text8; + PsText16Rec text16; + PsImageRec image; + PsFrameRec frame; + } c; +} DisplayElmRec; + +typedef DisplayElmRec *DisplayElmPtr; + +typedef struct _DisplayListRec +{ + struct _DisplayListRec *next; + int nelms; + DisplayElmRec elms[DPY_BLOCKSIZE]; +} DisplayListRec; + +typedef DisplayListRec *DisplayListPtr; + +/* + * Private structures + */ + +typedef struct +{ + XrmDatabase resDB; + ColormapPtr CMap; + Bool (*DestroyWindow)(); +} PsScreenPrivRec, *PsScreenPrivPtr; + +typedef struct +{ + char *jobFileName; + FILE *pJobFile; + GC lastGC; + unsigned char *dash; + int validGC; + ClientPtr getDocClient; + int getDocBufSize; + PsOutPtr pPsOut; +} PsContextPrivRec, *PsContextPrivPtr; + +typedef struct +{ + int validContext; + XpContextPtr context; +} PsWindowPrivRec, *PsWindowPrivPtr; + +typedef struct +{ + unsigned freeCompClip; + RegionPtr pCompositeClip; +} PsGCPrivRec, *PsGCPrivPtr; + +typedef struct +{ + XpContextPtr context; + GC lastGC; + int validGC; + DisplayListPtr dispList; +} PsPixmapPrivRec, *PsPixmapPrivPtr; + +/* + * Macro functions + */ + +#define SEND_PS(f,c) fwrite( c, sizeof( char ), strlen( c ), f ) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/* + * Functions in PsInit.c + */ + +extern Bool InitializePsDriver(int ndx, ScreenPtr pScreen, int argc, + char **argv); +static Bool PsDestroyContext(XpContextPtr pCon); +extern XpContextPtr PsGetContextFromWindow(WindowPtr win); + +/* + * Functions in PsPrint.c + */ + +extern int PsStartJob(XpContextPtr pCon, Bool sendClientData, ClientPtr client); +extern int PsEndJob(XpContextPtr pCon, Bool cancel); +extern int PsStartPage(XpContextPtr pCon, WindowPtr pWin); +extern int PsEndPage(XpContextPtr pCon, WindowPtr pWin); +extern int PsStartDoc(XpContextPtr pCon, XPDocumentType type); +extern int PsEndDoc(XpContextPtr pCon, Bool cancel); +extern int PsDocumentData(XpContextPtr pCon, DrawablePtr pDraw, char *pData, + int len_data, char *pFmt, int len_fmt, char *pOpt, int len_opt, + ClientPtr client); +extern int PsGetDocumentData(XpContextPtr pCon, ClientPtr client, + int maxBufferSize); + +/* + * Functions in PsGC.c + */ + +extern Bool PsCreateGC(GCPtr pGC); +static int PsGetDrawablePrivateStuff(DrawablePtr pDrawable, GC *gc, + unsigned long *valid, PsOutPtr *psOut, + ColormapPtr *cMap); +extern int PsUpdateDrawableGC(GCPtr pGC, DrawablePtr pDrawable, + PsOutPtr *psOut, ColormapPtr *cMap); +extern void PsValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable); +extern void PsChangeGC(GCPtr pGC, unsigned long changes); +extern void PsCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +extern void PsDestroyGC(GCPtr pGC); +extern void PsChangeClip(GCPtr pGC, int type, pointer pValue, int nrects); +extern void PsDestroyClip(GCPtr pGC); +extern void PsCopyClip(GCPtr pgcDst, GCPtr pgcSrc); + +extern GCPtr PsCreateAndCopyGC(DrawablePtr pDrawable, GCPtr pSrc); + +/* + * Functions in PsMisc.c + */ + +extern void PsQueryBestSize(int type, short *pwidth, short *pheight, + ScreenPtr pScreen); +extern Bool PsCloseScreen(int index, ScreenPtr pScreen); +extern void PsLineAttrs(PsOutPtr psOut, GCPtr pGC, ColormapPtr cMap); +extern int PsGetMediumDimensions( + XpContextPtr pCon, + CARD16 *pWidth, + CARD16 *pHeight); +extern int PsGetReproducibleArea( + XpContextPtr pCon, + xRectangle *pRect); +extern int PsSetImageResolution( + XpContextPtr pCon, + int imageRes, + Bool *status); + +/* + * Functions in PsSpans.c + */ + +extern void PsFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans, + DDXPointPtr pPoints, int *pWidths, int fSorted); +extern void PsSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc, + DDXPointPtr pPoints, int *pWidths, int nSpans, + int fSorted); + +/* + * Functions in PsArea.c + */ + +extern void PsPutScaledImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + int imageRes, char *pImage); +extern void PsPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *pImage); +extern RegionPtr PsCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty); +extern RegionPtr PsCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long plane); + +/* + * Functions in PsPixel.c + */ + +extern void PsPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints); +extern void PsPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, + int width, int height, int x, int y); + +/* + * Functions in PsLine.c + */ + +extern void PsPolyLine(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints); +extern void PsPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nSegments, + xSegment *pSegments); + +/* + * Functions in PsPolygon.c + */ + +extern void PsPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nRects, + xRectangle *pRects); +extern void PsFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int nPoints, DDXPointPtr pPoints); +extern void PsPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nRects, + xRectangle *pRects); + +/* + * Functions in PsPolygon.c + */ + +extern void PsPolyArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, + xArc *pArcs); +extern void PsPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, + xArc *pArcs); + +/* + * Functions in PsText.c + */ + +extern int PsPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *string); +extern int PsPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, unsigned short *string); +extern void PsImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *string); +extern void PsImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, unsigned short *string); +extern void PsImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, + pointer pGlyphBase); +extern void PsPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, + pointer pGlyphBase); + +/* + * Functions in PsWindow.c + */ + +extern Bool PsCreateWindow(WindowPtr pWin); +extern Bool PsMapWindow(WindowPtr pWin); +extern Bool PsPositionWindow(WindowPtr pWin, int x, int y); +extern Bool PsUnmapWindow(WindowPtr pWin); +extern void PsCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +extern Bool PsChangeWindowAttributes(WindowPtr pWin, unsigned long mask); +extern void PsPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); +extern Bool PsDestroyWindow(WindowPtr pWin); + +/* + * Functions in PsFonts.c + */ + +extern Bool PsRealizeFont(ScreenPtr pscr, FontPtr pFont); +extern Bool PsUnrealizeFont(ScreenPtr pscr, FontPtr pFont); +extern char *PsGetFontName(FontPtr pFont); +extern int PsGetFontSize(FontPtr pFont, float *mtx); +extern char *PsGetPSFontName(FontPtr pFont); +extern int PsIsISOLatin1Encoding(FontPtr pFont); + +/* + * Functions in PsAttr.c + */ + +extern char *PsGetAttributes(XpContextPtr pCon, XPAttributes pool); +extern char *PsGetOneAttribute(XpContextPtr pCon, XPAttributes pool, + char *attr); +extern int PsAugmentAttributes(XpContextPtr pCon, XPAttributes pool, + char *attrs); +extern int PsSetAttributes(XpContextPtr pCon, XPAttributes pool, char *attrs); + +/* + * Functions in PsColor.c + */ + +extern Bool PsCreateColormap(ColormapPtr pColor); +extern void PsDestroyColormap(ColormapPtr pColor); +extern void PsInstallColormap(ColormapPtr pColor); +extern void PsUninstallColormap(ColormapPtr pColor); +extern int PsListInstalledColormaps(ScreenPtr pScreen, XID *pCmapList); +extern void PsStoreColors(ColormapPtr pColor, int ndef, xColorItem *pdefs); +extern void PsResolveColor(unsigned short *pRed, unsigned short *pGreen, + unsigned short *pBlue, VisualPtr pVisual); +extern int PsGetPixelColor(ColormapPtr cMap, int pixval); +extern void PsSetFillColor(DrawablePtr pDrawable, GCPtr pGC, PsOutPtr psOut, + ColormapPtr cMap); + +/* + * Functions in PsPixmap.c + */ + +extern PixmapPtr PsCreatePixmap(ScreenPtr pScreen, int width, int height, + int depth); +extern Bool PsDestroyPixmap(PixmapPtr pPixmap); +extern DisplayListPtr PsGetFreeDisplayBlock(PsPixmapPrivPtr priv); +extern void PsReplayPixmap(PixmapPtr pix, DrawablePtr pDrawable); +extern int PsCloneDisplayElm(PixmapPtr dst, + DisplayElmPtr elm, DisplayElmPtr newElm, + int xoff, int yoff); +extern void PsCopyDisplayList(PixmapPtr src, PixmapPtr dst, int xoff, + int yoff, int x, int y, int w, int h); +extern PsElmPtr PsCreateFillElementList(PixmapPtr pix, int *nElms); +extern PsElmPtr PsCloneFillElementList(int nElms, PsElmPtr elms); +extern void PsDestroyFillElementList(int nElms, PsElmPtr elms); + +#endif /* _PS_H_ */ diff --git a/Xprint/ps/PsArc.c b/Xprint/ps/PsArc.c new file mode 100644 index 000000000..76804bb18 --- /dev/null +++ b/Xprint/ps/PsArc.c @@ -0,0 +1,178 @@ +/* $Xorg: PsArc.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsArc.c +** * +** * Contents: Arc-drawing code for the PS DDX driver +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include + +#include "Ps.h" +#include "gcstruct.h" +#include "windowstr.h" + +void +PsPolyArc( + DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = PolyArcCmd; + elm->gc = gc; + elm->c.arcs.nArcs = nArcs; + elm->c.arcs.pArcs = (xArc *)xalloc(nArcs*sizeof(xArc)); + memcpy(elm->c.arcs.pArcs, pArcs, nArcs*sizeof(xArc)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + PsLineAttrs(psOut, pGC, cMap); + for( i=0 ; itype==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = PolyFillArcCmd; + elm->gc = gc; + elm->c.arcs.nArcs = nArcs; + elm->c.arcs.pArcs = (xArc *)xalloc(nArcs*sizeof(xArc)); + memcpy(elm->c.arcs.pArcs, pArcs, nArcs*sizeof(xArc)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + PsArcEnum styl; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsSetFillColor(pDrawable, pGC, psOut, cMap); + PsLineAttrs(psOut, pGC, cMap); + if( pGC->arcMode==ArcChord ) styl = PsChord; + else styl = PsPieSlice; + for( i=0 ; itype==DRAWABLE_PIXMAP ) + { + int size = PixmapBytePad(w, depth)*h; + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + elm = &disp->elms[disp->nelms]; + elm->type = PutImageCmd; + elm->gc = gc; + elm->c.image.depth = depth; + elm->c.image.x = x; + elm->c.image.y = y; + elm->c.image.w = w; + elm->c.image.h = h; + elm->c.image.leftPad = leftPad; + elm->c.image.format = format; + elm->c.image.res = imageRes; + elm->c.image.pData = (char *)xalloc(size); + memcpy(elm->c.image.pData, pImage, size); + disp->nelms += 1; + } + else + { + int i, j; + int r, c; + int swap; + char *pt; + PsOutPtr psOut; + ColormapPtr cMap; + int pageRes, sw, sh; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + if (!imageRes) { + sw = w; + sh = h; + } else { + pageRes = XpGetResolution(XpGetPrintContext(requestingClient)); + sw = (float)w * (float)pageRes / (float)imageRes + 0.5; + sh = (float)h * (float)pageRes / (float)imageRes + 0.5; + } + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + pt = (char *)(&i); i = 1; if( pt[0]=='\001' ) swap = 1; else swap = 0; + + if( depth==24 ) + { + PsOut_BeginImage(psOut, 0, 0, x, y, w, h, sw, sh, 3); + if( format==XYPixmap ) + { + int rowsiz = PixmapBytePad(w, depth); + char *planes[3]; + planes[0] = pImage; + planes[1] = &pImage[rowsiz*h]; + planes[2] = &pImage[rowsiz*h*2]; + for( r=0 ; rbgPixel), + PsGetPixelColor(cMap, pGC->fgPixel), + x, y, w, h, sw, sh, 1); + for( r=0 ; r>j)&1)<<(7-j)); } + else + iv_ = iv; + c = iv_; + PsOut_OutImageBytes(psOut, 1, &c); + } + } + PsOut_EndImage(psOut); + } + } + } +error: + return; +} + +void +PsPutScaledImageIM(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, int imageRes, char *pImage) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + int size = PixmapBytePad(w, depth)*h; + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + elm = &disp->elms[disp->nelms]; + elm->type = PutImageCmd; + elm->gc = gc; + elm->c.image.depth = depth; + elm->c.image.x = x; + elm->c.image.y = y; + elm->c.image.w = w; + elm->c.image.h = h; + elm->c.image.leftPad = leftPad; + elm->c.image.format = format; + elm->c.image.res = imageRes; + elm->c.image.pData = (char *)xalloc(size); + memcpy(elm->c.image.pData, pImage, size); + disp->nelms += 1; + } + else + { + int i, j; + int r, c; + int swap; + char *pt; + PsOutPtr psOut; + ColormapPtr cMap; + int pageRes, sw, sh; +#ifdef BM_CACHE + long cache_id = 0; +#endif + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + if (!imageRes) { + sw = w; + sh = h; + } else { + pageRes = XpGetResolution(XpGetPrintContext(requestingClient)); + sw = (float)w * (float)pageRes / (float)imageRes + 0.5; + sh = (float)h * (float)pageRes / (float)imageRes + 0.5; + } + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + pt = (char *)(&i); i = 1; if( pt[0]=='\001' ) swap = 1; else swap = 0; + +#ifdef BM_CACHE + cache_id = PsBmIsImageCached(w, h, pImage); + + if(!cache_id) + { + cache_id = PsBmPutImageInCache(w, h, pImage); + + if(!cache_id) + return; + + PsOut_BeginImageCache(psOut, cache_id); +#endif + if( depth==24 ) + { + PsOut_BeginImageIM(psOut, 0, 0, x, y, w, h, sw, sh, 3); + if( format==XYPixmap ) + { + int rowsiz = PixmapBytePad(w, depth); + char *planes[3]; + planes[0] = pImage; + planes[1] = &pImage[rowsiz*h]; + planes[2] = &pImage[rowsiz*h*2]; + for( r=0 ; rbgPixel), + PsGetPixelColor(cMap, pGC->fgPixel), + x, y, w, h, sw, sh, 1); + for( r=0 ; r>j)&1)<<(7-j)); } + else + iv_ = iv; + c = iv_; + PsOut_OutImageBytes(psOut, 1, &c); + } + } + PsOut_EndImage(psOut); + } + } +#ifdef BM_CACHE + PsOut_EndImageCache(psOut); + } + PsOut_ImageCache(psOut, x, y, cache_id, PsGetPixelColor(cMap, pGC->bgPixel), + PsGetPixelColor(cMap, pGC->fgPixel)); +#endif + } +error: + return; +} +void +PsPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char *pImage) +{ + XpContextPtr pcon; + if (requestingClient && (pcon = XpGetPrintContext(requestingClient))) + PsPutScaledImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, + pcon->imageRes, pImage); +} +void +PsPutImageMask(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char *pImage) +{ + XpContextPtr pcon; + if (requestingClient && (pcon = XpGetPrintContext(requestingClient))) + PsPutScaledImageIM(pDrawable, pGC, depth, x, y, w, h, leftPad, format, + pcon->imageRes, pImage); +} + +RegionPtr +PsCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, + int width, int height, int dstx, int dsty) +{ + PixmapPtr src = (PixmapPtr)pSrc; + PixmapPtr dst = (PixmapPtr)pDst; + + if( pSrc->type!=DRAWABLE_PIXMAP ) return NULL; + if( pDst->type!=DRAWABLE_PIXMAP ) + { + PsOutPtr psOut; + ColormapPtr cMap; + if( PsUpdateDrawableGC(pGC, pDst, &psOut, &cMap)==FALSE ) return NULL; + PsOut_Offset(psOut, pDst->x, pDst->y); + PsOut_BeginFrame(psOut, dstx-srcx, dsty-srcy, dstx, dsty, width, height); + PsReplayPixmap(src, pDst); + PsOut_EndFrame(psOut); + } + else PsCopyDisplayList(src, dst, dstx-srcx, dsty-srcy, dstx, dsty, + width, height); + return NULL; +} + +RegionPtr +PsCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, + int width, int height, int dstx, int dsty, unsigned long plane) +{ + PixmapPtr src = (PixmapPtr)pSrc; + PixmapPtr dst = (PixmapPtr)pDst; + + if( pSrc->type!=DRAWABLE_PIXMAP ) return NULL; + if( pDst->type!=DRAWABLE_PIXMAP ) + { + PsOutPtr psOut; + ColormapPtr cMap; + if( PsUpdateDrawableGC(pGC, pDst, &psOut, &cMap)==FALSE ) return NULL; + PsOut_Offset(psOut, pDst->x, pDst->y); + PsOut_BeginFrame(psOut, dstx-srcx, dsty-srcy, dstx, dsty, width, height); + PsReplayPixmap(src, pDst); + PsOut_EndFrame(psOut); + } + else PsCopyDisplayList(src, dst, dstx-srcx, dsty-srcy, dstx, dsty, + width, height); + return NULL; +} diff --git a/Xprint/ps/PsAttVal.c b/Xprint/ps/PsAttVal.c new file mode 100644 index 000000000..83133e53a --- /dev/null +++ b/Xprint/ps/PsAttVal.c @@ -0,0 +1,202 @@ +/* + * $Xorg: PsAttVal.c,v 1.5 2001/03/13 18:45:31 pookie Exp $ + */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ + +#include "Ps.h" +#include "AttrValid.h" + +/* + * define valid values and defaults for Printer pool + */ +static XpOid ValidContentOrientationsOids[] = { + xpoid_val_content_orientation_portrait, + xpoid_val_content_orientation_landscape, + xpoid_val_content_orientation_reverse_portrait, + xpoid_val_content_orientation_reverse_landscape +}; +static XpOidList ValidContentOrientations = { + ValidContentOrientationsOids, XpNumber(ValidContentOrientationsOids) +}; + +static XpOid DefaultContentOrientationsOids[] = { + xpoid_val_content_orientation_portrait, + xpoid_val_content_orientation_landscape +}; +static XpOidList DefaultContentOrientations = { + DefaultContentOrientationsOids, XpNumber(DefaultContentOrientationsOids) +}; + +static XpOid ValidPlexesOids[] = { + xpoid_val_plex_simplex, xpoid_val_plex_duplex, xpoid_val_plex_tumble +}; +static XpOidList ValidPlexes = { + ValidPlexesOids, XpNumber(ValidPlexesOids) +}; + +static XpOid DefaultPlexesOids[] = { + xpoid_val_plex_simplex +}; +static XpOidList DefaultPlexes = { + DefaultPlexesOids, XpNumber(DefaultPlexesOids) +}; + +static unsigned long ValidPrinterResolutionsCards[] = { + 300, + 600, + 720, + 940, + 1200, + 1440, + 2400 +}; +static XpOidCardList ValidPrinterResolutions = { + ValidPrinterResolutionsCards, XpNumber(ValidPrinterResolutionsCards) +}; + +static unsigned long DefaultPrinterResolutionsCards[] = { + 300 +}; +static XpOidCardList DefaultPrinterResolutions = { + DefaultPrinterResolutionsCards, XpNumber(DefaultPrinterResolutionsCards) +}; + +static XpOid ValidListfontsModesOids[] = { + xpoid_val_xp_list_internal_printer_fonts, xpoid_val_xp_list_glyph_fonts +}; +static XpOidList ValidListfontsModes = { + ValidListfontsModesOids, XpNumber(ValidListfontsModesOids) +}; + +static XpOid DefaultListfontsModesOids[] = { + xpoid_val_xp_list_glyph_fonts +}; +static XpOidList DefaultListfontsModes = { + DefaultListfontsModesOids, XpNumber(DefaultListfontsModesOids) +}; + +static XpOid ValidSetupProvisoOids[] = { + xpoid_val_xp_setup_mandatory, xpoid_val_xp_setup_optional +}; +static XpOidList ValidSetupProviso = { + + + ValidSetupProvisoOids, XpNumber(ValidSetupProvisoOids) +}; + +static XpOidDocFmt ValidDocFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } +}; +static XpOidDocFmtList ValidDocFormatsSupported = { + ValidDocFormatsSupportedFmts, XpNumber(ValidDocFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultDocFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } +}; +static XpOidDocFmtList DefaultDocFormatsSupported = { + DefaultDocFormatsSupportedFmts, XpNumber(DefaultDocFormatsSupportedFmts) +}; + +static XpOidDocFmt ValidEmbeddedFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } +}; +static XpOidDocFmtList ValidEmbeddedFormatsSupported = { + ValidEmbeddedFormatsSupportedFmts, XpNumber(ValidEmbeddedFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultEmbeddedFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } +}; +static XpOidDocFmtList DefaultEmbeddedFormatsSupported = { + DefaultEmbeddedFormatsSupportedFmts, XpNumber(DefaultEmbeddedFormatsSupportedFmts) +}; + +static XpOidDocFmt ValidRawFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } + +}; +static XpOidDocFmtList ValidRawFormatsSupported = { + ValidRawFormatsSupportedFmts, XpNumber(ValidRawFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultRawFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } +}; +static XpOidDocFmtList DefaultRawFormatsSupported = { + DefaultRawFormatsSupportedFmts, XpNumber(DefaultRawFormatsSupportedFmts) +}; + +static XpOid ValidInputTraysOids[] = { + xpoid_val_input_tray_manual, + xpoid_val_input_tray_main, + xpoid_val_input_tray_envelope, + xpoid_val_input_tray_large_capacity, + xpoid_val_input_tray_bottom +}; +static XpOidList ValidInputTrays = { + ValidInputTraysOids, XpNumber(ValidInputTraysOids) +}; + +static XpOid ValidMediumSizesOids[] = { + xpoid_val_medium_size_iso_a4, + xpoid_val_medium_size_na_letter, + xpoid_val_medium_size_na_legal, + xpoid_val_medium_size_executive, + xpoid_val_medium_size_iso_designated_long, + xpoid_val_medium_size_na_number_10_envelope +}; +static XpOidList ValidMediumSizes = { + ValidMediumSizesOids, XpNumber(ValidMediumSizesOids) +}; + +static XpOidDocFmt DefaultDocumentFormat = { + "Postscript", "2", NULL +}; + + +/* + * init struct for XpValidate*Pool + */ +XpValidatePoolsRec PsValidatePoolsRec = { + &ValidContentOrientations, &DefaultContentOrientations, + &ValidDocFormatsSupported, &DefaultDocFormatsSupported, + &ValidInputTrays, &ValidMediumSizes, + &ValidPlexes, &DefaultPlexes, + &ValidPrinterResolutions, &DefaultPrinterResolutions, + &ValidEmbeddedFormatsSupported, &DefaultEmbeddedFormatsSupported, + &ValidListfontsModes, &DefaultListfontsModes, + &ValidRawFormatsSupported, &DefaultRawFormatsSupported, + &ValidSetupProviso, + &DefaultDocumentFormat +}; diff --git a/Xprint/ps/PsAttr.c b/Xprint/ps/PsAttr.c new file mode 100644 index 000000000..8a5bee9e3 --- /dev/null +++ b/Xprint/ps/PsAttr.c @@ -0,0 +1,113 @@ +/* $Xorg: PsAttr.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsAttr.c +** * +** * Contents: Attribute-handling functions for the PS driver +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include "Ps.h" +#include "attributes.h" + +char * +PsGetAttributes( + XpContextPtr pCon, + XPAttributes pool) +{ + return XpGetAttributes(pCon, pool); +} + +char * +PsGetOneAttribute( + XpContextPtr pCon, + XPAttributes pool, + char *attr) +{ + return XpGetOneAttribute(pCon, pool, attr); +} + +int +PsAugmentAttributes( + XpContextPtr pCon, + XPAttributes pool, + char *attrs) +{ + return XpAugmentAttributes(pCon, pool, attrs); +} + +int +PsSetAttributes( + XpContextPtr pCon, + XPAttributes pool, + char *attrs) +{ + return XpSetAttributes(pCon, pool, attrs); +} diff --git a/Xprint/ps/PsCache.c b/Xprint/ps/PsCache.c new file mode 100644 index 000000000..8c9f4a926 --- /dev/null +++ b/Xprint/ps/PsCache.c @@ -0,0 +1,324 @@ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996, 2000 Sun Microsystems, Inc. All Rights Reserved. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsCache.c +** * +** * Contents: Character-caching routines +** * +** * Created By: Jay Hobson (Sun MicroSystems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include "Ps.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "fntfil.h" +#include "fntfilst.h" + +#define GET 0 +#define RESET 1 + +struct bm_cache_list { + struct bm_cache_list *next; + struct bm_cache_list *prev; + int height; + long id; + char *pBuffer; +}; + +struct bm_cache_head { + struct bm_cache_list *head; + int width; + struct bm_cache_head *next; + struct bm_cache_head *prev; +}; + +static struct bm_cache_head *bm_cache = NULL; + +static long +PsBmUniqueId(int func) +{ + static long unique_id = 0; + + if(func == RESET) + { + unique_id = 0; + return 0; + } + else + return ++unique_id; +} + +int +PsBmIsImageCached( + int gWidth, + int gHeight, + char *pBuffer) +{ + int return_val = 0; + struct bm_cache_head *pList = bm_cache; + + while(pList != NULL && !return_val) + { + if(pList->width == gWidth) + { + struct bm_cache_list *pItem = pList->head; + + while(pItem != NULL) + { + if(pItem->height == gHeight) + { + int length = 4*(gWidth/32+(gWidth%32!=0))*gHeight; + + if(!memcmp(pItem->pBuffer, pBuffer, sizeof(char)*length)) + { + return_val = pItem->id; + break; + } + } + else if(pItem->height > gHeight) + break; + + pItem = pItem->next; + } + } + else if(pList->width > gWidth) + break; + + pList = pList->next; + } + return return_val; +} + +int +PsBmPutImageInCache( + int gWidth, + int gHeight, + char *pBuffer) +{ + int return_val = 0; + struct bm_cache_head *pList = bm_cache; + struct bm_cache_list *pNew; + int length = 4*(gWidth/32+(gWidth%32!=0))*gHeight; + + if(gWidth == 1 && gHeight == 1 && pBuffer[0] == 0) + return return_val; + + pNew = (struct bm_cache_list *)malloc(sizeof(struct bm_cache_list)); + pNew->next = NULL; + pNew->prev = NULL; + pNew->height = gHeight; + pNew->id = PsBmUniqueId(GET); + pNew->pBuffer = (char *)malloc(sizeof(char)*length); + + memcpy(pNew->pBuffer, pBuffer, length); + + while(pList != NULL) + { + if(pList->width == gWidth) + { + struct bm_cache_list *pItem = pList->head; + + while(pItem != NULL) + { + if(pItem->height >= gHeight) + { + pNew->next = pItem; + pNew->prev = pItem->prev; + if(pItem->prev != NULL) + pItem->prev->next = pNew; + else + pList->head = pNew; + pItem->prev = pNew; + + return_val = pNew->id; + + break; + } + else if(pItem->next == NULL) + { + pNew->prev = pItem; + pItem->next = pNew; + + return_val = pNew->id; + + break; + } + + pItem = pItem->next; + } + + break; + } + + pList = pList->next; + } + + if(pList == NULL) + { + struct bm_cache_head *pNewList; + + pNewList = (struct bm_cache_head *)malloc(sizeof(struct bm_cache_head)); + + pNewList->next = NULL; + pNewList->prev = NULL; + pNewList->width = gWidth; + pNewList->head = pNew; + + if(bm_cache == NULL) + { + bm_cache = pNewList; + return_val = pNew->id; + } + else + { + pList = bm_cache; + + while(pList != NULL) + { + if(pList->width > gWidth) + { + pNewList->next = pList; + pNewList->prev = pList->prev; + + if(pList->prev != NULL) + pList->prev->next = pNewList; + else + bm_cache = pNewList; + pList->prev = pNewList; + + return_val = pNew->id; + + break; + } + else if(pList->next == NULL) + { + pNewList->prev = pList; + pList->next = pNewList; + + return_val = pNew->id; + + break; + } + + pList = pList->next; + } + } + } + + return return_val; +} + + +static void +PsBmClearImageCacheItem( + struct bm_cache_list *pItem) +{ + if(pItem != NULL) + { + if(pItem->pBuffer != NULL) + free(pItem->pBuffer); + pItem->pBuffer = NULL; + + if(pItem->next) + PsBmClearImageCacheItem(pItem->next); + pItem->next = NULL; + + free(pItem); + pItem = NULL; + } +} + +static void +PsBmClearImageCacheList( + struct bm_cache_head *pList) +{ + if(pList != NULL) + { + if(pList->head) + PsBmClearImageCacheItem(pList->head); + pList->head = NULL; + + if(pList->next) + PsBmClearImageCacheList(pList->next); + pList->next = NULL; + + free(pList); + pList = NULL; + } +} + +void +PsBmClearImageCache() +{ + PsBmClearImageCacheList(bm_cache); + + bm_cache = NULL; + + PsBmUniqueId(RESET); +} + diff --git a/Xprint/ps/PsColor.c b/Xprint/ps/PsColor.c new file mode 100644 index 000000000..9c76904d6 --- /dev/null +++ b/Xprint/ps/PsColor.c @@ -0,0 +1,223 @@ +/* $Xorg: PsColor.c,v 1.4 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsColor.c +** * +** * Contents: Color routines for the PS driver +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include "Ps.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "colormapst.h" + +Bool +PsCreateColormap(ColormapPtr pColor) +{ + int i; + unsigned short rgb; + VisualPtr pVisual = pColor->pVisual; + Pixel pix; + + if( pVisual->class==TrueColor ) + { + for( i=0 ; iColormapEntries ; i++ ) + { + rgb = (i<<8)|i; + + pColor->red[i].fShared = FALSE; + pColor->red[i].co.local.red = rgb; + pColor->red[i].co.local.green = 0; + pColor->red[i].co.local.blue = 0; + + pColor->green[i].fShared = FALSE; + pColor->green[i].co.local.red = 0; + pColor->green[i].co.local.green = rgb; + pColor->green[i].co.local.blue = 0; + + pColor->blue[i].fShared = FALSE; + pColor->blue[i].co.local.red = 0; + pColor->blue[i].co.local.green = 0; + pColor->blue[i].co.local.blue = rgb; + } + } + return TRUE; +} + +void +PsDestroyColormap(ColormapPtr pColor) +{ +} + +void +PsInstallColormap(ColormapPtr pColor) +{ + PsScreenPrivPtr pPriv = + (PsScreenPrivPtr)pColor->pScreen->devPrivates[PsScreenPrivateIndex].ptr; + pPriv->CMap = pColor; +} + +void +PsUninstallColormap(ColormapPtr pColor) +{ +} + +int +PsListInstalledColormaps( + ScreenPtr pScreen, + XID *pCmapList) +{ + return 0; +} + +void +PsStoreColors( + ColormapPtr pColor, + int ndef, + xColorItem *pdefs) +{ + int i; + for( i=0 ; ired[pdefs[i].pixel].co.local.red = pdefs[i].red; + if( pdefs[i].flags&DoGreen ) + pColor->red[pdefs[i].pixel].co.local.green = pdefs[i].green; + if( pdefs[i].flags&DoBlue ) + pColor->red[pdefs[i].pixel].co.local.blue = pdefs[i].blue; + } +} + +void +PsResolveColor( + unsigned short *pRed, + unsigned short *pGreen, + unsigned short *pBlue, + VisualPtr pVisual) +{ +} + +int +PsGetPixelColor(ColormapPtr cMap, int pixval) +{ + int r, g, b; + if( cMap->pVisual->class==TrueColor ) return(pixval); + if( pixval<0 || pixval>255 ) return(0); + r = cMap->red[pixval].co.local.red>>8; + g = cMap->red[pixval].co.local.green>>8; + b = cMap->red[pixval].co.local.blue>>8; + return((r<<16)|(g<<8)|b); +} + +void +PsSetFillColor(DrawablePtr pDrawable, GCPtr pGC, PsOutPtr psOut, + ColormapPtr cMap) +{ + switch(pGC->fillStyle) + { + case FillSolid: + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + break; + case FillTiled: + if( !PsOut_BeginPattern(psOut, pGC->tile.pixmap, + pGC->tile.pixmap->drawable.width, + pGC->tile.pixmap->drawable.height, PsTile, 0, 0) ) + { + PsReplayPixmap(pGC->tile.pixmap, pDrawable); + PsOut_EndPattern(psOut); + } + PsOut_SetPattern(psOut, pGC->tile.pixmap, PsTile); + break; + case FillStippled: + if( !PsOut_BeginPattern(psOut, pGC->stipple, + pGC->stipple->drawable.width, + pGC->stipple->drawable.height, PsStip, 0, + PsGetPixelColor(cMap, pGC->fgPixel)) ) + { + PsReplayPixmap(pGC->stipple, pDrawable); + PsOut_EndPattern(psOut); + } + PsOut_SetPattern(psOut, pGC->stipple, PsStip); + break; + case FillOpaqueStippled: + if( !PsOut_BeginPattern(psOut, pGC->stipple, + pGC->stipple->drawable.width, + pGC->stipple->drawable.height, PsOpStip, + PsGetPixelColor(cMap, pGC->bgPixel), + PsGetPixelColor(cMap, pGC->fgPixel)) ) + { + PsReplayPixmap(pGC->stipple, pDrawable); + PsOut_EndPattern(psOut); + } + PsOut_SetPattern(psOut, pGC->stipple, PsOpStip); + break; + } +} diff --git a/Xprint/ps/PsDef.h b/Xprint/ps/PsDef.h new file mode 100644 index 000000000..ec648c442 --- /dev/null +++ b/Xprint/ps/PsDef.h @@ -0,0 +1,93 @@ +/* $Xorg: PsDef.h,v 1.4 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsDef.h +** * +** * Contents: extran defines and includes for the Ps driver +** * for a printing X server. +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ +#ifndef _PSDEF_H_ +#define _PSDEF_H_ + +#define DT_PRINT_JOB_HEADER "DT_PRINT_JOB_HEADER" +#define DT_PRINT_JOB_TRAILER "DT_PRINT_JOB_TRAILER" +#define DT_PRINT_JOB_COMMAND "DT_PRINT_JOB_COMMAND" +#define DT_PRINT_JOB_EXEC_COMMAND "DT_PRINT_JOB_EXEC_COMMAND" +#define DT_PRINT_JOB_EXEC_OPTIONS "DT_PRINT_JOB_EXEC_OPTION" +#define DT_PRINT_PAGE_HEADER "DT_PRINT_PAGE_HEADER" +#define DT_PRINT_PAGE_TRAILER "DT_PRINT_PAGE_TRAILER" +#define DT_PRINT_PAGE_COMMAND "DT_PRINT_PAGE_COMMAND" + +#define DT_IN_FILE_STRING "%(InFile)%" +#define DT_OUT_FILE_STRING "%(OutFile)%" +#define DT_ALLOWED_COMMANDS_FILE "printCommands" + +#endif /* _PSDEF_H_ */ diff --git a/Xprint/ps/PsFonts.c b/Xprint/ps/PsFonts.c new file mode 100644 index 000000000..1a4692692 --- /dev/null +++ b/Xprint/ps/PsFonts.c @@ -0,0 +1,185 @@ +/* $Xorg: PsFonts.c,v 1.6 2001/03/06 16:30:15 pookie Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsFonts.c +** * +** * Contents: Font code for PS driver. +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include "miscstruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "fontxlfd.h" + +#include "Ps.h" + +Bool +PsRealizeFont( + ScreenPtr pscr, + FontPtr pFont) +{ + return TRUE; +} + +Bool +PsUnrealizeFont( + ScreenPtr pscr, + FontPtr pFont) +{ + return TRUE; +} + +char * +PsGetFontName(FontPtr pFont) +{ + int i; + int nprops = pFont->info.nprops; + FontPropPtr props = pFont->info.props; + Atom name = MakeAtom("FONT", 4, True); + Atom value = (Atom)0; + + for( i=0 ; iinfo.nprops; + FontPropPtr props = pFont->info.props; + Atom name = MakeAtom("PRINTER_RESIDENT_FONT", 21, True); + Atom value = (Atom)0; + + for( i=0 ; iinfo.nprops; + FontPropPtr props = pFont->info.props; + Atom reg = MakeAtom("CHARSET_REGISTRY", 16, True); + Atom enc = MakeAtom("CHARSET_ENCODING", 16, True); + Atom rv = 0, ev = 0; + char *rp = 0; + char *ep = 0; + + for( i=0 ; iclientClip = NULL; + pGC->clientClipType = CT_NONE; + + pGC->ops = &PsGCOps; + pGC->funcs = &PsGCFuncs; + + pGC->clientClip = (pointer)xalloc(sizeof(PsClipRec)); + memset(pGC->clientClip, 0, sizeof(PsClipRec)); + return TRUE; +} + +static int +PsGetDrawablePrivateStuff( + DrawablePtr pDrawable, + GC *gc, + unsigned long *valid, + PsOutPtr *psOut, + ColormapPtr *cMap) +{ + XpContextPtr pCon; + PsPixmapPrivPtr pPriv; + PsContextPrivPtr cPriv; + PsScreenPrivPtr sPriv; + + switch(pDrawable->type) + { + case DRAWABLE_PIXMAP: + return FALSE; + case DRAWABLE_WINDOW: + pCon = PsGetContextFromWindow((WindowPtr)pDrawable); + if( pCon==NULL ) return FALSE; + else + { + cPriv = pCon->devPrivates[PsContextPrivateIndex].ptr; + sPriv = (PsScreenPrivPtr) + pDrawable->pScreen->devPrivates[PsScreenPrivateIndex].ptr; + *gc = cPriv->lastGC; + *valid = cPriv->validGC; + *psOut = cPriv->pPsOut; + *cMap = sPriv->CMap; + return TRUE; + } + default: + return FALSE; + } +} + +int +PsUpdateDrawableGC( + GCPtr pGC, + DrawablePtr pDrawable, + PsOutPtr *psOut, + ColormapPtr *cMap) +{ + GC dGC; + unsigned long valid; + int i; + PsContextPrivPtr cPriv; + BoxPtr boxes; + + if (!PsGetDrawablePrivateStuff(pDrawable, &dGC, &valid, psOut, cMap)) + return FALSE; + + switch (pDrawable->type) { + + case DRAWABLE_PIXMAP: + /* we don't support pixmaps yet! */ + return FALSE; + break; + case DRAWABLE_WINDOW: + if( pGC ) + { + RegionPtr pReg; + WindowPtr pWin = (WindowPtr)pDrawable; + Bool freeClip; + PsClipPtr clp = (PsClipPtr)pGC->clientClip; + if( clp->outterClips ) + { xfree(clp->outterClips); clp->outterClips = 0; } + clp->nOutterClips = 0; + if( pGC->subWindowMode==IncludeInferiors ) + { + pReg = NotClippedByChildren(pWin); + freeClip = TRUE; + } + else + { + pReg = &pWin->clipList; + freeClip = FALSE; + } + + if( pReg->data ) + { + boxes = (BoxPtr)((char *)pReg->data+sizeof(long)*2); + clp->nOutterClips = pReg->data->numRects; + clp->outterClips = + (PsRectPtr)xalloc(clp->nOutterClips*sizeof(PsRectRec)); + for( i=0 ; inOutterClips ; i++ ) + { + clp->outterClips[i].x = boxes[i].x1; + clp->outterClips[i].y = boxes[i].y1; + clp->outterClips[i].w = (boxes[i].x2-boxes[i].x1)+1; + clp->outterClips[i].h = (boxes[i].y2-boxes[i].y1)+1; + } + } + + if( freeClip ) (*pGC->pScreen->RegionDestroy)(pReg); + PsOut_Offset(*psOut, pDrawable->x, pDrawable->y); + PsOut_Clip(*psOut, pGC->clientClipType, (PsClipPtr)pGC->clientClip); + } + cPriv = ( PsGetContextFromWindow( (WindowPtr)pDrawable ) ) + ->devPrivates[PsContextPrivateIndex].ptr; + break; + } + return TRUE; +} + +void +PsValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + pGC->ops = &PsGCOps; +} + +void +PsChangeGC(GCPtr pGC, unsigned long changes) +{ +} + +void +PsCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ +} + +void +PsDestroyGC(GCPtr pGC) +{ + PsDestroyClip(pGC); + xfree(pGC->clientClip); +} + +void +PsChangeClip(GCPtr pGC, int type, pointer pValue, int nrects) +{ + int i; + PsClipPtr clp = (PsClipPtr)pGC->clientClip; + RegionPtr rgn; + BoxPtr boxes; + xRectangle *rects; + + PsDestroyClip(pGC); + pGC->clientClipType = type; + switch(type) + { + case CT_NONE: break; + case CT_PIXMAP: + clp->elms = PsCreateFillElementList((PixmapPtr)pValue, &clp->nElms); + (*pGC->pScreen->DestroyPixmap)((PixmapPtr)pValue); + break; + case CT_REGION: + rgn = (RegionPtr)pValue; + boxes = (BoxPtr)((char *)rgn->data+sizeof(long)*2); + clp->nRects = rgn->data->numRects; + clp->rects = (PsRectPtr)xalloc(clp->nRects*sizeof(PsRectRec)); + for( i=0 ; inRects ; i++ ) + { + clp->rects[i].x = boxes[i].x1; + clp->rects[i].y = boxes[i].y1; + clp->rects[i].w = (boxes[i].x2-boxes[i].x1)+1; + clp->rects[i].h = (boxes[i].y2-boxes[i].y1)+1; + } + (*pGC->pScreen->RegionDestroy)((RegionPtr)pValue); + break; + case CT_UNSORTED: + case CT_YSORTED: + case CT_YXSORTED: + case CT_YXBANDED: + rects = (xRectangle *)pValue; + clp->nRects = nrects; + clp->rects = (PsRectPtr)xalloc(clp->nRects*sizeof(PsRectRec)); + for( i=0 ; inRects ; i++ ) + { + clp->rects[i].x = rects[i].x; + clp->rects[i].y = rects[i].y; + clp->rects[i].w = rects[i].width; + clp->rects[i].h = rects[i].height; + } + xfree(pValue); + break; + } +} + +void +PsDestroyClip(GCPtr pGC) +{ + PsClipPtr clp = (PsClipPtr)pGC->clientClip; + + if( clp->rects ) xfree(clp->rects); + if( clp->outterClips ) xfree(clp->outterClips); + clp->rects = (PsRectPtr)0; + clp->outterClips = (PsRectPtr)0; + clp->nRects = 0; + clp->nOutterClips = 0; + if( clp->elms ) PsDestroyFillElementList(clp->nElms, clp->elms); + clp->elms = (PsElmPtr)0; + clp->nElms = 0; + pGC->clientClipType = CT_NONE; +} + +void +PsCopyClip(GCPtr pDst, GCPtr pSrc) +{ + PsClipPtr src = (PsClipPtr)pSrc->clientClip; + PsClipPtr dst = (PsClipPtr)pDst->clientClip; + + PsDestroyClip(pDst); + pDst->clientClipType = pSrc->clientClipType; + *dst = *src; + if( src->rects ) + { + dst->rects = (PsRectPtr)xalloc(src->nRects*sizeof(PsRectRec)); + memcpy(dst->rects, src->rects, src->nRects*sizeof(PsRectRec)); + } + if( src->elms ) + dst->elms = PsCloneFillElementList(src->nElms, src->elms); +} + + +GCPtr +PsCreateAndCopyGC(DrawablePtr pDrawable, GCPtr pSrc) +{ + GCPtr pDst; + + if ((pDst = + CreateScratchGC(pDrawable->pScreen, pDrawable->depth)) == NULL) + { + return NULL; + } + + if (CopyGC(pSrc, pDst, + GCFunction | GCPlaneMask | GCForeground | GCBackground | + GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle | + GCFillStyle | GCFillRule | GCTile | GCStipple | + GCTileStipXOrigin | GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCGraphicsExposures | GCClipXOrigin | + GCClipYOrigin | GCClipMask | GCDashOffset | GCDashList | + GCArcMode) != Success) + { + (void)FreeGC(pDst, (GContext)0); + + return NULL; + } + + return pDst; +} + diff --git a/Xprint/ps/PsInit.c b/Xprint/ps/PsInit.c new file mode 100644 index 000000000..72c83448e --- /dev/null +++ b/Xprint/ps/PsInit.c @@ -0,0 +1,413 @@ +/* $Xorg: PsInit.c,v 1.4 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsInit.c +** * +** * Contents: Initialization code of Ps driver for the print server. +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include +#include +#include +#include +#include + +#include "Ps.h" +#include "AttrValid.h" +#include "../../mfb/mfb.h" + +#include "windowstr.h" + +static void AllocatePsPrivates(ScreenPtr pScreen); +static int PsInitContext(XpContextPtr pCon); + +extern Bool _XpBoolNoop(); +extern void _XpVoidNoop(); +extern Bool cfbCreateDefColormap(ScreenPtr pScreen); + +int PsScreenPrivateIndex; +int PsContextPrivateIndex; +int PsPixmapPrivateIndex; +int PsWindowPrivateIndex; +int PsGCPrivateIndex; + +Bool +InitializePsDriver(ndx, pScreen, argc, argv) + int ndx; + ScreenPtr pScreen; + int argc; + char **argv; +{ + int maxXres, maxYres, maxWidth, maxHeight; + int maxRes, maxDim, numBytes; + PsScreenPrivPtr pPriv; + char **printerNames; + int numPrinters; + int nVisuals; + int nDepths; + VisualPtr visuals; + DepthPtr depths; + +/* + * Register this driver's InitContext function with the print + * extension. + */ + XpRegisterInitFunc(pScreen, "XP-POSTSCRIPT", PsInitContext); + +/* + * Create and fill in the devPrivate for the PS driver. + */ + AllocatePsPrivates(pScreen); + + pPriv = (PsScreenPrivPtr)pScreen->devPrivates[PsScreenPrivateIndex].ptr; +/*pPriv->resDB = rmdb;*/ + + pScreen->defColormap = (Colormap) FakeClientID(0); + pScreen->blackPixel = 1; + pScreen->whitePixel = 0; + pScreen->QueryBestSize = (QueryBestSizeProcPtr)PsQueryBestSize; + pScreen->SaveScreen = _XpBoolNoop; + pScreen->GetImage = _XpVoidNoop; + pScreen->GetSpans = _XpVoidNoop; + pScreen->CreateWindow = PsCreateWindow; + pScreen->DestroyWindow = PsDestroyWindow; + pScreen->PositionWindow = PsPositionWindow; + pScreen->ChangeWindowAttributes = PsChangeWindowAttributes; + pScreen->RealizeWindow = PsMapWindow; + pScreen->UnrealizeWindow = PsUnmapWindow; + pScreen->PaintWindowBackground = PsPaintWindow; + pScreen->PaintWindowBorder = PsPaintWindow; + pScreen->CloseScreen = PsCloseScreen; + pScreen->CopyWindow = PsCopyWindow; + /* XXX Hard routine to write! */ + +/* + * These two are going to be VERY different... + */ + pScreen->CreatePixmap = PsCreatePixmap; + pScreen->DestroyPixmap = PsDestroyPixmap; + pScreen->RealizeFont = PsRealizeFont; + pScreen->UnrealizeFont = PsUnrealizeFont; + pScreen->CreateGC = PsCreateGC; + pScreen->CreateColormap = PsCreateColormap; + pScreen->DestroyColormap = PsDestroyColormap; + pScreen->InstallColormap = PsInstallColormap; + pScreen->UninstallColormap = PsUninstallColormap; + pScreen->ListInstalledColormaps = PsListInstalledColormaps; + pScreen->StoreColors = PsStoreColors; + pScreen->ResolveColor = PsResolveColor; + /* Will BitmapToRegion make any difference at all? */ + pScreen->BitmapToRegion = mfbPixmapToRegion; + + nVisuals = 2; + nDepths = 2; + visuals = (VisualPtr)xalloc(nVisuals*sizeof(VisualRec)); + depths = (DepthPtr) xalloc(nDepths*sizeof(DepthRec)); + + visuals[0].vid = FakeClientID(0); + visuals[0].class = TrueColor; + visuals[0].bitsPerRGBValue = 8; + visuals[0].ColormapEntries = 256; + visuals[0].nplanes = 24; + visuals[0].redMask = 0x00FF0000; + visuals[0].greenMask = 0x0000FF00; + visuals[0].blueMask = 0x000000FF; + visuals[0].offsetRed = 16; + visuals[0].offsetGreen = 8; + visuals[0].offsetBlue = 0; + + visuals[1].vid = FakeClientID(0); + visuals[1].class = PseudoColor; + visuals[1].bitsPerRGBValue = 0; + visuals[1].ColormapEntries = 256; + visuals[1].nplanes = 8; + visuals[1].redMask = 0x0; + visuals[1].greenMask = 0x0; + visuals[1].blueMask = 0x0; + visuals[1].offsetRed = 0x0; + visuals[1].offsetGreen = 0x0; + visuals[1].offsetBlue = 0x0; + + depths[0].depth = 24; + depths[0].numVids = 1; + depths[0].vids = &visuals[0].vid; + + depths[1].depth = 8; + depths[1].numVids = 1; + depths[1].vids = &visuals[1].vid; + +/* THE FOLLOWING CAUSES SERVER DEFAULT VISUAL TO BE 24 BIT */ +/* miScreenInit(pScreen, (pointer)0, + pScreen->width, pScreen->height, + pScreen->width / (pScreen->mmWidth / 25.40), + pScreen->height / (pScreen->mmHeight / 25.40), + 0, 24, nDepths, + depths, visuals[1].vid, nVisuals, visuals, (miBSFuncPtr)0); */ + +/* THE FOLLOWING CAUSES SERVER DEFAULT VISUAL TO BE 8 BIT */ + miScreenInit(pScreen, (pointer)0, + pScreen->width, pScreen->height, + (int) (pScreen->width / (pScreen->mmWidth / 25.40)), + (int) (pScreen->height / (pScreen->mmHeight / 25.40)), + 0, 8, nDepths, + depths, visuals[1].vid, nVisuals, visuals, (miBSFuncPtr)0); + + if( cfbCreateDefColormap(pScreen)==FALSE ) return FALSE; + +/*scalingScreenInit(pScreen);*/ + + return TRUE; +} + +static void +AllocatePsPrivates(ScreenPtr pScreen) +{ + static int PsGeneration = -1; + + if(PsGeneration != serverGeneration) + { + PsScreenPrivateIndex = AllocateScreenPrivateIndex(); + + PsWindowPrivateIndex = AllocateWindowPrivateIndex(); + AllocateWindowPrivate(pScreen, PsWindowPrivateIndex, + sizeof(PsWindowPrivRec)); + + PsContextPrivateIndex = XpAllocateContextPrivateIndex(); + XpAllocateContextPrivate(PsContextPrivateIndex, + sizeof(PsContextPrivRec)); + + PsGCPrivateIndex = AllocateGCPrivateIndex(); + AllocateGCPrivate(pScreen, PsGCPrivateIndex, + sizeof(PsGCPrivRec)); + + PsPixmapPrivateIndex = AllocatePixmapPrivateIndex(); + AllocatePixmapPrivate(pScreen, PsPixmapPrivateIndex, + sizeof(PsPixmapPrivRec)); + + PsGeneration = serverGeneration; + } + pScreen->devPrivates[PsScreenPrivateIndex].ptr = + (pointer)xalloc(sizeof(PsScreenPrivRec)); +} + +/* + * PsInitContext + * + * Establish the appropriate values for a PrintContext used with the PS + * driver. + */ + +static char DOC_ATT_SUPP[]="document-attributes-supported"; +static char DOC_ATT_VAL[]="document-format"; +static char JOB_ATT_SUPP[]="job-attributes-supported"; +static char JOB_ATT_VAL[]=""; +static char PAGE_ATT_SUPP[]="xp-page-attributes-supported"; +static char PAGE_ATT_VAL[]="content-orientation default-printer-resolution \ +default-input-tray default-medium plex"; + +static int +PsInitContext(pCon) + XpContextPtr pCon; +{ + XpDriverFuncsPtr pFuncs; + PsContextPrivPtr pConPriv; + char *server, *attrStr; + extern XpValidatePoolsRec PsValidatePoolsRec; + + /* + * Initialize the attribute store for this printer. + */ + XpInitAttributes(pCon); + + /* + * Initialize the function pointers + */ + pFuncs = &(pCon->funcs); + pFuncs->StartJob = PsStartJob; + pFuncs->EndJob = PsEndJob; + pFuncs->StartDoc = PsStartDoc; + pFuncs->EndDoc = PsEndDoc; + pFuncs->StartPage = PsStartPage; + pFuncs->EndPage = PsEndPage; + pFuncs->PutDocumentData = PsDocumentData; + pFuncs->GetDocumentData = PsGetDocumentData; + pFuncs->GetAttributes = (char *(*)())PsGetAttributes; + pFuncs->SetAttributes = (int (*)())PsSetAttributes; + pFuncs->AugmentAttributes = (int (*)())PsAugmentAttributes; + pFuncs->GetOneAttribute = (char *(*)())PsGetOneAttribute; + pFuncs->DestroyContext = PsDestroyContext; + pFuncs->GetMediumDimensions = PsGetMediumDimensions; + pFuncs->GetReproducibleArea = PsGetReproducibleArea; + pFuncs->SetImageResolution = PsSetImageResolution; + + /* + * Set up the context privates + */ + pConPriv = + (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr; + + pConPriv->jobFileName = (char *)NULL; + pConPriv->pJobFile = (FILE *)NULL; + + pConPriv->getDocClient = (ClientPtr)NULL; + pConPriv->getDocBufSize = 0; + + /* + * document-attributes-supported + */ + server = XpGetOneAttribute( pCon, XPServerAttr, DOC_ATT_SUPP ); + if ((attrStr = (char *) xalloc(strlen(server) + + strlen(DOC_ATT_SUPP) + strlen(DOC_ATT_VAL) + + strlen(PAGE_ATT_VAL) + 6)) == NULL) + { + return BadAlloc; + } + sprintf(attrStr, "*%s:\t%s %s %s", + DOC_ATT_SUPP, server, DOC_ATT_VAL, PAGE_ATT_VAL); + XpAugmentAttributes( pCon, XPPrinterAttr, attrStr); + xfree(attrStr); + + /* + * job-attributes-supported + */ + server = XpGetOneAttribute( pCon, XPServerAttr, JOB_ATT_SUPP ); + if ((attrStr = (char *) xalloc(strlen(server) + strlen(JOB_ATT_SUPP) + + strlen(JOB_ATT_VAL) + 4)) == NULL) + { + return BadAlloc; + } + sprintf(attrStr, "*%s:\t%s %s", JOB_ATT_SUPP, server, JOB_ATT_VAL); + XpAugmentAttributes(pCon, XPPrinterAttr, attrStr); + xfree(attrStr); + + /* + * xp-page-attributes-supported + */ + server = XpGetOneAttribute( pCon, XPServerAttr, PAGE_ATT_SUPP ); + if ((attrStr = (char *) xalloc(strlen(server) + strlen(PAGE_ATT_SUPP) + + strlen(PAGE_ATT_VAL) + 4)) == NULL) + { + return BadAlloc; + } + sprintf(attrStr, "*%s:\t%s %s", PAGE_ATT_SUPP, server, PAGE_ATT_VAL); + XpAugmentAttributes(pCon, XPPrinterAttr, attrStr); + xfree(attrStr); + + /* + * Validate the attribute pools + */ + XpValidateAttributePool(pCon, XPPrinterAttr, &PsValidatePoolsRec); + XpValidateAttributePool(pCon, XPDocAttr, &PsValidatePoolsRec); + XpValidateAttributePool(pCon, XPJobAttr, &PsValidatePoolsRec); + XpValidateAttributePool(pCon, XPPageAttr, &PsValidatePoolsRec); + + return Success; +} + +static Bool +PsDestroyContext(pCon) + XpContextPtr pCon; +{ + PsContextPrivPtr pConPriv = + (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr; + + if( pConPriv->pJobFile!=(FILE *)NULL ) + { + fclose(pConPriv->pJobFile); + pConPriv->pJobFile = NULL; + } + if( pConPriv->jobFileName!=(char *)NULL ) + { + unlink(pConPriv->jobFileName); + xfree(pConPriv->jobFileName); + pConPriv->jobFileName = (char *)NULL; + } + +/*### free up visuals/depths ###*/ + + return Success; +} + +XpContextPtr +PsGetContextFromWindow(win) + WindowPtr win; +{ + PsWindowPrivPtr pPriv; + + while( win ) + { + pPriv = (PsWindowPrivPtr)win->devPrivates[PsWindowPrivateIndex].ptr; + if( pPriv->validContext ) return pPriv->context; + win = win->parent; + } + + return NULL; +} diff --git a/Xprint/ps/PsLine.c b/Xprint/ps/PsLine.c new file mode 100644 index 000000000..23e105804 --- /dev/null +++ b/Xprint/ps/PsLine.c @@ -0,0 +1,188 @@ +/* $Xorg: PsLine.c,v 1.4 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsLine.c +** * +** * Contents: Line drawing routines for the PS driver +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include "Ps.h" +#include "gcstruct.h" +#include "windowstr.h" + +void +PsPolyLine( + DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int nPoints, + xPoint *pPoints) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = PolyLineCmd; + elm->gc = gc; + elm->c.polyPts.mode = mode; + elm->c.polyPts.nPoints = nPoints; + elm->c.polyPts.pPoints = (xPoint *)xalloc(nPoints*sizeof(xPoint)); + memcpy(elm->c.polyPts.pPoints, pPoints, nPoints*sizeof(xPoint)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + PsPointPtr pts; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + PsLineAttrs(psOut, pGC, cMap); + pts = (PsPointPtr)xalloc(sizeof(PsPointRec)*nPoints); + if( mode==CoordModeOrigin ) + { + for( i=0 ; itype==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = PolySegmentCmd; + elm->gc = gc; + elm->c.segments.nSegments = nSegments; + elm->c.segments.pSegments = (xSegment *)xalloc(nSegments*sizeof(xSegment)); + memcpy(elm->c.segments.pSegments, pSegments, nSegments*sizeof(xSegment)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + PsPointRec pts[2]; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + PsLineAttrs(psOut, pGC, cMap); + for( i=0 ; i +#include "Ps.h" + +#include "cursor.h" +#include "resource.h" + +#include "windowstr.h" +#include "propertyst.h" + + +/*ARGSUSED*/ +void +PsQueryBestSize( + int type, + short *pwidth, + short *pheight, + ScreenPtr pScreen) +{ + unsigned width, highBit; + + switch(type) + { + case CursorShape: + *pwidth = 0; + *pheight = 0; + break; + case TileShape: + case StippleShape: + width = *pwidth; + if (!width) break; + /* Return the nearest power of two >= what they gave us */ + highBit = 0x80000000; + /* Find the highest 1 bit in the given width */ + while(!(highBit & width)) + highBit >>= 1; + /* If greater than that then return the next power of two */ + if((highBit - 1) & width) + highBit <<= 1; + *pwidth = highBit; + /* height is a don't-care */ + break; + } +} + +/* + * PsGetMediumDimensions is installed in the GetMediumDimensions field + * of each Ps-initialized context. + */ +int +PsGetMediumDimensions(XpContextPtr pCon, CARD16 *width, CARD16 *height) +{ + XpGetMediumDimensions(pCon, width, height); + return Success; +} + +/* + * PsGetReproducibleArea is installed in the GetReproducibleArea field + * of each Ps-initialized context. + */ +int +PsGetReproducibleArea(XpContextPtr pCon, xRectangle *pRect) +{ + XpGetReproductionArea(pCon, pRect); + return Success; +} + +/* + * PsSetImageResolution is installed in the SetImageResolution field + * of each Ps-initialized context. + */ +int +PsSetImageResolution(XpContextPtr pCon, int imageRes, Bool *status) +{ + pCon->imageRes = imageRes; + *status = True; + return Success; +} + +/* + * GetPropString searches the window heirarchy from pWin up looking for + * a property by the name of propName. If found, returns the property's + * value. If not, it returns NULL. + */ +/* +char * +GetPropString( + WindowPtr pWin, + char *propName) +{ + Atom atom; + PropertyPtr pProp = (PropertyPtr)NULL; + char *retVal; + + atom = MakeAtom(propName, strlen(propName), FALSE); + if(atom != BAD_RESOURCE) + { + WindowPtr pPropWin; + int n; +*/ + + /* + * The atom has been defined, but it might only exist as a + * property on an unrelated window. + */ +/* + for(pPropWin = pWin; pPropWin != (WindowPtr)NULL; + pPropWin = pPropWin->parent) + { + for(pProp = (PropertyPtr)(wUserProps(pPropWin)); + pProp != (PropertyPtr)NULL; + pProp = pProp->next) + { + if (pProp->propertyName == atom) + break; + } + if(pProp != (PropertyPtr)NULL) + break; + } + if(pProp == (PropertyPtr)NULL) + return (char *)NULL; + + n = (pProp->format/8) * pProp->size; *//* size (bytes) of prop */ +/* + retVal = (char *)xalloc(n + 1); + (void)memcpy((void *)retVal, (void *)pProp->data, n); + retVal[n] = '\0'; + + return retVal; + } + + return (char *)NULL; +} + +#include + +*/ +/* ARGSUSED */ +/* +static void SigchldHndlr (int dummy) +{ + int status, w; + struct sigaction act; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SigchldHndlr; + + w = wait (&status); + +*/ + /* + * Is this really necessary? + */ +/* + sigaction(SIGCHLD, &act, (struct sigaction *)NULL); +} +*/ + +/* + * SystemCmd provides a wrapper for the 'system' library call. The call + * appears to be sensitive to the handling of SIGCHLD, so this wrapper + * sets the status to SIG_DFL, and then resets the established handler + * after system returns. + */ +/* +int +SystemCmd(char *cmdStr) +{ + int status; + struct sigaction newAct, oldAct; + sigfillset(&newAct.sa_mask); + newAct.sa_flags = 0; + newAct.sa_handler = SIG_DFL; + sigfillset(&oldAct.sa_mask); + oldAct.sa_flags = 0; + oldAct.sa_handler = SigchldHndlr; + +*/ + /* + * get the old handler, and set the action to IGN + */ +/* + sigaction(SIGCHLD, &newAct, &oldAct); + + status = system (cmdStr); + + sigaction(SIGCHLD, &oldAct, (struct sigaction *)NULL); + return status; +} +*/ + +Bool +PsCloseScreen( + int index, + ScreenPtr pScreen) +{ + return TRUE; +} + +void +PsLineAttrs( + PsOutPtr psOut, + GCPtr pGC, + ColormapPtr cMap) +{ + int i; + int nDsh; + int dshOff; + int *dsh; + PsCapEnum cap; + PsJoinEnum join; + + switch(pGC->capStyle) { + case CapButt: cap = PsCButt; break; + case CapRound: cap = PsCRound; break; + case CapProjecting: cap = PsCSquare; break; + default: cap = PsCButt; break; } + switch(pGC->joinStyle) { + case JoinMiter: join = PsJMiter; break; + case JoinRound: join = PsJRound; break; + case JoinBevel: join = PsJBevel; break; + default: join = PsJBevel; break; } + if( pGC->lineStyle==LineSolid ) { nDsh = dshOff = 0; dsh = (int *)0; } + else + { + nDsh = pGC->numInDashList; + dshOff = pGC->dashOffset; + if( !nDsh ) dsh = (int *)0; + else + { + dsh = (int *)xalloc(sizeof(int)*nDsh); + for( i=0 ; idash[i]&0xFF; + } + } + + if( pGC->lineStyle!=LineDoubleDash ) + PsOut_LineAttrs(psOut, (int)pGC->lineWidth, + cap, join, nDsh, dsh, dshOff, -1); + else + PsOut_LineAttrs(psOut, (int)pGC->lineWidth, + cap, join, nDsh, dsh, dshOff, + PsGetPixelColor(cMap, pGC->bgPixel)); + if( nDsh && dsh ) xfree(dsh); +} diff --git a/Xprint/ps/PsPixel.c b/Xprint/ps/PsPixel.c new file mode 100644 index 000000000..c2c360d2e --- /dev/null +++ b/Xprint/ps/PsPixel.c @@ -0,0 +1,153 @@ +/* $Xorg: PsPixel.c,v 1.4 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsPixel.c +** * +** * Contents: Pixel-drawing code for the PS DDX driver +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1995 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include + +#include "windowstr.h" +#include "gcstruct.h" + +#include "Ps.h" + +void +PsPolyPoint( + DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int nPoints, + xPoint *pPoints) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = PolyPointCmd; + elm->gc = gc; + elm->c.polyPts.mode = mode; + elm->c.polyPts.nPoints = nPoints; + elm->c.polyPts.pPoints = (xPoint *)xalloc(nPoints*sizeof(xPoint)); + memcpy(elm->c.polyPts.pPoints, pPoints, nPoints*sizeof(xPoint)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + PsPointPtr pts; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + pts = (PsPointPtr)xalloc(sizeof(PsPointRec)*nPoints); + if( mode==CoordModeOrigin ) + { + for( i=0 ; idrawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth); + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = 0; + pPixmap->refcnt = 1; + + pPixmap->devPrivate.ptr = (PsPixmapPrivPtr)xalloc(sizeof(PsPixmapPrivRec)); + if( !pPixmap->devPrivate.ptr ) + { xfree(pPixmap); return NullPixmap; } + memset(pPixmap->devPrivate.ptr, 0, sizeof(PsPixmapPrivRec)); + return pPixmap; +} + +Bool +PsDestroyPixmap(PixmapPtr pPixmap) +{ + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pPixmap->devPrivate.ptr; + DisplayListPtr disp = priv->dispList; + + if( --pPixmap->refcnt ) return TRUE; + while( disp ) + { + int i; + DisplayListPtr oldDisp = disp; + disp = disp->next; + for( i=0 ; inelms ; i++ ) + { + DisplayElmPtr elm = &oldDisp->elms[i]; + + switch(elm->type) + { + case PolyPointCmd: + case PolyLineCmd: + if( elm->c.polyPts.pPoints ) xfree(elm->c.polyPts.pPoints); + break; + case PolySegmentCmd: + if( elm->c.segments.pSegments ) xfree(elm->c.segments.pSegments); + break; + case PolyRectangleCmd: + if( elm->c.rects.pRects ) xfree(elm->c.rects.pRects); + break; + case FillPolygonCmd: + if( elm->c.polyPts.pPoints ) xfree(elm->c.polyPts.pPoints); + break; + case PolyFillRectCmd: + if( elm->c.rects.pRects ) xfree(elm->c.rects.pRects); + break; + case PolyArcCmd: + if( elm->c.arcs.pArcs ) xfree(elm->c.arcs.pArcs); + break; + case PolyFillArcCmd: + if( elm->c.arcs.pArcs ) xfree(elm->c.arcs.pArcs); + break; + case Text8Cmd: + case TextI8Cmd: + if( elm->c.text8.string ) xfree(elm->c.text8.string); + break; + case Text16Cmd: + case TextI16Cmd: + if( elm->c.text16.string ) xfree(elm->c.text16.string); + break; + case PutImageCmd: + if( elm->c.image.pData ) xfree(elm->c.image.pData); + break; + case BeginFrameCmd: + break; + case EndFrameCmd: + break; + } + + if (elm->type != BeginFrameCmd && elm->type != EndFrameCmd) { + (void) FreeGC(elm->gc, (GContext) 0); + } + } + xfree(oldDisp); + } + xfree(priv); + xfree(pPixmap); + return TRUE; +} + +DisplayListPtr +PsGetFreeDisplayBlock(PsPixmapPrivPtr priv) +{ + DisplayListPtr disp = priv->dispList; + + for(; disp ; disp=disp->next ) + { + if( disp->nelms>=DPY_BLOCKSIZE && disp->next ) continue; + if( disp->nelmsnext = (DisplayListPtr)xalloc(sizeof(DisplayListRec)); + disp->next->next = (DisplayListPtr)0; + disp->next->nelms = 0; + } + disp = (DisplayListPtr)xalloc(sizeof(DisplayListRec)); + disp->next = (DisplayListPtr)0; + disp->nelms = 0; + priv->dispList = disp; + return(disp); +} + +void +PsReplay(DisplayElmPtr elm, DrawablePtr pDrawable) +{ + switch(elm->type) + { + case PolyPointCmd: + PsPolyPoint(pDrawable, elm->gc, elm->c.polyPts.mode, + elm->c.polyPts.nPoints, elm->c.polyPts.pPoints); + break; + case PolyLineCmd: + PsPolyLine(pDrawable, elm->gc, elm->c.polyPts.mode, + elm->c.polyPts.nPoints, elm->c.polyPts.pPoints); + break; + case PolySegmentCmd: + PsPolySegment(pDrawable, elm->gc, elm->c.segments.nSegments, + elm->c.segments.pSegments); + break; + case PolyRectangleCmd: + PsPolyRectangle(pDrawable, elm->gc, elm->c.rects.nRects, + elm->c.rects.pRects); + break; + case FillPolygonCmd: + PsFillPolygon(pDrawable, elm->gc, 0, elm->c.polyPts.mode, + elm->c.polyPts.nPoints, elm->c.polyPts.pPoints); + break; + case PolyFillRectCmd: + PsPolyFillRect(pDrawable, elm->gc, elm->c.rects.nRects, + elm->c.rects.pRects); + break; + case PolyArcCmd: + PsPolyArc(pDrawable, elm->gc, elm->c.arcs.nArcs, elm->c.arcs.pArcs); + break; + case PolyFillArcCmd: + PsPolyFillArc(pDrawable, elm->gc, elm->c.arcs.nArcs, elm->c.arcs.pArcs); + break; + case Text8Cmd: + PsPolyText8(pDrawable, elm->gc, elm->c.text8.x, elm->c.text8.y, + elm->c.text8.count, elm->c.text8.string); + break; + case Text16Cmd: + PsPolyText16(pDrawable, elm->gc, elm->c.text16.x, elm->c.text16.y, + elm->c.text16.count, elm->c.text16.string); + break; + case TextI8Cmd: + PsImageText8(pDrawable, elm->gc, elm->c.text8.x, elm->c.text8.y, + elm->c.text8.count, elm->c.text8.string); + break; + case TextI16Cmd: + PsImageText16(pDrawable, elm->gc, elm->c.text16.x, elm->c.text16.y, + elm->c.text16.count, elm->c.text16.string); + break; + case PutImageCmd: + PsPutScaledImage(pDrawable, elm->gc, elm->c.image.depth, + elm->c.image.x, elm->c.image.y, + elm->c.image.w, elm->c.image.h, elm->c.image.leftPad, + elm->c.image.format, elm->c.image.res, + elm->c.image.pData); + break; + case BeginFrameCmd: + { + PsOutPtr psOut; + ColormapPtr cMap; + if( PsUpdateDrawableGC(NULL, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_BeginFrame(psOut, 0, 0, elm->c.frame.x, elm->c.frame.y, + elm->c.frame.w, elm->c.frame.h); + } + break; + case EndFrameCmd: + { + PsOutPtr psOut; + ColormapPtr cMap; + if( PsUpdateDrawableGC(NULL, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_EndFrame(psOut); + } + break; + } +} + +void +PsReplayPixmap(PixmapPtr pix, DrawablePtr pDrawable) +{ + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp = priv->dispList; + DisplayElmPtr elm; + + for(; disp ; disp=disp->next ) + { + int i; + for( i=0,elm=disp->elms ; inelms ; i++,elm++ ) + PsReplay(elm, pDrawable); + } +} + +int +PsCloneDisplayElm(PixmapPtr dst, DisplayElmPtr elm, DisplayElmPtr newElm, + int xoff, int yoff) +{ + int i; + int size; + int status = 0; + + *newElm = *elm; + + /* I think this is the correct return value */ + if ((newElm->gc = PsCreateAndCopyGC(&dst->drawable, elm->gc)) == NULL) { + return 1; + } + + switch(elm->type) + { + case PolyPointCmd: + case PolyLineCmd: + newElm->c.polyPts.pPoints = + (xPoint *)xalloc(elm->c.polyPts.nPoints*sizeof(xPoint)); + for( i=0 ; ic.polyPts.nPoints ; i++ ) + { + newElm->c.polyPts.pPoints[i].x = elm->c.polyPts.pPoints[i].x+xoff; + newElm->c.polyPts.pPoints[i].y = elm->c.polyPts.pPoints[i].y+yoff; + } + break; + case PolySegmentCmd: + newElm->c.segments.pSegments = + (xSegment *)xalloc(elm->c.segments.nSegments*sizeof(xSegment)); + for( i=0 ; ic.segments.nSegments ; i++ ) + { + newElm->c.segments.pSegments[i].x1 = + elm->c.segments.pSegments[i].x1+xoff; + newElm->c.segments.pSegments[i].y1 = + elm->c.segments.pSegments[i].y1+yoff; + newElm->c.segments.pSegments[i].x2 = + elm->c.segments.pSegments[i].x2+xoff; + newElm->c.segments.pSegments[i].y2 = + elm->c.segments.pSegments[i].y2+yoff; + } + break; + case PolyRectangleCmd: + newElm->c.rects.pRects = + (xRectangle *)xalloc(elm->c.rects.nRects*sizeof(xRectangle)); + for( i=0 ; ic.rects.nRects ; i++ ) + { + newElm->c.rects.pRects[i].x = elm->c.rects.pRects[i].x+xoff; + newElm->c.rects.pRects[i].y = elm->c.rects.pRects[i].y+yoff; + newElm->c.rects.pRects[i].width = elm->c.rects.pRects[i].width; + newElm->c.rects.pRects[i].height = elm->c.rects.pRects[i].height; + } + break; + case FillPolygonCmd: + newElm->c.polyPts.pPoints = + (xPoint *)xalloc(elm->c.polyPts.nPoints*sizeof(xPoint)); + for( i=0 ; ic.polyPts.nPoints ; i++ ) + { + newElm->c.polyPts.pPoints[i].x = elm->c.polyPts.pPoints[i].x+xoff; + newElm->c.polyPts.pPoints[i].y = elm->c.polyPts.pPoints[i].y+yoff; + } + break; + case PolyFillRectCmd: + newElm->c.rects.pRects = + (xRectangle *)xalloc(elm->c.rects.nRects*sizeof(xRectangle)); + for( i=0 ; ic.rects.nRects ; i++ ) + { + newElm->c.rects.pRects[i].x = elm->c.rects.pRects[i].x+xoff; + newElm->c.rects.pRects[i].y = elm->c.rects.pRects[i].y+yoff; + newElm->c.rects.pRects[i].width = elm->c.rects.pRects[i].width; + newElm->c.rects.pRects[i].height = elm->c.rects.pRects[i].height; + } + break; + case PolyArcCmd: + newElm->c.arcs.pArcs = + (xArc *)xalloc(elm->c.arcs.nArcs*sizeof(xArc)); + for( i=0 ; ic.arcs.nArcs ; i++ ) + { + newElm->c.arcs.pArcs[i].x = elm->c.arcs.pArcs[i].x+xoff; + newElm->c.arcs.pArcs[i].y = elm->c.arcs.pArcs[i].y+yoff; + newElm->c.arcs.pArcs[i].width = elm->c.arcs.pArcs[i].width; + newElm->c.arcs.pArcs[i].height = elm->c.arcs.pArcs[i].height; + newElm->c.arcs.pArcs[i].angle1 = elm->c.arcs.pArcs[i].angle1; + newElm->c.arcs.pArcs[i].angle2 = elm->c.arcs.pArcs[i].angle2; + } + break; + case PolyFillArcCmd: + newElm->c.arcs.pArcs = + (xArc *)xalloc(elm->c.arcs.nArcs*sizeof(xArc)); + for( i=0 ; ic.arcs.nArcs ; i++ ) + { + newElm->c.arcs.pArcs[i].x = elm->c.arcs.pArcs[i].x+xoff; + newElm->c.arcs.pArcs[i].y = elm->c.arcs.pArcs[i].y+yoff; + newElm->c.arcs.pArcs[i].width = elm->c.arcs.pArcs[i].width; + newElm->c.arcs.pArcs[i].height = elm->c.arcs.pArcs[i].height; + newElm->c.arcs.pArcs[i].angle1 = elm->c.arcs.pArcs[i].angle1; + newElm->c.arcs.pArcs[i].angle2 = elm->c.arcs.pArcs[i].angle2; + } + break; + case Text8Cmd: + case TextI8Cmd: + newElm->c.text8.string = (char *)xalloc(elm->c.text8.count); + memcpy(newElm->c.text8.string, elm->c.text8.string, elm->c.text8.count); + newElm->c.text8.x += xoff; + newElm->c.text8.y += yoff; + break; + case Text16Cmd: + case TextI16Cmd: + newElm->c.text16.string = + (unsigned short *)xalloc(elm->c.text16.count*sizeof(unsigned short)); + memcpy(newElm->c.text16.string, elm->c.text16.string, + elm->c.text16.count*sizeof(unsigned short)); + newElm->c.text16.x += xoff; + newElm->c.text16.y += yoff; + break; + case PutImageCmd: + size = PixmapBytePad(elm->c.image.w, elm->c.image.depth)*elm->c.image.h; + newElm->c.image.pData = (char *)xalloc(size); + memcpy(newElm->c.image.pData, elm->c.image.pData, size); + newElm->c.image.x += xoff; + newElm->c.image.y += yoff; + break; + case BeginFrameCmd: + case EndFrameCmd: + status = 1; + break; + } + return(status); +} + +void +PsCopyDisplayList(PixmapPtr src, PixmapPtr dst, int xoff, int yoff, + int x, int y, int w, int h) +{ + PsPixmapPrivPtr sPriv = (PsPixmapPrivPtr)src->devPrivate.ptr; + PsPixmapPrivPtr dPriv = (PsPixmapPrivPtr)dst->devPrivate.ptr; + DisplayListPtr sDisp; + DisplayListPtr dDisp = PsGetFreeDisplayBlock(dPriv); + DisplayElmPtr elm = &dDisp->elms[dDisp->nelms]; + + elm->type = BeginFrameCmd; + elm->c.frame.x = x; + elm->c.frame.y = y; + elm->c.frame.w = w; + elm->c.frame.h = h; + dDisp->nelms += 1; + + sDisp = sPriv->dispList; + for(; sDisp ; sDisp=sDisp->next ) + { + int i; + for( i=0,elm=sDisp->elms ; inelms ; i++,elm++ ) + { + dDisp = PsGetFreeDisplayBlock(dPriv); + if (PsCloneDisplayElm(dst, elm, &dDisp->elms[dDisp->nelms], + xoff, yoff)==0) + { + dDisp->nelms += 1; + } + } + } + + dDisp = PsGetFreeDisplayBlock(dPriv); + elm = &dDisp->elms[dDisp->nelms]; + elm->type = EndFrameCmd; + dDisp->nelms += 1; +} + +PsElmPtr +PsCreateFillElementList(PixmapPtr pix, int *nElms) +{ + PsElmPtr elms = (PsElmPtr)0; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp = priv->dispList; + PsArcEnum styl; + + *nElms = 0; + for(; disp ; disp=disp->next ) + { + int i; + DisplayElmPtr elm = disp->elms; + + for( i=0 ; inelms ; i++,elm++ ) + { + if( !elm->gc->fgPixel ) continue; + switch(elm->type) + { + case FillPolygonCmd: + *nElms += 1; + break; + case PolyFillRectCmd: + *nElms += elm->c.rects.nRects; + break; + case PolyFillArcCmd: + *nElms += elm->c.arcs.nArcs; + break; + } + } + } + + if( (*nElms) ) + { + elms = (PsElmPtr)xalloc((*nElms)*sizeof(PsElmRec)); + if( elms ) + { + disp = priv->dispList; + *nElms = 0; + for(; disp ; disp=disp->next ) + { + int i, k; + DisplayElmPtr elm = disp->elms; + + for( i=0 ; inelms ; i++,elm++ ) + { + if( !elm->gc->fgPixel ) continue; + switch(elm->type) + { + case FillPolygonCmd: + elms[*nElms].type = PSOUT_POINTS; + elms[*nElms].nPoints = elm->c.polyPts.nPoints; + elms[*nElms].c.points = + (PsPointPtr)xalloc(elms[*nElms].nPoints*sizeof(PsPointRec)); + for( k=0 ; kc.polyPts.pPoints[k].x; + elms[*nElms].c.points[k].y = elm->c.polyPts.pPoints[k].y; + } + *nElms += 1; + break; + case PolyFillRectCmd: + for( k=0 ; kc.rects.nRects ; k++ ) + { + elms[*nElms].type = PSOUT_RECT; + elms[*nElms].nPoints = 0; + elms[*nElms].c.rect.x = elm->c.rects.pRects[k].x; + elms[*nElms].c.rect.y = elm->c.rects.pRects[k].y; + elms[*nElms].c.rect.w = elm->c.rects.pRects[k].width; + elms[*nElms].c.rect.h = elm->c.rects.pRects[k].height; + *nElms += 1; + } + break; + case PolyFillArcCmd: + if( elm->gc->arcMode==ArcChord ) styl = PsChord; + else styl = PsPieSlice; + for( k=0 ; kc.rects.nRects ; k++ ) + { + elms[*nElms].type = PSOUT_ARC; + elms[*nElms].nPoints = 0; + elms[*nElms].c.arc.x = elm->c.arcs.pArcs[k].x; + elms[*nElms].c.arc.y = elm->c.arcs.pArcs[k].y; + elms[*nElms].c.arc.w = elm->c.arcs.pArcs[k].width; + elms[*nElms].c.arc.h = elm->c.arcs.pArcs[k].height; + elms[*nElms].c.arc.a1 = elm->c.arcs.pArcs[k].angle1; + elms[*nElms].c.arc.a2 = elm->c.arcs.pArcs[k].angle2; + elms[*nElms].c.arc.style = styl; + *nElms += 1; + } + break; + } + } + } + } + } + return(elms); +} + +PsElmPtr +PsCloneFillElementList(int nElms, PsElmPtr elms) +{ + int i; + PsElmPtr newElms; + + newElms = (PsElmPtr)xalloc(nElms*sizeof(PsElmRec)); + if( !newElms ) return(newElms); + for( i=0 ; itype==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = PolyRectangleCmd; + elm->gc = gc; + elm->c.rects.nRects = nRects; + elm->c.rects.pRects = (xRectangle *)xalloc(nRects*sizeof(xRectangle)); + memcpy(elm->c.rects.pRects, pRects, nRects*sizeof(xRectangle)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + PsLineAttrs(psOut, pGC, cMap); + for( i=0 ; itype==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = FillPolygonCmd; + elm->gc = gc; + elm->c.polyPts.mode = mode; + elm->c.polyPts.nPoints = nPoints; + elm->c.polyPts.pPoints = (xPoint *)xalloc(nPoints*sizeof(xPoint)); + memcpy(elm->c.polyPts.pPoints, pPoints, nPoints*sizeof(xPoint)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + PsPointPtr pts; + PsRuleEnum rule; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsSetFillColor(pDrawable, pGC, psOut, cMap); + if( pGC->fillRule==EvenOddRule ) rule = PsEvenOdd; + else rule = PsNZWinding; + PsOut_FillRule(psOut, rule); + pts = (PsPointPtr)xalloc(sizeof(PsPointRec)*nPoints); + if( mode==CoordModeOrigin ) + { + for( i=0 ; itype==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = PolyFillRectCmd; + elm->gc = gc; + elm->c.rects.nRects = nRects; + elm->c.rects.pRects = (xRectangle *)xalloc(nRects*sizeof(xRectangle)); + memcpy(elm->c.rects.pRects, pRects, nRects*sizeof(xRectangle)); + disp->nelms += 1; + } + else + { + int i; + PsOutPtr psOut; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsSetFillColor(pDrawable, pGC, psOut, cMap); + for( i=0 ; i +#include +#include +#include +#include +#include +#include +#include + +#define NEED_EVENTS +#include "Xproto.h" +#undef NEED_EVENTS + +#include "Ps.h" + +#include "windowstr.h" +#include "attributes.h" +#include "Oid.h" + +/* static utility function to get document/page attributes */ +static void +S_GetPageAttributes(XpContextPtr pCon,int *iorient,int *icount, int *iplex, + int *ires, unsigned short *iwd, unsigned short *iht) +{ + char *count; + XpOid orient, plex; + /* + * Get the orientation + */ + orient = XpGetContentOrientation(pCon); + switch (orient) { + case xpoid_val_content_orientation_landscape: + *iorient = 1; + break; + case xpoid_val_content_orientation_reverse_portrait: + *iorient = 2; + break; + case xpoid_val_content_orientation_reverse_landscape: + *iorient = 3; + break; + case xpoid_val_content_orientation_portrait: + default: + *iorient = 0; + break; + } + + /* + * Get the count + */ + count = XpGetOneAttribute(pCon, XPDocAttr, "copy-count"); + if( count ) + { + int ii = sscanf(count, "%d", icount); + if( ii!=1 ) *icount = 1; + } + else *icount = 1; + + /* + * Get the plex + */ + plex = XpGetPlex(pCon); + switch(plex) + { + case xpoid_val_plex_duplex: + *iplex = 1; + break; + case xpoid_val_plex_tumble: + *iplex = 2; + break; + default: + *iplex = 0; + break; + } + + /* + * Get the resolution and media size + */ + *ires = XpGetResolution(pCon); + XpGetMediumDimensions(pCon, iwd, iht); +} + + +int +PsStartJob( + XpContextPtr pCon, + Bool sendClientData, + ClientPtr client) +{ + PsContextPrivPtr pConPriv = + (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr; + + /* + * Create a temporary file to store the printer output. + */ + if (!XpOpenTmpFile("w", &pConPriv->jobFileName, &pConPriv->pJobFile)) + return BadAlloc; + + return Success; +} + + + +/* I thought about making this following code into a set of routines + or using a goto, or something, but in the end decided not to, + because the plain old listing here makes the logic clearer. */ +int +PsEndJob( + XpContextPtr pCon, + Bool cancel) +{ + int r; + struct stat buffer; + int error; + + PsContextPrivPtr priv = + (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr; + + if (cancel == True) { + if (priv->getDocClient != (ClientPtr) NULL) { + (void) XpFinishDocData( priv->getDocClient ); + + priv->getDocClient = NULL; + priv->getDocBufSize = 0; + } + + /* job is cancelled - do we really care if we're out of space? */ + (void) fclose(priv->pJobFile); + priv->pJobFile = NULL; + + unlink(priv->jobFileName); + xfree(priv->jobFileName); + priv->jobFileName = (char *)NULL; + + return Success; + } + + /* + * Append any trailing information here + */ + PsOut_EndFile(priv->pPsOut, 0); + + /* this is where we find out if we're out of space */ + error = (fclose(priv->pJobFile) == EOF); + priv->pJobFile = NULL; + + /* status to the client if we have ran out of space on the disk or + some other resource problem with the temporary file... */ + if (error) { + if (priv->getDocClient != (ClientPtr) NULL) { + (void) XpFinishDocData( priv->getDocClient ); + + priv->getDocClient = NULL; + priv->getDocBufSize = 0; + } + + unlink(priv->jobFileName); + xfree(priv->jobFileName); + priv->jobFileName = (char *)NULL; + + return BadAlloc; + } + + /* we have finished without incident & no cancel */ + + if (priv->getDocClient != NULL && priv->getDocBufSize > 0) { + FILE *file; + + file = fopen(priv->jobFileName, "r"); + if (!file || (fstat(fileno(file), &buffer) < 0)) + r = BadAlloc; + else + r = XpSendDocumentData(priv->getDocClient, file, buffer.st_size, + priv->getDocBufSize); + if (file) + fclose(file); + + (void) XpFinishDocData(priv->getDocClient); + + priv->getDocClient = NULL; + priv->getDocBufSize = 0; + } + else { + XpSubmitJob(priv->jobFileName, pCon); + + r = Success; + } + + unlink(priv->jobFileName); + xfree(priv->jobFileName); + priv->jobFileName = (char *)NULL; + +#ifdef BM_CACHE + PsBmClearImageCache(); +#endif + + return r; +} + +/* StartPage + */ +int +PsStartPage( + XpContextPtr pCon, + WindowPtr pWin) +{ + int iorient, iplex, icount, ires; + unsigned short iwd, iht; + register WindowPtr pChild; + PsContextPrivPtr pConPriv = + (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr; + PsWindowPrivPtr pWinPriv = + (PsWindowPrivPtr)pWin->devPrivates[PsWindowPrivateIndex].ptr; + char s[80]; + xEvent event; + +/* + * Put a pointer to the context in the window private structure + */ + pWinPriv->validContext = 1; + pWinPriv->context = pCon; + + /* get page level attributes */ + S_GetPageAttributes(pCon,&iorient,&icount,&iplex,&ires,&iwd,&iht); + /* + * Start the page + */ + if (pConPriv->pPsOut == NULL) { + pConPriv->pPsOut = PsOut_BeginFile(pConPriv->pJobFile, + iorient, icount, iplex, ires, + (int)iwd, (int)iht, False); + } + PsOut_BeginPage(pConPriv->pPsOut, iorient, icount, iplex, ires, + (int)iwd, (int)iht); + + return Success; +} + + +/* + * EndPage: + * + * Write page trailer to page file + * Write page file to job file + */ +int +PsEndPage( + XpContextPtr pCon, + WindowPtr pWin) +{ + PsWindowPrivPtr pWinPriv = + (PsWindowPrivPtr)pWin->devPrivates[PsWindowPrivateIndex].ptr; + PsContextPrivPtr pConPriv = + (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr; + + PsOut_EndPage(pConPriv->pPsOut); + + pWinPriv->validContext = 0; + pWinPriv->context = NULL; + + /* status to the client if we have ran out of space on the disk or + some other resource problem with the temporary file... */ +/* if (ferror(pConPriv->pJobFile)) return BadAlloc; */ + + return Success; +} + +/* + * The PsStartDoc() and PsEndDoc() functions serve basically as NOOP + * placeholders. This driver doesn't deal with the notion of multiple + * documents per page. + */ + +int +PsStartDoc(XpContextPtr pCon, XPDocumentType type) +{ + int iorient, iplex, icount, ires; + unsigned short iwd, iht; + PsContextPrivPtr pConPriv = + (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr; + + /* get document level attributes */ + S_GetPageAttributes(pCon,&iorient,&icount,&iplex,&ires,&iwd,&iht); + + pConPriv->pPsOut = PsOut_BeginFile(pConPriv->pJobFile, + iorient, icount, iplex, ires, + (int)iwd, (int)iht, (type == XPDocRaw)); + + return Success; +} + +int +PsEndDoc( + XpContextPtr pCon, + Bool cancel) +{ + return Success; +} + +/* + * PsDocumentData() + * + * Hand any pre-generated PDL down to the spool files, formatting it + * as necessary to fit the given window. + */ + +int +PsDocumentData( + XpContextPtr pCon, + DrawablePtr pDraw, + char *pData, + int len_data, + char *pFmt, + int len_fmt, + char *pOpt, + int len_opt, + ClientPtr client) +{ + PsContextPrivPtr cPriv; + PsOutPtr psOut; + + if (len_fmt != 12 || !strcmp(pFmt, "PostScript 2") || len_opt) + return BadValue; + cPriv = pCon->devPrivates[PsContextPrivateIndex].ptr; + psOut = cPriv->pPsOut; + + if (pDraw) + PsOut_BeginFrame(psOut, 0, 0, pDraw->x, pDraw->y, + pDraw->width, pDraw->height); + PsOut_RawData(psOut, pData, len_data); + if (pDraw) + PsOut_EndFrame(psOut); + + return Success; +} + +/* + * + * PsGetDocumentData() + * + * This function allows the driver to send the generated PS back to + * the client. + */ + +int +PsGetDocumentData( + XpContextPtr pCon, + ClientPtr client, + int maxBufferSize) +{ + PsContextPrivPtr pPriv = (PsContextPrivPtr) + pCon->devPrivates[PsContextPrivateIndex].ptr; + + pPriv->getDocClient = client; + pPriv->getDocBufSize = maxBufferSize; + + return Success; +} + diff --git a/Xprint/ps/PsSpans.c b/Xprint/ps/PsSpans.c new file mode 100644 index 000000000..4d8fb3459 --- /dev/null +++ b/Xprint/ps/PsSpans.c @@ -0,0 +1,162 @@ +/* $Xorg: PsSpans.c,v 1.4 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsSpans.c +** * +** * Contents: Code to set and fill spans in the PS DDX +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include "Ps.h" +#include "gcstruct.h" +#include "windowstr.h" + +void +PsFillSpans( + DrawablePtr pDrawable, + GCPtr pGC, + int nSpans, + DDXPointPtr pPoints, + int *pWidths, + int fSorted) +{ + char t[80]; + PsOutPtr psOut; + int xoffset, yoffset; + xRectangle *rects, *r; + RegionPtr fillRegion, region; + int i; + int nbox; + BoxPtr pbox; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + + /* + * Build a region out of the spans + */ + rects = (xRectangle *)xalloc(nSpans*sizeof(xRectangle)); + xoffset = pDrawable->x; + yoffset = pDrawable->y; + + for( i = 0, r = rects; i < nSpans; i++, r++ ) + { + r->x = pPoints[i].x + xoffset; + r->y = pPoints[i].y + yoffset; + r->width = pWidths[i]; + r->height = 1; + } + fillRegion = miRectsToRegion(nSpans, rects, + (fSorted)?CT_YSORTED:CT_UNSORTED); + + /* + * Intersect this region with the clip region. Whatever's left, + * should be filled. + */ +/*miIntersect(region, fillRegion, pGC->clientClip);*/ + + pbox = REGION_RECTS(region); + nbox = REGION_NUM_RECTS(region); + + /* Enter HP-GL/2 */ + /*###SEND_PCL( outFile, "\27%0B" );*/ + + while( nbox ) + { +/*### + sprintf( t, "PU%d,%d;RR%d,%d;", pbox->x1, pbox->y1, pbox->x2, pbox->y2); + SEND_PCL( outFile, t ); +*/ + nbox--; + pbox++; + } + + /* Go back to PCL */ + /*###SEND_PCL( outFile, "\27%0A" );*/ + + /* + * Clean up the temporary regions + */ + miRegionDestroy(fillRegion); + miRegionDestroy(region); + xfree(rects); +} + +void +PsSetSpans( + DrawablePtr pDrawable, + GCPtr pGC, + char *pSrc, + DDXPointPtr pPoints, + int *pWidths, + int nSpans, + int fSorted) +{ +} diff --git a/Xprint/ps/PsText.c b/Xprint/ps/PsText.c new file mode 100644 index 000000000..618d0a163 --- /dev/null +++ b/Xprint/ps/PsText.c @@ -0,0 +1,478 @@ +/* $Xorg: PsText.c,v 1.7 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsText.c +** * +** * Contents: Character-drawing routines for the PS DDX +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include "Ps.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "fntfil.h" +#include "fntfilst.h" +#include + +static int readFontName(char *fileName, char *file_name, char *dlfnam) +{ + FILE *file; + struct stat statb; + int count, i, status; + char buf[256]; + char *front, *end, *fn; + + file = fopen(fileName, "r"); + if(file) + { + if (fstat (fileno(file), &statb) == -1) + return 0; + while(fgets(buf, 255, file)) + { + if((fn = strstr(buf, " -"))) + { + strcpy(file_name, buf); + file_name[fn - buf - 4] = '\0'; + fn++; + if((front = strstr(fn, "normal-"))) + { + fn[front - fn] = '\0'; + if(strstr(dlfnam, fn)) + { + fclose(file); + return 1; + } + } + } + } + } + file_name[0] = '\0'; + fclose(file); + return 0; +} + +int +PsPolyText8( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *string) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return x; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = Text8Cmd; + elm->gc = gc; + elm->c.text8.x = x; + elm->c.text8.y = y; + elm->c.text8.count = count; + elm->c.text8.string = (char *)xalloc(count); + memcpy(elm->c.text8.string, string, count); + disp->nelms += 1; + } + else + { + char *fnam, ffname[512], *dlfnam; + FontDirectoryPtr dir; + char file_name[MAXFONTNAMELEN]; + + dir = pGC->font->fpe->private; + sprintf(ffname, "%s%s", dir->directory, "fonts.dir"); + + fnam = PsGetPSFontName(pGC->font); + if(!fnam){ + if(!(dlfnam = PsGetFontName(pGC->font))) + return x; + /* If Type1 font, try to download to printer first */ + if(strstr(ffname, "Type1") && readFontName(ffname, file_name, dlfnam)) + { + int iso; + int siz; + float mtx[4]; + PsOutPtr psOut; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) + return x; + sprintf(ffname, "%s%s%s", dir->directory, file_name, ".pfa"); + PsOut_DownloadType1(psOut, file_name, ffname); + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + siz = PsGetFontSize(pGC->font, mtx); + iso = PsIsISOLatin1Encoding(pGC->font); + if( !siz ) PsOut_TextAttrsMtx(psOut, file_name, mtx, 1); + else PsOut_TextAttrs(psOut, file_name, siz, 1); + PsOut_Text(psOut, x, y, string, count, -1); + return x; + } + { + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; + + GetGlyphs(pGC->font, (unsigned long)count, + (unsigned char *)string, Linear8Bit,&n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n != 0) + PsPolyGlyphBlt(pDrawable, pGC, x, y, n, + charinfo, FONTGLYPHS(pGC->font)); + x += w; + } + }else{ + int iso; + int siz; + float mtx[4]; + PsOutPtr psOut; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return x; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + siz = PsGetFontSize(pGC->font, mtx); + iso = PsIsISOLatin1Encoding(pGC->font); + if( !siz ) PsOut_TextAttrsMtx(psOut, fnam, mtx, iso); + else PsOut_TextAttrs(psOut, fnam, siz, iso); + PsOut_Text(psOut, x, y, string, count, -1); + } + } + return x; +} + +int +PsPolyText16( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *string) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return x; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = Text16Cmd; + elm->gc = gc; + elm->c.text16.x = x; + elm->c.text16.y = y; + elm->c.text16.count = count; + elm->c.text16.string = + (unsigned short *)xalloc(count*sizeof(unsigned short)); + memcpy(elm->c.text16.string, string, count*sizeof(unsigned short)); + disp->nelms += 1; + } + else + { + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)string, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n != 0) + PsPolyGlyphBlt(pDrawable, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); + x += w; + } + return x; +} + +void +PsImageText8( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *string) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = TextI8Cmd; + elm->gc = gc; + elm->c.text8.x = x; + elm->c.text8.y = y; + elm->c.text8.count = count; + elm->c.text8.string = (char *)xalloc(count); + memcpy(elm->c.text8.string, string, count); + disp->nelms += 1; + } + else + { + int iso; + int siz; + float mtx[4]; + char *fnam; + PsOutPtr psOut; + ColormapPtr cMap; + + if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; + PsOut_Offset(psOut, pDrawable->x, pDrawable->y); + PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); + fnam = PsGetPSFontName(pGC->font); + if( !fnam ) fnam = "Times-Roman"; + siz = PsGetFontSize(pGC->font, mtx); + iso = PsIsISOLatin1Encoding(pGC->font); + if( !siz ) PsOut_TextAttrsMtx(psOut, fnam, mtx, iso); + else PsOut_TextAttrs(psOut, fnam, siz, iso); + PsOut_Text(psOut, x, y, string, count, PsGetPixelColor(cMap, pGC->bgPixel)); + } +} + +void +PsImageText16( + DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *string) +{ + if( pDrawable->type==DRAWABLE_PIXMAP ) + { + DisplayElmPtr elm; + PixmapPtr pix = (PixmapPtr)pDrawable; + PsPixmapPrivPtr priv = (PsPixmapPrivPtr)pix->devPrivate.ptr; + DisplayListPtr disp; + GCPtr gc; + + if ((gc = PsCreateAndCopyGC(pDrawable, pGC)) == NULL) return; + + disp = PsGetFreeDisplayBlock(priv); + + elm = &disp->elms[disp->nelms]; + elm->type = TextI16Cmd; + elm->gc = gc; + elm->c.text16.x = x; + elm->c.text16.y = y; + elm->c.text16.count = count; + elm->c.text16.string = + (unsigned short *)xalloc(count*sizeof(unsigned short)); + memcpy(elm->c.text16.string, string, count*sizeof(unsigned short)); + disp->nelms += 1; + } + else + { + int i; + char *str; + if( !count ) return; + str = (char *)xalloc(count); + for( i=0 ; ifont; + width = FONTMAXBOUNDS(pfont,rightSideBearing) - + FONTMINBOUNDS(pfont,leftSideBearing); + height = FONTMAXBOUNDS(pfont,ascent) + + FONTMAXBOUNDS(pfont,descent); + + if ((width == 0) || (height == 0) ) + return; + { + int i; + w = 0; + for (i=0; i < nGlyphs; i++) w += pCharInfo[i]->metrics.characterWidth; + } + pGCtmp = GetScratchGC(1, pDrawable->pScreen); + if (!pGCtmp) + { + (*pDrawable->pScreen->DestroyPixmap)(pPixmap); + return; + } + + gcvals[0] = GXcopy; + gcvals[1] = pGC->fgPixel; + gcvals[2] = pGC->bgPixel; + + DoChangeGC(pGCtmp, GCFunction|GCForeground|GCBackground, gcvals, 0); + + + nbyLine = BitmapBytePad(width); + pbits = (unsigned char *)ALLOCATE_LOCAL(height*nbyLine); + if (!pbits){ + PsDestroyPixmap(pPixmap); + return; + } + tmpx = 0; + while(nGlyphs--) + { + pci = *pCharInfo++; + pglyph = FONTGLYPHBITS(pGlyphBase, pci); + gWidth = GLYPHWIDTHPIXELS(pci); + gHeight = GLYPHHEIGHTPIXELS(pci); + if (gWidth && gHeight) + { + nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci); + nbyPadGlyph = BitmapBytePad(gWidth); + + if (nbyGlyphWidth == nbyPadGlyph +#if GLYPHPADBYTES != 4 + && (((int) pglyph) & 3) == 0 +#endif + ) + { + pb = pglyph; + } + else + { + for (i=0, pb = pbits; imetrics.leftSideBearing, + y - pci->metrics.ascent, gWidth, gHeight, + 0, XYBitmap, (char *)pb); + x += pci->metrics.characterWidth; + } + } + DEALLOCATE_LOCAL(pbits); + FreeScratchGC(pGCtmp); +} diff --git a/Xprint/ps/PsWindow.c b/Xprint/ps/PsWindow.c new file mode 100644 index 000000000..3a9a7ed2a --- /dev/null +++ b/Xprint/ps/PsWindow.c @@ -0,0 +1,458 @@ +/* $Xorg: PsWindow.c,v 1.4 2001/02/09 02:04:36 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: PsWindow.c +** * +** * Contents: Window code for PS driver. +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include +#include +#include + +#include "mistruct.h" +#include "regionstr.h" +#include "windowstr.h" +#include "gcstruct.h" + +#include "Ps.h" + +extern WindowPtr *WindowTable; + +/* + * The following list of strings defines the properties which will be + * placed on the screen's root window if the property was defined in + * the start-up configuration resource database. + */ +static char *propStrings[] = { + DT_PRINT_JOB_HEADER, + DT_PRINT_JOB_TRAILER, + DT_PRINT_JOB_COMMAND, + DT_PRINT_JOB_EXEC_COMMAND, + DT_PRINT_JOB_EXEC_OPTIONS, + DT_PRINT_PAGE_HEADER, + DT_PRINT_PAGE_TRAILER, + DT_PRINT_PAGE_COMMAND, + (char *)NULL +}; + + +/* + * PsCreateWindow - watch for the creation of the root window. + * When it's created, register the screen with the print extension, + * and put the default command/header properties on it. + */ +/*ARGSUSED*/ + +Bool +PsCreateWindow(WindowPtr pWin) +{ + PsWindowPrivPtr pPriv; + +#if 0 + Bool status = Success; + ScreenPtr pScreen = pWin->drawable.pScreen; + PsScreenPrivPtr pScreenPriv = (PsScreenPrivPtr) + pScreen->devPrivates[PsScreenPrivateIndex].ptr; + PsWindowPrivPtr pWinPriv = (PsWindowPrivPtr) + pWin->devPrivates[PsWindowPrivateIndex].ptr; + + /* + * Initialize this window's private struct. + */ + pWinPriv->jobFileName = (char *)NULL; + pWinPriv->pJobFile = (FILE *)NULL; + pWinPriv->pageFileName = (char *)NULL; + pWinPriv->pPageFile = (FILE *)NULL; + + if(pWin->parent == (WindowPtr)NULL) /* root window? */ + { + Atom propName; /* type = XA_STRING */ + char *propVal; + int i; + XrmDatabase rmdb = pScreenPriv->resDB; + + /* + * Put the defaults spec'd in the config files in properties on this + * screen's root window. + */ + for(i = 0; propStrings[i] != (char *)NULL; i++) + { + if((propVal = _DtPrintGetPrinterResource(pWin, rmdb, + propStrings[i])) != + (char *)NULL) + { + propName = MakeAtom(propStrings[i], strlen(propStrings[i]), + TRUE); + ChangeWindowProperty(pWin, propName, XA_STRING, 8, + PropModeReplace, strlen(propVal), + (pointer)propVal, FALSE); + xfree(propVal); + } + } + } + + return status; +#endif + + pPriv = (PsWindowPrivPtr)pWin->devPrivates[PsWindowPrivateIndex].ptr; + pPriv->validContext = 0; + + return TRUE; +} + + +/*ARGSUSED*/ +Bool PsMapWindow(WindowPtr pWindow) +{ + return TRUE; +} + +/*ARGSUSED*/ +Bool +PsPositionWindow( + WindowPtr pWin, + int x, + int y) +{ + return TRUE; +} + +/*ARGSUSED*/ +Bool +PsUnmapWindow(WindowPtr pWindow) +{ + return TRUE; +} + +/*ARGSUSED*/ +void +PsCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ +} + +/*ARGSUSED*/ +Bool +PsChangeWindowAttributes( + WindowPtr pWin, + unsigned long mask) +{ + return TRUE; +} + + +void +PsPaintWindow( + WindowPtr pWin, + RegionPtr pRegion, + int what) +{ + int status; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + pointer gcval[7]; + pointer newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + + gcmask = 0; + + /* + * We don't want to paint a window that has no place to put the + * PS output. + */ + if( PsGetContextFromWindow(pWin)==(XpContextPtr)NULL ) return; + + if( what==PW_BACKGROUND ) + { + switch(pWin->backgroundState) + { + case None: return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground) + (pWin->parent, pRegion, what); + return; + case BackgroundPixel: + newValues[FOREGROUND] = (pointer)pWin->background.pixel; + newValues[FILLSTYLE] = (pointer)FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE] = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE] = (pointer)FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if( pWin->borderIsPixel ) + { + newValues[FOREGROUND] = (pointer)pWin->border.pixel; + newValues[FILLSTYLE] = (pointer)FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE] = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE] = (pointer)FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(pRegion) * + sizeof(xRectangle)); + if( !prect ) return; + + newValues[FUNCTION] = (pointer)GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while( pBgWin->backgroundState==ParentRelative ) pBgWin = pBgWin->parent; + } + + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if( !pGC ) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if( what==PW_BORDER ) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX] = (pointer)(long)pBgWin->drawable.x; + newValues[ABSY] = (pointer)(long)pBgWin->drawable.y; + } + else + { + newValues[ABSX] = (pointer)0; + newValues[ABSY] = (pointer)0; + } + +/* + * XXX Backing store is turned off for the PS driver + + if( pWin->backStorage ) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + */ + + mask = gcmask; + gcmask = 0; + i = 0; + while( mask ) + { + index = lowbit (mask); + mask &= ~index; + switch(index) + { + case GCFunction: + if( (pointer)(long)pGC->alu!=newValues[FUNCTION] ) + { + gcmask |= index; + gcval[i++] = newValues[FUNCTION]; + } + break; + case GCTileStipXOrigin: + if( (pointer)(long)pGC->patOrg.x!=newValues[ABSX] ) + { + gcmask |= index; + gcval[i++] = newValues[ABSX]; + } + break; + case GCTileStipYOrigin: + if( (pointer)(long)pGC->patOrg.y!=newValues[ABSY] ) + { + gcmask |= index; + gcval[i++] = newValues[ABSY]; + } + break; + case GCClipMask: + if( (pointer)pGC->clientClipType!=(pointer)CT_NONE ) + { + gcmask |= index; + gcval[i++] = (pointer)CT_NONE; + } + break; + case GCSubwindowMode: + if( (pointer)pGC->subWindowMode!=newValues[SUBWINDOW] ) + { + gcmask |= index; + gcval[i++] = newValues[SUBWINDOW]; + } + break; + case GCTile: + if( pGC->tileIsPixel || (pointer)pGC->tile.pixmap!=newValues[TILE] ) + { + gcmask |= index; + gcval[i++] = newValues[TILE]; + } + break; + case GCFillStyle: + if( (pointer)pGC->fillStyle!=newValues[FILLSTYLE] ) + { + gcmask |= index; + gcval[i++] = newValues[FILLSTYLE]; + } + break; + case GCForeground: + if( (pointer)pGC->fgPixel!=newValues[FOREGROUND] ) + { + gcmask |= index; + gcval[i++] = newValues[FOREGROUND]; + } + break; + } + } + + if( gcmask ) DoChangeGC(pGC, gcmask, (XID *)gcval, 1); + + if( pWin->drawable.serialNumber!=pGC->serialNumber ) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(pRegion); + pbox = REGION_RECTS(pRegion); + for( i=numRects ; --i >= 0 ; pbox++,prect++ ) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + +/* + * XXX Backing store is turned off for the PS driver + + if( pWin->backStorage ) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + */ + + if( what==PW_BORDER ) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); +} + +/*ARGSUSED*/ +Bool +PsDestroyWindow(WindowPtr pWin) +{ + return TRUE; +} diff --git a/Xprint/ps/psout.c b/Xprint/ps/psout.c new file mode 100644 index 000000000..d4a64eacb --- /dev/null +++ b/Xprint/ps/psout.c @@ -0,0 +1,1623 @@ +/* $Xorg: psout.c,v 1.9 2001/03/26 15:25:12 coskrey Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996, 2000 Sun Microsystems, Inc. All Rights Reserved. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: psout.c +** * +** * Contents: Code to output PostScript to file +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#include +#include "os.h" +#include "psout.h" + +PsElmPtr PsCloneFillElementList(int nElms, PsElmPtr elms); + +typedef void *voidPtr; + +typedef struct PsPatRec_ +{ + PsFillEnum type; + voidPtr tag; +} PsPatRec; + +typedef PsPatRec *PsPatPtr; + +typedef struct PsOutRec_ +{ + FILE *Fp; + char Buf[256]; + int CurColor; + int LineWidth; + PsCapEnum LineCap; + PsJoinEnum LineJoin; + int NDashes; + int *Dashes; + int DashOffset; + int LineBClr; + PsRuleEnum FillRule; + char *FontName; + int FontSize; + float FontMtx[4]; + int ImageFormat; + int RevImage; + int NPatterns; + int MxPatterns; + PsPatPtr Patterns; + int ClipType; + PsClipRec Clip; + int InFrame; + int XOff; + int YOff; + + PsFillEnum InTile; + int ImgSkip; + int ImgBClr; + int ImgFClr; + int ImgX; + int ImgY; + int ImgW; + int ImgH; + int SclW; + int SclH; + + int NDownloads; + int MxDownloads; + char **Downloads; + Bool isRaw; + + int start_image; +} PsOutRec; + +/* + * Standard definitions + */ + +static char *S_StandardDefs = "\ +/d{def}bind def\ +/b{bind}bind d\ +/bd{b d}b d\ +/x{exch}bd\ +/xd{x d}bd\ +/dp{dup}bd\ +/t{true}bd\ +/f{false}bd\ +/p{pop}bd\ +/r{roll}bd\ +/c{copy}bd\ +/i{index}bd\ +/rp{repeat}bd\ +/n{newpath}bd\ +/w{setlinewidth}bd\ +/lc{setlinecap}bd\ +/lj{setlinejoin}bd\ +/sml{setmiterlimit}bd\ +/ds{setdash}bd\ +/ie{ifelse}bd\ +/len{length}bd\ +/m{moveto}bd\ +/l{lineto}bd\ +/rl{rlineto}bd\ +/a{arc}bd\ +/an{arcn}bd\ +/st{stroke}bd\ +/fl{fill}bd\ +/ef{eofill}bd\ +/sp{showpage}bd\ +/cp{closepath}bd\ +/clp{clippath}bd\ +/cl{clip}bd\ +/pb{pathbbox}bd\ +/tr{translate}bd\ +/rt{rotate}bd\ +/dv{div}bd\ +/ml{mul}bd\ +/ad{add}bd\ +/ng{neg}bd\ +/scl{scale}bd\ +/sc{setrgbcolor}bd\ +/g{setgray}bd\ +/gs{gsave}bd\ +/gr{grestore}bd\ +/sv{save}bd\ +/rs{restore}bd\ +/mx{matrix}bd\ +/cm{currentmatrix}bd\ +/sm{setmatrix}bd\ +/ccm{concatmatrix}bd\ +/cc{concat}bd\ +/ff{findfont}bd\ +/mf{makefont}bd\ +/sf{setfont}bd\ +/cft{currentfont}bd\ +/fd{FontDirectory}bd\ +/sh{show}bd\ +/stw{stringwidth}bd\ +/ci{colorimage}bd\ +/ig{image}bd\ +/im{imagemask}bd\ +/cf{currentfile}bd\ +/rh{readhexstring}bd\ +/str{string}bd\ +/al{aload}bd\ +/wh{where}bd\ +/kn{known}bd\ +/stp{stopped}bd\ +/bg{begin}bd\ +/ed{end}bd\ +/fa{forall}bd\ +/pi{putinterval}bd\ +/mk{mark}bd\ +/ctm{cleartomark}bd\ +/df{definefont}bd\ +/cd{currentdict}bd\ +/db{20 dict dp bg}bd\ +/de{ed}bd\ +/languagelevel wh{p languagelevel}{1}ie\ + 1 eq{/makepattern{p}bd/setpattern{p}bd/setpagedevice{p}bd}if\ +/mp{makepattern}bd\ +/spt{setpattern}bd\ +/spd{setpagedevice}bd\ +"; + +/* + * Composite definitions + * + * + * XYr - Return X/Y dpi for device + * + * XYr + * + * Cs - Coordinate setup (for origin upper left) + * + * Cs + * + * P - Draw a point + * + * P + * + * R - Add rectangle to path + * + * R + * + * Ac - Add arc to path + * + * Ac + * + * An - Add arc to path (counterclockwise) + * + * An + * + * Tf - Set font + * + * Tf + * + * Tfm - Set font with matrix + * + * Tfm + * + * T - Draw text + * + * T + * + * Tb - Draw text with background color + * + * Tb + * + * Im1 - Image 1 bit monochrome imagemask + * + * Im1 + * + * Im24 - Image 24 bit RGB color + * + * Im24 + * + * Im1t - Image 1 bit monochrome imagemask (in tile) + * + * Im1t + * + * Im24t - Image 24 bit RGB color (in tile) + * + * Im24t + */ + +static char *S_CompositeDefs = "\ +/XYr{/currentpagedevice wh\ + {p currentpagedevice dp /HWResolution kn\ + {/HWResolution get al p}{p 300 300}ie}{300 300}ie}bd\ +/Cs{dp 0 eq{0 pHt tr XYr -1 x dv 72 ml x 1 x dv 72 ml x scl}if\ + dp 1 eq{90 rt XYr -1 x dv 72 ml x 1 x dv 72 ml x scl}if\ + dp 2 eq{pWd 0 tr XYr 1 x dv 72 ml x -1 x dv 72 ml x scl}if\ + 3 eq{pHt pWd tr 90 rt XYr 1 x dv 72 ml x -1 x dv 72 ml x scl}if}bd\ +/P{gs 1 w [] 0 ds 2 c m .1 ad x .1 ad x l st gr}bd\ +/R{4 2 r m 1 i 0 rl 0 x rl ng 0 rl cp}bd\ +/Ac{mx_ cm p 6 -2 r tr 4 2 r ng scl 0 0 .5 5 3 r a mx_ sm}bd\ +/An{mx_ cm p 6 -2 r tr 4 2 r ng scl 0 0 .5 5 3 r an mx_ sm}bd\ +/ISO{dp len dict bg{1 i/FID ne{d}{p p}ie}fa\ + /Encoding ISOLatin1Encoding d cd ed df}bd\ +/iN{dp len str cvs dp len x 1 i 3 ad str 2 c c p x p dp 3 -1 r(ISO)pi}bd\ +/Tp{{x dp iN dp fd x kn{x p dp/f_ x d ff}{dp/f_ x d x ff ISO}ie x}\ + {x dp/f_ x d ff x}ie}bd\ +/Tf{Tp[x 0 0 2 i ng 0 0] dp/fm_ x d mf sf}bd\ +/Tfm{Tp 1 -1 tm1_ scl tm2_ ccm dp/fm_ x d mf sf}bd\ +/T{m sh}bd\ +/Tb{gs sc f_ ff sf cft/FontMatrix get 3 get\ + cft/FontBBox get dp 1 get x 3 get 2 i ml 3 1 r ml\ + 0 0 m 4 i stw p 4 i 4 i m fm_ cc\ + 0 2 i rl dp 0 rl 0 2 i ng rl 0 3 i rl ng 0 rl cp fl p p\ + gr T}bd\ +/Im1{6 4 r tr scl t [3 i 0 0 5 i 0 0]{cf str1 rh p} im}bd\ +/Im1rev{6 4 r tr scl f [3 i 0 0 5 i 0 0]{cf str1 rh p} im}bd\ +/Im24{gs 6 4 r tr scl 8 [3 i 0 0 5 i 0 0]{cf str3 rh p} f 3 ci}bd\ +/Im1t{6 4 r tr scl t [3 i 0 0 5 i 0 0]{} im}bd\ +/Im24t{gs 6 4 r tr scl 8 [3 i 0 0 5 i 0 0]{} f 3 ci}bd\ +/ck2{/currentpagedevice wh \ +{p dp currentpagedevice dp 3 -1 r kn \ +{x get al p 3 -1 r eq 3 1 r eq and } \ +{p p p p t}ie} \ +{p p p t}ie}bd \ +/ck1{/currentpagedevice wh \ +{p dp currentpagedevice dp 3 -1 r kn \ +{x get eq} {p p p t}ie} \ +{p p t}ie}bd \ +/mtx{scl t [3 i 0 0 5 i 0 0]}bd \ +"; + +int pagenum = 0; +char *pg_orient[] = {"Portrait","Landscape","Reverse Portrait","Reverse Landscape"}; +/* + * Setup definitions + */ + +static char *S_SetupDefs = "\ + /mx_ mx d\ + /im_ mx d\ + /tm1_ mx d\ + /tm2_ mx d\ + /str3 3 str d\ + /str1 1 str d\ +"; + +/******************************************************************* + * PRIVATE FUNCTIONS * + *******************************************************************/ + +static void +S_Flush(PsOutPtr self) +{ + if( self->Buf[0] ) + { + if( self->Buf[strlen(self->Buf)-1]!='\n' ) strcat(self->Buf, "\n"); + + if (!ferror(self->Fp)) { + (void) fputs(self->Buf, self->Fp); + } + + self->Buf[0] = '\0'; + } +} + +static void +S_Comment(PsOutPtr self, char *comment) +{ + S_Flush(self); + strcpy(self->Buf, comment); + S_Flush(self); +} + +static void +S_OutDefs(PsOutPtr self, char *defs) +{ + int i, k=0; + S_Flush(self); + memset(self->Buf, 0, 256); + for( i=0 ; defs[i]!='\0' ;) + { + if( k>70 && (i==0 || (i && defs[i-1]!='/')) && + (defs[i]==' ' || defs[i]=='/' || defs[i]=='{') ) + { + S_Flush(self); + k = 0; + memset(self->Buf, 0, 256); + } + if( k && self->Buf[k-1]==' ' && defs[i]==' ' ) { i++; continue; } + self->Buf[k] = defs[i]; + k++; i++; + } + S_Flush(self); +} + +static void +S_OutNum(PsOutPtr self, float num) +{ + int i; + char buf[64]; + sprintf(buf, "%.3f", num); + for( i=strlen(buf)-1 ; buf[i]=='0' ; i-- ); buf[i+1] = '\0'; + if( buf[strlen(buf)-1]=='.' ) buf[strlen(buf)-1] = '\0'; + if( self->Buf[0] ) strcat(self->Buf, " "); + strcat(self->Buf, buf); + if( strlen(self->Buf)>70 ) S_Flush(self); +} + +static void +S_OutStr(PsOutPtr self, char *txt, int txtl) +{ + int i, k; + char buf[512]; + for( i=0,k=0 ; i=' ' && txt[i]<='~') && + txt[i]!='(' && txt[i]!=')' && txt[i]!='\\' ) + { buf[k] = txt[i]; k++; continue; } + buf[k] = '\\'; k++; + sprintf(&buf[k], "%03o", txt[i]&0xFF); + k += 3; + } + strcat(self->Buf, "("); + i = strlen(self->Buf); + memcpy(&self->Buf[i], buf, k); + self->Buf[i+k] = '\0'; + strcat(self->Buf, ")"); + if( strlen(self->Buf)>70 ) S_Flush(self); +} + +static void +S_OutTok(PsOutPtr self, char *tok, int cr) +{ + if( self->Buf[0] ) strcat(self->Buf, " "); + strcat(self->Buf, tok); + if( cr ) S_Flush(self); +} + +static void +S_Color(PsOutPtr self, int clr) +{ + int ir, ig, ib; + ir = clr>>16; ig = (clr>>8)&0xFF; ib = clr&0xFF; + if( ir==ig && ig==ib ) + { S_OutNum(self, (float)ir/255.); S_OutTok(self, "g", 1); } + else + { + S_OutNum(self, (float)ir/255.); + S_OutNum(self, (float)ig/255.); + S_OutNum(self, (float)ib/255.); + S_OutTok(self, "sc", 1); + } +} + +static void +S_SetPageDevice(PsOutPtr self, int orient, int count, int plex, int res, + int wd, int ht, int isPage) +{ + float fwd = ((float)wd/(float)res)*72.; + float fht = ((float)ht/(float)res)*72.; + + S_OutTok(self, "/pWd", 0); + S_OutNum(self, fwd); + S_OutTok(self, "d /pHt", 0); + S_OutNum(self, fht); + S_OutTok(self, "d", 1); + + /* + * if these are page attributes, have PostScript check to see if they + * have changed. If not, don't do setpagedevice, since it will cause + * a page flush and screw up duplex printing. Having PostScript check + * means we don't have to keep track ourselves. + */ + if(isPage) { + S_OutNum(self, (float) orient); + S_OutTok(self, "/Orientation ck1", 0); + S_OutTok(self, "pWd pHt /PageSize ck2 and not {", 1); + } + S_OutTok(self, "{db", 0); + + S_OutTok(self, "/Orientation", 0); + S_OutNum(self, (float) orient); + S_OutTok(self, " d ", 0); + S_OutTok(self, "/PageSize [pWd pHt] d", 0); + + S_OutTok(self, " de spd", 0); + /* + * save a flag to show if we failed to set orientation... determined + * by both/either Orientation and/or PageSize, use this + * later to set/not set orientation using Cs command. + */ + S_OutTok(self,"}stp /orientationFailed x d", 1); + /* + * if these are page attributes, have PostScript check to see if they + * have changed. If not, don't do setpagedevice, since it will cause + * a page flush and screw up duplex printing. Having PostScript check + * means we don't have to keep track ourselves. + */ + if(isPage) + { + S_OutTok(self,"}if",1); + + S_OutTok(self, (plex==0)?"f":"t", 0); + S_OutTok(self, "/Duplex ck1 ", 0); + + S_OutTok(self, (plex==2)?"t":"f", 0); + S_OutTok(self, "/Tumble ck1 and ", 0); + + + S_OutNum(self, (float)res); + S_OutNum(self, (float)res); + S_OutTok(self, " /HWResolution ck2 and", 0); + + if( count>1 ) + { + S_OutNum(self, (float)count); + S_OutTok(self, " /NumCopies", 0); + S_OutTok(self, " ck1 and ", 0); + } + S_OutTok(self," not {",1); + } + S_OutTok(self, "{db", 0); + + S_OutTok(self, "/Duplex ", 0); + S_OutTok(self, (plex==0)?"f":"t", 0); + S_OutTok(self, " d ", 0); + + S_OutTok(self, "/Tumble ", 0); + S_OutTok(self, (plex==2)?"t":"f", 0); + S_OutTok(self, " d ", 0); + + S_OutTok(self, " /HWResolution [", 0); + S_OutNum(self, (float)res); + S_OutNum(self, (float)res); + S_OutTok(self, "] d ", 0); + + if( count>1 ) + { + S_OutTok(self, " /NumCopies", 0); + S_OutNum(self, (float)count); + S_OutTok(self, " d ", 0); + } + S_OutTok(self, " de spd}stp p", 1); + + if(isPage) + { + S_OutTok(self, "}if", 1); + } +} + +/******************************************************************* + * PUBLIC FUNCTIONS * + *******************************************************************/ + +FILE * +PsOut_ChangeFile(PsOutPtr self, FILE *fp) +{ + FILE *nfp; + + nfp = self->Fp; + + self->Fp = fp; + + return nfp; +} + +PsOutPtr +PsOut_BeginFile(FILE *fp, int orient, int count, int plex, int res, + int wd, int ht, Bool raw) +{ + int i; +/* + * Get ready to output PostScript header + */ + PsOutPtr psout; + psout = (PsOutPtr)xalloc(sizeof(PsOutRec)); + memset(psout, 0, sizeof(PsOutRec)); + psout->Fp = fp; + psout->isRaw = raw; + pagenum = 0; + + if (!raw) { +/* + * Output PostScript header + */ + S_Comment(psout, "%!PS-Adobe-3.0 EPSF-3.0"); + S_Comment(psout, "%%Creator: The Open Group PostScript Print Server"); + /*### BoundingBox ###*/ + S_Comment(psout, "%%EndComments"); + S_Comment(psout, "%%BeginProlog"); + S_Comment(psout, "%%BeginProcSet: XServer_PS_Functions"); + S_OutDefs(psout, S_StandardDefs); + S_OutDefs(psout, S_CompositeDefs); + S_Comment(psout, "%%EndProcSet"); + S_Comment(psout, "%%EndProlog"); + S_Comment(psout, "%%BeginSetup"); + /* set document level page attributes */ + S_SetPageDevice(psout, orient, count, plex, res, wd, ht, 0); + S_Comment(psout, "%%Pages: atend"); + S_OutDefs(psout, S_SetupDefs); + S_Comment(psout, "%%EndSetup"); + } +/* + * Initialize the structure + */ + psout->CurColor = 0xFFFFFFFF; + psout->LineWidth = 1; + psout->LineCap = PsCButt; + psout->LineJoin = PsJMiter; + psout->NDashes = 0; + psout->Dashes = (int *)0; + psout->FontName = (char *)0; + psout->FontSize = 0; + psout->start_image = 0; + for( i=0 ; i<4 ; i++ ) psout->FontMtx[i] = 0.; + psout->ImageFormat = 0; + return(psout); +} + +void +PsOut_EndFile(PsOutPtr self, int closeFile) +{ + char coms[50]; + int i; + + if (!self->isRaw) { + S_Comment(self,"%%Trailer"); + sprintf(coms,"%%%%Pages: %d",pagenum); + S_Comment(self, coms); + S_Comment(self, "%%EOF"); + } + if( self->NDashes && self->Dashes ) xfree(self->Dashes); + if( self->FontName ) xfree(self->FontName); + if( self->Patterns ) xfree(self->Patterns); + if( self->Clip.rects ) xfree(self->Clip.rects); + if( closeFile ) fclose(self->Fp); + for( i=0 ; iNDownloads ; i++ ) xfree(self->Downloads[i]); + if( self->Downloads ) xfree(self->Downloads); + pagenum = 0; /* reset page num back to 0 */ + xfree(self); +} + +void +PsOut_BeginPage(PsOutPtr self, int orient, int count, int plex, int res, + int wd, int ht) +{ + char coms[50]; + +/*** comment for pagenumbers *****/ + + S_Comment(self,"%%PageHeader"); + pagenum++; + sprintf(coms,"%%%%Page: %d %d",pagenum,pagenum); + S_Comment(self, coms); + sprintf(coms,"%%%%PageOrientation: %s",pg_orient[orient]); + S_Comment(self, coms); + +/*** end comment *****************/ + + /* set page level page attributes */ + S_SetPageDevice(self, orient, count, plex, res, wd, ht, 1); + + S_OutTok(self, "gs ", 0); + /* + * check to see if we set orientation already; if it wasn't set, + * use Cs to set orientation here. + */ + S_OutNum(self, (float)orient); + S_OutTok(self, "orientationFailed { ", 0); + S_OutNum(self, (float)orient); + S_OutTok(self, " } { 0 }ie Cs 100 sml gs", 1); +} + +void +PsOut_EndPage(PsOutPtr self) +{ + S_OutTok(self, "gr gr sp", 1); + + /* did grestore: mark attributes 'dirty' so they will be re-sent */ + PsOut_DirtyAttributes(self); + +/*** comment for pagenumbers *****/ + + S_Comment(self,"%%PageTrailer"); + +/*** end comment *****************/ +} + +void +PsOut_DirtyAttributes(PsOutPtr self) +{ + int i; + self->CurColor = 0xFFFFFFFF; + self->LineWidth = -1; + self->LineCap = (PsCapEnum)-1; + self->LineJoin = (PsJoinEnum)-1; + self->NDashes = -1; + self->FontSize = -1; + for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = -1.; + if( self->Dashes ) { xfree(self->Dashes); self->Dashes = (int *)0; } + if( self->FontName ) { xfree(self->FontName); self->FontName = (char *)0; } +} + +void +PsOut_Comment(PsOutPtr self, char *comment) +{ + S_Comment(self, comment); +} + +void +PsOut_Offset(PsOutPtr self, int x, int y) +{ + self->XOff = x; + self->YOff = y; +} + +void +PsOut_Clip(PsOutPtr self, int clpTyp, PsClipPtr clpinf) +{ + int i, k; + int changed = 0; + int xo = self->XOff; + int yo = self->YOff; + + if( self->InTile ) return; + if( self->InFrame ) xo = yo = 0; + if( clpTyp!=self->ClipType ) changed = 1; + else + { + if( clpinf->nRects!=self->Clip.nRects ) changed = 1; + else + { + if( clpinf->nOutterClips!=self->Clip.nOutterClips ) changed = 1; + else + { + for( i=0 ; inOutterClips ; i++ ) + { + if( memcmp(&clpinf->outterClips[i], &self->Clip.outterClips[i], + sizeof(PsRectRec))!=0 ) break; + } + if( inOutterClips ) changed = 1; + else + { + for( i=0 ; inRects ; i++ ) + { + if( memcmp(&clpinf->rects[i], &self->Clip.rects[i], + sizeof(PsRectRec))!=0 ) { changed = 1; break; } + } + } + } + } + if( clpinf->nElms!=self->Clip.nElms ) changed = 1; + else + { + for( i=0 ; inElms ; i++ ) + { + if( clpinf->elms[i].type!=PSOUT_POINTS ) + { + if( memcmp(&clpinf->elms[i], &self->Clip.elms[i], + sizeof(PsElmRec))!=0 ) { changed = 1; break; } + } + else + { + if( clpinf->elms[i].type!=self->Clip.elms[i].type || + clpinf->elms[i].nPoints!=self->Clip.elms[i].nPoints ) + { changed = 1; break; } + else + { + for( k=0 ; kelms[i].nPoints ; k++ ) + { + if( memcmp(&clpinf->elms[i].c.points[k], + &self->Clip.elms[i].c.points[k], sizeof(PsPointRec)) ) + { changed = 1; break; } + } + if( changed ) break; + } + } + } + } + } + + if( self->Clip.rects ) xfree(self->Clip.rects); + if( self->Clip.outterClips ) xfree(self->Clip.outterClips); + if( self->Clip.elms ) + PsDestroyFillElementList(self->Clip.nElms, self->Clip.elms); + self->ClipType = clpTyp; + self->Clip.nRects = clpinf->nRects; + self->Clip.nElms = clpinf->nElms; + self->Clip.nOutterClips = clpinf->nOutterClips; + if( clpinf->nRects ) + { + self->Clip.rects = (PsRectPtr)xalloc(clpinf->nRects*sizeof(PsRectRec)); + memcpy(self->Clip.rects, clpinf->rects, clpinf->nRects*sizeof(PsRectRec)); + } + else self->Clip.rects = 0; + if( clpinf->nOutterClips ) + { + self->Clip.outterClips = (PsRectPtr)xalloc(clpinf->nOutterClips* + sizeof(PsRectRec)); + memcpy(self->Clip.outterClips, clpinf->outterClips, + clpinf->nOutterClips*sizeof(PsRectRec)); + } + else self->Clip.outterClips = 0; + if( clpinf->nElms ) + self->Clip.elms = PsCloneFillElementList(clpinf->nElms, clpinf->elms); + else self->Clip.elms = 0; + + PsOut_DirtyAttributes(self); + S_OutTok(self, "gr gs", 1); + if( self->Clip.nOutterClips ) + { + for( i=0 ; iClip.nOutterClips ; i++ ) + { + S_OutNum(self, (float)(self->Clip.outterClips[i].x)); + S_OutNum(self, (float)(self->Clip.outterClips[i].y)); + S_OutNum(self, (float)self->Clip.outterClips[i].w); + S_OutNum(self, (float)self->Clip.outterClips[i].h); + S_OutTok(self, "R", 1); + } + S_OutTok(self, "cl n", 1); + } + if( self->Clip.nRects ) + { + for( i=0 ; iClip.nRects ; i++ ) + { + S_OutNum(self, (float)(self->Clip.rects[i].x+xo)); + S_OutNum(self, (float)(self->Clip.rects[i].y+yo)); + S_OutNum(self, (float)self->Clip.rects[i].w); + S_OutNum(self, (float)self->Clip.rects[i].h); + S_OutTok(self, "R", 1); + } + S_OutTok(self, "cl n", 1); + } + if( self->Clip.nElms ) + { + PsElmPtr elm = self->Clip.elms; + for( i=0 ; iClip.nElms ; i++,elm++ ) + { + switch(elm->type) + { + case PSOUT_POINTS: + for( k=0 ; knPoints ; k++ ) + { + S_OutNum(self, (float)elm->c.points[k].x+xo); + S_OutNum(self, (float)elm->c.points[k].y+yo); + if( k==0 ) S_OutTok(self, "m", 0); + else S_OutTok(self, "l", 0); + } + S_OutTok(self, "cp", 1); + break; + case PSOUT_RECT: + S_OutNum(self, (float)elm->c.rect.x+xo); + S_OutNum(self, (float)elm->c.rect.y+yo); + S_OutNum(self, (float)elm->c.rect.w); + S_OutNum(self, (float)elm->c.rect.h); + S_OutTok(self, "R", 1); + break; + case PSOUT_ARC: + if( elm->c.arc.style==PsPieSlice ) + { + S_OutNum(self, (float)elm->c.arc.x+xo+(float)elm->c.arc.w/2.); + S_OutNum(self, (float)elm->c.arc.y+yo+(float)elm->c.arc.h/2.); + S_OutTok(self, "m", 0); + } + S_OutNum(self, (float)elm->c.arc.x+xo+(float)elm->c.arc.w/2.); + S_OutNum(self, (float)elm->c.arc.y+yo+(float)elm->c.arc.h/2.); + S_OutNum(self, (float)elm->c.arc.w); + S_OutNum(self, (float)elm->c.arc.h); + S_OutNum(self, (float)elm->c.arc.a1/64.); + S_OutNum(self, (float)elm->c.arc.a1/64.+(float)elm->c.arc.a2/64.); + if( elm->c.arc.a2<0 ) S_OutTok(self, "An cp", 1); + else S_OutTok(self, "Ac cp", 1); + break; + } + } + S_OutTok(self, "cl n", 1); + } +} + +void +PsOut_Color(PsOutPtr self, int clr) +{ + if( clr==self->CurColor || self->InTile>=PsStip ) return; + self->CurColor = clr; + S_Color(self, clr); +} + +void +PsOut_FillRule(PsOutPtr self, PsRuleEnum rule) +{ + self->FillRule = rule; +} + +void +PsOut_LineAttrs(PsOutPtr self, int wd, PsCapEnum cap, PsJoinEnum join, + int nDsh, int *dsh, int dshOff, int bclr) +{ + int i; + int same = 1; + + if( wd!=self->LineWidth && wd>=0 ) + { + if( wd==0 ) wd = 1; + self->LineWidth = wd; + S_OutNum(self, (float)wd); S_OutTok(self, "w", 1); + } + if( cap!=self->LineCap ) + { + self->LineCap = cap; + S_OutNum(self, (float)cap); S_OutTok(self, "lc", 1); + } + if( join!=self->LineJoin ) + { + self->LineJoin = join; + S_OutNum(self, (float)join); S_OutTok(self, "lj", 1); + } + if( nDsh!=self->NDashes ) same = 0; + else if( dshOff!=self->DashOffset ) same = 0; + else if( nDsh ) + { + for( i=0 ; iDashes[i] ) break; } + if( iNDashes && self->Dashes ) + { xfree(self->Dashes); self->Dashes = (int *)0; } + self->NDashes = nDsh; + self->DashOffset = dshOff; + if( nDsh ) self->Dashes = (int *)xalloc(sizeof(int)*nDsh); + S_OutTok(self, "[", 0); + for( i=0 ; iDashes[i] = dsh[i]; + S_OutNum(self, (float)dsh[i]); + } + S_OutTok(self, "]", 0); + S_OutNum(self, (float)dshOff); + S_OutTok(self, "ds", 1); + } + + if( nDsh ) self->LineBClr = bclr; else bclr = -1; +} + +void +PsOut_TextAttrs(PsOutPtr self, char *fnam, int siz, int iso) +{ + int i; + char buf[256]; + if( self->FontName && strcmp(fnam, self->FontName)==0 && + siz==self->FontSize ) return; + if( self->FontName ) xfree(self->FontName); + self->FontName = (char *)xalloc(strlen(fnam)+1); + strcpy(self->FontName, fnam); + self->FontSize = siz; + for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = -1.; + strcpy(buf, "/"); strcat(buf, fnam); + S_OutTok(self, buf, 0); + S_OutNum(self, (float)siz); + if( iso ) S_OutTok(self, "t", 0); + else S_OutTok(self, "f", 0); + S_OutTok(self, "Tf", 1); +} + +void +PsOut_TextAttrsMtx(PsOutPtr self, char *fnam, float *mtx, int iso) +{ + int i; + char buf[256]; + if( self->FontName && strcmp(fnam, self->FontName)==0 && + mtx[0]==self->FontMtx[0] && mtx[1]==self->FontMtx[1] && + mtx[2]==self->FontMtx[2] && mtx[3]==self->FontMtx[3] ) return; + if( self->FontName ) xfree(self->FontName); + self->FontName = (char *)xalloc(strlen(fnam)+1); + strcpy(self->FontName, fnam); + for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = mtx[i]; + self->FontSize = -1; + strcpy(buf, "/"); strcat(buf, fnam); strcat(buf, " ["); + S_OutTok(self, buf, 0); + for( i=0 ; i<4 ; i++ ) S_OutNum(self, mtx[i]); + S_OutTok(self, "0 0]", 0); + if( iso ) S_OutTok(self, "t", 0); + else S_OutTok(self, "f", 0); + S_OutTok(self, "Tfm", 1); +} + +void +PsOut_Polygon(PsOutPtr self, int nPts, PsPointPtr pts) +{ + int i; + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + if( nPts<=2 ) return; + for( i=0 ; iFillRule==PsEvenOdd ) S_OutTok(self, "cp ef", 1); + else S_OutTok(self, "cp fl", 1); +} + +void +PsOut_FillRect(PsOutPtr self, int x, int y, int w, int h) +{ + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + S_OutNum(self, (float)x); + S_OutNum(self, (float)y); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutTok(self, "R fl", 1); +} + +void +PsOut_FillArc(PsOutPtr self, int x, int y, int w, int h, + float ang1, float ang2, PsArcEnum style) +{ + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + if( style==PsPieSlice ) + { + S_OutNum(self, (float)x+(float)w/2.); + S_OutNum(self, (float)y+(float)h/2.); + S_OutTok(self, "m", 0); + } + S_OutNum(self, (float)x+(float)w/2.); + S_OutNum(self, (float)y+(float)h/2.); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutNum(self, ang1); + S_OutNum(self, ang1+ang2); + if( ang2<0 ) S_OutTok(self, "An cp fl", 1); + else S_OutTok(self, "Ac cp fl", 1); +} + +void +PsOut_Lines(PsOutPtr self, int nPts, PsPointPtr pts) +{ + int i; + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + if( nPts<1 ) return; + for( i=0 ; iLineBClr>=0 ) + { + S_OutTok(self, "gs", 0); + S_Color(self, self->LineBClr); + S_OutTok(self, "[] 0 ds st gr", 0); + } + S_OutTok(self, "st", 1); +} + +void +PsOut_Points(PsOutPtr self, int nPts, PsPointPtr pts) +{ + int i; + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + if( nPts<1 ) return; + for( i=0 ; iXOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + S_OutNum(self, (float)x); + S_OutNum(self, (float)y); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutTok(self, "R", 0); + if( self->LineBClr>=0 ) + { + S_OutTok(self, "gs", 0); + S_Color(self, self->LineBClr); + S_OutTok(self, "[] 0 ds st gr", 0); + } + S_OutTok(self, "st", 1); +} + +void +PsOut_DrawArc(PsOutPtr self, int x, int y, int w, int h, + float ang1, float ang2) +{ + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + S_OutNum(self, (float)x+(float)w/2.); + S_OutNum(self, (float)y+(float)h/2.); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutNum(self, ang1); + S_OutNum(self, ang1+ang2); + if( ang2<0 ) S_OutTok(self, "An", 0); + else S_OutTok(self, "Ac", 0); + if( self->LineBClr>=0 ) + { + S_OutTok(self, "gs", 0); + S_Color(self, self->LineBClr); + S_OutTok(self, "[] 0 ds st gr", 0); + } + S_OutTok(self, "st", 1); +} + +void +PsOut_Text(PsOutPtr self, int x, int y, char *text, int textl, int bclr) +{ + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + S_OutStr(self, text, textl); + S_OutNum(self, (float)x); + S_OutNum(self, (float)y); + if( bclr<0 ) S_OutTok(self, "T", 1); + else + { + int ir = bclr>>16; + int ig = (bclr>>8)&0xFF; + int ib = bclr&0xFF; + S_OutNum(self, (float)ir/255.); + S_OutNum(self, (float)ig/255.); + S_OutNum(self, (float)ib/255.); + S_OutTok(self, "Tb", 1); + } +} + +#ifdef BM_CACHE +void /* new */ +PsOut_ImageCache(PsOutPtr self, int x, int y, long cache_id, int bclr, int fclr) +{ + char cacheID[10]; + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + sprintf(cacheID, "c%di", cache_id); + + S_OutNum(self, (float)x); + S_OutNum(self, (float)y); + + if( fclr==0xFFFFFF ) + { + int ir, ig, ib; + ir = bclr>>16; ig = (bclr>>8)&0xFF; ib = bclr&0xFF; + if( ir==ig && ig==ib ) + S_OutNum(self, (float)ir/255.); + else + S_OutNum(self, (float)0); + self->RevImage = 1; + } + else + { + int ir, ig, ib; + ir = fclr>>16; ig = (fclr>>8)&0xFF; ib = fclr&0xFF; + if( ir==ig && ig==ib ) + S_OutNum(self, (float)ir/255.); + else + S_OutNum(self, (float)0); + } + + S_OutTok(self, cacheID, 1); +} /* new */ + +void /* new */ +PsOut_BeginImageCache(PsOutPtr self, long cache_id) +{ + char cacheID[10]; + + sprintf(cacheID, "/c%di {", cache_id); + + S_OutTok(self, cacheID, 0); +} /* new */ + +void /* new */ +PsOut_EndImageCache(PsOutPtr self) +{ + S_OutTok(self, "}bd", 1); +} /* new */ +#endif + +void +PsOut_BeginImage(PsOutPtr self, int bclr, int fclr, int x, int y, + int w, int h, int sw, int sh, int format) +{ + int savClr = self->CurColor; + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + if( self->InTile ) + { + if( self->InTile>=PsStip && format!=1 ) { self->ImgSkip = 1; return; } + self->ImgBClr = bclr; self->ImgFClr = fclr; + self->ImgX = x; self->ImgY = y; + self->ImgW = w; self->ImgH = h; + self->SclW = sw; self->SclH = sh; + S_OutTok(self, "<", 0); + self->ImageFormat = format; + self->RevImage = 0; + if( self->InTile==PsTile && format==1 && fclr==0xFFFFFF ) + self->RevImage = 1; + return; + } + + self->RevImage = 0; + if( format==1 ) + { + S_OutTok(self, "gs", 0); + if( fclr==0xFFFFFF ) + { + PsOut_Color(self, fclr); + PsOut_FillRect(self, x, y, sw, sh); + PsOut_Color(self, bclr); + self->RevImage = 1; + } + else + { + PsOut_Color(self, bclr); + PsOut_FillRect(self, x, y, sw, sh); + PsOut_Color(self, fclr); + } + } + S_OutNum(self, (float)x); + S_OutNum(self, (float)y); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutNum(self, (float)sw); + S_OutNum(self, (float)sh); + if( format==1 ) { + if(self->RevImage) + S_OutTok(self, "Im1rev", 1); + else + S_OutTok(self, "Im1", 1); + } + else S_OutTok(self, "Im24", 1); + self->ImageFormat = format; + self->CurColor = savClr; +} + +void +PsOut_BeginImageIM(PsOutPtr self, int bclr, int fclr, int x, int y, + int w, int h, int sw, int sh, int format) +{ + int savClr = self->CurColor; + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame || self->InTile ) xo = yo = 0; + x += xo; y += yo; + if( self->InTile ) + { + if( self->InTile>=PsStip && format!=1 ) { self->ImgSkip = 1; return; } + self->ImgBClr = bclr; self->ImgFClr = fclr; + self->ImgX = x; self->ImgY = y; + self->ImgW = w; self->ImgH = h; + self->SclW = sw; self->SclH = sh; + S_OutTok(self, "<", 0); + self->ImageFormat = format; + self->RevImage = 0; + if( self->InTile==PsTile && format==1 && fclr==0xFFFFFF ) + self->RevImage = 1; + return; + } + + self->RevImage = 0; + if( format==1 ) + { + S_OutTok(self, "gs", 0); +#ifdef BM_CACHE + S_OutTok(self, "g", 1); +#else + if( fclr==0xFFFFFF ) + { + PsOut_Color(self, bclr); + self->RevImage = 1; + } + else + { + PsOut_Color(self, fclr); + } +#endif + } + +#ifdef BM_CACHE + S_OutTok(self, "tr", 0); /* new */ +#else + S_OutNum(self, (float)x); + S_OutNum(self, (float)y); +#endif + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutNum(self, (float)sw); + S_OutNum(self, (float)sh); +#ifdef BM_CACHE + S_OutTok(self, "mtx", 1); /* new */ + S_OutTok(self, "<", 0); /* new */ + self->start_image = 1; +#else + if( format==1 ){ + if(self->RevImage) + S_OutTok(self, "Im1rev", 1); + else + S_OutTok(self, "Im1", 1); + } + else S_OutTok(self, "Im24", 1); +#endif + self->ImageFormat = format; + self->CurColor = savClr; +} + +void +PsOut_EndImage(PsOutPtr self) +{ + if( self->ImgSkip ) { self->ImgSkip = 0; return; } + if( self->InTile ) + { + S_OutTok(self, ">", 1); + if( self->ImageFormat==1 && self->InTile==PsTile ) + { + if( self->ImgFClr==0xFFFFFF ) + { + PsOut_Color(self, self->ImgFClr); + PsOut_FillRect(self, self->ImgX, self->ImgY, self->SclW, self->SclH); + PsOut_Color(self, self->ImgBClr); + } + else + { + PsOut_Color(self, self->ImgBClr); + PsOut_FillRect(self, self->ImgX, self->ImgY, self->SclW, self->SclH); + PsOut_Color(self, self->ImgFClr); + } + } + S_OutNum(self, (float)self->ImgX); + S_OutNum(self, (float)self->ImgY); + S_OutNum(self, (float)self->ImgW); + S_OutNum(self, (float)self->ImgH); + S_OutNum(self, (float)self->SclW); + S_OutNum(self, (float)self->SclH); + if( self->ImageFormat==1 ) S_OutTok(self, "Im1t", 1); + else S_OutTok(self, "Im24t", 1); + self->ImageFormat = 0; + self->RevImage = 0; + return; + } + +#ifdef BM_CACHE + if(self->start_image) + S_OutTok(self, "> im", 1); /* new */ +#endif + self->ImageFormat = 0; + self->RevImage = 0; + S_Flush(self); +#ifdef BM_CACHE + if(self->start_image) + { + self->start_image = 0; + S_OutTok(self, "gr", 0); + } + else + S_OutTok(self, "gr", 1); +#else + S_OutTok(self, "gr", 1); +#endif +} + +void +PsOut_OutImageBytes(PsOutPtr self, int nBytes, char *bytes) +{ + int i; + char buf[5]; + + if( (!self->ImageFormat) || self->ImgSkip ) return; + for( i=0 ; iRevImage ) sprintf(buf, "%02x", (int)(bytes[i]^0xFF)&0xFF); + else sprintf(buf, "%02x", (int)bytes[i]&0xFF); + strcat(self->Buf, buf); + if( strlen(self->Buf)>70 ) S_Flush(self); + } +} + +void +PsOut_BeginFrame(PsOutPtr self, int xoff, int yoff, int x, int y, + int w, int h) +{ + int xo = self->XOff; + int yo = self->YOff; + + if( self->InFrame ) xo = yo = 0; + S_OutTok(self, "gs", 0); + S_OutNum(self, (float)(x+xo)); + S_OutNum(self, (float)(y+yo)); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutTok(self, "R cl n", 0); + xoff += xo; yoff += yo; + if( xoff || yoff ) + { + S_OutNum(self, (float)xoff); + S_OutNum(self, (float)yoff); + S_OutTok(self, "tr", 0); + } + S_OutTok(self, "gs", 1); + self->InFrame += 1; +} + +void +PsOut_EndFrame(PsOutPtr self) +{ + self->InFrame -= 1; + if( self->InFrame<0 ) self->InFrame = 0; + S_OutTok(self, "gr gr", 1); + PsOut_DirtyAttributes(self); +} + +int +PsOut_BeginPattern(PsOutPtr self, void *tag, int w, int h, PsFillEnum type, + int bclr, int fclr) +{ + int i; + char key[64]; + + for( i=0 ; iNPatterns ; i++ ) + { if( self->Patterns[i].tag==tag && self->Patterns[i].type==type ) break; } + if( iNPatterns ) return(1); + if( (self->NPatterns+1)>self->MxPatterns ) + { + if( self->Patterns ) + { + self->MxPatterns *= 2; + self->Patterns = + (PsPatPtr)xrealloc(self->Patterns, sizeof(PsPatRec)*self->MxPatterns); + } + else + { + self->MxPatterns = 64; + self->Patterns = (PsPatPtr)xalloc(sizeof(PsPatRec)*self->MxPatterns); + } + } + self->Patterns[self->NPatterns].tag = tag; + self->Patterns[self->NPatterns].type = type; + sprintf(key, "/ %d", (int)tag); + switch(type) { + case PsTile: key[1] = 't'; break; + case PsStip: key[1] = 's'; break; + case PsOpStip: key[1] = 'o'; break; } + S_OutTok(self, key, 0); + S_OutTok(self, "db/PatternType 1 d/PaintType 1 d", 0); + S_OutTok(self, "/TilingType 1 d/BBox[0 0", 0); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutTok(self, "]d/XStep", 0); + S_OutNum(self, (float)w); + S_OutTok(self, "d/YStep", 0); + S_OutNum(self, (float)h); + S_OutTok(self, "d/PaintProc{bg sv", 1); + if( type==PsOpStip ) + { + S_Color(self, bclr); + S_OutTok(self, "0 0", 0); + S_OutNum(self, (float)w); + S_OutNum(self, (float)h); + S_OutTok(self, "R fl", 1); + } + if( type!=PsTile ) S_Color(self, fclr); + self->NPatterns += 1; + self->InTile = type; + return(0); +} + +void +PsOut_EndPattern(PsOutPtr self) +{ + self->InTile = PsSolid; + S_OutTok(self, "rs ed}d de im_ mp d", 1); +} + +void +PsOut_SetPattern(PsOutPtr self, void *tag, PsFillEnum type) +{ + int i; + char key[64]; + + for( i=0 ; iNPatterns ; i++ ) + { if( tag==self->Patterns[i].tag && type==self->Patterns[i].type ) break; } + if( i>=self->NPatterns ) return; + sprintf(key, " %d", (int)tag); + switch(type) { + case PsTile: key[0] = 't'; break; + case PsStip: key[0] = 's'; break; + case PsOpStip: key[0] = 'o'; break; } + S_OutTok(self, key, 0); + S_OutTok(self, "spt", 1); + self->CurColor = 0xFFFFFFFF; +} + +void +PsOut_RawData(PsOutPtr self, char *data, int len) +{ + S_Flush(self); + if (!ferror(self->Fp)) { + (void) fwrite(data, 1, len, self->Fp); + } +} + +void +PsOut_DownloadType1(PsOutPtr self, char *name, char *fname) +{ + int i; + int stt; + char buf[256]; + FILE *fp; + + for( i=0 ; iNDownloads ; i++ ) + { if( strcmp(name, self->Downloads[i])==0 ) break; } + if( iNDownloads ) return; + + if( (self->NDownloads+1)>self->MxDownloads ) + { + if( self->NDownloads ) + { + self->MxDownloads *= 2; + self->Downloads = (char **)xrealloc(self->Downloads, + self->MxDownloads*sizeof(char *)); + } + else + { + self->MxDownloads = 32; + self->Downloads = (char **)xalloc(self->MxDownloads*sizeof(char *)); + } + } + + self->Downloads[self->NDownloads] = (char *)xalloc(strlen(name)+1); + strcpy(self->Downloads[self->NDownloads], name); + self->NDownloads += 1; + + S_Flush(self); + sprintf(buf, "%%%%BeginFont: %s", name); + S_Comment(self, buf); + fp = fopen(fname, "r"); + if( !fp ) return; + fread(buf, 1, 1, fp); + fseek(fp, (long)0, 0); + if( (buf[0]&0xFF)==0x80 ) + { + int len; + + for(;;) + { + stt = fread(buf, 1, 2, fp); + if( stt!=2 || (buf[0]&0xFF)!=0x80 ) break; + if( (int)buf[1]<1 || (int)buf[1]>2 ) break; + stt = fread(buf, 1, 4, fp); + if( stt!=4 ) break; + len = ((buf[3]&0xFF)<<24)|((buf[2]&0xFF)<<16)| + ((buf[1]&0xFF)<<8)|(buf[0]&0xFF); + for(; len ;) + { + i = len<256 ? len : 256; + stt = fread(buf, 1, i, fp); + if( stt<=0 ) break; + if (!ferror(self->Fp)) { + (void) fwrite(buf, 1, stt, self->Fp); + } + if( sttFp)) { + (void) fwrite(buf, 1, stt, self->Fp); + } + if( stt<256 ) break; + } + } + fclose(fp); + S_Flush(self); + S_Comment(self, "%%EndFont"); +} diff --git a/Xprint/ps/psout.h b/Xprint/ps/psout.h new file mode 100644 index 000000000..e8ca56458 --- /dev/null +++ b/Xprint/ps/psout.h @@ -0,0 +1,202 @@ +/* $Xorg: psout.h,v 1.6 2001/02/09 02:04:37 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * (c) Copyright 1996 Hewlett-Packard Company + * (c) Copyright 1996 International Business Machines Corp. + * (c) Copyright 1996 Sun Microsystems, Inc. + * (c) Copyright 1996 Novell, Inc. + * (c) Copyright 1996 Digital Equipment Corp. + * (c) Copyright 1996 Fujitsu Limited + * (c) Copyright 1996 Hitachi, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the names of the copyright holders + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * from said copyright holders. + */ + +/******************************************************************* +** +** ********************************************************* +** * +** * File: psout.h +** * +** * Contents: Include file for psout.c +** * +** * Created By: Roger Helmendach (Liberty Systems) +** * +** * Copyright: Copyright 1996 The Open Group, Inc. +** * +** ********************************************************* +** +********************************************************************/ + +#ifndef _psout_ +#define _psout_ + +#include + +typedef enum PsCapEnum_ { PsCButt=0, PsCRound, PsCSquare } PsCapEnum; +typedef enum PsJoinEnum_ { PsJMiter=0, PsJRound, PsJBevel } PsJoinEnum; +typedef enum PsArcEnum_ { PsChord, PsPieSlice } PsArcEnum; +typedef enum PsRuleEnum_ { PsEvenOdd, PsNZWinding } PsRuleEnum; +typedef enum PsFillEnum_ { PsSolid=0, PsTile, PsStip, PsOpStip } PsFillEnum; + +typedef struct PsPointRec_ +{ + int x; + int y; +} PsPointRec; + +typedef PsPointRec *PsPointPtr; + +typedef struct PsRectRec_ +{ + int x; + int y; + int w; + int h; +} PsRectRec; + +typedef PsRectRec *PsRectPtr; + +typedef struct PsArcRec_ +{ + int x; + int y; + int w; + int h; + int a1; + int a2; + PsArcEnum style; +} PsArcRec; + +typedef PsArcRec *PsArcPtr; + +#define PSOUT_RECT 0 +#define PSOUT_ARC 1 +#define PSOUT_POINTS 2 + +typedef struct PsElmRec_ +{ + int type; + int nPoints; + union + { + PsRectRec rect; + PsArcRec arc; + PsPointPtr points; + } c; +} PsElmRec; + +typedef PsElmRec *PsElmPtr; + +typedef struct PsClipRec_ +{ + int nRects; + PsRectPtr rects; + int nElms; + PsElmPtr elms; + int nOutterClips; + PsRectPtr outterClips; +} PsClipRec; + +typedef PsClipRec *PsClipPtr; + +typedef struct PsOutRec_ *PsOutPtr; + +extern PsOutPtr PsOut_BeginFile(FILE *fp, int orient, int count, int plex, + int res, int wd, int ht, Bool raw); +extern void PsOut_EndFile(PsOutPtr self, int closeFile); +extern void PsOut_BeginPage(PsOutPtr self, int orient, int count, int plex, + int res, int wd, int ht); +extern void PsOut_EndPage(PsOutPtr self); +extern void PsOut_DirtyAttributes(PsOutPtr self); +extern void PsOut_Comment(PsOutPtr self, char *comment); +extern void PsOut_Offset(PsOutPtr self, int x, int y); + +extern void PsOut_Clip(PsOutPtr self, int clpTyp, PsClipPtr clpinf); + +extern void PsOut_Color(PsOutPtr self, int clr); +extern void PsOut_FillRule(PsOutPtr self, PsRuleEnum rule); +extern void PsOut_LineAttrs(PsOutPtr self, int wd, PsCapEnum cap, + PsJoinEnum join, int nDsh, int *dsh, int dshOff, + int bclr); +extern void PsOut_TextAttrs(PsOutPtr self, char *fnam, int siz, int iso); +extern void PsOut_TextAttrsMtx(PsOutPtr self, char *fnam, float *mtx, int iso); + +extern void PsOut_Polygon(PsOutPtr self, int nPts, PsPointPtr pts); +extern void PsOut_FillRect(PsOutPtr self, int x, int y, int w, int h); +extern void PsOut_FillArc(PsOutPtr self, int x, int y, int w, int h, + float ang1, float ang2, PsArcEnum style); + +extern void PsOut_Lines(PsOutPtr self, int nPts, PsPointPtr pts); +extern void PsOut_Points(PsOutPtr self, int nPts, PsPointPtr pts); +extern void PsOut_DrawRect(PsOutPtr self, int x, int y, int w, int h); +extern void PsOut_DrawArc(PsOutPtr self, int x, int y, int w, int h, + float ang1, float ang2); + +extern void PsOut_Text(PsOutPtr self, int x, int y, char *text, int textl, + int bclr); + +extern void PsOut_BeginImage(PsOutPtr self, int bclr, int fclr, int x, int y, + int w, int h, int sw, int sh, int format); +extern void PsOut_EndImage(PsOutPtr self); +extern void PsOut_OutImageBytes(PsOutPtr self, int nBytes, char *bytes); + +extern void PsOut_BeginFrame(PsOutPtr self, int xoff, int yoff, int x, int y, + int w, int h); +extern void PsOut_EndFrame(PsOutPtr self); + +extern int PsOut_BeginPattern(PsOutPtr self, void *tag, int w, int h, + PsFillEnum type, int bclr, int fclr); +extern void PsOut_EndPattern(PsOutPtr self); +extern void PsOut_SetPattern(PsOutPtr self, void *tag, PsFillEnum type); + +extern void PsOut_RawData(PsOutPtr self, char *data, int len); +extern void PsOut_DownloadType1(PsOutPtr self, char *name, char *fname); + +#endif diff --git a/Xprint/raster/Raster.c b/Xprint/raster/Raster.c new file mode 100644 index 000000000..db72b9b32 --- /dev/null +++ b/Xprint/raster/Raster.c @@ -0,0 +1,1585 @@ +/* $Xorg: Raster.c,v 1.4 2001/03/14 18:46:12 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: printer/Raster.c +** * +** * Contents: +** * Raster driver for the print server. +** * +** * Copyright: Copyright 1993, 1995 Hewlett-Packard Company +** * +** ********************************************************* +** +********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "X.h" +#include "Xos.h" /* for SIGCLD on pre-POSIX systems */ +#define NEED_EVENTS +#include "Xproto.h" +#undef NEED_EVENTS +#include "Xatom.h" +#include "misc.h" +#include "dixstruct.h" +#include "scrnintstr.h" +#include "screenint.h" +#include "colormapst.h" +#include "windowstr.h" +#include "propertyst.h" +#include "servermd.h" /* needed for IMAGE_BUFSIZE */ + +#define _XP_PRINT_SERVER_ +#include "extensions/Print.h" +#undef _XP_PRINT_SERVER_ +#include "Raster.h" + +#include "attributes.h" +#include "AttrValid.h" + +static void AllocateRasterPrivates( + ScreenPtr pScreen); +static Bool RasterChangeWindowAttributes( + WindowPtr pWin, + unsigned long mask); +static int StartJob( + XpContextPtr pCon, + Bool sendClientData); +static int StartPage( + XpContextPtr pCon, + WindowPtr pWin); +static int StartDoc( + XpContextPtr pCon); +static int EndDoc( + XpContextPtr pCon, + Bool cancel); +static int EndJob( + XpContextPtr pCon, + Bool cancel); +static int EndPage( + XpContextPtr pCon, + WindowPtr pWin, + Bool cancel); +static int DocumentData( + XpContextPtr pCon, + DrawablePtr pDraw, + char *pData, + int len_data, + char *pDoc_fmt, + int len_fmt, + char *pOptions, + int len_options, + ClientPtr client); +static int GetDocumentData( + XpContextPtr pContext, + ClientPtr client, + int maxBufferSize); +static void FreePageFiles( + RasterContextPrivPtr pWinPriv); +static int SystemCmd( + char *pCommand); +static Bool RasterCloseScreen( + int index, + ScreenPtr pScreen); +static int RasterInitContext(XpContextPtr pCon); +static Bool RasterDestroyContext(XpContextPtr pCon); +static char *RasterGetAttributes( + XpContextPtr pContext, + XPAttributes class); +static char *RasterGetOneAttribute(XpContextPtr pCon, + XPAttributes class, + char *attribute); +static void RasterSetAttributes(XpContextPtr pCon, + XPAttributes class, + char *attributes); +static void RasterAugmentAttributes(XpContextPtr pCon, + XPAttributes class, + char *attributes); +static int RasterMediumDimensions(XpContextPtr pCon, + CARD16 *width, + CARD16 *height); +static int RasterReproducibleArea(XpContextPtr pCon, + xRectangle *pRect); + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define DOC_PCL 1 +#define DOC_RASTER 2 + +extern Bool _XpBoolNoop(); +extern void _XpVoidNoop(); +extern void XpDestroyAttributes(); +extern char *ReplaceFileString( + char *string, + char *inFileName, + char *outFileName); +extern char *XpGetConfigDir(); + +extern XpValidatePoolsRec RasterValidatePoolsRec; /* From RasterAttVal.c */ + +static int RasterScreenPrivateIndex, RasterContextPrivateIndex; +static int RasterGeneration = 0; +static char RASTER_DRIV_NAME[] = "XP-RASTER"; +static int doc_type = DOC_RASTER; + +#define ABSOLUTE_PCLCOMP_PATH1 "/usr/openwin/bin/pclcomp" +#define ABSOLUTE_PCLCOMP_PATH2 "/usr/X11/bin/pclcomp" + +static char *pcl3_output_cmds[] = { + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -0 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -01 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -02 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -03 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -012 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -013 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -023 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% | pclcomp -0123 > %(OutFile)%", + "xpr -device ljet -rv -landscape < %(InFile)% > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -0 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -01 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -02 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -03 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -012 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -013 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -023 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% | pclcomp -0123 > %(OutFile)%", + "xpr -device ljet -rv < %(InFile)% > %(OutFile)%"}; + +Bool +InitializeRasterDriver( + int ndx, + ScreenPtr pScreen, + int argc, + char **argv) +{ + char specifier[MAX_TOKEN_LEN]; + int xRes, yRes, maxWidth, maxHeight; + int maxRes, maxDim, numBytes; + RasterScreenPrivPtr pPriv; + XpDriverFuncsPtr pFuncs; + char **printerNames, *printDescFile; + int numPrinters; + + /* + * Register this driver's InitContext function with the print extension. + * This is a bit + * sleazy, as the extension hasn't yet been initialized, but the + * extension needs to know this, and this seems the best time to + * provide the information. + */ + XpRegisterInitFunc( pScreen, RASTER_DRIV_NAME, RasterInitContext ); + + /* + * Create and load the devPrivate for the printer layer. + */ + AllocateRasterPrivates(pScreen); + + pPriv = (RasterScreenPrivPtr) + pScreen->devPrivates[RasterScreenPrivateIndex].ptr; + + maxDim = MAX( pScreen->height, pScreen->width ); + numBytes = maxDim + BITMAP_SCANLINE_PAD - 1; /* pixels per row */ + numBytes *= maxDim; + numBytes /= 8; /* bytes per row */ + xRes = pScreen->width / (pScreen->mmWidth / 25.4); + yRes = pScreen->height / (pScreen->mmHeight / 25.4); + maxRes = MAX( xRes, yRes ); + + pPriv->pBits = (char *)xalloc(numBytes); + + /* + * Have to allocate maxDim X maxDim to allow for landscape mode. + */ + mfbScreenInit(pScreen, pPriv->pBits, maxDim, maxDim, maxRes, + maxRes, maxDim); + pScreen->blackPixel = 1; + pScreen->whitePixel = 0; + if(mfbCreateDefColormap(pScreen) == FALSE) + ; /* XXX what do I do if it fails? */ + + /* + cfbScreenInit(pScreen, pPriv->pBits, maxWidth, maxHeight, maxXres, + maxYres, maxWidth); + scalingScreenInit(pScreen); + */ + + pScreen->SaveScreen = _XpBoolNoop; + pPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pScreen->ChangeWindowAttributes = RasterChangeWindowAttributes; + pPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = RasterCloseScreen; + + return TRUE; +} + +/* + * GetPropString searches the context's config database for a property + * by the name of propName. If found, it returns the property's + * value, otherwise it returns NULL unless the requested attribute + * is RASTER_PRINT_PAGE_COMMAND, in which case it returns a hard-coded + * default string to invoke xpr to produce a PostScript(tm) formatted + * raster. + */ + +static char * +GetPropString( + XpContextPtr pCon, + char *propName) +{ + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + char *type; + XrmValue val; + struct stat status; + int pclcomp_exists = 0; + + if( XrmGetResource(pConPriv->config, propName, propName, &type, &val) == + True ) + return (char *)val.addr; + + if( !strcmp( propName, RASTER_PRINT_PAGE_COMMAND ) ) + if( doc_type == DOC_RASTER ) + return "xpr -device ps %(InFile)% > %(OutFile)%"; + else + { + XpOid orientation; + XpOid compression; + int pcl3_output_index = 0; + + orientation = XpGetContentOrientation(pCon); + compression = XpGetAvailableCompression(pCon); + + switch(orientation) { + case xpoid_val_content_orientation_landscape: + pcl3_output_index = 0; + break; + default: + pcl3_output_index += 9; + break; + } + + if(stat(ABSOLUTE_PCLCOMP_PATH1, &status) != -1) + pclcomp_exists = 1; + else if(stat(ABSOLUTE_PCLCOMP_PATH2, &status) != -1) + pclcomp_exists = 1; + + if(pclcomp_exists) + switch(compression) { + case xpoid_val_available_compressions_0: + pcl3_output_index += 0; + break; + case xpoid_val_available_compressions_01: + pcl3_output_index += 1; + break; + case xpoid_val_available_compressions_02: + pcl3_output_index += 2; + break; + case xpoid_val_available_compressions_03: + pcl3_output_index += 3; + break; + case xpoid_val_available_compressions_012: + pcl3_output_index += 4; + break; + case xpoid_val_available_compressions_013: + pcl3_output_index += 5; + break; + case xpoid_val_available_compressions_023: + pcl3_output_index += 6; + break; + default: + pcl3_output_index += 7; + break; + } + else + pcl3_output_index += 8; + + return pcl3_output_cmds[pcl3_output_index]; + } + else + return NULL; +} + +static void +SetDocumentType( + XpContextPtr pCon) +{ + XpOidList* attrs_supported; + + /* + * only validate attributes found in document-attributes-supported + */ + attrs_supported = + XpGetListAttr(pCon, XPPrinterAttr, + xpoid_att_document_attributes_supported, + (const XpOidList*)NULL); + + if(XpOidListHasOid(attrs_supported, xpoid_att_document_format)) + { + const char* value_in; + XpOidDocFmt *f; + + value_in = XpGetStringAttr(pCon, XPDocAttr, xpoid_att_document_format); + + f = XpOidDocFmtNew( value_in ); + + if( f != NULL ) + { + if( !strcmp( f->format, "PCL" ) ) + doc_type = DOC_PCL; + else + doc_type = DOC_RASTER; + + XpOidDocFmtDelete( f ); + } + } + + /* + * clean up + */ + XpOidListDelete(attrs_supported); +} + +static int +StartJob( + XpContextPtr pCon, + Bool sendClientData) +{ + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + char *jobHeader; + + SetDocumentType( pCon ); + + /* + * Check for existing page file, and delete it if it exists. + */ + if(pConPriv->pageFileName != (char *)NULL) + { + if(pConPriv->pPageFile != (FILE *)NULL) + { + fclose(pConPriv->pPageFile); + pConPriv->pPageFile = (FILE *)NULL; + } + unlink(pConPriv->pageFileName); + Xfree(pConPriv->pageFileName); + pConPriv->pageFileName = (char *)NULL; + } + + /* + * Create a temporary file to store the printer output. + */ + if(!sendClientData) + { + /* + * Create a temporary file to store the printer output. + */ + if (!XpOpenTmpFile("w", &pConPriv->jobFileName, &pConPriv->pJobFile)) + return BadAlloc; + } + + return Success; +} + +/* + * StartDoc and EndDoc are just no-ops in this implementation, since + * our view of the spooler really doesn't recognize documents. + */ + +static int +StartDoc( + XpContextPtr pCon) +{ + return Success; +} + +static int EndDoc( + XpContextPtr pCon, + Bool cancel) +{ + return Success; +} + +/* + * BuidArgVector takes a pointer to a comma-separated list of command + * options and splits it out into an array of argument pointers. The + * caller must not free the optionList after calling this function until + * the returned arg vector is no longer needed, at which time the arg + * vector should also be freed. + */ + +#define SEPARATOR_CHAR (char)',' + +static char ** +BuildArgVector( + char *optionList, + char **argVector, + int argCount) +{ + char *curArg, *lastChar, *endArg; + int optionLen; + + curArg = optionList; + lastChar = optionList + strlen(optionList); /* includes final NULL */ + + while(curArg != (char *)NULL && curArg < lastChar) + { + /* strip leading white space */ + while(curArg < lastChar && isascii((int)*curArg) && + isspace((int)*curArg)) + curArg++; + + if(curArg < lastChar) + { + argVector = (char **)Xrealloc(argVector, + sizeof(char *) * (argCount + 2)); + argVector[argCount] = curArg; + argVector[++argCount] = (char *)NULL; + + endArg = strchr(curArg, SEPARATOR_CHAR); + + /* Should I strip trailing white space ??? */ + + if(endArg != (char *)NULL) + { + *endArg = (char)'\0'; + curArg = endArg + 1; + } + else + curArg = (char *)NULL; + } + } + + return argVector; +} + +static int +EndJob( + XpContextPtr pCon, + Bool cancel) +{ + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + + if( cancel == True ) + { + if(pConPriv->getDocClient != (ClientPtr)NULL) { + XpFinishDocData(pConPriv->getDocClient); + + pConPriv->getDocClient = (ClientPtr)NULL; + pConPriv->getDocBufSize = 0; + } + + if(pConPriv->jobFileName != (char *)NULL) + { + unlink(pConPriv->jobFileName); + Xfree(pConPriv->jobFileName); + pConPriv->jobFileName = (char *)NULL; + } + + return Success; + } + + if(pConPriv->getDocClient != (ClientPtr)NULL&&pConPriv->getDocBufSize > 0) + { + XpFinishDocData(pConPriv->getDocClient); + + pConPriv->getDocClient = (ClientPtr)NULL; + pConPriv->getDocBufSize = 0; + + return Success; + } + + if(pConPriv->pJobFile != (FILE *)NULL) + { + fclose(pConPriv->pJobFile); + pConPriv->pJobFile = (FILE *)NULL; + + if(pConPriv->jobFileName != (char *)NULL) + { + XpSubmitJob( pConPriv->jobFileName, pCon ); + unlink(pConPriv->jobFileName); + Xfree(pConPriv->jobFileName); + pConPriv->jobFileName = (char *)NULL; + } + } + + return Success; +} + +/* StartPage + * + * If page file exists + * close page file + * set page file pointer = NULL + * unlink page file + */ +static int +StartPage( + XpContextPtr pCon, + WindowPtr pWin) +{ + register WindowPtr pChild; + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + unsigned short width, height; + xEvent event; + + if(pConPriv->pPageFile != (FILE *)NULL) + { + fclose(pConPriv->pPageFile); + pConPriv->pPageFile = (FILE *)NULL; + } + if(pConPriv->pageFileName != (char *)NULL) + { + unlink(pConPriv->pageFileName); + pConPriv->pageFileName = (char *)NULL; + } + + return Success; +} + +#include "X11/XWDFile.h" + + +#define lowbit(x) ((x) & (~(x) + 1)) + +/* + * Get the XWDColors of all pixels in colormap - returns # of colors + */ +static XWDColor * +Get_XWDColors( + ColormapPtr pCmap) +{ + int i, ncolors; + xrgb *prgbList; + Pixel *pPixels; + XWDColor *colors; + + ncolors = pCmap->pVisual->ColormapEntries; + if (!(colors = (XWDColor *) malloc (sizeof(XWDColor) * ncolors))) + return (XWDColor *) NULL; + if (!(prgbList = (xrgb*) malloc(sizeof(xrgb) * ncolors))) + { + Xfree(colors); + return (XWDColor *) NULL; + } + if (!(pPixels = (Pixel*) malloc(sizeof(Pixel) * ncolors))) + { + Xfree(colors); + Xfree(prgbList); + return (XWDColor *) NULL; + } + + if (pCmap->pVisual->class == DirectColor || + pCmap->pVisual->class == TrueColor) { + Pixel red, green, blue, red1, green1, blue1; + + red = green = blue = 0; + red1 = lowbit(pCmap->pVisual->redMask); + green1 = lowbit(pCmap->pVisual->greenMask); + blue1 = lowbit(pCmap->pVisual->blueMask); + for (i=0; i pCmap->pVisual->redMask) + red = 0; + green += green1; + if (green > pCmap->pVisual->greenMask) + green = 0; + blue += blue1; + if (blue > pCmap->pVisual->blueMask) + blue = 0; + } + } else { + for (i=0; idrawable; + XWDFileHeader header; + int win_name_size; + int header_size; + int ncolors, i; + char *win_name; + VisualPtr pVisual; + ColormapPtr pCmap; + XWDColor *pColors; + unsigned long swaptest = 1; + + widthBytesLine = PixmapBytePad(pWin->drawable.width, pWin->drawable.depth); + length = widthBytesLine * pWin->drawable.height; + height = pWin->drawable.height; + + if(length <= 0) + return Success; + + if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && (length & 3)) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & 3) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) Xalloc(length))) + return (BadAlloc); + + /* + * Start of Xwd header code. + */ + + /* + * XXX - Should we use the real window name??? + */ + win_name = "xwdump"; + /* sizeof(char) is included for the null string terminator. */ + win_name_size = strlen(win_name) + sizeof(char); + + pCmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP); + pVisual = pCmap->pVisual; + if((pColors = Get_XWDColors(pCmap)) == (XWDColor *)NULL) + { + Xfree(pBuf); + return (BadAlloc); + } + + /* + * Write out header information. + */ + header_size = sizeof(header) + win_name_size; + header.header_size = (CARD32) header_size; + header.file_version = (CARD32) XWD_FILE_VERSION; + header.pixmap_format = (CARD32) ZPixmap; /* Must match GetImage below */ + header.pixmap_depth = (CARD32) pDraw->depth; + header.pixmap_width = (CARD32) pDraw->width; + header.pixmap_height = (CARD32) pDraw->height; + header.xoffset = (CARD32) 0; + header.byte_order = (CARD32) screenInfo.imageByteOrder; + header.bitmap_unit = (CARD32) screenInfo.bitmapScanlineUnit; + header.bitmap_bit_order = (CARD32) screenInfo.bitmapBitOrder; + header.bitmap_pad = (CARD32) screenInfo.bitmapScanlinePad; + header.bits_per_pixel = (CARD32) pDraw->bitsPerPixel; + header.bytes_per_line = (CARD32) widthBytesLine; + header.visual_class = (CARD32) pVisual->class; + header.red_mask = (CARD32) pVisual->redMask; + header.green_mask = (CARD32) pVisual->greenMask; + header.blue_mask = (CARD32) pVisual->blueMask; + header.bits_per_rgb = (CARD32) pVisual->bitsPerRGBValue; + header.colormap_entries = (CARD32) pVisual->ColormapEntries; + header.ncolors = ncolors = (CARD32) pVisual->ColormapEntries; + header.window_width = (CARD32) pDraw->width; + header.window_height = (CARD32) pDraw->height; + header.window_x = 0; + header.window_y = 0; + header.window_bdrwidth = (CARD32) 0; + + if (*(char *) &swaptest) { + _swaplong((char *) &header, sizeof(header)); + for (i = 0; i < ncolors; i++) { + _swaplong((char *) &pColors[i].pixel, sizeof(long)); + _swapshort((char *) &pColors[i].red, 3 * sizeof(short)); + } + } + + (void) fwrite((char *)&header, sizeof(header), 1, pRasterFile); + (void) fwrite(win_name, win_name_size, 1, pRasterFile); + (void) fwrite((char *) pColors, sizeof(XWDColor), ncolors, pRasterFile); + + Xfree(pColors); + + /* + * End of Xwd header code. + */ + + linesDone = 0; + while(height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + 0, + linesDone, + pWin->drawable.width, + nlines, + ZPixmap, + ~0, + pBuf); + + if(fwrite(pBuf, sizeof(char), (size_t)(nlines * widthBytesLine), + pRasterFile) != + (size_t)(nlines * widthBytesLine)) + { + Xfree(pBuf); + return BadAlloc; + } + linesDone += nlines; + } + Xfree(pBuf); + return Success; +} + + +static int +SendPage( XpContextPtr pCon ) +{ + struct stat statBuf; + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + + if(stat(pConPriv->pageFileName, &statBuf) < 0) + return BadAlloc; + + return XpSendDocumentData(pConPriv->getDocClient, + pConPriv->pPageFile, (int)statBuf.st_size, + pConPriv->getDocBufSize); +} + +/* + * EndPage: + * + * If page file doesn't exist: + * { + * Create page file + * Open page file + * Write page header to page file + * if(preRasterFile exists) + * copy preRasterFile contents to page file + * if(noRasterFile exists) + * write noRasterFile contents to page file + * else + * Create raster image file + * Open raster image file + * GetImage data + * Write Image data to raster image file + * invoke page_command on raster image file + * Write raster image file contents to page file + * Unlink tempPage file + * if(postRasterFile exists) + * write postRasterFile contents to page file + * Write page trailer to page file + * } + * Write page file to job file + */ +static int +EndPage( + XpContextPtr pCon, + WindowPtr pWin, + Bool cancel) +{ + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + struct stat statBuf; + char *rasterFileName = (char *)NULL, *pCommand = (char *)NULL, + *pHeader = (char *)NULL, *pTrailer = (char *)NULL; + FILE *pRasterFile = (FILE *)NULL; + + if( cancel == True ) + return Success; + + if(pConPriv->pageFileName == (char *)NULL) + { + /* + * Open the page file. + */ + if (!XpOpenTmpFile("w+", &pConPriv->pageFileName, + &pConPriv->pPageFile)) + goto BAD_PAGE_ALLOC; + + /* + * Copy any pre-raster document data to the page file. + */ + if(pConPriv->pPreRasterFile != (FILE *)NULL) + { + if(CopyContentsAndDelete(&pConPriv->pPreRasterFile, + &pConPriv->preRasterFileName, + pConPriv->pPageFile) == FALSE) + goto BAD_PAGE_ALLOC; + } + + /* + * Copy either the no-raster document data, or the raster + * data itself to the page file. + * If the no-raster file exists, then we don't process the + * actual window raster bits. + */ + if(pConPriv->pNoRasterFile != (FILE *)NULL) + { + if(CopyContentsAndDelete(&pConPriv->pNoRasterFile, + &pConPriv->noRasterFileName, + pConPriv->pPageFile) == FALSE) + goto BAD_PAGE_ALLOC; + } + else + { + /* + * Open the raster image file. + */ + if (!XpOpenTmpFile("w", &rasterFileName, &pRasterFile)) + goto BAD_PAGE_ALLOC; + + /* + * Write the page image data to the raster image file. + */ + if(WriteWindowRaster(pWin, pRasterFile) != Success) + goto BAD_PAGE_ALLOC; + + /* + * Invoke the page_command on the raster image file. + */ + if((pCommand = GetPropString(pCon, RASTER_PRINT_PAGE_COMMAND)) != + (char *)NULL) + { + char *outFileName; + FILE *pOutFile; + + if (!XpOpenTmpFile("w", &outFileName, &pOutFile)) + goto BAD_PAGE_ALLOC; + fclose(pOutFile); + + pCommand = ReplaceFileString(strdup(pCommand), rasterFileName, + outFileName); + fclose(pRasterFile); + SystemCmd(pCommand); + free(pCommand); + /* + * Delete the unprocessed raster file. + */ + unlink(rasterFileName); + Xfree(rasterFileName); + rasterFileName = outFileName; + if((pRasterFile = fopen(rasterFileName, "r")) == (FILE *)NULL) + goto BAD_PAGE_ALLOC; + } + else + { + fclose(pRasterFile); + if((pRasterFile = fopen(rasterFileName, "r")) == (FILE *)NULL) + goto BAD_PAGE_ALLOC; + } + + /* + * Copy the raster image file contents to the page file. + * Note that pRasterFile must be set to the start of the + * raster file. + */ + if(CopyContentsAndDelete(&pRasterFile, + &rasterFileName, + pConPriv->pPageFile) == FALSE) + goto BAD_PAGE_ALLOC; + } + + /* + * Copy any post-raster document data to the page file. + */ + if(pConPriv->pPostRasterFile != (FILE *)NULL) + { + if(CopyContentsAndDelete(&pConPriv->pPostRasterFile, + &pConPriv->postRasterFileName, + pConPriv->pPageFile) == FALSE) + goto BAD_PAGE_ALLOC; + } + + } + + /* + * Write the page file contents to the job file or to the client + * performing GetDocumentData. + * pConPriv->pPageFile must first be set to the start of the page file. + */ + rewind(pConPriv->pPageFile); + if(stat(pConPriv->pageFileName, &statBuf) < 0) + goto BAD_PAGE_ALLOC; + + /* + * Send the page data to whatever client has called GetDocumentData. + */ + if(pConPriv->getDocClient != (ClientPtr)NULL&&pConPriv->getDocBufSize > 0) + { + int retval; + /* + * We should do something like the following: suspend the + * caller until we can gracefully write all the data in small + * chunks to the receiver, but for now we'll just call WriteToClient + * on the huge chunk + */ + retval = SendPage(pCon); + fclose(pConPriv->pPageFile); + pConPriv->pPageFile = (FILE *)NULL; + unlink(pConPriv->pageFileName); + free(pConPriv->pageFileName); + pConPriv->pageFileName = (char *)NULL; + return retval; + } + + if(pConPriv->pJobFile == (FILE *)NULL) + { + /* + * This shouldn't be necessary. I believe we only get here if + * someone calls "EndPage" prior to "StartJob". This error + * condition should probably be trapped at a higher level. + */ + + if(pConPriv->jobFileName != (char *)NULL) + Xfree(pConPriv->jobFileName); + /* + * Create a temporary file to store the printer output. + */ + if (!XpOpenTmpFile("w", &pConPriv->jobFileName, &pConPriv->pJobFile)) + goto BAD_PAGE_ALLOC; + } + + if(TransferBytes(pConPriv->pPageFile, pConPriv->pJobFile, + (int)statBuf.st_size) != (int)statBuf.st_size) + goto BAD_PAGE_ALLOC; + + fclose(pConPriv->pPageFile); + pConPriv->pPageFile = (FILE *)NULL; + unlink(pConPriv->pageFileName); + free(pConPriv->pageFileName); + pConPriv->pageFileName = (char *)NULL; + + return Success; + + BAD_PAGE_ALLOC: + + FreePageFiles(pConPriv); + + if(pRasterFile != (FILE *)NULL) + fclose(pRasterFile); + if(rasterFileName != (char *)NULL) + { + unlink(rasterFileName); + Xfree(rasterFileName); + } + return BadAlloc; +} + +static int +DocumentData( + XpContextPtr pCon, + DrawablePtr pDraw, + char *pData, + int len_data, + char *pDoc_fmt, + int len_fmt, + char *pOptions, + int len_options, + ClientPtr client) +{ + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + char *preRasterStr = PRE_RASTER, *postRasterStr = POST_RASTER, + *noRasterStr = NO_RASTER; + + /* + * Check that options equals either PRE_RASTER or POST_RASTER. + */ + if(len_options == strlen(preRasterStr) && + strncmp(pOptions, preRasterStr, strlen(preRasterStr)) == 0) + { + if(pConPriv->pPreRasterFile == (FILE *)NULL) + { + if (!XpOpenTmpFile("w+", &pConPriv->preRasterFileName, + &pConPriv->pPreRasterFile)) + return BadAlloc; + } + if(fwrite(pData, sizeof(char), (size_t)len_data, + pConPriv->pPreRasterFile) != (size_t)len_data) + return BadAlloc; + fflush(pConPriv->pPreRasterFile); + } + else if(len_options == strlen(postRasterStr) && + strncmp(pOptions, postRasterStr, strlen(postRasterStr)) == 0) + { + if(pConPriv->pPostRasterFile == (FILE *)NULL) + { + if (!XpOpenTmpFile("w+", &pConPriv->postRasterFileName, + &pConPriv->pPostRasterFile)) + return BadAlloc; + } + if(fwrite(pData, sizeof(char), (size_t)len_data, + pConPriv->pPostRasterFile) != (size_t)len_data) + return BadAlloc; + fflush(pConPriv->pPostRasterFile); + } + else if(len_options == strlen(noRasterStr) && + strncmp(pOptions, noRasterStr, strlen(noRasterStr)) == 0) + { + if(pConPriv->pNoRasterFile == (FILE *)NULL) + { + if (!XpOpenTmpFile("w+", &pConPriv->noRasterFileName, + &pConPriv->pNoRasterFile)) + return BadAlloc; + } + if(fwrite(pData, sizeof(char), (size_t)len_data, + pConPriv->pNoRasterFile) != (size_t)len_data) + return BadAlloc; + fflush(pConPriv->pNoRasterFile); + } + else + return BadValue; + + return Success; +} + +/* + * GetDocumentData notes which client is requesting the document data for + * a particular context. The Raster driver's EndPage function causes the + * data to be written to the proper client. + */ +static int +GetDocumentData( + XpContextPtr pContext, + ClientPtr client, + int maxBufferSize) +{ + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pContext->devPrivates[RasterContextPrivateIndex].ptr; + + pConPriv->getDocClient = client; + pConPriv->getDocBufSize = maxBufferSize; + return Success; +} + +static void +AllocateRasterPrivates( + ScreenPtr pScreen) +{ + if(RasterGeneration != serverGeneration) + { + RasterScreenPrivateIndex = AllocateScreenPrivateIndex(); + RasterContextPrivateIndex = XpAllocateContextPrivateIndex(); + XpAllocateContextPrivate( RasterContextPrivateIndex, + sizeof( RasterContextPrivRec ) ); + + RasterGeneration = serverGeneration; + } + pScreen->devPrivates[RasterScreenPrivateIndex].ptr = (pointer)Xalloc( + sizeof(RasterScreenPrivRec)); +} + +/* + * RasterChangeWindowAttributes - Make sure that the window's backing + * store is turned on. + */ +static Bool +RasterChangeWindowAttributes( + WindowPtr pWin, + unsigned long mask) +{ + Bool status = Success; + ScreenPtr pScreen = pWin->drawable.pScreen; + RasterScreenPrivPtr pScreenPriv = (RasterScreenPrivPtr) + pScreen->devPrivates[RasterScreenPrivateIndex].ptr; + + if(pWin->backingStore == NotUseful) + { + pWin->backingStore = WhenMapped; + mask |= CWBackingStore; + } + + if(pScreenPriv->ChangeWindowAttributes != (Bool (*)())NULL) + { + pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes; + status = pScreen->ChangeWindowAttributes(pWin, mask); + pScreen->ChangeWindowAttributes = RasterChangeWindowAttributes; + } + if(status != TRUE) + return status; +} + +/* + * RasterValidateDocFormats - Inspects the files available in the + * ddx-config/XP-RASTER directory to find the names of PDLs for which + * we have processing commands. These names are then intersected with + * the contents of the printer's document-formats-supported attribute, + * and the result is stored back into document-formats-supported. + * We have hard-coded knowledge of how to produce PS, so we always + * leave that in, if it's listed in document-formats-supported, + * even if we don't have a configuration file. If there is a + * configuration file for PS, then its contents will override our default. + */ +static void +RasterValidateDocFormats( + XpContextPtr pCon) +{ +} + +/* + * RasterValidateAttrs - Inspects and Corrects the attribute values + * in the specified context. + */ +static void +RasterValidateAttrs( + XpContextPtr pCon) +{ + RasterValidateDocFormats(pCon); + XpValidatePrinterPool(pCon, &RasterValidatePoolsRec); + XpValidateJobPool(pCon, &RasterValidatePoolsRec); + XpValidateDocumentPool(pCon, &RasterValidatePoolsRec); +} + +/* + * RasterInitContext - Establish the appropriate values for a + * PrintContext used with the Raster Driver. + */ +static char DOC_ATT_SUPP[]="document-attributes-supported:\tdefault-medium document-format"; +static char JOB_ATT_SUPP[]="job-attributes-supported:\t"; +static char DDX_DIR[]="ddx-config"; + +static int +RasterInitContext( + XpContextPtr pCon) +{ + char *configFileName, *val, *attrStr; + RasterContextPrivPtr pConPriv; + XpDriverFuncsPtr pFuncs; + + /* + * Initialize the attribute store for this printer. + */ + XpInitAttributes( pCon ); + + /* + * Validate the attributes + */ + RasterValidateAttrs( pCon ); + + + /* + * Initialize the function pointers + */ + pFuncs = &( pCon->funcs ); + pFuncs->StartJob = StartJob; + pFuncs->EndJob = EndJob; + pFuncs->StartDoc = StartDoc; + pFuncs->EndDoc = EndDoc; + pFuncs->StartPage = StartPage; + pFuncs->EndPage = EndPage; + pFuncs->PutDocumentData = DocumentData; + pFuncs->GetDocumentData = GetDocumentData; + pFuncs->DestroyContext = RasterDestroyContext; + pFuncs->GetAttributes = (char *(*)())RasterGetAttributes; + pFuncs->GetOneAttribute = (char *(*)())RasterGetOneAttribute; + pFuncs->SetAttributes = (int(*)())RasterSetAttributes; + pFuncs->AugmentAttributes = (int(*)())RasterAugmentAttributes; + pFuncs->GetMediumDimensions = (int(*)())RasterMediumDimensions; + pFuncs->GetReproducibleArea = (int(*)())RasterReproducibleArea; + + /* + * Set up the context privates + */ + pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + + pConPriv->jobFileName = (char *)NULL; + pConPriv->pageFileName = (char *)NULL; + pConPriv->preRasterFileName = (char *)NULL; + pConPriv->postRasterFileName = (char *)NULL; + pConPriv->noRasterFileName = (char *)NULL; + pConPriv->pJobFile = (FILE *)NULL; + pConPriv->pPageFile = (FILE *)NULL; + pConPriv->pPreRasterFile = (FILE *)NULL; + pConPriv->pPostRasterFile = (FILE *)NULL; + pConPriv->pNoRasterFile = (FILE *)NULL; + + pConPriv->getDocClient = (ClientPtr)NULL; + pConPriv->getDocBufSize = 0; + + /* + * Get the configuration information for the context's printer + */ + configFileName = XpGetOneAttribute( pCon, XPPrinterAttr, + "xp-ddx-config-file-name" ); + if(configFileName && strlen(configFileName)) + { + if( configFileName[0] == '/' ) + pConPriv->config = XrmGetFileDatabase( configFileName ); + else + { + char *configDir, *configFilePath; + + configDir = XpGetConfigDir(FALSE); + configFilePath = (char *)malloc((strlen(configDir) + + strlen(DDX_DIR) + + strlen(RASTER_DRIV_NAME) + + strlen(configFileName) + + 4)* sizeof(char)); + sprintf(configFilePath, "%s/%s/%s/%s", configDir, DDX_DIR, + RASTER_DRIV_NAME, configFileName); + pConPriv->config = XrmGetFileDatabase(configFilePath); + free(configDir); + free(configFilePath); + } + } + else + pConPriv->config = (XrmDatabase)NULL; + + /* + * Add our own attribute initialization + */ + /* + * document-attributes-supported + */ + val = XpGetOneAttribute(pCon, XPServerAttr, "document-attributes-supported"); + if((attrStr = (char *)xalloc(strlen(val) + strlen(DOC_ATT_SUPP) + 4)) == + (char *)NULL) + return BadAlloc; + sprintf(attrStr, "*%s %s", DOC_ATT_SUPP, val); + XpAugmentAttributes(pCon, XPPrinterAttr, attrStr); + xfree(attrStr); + + /* + * job-attributes-supported + */ + val = XpGetOneAttribute(pCon, XPServerAttr, "job-attributes-supported"); + if((attrStr = (char *)xalloc(strlen(val) + strlen(JOB_ATT_SUPP) + 4)) == + (char *)NULL) + return BadAlloc; + sprintf(attrStr, "*%s %s", JOB_ATT_SUPP, val); + XpAugmentAttributes(pCon, XPPrinterAttr, attrStr); + xfree(attrStr); + + /* + * PageAttributesSupported + */ + XpAugmentAttributes(pCon, XPPrinterAttr, "*xp-page-attributes-supported:"); + + return Success; +} + + + +static Bool +RasterDestroyContext( + XpContextPtr pCon) +{ + RasterContextPrivPtr pConPriv = (RasterContextPrivPtr) + pCon->devPrivates[RasterContextPrivateIndex].ptr; + + /* + * Clean up the temporary files + */ + FreePageFiles( pConPriv ); + + if( pConPriv->pJobFile != (FILE *)NULL ) + { + fclose( pConPriv->pJobFile ); + pConPriv->pJobFile = (FILE *)NULL; + } + if( pConPriv->jobFileName != (char *)NULL ) + { + unlink( pConPriv->jobFileName ); + Xfree( pConPriv->jobFileName ); + } + if(pConPriv->config) + { + XrmDestroyDatabase(pConPriv->config); + pConPriv->config = (XrmDatabase)NULL; + } + + XpDestroyAttributes( pCon ); + return Success; +} + +static char * +RasterGetAttributes( + XpContextPtr pContext, + XPAttributes class) +{ + return XpGetAttributes( pContext, class ); +} + +static char * +RasterGetOneAttribute( + XpContextPtr pContext, + XPAttributes class, + char *attr) +{ + return XpGetOneAttribute( pContext, class, attr ); +} + +static void +RasterSetAttributes(XpContextPtr pCon, + XPAttributes class, + char *attributes) +{ + XpSetAttributes( pCon, class, attributes ); +} + +static void +RasterAugmentAttributes( + XpContextPtr pCon, + XPAttributes class, + char *attributes) +{ + XpAugmentAttributes( pCon, class, attributes ); +} + +static void +FreePageFiles( + RasterContextPrivPtr pConPriv) +{ + if(pConPriv->pPageFile != (FILE *)NULL) + { + fclose(pConPriv->pPageFile); + pConPriv->pPageFile = (FILE *)NULL; + } + if(pConPriv->pageFileName != (char *)NULL) + { + unlink(pConPriv->pageFileName); + Xfree(pConPriv->pageFileName); + pConPriv->pageFileName = (char *)NULL; + } + if(pConPriv->pPreRasterFile != (FILE *)NULL) + { + fclose(pConPriv->pPreRasterFile); + pConPriv->pPreRasterFile = (FILE *)NULL; + } + if(pConPriv->preRasterFileName != (char *)NULL) + { + unlink(pConPriv->preRasterFileName); + Xfree(pConPriv->preRasterFileName); + pConPriv->preRasterFileName = (char *)NULL; + } + if(pConPriv->pPostRasterFile != (FILE *)NULL) + { + fclose(pConPriv->pPostRasterFile); + pConPriv->pPostRasterFile = (FILE *)NULL; + } + if(pConPriv->postRasterFileName != (char *)NULL) + { + unlink(pConPriv->postRasterFileName); + Xfree(pConPriv->postRasterFileName); + pConPriv->postRasterFileName = (char *)NULL; + } + if(pConPriv->pNoRasterFile != (FILE *)NULL) + { + fclose(pConPriv->pNoRasterFile); + pConPriv->pNoRasterFile = (FILE *)NULL; + } + if(pConPriv->noRasterFileName != (char *)NULL) + { + unlink(pConPriv->noRasterFileName); + Xfree(pConPriv->noRasterFileName); + pConPriv->noRasterFileName = (char *)NULL; + } +} + +/* + * RasterCloseScreen - Call any wrapped CloseScreen function, + * and free the screen memory. + */ +static Bool +RasterCloseScreen( + int index, + ScreenPtr pScreen) +{ + Bool status = Success; + RasterScreenPrivPtr pScreenPriv = (RasterScreenPrivPtr) + pScreen->devPrivates[RasterScreenPrivateIndex].ptr; + + /* + * Call any wrapped CloseScreen proc. + */ + if(pScreenPriv->CloseScreen != (Bool (*)())NULL) + { + pScreen->CloseScreen = pScreenPriv->CloseScreen; + status = pScreen->CloseScreen(index, pScreen); + pScreen->CloseScreen = RasterCloseScreen; + } + + Xfree(pScreenPriv->pBits); + Xfree(pScreenPriv); + + return status; +} + +#include + +/* ARGSUSED */ +static void SigchldHndlr (int dummy) +{ + int status, w; + struct sigaction act; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SigchldHndlr; + + w = wait (&status); + + /* + * Is this really necessary? + */ + sigaction(SIGCHLD, &act, (struct sigaction *)NULL); +} + +/* + * SystemCmd provides a wrapper for the 'system' library call. The call + * appears to be sensitive to the handling of SIGCHLD, so this wrapper + * sets the status to SIG_DFL, and then resets the established handler + * after system returns. + */ +static int +SystemCmd(char *cmdStr) +{ + int status; + struct sigaction newAct, oldAct; + sigfillset(&newAct.sa_mask); + newAct.sa_flags = 0; + newAct.sa_handler = SIG_DFL; + sigfillset(&oldAct.sa_mask); + oldAct.sa_flags = 0; + oldAct.sa_handler = SigchldHndlr; + + /* + * get the old handler, and set the action to IGN + */ + sigaction(SIGCHLD, &newAct, &oldAct); + + status = system (cmdStr); + + sigaction(SIGCHLD, &oldAct, (struct sigaction *)NULL); + return status; +} + +/* + * RasterMediumDimensions is installed in the GetMediumDimensions field + * of each raster-initialized context. + */ +static int +RasterMediumDimensions(XpContextPtr pCon, + CARD16 *width, + CARD16 *height) +{ + XpGetMediumDimensions(pCon, width, height); + return Success; +} + +/* + * RasterReproducibleArea is installed in the GetReproducibleArea field + * of each raster-initialized context. + */ +static int +RasterReproducibleArea(XpContextPtr pCon, + xRectangle *pRect) +{ + XpGetReproductionArea(pCon, pRect); + return Success; +} diff --git a/Xprint/raster/Raster.h b/Xprint/raster/Raster.h new file mode 100644 index 000000000..b793f89a0 --- /dev/null +++ b/Xprint/raster/Raster.h @@ -0,0 +1,106 @@ +/* $Xorg: Raster.h,v 1.3 2000/08/17 19:48:12 cpqbld Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: printer/Raster.h +** * +** * Contents: defines and includes for the raster layer +** * for a printing X server. +** * +** * Copyright: Copyright 1993 Hewlett-Packard Company +** * +** ********************************************************* +** +********************************************************************/ +#ifndef _RASTER_H_ +#define _RASTER_H_ + +/* + * Some sleazes to force the XrmDB stuff into the server + */ +typedef char *XPointer; +#define Status int +#define True 1 +#define False 0 +#include "misc.h" +#include +#include "../Xresource.h" + +#define _XP_PRINT_SERVER_ +#include "extensions/Printstr.h" +#undef _XP_PRINT_SERVER_ + +#define MAX_TOKEN_LEN 512 + +#define RASTER_PRINT_PAGE_COMMAND "_XP_RASTER_PAGE_PROC_COMMAND" + +#define RASTER_IN_FILE_STRING "%(InFile)%" +#define RASTER_OUT_FILE_STRING "%(OutFile)%" + +#define RASTER_ALLOWED_COMMANDS_FILE "printCommands" + +/* + * Defines for the "options" in DtPrintDocumentData. + */ +#define PRE_RASTER "PRE-RASTER" +#define POST_RASTER "POST-RASTER" +#define NO_RASTER "NO-RASTER" + + +typedef struct { + char *pBits; + Bool (* CreateWindow)(); /* pWin */ + Bool (* ChangeWindowAttributes)(); /* pWin, mask */ + Bool (* DestroyWindow)(); /* pWin */ + Bool (* CloseScreen)(); /* index, pScreen */ +} RasterScreenPrivRec, *RasterScreenPrivPtr; + +typedef struct { + XrmDatabase config; + char *jobFileName; + FILE *pJobFile; + char *pageFileName; + FILE *pPageFile; + char *preRasterFileName; /* Pre-raster document data */ + FILE *pPreRasterFile; + char *noRasterFileName; /* Raster replacement document data */ + FILE *pNoRasterFile; + char *postRasterFileName; /* Post-raster document data */ + FILE *pPostRasterFile; + ClientPtr getDocClient; + int getDocBufSize; +} RasterContextPrivRec, *RasterContextPrivPtr; + +#endif /* _RASTER_H_ */ diff --git a/Xprint/raster/RasterAttVal.c b/Xprint/raster/RasterAttVal.c new file mode 100644 index 000000000..f76a890d3 --- /dev/null +++ b/Xprint/raster/RasterAttVal.c @@ -0,0 +1,265 @@ +/* $Xorg: RasterAttVal.c,v 1.4 2001/03/14 18:46:34 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +#include +#include "X.h" +#include "misc.h" +#include "dixstruct.h" +#include "scrnintstr.h" +#include "screenint.h" +#define _XP_PRINT_SERVER_ +#include "extensions/Print.h" +#undef _XP_PRINT_SERVER_ +#include "Raster.h" + +#include "attributes.h" +#include "AttrValid.h" + +/* + * define valid values and defaults for Printer pool + */ +static XpOid ValidContentOrientationsOids[] = { + xpoid_val_content_orientation_portrait, + xpoid_val_content_orientation_landscape +}; +static XpOidList ValidContentOrientations = { + ValidContentOrientationsOids, XpNumber(ValidContentOrientationsOids) +}; + +static XpOid DefaultContentOrientationsOids[] = { + xpoid_val_content_orientation_portrait, + xpoid_val_content_orientation_landscape +}; +static XpOidList DefaultContentOrientations = { + DefaultContentOrientationsOids, XpNumber(DefaultContentOrientationsOids) +}; + +static XpOid ValidPlexesOids[] = { + xpoid_val_plex_simplex +}; +static XpOidList ValidPlexes = { + ValidPlexesOids, XpNumber(ValidPlexesOids) +}; + +static XpOid DefaultPlexesOids[] = { + xpoid_val_plex_simplex +}; +static XpOidList DefaultPlexes = { + DefaultPlexesOids, XpNumber(DefaultPlexesOids) +}; + +static unsigned long ValidPrinterResolutionsCards[] = { + 150, 300, 600 +}; +static XpOidCardList ValidPrinterResolutions = { + ValidPrinterResolutionsCards, XpNumber(ValidPrinterResolutionsCards) +}; + +static unsigned long DefaultPrinterResolutionsCards[] = { + 300 +}; +static XpOidCardList DefaultPrinterResolutions = { + DefaultPrinterResolutionsCards, XpNumber(DefaultPrinterResolutionsCards) +}; + +static XpOid ValidListfontsModesOids[] = { + xpoid_val_xp_list_glyph_fonts +}; +static XpOidList ValidListfontsModes = { + ValidListfontsModesOids, XpNumber(ValidListfontsModesOids) +}; + +static XpOid DefaultListfontsModesOids[] = { + xpoid_val_xp_list_glyph_fonts +}; +static XpOidList DefaultListfontsModes = { + DefaultListfontsModesOids, XpNumber(DefaultListfontsModesOids) +}; + +static XpOid ValidSetupProvisoOids[] = { + xpoid_val_xp_setup_mandatory, xpoid_val_xp_setup_optional +}; +static XpOidList ValidSetupProviso = { + ValidSetupProvisoOids, XpNumber(ValidSetupProvisoOids) +}; + +static XpOidDocFmt ValidDocFormatsSupportedFmts[] = { + { "Postscript", "2", NULL }, + { "PCL", "3", NULL } +}; +static XpOidDocFmtList ValidDocFormatsSupported = { + ValidDocFormatsSupportedFmts, XpNumber(ValidDocFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultDocFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } +}; +static XpOidDocFmtList DefaultDocFormatsSupported = { + DefaultDocFormatsSupportedFmts, XpNumber(DefaultDocFormatsSupportedFmts) +}; + +static XpOidDocFmtList ValidEmbeddedFormatsSupported = { + (XpOidDocFmt *)NULL, 0 +}; + +static XpOidDocFmtList DefaultEmbeddedFormatsSupported = { + (XpOidDocFmt *)NULL, 0 +}; + +static XpOidDocFmt ValidRawFormatsSupportedFmts[] = { + { "Postscript", "2", NULL }, + { "PCL", "3", NULL } +}; +static XpOidDocFmtList ValidRawFormatsSupported = { + ValidRawFormatsSupportedFmts, XpNumber(ValidRawFormatsSupportedFmts) +}; + +static XpOidDocFmt DefaultRawFormatsSupportedFmts[] = { + { "Postscript", "2", NULL } +}; +static XpOidDocFmtList DefaultRawFormatsSupported = { + DefaultRawFormatsSupportedFmts, XpNumber(DefaultRawFormatsSupportedFmts) +}; + +static XpOidList ValidInputTrays = { + (XpOid *)NULL, 0 +}; + +static XpOid ValidMediumSizesOids[] = { + xpoid_val_medium_size_iso_a0, + xpoid_val_medium_size_iso_a1, + xpoid_val_medium_size_iso_a2, + xpoid_val_medium_size_iso_a3, + xpoid_val_medium_size_iso_a4, + xpoid_val_medium_size_iso_a5, + xpoid_val_medium_size_iso_a6, + xpoid_val_medium_size_iso_a7, + xpoid_val_medium_size_iso_a8, + xpoid_val_medium_size_iso_a9, + xpoid_val_medium_size_iso_a10, + xpoid_val_medium_size_iso_b0, + xpoid_val_medium_size_iso_b1, + xpoid_val_medium_size_iso_b2, + xpoid_val_medium_size_iso_b3, + xpoid_val_medium_size_iso_b4, + xpoid_val_medium_size_iso_b5, + xpoid_val_medium_size_iso_b6, + xpoid_val_medium_size_iso_b7, + xpoid_val_medium_size_iso_b8, + xpoid_val_medium_size_iso_b9, + xpoid_val_medium_size_iso_b10, + xpoid_val_medium_size_na_letter, + xpoid_val_medium_size_na_legal, + xpoid_val_medium_size_executive, + xpoid_val_medium_size_folio, + xpoid_val_medium_size_invoice, + xpoid_val_medium_size_ledger, + xpoid_val_medium_size_quarto, + xpoid_val_medium_size_iso_c3, + xpoid_val_medium_size_iso_c4, + xpoid_val_medium_size_iso_c5, + xpoid_val_medium_size_iso_c6, + xpoid_val_medium_size_iso_designated_long, + xpoid_val_medium_size_na_10x13_envelope, + xpoid_val_medium_size_na_9x12_envelope, + xpoid_val_medium_size_na_number_10_envelope, + xpoid_val_medium_size_na_7x9_envelope, + xpoid_val_medium_size_na_9x11_envelope, + xpoid_val_medium_size_na_10x14_envelope, + xpoid_val_medium_size_na_number_9_envelope, + xpoid_val_medium_size_monarch_envelope, + xpoid_val_medium_size_a, + xpoid_val_medium_size_b, + xpoid_val_medium_size_c, + xpoid_val_medium_size_d, + xpoid_val_medium_size_e, + xpoid_val_medium_size_jis_b0, + xpoid_val_medium_size_jis_b1, + xpoid_val_medium_size_jis_b2, + xpoid_val_medium_size_jis_b3, + xpoid_val_medium_size_jis_b4, + xpoid_val_medium_size_jis_b5, + xpoid_val_medium_size_jis_b6, + xpoid_val_medium_size_jis_b7, + xpoid_val_medium_size_jis_b8, + xpoid_val_medium_size_jis_b9, + xpoid_val_medium_size_jis_b10 +}; +static XpOidList ValidMediumSizes = { + ValidMediumSizesOids, XpNumber(ValidMediumSizesOids) +}; + +static XpOidDocFmt DefaultDocumentFormat = { + "Postscript", "2", NULL +}; + +static XpOid ValidAvailableCompressionsOids[] = { + xpoid_val_available_compressions_0, + xpoid_val_available_compressions_01, + xpoid_val_available_compressions_02, + xpoid_val_available_compressions_03, + xpoid_val_available_compressions_012, + xpoid_val_available_compressions_013, + xpoid_val_available_compressions_023, + xpoid_val_available_compressions_0123 +}; + +static XpOidList ValidAvailableCompressions = { + ValidAvailableCompressionsOids, XpNumber(ValidAvailableCompressionsOids) +}; + +static XpOid DefaultAvailableCompressionsOids[] = { + xpoid_val_available_compressions_0123, + xpoid_val_available_compressions_0 +}; + +static XpOidList DefaultAvailableCompressions = { + DefaultAvailableCompressionsOids, XpNumber(DefaultAvailableCompressionsOids) +}; + + +/* + * init struct for XpValidate*Pool + */ +XpValidatePoolsRec RasterValidatePoolsRec = { + &ValidContentOrientations, &DefaultContentOrientations, + &ValidDocFormatsSupported, &DefaultDocFormatsSupported, + &ValidInputTrays, &ValidMediumSizes, + &ValidPlexes, &DefaultPlexes, + &ValidPrinterResolutions, &DefaultPrinterResolutions, + &ValidEmbeddedFormatsSupported, &DefaultEmbeddedFormatsSupported, + &ValidListfontsModes, &DefaultListfontsModes, + &ValidRawFormatsSupported, &DefaultRawFormatsSupported, + &ValidSetupProviso, + &DefaultDocumentFormat, + &ValidAvailableCompressions, &DefaultAvailableCompressions +}; diff --git a/cfb/cfb.h b/cfb/cfb.h new file mode 100644 index 000000000..f8b48f66a --- /dev/null +++ b/cfb/cfb.h @@ -0,0 +1,1494 @@ +/* $Xorg: cfb.h,v 1.3 2000/08/17 19:48:12 cpqbld Exp $ */ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ + +#include "X.h" +#include "pixmap.h" +#include "region.h" +#include "gc.h" +#include "colormap.h" +#include "miscstruct.h" +#include "servermd.h" +#include "windowstr.h" +#include "mfb.h" +#undef PixelType + +#include "cfbmap.h" + +/* + private filed of pixmap + pixmap.devPrivate = (unsigned int *)pointer_to_bits + pixmap.devKind = width_of_pixmap_in_bytes +*/ + +extern int cfbGCPrivateIndex; +extern int cfbWindowPrivateIndex; + +/* private field of GC */ +typedef struct { + unsigned char rop; /* special case rop values */ + /* next two values unused in cfb, included for compatibility with mfb */ + unsigned char ropOpStip; /* rop for opaque stipple */ + /* this value is ropFillArea in mfb, usurped for cfb */ + unsigned char oneRect; /* drawable has one clip rect */ + unsigned fExpose:1; /* callexposure handling ? */ + unsigned freeCompClip:1; + PixmapPtr pRotatedPixmap; + RegionPtr pCompositeClip; /* FREE_CC or REPLACE_CC */ + unsigned long xor, and; /* reduced rop values */ + } cfbPrivGC; + +typedef cfbPrivGC *cfbPrivGCPtr; + +#define cfbGetGCPrivate(pGC) ((cfbPrivGCPtr)\ + (pGC)->devPrivates[cfbGCPrivateIndex].ptr) + +#define cfbGetCompositeClip(pGC) (((cfbPrivGCPtr)\ + (pGC)->devPrivates[cfbGCPrivateIndex].ptr)->pCompositeClip) + +/* way to carry RROP info around */ +typedef struct { + unsigned char rop; + unsigned long xor, and; +} cfbRRopRec, *cfbRRopPtr; + +/* private field of window */ +typedef struct { + unsigned char fastBorder; /* non-zero if border is 32 bits wide */ + unsigned char fastBackground; + unsigned short unused; /* pad for alignment with Sun compiler */ + DDXPointRec oldRotate; + PixmapPtr pRotatedBackground; + PixmapPtr pRotatedBorder; + } cfbPrivWin; + +#define cfbGetWindowPrivate(_pWin) ((cfbPrivWin *)\ + (_pWin)->devPrivates[cfbWindowPrivateIndex].ptr) + + +/* cfb8bit.c */ + +extern int cfbSetStipple( +#if NeedFunctionPrototypes + int /*alu*/, + unsigned long /*fg*/, + unsigned long /*planemask*/ +#endif +); + +extern int cfbSetOpaqueStipple( +#if NeedFunctionPrototypes + int /*alu*/, + unsigned long /*fg*/, + unsigned long /*bg*/, + unsigned long /*planemask*/ +#endif +); + +extern int cfbComputeClipMasks32( +#if NeedFunctionPrototypes + BoxPtr /*pBox*/, + int /*numRects*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + CARD32 * /*clips*/ +#endif +); +/* cfb8cppl.c */ + +extern void cfbCopyImagePlane( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + int /*rop*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbCopyPlane8to1( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + int /*rop*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/, + unsigned long /*bitPlane*/ +#endif +); +/* cfb8lineCO.c */ + +extern int cfb8LineSS1RectCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/, + DDXPointPtr /*pptInitOrig*/, + int * /*x1p*/, + int * /*y1p*/, + int * /*x2p*/, + int * /*y2p*/ +#endif +); + +extern void cfb8LineSS1Rect( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/ +#endif +); + +extern void cfb8ClippedLineCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x1*/, + int /*y1*/, + int /*x2*/, + int /*y2*/, + BoxPtr /*boxp*/, + Bool /*shorten*/ +#endif +); +/* cfb8lineCP.c */ + +extern int cfb8LineSS1RectPreviousCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/, + DDXPointPtr /*pptInitOrig*/, + int * /*x1p*/, + int * /*y1p*/, + int * /*x2p*/, + int * /*y2p*/ + +#endif +); +/* cfb8lineG.c */ + +extern int cfb8LineSS1RectGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/, + DDXPointPtr /*pptInitOrig*/, + int * /*x1p*/, + int * /*y1p*/, + int * /*x2p*/, + int * /*y2p*/ +#endif +); + +extern void cfb8ClippedLineGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x1*/, + int /*y1*/, + int /*x2*/, + int /*y2*/, + BoxPtr /*boxp*/, + Bool /*shorten*/ +#endif +); +/* cfb8lineX.c */ + +extern int cfb8LineSS1RectXor( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/, + DDXPointPtr /*pptInitOrig*/, + int * /*x1p*/, + int * /*y1p*/, + int * /*x2p*/, + int * /*y2p*/ +#endif +); + +extern void cfb8ClippedLineXor( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x1*/, + int /*y1*/, + int /*x2*/, + int /*y2*/, + BoxPtr /*boxp*/, + Bool /*shorten*/ +#endif +); +/* cfb8segC.c */ + +extern int cfb8SegmentSS1RectCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegInit*/ +#endif +); +/* cfb8segCS.c */ + +extern int cfb8SegmentSS1RectShiftCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegInit*/ +#endif +); + +extern void cfb8SegmentSS1Rect( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegInit*/ +#endif +); +/* cfb8segG.c */ + +extern int cfb8SegmentSS1RectGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegInit*/ +#endif +); +/* cfbsegX.c */ + +extern int cfb8SegmentSS1RectXor( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegInit*/ +#endif +); +/* cfballpriv.c */ + +extern Bool cfbAllocatePrivates( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int * /*window_index*/, + int * /*gc_index*/ +#endif +); +/* cfbbitblt.c */ + +extern RegionPtr cfbBitBlt( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr/*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/, + void (* /*doBitBlt*/)(), + unsigned long /*bitPlane*/ +#endif +); + +extern void cfbDoBitblt( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/ +#endif +); + +extern RegionPtr cfbCopyArea( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr/*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/ +#endif +); + +extern void cfbCopyPlane1to8( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + int /*rop*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/, + unsigned long /*bitPlane*/ +#endif +); + +extern RegionPtr cfbCopyPlane( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr /*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/, + unsigned long /*bitPlane*/ +#endif +); +/* cfbbltC.c */ + +extern void cfbDoBitbltCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/ +#endif +); +/* cfbbltG.c */ + +extern void cfbDoBitbltGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/ +#endif +); +/* cfbbltO.c */ + +extern void cfbDoBitbltOr( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/ +#endif +); +/* cfbbltX.c */ + +extern void cfbDoBitbltXor( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/, + unsigned long /*planemask*/ +#endif +); +/* cfbbres.c */ + +extern void cfbBresS( +#if NeedFunctionPrototypes + int /*rop*/, + unsigned long /*and*/, + unsigned long /*xor*/, + unsigned long * /*addrl*/, + int /*nlwidth*/, + int /*signdx*/, + int /*signdy*/, + int /*axis*/, + int /*x1*/, + int /*y1*/, + int /*e*/, + int /*e1*/, + int /*e2*/, + int /*len*/ +#endif +); +/* cfbbresd.c */ + +extern void cfbBresD( +#if NeedFunctionPrototypes + cfbRRopPtr /*rrops*/, + int * /*pdashIndex*/, + unsigned char * /*pDash*/, + int /*numInDashList*/, + int * /*pdashOffset*/, + int /*isDoubleDash*/, + unsigned long * /*addrl*/, + int /*nlwidth*/, + int /*signdx*/, + int /*signdy*/, + int /*axis*/, + int /*x1*/, + int /*y1*/, + int /*e*/, + int /*e1*/, + int /*e2*/, + int /*len*/ +#endif +); +/* cfbbstore.c */ + +extern void cfbSaveAreas( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/, + RegionPtr /*prgnSave*/, + int /*xorg*/, + int /*yorg*/, + WindowPtr /*pWin*/ +#endif +); + +extern void cfbRestoreAreas( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/, + RegionPtr /*prgnRestore*/, + int /*xorg*/, + int /*yorg*/, + WindowPtr /*pWin*/ +#endif +); +/* cfbcmap.c */ + +extern int cfbListInstalledColormaps( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + Colormap * /*pmaps*/ +#endif +); + +extern void cfbInstallColormap( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/ +#endif +); + +extern void cfbUninstallColormap( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/ +#endif +); + +extern void cfbResolveColor( +#if NeedFunctionPrototypes + unsigned short * /*pred*/, + unsigned short * /*pgreen*/, + unsigned short * /*pblue*/, + VisualPtr /*pVisual*/ +#endif +); + +extern Bool cfbInitializeColormap( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/ +#endif +); + +extern int cfbExpandDirectColors( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + int /*ndef*/, + xColorItem * /*indefs*/, + xColorItem * /*outdefs*/ +#endif +); + +extern Bool cfbCreateDefColormap( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/ +#endif +); + +extern Bool cfbSetVisualTypes( +#if NeedFunctionPrototypes + int /*depth*/, + int /*visuals*/, + int /*bitsPerRGB*/ +#endif +); + +extern Bool cfbInitVisuals( +#if NeedFunctionPrototypes + VisualPtr * /*visualp*/, + DepthPtr * /*depthp*/, + int * /*nvisualp*/, + int * /*ndepthp*/, + int * /*rootDepthp*/, + VisualID * /*defaultVisp*/, + unsigned long /*sizes*/, + int /*bitsPerRGB*/ +#endif +); +/* cfbfillarcC.c */ + +extern void cfbPolyFillArcSolidCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); +/* cfbfillarcG.c */ + +extern void cfbPolyFillArcSolidGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); +/* cfbfillrct.c */ + +extern void cfbFillBoxTileOdd( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*n*/, + BoxPtr /*rects*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/ +#endif +); + +extern void cfbFillRectTileOdd( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfbPolyFillRect( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nrectFill*/, + xRectangle * /*prectInit*/ +#endif +); +/* cfbfillsp.c */ + +extern void cfbUnnaturalTileFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void cfbUnnaturalStippleFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void cfb8Stipple32FS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void cfb8OpaqueStipple32FS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); +/* cfbgc.c */ + +extern GCOpsPtr cfbMatchCommon( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + cfbPrivGCPtr /*devPriv*/ +#endif +); + +extern Bool cfbCreateGC( +#if NeedFunctionPrototypes + GCPtr /*pGC*/ +#endif +); + +extern void cfbValidateGC( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + unsigned long /*changes*/, + DrawablePtr /*pDrawable*/ +#endif +); + +/* cfbgetsp.c */ + +extern void cfbGetSpans( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*wMax*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + int /*nspans*/, + char * /*pdstStart*/ +#endif +); +/* cfbglblt8.c */ + +extern void cfbPolyGlyphBlt8( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* cfbglrop8.c */ + +extern void cfbPolyGlyphRop8( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* cfbhrzvert.c */ + +extern int cfbHorzS( +#if NeedFunctionPrototypes + int /*rop*/, + unsigned long /*and*/, + unsigned long /*xor*/, + unsigned long * /*addrl*/, + int /*nlwidth*/, + int /*x1*/, + int /*y1*/, + int /*len*/ +#endif +); + +extern int cfbVertS( +#if NeedFunctionPrototypes + int /*rop*/, + unsigned long /*and*/, + unsigned long /*xor*/, + unsigned long * /*addrl*/, + int /*nlwidth*/, + int /*x1*/, + int /*y1*/, + int /*len*/ +#endif +); +/* cfbigblt8.c */ + +extern void cfbImageGlyphBlt8( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* cfbimage.c */ + +extern void cfbPutImage( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*depth*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*leftPad*/, + int /*format*/, + char * /*pImage*/ +#endif +); + +extern void cfbGetImage( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*sx*/, + int /*sy*/, + int /*w*/, + int /*h*/, + unsigned int /*format*/, + unsigned long /*planeMask*/, + char * /*pdstLine*/ +#endif +); +/* cfbline.c */ + +extern void cfbLineSS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/ +#endif +); + +extern void cfbLineSD( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/ +#endif +); +/* cfbmskbits.c */ +/* cfbpixmap.c */ + +extern PixmapPtr cfbCreatePixmap( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int /*width*/, + int /*height*/, + int /*depth*/ +#endif +); + +extern Bool cfbDestroyPixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/ +#endif +); + +extern PixmapPtr cfbCopyPixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pSrc*/ +#endif +); + +extern void cfbPadPixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/ +#endif +); + +extern void cfbXRotatePixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPix*/, + int /*rw*/ +#endif +); + +extern void cfbYRotatePixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPix*/, + int /*rh*/ +#endif +); + +extern void cfbCopyRotatePixmap( +#if NeedFunctionPrototypes + PixmapPtr /*psrcPix*/, + PixmapPtr * /*ppdstPix*/, + int /*xrot*/, + int /*yrot*/ +#endif +); +/* cfbply1rctC.c */ + +extern void cfbFillPoly1RectCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +#endif +); +/* cfbply1rctG.c */ + +extern void cfbFillPoly1RectGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +#endif +); +/* cfbpntwin.c */ + +extern void cfbPaintWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + RegionPtr /*pRegion*/, + int /*what*/ +#endif +); + +extern void cfbFillBoxSolid( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*nBox*/, + BoxPtr /*pBox*/, + unsigned long /*pixel*/ +#endif +); + +extern void cfbFillBoxTile32( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*nBox*/, + BoxPtr /*pBox*/, + PixmapPtr /*tile*/ +#endif +); +/* cfbpolypnt.c */ + +extern void cfbPolyPoint( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + xPoint * /*pptInit*/ +#endif +); +/* cfbpush8.c */ + +extern void cfbPushPixels8( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + PixmapPtr /*pBitmap*/, + DrawablePtr /*pDrawable*/, + int /*dx*/, + int /*dy*/, + int /*xOrg*/, + int /*yOrg*/ +#endif +); +/* cfbrctstp8.c */ + +extern void cfb8FillRectOpaqueStippled32( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfb8FillRectTransparentStippled32( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfb8FillRectStippledUnnatural( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); +/* cfbrrop.c */ + +extern int cfbReduceRasterOp( +#if NeedFunctionPrototypes + int /*rop*/, + unsigned long /*fg*/, + unsigned long /*pm*/, + unsigned long * /*andp*/, + unsigned long * /*xorp*/ +#endif +); +/* cfbscrinit.c */ + +extern Bool cfbCloseScreen( +#if NeedFunctionPrototypes + int /*index*/, + ScreenPtr /*pScreen*/ +#endif +); + +extern Bool cfbSetupScreen( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + pointer /*pbits*/, + int /*xsize*/, + int /*ysize*/, + int /*dpix*/, + int /*dpiy*/, + int /*width*/ +#endif +); + +extern int cfbFinishScreenInit( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + pointer /*pbits*/, + int /*xsize*/, + int /*ysize*/, + int /*dpix*/, + int /*dpiy*/, + int /*width*/ +#endif +); + +extern Bool cfbScreenInit( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + pointer /*pbits*/, + int /*xsize*/, + int /*ysize*/, + int /*dpix*/, + int /*dpiy*/, + int /*width*/ +#endif +); +/* cfbseg.c */ + +extern void cfbSegmentSS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSeg*/ +#endif +); + +extern void cfbSegmentSD( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSeg*/ +#endif +); +/* cfbsetsp.c */ + +extern int cfbSetScanline( +#if NeedFunctionPrototypes + int /*y*/, + int /*xOrigin*/, + int /*xStart*/, + int /*xEnd*/, + unsigned int * /*psrc*/, + int /*alu*/, + int * /*pdstBase*/, + int /*widthDst*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbSetSpans( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + char * /*psrc*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + int /*nspans*/, + int /*fSorted*/ +#endif +); +/* cfbsolidC.c */ + +extern void cfbFillRectSolidCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfbSolidSpansCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); +/* cfbsolidG.c */ + +extern void cfbFillRectSolidGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfbSolidSpansGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); +/* cfbsolidX.c */ + +extern void cfbFillRectSolidXor( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfbSolidSpansXor( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); +/* cfbteblt8.c */ + +extern void cfbTEGlyphBlt8( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*xInit*/, + int /*yInit*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* cfbtegblt.c */ + +extern void cfbTEGlyphBlt( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* cfbtile32C.c */ + +extern void cfbFillRectTile32Copy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfbTile32FSCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); +/* cfbtile32G.c */ + +extern void cfbFillRectTile32General( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nBox*/, + BoxPtr /*pBox*/ +#endif +); + +extern void cfbTile32FSGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); +/* cfbtileoddC.c */ + +extern void cfbFillBoxTileOddCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*nBox*/, + BoxPtr /*pBox*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbFillSpanTileOddCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*n*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbFillBoxTile32sCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*nBox*/, + BoxPtr /*pBox*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbFillSpanTile32sCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*n*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); +/* cfbtileoddG.c */ + +extern void cfbFillBoxTileOddGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*nBox*/, + BoxPtr /*pBox*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbFillSpanTileOddGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*n*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbFillBoxTile32sGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*nBox*/, + BoxPtr /*pBox*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); + +extern void cfbFillSpanTile32sGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*n*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + PixmapPtr /*tile*/, + int /*xrot*/, + int /*yrot*/, + int /*alu*/, + unsigned long /*planemask*/ +#endif +); +/* cfbwindow.c */ + +extern Bool cfbCreateWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern Bool cfbDestroyWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern Bool cfbMapWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWindow*/ +#endif +); + +extern Bool cfbPositionWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/ +#endif +); + +extern Bool cfbUnmapWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWindow*/ +#endif +); + +extern void cfbCopyWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + DDXPointRec /*ptOldOrg*/, + RegionPtr /*prgnSrc*/ +#endif +); + +extern Bool cfbChangeWindowAttributes( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + unsigned long /*mask*/ +#endif +); +/* cfbzerarcC.c */ + +extern void cfbZeroPolyArcSS8Copy( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); +/* cfbzerarcG.c */ + +extern void cfbZeroPolyArcSS8General( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); +/* cfbzerarcX.c */ + +extern void cfbZeroPolyArcSS8Xor( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); + +/* + * This is the only completely portable way to + * compute this info + */ + +#define BitsPerPixel(d) (\ + (1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \ + (PixmapWidthPaddingInfo[d].padRoundUp+1)) + +/* Common macros for extracting drawing information */ + +#if !defined(SINGLEDEPTH) && PSZ != 8 || defined(FORCE_SEPARATE_PRIVATE) + +#define CFB_NEED_SCREEN_PRIVATE + +extern int cfbScreenPrivateIndex; +#define cfbGetScreenPixmap(s) ((PixmapPtr) (s)->devPrivates[cfbScreenPrivateIndex].ptr) +#else +#define cfbGetScreenPixmap(s) ((PixmapPtr) (s)->devPrivate) +#endif + +#ifdef PIXMAP_PER_WINDOW +#define cfbGetWindowPixmap(d) ((PixmapPtr) ((WindowPtr) d)->devPrivates[frameWindowPrivateIndex].ptr) +#else +#define cfbGetWindowPixmap(d) cfbGetScreenPixmap((d)->pScreen) +#endif + +#define cfbGetTypedWidth(pDrawable,wtype) (\ + (((pDrawable)->type != DRAWABLE_PIXMAP) ? \ + (int) (cfbGetWindowPixmap(pDrawable)->devKind) : \ + (int)(((PixmapPtr)pDrawable)->devKind)) / sizeof (wtype)) + +#define cfbGetByteWidth(pDrawable) cfbGetTypedWidth(pDrawable, unsigned char) + +#define cfbGetPixelWidth(pDrawable) cfbGetTypedWidth(pDrawable, PixelType) + +#define cfbGetLongWidth(pDrawable) cfbGetTypedWidth(pDrawable, unsigned long) + +#define cfbGetTypedWidthAndPointer(pDrawable, width, pointer, wtype, ptype) {\ + PixmapPtr _pPix; \ + if ((pDrawable)->type != DRAWABLE_PIXMAP) \ + _pPix = cfbGetWindowPixmap(pDrawable); \ + else \ + _pPix = (PixmapPtr) (pDrawable); \ + (pointer) = (ptype *) _pPix->devPrivate.ptr; \ + (width) = ((int) _pPix->devKind) / sizeof (wtype); \ +} + +#define cfbGetByteWidthAndPointer(pDrawable, width, pointer) \ + cfbGetTypedWidthAndPointer(pDrawable, width, pointer, unsigned char, unsigned char) + +#define cfbGetLongWidthAndPointer(pDrawable, width, pointer) \ + cfbGetTypedWidthAndPointer(pDrawable, width, pointer, unsigned long, unsigned long) + +#define cfbGetPixelWidthAndPointer(pDrawable, width, pointer) \ + cfbGetTypedWidthAndPointer(pDrawable, width, pointer, PixelType, PixelType) + +#define cfbGetWindowTypedWidthAndPointer(pWin, width, pointer, wtype, ptype) {\ + PixmapPtr _pPix = cfbGetWindowPixmap((DrawablePtr) (pWin)); \ + (pointer) = (ptype *) _pPix->devPrivate.ptr; \ + (width) = ((int) _pPix->devKind) / sizeof (wtype); \ +} + +#define cfbGetWindowLongWidthAndPointer(pWin, width, pointer) \ + cfbGetWindowTypedWidthAndPointer(pWin, width, pointer, unsigned long, unsigned long) + +#define cfbGetWindowByteWidthAndPointer(pWin, width, pointer) \ + cfbGetWindowTypedWidthAndPointer(pWin, width, pointer, unsigned char, unsigned char) + +#define cfbGetWindowPixelWidthAndPointer(pDrawable, width, pointer) \ + cfbGetWindowTypedWidthAndPointer(pDrawable, width, pointer, PixelType, PixelType) + +/* Macros which handle a coordinate in a single register */ + +/* Most compilers will convert divide by 65536 into a shift, if signed + * shifts exist. If your machine does arithmetic shifts and your compiler + * can't get it right, add to this line. + */ + +/* mips compiler - what a joke - it CSEs the 65536 constant into a reg + * forcing as to use div instead of shift. Let's be explicit. + */ + +#if defined(mips) || defined(sparc) || defined(__alpha) +#define GetHighWord(x) (((int) (x)) >> 16) +#else +#define GetHighWord(x) (((int) (x)) / 65536) +#endif + +#if IMAGE_BYTE_ORDER == MSBFirst +#define intToCoord(i,x,y) (((x) = GetHighWord(i)), ((y) = (int) ((short) (i)))) +#define coordToInt(x,y) (((x) << 16) | (y)) +#define intToX(i) (GetHighWord(i)) +#define intToY(i) ((int) ((short) i)) +#else +#define intToCoord(i,x,y) (((x) = (int) ((short) (i))), ((y) = GetHighWord(i))) +#define coordToInt(x,y) (((y) << 16) | (x)) +#define intToX(i) ((int) ((short) (i))) +#define intToY(i) (GetHighWord(i)) +#endif diff --git a/cfb/cfb8bit.c b/cfb/cfb8bit.c new file mode 100644 index 000000000..080970e70 --- /dev/null +++ b/cfb/cfb8bit.c @@ -0,0 +1,466 @@ +/* $Xorg: cfb8bit.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ +/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * cfb8bit.c + * + * 8 bit color frame buffer utility routines + */ + + +#if PSZ == 8 + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" + +PixelGroup cfb8StippleMasks[NUM_MASKS] = { +#if NUM_MASKS == 16 + 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, + 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, + 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, + 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff +#else /* NUM_MASKS == 256 */ + 0x0000000000000000, 0x00000000000000ff, + 0x000000000000ff00, 0x000000000000ffff, + 0x0000000000ff0000, 0x0000000000ff00ff, + 0x0000000000ffff00, 0x0000000000ffffff, + 0x00000000ff000000, 0x00000000ff0000ff, + 0x00000000ff00ff00, 0x00000000ff00ffff, + 0x00000000ffff0000, 0x00000000ffff00ff, + 0x00000000ffffff00, 0x00000000ffffffff, + 0x000000ff00000000, 0x000000ff000000ff, + 0x000000ff0000ff00, 0x000000ff0000ffff, + 0x000000ff00ff0000, 0x000000ff00ff00ff, + 0x000000ff00ffff00, 0x000000ff00ffffff, + 0x000000ffff000000, 0x000000ffff0000ff, + 0x000000ffff00ff00, 0x000000ffff00ffff, + 0x000000ffffff0000, 0x000000ffffff00ff, + 0x000000ffffffff00, 0x000000ffffffffff, + 0x0000ff0000000000, 0x0000ff00000000ff, + 0x0000ff000000ff00, 0x0000ff000000ffff, + 0x0000ff0000ff0000, 0x0000ff0000ff00ff, + 0x0000ff0000ffff00, 0x0000ff0000ffffff, + 0x0000ff00ff000000, 0x0000ff00ff0000ff, + 0x0000ff00ff00ff00, 0x0000ff00ff00ffff, + 0x0000ff00ffff0000, 0x0000ff00ffff00ff, + 0x0000ff00ffffff00, 0x0000ff00ffffffff, + 0x0000ffff00000000, 0x0000ffff000000ff, + 0x0000ffff0000ff00, 0x0000ffff0000ffff, + 0x0000ffff00ff0000, 0x0000ffff00ff00ff, + 0x0000ffff00ffff00, 0x0000ffff00ffffff, + 0x0000ffffff000000, 0x0000ffffff0000ff, + 0x0000ffffff00ff00, 0x0000ffffff00ffff, + 0x0000ffffffff0000, 0x0000ffffffff00ff, + 0x0000ffffffffff00, 0x0000ffffffffffff, + 0x00ff000000000000, 0x00ff0000000000ff, + 0x00ff00000000ff00, 0x00ff00000000ffff, + 0x00ff000000ff0000, 0x00ff000000ff00ff, + 0x00ff000000ffff00, 0x00ff000000ffffff, + 0x00ff0000ff000000, 0x00ff0000ff0000ff, + 0x00ff0000ff00ff00, 0x00ff0000ff00ffff, + 0x00ff0000ffff0000, 0x00ff0000ffff00ff, + 0x00ff0000ffffff00, 0x00ff0000ffffffff, + 0x00ff00ff00000000, 0x00ff00ff000000ff, + 0x00ff00ff0000ff00, 0x00ff00ff0000ffff, + 0x00ff00ff00ff0000, 0x00ff00ff00ff00ff, + 0x00ff00ff00ffff00, 0x00ff00ff00ffffff, + 0x00ff00ffff000000, 0x00ff00ffff0000ff, + 0x00ff00ffff00ff00, 0x00ff00ffff00ffff, + 0x00ff00ffffff0000, 0x00ff00ffffff00ff, + 0x00ff00ffffffff00, 0x00ff00ffffffffff, + 0x00ffff0000000000, 0x00ffff00000000ff, + 0x00ffff000000ff00, 0x00ffff000000ffff, + 0x00ffff0000ff0000, 0x00ffff0000ff00ff, + 0x00ffff0000ffff00, 0x00ffff0000ffffff, + 0x00ffff00ff000000, 0x00ffff00ff0000ff, + 0x00ffff00ff00ff00, 0x00ffff00ff00ffff, + 0x00ffff00ffff0000, 0x00ffff00ffff00ff, + 0x00ffff00ffffff00, 0x00ffff00ffffffff, + 0x00ffffff00000000, 0x00ffffff000000ff, + 0x00ffffff0000ff00, 0x00ffffff0000ffff, + 0x00ffffff00ff0000, 0x00ffffff00ff00ff, + 0x00ffffff00ffff00, 0x00ffffff00ffffff, + 0x00ffffffff000000, 0x00ffffffff0000ff, + 0x00ffffffff00ff00, 0x00ffffffff00ffff, + 0x00ffffffffff0000, 0x00ffffffffff00ff, + 0x00ffffffffffff00, 0x00ffffffffffffff, + 0xff00000000000000, 0xff000000000000ff, + 0xff0000000000ff00, 0xff0000000000ffff, + 0xff00000000ff0000, 0xff00000000ff00ff, + 0xff00000000ffff00, 0xff00000000ffffff, + 0xff000000ff000000, 0xff000000ff0000ff, + 0xff000000ff00ff00, 0xff000000ff00ffff, + 0xff000000ffff0000, 0xff000000ffff00ff, + 0xff000000ffffff00, 0xff000000ffffffff, + 0xff0000ff00000000, 0xff0000ff000000ff, + 0xff0000ff0000ff00, 0xff0000ff0000ffff, + 0xff0000ff00ff0000, 0xff0000ff00ff00ff, + 0xff0000ff00ffff00, 0xff0000ff00ffffff, + 0xff0000ffff000000, 0xff0000ffff0000ff, + 0xff0000ffff00ff00, 0xff0000ffff00ffff, + 0xff0000ffffff0000, 0xff0000ffffff00ff, + 0xff0000ffffffff00, 0xff0000ffffffffff, + 0xff00ff0000000000, 0xff00ff00000000ff, + 0xff00ff000000ff00, 0xff00ff000000ffff, + 0xff00ff0000ff0000, 0xff00ff0000ff00ff, + 0xff00ff0000ffff00, 0xff00ff0000ffffff, + 0xff00ff00ff000000, 0xff00ff00ff0000ff, + 0xff00ff00ff00ff00, 0xff00ff00ff00ffff, + 0xff00ff00ffff0000, 0xff00ff00ffff00ff, + 0xff00ff00ffffff00, 0xff00ff00ffffffff, + 0xff00ffff00000000, 0xff00ffff000000ff, + 0xff00ffff0000ff00, 0xff00ffff0000ffff, + 0xff00ffff00ff0000, 0xff00ffff00ff00ff, + 0xff00ffff00ffff00, 0xff00ffff00ffffff, + 0xff00ffffff000000, 0xff00ffffff0000ff, + 0xff00ffffff00ff00, 0xff00ffffff00ffff, + 0xff00ffffffff0000, 0xff00ffffffff00ff, + 0xff00ffffffffff00, 0xff00ffffffffffff, + 0xffff000000000000, 0xffff0000000000ff, + 0xffff00000000ff00, 0xffff00000000ffff, + 0xffff000000ff0000, 0xffff000000ff00ff, + 0xffff000000ffff00, 0xffff000000ffffff, + 0xffff0000ff000000, 0xffff0000ff0000ff, + 0xffff0000ff00ff00, 0xffff0000ff00ffff, + 0xffff0000ffff0000, 0xffff0000ffff00ff, + 0xffff0000ffffff00, 0xffff0000ffffffff, + 0xffff00ff00000000, 0xffff00ff000000ff, + 0xffff00ff0000ff00, 0xffff00ff0000ffff, + 0xffff00ff00ff0000, 0xffff00ff00ff00ff, + 0xffff00ff00ffff00, 0xffff00ff00ffffff, + 0xffff00ffff000000, 0xffff00ffff0000ff, + 0xffff00ffff00ff00, 0xffff00ffff00ffff, + 0xffff00ffffff0000, 0xffff00ffffff00ff, + 0xffff00ffffffff00, 0xffff00ffffffffff, + 0xffffff0000000000, 0xffffff00000000ff, + 0xffffff000000ff00, 0xffffff000000ffff, + 0xffffff0000ff0000, 0xffffff0000ff00ff, + 0xffffff0000ffff00, 0xffffff0000ffffff, + 0xffffff00ff000000, 0xffffff00ff0000ff, + 0xffffff00ff00ff00, 0xffffff00ff00ffff, + 0xffffff00ffff0000, 0xffffff00ffff00ff, + 0xffffff00ffffff00, 0xffffff00ffffffff, + 0xffffffff00000000, 0xffffffff000000ff, + 0xffffffff0000ff00, 0xffffffff0000ffff, + 0xffffffff00ff0000, 0xffffffff00ff00ff, + 0xffffffff00ffff00, 0xffffffff00ffffff, + 0xffffffffff000000, 0xffffffffff0000ff, + 0xffffffffff00ff00, 0xffffffffff00ffff, + 0xffffffffffff0000, 0xffffffffffff00ff, + 0xffffffffffffff00, 0xffffffffffffffff +#endif +}; + +int cfb8StippleMode, cfb8StippleAlu, cfb8StippleRRop; +PixelGroup cfb8StippleFg, cfb8StippleBg, cfb8StipplePm; +PixelGroup cfb8StippleAnd[NUM_MASKS], cfb8StippleXor[NUM_MASKS]; + +int +cfb8SetStipple (alu, fg, planemask) +int alu; +unsigned long fg, planemask; +{ + unsigned long and, xor, rrop; + int s; + unsigned long c; + + cfb8StippleMode = FillStippled; + cfb8StippleAlu = alu; + cfb8StippleFg = fg & PMSK; + cfb8StipplePm = planemask & PMSK; + rrop = cfbReduceRasterOp (alu, fg, planemask, &and, &xor); + cfb8StippleRRop = rrop; + /* + * create the appropriate pixel-fill bits for current + * foreground + */ + for (s = 0; s < NUM_MASKS; s++) + { + c = cfb8StippleMasks[s]; + cfb8StippleAnd[s] = and | ~c; + cfb8StippleXor[s] = xor & c; + } + return TRUE; +} + + +int +cfb8SetOpaqueStipple (alu, fg, bg, planemask) +int alu; +unsigned long fg, bg, planemask; +{ + unsigned long andfg, xorfg, andbg, xorbg, rropfg, rropbg; + int s; + unsigned long c; + + cfb8StippleMode = FillOpaqueStippled; + cfb8StippleAlu = alu; + cfb8StippleFg = fg & PMSK; + cfb8StippleBg = bg & PMSK; + cfb8StipplePm = planemask & PMSK; + rropfg = cfbReduceRasterOp (alu, cfb8StippleFg, cfb8StipplePm, &andfg, &xorfg); + rropbg = cfbReduceRasterOp (alu, cfb8StippleBg, cfb8StipplePm, &andbg, &xorbg); + if (rropfg == rropbg) + cfb8StippleRRop = rropfg; + else + cfb8StippleRRop = GXset; + /* + * create the appropriate pixel-fill bits for current + * foreground + */ + for (s = 0; s < NUM_MASKS; s++) + { + c = cfb8StippleMasks[s]; + cfb8StippleAnd[s] = (andfg | ~c) & (andbg | c); + cfb8StippleXor[s] = (xorfg & c) | (xorbg & ~c); + } + return TRUE; +} + +/* + * a grungy little routine. This computes clip masks + * for partial character blts. Returns rgnOUT if the + * entire character is clipped; returns rgnIN if the entire + * character is unclipped; returns rgnPART if a portion of + * the character is visible. Computes clip masks for each + * longword of the character -- and those with the + * contents of the glyph to compute the visible bits. + */ + +#if PGSZ == 32 +#if (BITMAP_BIT_ORDER == MSBFirst) +PixelGroup cfb8BitLenMasks[PGSZ] = { + 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff, + 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff, + 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff, + 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, + 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff, + 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff, + 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f, + 0x0000000f, 0x00000007, 0x00000003, 0x00000001, +}; +#else +PixelGroup cfb8BitLenMasks[PGSZ] = { + 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, + 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, + 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, + 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, + 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, + 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, + 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, + 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, +}; +#endif /* BITMAP_BIT_ORDER */ +#else /* PGSZ == 64 */ +#if (BITMAP_BIT_ORDER == MSBFirst) +PixelGroup cfb8BitLenMasks[PGSZ] = { + 0xffffffffffffffff, 0x7fffffffffffffff, + 0x3fffffffffffffff, 0x1fffffffffffffff, + 0x0fffffffffffffff, 0x07ffffffffffffff, + 0x03ffffffffffffff, 0x01ffffffffffffff, + 0x00ffffffffffffff, 0x007fffffffffffff, + 0x003fffffffffffff, 0x001fffffffffffff, + 0x000fffffffffffff, 0x0007ffffffffffff, + 0x0003ffffffffffff, 0x0001ffffffffffff, + 0x0000ffffffffffff, 0x00007fffffffffff, + 0x00003fffffffffff, 0x00001fffffffffff, + 0x00000fffffffffff, 0x000007ffffffffff, + 0x000003ffffffffff, 0x000001ffffffffff, + 0x000000ffffffffff, 0x0000007fffffffff, + 0x0000003fffffffff, 0x0000001fffffffff, + 0x0000000fffffffff, 0x00000007ffffffff, + 0x00000003ffffffff, 0x00000001ffffffff, + 0x00000000ffffffff, 0x000000007fffffff, + 0x000000003fffffff, 0x000000001fffffff, + 0x000000000fffffff, 0x0000000007ffffff, + 0x0000000003ffffff, 0x0000000001ffffff, + 0x0000000000ffffff, 0x00000000007fffff, + 0x00000000003fffff, 0x00000000001fffff, + 0x00000000000fffff, 0x000000000007ffff, + 0x000000000003ffff, 0x000000000001ffff, + 0x000000000000ffff, 0x0000000000007fff, + 0x0000000000003fff, 0x0000000000001fff, + 0x0000000000000fff, 0x00000000000007ff, + 0x00000000000003ff, 0x00000000000001ff, + 0x00000000000000ff, 0x000000000000007f, + 0x000000000000003f, 0x000000000000001f, + 0x000000000000000f, 0x0000000000000007, + 0x0000000000000003, 0x0000000000000001 +}; +#else +PixelGroup cfb8BitLenMasks[PGSZ] = { + 0xffffffffffffffff, 0xfffffffffffffffe, + 0xfffffffffffffffc, 0xfffffffffffffff8, + 0xfffffffffffffff0, 0xffffffffffffffe0, + 0xffffffffffffffc0, 0xffffffffffffff80, + 0xffffffffffffff00, 0xfffffffffffffe00, + 0xfffffffffffffc00, 0xfffffffffffff800, + 0xfffffffffffff000, 0xffffffffffffe000, + 0xffffffffffffc000, 0xffffffffffff8000, + 0xffffffffffff0000, 0xfffffffffffe0000, + 0xfffffffffffc0000, 0xfffffffffff80000, + 0xfffffffffff00000, 0xffffffffffe00000, + 0xffffffffffc00000, 0xffffffffff800000, + 0xffffffffff000000, 0xfffffffffe000000, + 0xfffffffffc000000, 0xfffffffff8000000, + 0xfffffffff0000000, 0xffffffffe0000000, + 0xffffffffc0000000, 0xffffffff80000000, + 0xffffffff00000000, 0xfffffffe00000000, + 0xfffffffc00000000, 0xfffffff800000000, + 0xfffffff000000000, 0xffffffe000000000, + 0xffffffc000000000, 0xffffff8000000000, + 0xffffff0000000000, 0xfffffe0000000000, + 0xfffffc0000000000, 0xfffff80000000000, + 0xfffff00000000000, 0xffffe00000000000, + 0xffffc00000000000, 0xffff800000000000, + 0xffff000000000000, 0xfffe000000000000, + 0xfffc000000000000, 0xfff8000000000000, + 0xfff0000000000000, 0xffe0000000000000, + 0xffc0000000000000, 0xff80000000000000, + 0xff00000000000000, 0xfe00000000000000, + 0xfc00000000000000, 0xf800000000000000, + 0xf000000000000000, 0xe000000000000000, + 0xc000000000000000, 0x8000000000000000 +}; +#endif /* BITMAP_BIT_ORDER */ +#endif /* PGSZ */ + + + +int +cfb8ComputeClipMasks32 (pBox, numRects, x, y, w, h, clips) + BoxPtr pBox; + int numRects; + int x, y, w, h; + CARD32 *clips; +{ + int yBand, yBandBot; + int ch; + unsigned long clip; + int partIN = FALSE, partOUT = FALSE; + int result; + + if (numRects == 0) + return rgnOUT; + while (numRects && pBox->y2 <= y) + { + --numRects; + ++pBox; + } + if (!numRects || pBox->y1 >= y + h) + return rgnOUT; + yBand = pBox->y1; + while (numRects && pBox->y1 == yBand && pBox->x2 <= x) + { + --numRects; + ++pBox; + } + if (!numRects || pBox->y1 >= y + h) + return rgnOUT; + if (numRects && + x >= pBox->x1 && + x + w <= pBox->x2 && + y >= pBox->y1 && + y + h <= pBox->y2) + { + return rgnIN; + } + ch = 0; + while (numRects && pBox->y1 < y + h) + { + yBand = pBox->y1; + yBandBot = pBox->y2; + while (ch < h && y + ch < yBand) + { + partOUT = TRUE; + clips[ch++] = 0; + } + if (ch >= h) + break; + while (numRects && pBox->y1 == yBand && pBox->x2 <= x) + { + --numRects; + ++pBox; + } + if (!numRects) + break; + clip = 0; + while (numRects && pBox->y1 == yBand && pBox->x1 < x + w) + { + if (x < pBox->x1) + if (pBox->x2 < x + w) + clip |= cfb8BitLenMasks[pBox->x1 - x] & ~cfb8BitLenMasks[pBox->x2 - x]; + else + clip |= cfb8BitLenMasks[pBox->x1 - x]; + else + if (pBox->x2 < x + w) + clip |= ~cfb8BitLenMasks[pBox->x2 - x]; + else + clip = ~0; + --numRects; + ++pBox; + } + if (clip != 0) + partIN = TRUE; + if (clip != ~0) + partOUT = TRUE; + while (ch < h && y + ch < yBandBot) + clips[ch++] = clip; + while (numRects && pBox->y1 == yBand) + { + --numRects; + ++pBox; + } + } + while (ch < h) + { + partOUT = TRUE; + clips[ch++] = 0; + } + result = rgnOUT; + if (partIN) + { + if (partOUT) + result = rgnPART; + else + result = rgnIN; + } + return result; +} + +#endif /* PSZ == 8 */ diff --git a/cfb/cfb8bit.h b/cfb/cfb8bit.h new file mode 100644 index 000000000..23853bf2d --- /dev/null +++ b/cfb/cfb8bit.h @@ -0,0 +1,1196 @@ +/* + * cfb8bit.h + * + * Defines which are only useful to 8 bit color frame buffers + * + * That doesn't seem to be true any more. Some of the macros in here + * are used for depths other than 8. Perhaps the file should be + * renamed. dpw + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/* $Xorg: cfb8bit.h,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ + +#include "servermd.h" + +#if (BITMAP_BIT_ORDER == MSBFirst) +#define GetBitGroup(x) (((PixelGroup) (x)) >> (PGSZ - PGSZB)) +#define NextBitGroup(x) ((x) <<= PGSZB) +#define NextSomeBits(x,n) ((x) <<= (n)) +#else +#define GetBitGroup(x) ((x) & PGSZBMSK) +#define NextBitGroup(x) ((x) >>= PGSZB) +#define NextSomeBits(x,n) ((x) >>= (n)) +#endif + +#define RotBitsLeft(x,k) ((x) = BitLeft (x,k) | \ + BitRight (x, PGSZ-(k))) + +#if defined(__GNUC__) && defined(mc68020) +#undef RotBitsLeft +#define RotBitsLeft(x,k) asm("rol%.l %2,%0" \ + : "=d" (x) \ + : "0" (x), "dI" (k)) +#endif + +#if PSZ == 8 + +#define GetPixelGroup(x) (cfb8StippleXor[GetBitGroup(x)]) +#define RRopPixels(dst,x) (DoRRop(dst,cfb8StippleAnd[x], cfb8StippleXor[x])) +#define RRopPixelGroup(dst,x) (RRopPixels(dst,GetBitGroup(x))) +#define MaskRRopPixels(dst,x,mask) (DoMaskRRop(dst,cfb8StippleAnd[x], cfb8StippleXor[x], mask)) + +#define NUM_MASKS (1<= MFB_PPW) \ + { \ + inputBits = *srcTemp++; \ + bitsLeft -= MFB_PPW; \ + partBitsLeft = MFB_PPW; \ + } \ + else \ + { \ + inputBits = 0; \ + if (bitsLeft) \ + inputBits = *srcTemp & ~cfb8BitLenMasks[bitsLeft]; \ + srcTemp = srcStart; \ + partBitsLeft = bitsLeft; \ + bitsLeft = bitsWhole; \ + } + +#define NextUnnaturalStippleBits \ + if (partBitsLeft >= PPW) { \ + bits = GetBitGroup (inputBits); \ + NextBitGroup (inputBits); \ + partBitsLeft -= PPW; \ + } else { \ + bits = GetBitGroup (inputBits); \ + nextPartBits = PPW - partBitsLeft; \ + NextUnnaturalStippleWord \ + if (partBitsLeft < nextPartBits) { \ + if (partBitsLeft) {\ + bits |= BitRight (GetBitGroup (inputBits), \ + PPW - nextPartBits) & PPWMSK;\ + nextPartBits -= partBitsLeft; \ + } \ + NextUnnaturalStippleWord \ + } \ + bits |= BitRight (GetBitGroup (inputBits), \ + PPW - nextPartBits) & PPWMSK; \ + NextSomeBits (inputBits, nextPartBits); \ + partBitsLeft -= nextPartBits; \ + } + +#define NextUnnaturalStippleBitsFast \ + if (partBitsLeft >= PPW) { \ + bits = GetBitGroup(inputBits); \ + NextBitGroup(inputBits); \ + partBitsLeft -= PPW; \ + } else { \ + bits = GetBitGroup (inputBits); \ + nextPartBits = PPW - partBitsLeft; \ + inputBits = *srcTemp++; \ + bits |= BitRight (GetBitGroup (inputBits), \ + partBitsLeft) & PPWMSK; \ + NextSomeBits (inputBits, nextPartBits); \ + partBitsLeft = MFB_PPW - nextPartBits; \ + } + +/* + * WriteBitGroup takes the destination address, a pixel + * value (which must be 8 bits duplicated 4 time with PFILL) + * and the PPW bits to write, which must be in the low order + * bits of the register (probably from GetBitGroup) and writes + * the appropriate locations in memory with the pixel value. This + * is a copy-mode only operation. + */ + +#define RRopBitGroup(dst,bits) \ + { \ + register PixelGroup _bitsTmp = (bits); \ + *(dst) = RRopPixels(*(dst),bits); \ + } + +#define MaskRRopBitGroup(dst,bits,mask) \ + { \ + register PixelGroup _bitsTmp = (bits); \ + *(dst) = MaskRRopPixels(*(dst),bits,mask); \ + } +#endif /* PSZ == 8 */ + +#if !defined(AVOID_MEMORY_READ) && PSZ == 8 + +#define WriteBitGroup(dst,pixel,bits) \ + { \ + register PixelGroup _maskTmp = cfb8PixelMasks[(bits)]; \ + *(dst) = (*(dst) & ~_maskTmp) | ((pixel) & _maskTmp); \ + } + +#define SwitchBitGroup(dst,pixel,bits) \ + { \ + register PixelGroup _maskTmp = cfb8PixelMasks[(bits)]; \ + register PixelGroup _pixTmp = ((pixel) & _maskTmp); \ + _maskTmp = ~_maskTmp; \ + SwitchBitsLoop (*(dst) = (*(dst) & _maskTmp) | _pixTmp;) \ + } + +#else /* AVOID_MEMORY_READ */ + +#if PGSZ == 32 +#if (BITMAP_BIT_ORDER == MSBFirst) +#define SinglePixel0 3 +#define SinglePixel1 2 +#define SinglePixel2 1 +#define SinglePixel3 0 +#define DoublePixel0 1 +#define DoublePixel1 0 +#else +#define SinglePixel0 0 +#define SinglePixel1 1 +#define SinglePixel2 2 +#define SinglePixel3 3 +#define DoublePixel0 0 +#define DoublePixel1 1 +#endif +#define QuadPixel0 0 +#else /* PGSZ == 64 */ +#if (BITMAP_BIT_ORDER == MSBFirst) +#define SinglePixel0 7 +#define SinglePixel1 6 +#define SinglePixel2 5 +#define SinglePixel3 4 +#define SinglePixel4 3 +#define SinglePixel5 2 +#define SinglePixel6 1 +#define SinglePixel7 0 +#define DoublePixel0 3 +#define DoublePixel1 2 +#define DoublePixel2 1 +#define DoublePixel3 0 +#define QuadPixel0 1 +#define QuadPixel1 0 +#else +#define SinglePixel0 0 +#define SinglePixel1 1 +#define SinglePixel2 2 +#define SinglePixel3 3 +#define SinglePixel4 4 +#define SinglePixel5 5 +#define SinglePixel6 6 +#define SinglePixel7 7 +#define DoublePixel0 0 +#define DoublePixel1 1 +#define DoublePixel2 2 +#define DoublePixel3 3 +#define QuadPixel0 0 +#define QuadPixel1 1 +#endif +#define OctaPixel0 0 +#endif /* PGSZ == 64 */ + +#if PSZ == 8 + +#if PGSZ == 32 +#define WriteBitGroup(dst,pixel,bits) \ + switch (bits) { \ + case 0: \ + break; \ + case 1: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + break; \ + case 2: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 3: \ + ((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + break; \ + case 4: \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 5: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 6: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 7: \ + ((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 8: \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 9: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 10: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 11: \ + ((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 12: \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 13: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 14: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[0] = (pixel); \ + break; \ + } +#else /* PGSZ == 64 */ +#define WriteBitGroup(dst,pixel,bits) \ + if ( bits == 0xff ) \ + ((PixelGroup *) (dst))[OctaPixel0] = (pixel); \ + else { \ + switch (bits & 0x0f) { \ + case 0: \ + break; \ + case 1: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + break; \ + case 2: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 3: \ + ((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + break; \ + case 4: \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 5: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 6: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 7: \ + ((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 8: \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 9: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 10: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 11: \ + ((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 12: \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 13: \ + ((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 14: \ + ((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[QuadPixel0] = (pixel); \ + break; \ + } \ + switch ((bits & 0xf0) >> 4) { \ + case 0: \ + break; \ + case 1: \ + ((CARD8 *) (dst))[SinglePixel4] = (pixel); \ + break; \ + case 2: \ + ((CARD8 *) (dst))[SinglePixel5] = (pixel); \ + break; \ + case 3: \ + ((CARD16 *) (dst))[DoublePixel2] = (pixel); \ + break; \ + case 4: \ + ((CARD8 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 5: \ + ((CARD8 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 6: \ + ((CARD8 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 7: \ + ((CARD16 *) (dst))[DoublePixel2] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 8: \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 9: \ + ((CARD8 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 10: \ + ((CARD8 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 11: \ + ((CARD16 *) (dst))[DoublePixel2] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 12: \ + ((CARD16 *) (dst))[DoublePixel3] = (pixel); \ + break; \ + case 13: \ + ((CARD8 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel3] = (pixel); \ + break; \ + case 14: \ + ((CARD8 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel3] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[QuadPixel1] = (pixel); \ + break; \ + } \ + } +#endif /* PGSZ == 64 */ + +#if PGSZ == 32 +#define SwitchBitGroup(dst,pixel,bits) { \ + switch (bits) { \ + case 0: \ + break; \ + case 1: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel);) \ + break; \ + case 2: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel);) \ + break; \ + case 3: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel0] = (pixel);) \ + break; \ + case 4: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 5: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 6: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 7: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 8: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 9: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 10: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 11: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 12: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel1] = (pixel);) \ + break; \ + case 13: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel);) \ + break; \ + case 14: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel);) \ + break; \ + case 15: \ + SwitchBitsLoop (((CARD32 *) (dst))[0] = (pixel);) \ + break; \ + } \ +} +#else /* PGSZ == 64 */ +#define SwitchBitGroup(dst,pixel,bits) { \ + if ( bits == 0xff ) \ + SwitchBitsLoop (((PixelGroup *) (dst))[OctaPixel0] = (pixel);) \ + else { \ + switch (bits & 0x0f) { \ + case 0: \ + break; \ + case 1: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel);) \ + break; \ + case 2: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel);) \ + break; \ + case 3: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel0] = (pixel);)\ + break; \ + case 4: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 5: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 6: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 7: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 8: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 9: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 10: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 11: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 12: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel1] = (pixel);)\ + break; \ + case 13: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel);)\ + break; \ + case 14: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel1] = (pixel);)\ + break; \ + case 15: \ + SwitchBitsLoop (((CARD32 *) (dst))[QuadPixel0] = (pixel);) \ + break; \ + } \ + switch ((bits & 0xf0) >> 4) { \ + case 0: \ + break; \ + case 1: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel4] = (pixel);) \ + break; \ + case 2: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel5] = (pixel);) \ + break; \ + case 3: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel2] = (pixel);)\ + break; \ + case 4: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel6] = (pixel);) \ + break; \ + case 5: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel6] = (pixel);) \ + break; \ + case 6: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel6] = (pixel);) \ + break; \ + case 7: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel2] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel6] = (pixel);) \ + break; \ + case 8: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel7] = (pixel);) \ + break; \ + case 9: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel);) \ + break; \ + case 10: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel);) \ + break; \ + case 11: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel2] = (pixel); \ + ((CARD8 *) (dst))[SinglePixel7] = (pixel);) \ + break; \ + case 12: \ + SwitchBitsLoop (((CARD16 *) (dst))[DoublePixel3] = (pixel);)\ + break; \ + case 13: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel3] = (pixel);)\ + break; \ + case 14: \ + SwitchBitsLoop (((CARD8 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD16 *) (dst))[DoublePixel3] = (pixel);)\ + break; \ + case 15: \ + SwitchBitsLoop (((CARD32 *) (dst))[QuadPixel1] = (pixel);) \ + break; \ + } \ + } \ +} +#endif /* PGSZ == 64 */ +#endif /* PSZ == 8 */ + +#if PSZ == 16 + +#if PGSZ == 32 +#define WriteBitGroup(dst,pixel,bits) \ + switch (bits) { \ + case 0: \ + break; \ + case 1: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + break; \ + case 2: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 3: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + break; \ + case 4: \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 5: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 6: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 7: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 8: \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 9: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 10: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 11: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 12: \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 13: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 14: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + } +#else /* PGSZ == 64 */ +#define WriteBitGroup(dst,pixel,bits) \ + if ( bits == 0xff ) { \ + ((PixelGroup *) (dst))[QuadPixel0] = (pixel); \ + ((PixelGroup *) (dst))[QuadPixel1] = (pixel); \ + } \ + else { \ + switch (bits & 0x0f) { \ + case 0: \ + break; \ + case 1: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + break; \ + case 2: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 3: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + break; \ + case 4: \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 5: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 6: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 7: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 8: \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 9: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 10: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 11: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 12: \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 13: \ + ((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 14: \ + ((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel); \ + break; \ + } \ + switch ((bits & 0xf0) >> 4) { \ + case 0: \ + break; \ + case 1: \ + ((CARD16 *) (dst))[SinglePixel4] = (pixel); \ + break; \ + case 2: \ + ((CARD16 *) (dst))[SinglePixel5] = (pixel); \ + break; \ + case 3: \ + ((CARD32 *) (dst))[DoublePixel2] = (pixel); \ + break; \ + case 4: \ + ((CARD16 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 5: \ + ((CARD16 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 6: \ + ((CARD16 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 7: \ + ((CARD32 *) (dst))[DoublePixel2] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 8: \ + ((CARD16 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 9: \ + ((CARD16 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 10: \ + ((CARD16 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 11: \ + ((CARD32 *) (dst))[DoublePixel2] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 12: \ + ((CARD32 *) (dst))[DoublePixel3] = (pixel); \ + break; \ + case 13: \ + ((CARD16 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel3] = (pixel); \ + break; \ + case 14: \ + ((CARD16 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel3] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[DoublePixel2] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel3] = (pixel); \ + break; \ + } \ + } +#endif /* PGSZ */ + +#if PGSZ == 32 +#define SwitchBitGroup(dst,pixel,bits) { \ + switch (bits) { \ + case 0: \ + break; \ + case 1: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel0] = (pixel);) \ + break; \ + case 2: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel1] = (pixel);) \ + break; \ + case 3: \ + SwitchBitsLoop (((CARD32 *) (dst))[DoublePixel0] = (pixel);) \ + break; \ + case 4: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 5: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 6: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 7: \ + SwitchBitsLoop (((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 8: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 9: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 10: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 11: \ + SwitchBitsLoop (((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD16 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 12: \ + SwitchBitsLoop (((CARD32 *) (dst))[DoublePixel1] = (pixel);) \ + break; \ + case 13: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel);) \ + break; \ + case 14: \ + SwitchBitsLoop (((CARD16 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel);) \ + break; \ + case 15: \ + SwitchBitsLoop (((CARD32 *) (dst))[DoublePixel0] = (pixel); \ + ((CARD32 *) (dst))[DoublePixel1] = (pixel);) \ + break; \ + } \ +} +#else /* PGSZ == 64 */ +#define SwitchBitGroup(dst,pixel,bits) { \ + cfb cannot hack 64-bit SwitchBitGroup psz=PSZ +#endif /* PGSZ */ + +#endif /* PSZ == 16 */ + + +#if PSZ == 32 + +#if PGSZ == 32 +#define WriteBitGroup(dst,pixel,bits) \ + switch (bits) { \ + case 0: \ + break; \ + case 1: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + break; \ + case 2: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 3: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 4: \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 5: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 6: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 7: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 8: \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 9: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 10: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 11: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 12: \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 13: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 14: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + } +#else /* PGSZ == 64 */ +#define WriteBitGroup(dst,pixel,bits) \ + if ( bits == 0xff ) { \ + ((PixelGroup *) (dst))[DoublePixel0] = (pixel); \ + ((PixelGroup *) (dst))[DoublePixel1] = (pixel); \ + ((PixelGroup *) (dst))[DoublePixel2] = (pixel); \ + ((PixelGroup *) (dst))[DoublePixel3] = (pixel); \ + } \ + else { \ + switch (bits & 0x0f) { \ + case 0: \ + break; \ + case 1: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + break; \ + case 2: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 3: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + break; \ + case 4: \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 5: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 6: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 7: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + break; \ + case 8: \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 9: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 10: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 11: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 12: \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 13: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 14: \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel); \ + break; \ + } \ + switch ((bits & 0xf0) >> 4) { \ + case 0: \ + break; \ + case 1: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + break; \ + case 2: \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + break; \ + case 3: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + break; \ + case 4: \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 5: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 6: \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 7: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + break; \ + case 8: \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 9: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 10: \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 11: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 12: \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 13: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 14: \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + case 15: \ + ((CARD32 *) (dst))[SinglePixel4] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel5] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel6] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel7] = (pixel); \ + break; \ + } \ + } +#endif /* PGSZ */ + +#if PGSZ == 32 +#define SwitchBitGroup(dst,pixel,bits) { \ + switch (bits) { \ + case 0: \ + break; \ + case 1: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel);) \ + break; \ + case 2: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel1] = (pixel);) \ + break; \ + case 3: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel);) \ + break; \ + case 4: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 5: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 6: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 7: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel);) \ + break; \ + case 8: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 9: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 10: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 11: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 12: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 13: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 14: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + case 15: \ + SwitchBitsLoop (((CARD32 *) (dst))[SinglePixel0] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel1] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel2] = (pixel); \ + ((CARD32 *) (dst))[SinglePixel3] = (pixel);) \ + break; \ + } \ +} +#else /* PGSZ == 64 */ +#define SwitchBitGroup(dst,pixel,bits) { \ + cfb cannot hack 64-bit SwitchBitGroup psz=PSZ +#endif /* PGSZ */ + +#endif /* PSZ == 32 */ +#endif /* AVOID_MEMORY_READ */ + +extern PixelGroup cfb8BitLenMasks[PGSZ]; + +extern int cfb8SetStipple ( +#if NeedFunctionPrototypes + int /*alu*/, + unsigned long /*fg*/, + unsigned long /*planemask*/ +#endif +); + +extern int cfb8SetOpaqueStipple ( +#if NeedFunctionPrototypes + int /*alu*/, + unsigned long /*fg*/, + unsigned long /*bg*/, + unsigned long /*planemask*/ +#endif +); + +extern int cfb8ComputeClipMasks32 ( +#if NeedFunctionPrototypes + BoxPtr /*pBox*/, + int /*numRects*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + CARD32 * /*clips*/ +#endif +); diff --git a/cfb/cfb8line.c b/cfb/cfb8line.c new file mode 100644 index 000000000..7a5f1ac5d --- /dev/null +++ b/cfb/cfb8line.c @@ -0,0 +1,915 @@ +/* + * $Xorg: cfb8line.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +#include "X.h" + +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "mistruct.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfbrrop.h" +#include "miline.h" + +#ifdef PIXEL_ADDR + +#if defined(__GNUC__) && defined(mc68020) +#define STUPID volatile +#define REARRANGE +#else +#define STUPID +#endif + +#ifdef __GNUC__ +/* lame compiler doesn't even look at 'register' attributes */ +#define I_H do{ +#define I_T }while(0); +#define IMPORTANT_START I_H I_H I_H I_H I_H I_H I_H I_H I_H I_H +#define IMPORTANT_END I_T I_T I_T I_T I_T I_T I_T I_T I_T I_T +#else +#define IMPORTANT_START +#define IMPORTANT_END +#endif + +#define isClipped(c,ul,lr) ((((c) - (ul)) | ((lr) - (c))) & ClipMask) + +#ifdef POLYSEGMENT + +# ifdef sun +# define WIDTH_FAST 1152 +# endif + +# ifdef ultrix +# define WIDTH_FAST 1024 +# endif + +# ifdef Mips +# define WIDTH_FAST 4096 +# endif +# ifdef WIDTH_FAST +# if WIDTH_FAST == 1024 +# define FAST_MUL(y) ((y) << 10) +# endif + +# if WIDTH_FAST == 1152 +# define FAST_MUL(y) (((y) << 10) + ((y) << 7)) +# endif + +# if WIDTH_FAST == 1280 +# define FAST_MUL(y) (((y) << 10) + ((y) << 8)) +# endif + +# if WIDTH_FAST == 2048 +# define FAST_MUL(y) ((y) << 11) +# endif + +# if WIDTH_FAST == 4096 +# define FAST_MUL(y) ((y) << 12) +# endif +# endif + +# if defined(WIDTH_SHIFT) +# ifdef FAST_MUL +# define FUNC_NAME(e) RROP_NAME(RROP_NAME_CAT(e,Shift)) +# if RROP == GXcopy +# define INCLUDE_OTHERS +# define SERIOUS_UNROLLING +# endif +# define INCLUDE_DRAW +# define NWIDTH(nwidth) WIDTH_FAST +# define WIDTH_MUL(y,w) FAST_MUL(y) +# endif +# else +# define FUNC_NAME(e) RROP_NAME(e) +# define WIDTH_MUL(y,w) ((y) * (w)) +# define NWIDTH(nwidth) (nwidth) +# define INCLUDE_DRAW +# if !defined (FAST_MUL) && RROP == GXcopy +# define INCLUDE_OTHERS +# define SERIOUS_UNROLLING +# endif +# endif +#else + +# define INCLUDE_DRAW +# define WIDTH_MUL(y,w) ((y) * (w)) +# define NWIDTH(nwidth) nwidth +# ifdef PREVIOUS +# define FUNC_NAME(e) RROP_NAME(RROP_NAME_CAT(e,Previous)) +# else +# define FUNC_NAME(e) RROP_NAME(e) +# if RROP == GXcopy +# define INCLUDE_OTHERS +# ifdef PLENTIFUL_REGISTERS +# define SAVE_X2Y2 +# endif +# define ORIGIN +# define SERIOUS_UNROLLING +# else +# define EITHER_MODE +# endif +# endif +#endif + +#ifdef INCLUDE_DRAW + +int +#ifdef POLYSEGMENT +FUNC_NAME(cfb8SegmentSS1Rect) (pDrawable, pGC, nseg, pSegInit) + DrawablePtr pDrawable; + GCPtr pGC; + int nseg; + xSegment *pSegInit; +#else +FUNC_NAME(cfb8LineSS1Rect) (pDrawable, pGC, mode, npt, pptInit, pptInitOrig, + x1p,y1p,x2p,y2p) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; /* number of points */ + DDXPointPtr pptInit, pptInitOrig; + int *x1p, *y1p, *x2p, *y2p; +#endif /* POLYSEGEMENT */ +{ + register long e; + register int y1_or_e1; + register PixelType *addrp; + register int stepmajor; + register int stepminor; +#ifndef REARRANGE + register long e3; +#endif +#ifdef mc68000 + register short x1_or_len; +#else + register int x1_or_len; +#endif + RROP_DECLARE + +#ifdef SAVE_X2Y2 +# define c2 y2 +#else + register int c2; +#endif +#ifndef ORIGIN + register int _x1, _y1, _x2, _y2; /* only used for CoordModePrevious */ + int extents_x1, extents_y1, extents_x2, extents_y2; +#endif /* !ORIGIN */ +#ifndef PREVIOUS + register int upperleft, lowerright; + CARD32 ClipMask = 0x80008000; +#endif /* !PREVIOUS */ +#ifdef POLYSEGMENT + register int capStyle; +#endif /* POLYSEGMENT */ +#ifdef SAVE_X2Y2 + register int x2, y2; +# define X1 x1_or_len +# define Y1 y1_or_e1 +# define X2 x2 +# define Y2 y2 +#else +# ifdef POLYSEGMENT +# define X1 x1_or_len +# define Y1 y1_or_e1 +# else +# define X1 intToX(y1_or_e1) +# define Y1 intToY(y1_or_e1) +# endif /* POLYSEGMENT */ +# define X2 intToX(c2) +# define Y2 intToY(c2) +#endif /* SAVE_X2Y2 */ + PixelType *addr; + int nwidth; + cfbPrivGCPtr devPriv; + BoxPtr extents; + int *ppt; + int octant; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + + devPriv = cfbGetGCPrivate(pGC); + cfbGetPixelWidthAndPointer (pDrawable, nwidth, addr); +#ifndef REARRANGE + RROP_FETCH_GCPRIV(devPriv); +#endif + extents = &devPriv->pCompositeClip->extents; +#ifndef PREVIOUS + c2 = *((int *) &pDrawable->x); + c2 -= (c2 & 0x8000) << 1; + upperleft = *((int *) &extents->x1) - c2; + lowerright = *((int *) &extents->x2) - c2 - 0x00010001; +#endif /* !PREVIOUS */ + addr = addr + WIDTH_MUL(pDrawable->y,nwidth) + pDrawable->x; +#ifdef POLYSEGMENT + capStyle = pGC->capStyle - CapNotLast; + ppt = (int *) pSegInit; + while (nseg--) +#else /* POLYSEGMENT */ +#ifdef EITHER_MODE + mode -= CoordModePrevious; + if (!mode) +#endif /* EITHER_MODE */ +#ifndef ORIGIN + { /* CoordModePrevious */ + ppt = (int *)pptInit + 1; + _x1 = *x1p; + _y1 = *y1p; + extents_x1 = extents->x1 - pDrawable->x; + extents_x2 = extents->x2 - pDrawable->x; + extents_y1 = extents->y1 - pDrawable->y; + extents_y2 = extents->y2 - pDrawable->y; + if (_x1 < extents_x1 || _x1 >= extents_x2 || + _y1 < extents_y1 || _y1 >= extents_y2) + { + c2 = *ppt++; + intToCoord(c2, _x2, _y2); + *x2p = _x1 + _x2; + *y2p = _y1 + _y2; + return 1; + } + addrp = addr + WIDTH_MUL(_y1, nwidth) + _x1; + _x2 = _x1; + _y2 = _y1; + } +#endif /* !ORIGIN */ +#ifdef EITHER_MODE + else +#endif /* EITHER_MODE */ +#ifndef PREVIOUS + { + ppt = (int *) pptInit; + c2 = *ppt++; + if (isClipped (c2, upperleft, lowerright)) + { + return 1; + } +#ifdef SAVE_X2Y2 + intToCoord(c2,x2,y2); +#endif + addrp = addr + WIDTH_MUL(Y2, nwidth) + X2; + } +#endif /* !PREVIOUS */ + while (--npt) +#endif /* POLYSEGMENT */ + { +#ifdef POLYSEGMENT + y1_or_e1 = ppt[0]; + c2 = ppt[1]; + ppt += 2; + if (isClipped(y1_or_e1,upperleft,lowerright)|isClipped(c2,upperleft,lowerright)) + break; + intToCoord(y1_or_e1,x1_or_len,y1_or_e1); + /* compute now to avoid needing x1, y1 later */ + addrp = addr + WIDTH_MUL(y1_or_e1, nwidth) + x1_or_len; +#else /* !POLYSEGMENT */ +#ifdef EITHER_MODE + if (!mode) +#endif /* EITHER_MODE */ +#ifndef ORIGIN + { + /* CoordModePrevious */ + _x1 = _x2; + _y1 = _y2; + c2 = *ppt++; + intToCoord(c2, _x2, _y2); + _x2 = _x1 + _x2; + _y2 = _y1 + _y2; + + if (_x2 < extents_x1 || _x2 >= extents_x2 || + _y2 < extents_y1 || _y2 >= extents_y2) + { + break; + } + CalcLineDeltas(_x1, _y1, _x2, _y2, x1_or_len, y1_or_e1, + stepmajor, stepminor, 1, NWIDTH(nwidth), octant); + } +#endif /* !ORIGIN */ +#ifdef EITHER_MODE + else +#endif /* EITHER_MODE */ +#ifndef PREVIOUS + { +#ifndef SAVE_X2Y2 + y1_or_e1 = c2; +#else + y1_or_e1 = y2; + x1_or_len = x2; +#endif /* SAVE_X2Y2 */ + c2 = *ppt++; + + if (isClipped (c2, upperleft, lowerright)) + break; +#ifdef SAVE_X2Y2 + intToCoord(c2,x2,y2); +#endif + CalcLineDeltas(X1, Y1, X2, Y2, x1_or_len, y1_or_e1, + stepmajor, stepminor, 1, NWIDTH(nwidth), octant); + } +#endif /* !PREVIOUS */ +#endif /* POLYSEGMENT */ + +#ifdef POLYSEGMENT + CalcLineDeltas(X1, Y1, X2, Y2, x1_or_len, y1_or_e1, + stepmajor, stepminor, 1, NWIDTH(nwidth), octant); + /* + * although the horizontal code works for polyline, it + * slows down 10 pixel lines by 15%. Thus, this + * code is optimized for horizontal segments and + * random orientation lines, which seems like a reasonable + * assumption + */ + if (y1_or_e1 != 0) + { +#endif /* POLYSEGMENT */ + if (x1_or_len < y1_or_e1) + { +#ifdef REARRANGE + register int e3; +#endif + + e3 = x1_or_len; + x1_or_len = y1_or_e1; + y1_or_e1 = e3; + + e3 = stepminor; + stepminor = stepmajor; + stepmajor = e3; + SetYMajorOctant(octant); + } + + e = -x1_or_len; +#ifdef POLYSEGMENT + if (!capStyle) + x1_or_len--; +#endif + + { +#ifdef REARRANGE + register int e3; + RROP_DECLARE + RROP_FETCH_GCPRIV(devPriv); +#endif + + y1_or_e1 = y1_or_e1 << 1; + e3 = e << 1; + + FIXUP_ERROR(e, octant, bias); + +#define body {\ + RROP_SOLID(addrp); \ + addrp += stepmajor; \ + e += y1_or_e1; \ + if (e >= 0) \ + { \ + addrp += stepminor; \ + e += e3; \ + } \ + } + +#ifdef LARGE_INSTRUCTION_CACHE + +# ifdef SERIOUS_UNROLLING +# define UNROLL 16 +# else +# define UNROLL 4 +# endif +#define CASE(n) case -n: body + + while ((x1_or_len -= UNROLL) >= 0) + { + body body body body +# if UNROLL >= 8 + body body body body +# endif +# if UNROLL >= 12 + body body body body +# endif +# if UNROLL >= 16 + body body body body +# endif + } + switch (x1_or_len) + { + CASE(1) CASE(2) CASE(3) +# if UNROLL >= 8 + CASE(4) CASE(5) CASE(6) CASE(7) +# endif +# if UNROLL >= 12 + CASE(8) CASE(9) CASE(10) CASE(11) +# endif +# if UNROLL >= 16 + CASE(12) CASE(13) CASE(14) CASE(15) +# endif + } +#else /* !LARGE_INSTRUCTION_CACHE */ + + IMPORTANT_START + IMPORTANT_START + + if (x1_or_len & 1) + body + x1_or_len >>= 1; + while (x1_or_len--) { + body body + } + + IMPORTANT_END + IMPORTANT_END +#endif /* LARGE_INSTRUCTION_CACHE */ + +#ifdef POLYSEGMENT + RROP_SOLID(addrp); +#endif + } +#undef body +#ifdef POLYSEGMENT + } + else + { +# ifdef REARRANGE + register int e3; + RROP_DECLARE + RROP_FETCH_GCPRIV(devPriv); +# endif /* REARRANGE */ + if (stepmajor < 0) + { + addrp -= x1_or_len; + if (capStyle) + x1_or_len++; + else + addrp++; + } + else + { + if (capStyle) + x1_or_len++; + } + y1_or_e1 = ((int) addrp) & PIM; + addrp = (PixelType *) (((unsigned char *) addrp) - y1_or_e1); +#if PGSZ == 32 +# if PWSH != 2 + y1_or_e1 >>= (2 - PWSH); +# endif +#else /* PGSZ == 64 */ +# if PWSH != 3 + y1_or_e1 >>= (3 - PWSH); +# endif +#endif /* PGSZ */ + if (y1_or_e1 + x1_or_len <= PPW) + { + if (x1_or_len) + { + maskpartialbits(y1_or_e1, x1_or_len, e) + RROP_SOLID_MASK((unsigned long *) addrp, e); + } + } + else + { + maskbits(y1_or_e1, x1_or_len, e, e3, x1_or_len) + if (e) + { + RROP_SOLID_MASK((unsigned long *) addrp, e); + addrp += PPW; + } + RROP_SPAN(addrp, x1_or_len) + if (e3) + RROP_SOLID_MASK((unsigned long *) addrp, e3); + } + } +#endif /* POLYSEGMENT */ + } +#ifdef POLYSEGMENT + if (nseg >= 0) + return (xSegment *) ppt - pSegInit; +#else + if (npt) + { +#ifdef EITHER_MODE + if (!mode) +#endif /* EITHER_MODE */ +#ifndef ORIGIN + { + *x1p = _x1; + *y1p = _y1; + *x2p = _x2; + *y2p = _y2; + } +#endif /* !ORIGIN */ + return ((DDXPointPtr) ppt - pptInit) - 1; + } +#endif /* POLYSEGMENT */ + +#ifndef POLYSEGMENT +# ifndef ORIGIN +# define C2 c2 +# else +# define C2 ppt[-1] +# endif +#ifdef EITHER_MODE + if (pGC->capStyle != CapNotLast && + ((mode ? (C2 != *((int *) pptInitOrig)) + : ((_x2 != pptInitOrig->x) || + (_y2 != pptInitOrig->y))) + || (ppt == ((int *)pptInitOrig) + 2))) +#endif /* EITHER_MODE */ +#ifdef PREVIOUS + if (pGC->capStyle != CapNotLast && + ((_x2 != pptInitOrig->x) || + (_y2 != pptInitOrig->y) || + (ppt == ((int *)pptInitOrig) + 2))) +#endif /* PREVIOUS */ +#ifdef ORIGIN + if (pGC->capStyle != CapNotLast && + ((C2 != *((int *) pptInitOrig)) || + (ppt == ((int *)pptInitOrig) + 2))) +#endif /* !PREVIOUS */ + { +# ifdef REARRANGE + RROP_DECLARE + + RROP_FETCH_GCPRIV(devPriv); +# endif + RROP_SOLID (addrp); + } +#endif /* !POLYSEGMENT */ + return -1; +} + +#endif /* INCLUDE_DRAW */ + + +#ifdef INCLUDE_OTHERS + +#ifdef POLYSEGMENT + +void +cfb8SegmentSS1Rect (pDrawable, pGC, nseg, pSegInit) + DrawablePtr pDrawable; + GCPtr pGC; + int nseg; + xSegment *pSegInit; +{ + int (*func)(); + void (*clip)(); + int drawn; + cfbPrivGCPtr devPriv; + + devPriv = cfbGetGCPrivate(pGC); +#ifdef NO_ONE_RECT + if (REGION_NUM_RECTS(devPriv->pCompositeClip) != 1) + { + cfbSegmentSS(pDrawable, pGC, nseg, pSegInit); + return; + } +#endif + switch (devPriv->rop) + { + case GXcopy: + func = cfb8SegmentSS1RectCopy; + clip = cfb8ClippedLineCopy; +#ifdef FAST_MUL + if (cfbGetPixelWidth (pDrawable) == WIDTH_FAST) + func = cfb8SegmentSS1RectShiftCopy; +#endif + break; + case GXxor: + func = cfb8SegmentSS1RectXor; + clip = cfb8ClippedLineXor; + break; + default: + func = cfb8SegmentSS1RectGeneral; + clip = cfb8ClippedLineGeneral; + break; + } + while (nseg) + { + drawn = (*func) (pDrawable, pGC, nseg, pSegInit); + if (drawn == -1) + break; + (*clip) (pDrawable, pGC, + pSegInit[drawn-1].x1, pSegInit[drawn-1].y1, + pSegInit[drawn-1].x2, pSegInit[drawn-1].y2, + &devPriv->pCompositeClip->extents, + pGC->capStyle == CapNotLast); + pSegInit += drawn; + nseg -= drawn; + } +} + +#else /* POLYSEGMENT */ + +void +cfb8LineSS1Rect (pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int npt; + DDXPointPtr pptInit; +{ + int (*func)(); + void (*clip)(); + int drawn; + cfbPrivGCPtr devPriv; + int x1, y1, x2, y2; + DDXPointPtr pptInitOrig = pptInit; + + devPriv = cfbGetGCPrivate(pGC); +#ifdef NO_ONE_RECT + if (REGION_NUM_RECTS(devPriv->pCompositeClip) != 1) + { + cfbLineSS(pDrawable, pGC, mode, npt, pptInit); + return; + } +#endif + switch (devPriv->rop) + { + case GXcopy: + func = cfb8LineSS1RectCopy; + clip = cfb8ClippedLineCopy; + if (mode == CoordModePrevious) + func = cfb8LineSS1RectPreviousCopy; + break; + case GXxor: + func = cfb8LineSS1RectXor; + clip = cfb8ClippedLineXor; + break; + default: + func = cfb8LineSS1RectGeneral; + clip = cfb8ClippedLineGeneral; + break; + } + if (mode == CoordModePrevious) + { + x1 = pptInit->x; + y1 = pptInit->y; + while (npt > 1) + { + drawn = (*func) (pDrawable, pGC, mode, npt, pptInit, pptInitOrig, + &x1, &y1, &x2, &y2); + if (drawn == -1) + break; + (*clip) (pDrawable, pGC, x1, y1, x2, y2, + &devPriv->pCompositeClip->extents, + drawn != npt - 1 || pGC->capStyle == CapNotLast); + pptInit += drawn; + npt -= drawn; + x1 = x2; + y1 = y2; + } + } + else + { + while (npt > 1) + { + drawn = (*func) (pDrawable, pGC, mode, npt, pptInit, pptInitOrig, + &x1, &y1, &x2, &y2); + if (drawn == -1) + break; + (*clip) (pDrawable, pGC, + pptInit[drawn-1].x, pptInit[drawn-1].y, + pptInit[drawn].x, pptInit[drawn].y, + &devPriv->pCompositeClip->extents, + drawn != npt - 1 || pGC->capStyle == CapNotLast); + pptInit += drawn; + npt -= drawn; + } + } +} + +#endif /* else POLYSEGMENT */ +#endif /* INCLUDE_OTHERS */ + +#if !defined(POLYSEGMENT) && !defined (PREVIOUS) + +void +RROP_NAME (cfb8ClippedLine) (pDrawable, pGC, x1, y1, x2, y2, boxp, shorten) + DrawablePtr pDrawable; + GCPtr pGC; + int x1, y1, x2, y2; + BoxPtr boxp; + Bool shorten; +{ + int oc1, oc2; + int e, e1, e3, len; + int adx, ady; + + PixelType *addr; + int nwidth; + int stepx, stepy; + int xorg, yorg; + int new_x1, new_y1, new_x2, new_y2; + Bool pt1_clipped, pt2_clipped; + int changex, changey, result; + int octant; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + + cfbGetPixelWidthAndPointer(pDrawable, nwidth, addr); + + xorg = pDrawable->x; + yorg = pDrawable->y; + x1 += xorg; + y1 += yorg; + x2 += xorg; + y2 += yorg; + oc1 = 0; + oc2 = 0; + OUTCODES (oc1, x1, y1, boxp); + OUTCODES (oc2, x2, y2, boxp); + + if (oc1 & oc2) + return; + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, stepx, stepy, 1, nwidth, octant); + + if (adx <= ady) + { + int t; + + t = adx; + adx = ady; + ady = t; + + t = stepx; + stepx = stepy; + stepy = t; + + SetYMajorOctant(octant); + } + e = - adx; + e1 = ady << 1; + e3 = - (adx << 1); + + FIXUP_ERROR(e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if (IsXMajorOctant(octant)) + { + result = miZeroClipLine(boxp->x1, boxp->y1, boxp->x2 - 1, boxp->y2 - 1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + return; + + len = abs(new_x2 - new_x1) - 1; /* this routine needs the "-1" */ + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + * if x2,y2 isn't clipped, use the capstyle + * (shorten == TRUE <--> CapNotLast) + */ + if (pt2_clipped || !shorten) + len++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + changex = abs(new_x1 - x1); + changey = abs(new_y1 - y1); + e = e + changey * e3 + changex * e1; + } + } + else /* Y_AXIS */ + { + result = miZeroClipLine(boxp->x1, boxp->y1, boxp->x2 - 1, boxp->y2 - 1, + &new_x1, &new_y1, &new_x2, &new_y2, + ady, adx, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + return; + + len = abs(new_y2 - new_y1) - 1; /* this routine needs the "-1" */ + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + * if x2,y2 isn't clipped, use the capstyle + * (shorten == TRUE <--> CapNotLast) + */ + if (pt2_clipped || !shorten) + len++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + changex = abs(new_x1 - x1); + changey = abs(new_y1 - y1); + e = e + changex * e3 + changey * e1; + } + } + x1 = new_x1; + y1 = new_y1; + { + register PixelType *addrp; + RROP_DECLARE + + RROP_FETCH_GC(pGC); + + addrp = addr + (y1 * nwidth) + x1; + +#ifndef REARRANGE + if (!ady) + { +#define body { RROP_SOLID(addrp); addrp += stepx; } + while (len >= PGSZB) + { + body body body body +#if PGSZ == 64 + body body body body +#endif + len -= PGSZB; + } + switch (len) + { +#if PGSZ == 64 + case 7: body case 6: body case 5: body case 4: body +#endif + case 3: body case 2: body case 1: body + } +#undef body + } + else +#endif /* !REARRANGE */ + { +#define body {\ + RROP_SOLID(addrp); \ + addrp += stepx; \ + e += e1; \ + if (e >= 0) \ + { \ + addrp += stepy; \ + e += e3; \ + } \ + } + +#ifdef LARGE_INSTRUCTION_CACHE + while ((len -= PGSZB) >= 0) + { + body body body body +#if PGSZ == 64 + body body body body +#endif + } + switch (len) + { + case -1: body case -2: body case -3: body +#if PGSZ == 64 + case -4: body case -5: body case -6: body case -7: body +#endif + } +#else /* !LARGE_INSTRUCTION_CACHE */ + IMPORTANT_START; + + while ((len -= 2) >= 0) + { + body body; + } + if (len & 1) + body; + + IMPORTANT_END; +#endif /* LARGE_INSTRUCTION_CACHE */ + } + RROP_SOLID(addrp); +#undef body + } +} + +#endif /* !POLYSEGMENT && !PREVIOUS */ +#endif /* PIXEL_ADDR */ diff --git a/cfb/cfballpriv.c b/cfb/cfballpriv.c new file mode 100644 index 000000000..abd634e2c --- /dev/null +++ b/cfb/cfballpriv.c @@ -0,0 +1,84 @@ +/* + * $Xorg: cfballpriv.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ + * +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "resource.h" +#include "colormap.h" +#include "colormapst.h" +#include "cfb.h" +#include "mi.h" +#include "mistruct.h" +#include "dix.h" +#include "cfbmskbits.h" +#include "mibstore.h" + +int cfbWindowPrivateIndex; +int cfbGCPrivateIndex; +#ifdef CFB_NEED_SCREEN_PRIVATE +int cfbScreenPrivateIndex; +#endif + +extern RegionPtr (*cfbPuntCopyPlane)(); + +Bool +cfbAllocatePrivates(pScreen, window_index, gc_index) + ScreenPtr pScreen; + int *window_index, *gc_index; +{ + if (!window_index || !gc_index || + *window_index == -1 && *gc_index == -1) + { + if (!mfbAllocatePrivates(pScreen, + &cfbWindowPrivateIndex, &cfbGCPrivateIndex)) + return FALSE; + if (window_index) + *window_index = cfbWindowPrivateIndex; + if (gc_index) + *gc_index = cfbGCPrivateIndex; + } + else + { + cfbWindowPrivateIndex = *window_index; + cfbGCPrivateIndex = *gc_index; + } + if (!AllocateWindowPrivate(pScreen, cfbWindowPrivateIndex, + sizeof(cfbPrivWin)) || + !AllocateGCPrivate(pScreen, cfbGCPrivateIndex, sizeof(cfbPrivGC))) + return FALSE; + cfbPuntCopyPlane = miCopyPlane; +#ifdef CFB_NEED_SCREEN_PRIVATE + cfbScreenPrivateIndex = AllocateScreenPrivateIndex (); + if (cfbScreenPrivateIndex == -1) + return FALSE; +#endif + return TRUE; +} diff --git a/cfb/cfbbitblt.c b/cfb/cfbbitblt.c new file mode 100644 index 000000000..3afe4eb81 --- /dev/null +++ b/cfb/cfbbitblt.c @@ -0,0 +1,759 @@ +/* + * cfb copy area + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Keith Packard + +*/ +/* $Xorg: cfbbitblt.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" +#include "fastblt.h" +#define MFB_CONSTS_ONLY +#include "maskbits.h" + +RegionPtr +cfbBitBlt (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, bitPlane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GC *pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + void (*doBitBlt)(); + unsigned long bitPlane; +{ + RegionPtr prgnSrcClip; /* may be a new region, or just a copy */ + Bool freeSrcClip = FALSE; + + RegionPtr prgnExposed; + RegionRec rgnDst; + DDXPointPtr pptSrc; + register DDXPointPtr ppt; + register BoxPtr pbox; + int i; + register int dx; + register int dy; + xRectangle origSource; + DDXPointRec origDest; + int numRects; + BoxRec fastBox; + int fastClip = 0; /* for fast clipping with pixmap source */ + int fastExpose = 0; /* for fast exposures with pixmap source */ + + origSource.x = srcx; + origSource.y = srcy; + origSource.width = width; + origSource.height = height; + origDest.x = dstx; + origDest.y = dsty; + + if ((pSrcDrawable != pDstDrawable) && + pSrcDrawable->pScreen->SourceValidate) + { + (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height); + } + + srcx += pSrcDrawable->x; + srcy += pSrcDrawable->y; + + /* clip the source */ + + if (pSrcDrawable->type == DRAWABLE_PIXMAP) + { + if ((pSrcDrawable == pDstDrawable) && + (pGC->clientClipType == CT_NONE)) + { + prgnSrcClip = cfbGetCompositeClip(pGC); + } + else + { + fastClip = 1; + } + } + else + { + if (pGC->subWindowMode == IncludeInferiors) + { + if (!((WindowPtr) pSrcDrawable)->parent) + { + /* + * special case bitblt from root window in + * IncludeInferiors mode; just like from a pixmap + */ + fastClip = 1; + } + else if ((pSrcDrawable == pDstDrawable) && + (pGC->clientClipType == CT_NONE)) + { + prgnSrcClip = cfbGetCompositeClip(pGC); + } + else + { + prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); + freeSrcClip = TRUE; + } + } + else + { + prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; + } + } + + fastBox.x1 = srcx; + fastBox.y1 = srcy; + fastBox.x2 = srcx + width; + fastBox.y2 = srcy + height; + + /* Don't create a source region if we are doing a fast clip */ + if (fastClip) + { + fastExpose = 1; + /* + * clip the source; if regions extend beyond the source size, + * make sure exposure events get sent + */ + if (fastBox.x1 < pSrcDrawable->x) + { + fastBox.x1 = pSrcDrawable->x; + fastExpose = 0; + } + if (fastBox.y1 < pSrcDrawable->y) + { + fastBox.y1 = pSrcDrawable->y; + fastExpose = 0; + } + if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) + { + fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + fastExpose = 0; + } + if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) + { + fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + fastExpose = 0; + } + } + else + { + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); + } + + dstx += pDstDrawable->x; + dsty += pDstDrawable->y; + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + if (!((WindowPtr)pDstDrawable)->realized) + { + if (!fastClip) + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return NULL; + } + } + + dx = srcx - dstx; + dy = srcy - dsty; + + /* Translate and clip the dst to the destination composite clip */ + if (fastClip) + { + RegionPtr cclip; + + /* Translate the region directly */ + fastBox.x1 -= dx; + fastBox.x2 -= dx; + fastBox.y1 -= dy; + fastBox.y2 -= dy; + + /* If the destination composite clip is one rectangle we can + do the clip directly. Otherwise we have to create a full + blown region and call intersect */ + + /* XXX because CopyPlane uses this routine for 8-to-1 bit + * copies, this next line *must* also correctly fetch the + * composite clip from an mfb gc + */ + + cclip = cfbGetCompositeClip(pGC); + if (REGION_NUM_RECTS(cclip) == 1) + { + BoxPtr pBox = REGION_RECTS(cclip); + + if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1; + if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2; + if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1; + if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2; + + /* Check to see if the region is empty */ + if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) + { + REGION_INIT(pGC->pScreen, &rgnDst, NullBox, 0); + } + else + { + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); + } + } + else + { + /* We must turn off fastClip now, since we must create + a full blown region. It is intersected with the + composite clip below. */ + fastClip = 0; + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1); + } + } + else + { + REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); + } + + if (!fastClip) + { + REGION_INTERSECT(pGC->pScreen, &rgnDst, + &rgnDst, + cfbGetCompositeClip(pGC)); + } + + /* Do bit blitting */ + numRects = REGION_NUM_RECTS(&rgnDst); + if (numRects && width && height) + { + if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects * + sizeof(DDXPointRec)))) + { + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return NULL; + } + pbox = REGION_RECTS(&rgnDst); + ppt = pptSrc; + for (i = numRects; --i >= 0; pbox++, ppt++) + { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc, pGC->planemask, bitPlane); + DEALLOCATE_LOCAL(pptSrc); + } + + prgnExposed = NULL; + if ( cfbGetGCPrivate(pGC)->fExpose) + { + extern RegionPtr miHandleExposures(); + + /* Pixmap sources generate a NoExposed (we return NULL to do this) */ + if (!fastExpose) + prgnExposed = + miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + origSource.x, origSource.y, + (int)origSource.width, + (int)origSource.height, + origDest.x, origDest.y, bitPlane); + } + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return prgnExposed; +} + + +void +cfbDoBitblt (pSrc, pDst, alu, prgnDst, pptSrc, planemask) + DrawablePtr pSrc, pDst; + int alu; + RegionPtr prgnDst; + DDXPointPtr pptSrc; + unsigned long planemask; +{ + void (*blt)() = cfbDoBitbltGeneral; + if ((planemask & PMSK) == PMSK) { + switch (alu) { + case GXcopy: + blt = cfbDoBitbltCopy; + break; + case GXxor: + blt = cfbDoBitbltXor; + break; + case GXor: + blt = cfbDoBitbltOr; + break; + } + } + (*blt) (pSrc, pDst, alu, prgnDst, pptSrc, planemask); +} + +RegionPtr +cfbCopyArea(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GC *pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; +{ + void (*doBitBlt) (); + + doBitBlt = cfbDoBitbltCopy; + if (pGC->alu != GXcopy || (pGC->planemask & PMSK) != PMSK) + { + doBitBlt = cfbDoBitbltGeneral; + if ((pGC->planemask & PMSK) == PMSK) + { + switch (pGC->alu) { + case GXxor: + doBitBlt = cfbDoBitbltXor; + break; + case GXor: + doBitBlt = cfbDoBitbltOr; + break; + } + } + } + return cfbBitBlt (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L); +} + +#if PSZ == 8 +void +cfbCopyPlane1to8 (pSrcDrawable, pDstDrawable, rop, prgnDst, pptSrc, planemask, bitPlane) + DrawablePtr pSrcDrawable; /* must be a bitmap */ + DrawablePtr pDstDrawable; /* must be depth 8 drawable */ + int rop; /* not used; caller must call cfb8CheckOpaqueStipple + * beforehand to get cfb8StippleRRop set correctly */ + unsigned long planemask; /* to apply to destination writes */ + RegionPtr prgnDst; /* region in destination to draw to; + * screen relative coords. if dest is a window; + * drawable relative if dest is a pixmap */ + DDXPointPtr pptSrc; /* drawable relative src coords to copy from; + * must be one point for each box in prgnDst */ + unsigned long bitPlane; /* not used; assumed always to be 1 */ +{ + int srcx, srcy; /* upper left corner of box being copied in source */ + int dstx, dsty; /* upper left corner of box being copied in dest */ + int width, height; /* in pixels, unpadded, of box being copied */ + int xoffSrc; /* bit # in leftmost word of row from which copying starts */ + int xoffDst; /* byte # in leftmost word of row from which copying starts */ + unsigned long *psrcBase, *pdstBase; /* start of drawable's pixel data */ + int widthSrc; /* # of groups of 32 pixels (1 bit/pixel) in src bitmap*/ + int widthDst; /* # of groups of 4 pixels (8 bits/pixel) in dst */ + unsigned long *psrcLine, *pdstLine; /* steps a row at a time thru src/dst; + * may point into middle of row */ + register unsigned long *psrc, *pdst; /* steps within the row */ + register unsigned long bits, tmp; /* bits from source */ + register int leftShift; + register int rightShift; + unsigned long startmask; /* left edge pixel mask */ + unsigned long endmask; /* right edge pixel mask */ + register int nlMiddle; /* number of words in middle of the row to draw */ + register int nl; + int firstoff; + int secondoff; + unsigned long src; + int nbox; /* number of boxes in region to copy */ + BoxPtr pbox; /* steps thru boxes in region */ + int pixelsRemainingOnRightEdge; /* # pixels to be drawn on a row after + * the main "middle" loop */ + + cfbGetLongWidthAndPointer (pSrcDrawable, widthSrc, psrcBase) + cfbGetLongWidthAndPointer (pDstDrawable, widthDst, pdstBase) + + nbox = REGION_NUM_RECTS(prgnDst); + pbox = REGION_RECTS(prgnDst); + while (nbox--) + { + dstx = pbox->x1; + dsty = pbox->y1; + srcx = pptSrc->x; + srcy = pptSrc->y; + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + pbox++; + pptSrc++; + + psrcLine = psrcBase + srcy * widthSrc + (srcx >> MFB_PWSH); + pdstLine = pdstBase + dsty * widthDst + (dstx >> PWSH); + xoffSrc = srcx & MFB_PIM; /* finds starting bit in src */ + xoffDst = dstx & PIM; /* finds starting byte in dst */ + + /* compute startmask, endmask, nlMiddle */ + + if (xoffDst + width < PPW) /* XXX should this be '<= PPW' ? */ + { /* the copy only affects one word per row in destination */ + maskpartialbits(dstx, width, startmask); + endmask = 0; /* nothing on right edge */ + nlMiddle = 0; /* nothing in middle */ + } + else + { /* the copy will affect multiple words per row in destination */ + maskbits(dstx, width, startmask, endmask, nlMiddle); + } + + /* + * compute constants for the first four bits to be + * copied. This avoids troubles with partial first + * writes, and difficult shift computation + */ + if (startmask) + { + firstoff = xoffSrc - xoffDst; + if (firstoff > (MFB_PPW-PPW)) + secondoff = MFB_PPW - firstoff; + if (xoffDst) + { + srcx += (PPW-xoffDst); + xoffSrc = srcx & MFB_PIM; + } + } + leftShift = xoffSrc; + rightShift = MFB_PPW - leftShift; + + pixelsRemainingOnRightEdge = (nlMiddle & 7) * PPW + + ((dstx + width) & PIM); + + /* setup is done; now let's move some bits */ + + /* caller must call cfb8CheckOpaqueStipple before this function + * to set cfb8StippleRRop! + */ + + if (cfb8StippleRRop == GXcopy) + { + while (height--) + { /* one iteration of this loop copies one row */ + psrc = psrcLine; + pdst = pdstLine; + psrcLine += widthSrc; + pdstLine += widthDst; + bits = *psrc++; + if (startmask) + { + if (firstoff < 0) + tmp = BitRight (bits, -firstoff); + else + { + tmp = BitLeft (bits, firstoff); + /* + * need a more cautious test for partialmask + * case... + */ + if (firstoff >= (MFB_PPW-PPW)) + { + bits = *psrc++; + if (firstoff != (MFB_PPW-PPW)) + tmp |= BitRight (bits, secondoff); + } + } + *pdst = (*pdst & ~startmask) | (GetPixelGroup(tmp) & startmask); + pdst++; + } + nl = nlMiddle; + while (nl >= 8) + { + nl -= 8; + tmp = BitLeft(bits, leftShift); + bits = *psrc++; + if (rightShift != MFB_PPW) + tmp |= BitRight(bits, rightShift); + +#ifdef FAST_CONSTANT_OFFSET_MODE +# define StorePixels(pdst,o,pixels) (pdst)[o] = (pixels) +# define EndStep(pdst,o) (pdst) += (o) +# define StoreRopPixels(pdst,o,and,xor) (pdst)[o] = DoRRop((pdst)[o],and,xor); +#else +# define StorePixels(pdst,o,pixels) *(pdst)++ = (pixels) +# define EndStep(pdst,o) +# define StoreRopPixels(pdst,o,and,xor) *(pdst) = DoRRop(*(pdst),and,xor); (pdst)++; +#endif + +#define Step(c) NextBitGroup(c); +#define StoreBitsPlain(o,c) StorePixels(pdst,o,GetPixelGroup(c)) +#define StoreRopBitsPlain(o,c) StoreRopPixels(pdst,o,\ + cfb8StippleAnd[GetBitGroup(c)], \ + cfb8StippleXor[GetBitGroup(c)]) +#define StoreBits0(c) StoreBitsPlain(0,c) +#define StoreRopBits0(c) StoreRopBitsPlain(0,c) + +#if (BITMAP_BIT_ORDER == MSBFirst) +# define StoreBits(o,c) StoreBitsPlain(o,c) +# define StoreRopBits(o,c) StoreRopBitsPlain(o,c) +# define FirstStep(c) Step(c) +#else /* BITMAP_BIT_ORDER == LSBFirst */ +#if PGSZ == 64 +# define StoreBits(o,c) StorePixels(pdst,o, (cfb8Pixels[c & 0xff])) +# define StoreRopBits(o,c) StoreRopPixels(pdst,o, \ + (cfb8StippleAnd[c & 0xff]), \ + (cfb8StippleXor[c & 0xff])) +# define FirstStep(c) c = BitLeft (c, 8); +#else +/* 0x3c is 0xf << 2 (4 bits, long word) */ +# define StoreBits(o,c) StorePixels(pdst,o,*((unsigned long *)\ + (((char *) cfb8Pixels) + (c & 0x3c)))) +# define StoreRopBits(o,c) StoreRopPixels(pdst,o, \ + *((unsigned long *) (((char *) cfb8StippleAnd) + (c & 0x3c))), \ + *((unsigned long *) (((char *) cfb8StippleXor) + (c & 0x3c)))) +# define FirstStep(c) c = BitLeft (c, 2); +#endif /* PGSZ */ +#endif /* BITMAP_BIT_ORDER */ + + StoreBits0(tmp); FirstStep(tmp); + StoreBits(1,tmp); Step(tmp); + StoreBits(2,tmp); Step(tmp); + StoreBits(3,tmp); Step(tmp); + StoreBits(4,tmp); Step(tmp); + StoreBits(5,tmp); Step(tmp); + StoreBits(6,tmp); Step(tmp); + StoreBits(7,tmp); EndStep (pdst,8); + } + + /* do rest of middle and partial word on right edge */ + + if (pixelsRemainingOnRightEdge) + { + tmp = BitLeft(bits, leftShift); + + if (pixelsRemainingOnRightEdge > rightShift) + { + bits = *psrc++; + tmp |= BitRight (bits, rightShift); + } + EndStep (pdst, nl); + switch (nl) + { + case 7: + StoreBitsPlain(-7,tmp); Step(tmp); + case 6: + StoreBitsPlain(-6,tmp); Step(tmp); + case 5: + StoreBitsPlain(-5,tmp); Step(tmp); + case 4: + StoreBitsPlain(-4,tmp); Step(tmp); + case 3: + StoreBitsPlain(-3,tmp); Step(tmp); + case 2: + StoreBitsPlain(-2,tmp); Step(tmp); + case 1: + StoreBitsPlain(-1,tmp); Step(tmp); + } + if (endmask) + *pdst = (*pdst & ~endmask) | (GetPixelGroup(tmp) & endmask); + } + } + } + else /* cfb8StippleRRop != GXcopy */ + { + while (height--) + { /* one iteration of this loop copies one row */ + psrc = psrcLine; + pdst = pdstLine; + psrcLine += widthSrc; + pdstLine += widthDst; + bits = *psrc++; + + /* do partial word on left edge */ + + if (startmask) + { + if (firstoff < 0) + tmp = BitRight (bits, -firstoff); + else + { + tmp = BitLeft (bits, firstoff); + if (firstoff >= (MFB_PPW-PPW)) + { + bits = *psrc++; + if (firstoff != (MFB_PPW-PPW)) + tmp |= BitRight (bits, secondoff); + } + } + src = GetBitGroup(tmp); + *pdst = MaskRRopPixels (*pdst, src, startmask); + pdst++; + } + + /* do middle of row */ + + nl = nlMiddle; + while (nl >= 8) + { + nl -= 8; + tmp = BitLeft(bits, leftShift); + bits = *psrc++; + if (rightShift != MFB_PPW) + tmp |= BitRight(bits, rightShift); + StoreRopBits0(tmp); FirstStep(tmp); + StoreRopBits(1,tmp); Step(tmp); + StoreRopBits(2,tmp); Step(tmp); + StoreRopBits(3,tmp); Step(tmp); + StoreRopBits(4,tmp); Step(tmp); + StoreRopBits(5,tmp); Step(tmp); + StoreRopBits(6,tmp); Step(tmp); + StoreRopBits(7,tmp); EndStep(pdst,8); + } + + /* do rest of middle and partial word on right edge */ + + if (pixelsRemainingOnRightEdge) + { + tmp = BitLeft(bits, leftShift); + + if (pixelsRemainingOnRightEdge > rightShift) + { + bits = *psrc++; /* XXX purify abr here */ + tmp |= BitRight (bits, rightShift); + } + while (nl--) + { + src = GetBitGroup (tmp); + *pdst = RRopPixels (*pdst, src); + pdst++; + NextBitGroup(tmp); + } + if (endmask) + { + src = GetBitGroup (tmp); + *pdst = MaskRRopPixels (*pdst, src, endmask); + } + } + } /* end copy one row */ + } /* end alu is non-copy-mode case */ + } /* end iteration over region boxes */ +} + +#endif + +/* shared among all different cfb depths through linker magic */ +RegionPtr (*cfbPuntCopyPlane)(); + +RegionPtr cfbCopyPlane(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane) + DrawablePtr pSrcDrawable; + DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long bitPlane; +{ + RegionPtr ret; + extern RegionPtr miHandleExposures(); + void (*doBitBlt)(); + +#if PSZ == 8 + + if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 8) + { + if (bitPlane == 1) + { + doBitBlt = cfbCopyPlane1to8; + cfb8CheckOpaqueStipple (pGC->alu, + pGC->fgPixel, pGC->bgPixel, + pGC->planemask); + ret = cfbBitBlt (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, bitPlane); + } + else + ret = miHandleExposures (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + } + else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 1) + { + extern int InverseAlu[16]; + int oldalu; + + oldalu = pGC->alu; + if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1) + pGC->alu = InverseAlu[pGC->alu]; + else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)) + pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel); + ret = cfbBitBlt (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, + cfbCopyPlane8to1, bitPlane); + pGC->alu = oldalu; + } + else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 8) + { + PixmapPtr pBitmap; + ScreenPtr pScreen = pSrcDrawable->pScreen; + GCPtr pGC1; + + pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1); + if (!pBitmap) + return NULL; + pGC1 = GetScratchGC (1, pScreen); + if (!pGC1) + { + (*pScreen->DestroyPixmap) (pBitmap); + return NULL; + } + /* + * don't need to set pGC->fgPixel,bgPixel as copyPlane8to1 + * ignores pixel values, expecting the rop to "do the + * right thing", which GXcopy will. + */ + ValidateGC ((DrawablePtr) pBitmap, pGC1); + /* no exposures here, scratch GC's don't get graphics expose */ + (void) cfbBitBlt (pSrcDrawable, (DrawablePtr) pBitmap, + pGC1, srcx, srcy, width, height, 0, 0, + cfbCopyPlane8to1, bitPlane); + cfb8CheckOpaqueStipple (pGC->alu, + pGC->fgPixel, pGC->bgPixel, + pGC->planemask); + /* no exposures here, copy bits from inside a pixmap */ + (void) cfbBitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC, + 0, 0, width, height, dstx, dsty, cfbCopyPlane1to8, 1); + FreeScratchGC (pGC1); + (*pScreen->DestroyPixmap) (pBitmap); + /* compute resultant exposures */ + ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, bitPlane); + } + else +#endif + ret = (*cfbPuntCopyPlane) (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + return ret; +} diff --git a/cfb/cfbblt.c b/cfb/cfbblt.c new file mode 100644 index 000000000..f87acc03d --- /dev/null +++ b/cfb/cfbblt.c @@ -0,0 +1,633 @@ +/* + * cfb copy area + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Keith Packard + +*/ +/* $Xorg: cfbblt.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" +#include "fastblt.h" +#include "mergerop.h" + +#ifdef notdef /* XXX fails right now, walks off end of pixmaps */ +#if defined (FAST_UNALIGNED_READS) && PSZ == 8 +#define DO_UNALIGNED_BITBLT +#endif +#endif + +#if defined(FAST_MEMCPY) && (MROP == Mcopy) && PSZ == 8 +#define DO_MEMCPY +#endif + +void +MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask) + DrawablePtr pSrc, pDst; + int alu; + RegionPtr prgnDst; + DDXPointPtr pptSrc; + unsigned long planemask; +{ + unsigned long *psrcBase, *pdstBase; + /* start of src and dst bitmaps */ + int widthSrc, widthDst; /* add to get to same position in next line */ + + BoxPtr pbox; + int nbox; + + BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; + /* temporaries for shuffling rectangles */ + DDXPointPtr pptTmp, pptNew1, pptNew2; + /* shuffling boxes entails shuffling the + source points too */ + int w, h; + int xdir; /* 1 = left right, -1 = right left/ */ + int ydir; /* 1 = top down, -1 = bottom up */ + + unsigned long *psrcLine, *pdstLine; + /* pointers to line with current src and dst */ + register unsigned long *psrc;/* pointer to current src longword */ + register unsigned long *pdst;/* pointer to current dst longword */ + + MROP_DECLARE_REG() + + /* following used for looping through a line */ + unsigned long startmask, endmask; /* masks for writing ends of dst */ + int nlMiddle; /* whole longwords in dst */ + int xoffSrc, xoffDst; + register int leftShift, rightShift; + register unsigned long bits; + register unsigned long bits1; + register int nl; /* temp copy of nlMiddle */ + + /* place to store full source word */ + int nstart; /* number of ragged bits at start of dst */ + int nend; /* number of ragged bits at end of dst */ + int srcStartOver; /* pulling nstart bits from src + overflows into the next word? */ + int careful; + int tmpSrc; + + MROP_INITIALIZE(alu,planemask); + + cfbGetLongWidthAndPointer (pSrc, widthSrc, psrcBase) + + cfbGetLongWidthAndPointer (pDst, widthDst, pdstBase) + + /* XXX we have to err on the side of safety when both are windows, + * because we don't know if IncludeInferiors is being used. + */ + careful = ((pSrc == pDst) || + ((pSrc->type == DRAWABLE_WINDOW) && + (pDst->type == DRAWABLE_WINDOW))); + + pbox = REGION_RECTS(prgnDst); + nbox = REGION_NUM_RECTS(prgnDst); + + pboxNew1 = NULL; + pptNew1 = NULL; + pboxNew2 = NULL; + pptNew2 = NULL; + if (careful && (pptSrc->y < pbox->y1)) + { + /* walk source botttom to top */ + ydir = -1; + widthSrc = -widthSrc; + widthDst = -widthDst; + + if (nbox > 1) + { + /* keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + if(!pboxNew1) + return; + pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); + if(!pptNew1) + { + DEALLOCATE_LOCAL(pboxNew1); + return; + } + pboxBase = pboxNext = pbox+nbox-1; + while (pboxBase >= pbox) + { + while ((pboxNext >= pbox) && + (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext+1; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp <= pboxBase) + { + *pboxNew1++ = *pboxTmp++; + *pptNew1++ = *pptTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + pptNew1 -= nbox; + pptSrc = pptNew1; + } + } + else + { + /* walk source top to bottom */ + ydir = 1; + } + + if (careful && (pptSrc->x < pbox->x1)) + { + /* walk source right to left */ + xdir = -1; + + if (nbox > 1) + { + /* reverse order of rects in each band */ + pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); + if(!pboxNew2 || !pptNew2) + { + if (pptNew2) DEALLOCATE_LOCAL(pptNew2); + if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2); + if (pboxNew1) + { + DEALLOCATE_LOCAL(pptNew1); + DEALLOCATE_LOCAL(pboxNew1); + } + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox+nbox) + { + while ((pboxNext < pbox+nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp != pboxBase) + { + *pboxNew2++ = *--pboxTmp; + *pptNew2++ = *--pptTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + pptNew2 -= nbox; + pptSrc = pptNew2; + } + } + else + { + /* walk source left to right */ + xdir = 1; + } + + while(nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + + if (ydir == -1) /* start at last scanline of rectangle */ + { + psrcLine = psrcBase + ((pptSrc->y+h-1) * -widthSrc); + pdstLine = pdstBase + ((pbox->y2-1) * -widthDst); + } + else /* start at first scanline */ + { + psrcLine = psrcBase + (pptSrc->y * widthSrc); + pdstLine = pdstBase + (pbox->y1 * widthDst); + } + if ((pbox->x1 & PIM) + w <= PPW) + { + maskpartialbits (pbox->x1, w, endmask); + startmask = 0; + nlMiddle = 0; + } + else + { + maskbits(pbox->x1, w, startmask, endmask, nlMiddle); + } + +#ifdef DO_MEMCPY + /* If the src and dst scanline don't overlap, do forward case. */ + + if ((xdir == 1) || (pptSrc->y != pbox->y1) + || (pptSrc->x + w <= pbox->x1)) + { + char *psrc = (char *) psrcLine + pptSrc->x; + char *pdst = (char *) pdstLine + pbox->x1; + while (h--) + { + memcpy(pdst, psrc, w); + pdst += widthDst << 2; + psrc += widthSrc << 2; + } + } +#else /* ! DO_MEMCPY */ + if (xdir == 1) + { + xoffSrc = pptSrc->x & PIM; + xoffDst = pbox->x1 & PIM; + pdstLine += (pbox->x1 >> PWSH); + psrcLine += (pptSrc->x >> PWSH); +#ifdef DO_UNALIGNED_BITBLT + nl = xoffSrc - xoffDst; + psrcLine = (unsigned long *) + (((unsigned char *) psrcLine) + nl); +#else + if (xoffSrc == xoffDst) +#endif + { + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + pdstLine += widthDst; + psrcLine += widthSrc; + if (startmask) + { + *pdst = MROP_MASK(*psrc, *pdst, startmask); + psrc++; + pdst++; + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); +#define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); + +#define LoopReset \ +pdst += UNROLL; \ +psrc += UNROLL; + +#else + +#define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++; +#define BodyEven(n) BodyOdd(n) + +#define LoopReset ; + +#endif + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else +#ifdef NOTDEF + /* you'd think this would be faster -- + * a single instruction instead of 6 + * but measurements show it to be ~15% slower + */ + while ((nl -= 6) >= 0) + { + asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0" + : "=m" (*(char *)pdst) + : "m" (*(char *)psrc) + : "d0", "d1", "d2", "d3", + "a2", "a3"); + pdst += 6; + } + nl += 6; + while (nl--) + *pdst++ = *psrc++; +#endif + DuffL(nl, label1, + *pdst = MROP_SOLID (*psrc, *pdst); + pdst++; psrc++;) +#endif + + if (endmask) + *pdst = MROP_MASK(*psrc, *pdst, endmask); + } + } +#ifndef DO_UNALIGNED_BITBLT + else + { + if (xoffSrc > xoffDst) + { +#if PGSZ == 32 + leftShift = (xoffSrc - xoffDst) << (5 - PWSH); +#else /* PGSZ == 64 */ + leftShift = (xoffSrc - xoffDst) << (6 - PWSH); +#endif /* PGSZ */ + rightShift = PGSZ - leftShift; + } + else + { +#if PGSZ == 32 + rightShift = (xoffDst - xoffSrc) << (5 - PWSH); +#else /* PGSZ == 64 */ + rightShift = (xoffDst - xoffSrc) << (6 - PWSH); +#endif /* PGSZ */ + leftShift = PGSZ - rightShift; + } + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + pdstLine += widthDst; + psrcLine += widthSrc; + bits = 0; + if (xoffSrc > xoffDst) + bits = *psrc++; + if (startmask) + { + bits1 = BitLeft(bits,leftShift); + bits = *psrc++; + bits1 |= BitRight(bits,rightShift); + *pdst = MROP_MASK(bits1, *pdst, startmask); + pdst++; + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE + bits1 = bits; + +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) \ +bits = psrc[-n]; \ +pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]); + +#define BodyEven(n) \ +bits1 = psrc[-n]; \ +pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]); + +#define LoopReset \ +pdst += UNROLL; \ +psrc += UNROLL; + +#else + +#define BodyOdd(n) \ +bits = *psrc++; \ +*pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \ +pdst++; + +#define BodyEven(n) \ +bits1 = *psrc++; \ +*pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \ +pdst++; + +#define LoopReset ; + +#endif /* !FAST_CONSTANT_OFFSET_MODE */ + + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL (nl,label2, + bits1 = BitLeft(bits, leftShift); + bits = *psrc++; + *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst); + pdst++; + ) +#endif + + if (endmask) + { + bits1 = BitLeft(bits, leftShift); + if (BitLeft(endmask, rightShift)) + { + bits = *psrc; + bits1 |= BitRight(bits, rightShift); + } + *pdst = MROP_MASK (bits1, *pdst, endmask); + } + } + } +#endif /* DO_UNALIGNED_BITBLT */ + } +#endif /* ! DO_MEMCPY */ + else /* xdir == -1 */ + { + xoffSrc = (pptSrc->x + w - 1) & PIM; + xoffDst = (pbox->x2 - 1) & PIM; + pdstLine += ((pbox->x2-1) >> PWSH) + 1; + psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1; +#ifdef DO_UNALIGNED_BITBLT + nl = xoffSrc - xoffDst; + psrcLine = (unsigned long *) + (((unsigned char *) psrcLine) + nl); +#else + if (xoffSrc == xoffDst) +#endif + { + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + pdstLine += widthDst; + psrcLine += widthSrc; + if (endmask) + { + pdst--; + psrc--; + *pdst = MROP_MASK (*psrc, *pdst, endmask); + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE +#ifdef FAST_CONSTANT_OFFSET_MODE + psrc -= nl & (UNROLL - 1); + pdst -= nl & (UNROLL - 1); + +#define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]); + +#define BodyEven(n) BodyOdd(n) + +#define LoopReset \ +pdst -= UNROLL;\ +psrc -= UNROLL; + +#else + +#define BodyOdd(n) --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst); +#define BodyEven(n) BodyOdd(n) +#define LoopReset ; + +#endif + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL(nl,label3, + --pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);) +#endif + + if (startmask) + { + --pdst; + --psrc; + *pdst = MROP_MASK(*psrc, *pdst, startmask); + } + } + } +#ifndef DO_UNALIGNED_BITBLT + else + { + if (xoffDst > xoffSrc) + { +#if PGSZ == 32 + rightShift = (xoffDst - xoffSrc) << (5 - PWSH); +#else /* PGSZ == 64 */ + rightShift = (xoffDst - xoffSrc) << (6 - PWSH); +#endif /* PGSZ */ + leftShift = PGSZ - rightShift; + } + else + { +#if PGSZ == 32 + leftShift = (xoffSrc - xoffDst) << (5 - PWSH); +#else /* PGSZ == 64 */ + leftShift = (xoffSrc - xoffDst) << (6 - PWSH); +#endif /* PGSZ */ + rightShift = PGSZ - leftShift; + } + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + pdstLine += widthDst; + psrcLine += widthSrc; + bits = 0; + if (xoffDst > xoffSrc) + bits = *--psrc; + if (endmask) + { + bits1 = BitRight(bits, rightShift); + bits = *--psrc; + bits1 |= BitLeft(bits, leftShift); + pdst--; + *pdst = MROP_MASK(bits1, *pdst, endmask); + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE + bits1 = bits; +#ifdef FAST_CONSTANT_OFFSET_MODE + psrc -= nl & (UNROLL - 1); + pdst -= nl & (UNROLL - 1); + +#define BodyOdd(n) \ +bits = psrc[n-1]; \ +pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]); + +#define BodyEven(n) \ +bits1 = psrc[n-1]; \ +pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]); + +#define LoopReset \ +pdst -= UNROLL; \ +psrc -= UNROLL; + +#else + +#define BodyOdd(n) \ +bits = *--psrc; --pdst; \ +*pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst); + +#define BodyEven(n) \ +bits1 = *--psrc; --pdst; \ +*pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst); + +#define LoopReset ; + +#endif + + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL (nl, label4, + bits1 = BitRight(bits, rightShift); + bits = *--psrc; + --pdst; + *pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst); + ) +#endif + + if (startmask) + { + bits1 = BitRight(bits, rightShift); + if (BitRight (startmask, leftShift)) + { + bits = *--psrc; + bits1 |= BitLeft(bits, leftShift); + } + --pdst; + *pdst = MROP_MASK(bits1, *pdst, startmask); + } + } + } +#endif + } + pbox++; + pptSrc++; + } + if (pboxNew2) + { + DEALLOCATE_LOCAL(pptNew2); + DEALLOCATE_LOCAL(pboxNew2); + } + if (pboxNew1) + { + DEALLOCATE_LOCAL(pptNew1); + DEALLOCATE_LOCAL(pboxNew1); + } +} diff --git a/cfb/cfbbres.c b/cfb/cfbbres.c new file mode 100644 index 000000000..139a868b7 --- /dev/null +++ b/cfb/cfbbres.c @@ -0,0 +1,233 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: cfbbres.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ +#include "X.h" +#include "misc.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "servermd.h" +#include "miline.h" + +/* Solid bresenham line */ +/* NOTES + e2 is used less often than e1, so it's not in a register +*/ + +void +cfbBresS(rop, and, xor, addrl, nlwidth, signdx, signdy, axis, x1, y1, e, e1, + e2, len) + int rop; + unsigned long and, xor; + unsigned long *addrl; /* pointer to base of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register int signdx; + int signdy; /* signs of directions */ + int axis; /* major axis (Y_AXIS or X_AXIS) */ + int x1, y1; /* initial point */ + register int e; /* error accumulator */ + register int e1; /* bresenham increments */ + int e2; + int len; /* length of line */ +{ + register int e3 = e2-e1; +#ifdef PIXEL_ADDR + register PixelType *addrp; /* Pixel pointer */ + + if (len == 0) + return; + /* point to first point */ + nlwidth <<= PWSH; + addrp = (PixelType *)(addrl) + (y1 * nlwidth) + x1; + if (signdy < 0) + nlwidth = -nlwidth; + e = e-e1; /* to make looping easier */ + + if (axis == Y_AXIS) + { + int t; + + t = nlwidth; + nlwidth = signdx; + signdx = t; + } + if (rop == GXcopy) + { + --len; +#define body {\ + *addrp = xor; \ + addrp += signdx; \ + e += e1; \ + if (e >= 0) \ + { \ + addrp += nlwidth; \ + e += e3; \ + } \ + } + while (len >= 4) + { + body body body body + len -= 4; + } + switch (len) + { + case 3: body case 2: body case 1: body + } +#undef body + *addrp = xor; + } + else /* not GXcopy */ + { + while(len--) + { + *addrp = DoRRop (*addrp, and, xor); + e += e1; + if (e >= 0) + { + addrp += nlwidth; + e += e3; + } + addrp += signdx; + } + } +#else /* !PIXEL_ADDR */ + register unsigned long tmp, bit; + unsigned long leftbit, rightbit; + + /* point to longword containing first point */ + addrl = (addrl + (y1 * nlwidth) + (x1 >> PWSH)); + if (signdy < 0) + nlwidth = -nlwidth; + e = e-e1; /* to make looping easier */ + + leftbit = cfbmask[0]; + rightbit = cfbmask[PPW-1]; + bit = cfbmask[x1 & PIM]; + + if (axis == X_AXIS) + { + if (signdx > 0) + { + while (len--) + { + *addrl = DoMaskRRop (*addrl, and, xor, bit); + bit = SCRRIGHT(bit,1); + e += e1; + if (e >= 0) + { + addrl += nlwidth; + e += e3; + } + if (!bit) + { + bit = leftbit; + addrl++; + } + } + } + else + { + while (len--) + { + *addrl = DoMaskRRop (*addrl, and, xor, bit); + e += e1; + bit = SCRLEFT(bit,1); + if (e >= 0) + { + addrl += nlwidth; + e += e3; + } + if (!bit) + { + bit = rightbit; + addrl--; + } + } + } + } /* if X_AXIS */ + else + { + if (signdx > 0) + { + while(len--) + { + *addrl = DoMaskRRop (*addrl, and, xor, bit); + e += e1; + if (e >= 0) + { + bit = SCRRIGHT(bit,1); + if (!bit) + { + bit = leftbit; + addrl++; + } + e += e3; + } + addrl += nlwidth; + } + } + else + { + while(len--) + { + *addrl = DoMaskRRop (*addrl, and, xor, bit); + e += e1; + if (e >= 0) + { + bit = SCRLEFT(bit,1); + if (!bit) + { + bit = rightbit; + addrl--; + } + e += e3; + } + addrl += nlwidth; + } + } + } /* else Y_AXIS */ +#endif +} diff --git a/cfb/cfbbresd.c b/cfb/cfbbresd.c new file mode 100644 index 000000000..6612803ae --- /dev/null +++ b/cfb/cfbbresd.c @@ -0,0 +1,258 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: cfbbresd.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ +#include "X.h" +#include "misc.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "miline.h" + +/* Dashed bresenham line */ + +void +cfbBresD(rrops, + pdashIndex, pDash, numInDashList, pdashOffset, isDoubleDash, + addrl, nlwidth, + signdx, signdy, axis, x1, y1, e, e1, e2, len) + cfbRRopPtr rrops; + int *pdashIndex; /* current dash */ + unsigned char *pDash; /* dash list */ + int numInDashList; /* total length of dash list */ + int *pdashOffset; /* offset into current dash */ + int isDoubleDash; + unsigned long *addrl; /* pointer to base of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + int signdx, signdy; /* signs of directions */ + int axis; /* major axis (Y_AXIS or X_AXIS) */ + int x1, y1; /* initial point */ + register int e; /* error accumulator */ + register int e1; /* bresenham increments */ + int e2; + int len; /* length of line */ +{ +#ifdef PIXEL_ADDR + register PixelType *addrp; +#endif + register int e3 = e2-e1; + int dashIndex; + int dashOffset; + int dashRemaining; + unsigned long xorFg, andFg, xorBg, andBg; + Bool isCopy; + int thisDash; + + dashOffset = *pdashOffset; + dashIndex = *pdashIndex; + isCopy = (rrops[0].rop == GXcopy && rrops[1].rop == GXcopy); + xorFg = rrops[0].xor; + andFg = rrops[0].and; + xorBg = rrops[1].xor; + andBg = rrops[1].and; + dashRemaining = pDash[dashIndex] - dashOffset; + if ((thisDash = dashRemaining) >= len) + { + thisDash = len; + dashRemaining -= len; + } + e = e-e1; /* to make looping easier */ + +#define BresStep(minor,major) {if ((e += e1) >= 0) { e += e3; minor; } major;} + +#define NextDash {\ + dashIndex++; \ + if (dashIndex == numInDashList) \ + dashIndex = 0; \ + dashRemaining = pDash[dashIndex]; \ + if ((thisDash = dashRemaining) >= len) \ + { \ + dashRemaining -= len; \ + thisDash = len; \ + } \ +} + +#ifdef PIXEL_ADDR + +#define Loop(store) while (thisDash--) {\ + store; \ + BresStep(addrp+=signdy,addrp+=signdx) \ + } + /* point to first point */ + nlwidth <<= PWSH; + addrp = (PixelType *)(addrl) + (y1 * nlwidth) + x1; + signdy *= nlwidth; + if (axis == Y_AXIS) + { + int t; + + t = signdx; + signdx = signdy; + signdy = t; + } + + if (isCopy) + { + for (;;) + { + len -= thisDash; + if (dashIndex & 1) { + if (isDoubleDash) { + Loop(*addrp = xorBg) + } else { + Loop(;) + } + } else { + Loop(*addrp = xorFg) + } + if (!len) + break; + NextDash + } + } + else + { + for (;;) + { + len -= thisDash; + if (dashIndex & 1) { + if (isDoubleDash) { + Loop(*addrp = DoRRop(*addrp,andBg, xorBg)) + } else { + Loop(;) + } + } else { + Loop(*addrp = DoRRop(*addrp,andFg, xorFg)) + } + if (!len) + break; + NextDash + } + } +#else /* !PIXEL_ADDR */ + { + register unsigned long tmp; + unsigned long startbit, bit; + + /* point to longword containing first point */ + addrl = (addrl + (y1 * nlwidth) + (x1 >> PWSH)); + signdy = signdy * nlwidth; + + if (signdx > 0) + startbit = cfbmask[0]; + else + startbit = cfbmask[PPW-1]; + bit = cfbmask[x1 & PIM]; + +#define X_Loop(store) while(thisDash--) {\ + store; \ + BresStep(addrl += signdy, \ + if (signdx > 0) \ + bit = SCRRIGHT(bit,1); \ + else \ + bit = SCRLEFT(bit,1); \ + if (!bit) \ + { \ + bit = startbit; \ + addrl += signdx; \ + }) \ + } +#define Y_Loop(store) while(thisDash--) {\ + store; \ + BresStep(if (signdx > 0) \ + bit = SCRRIGHT(bit,1); \ + else \ + bit = SCRLEFT(bit,1); \ + if (!bit) \ + { \ + bit = startbit; \ + addrl += signdx; \ + }, \ + addrl += signdy) \ + } + + if (axis == X_AXIS) + { + for (;;) + { + len -= thisDash; + if (dashIndex & 1) { + if (isDoubleDash) { + X_Loop(*addrl = DoMaskRRop(*addrl, andBg, xorBg, bit)); + } else { + X_Loop(;) + } + } else { + X_Loop(*addrl = DoMaskRRop(*addrl, andFg, xorFg, bit)); + } + if (!len) + break; + NextDash + } + } /* if X_AXIS */ + else + { + for (;;) + { + len -= thisDash; + if (dashIndex & 1) { + if (isDoubleDash) { + Y_Loop(*addrl = DoMaskRRop(*addrl, andBg, xorBg, bit)); + } else { + Y_Loop(;) + } + } else { + Y_Loop(*addrl = DoMaskRRop(*addrl, andFg, xorFg, bit)); + } + if (!len) + break; + NextDash + } + } /* else Y_AXIS */ + } +#endif + *pdashIndex = dashIndex; + *pdashOffset = pDash[dashIndex] - dashRemaining; +} diff --git a/cfb/cfbbstore.c b/cfb/cfbbstore.c new file mode 100644 index 000000000..ae0303dce --- /dev/null +++ b/cfb/cfbbstore.c @@ -0,0 +1,147 @@ +/*- + * cfbbstore.c -- + * Functions required by the backing-store implementation in MI. + * + * Copyright (c) 1987 by the Regents of the University of California + * + * 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. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * + */ +/* $Xorg: cfbbstore.c,v 1.3 2000/08/17 19:48:13 cpqbld Exp $ */ + +#include "cfb.h" +#include "X.h" +#include "mibstore.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" + +/*- + *----------------------------------------------------------------------- + * cfbSaveAreas -- + * Function called by miSaveAreas to actually fetch the areas to be + * saved into the backing pixmap. This is very simple to do, since + * cfbDoBitblt is designed for this very thing. The region to save is + * already destination-relative and we're given the offset to the + * window origin, so we have only to create an array of points of the + * u.l. corners of the boxes in the region translated to the screen + * coordinate system and fetch the screen pixmap out of its devPrivate + * field.... + * + * Results: + * None. + * + * Side Effects: + * Data are copied from the screen into the pixmap. + * + *----------------------------------------------------------------------- + */ +void +cfbSaveAreas(pPixmap, prgnSave, xorg, yorg, pWin) + PixmapPtr pPixmap; /* Backing pixmap */ + RegionPtr prgnSave; /* Region to save (pixmap-relative) */ + int xorg; /* X origin of region */ + int yorg; /* Y origin of region */ + WindowPtr pWin; +{ + register DDXPointPtr pPt; + DDXPointPtr pPtsInit; + register BoxPtr pBox; + register int i; + ScreenPtr pScreen = pPixmap->drawable.pScreen; + PixmapPtr pScrPix; + + i = REGION_NUM_RECTS(prgnSave); + pPtsInit = (DDXPointPtr)ALLOCATE_LOCAL(i * sizeof(DDXPointRec)); + if (!pPtsInit) + return; + + pBox = REGION_RECTS(prgnSave); + pPt = pPtsInit; + while (--i >= 0) { + pPt->x = pBox->x1 + xorg; + pPt->y = pBox->y1 + yorg; + pPt++; + pBox++; + } + +#ifdef CFB_NEED_SCREEN_PRIVATE + pScrPix = (PixmapPtr) pScreen->devPrivates[cfbScreenPrivateIndex].ptr; +#else + pScrPix = (PixmapPtr) pScreen->devPrivate; +#endif + + cfbDoBitbltCopy((DrawablePtr) pScrPix, (DrawablePtr)pPixmap, + GXcopy, prgnSave, pPtsInit, ~0L); + + DEALLOCATE_LOCAL (pPtsInit); +} + +/*- + *----------------------------------------------------------------------- + * cfbRestoreAreas -- + * Function called by miRestoreAreas to actually fetch the areas to be + * restored from the backing pixmap. This is very simple to do, since + * cfbDoBitblt is designed for this very thing. The region to restore is + * already destination-relative and we're given the offset to the + * window origin, so we have only to create an array of points of the + * u.l. corners of the boxes in the region translated to the pixmap + * coordinate system and fetch the screen pixmap out of its devPrivate + * field.... + * + * Results: + * None. + * + * Side Effects: + * Data are copied from the pixmap into the screen. + * + *----------------------------------------------------------------------- + */ +void +cfbRestoreAreas(pPixmap, prgnRestore, xorg, yorg, pWin) + PixmapPtr pPixmap; /* Backing pixmap */ + RegionPtr prgnRestore; /* Region to restore (screen-relative)*/ + int xorg; /* X origin of window */ + int yorg; /* Y origin of window */ + WindowPtr pWin; +{ + register DDXPointPtr pPt; + DDXPointPtr pPtsInit; + register BoxPtr pBox; + register int i; + ScreenPtr pScreen = pPixmap->drawable.pScreen; + PixmapPtr pScrPix; + + i = REGION_NUM_RECTS(prgnRestore); + pPtsInit = (DDXPointPtr)ALLOCATE_LOCAL(i*sizeof(DDXPointRec)); + if (!pPtsInit) + return; + + pBox = REGION_RECTS(prgnRestore); + pPt = pPtsInit; + while (--i >= 0) { + pPt->x = pBox->x1 - xorg; + pPt->y = pBox->y1 - yorg; + pPt++; + pBox++; + } + +#ifdef CFB_NEED_SCREEN_PRIVATE + pScrPix = (PixmapPtr) pScreen->devPrivates[cfbScreenPrivateIndex].ptr; +#else + pScrPix = (PixmapPtr) pScreen->devPrivate; +#endif + + cfbDoBitbltCopy((DrawablePtr)pPixmap, (DrawablePtr) pScrPix, + GXcopy, prgnRestore, pPtsInit, ~0L); + + DEALLOCATE_LOCAL (pPtsInit); +} diff --git a/cfb/cfbcmap.c b/cfb/cfbcmap.c new file mode 100644 index 000000000..103860e86 --- /dev/null +++ b/cfb/cfbcmap.c @@ -0,0 +1,587 @@ +/* $Xorg: cfbcmap.c,v 1.3 2000/08/17 19:48:13 cpqbld Exp $ */ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ + + +#include "X.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "colormapst.h" +#include "resource.h" + +#ifdef STATIC_COLOR + +static ColormapPtr InstalledMaps[MAXSCREENS]; + +int +cfbListInstalledColormaps(pScreen, pmaps) + ScreenPtr pScreen; + Colormap *pmaps; +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + *pmaps = InstalledMaps[pScreen->myNum]->mid; + return (1); +} + + +void +cfbInstallColormap(pmap) + ColormapPtr pmap; +{ + int index = pmap->pScreen->myNum; + ColormapPtr oldpmap = InstalledMaps[index]; + + if(pmap != oldpmap) + { + /* Uninstall pInstalledMap. No hardware changes required, just + * notify all interested parties. */ + if(oldpmap != (ColormapPtr)None) + WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); + /* Install pmap */ + InstalledMaps[index] = pmap; + WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); + + } +} + +void +cfbUninstallColormap(pmap) + ColormapPtr pmap; +{ + int index = pmap->pScreen->myNum; + ColormapPtr curpmap = InstalledMaps[index]; + + if(pmap == curpmap) + { + if (pmap->mid != pmap->pScreen->defColormap) + { + curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, + RT_COLORMAP); + (*pmap->pScreen->InstallColormap)(curpmap); + } + } +} + +#endif + +void +cfbResolveColor(pred, pgreen, pblue, pVisual) + unsigned short *pred, *pgreen, *pblue; + register VisualPtr pVisual; +{ + int shift = 16 - pVisual->bitsPerRGBValue; + unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1; + + if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) + { + /* rescale to rgb bits */ + *pred = ((*pred >> shift) * 65535) / lim; + *pgreen = ((*pgreen >> shift) * 65535) / lim; + *pblue = ((*pblue >> shift) * 65535) / lim; + } + else if (pVisual->class == GrayScale) + { + /* rescale to gray then rgb bits */ + *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100; + *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim; + } + else if (pVisual->class == StaticGray) + { + unsigned limg = pVisual->ColormapEntries - 1; + /* rescale to gray then [0..limg] then [0..65535] then rgb bits */ + *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100; + *pred = ((((*pred * (limg + 1))) >> 16) * 65535) / limg; + *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim; + } + else + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + /* rescale to [0..limN] then [0..65535] then rgb bits */ + *pred = ((((((*pred * (limr + 1)) >> 16) * + 65535) / limr) >> shift) * 65535) / lim; + *pgreen = ((((((*pgreen * (limg + 1)) >> 16) * + 65535) / limg) >> shift) * 65535) / lim; + *pblue = ((((((*pblue * (limb + 1)) >> 16) * + 65535) / limb) >> shift) * 65535) / lim; + } +} + +Bool +cfbInitializeColormap(pmap) + register ColormapPtr pmap; +{ + register unsigned i; + register VisualPtr pVisual; + unsigned lim, maxent, shift; + + pVisual = pmap->pVisual; + lim = (1 << pVisual->bitsPerRGBValue) - 1; + shift = 16 - pVisual->bitsPerRGBValue; + maxent = pVisual->ColormapEntries - 1; + if (pVisual->class == TrueColor) + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = + ((((i * 65535) / limr) >> shift) * 65535) / lim; + pmap->green[i].co.local.green = + ((((i * 65535) / limg) >> shift) * 65535) / lim; + pmap->blue[i].co.local.blue = + ((((i * 65535) / limb) >> shift) * 65535) / lim; + } + } + else if (pVisual->class == StaticColor) + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = + ((((((i & pVisual->redMask) >> pVisual->offsetRed) + * 65535) / limr) >> shift) * 65535) / lim; + pmap->red[i].co.local.green = + ((((((i & pVisual->greenMask) >> pVisual->offsetGreen) + * 65535) / limg) >> shift) * 65535) / lim; + pmap->red[i].co.local.blue = + ((((((i & pVisual->blueMask) >> pVisual->offsetBlue) + * 65535) / limb) >> shift) * 65535) / lim; + } + } + else if (pVisual->class == StaticGray) + { + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift) + * 65535) / lim; + pmap->red[i].co.local.green = pmap->red[i].co.local.red; + pmap->red[i].co.local.blue = pmap->red[i].co.local.red; + } + } + return TRUE; +} + +/* When simulating DirectColor on PseudoColor hardware, multiple + entries of the colormap must be updated + */ + +#define AddElement(mask) { \ + pixel = red | green | blue; \ + for (i = 0; i < nresult; i++) \ + if (outdefs[i].pixel == pixel) \ + break; \ + if (i == nresult) \ + { \ + nresult++; \ + outdefs[i].pixel = pixel; \ + outdefs[i].flags = 0; \ + } \ + outdefs[i].flags |= (mask); \ + outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \ + outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \ + outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \ +} + +cfbExpandDirectColors (pmap, ndef, indefs, outdefs) + ColormapPtr pmap; + int ndef; + xColorItem *indefs, *outdefs; +{ + int minred, mingreen, minblue; + register int red, green, blue; + int maxred, maxgreen, maxblue; + int stepred, stepgreen, stepblue; + VisualPtr pVisual; + register int pixel; + register int nresult; + register int i; + + pVisual = pmap->pVisual; + + stepred = 1 << pVisual->offsetRed; + stepgreen = 1 << pVisual->offsetGreen; + stepblue = 1 << pVisual->offsetBlue; + maxred = pVisual->redMask; + maxgreen = pVisual->greenMask; + maxblue = pVisual->blueMask; + nresult = 0; + for (;ndef--; indefs++) + { + if (indefs->flags & DoRed) + { + red = indefs->pixel & pVisual->redMask; + for (green = 0; green <= maxgreen; green += stepgreen) + { + for (blue = 0; blue <= maxblue; blue += stepblue) + { + AddElement (DoRed) + } + } + } + if (indefs->flags & DoGreen) + { + green = indefs->pixel & pVisual->greenMask; + for (red = 0; red <= maxred; red += stepred) + { + for (blue = 0; blue <= maxblue; blue += stepblue) + { + AddElement (DoGreen) + } + } + } + if (indefs->flags & DoBlue) + { + blue = indefs->pixel & pVisual->blueMask; + for (red = 0; red <= maxred; red += stepred) + { + for (green = 0; green <= maxgreen; green += stepgreen) + { + AddElement (DoBlue) + } + } + } + } + return nresult; +} + +Bool +cfbCreateDefColormap(pScreen) + ScreenPtr pScreen; +{ +/* + * In the following sources PC X server vendors may want to delete + * "_not_tog" from "#ifdef WIN32_not_tog" + */ +#ifdef WIN32_not_tog + /* + * these are the MS-Windows desktop colors, adjusted for X's 16-bit + * color specifications. + */ + static xColorItem citems[] = { + { 0, 0, 0, 0, 0, 0 }, + { 1, 0x8000, 0, 0, 0, 0 }, + { 2, 0, 0x8000, 0, 0, 0 }, + { 3, 0x8000, 0x8000, 0, 0, 0 }, + { 4, 0, 0, 0x8000, 0, 0 }, + { 5, 0x8000, 0, 0x8000, 0, 0 }, + { 6, 0, 0x8000, 0x8000, 0, 0 }, + { 7, 0xc000, 0xc000, 0xc000, 0, 0 }, + { 8, 0xc000, 0xdc00, 0xc000, 0, 0 }, + { 9, 0xa600, 0xca00, 0xf000, 0, 0 }, + { 246, 0xff00, 0xfb00, 0xf000, 0, 0 }, + { 247, 0xa000, 0xa000, 0xa400, 0, 0 }, + { 248, 0x8000, 0x8000, 0x8000, 0, 0 }, + { 249, 0xff00, 0, 0, 0, 0 }, + { 250, 0, 0xff00, 0, 0, 0 }, + { 251, 0xff00, 0xff00, 0, 0, 0 }, + { 252, 0, 0, 0xff00, 0, 0 }, + { 253, 0xff00, 0, 0xff00, 0, 0 }, + { 254, 0, 0xff00, 0xff00, 0, 0 }, + { 255, 0xff00, 0xff00, 0xff00, 0, 0 } + }; +#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0] + int i; +#else + unsigned short zero = 0, ones = 0xFFFF; +#endif + Pixel wp, bp; + VisualPtr pVisual; + ColormapPtr cmap; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + + if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap, + (pVisual->class & DynamicClass) ? AllocNone : AllocAll, + 0) + != Success) + return FALSE; + wp = pScreen->whitePixel; + bp = pScreen->blackPixel; +#ifdef WIN32_not_tog + for (i = 0; i < NUM_DESKTOP_COLORS; i++) { + if (AllocColor (cmap, + &citems[i].red, &citems[i].green, &citems[i].blue, + &citems[i].pixel, 0) != Success) + return FALSE; + } +#else + if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) != + Success) || + (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != + Success)) + return FALSE; + pScreen->whitePixel = wp; + pScreen->blackPixel = bp; +#endif + (*pScreen->InstallColormap)(cmap); + return TRUE; +} + +extern int defaultColorVisualClass; + +#define _RZ(d) ((d + 2) / 3) +#define _RS(d) 0 +#define _RM(d) ((1 << _RZ(d)) - 1) +#define _GZ(d) ((d - _RZ(d) + 1) / 2) +#define _GS(d) _RZ(d) +#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d)) +#define _BZ(d) (d - _RZ(d) - _GZ(d)) +#define _BS(d) (_RZ(d) + _GZ(d)) +#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d)) +#define _CE(d) (1 << _RZ(d)) + +#define MAX_PSEUDO_DEPTH 10 /* largest DAC size I know */ + +#define StaticGrayMask (1 << StaticGray) +#define GrayScaleMask (1 << GrayScale) +#define StaticColorMask (1 << StaticColor) +#define PseudoColorMask (1 << PseudoColor) +#define TrueColorMask (1 << TrueColor) +#define DirectColorMask (1 << DirectColor) + +#define ALL_VISUALS (StaticGrayMask|\ + GrayScaleMask|\ + StaticColorMask|\ + PseudoColorMask|\ + TrueColorMask|\ + DirectColorMask) + +#define LARGE_VISUALS (TrueColorMask|\ + DirectColorMask) + +typedef struct _cfbVisuals { + struct _cfbVisuals *next; + int depth; + int bitsPerRGB; + int visuals; + int count; +} cfbVisualsRec, *cfbVisualsPtr; + +static int cfbVisualPriority[] = { + PseudoColor, DirectColor, GrayScale, StaticColor, TrueColor, StaticGray +}; + +#define NUM_PRIORITY 6 + +static cfbVisualsPtr cfbVisuals; + +Bool +cfbSetVisualTypes (depth, visuals, bitsPerRGB) + int depth; + int visuals; +{ + cfbVisualsPtr new, *prev, v; + int count; + + new = (cfbVisualsPtr) xalloc (sizeof *new); + if (!new) + return FALSE; + new->next = 0; + new->depth = depth; + new->visuals = visuals; + new->bitsPerRGB = bitsPerRGB; + count = (visuals >> 1) & 033333333333; + count = visuals - count - ((count >> 1) & 033333333333); + count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */ + new->count = count; + for (prev = &cfbVisuals; v = *prev; prev = &v->next); + *prev = new; + return TRUE; +} + +/* + * Given a list of formats for a screen, create a list + * of visuals and depths for the screen which coorespond to + * the set which can be used with this version of cfb. + */ + +Bool +cfbInitVisuals (visualp, depthp, nvisualp, ndepthp, rootDepthp, defaultVisp, sizes, bitsPerRGB) + VisualPtr *visualp; + DepthPtr *depthp; + int *nvisualp, *ndepthp; + int *rootDepthp; + VisualID *defaultVisp; + unsigned long sizes; + int bitsPerRGB; +{ + int i, j, k; + VisualPtr visual; + DepthPtr depth; + VisualID *vid; + int d, b; + int f; + int ndepth, nvisual; + int nvtype; + int vtype; + VisualID defaultVisual; + cfbVisualsPtr visuals, nextVisuals; + + /* none specified, we'll guess from pixmap formats */ + if (!cfbVisuals) + { + for (f = 0; f < screenInfo.numPixmapFormats; f++) + { + d = screenInfo.formats[f].depth; + b = screenInfo.formats[f].bitsPerPixel; + if (sizes & (1 << (b - 1))) + { + if (d > MAX_PSEUDO_DEPTH) + vtype = LARGE_VISUALS; + else if (d == 1) + vtype = StaticGrayMask; + else + vtype = ALL_VISUALS; + } + else + vtype = 0; + if (!cfbSetVisualTypes (d, vtype, bitsPerRGB)) + return FALSE; + } + } + nvisual = 0; + ndepth = 0; + for (visuals = cfbVisuals; visuals; visuals = nextVisuals) + { + nextVisuals = visuals->next; + ndepth++; + nvisual += visuals->count; + } + depth = (DepthPtr) xalloc (ndepth * sizeof (DepthRec)); + visual = (VisualPtr) xalloc (nvisual * sizeof (VisualRec)); + if (!depth || !visual) + { + xfree (depth); + xfree (visual); + return FALSE; + } + *depthp = depth; + *visualp = visual; + *ndepthp = ndepth; + *nvisualp = nvisual; + for (visuals = cfbVisuals; visuals; visuals = nextVisuals) + { + nextVisuals = visuals->next; + d = visuals->depth; + vtype = visuals->visuals; + nvtype = visuals->count; + vid = NULL; + if (nvtype) + { + vid = (VisualID *) xalloc (nvtype * sizeof (VisualID)); + if (!vid) + return FALSE; + } + depth->depth = d; + depth->numVids = nvtype; + depth->vids = vid; + depth++; + for (i = 0; i < NUM_PRIORITY; i++) { + if (! (vtype & (1 << cfbVisualPriority[i]))) + continue; + visual->class = cfbVisualPriority[i]; + visual->bitsPerRGBValue = visuals->bitsPerRGB; + visual->ColormapEntries = 1 << d; + visual->nplanes = d; + visual->vid = *vid = FakeClientID (0); + switch (visual->class) { + case PseudoColor: + case GrayScale: + case StaticGray: + visual->redMask = 0; + visual->greenMask = 0; + visual->blueMask = 0; + visual->offsetRed = 0; + visual->offsetGreen = 0; + visual->offsetBlue = 0; + break; + case DirectColor: + case TrueColor: + visual->ColormapEntries = _CE(d); + /* fall through */ + case StaticColor: + visual->redMask = _RM(d); + visual->greenMask = _GM(d); + visual->blueMask = _BM(d); + visual->offsetRed = _RS(d); + visual->offsetGreen = _GS(d); + visual->offsetBlue = _BS(d); + } + vid++; + visual++; + } + xfree (visuals); + } + cfbVisuals = NULL; + visual = *visualp; + depth = *depthp; + for (i = 0; i < ndepth; i++) + { + if (*rootDepthp && *rootDepthp != depth[i].depth) + continue; + for (j = 0; j < depth[i].numVids; j++) + { + for (k = 0; k < nvisual; k++) + if (visual[k].vid == depth[i].vids[j]) + break; + if (k == nvisual) + continue; + if (defaultColorVisualClass < 0 || + visual[k].class == defaultColorVisualClass) + break; + } + if (j != depth[i].numVids) + break; + } + if (i == ndepth) { + i = 0; + j = 0; + } + *rootDepthp = depth[i].depth; + *defaultVisp = depth[i].vids[j]; + return TRUE; +} diff --git a/cfb/cfbfillarc.c b/cfb/cfbfillarc.c new file mode 100644 index 000000000..89d184983 --- /dev/null +++ b/cfb/cfbfillarc.c @@ -0,0 +1,265 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: cfbfillarc.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ + +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "mifillarc.h" +#include "cfbrrop.h" +#include "mi.h" + +/* gcc 1.35 is stupid */ +#if defined(__GNUC__) && defined(mc68020) +#define STUPID volatile +#else +#define STUPID +#endif + +static void +RROP_NAME(cfbFillEllipseSolid) (pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + STUPID int x, y, e; + STUPID int yk, xk, ym, xm, dx, dy, xorg, yorg; + miFillArcRec info; + unsigned long *addrlt, *addrlb; + register unsigned long *addrl; + register int n; + int nlwidth; + RROP_DECLARE + register int xpos; + register int slw; + unsigned long startmask, endmask; + int nlmiddle; + + cfbGetLongWidthAndPointer (pDraw, nlwidth, addrlt) + + RROP_FETCH_GC(pGC); + miFillArcSetup(arc, &info); + MIFILLARCSETUP(); + xorg += pDraw->x; + yorg += pDraw->y; + addrlb = addrlt; + addrlt += nlwidth * (yorg - y); + addrlb += nlwidth * (yorg + y + dy); + while (y) + { + addrlt += nlwidth; + addrlb -= nlwidth; + MIFILLARCSTEP(slw); + if (!slw) + continue; + xpos = xorg - x; + addrl = addrlt + (xpos >> PWSH); + if (((xpos & PIM) + slw) <= PPW) + { + maskpartialbits(xpos, slw, startmask); + RROP_SOLID_MASK(addrl,startmask); + if (miFillArcLower(slw)) + { + addrl = addrlb + (xpos >> PWSH); + RROP_SOLID_MASK(addrl, startmask); + } + continue; + } + maskbits(xpos, slw, startmask, endmask, nlmiddle); + if (startmask) + { + RROP_SOLID_MASK(addrl, startmask); + addrl++; + } + n = nlmiddle; + RROP_SPAN(addrl,n) + + if (endmask) + RROP_SOLID_MASK(addrl, endmask); + if (!miFillArcLower(slw)) + continue; + addrl = addrlb + (xpos >> PWSH); + if (startmask) + { + RROP_SOLID_MASK(addrl, startmask); + addrl++; + } + n = nlmiddle; + RROP_SPAN(addrl, n); + if (endmask) + RROP_SOLID_MASK(addrl, endmask); + } +} + +#define FILLSPAN(xl,xr,addr) \ + if (xr >= xl) \ + { \ + n = xr - xl + 1; \ + addrl = addr + (xl >> PWSH); \ + if (((xl & PIM) + n) <= PPW) \ + { \ + maskpartialbits(xl, n, startmask); \ + RROP_SOLID_MASK(addrl, startmask); \ + } \ + else \ + { \ + maskbits(xl, n, startmask, endmask, n); \ + if (startmask) \ + { \ + RROP_SOLID_MASK(addrl, startmask); \ + addrl++; \ + } \ + while (n--) \ + { \ + RROP_SOLID(addrl); \ + ++addrl; \ + } \ + if (endmask) \ + RROP_SOLID_MASK(addrl, endmask); \ + } \ + } + +#define FILLSLICESPANS(flip,addr) \ + if (!flip) \ + { \ + FILLSPAN(xl, xr, addr); \ + } \ + else \ + { \ + xc = xorg - x; \ + FILLSPAN(xc, xr, addr); \ + xc += slw - 1; \ + FILLSPAN(xl, xc, addr); \ + } + +static void +RROP_NAME(cfbFillArcSliceSolid)(pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; + register int x, y, e; + miFillArcRec info; + miArcSliceRec slice; + int xl, xr, xc; + unsigned long *addrlt, *addrlb; + register unsigned long *addrl; + register int n; + int nlwidth; + RROP_DECLARE + unsigned long startmask, endmask; + + cfbGetLongWidthAndPointer (pDraw, nlwidth, addrlt) + + RROP_FETCH_GC(pGC); + miFillArcSetup(arc, &info); + miFillArcSliceSetup(arc, &slice, pGC); + MIFILLARCSETUP(); + xorg += pDraw->x; + yorg += pDraw->y; + addrlb = addrlt; + addrlt += nlwidth * (yorg - y); + addrlb += nlwidth * (yorg + y + dy); + slice.edge1.x += pDraw->x; + slice.edge2.x += pDraw->x; + while (y > 0) + { + addrlt += nlwidth; + addrlb -= nlwidth; + MIFILLARCSTEP(slw); + MIARCSLICESTEP(slice.edge1); + MIARCSLICESTEP(slice.edge2); + if (miFillSliceUpper(slice)) + { + MIARCSLICEUPPER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_top, addrlt); + } + if (miFillSliceLower(slice)) + { + MIARCSLICELOWER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_bot, addrlb); + } + } +} + +void +RROP_NAME(cfbPolyFillArcSolid) (pDraw, pGC, narcs, parcs) + DrawablePtr pDraw; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + register xArc *arc; + register int i; + int x2, y2; + BoxRec box; + RegionPtr cclip; + + cclip = cfbGetCompositeClip(pGC); + for (arc = parcs, i = narcs; --i >= 0; arc++) + { + if (miFillArcEmpty(arc)) + continue; + if (miCanFillArc(arc)) + { + box.x1 = arc->x + pDraw->x; + box.y1 = arc->y + pDraw->y; + /* + * Because box.x2 and box.y2 get truncated to 16 bits, and the + * RECT_IN_REGION test treats the resulting number as a signed + * integer, the RECT_IN_REGION test alone can go the wrong way. + * This can result in a server crash because the rendering + * routines in this file deal directly with cpu addresses + * of pixels to be stored, and do not clip or otherwise check + * that all such addresses are within their respective pixmaps. + * So we only allow the RECT_IN_REGION test to be used for + * values that can be expressed correctly in a signed short. + */ + x2 = box.x1 + (int)arc->width + 1; + box.x2 = x2; + y2 = box.y1 + (int)arc->height + 1; + box.y2 = y2; + if ( (x2 <= MAXSHORT) && (y2 <= MAXSHORT) && + (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) ) + { + if ((arc->angle2 >= FULLCIRCLE) || + (arc->angle2 <= -FULLCIRCLE)) + RROP_NAME(cfbFillEllipseSolid)(pDraw, pGC, arc); + else + RROP_NAME(cfbFillArcSliceSolid)(pDraw, pGC, arc); + continue; + } + } + miPolyFillArc(pDraw, pGC, 1, arc); + } +} diff --git a/cfb/cfbfillrct.c b/cfb/cfbfillrct.c new file mode 100644 index 000000000..a0b72e7c4 --- /dev/null +++ b/cfb/cfbfillrct.c @@ -0,0 +1,286 @@ +/* + * Fill rectangles. + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/* $Xorg: cfbfillrct.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "gcstruct.h" +#include "window.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "windowstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "mergerop.h" + + +void +cfbFillBoxTileOdd (pDrawable, n, rects, tile, xrot, yrot) + DrawablePtr pDrawable; + int n; + BoxPtr rects; + PixmapPtr tile; + int xrot, yrot; +{ + if (tile->drawable.width & PIM) + cfbFillBoxTileOddCopy (pDrawable, n, rects, tile, xrot, yrot, GXcopy, ~0L); + else + cfbFillBoxTile32sCopy (pDrawable, n, rects, tile, xrot, yrot, GXcopy, ~0L); +} + +void +cfbFillRectTileOdd (pDrawable, pGC, nBox, pBox) + DrawablePtr pDrawable; + GCPtr pGC; + int nBox; + BoxPtr pBox; +{ + int xrot, yrot; + void (*fill)(); + + xrot = pDrawable->x + pGC->patOrg.x; + yrot = pDrawable->y + pGC->patOrg.y; + if (pGC->tile.pixmap->drawable.width & PIM) + { + fill = cfbFillBoxTileOddGeneral; + if ((pGC->planemask & PMSK) == PMSK) + { + if (pGC->alu == GXcopy) + fill = cfbFillBoxTileOddCopy; + } + } + else + { + fill = cfbFillBoxTile32sGeneral; + if ((pGC->planemask & PMSK) == PMSK) + { + if (pGC->alu == GXcopy) + fill = cfbFillBoxTile32sCopy; + } + } + (*fill) (pDrawable, nBox, pBox, pGC->tile.pixmap, xrot, yrot, pGC->alu, pGC->planemask); +} + +#define NUM_STACK_RECTS 1024 + +void +cfbPolyFillRect(pDrawable, pGC, nrectFill, prectInit) + DrawablePtr pDrawable; + register GCPtr pGC; + int nrectFill; /* number of rectangles to fill */ + xRectangle *prectInit; /* Pointer to first rectangle to fill */ +{ + xRectangle *prect; + RegionPtr prgnClip; + register BoxPtr pbox; + register BoxPtr pboxClipped; + BoxPtr pboxClippedBase; + BoxPtr pextent; + BoxRec stackRects[NUM_STACK_RECTS]; + cfbPrivGC *priv; + int numRects; + void (*BoxFill)(); + int n; + int xorg, yorg; + + priv = cfbGetGCPrivate(pGC); + prgnClip = priv->pCompositeClip; + + BoxFill = 0; + switch (pGC->fillStyle) + { + case FillSolid: + switch (priv->rop) { + case GXcopy: + BoxFill = cfbFillRectSolidCopy; + break; + case GXxor: + BoxFill = cfbFillRectSolidXor; + break; + default: + BoxFill = cfbFillRectSolidGeneral; + break; + } + break; + case FillTiled: + if (!cfbGetGCPrivate(pGC)->pRotatedPixmap) + BoxFill = cfbFillRectTileOdd; + else + { + if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK) + BoxFill = cfbFillRectTile32Copy; + else + BoxFill = cfbFillRectTile32General; + } + break; +#if PSZ == 8 + case FillStippled: + if (!cfbGetGCPrivate(pGC)->pRotatedPixmap) + BoxFill = cfb8FillRectStippledUnnatural; + else + BoxFill = cfb8FillRectTransparentStippled32; + break; + case FillOpaqueStippled: + if (!cfbGetGCPrivate(pGC)->pRotatedPixmap) + BoxFill = cfb8FillRectStippledUnnatural; + else + BoxFill = cfb8FillRectOpaqueStippled32; + break; +#endif + } + prect = prectInit; + xorg = pDrawable->x; + yorg = pDrawable->y; + if (xorg || yorg) + { + prect = prectInit; + n = nrectFill; + while(n--) + { + prect->x += xorg; + prect->y += yorg; + prect++; + } + } + + prect = prectInit; + + numRects = REGION_NUM_RECTS(prgnClip) * nrectFill; + if (numRects > NUM_STACK_RECTS) + { + pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec)); + if (!pboxClippedBase) + return; + } + else + pboxClippedBase = stackRects; + + pboxClipped = pboxClippedBase; + + if (REGION_NUM_RECTS(prgnClip) == 1) + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_RECTS(prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + if ((pboxClipped->x1 = prect->x) < x1) + pboxClipped->x1 = x1; + + if ((pboxClipped->y1 = prect->y) < y1) + pboxClipped->y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + pboxClipped->x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + pboxClipped->y2 = by2; + + prect++; + if ((pboxClipped->x1 < pboxClipped->x2) && + (pboxClipped->y1 < pboxClipped->y2)) + { + pboxClipped++; + } + } + } + else + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + BoxRec box; + + if ((box.x1 = prect->x) < x1) + box.x1 = x1; + + if ((box.y1 = prect->y) < y1) + box.y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + box.x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + box.y2 = by2; + + prect++; + + if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) + continue; + + n = REGION_NUM_RECTS (prgnClip); + pbox = REGION_RECTS(prgnClip); + + /* clip the rectangle to each box in the clip region + this is logically equivalent to calling Intersect() + */ + while(n--) + { + pboxClipped->x1 = max(box.x1, pbox->x1); + pboxClipped->y1 = max(box.y1, pbox->y1); + pboxClipped->x2 = min(box.x2, pbox->x2); + pboxClipped->y2 = min(box.y2, pbox->y2); + pbox++; + + /* see if clipping left anything */ + if(pboxClipped->x1 < pboxClipped->x2 && + pboxClipped->y1 < pboxClipped->y2) + { + pboxClipped++; + } + } + } + } + if (pboxClipped != pboxClippedBase) + (*BoxFill) (pDrawable, pGC, + pboxClipped-pboxClippedBase, pboxClippedBase); + if (pboxClippedBase != stackRects) + DEALLOCATE_LOCAL(pboxClippedBase); +} diff --git a/cfb/cfbfillsp.c b/cfb/cfbfillsp.c new file mode 100644 index 000000000..b0de9bd7d --- /dev/null +++ b/cfb/cfbfillsp.c @@ -0,0 +1,960 @@ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ + +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: cfbfillsp.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "gcstruct.h" +#include "window.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "windowstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" + +#include "mergerop.h" + +#if PSZ == 8 +#include "cfb8bit.h" +#endif + +#define MFB_CONSTS_ONLY +#include "maskbits.h" + +#include "mi.h" +#include "mispans.h" + +/* scanline filling for color frame buffer + written by drewry, oct 1986 modified by smarks + changes for compatibility with Little-endian systems Jul 1987; MIT:yba. + + these routines all clip. they assume that anything that has called +them has already translated the points (i.e. pGC->miTranslate is +non-zero, which is howit gets set in cfbCreateGC().) + + the number of new scnalines created by clipping == +MaxRectsPerBand * nSpans. + + FillSolid is overloaded to be used for OpaqueStipple as well, +if fgPixel == bgPixel. +Note that for solids, PrivGC.rop == PrivGC.ropOpStip + + + FillTiled is overloaded to be used for OpaqueStipple, if +fgPixel != bgPixel. based on the fill style, it uses +{RotatedTile, gc.alu} or {RotatedStipple, PrivGC.ropOpStip} +*/ + +#ifdef notdef +#include +static +dumpspans(n, ppt, pwidth) + int n; + DDXPointPtr ppt; + int *pwidth; +{ + fprintf(stderr,"%d spans\n", n); + while (n--) { + fprintf(stderr, "[%d,%d] %d\n", ppt->x, ppt->y, *pwidth); + ppt++; + pwidth++; + } + fprintf(stderr, "\n"); +} +#endif + +/* Fill spans with tiles that aren't 32 bits wide */ +void +cfbUnnaturalTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) +DrawablePtr pDrawable; +GC *pGC; +int nInit; /* number of spans to fill */ +DDXPointPtr pptInit; /* pointer to list of start points */ +int *pwidthInit; /* pointer to list of n widths */ +int fSorted; +{ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + void (*fill)(); + int xrot, yrot; + + if (!(pGC->planemask)) + return; + + if (pGC->tile.pixmap->drawable.width & PIM) + { + fill = cfbFillSpanTileOddGeneral; + if ((pGC->planemask & PMSK) == PMSK) + { + if (pGC->alu == GXcopy) + fill = cfbFillSpanTileOddCopy; + } + } + else + { + fill = cfbFillSpanTile32sGeneral; + if ((pGC->planemask & PMSK) == PMSK) + { + if (pGC->alu == GXcopy) + fill = cfbFillSpanTile32sCopy; + } + } + n = nInit * miFindMaxBand( cfbGetCompositeClip(pGC) ); + if ( n == 0 ) + return; + pwidth = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + ppt = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!ppt || !pwidth) + { + if (ppt) DEALLOCATE_LOCAL(ppt); + if (pwidth) DEALLOCATE_LOCAL(pwidth); + return; + } + n = miClipSpans( cfbGetCompositeClip(pGC), + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + xrot = pDrawable->x + pGC->patOrg.x; + yrot = pDrawable->y + pGC->patOrg.y; + + (*fill) (pDrawable, n, ppt, pwidth, pGC->tile.pixmap, xrot, yrot, pGC->alu, pGC->planemask); + + DEALLOCATE_LOCAL(ppt); + DEALLOCATE_LOCAL(pwidth); +} + +#if PSZ == 8 + +void +cfbUnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) +DrawablePtr pDrawable; +GC *pGC; +int nInit; /* number of spans to fill */ +DDXPointPtr pptInit; /* pointer to list of start points */ +int *pwidthInit; /* pointer to list of n widths */ +int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + DDXPointPtr ppt; /* pointer to list of start points */ + int *pwidth; /* pointer to list of n widths */ + int *pwidthFree;/* copies of the pointers to free */ + DDXPointPtr pptFree; + unsigned long *pdstBase; /* pointer to start of bitmap */ + int nlwDst; /* width in longwords of bitmap */ + register unsigned long *pdst; /* pointer to current word in bitmap */ + PixmapPtr pStipple; /* pointer to stipple we want to fill with */ + int nlw; + int x, y, w, xrem, xSrc, ySrc; + int stwidth, stippleWidth; + int stippleHeight; + register unsigned long bits, inputBits; + register int partBitsLeft; + int nextPartBits; + int bitsLeft, bitsWhole; + unsigned long *srcTemp, *srcStart; + unsigned long *psrcBase; + unsigned long startmask, endmask; + + if (pGC->fillStyle == FillStippled) + cfb8CheckStipple (pGC->alu, pGC->fgPixel, pGC->planemask); + else + cfb8CheckOpaqueStipple (pGC->alu, pGC->fgPixel, pGC->bgPixel, pGC->planemask); + + if (cfb8StippleRRop == GXnoop) + return; + + n = nInit * miFindMaxBand( cfbGetCompositeClip(pGC) ); + if ( n == 0 ) + return; + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans( cfbGetCompositeClip(pGC), + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + /* + * OK, so what's going on here? We have two Drawables: + * + * The Stipple: + * Depth = 1 + * Width = stippleWidth + * Words per scanline = stwidth + * Pointer to pixels = pStipple->devPrivate.ptr + */ + + pStipple = pGC->stipple; + + stwidth = pStipple->devKind >> PWSH; + stippleWidth = pStipple->drawable.width; + stippleHeight = pStipple->drawable.height; + psrcBase = (unsigned long *) pStipple->devPrivate.ptr; + + /* + * The Target: + * Depth = PSZ + * Width = determined from *pwidth + * Words per scanline = nlwDst + * Pointer to pixels = addrlBase + */ + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pdstBase) + + /* this replaces rotating the stipple. Instead we just adjust the offset + * at which we start grabbing bits from the stipple. + * Ensure that ppt->x - xSrc >= 0 and ppt->y - ySrc >= 0, + * so that iline and xrem always stay within the stipple bounds. + */ + + modulus (pGC->patOrg.x, stippleWidth, xSrc); + xSrc += pDrawable->x - stippleWidth; + modulus (pGC->patOrg.y, stippleHeight, ySrc); + ySrc += pDrawable->y - stippleHeight; + + bitsWhole = stippleWidth; + + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + w = *pwidth++; + pdst = pdstBase + y * nlwDst + (x >> PWSH); + y = (y - ySrc) % stippleHeight; + srcStart = psrcBase + y * stwidth; + xrem = ((x & ~(PGSZB-1)) - xSrc) % stippleWidth; + srcTemp = srcStart + (xrem >> MFB_PWSH); + bitsLeft = stippleWidth - (xrem & ~MFB_PIM); + xrem &= MFB_PIM; + NextUnnaturalStippleWord + if (partBitsLeft < xrem) + FatalError ("cfbUnnaturalStippleFS bad partBitsLeft %d xrem %d", + partBitsLeft, xrem); + NextSomeBits (inputBits, xrem); + partBitsLeft -= xrem; + if (((x & PIM) + w) <= PPW) + { + maskpartialbits (x, w, startmask) + NextUnnaturalStippleBits + *pdst = MaskRRopPixels(*pdst,bits,startmask); + } + else + { + maskbits (x, w, startmask, endmask, nlw); + nextPartBits = (x & (PGSZB-1)) + w; + if (nextPartBits < partBitsLeft) + { + if (startmask) + { + MaskRRopBitGroup(pdst,GetBitGroup(inputBits),startmask) + pdst++; + NextBitGroup (inputBits); + } + while (nlw--) + { + RRopBitGroup (pdst, GetBitGroup (inputBits)); + pdst++; + NextBitGroup (inputBits); + } + if (endmask) + { + MaskRRopBitGroup(pdst,GetBitGroup(inputBits),endmask) + } + } + else if (bitsLeft != bitsWhole && nextPartBits < partBitsLeft + bitsLeft) + { + NextUnnaturalStippleBitsFast + if (startmask) + { + *pdst = MaskRRopPixels(*pdst,bits,startmask); + pdst++; + NextUnnaturalStippleBitsFast + } + while (nlw--) + { + *pdst = RRopPixels(*pdst,bits); + pdst++; + NextUnnaturalStippleBitsFast + } + if (endmask) + *pdst = MaskRRopPixels (*pdst,bits,endmask); + } + else + { + NextUnnaturalStippleBits + if (startmask) + { + *pdst = MaskRRopPixels(*pdst,bits,startmask); + pdst++; + NextUnnaturalStippleBits + } + while (nlw--) + { + *pdst = RRopPixels(*pdst,bits); + pdst++; + NextUnnaturalStippleBits + } + if (endmask) + *pdst = MaskRRopPixels(*pdst,bits,endmask); + } + } + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + +#else /* PSZ != 8 */ + +/* Fill spans with stipples that aren't 32 bits wide */ +void +cfbUnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) +DrawablePtr pDrawable; +GC *pGC; +int nInit; /* number of spans to fill */ +DDXPointPtr pptInit; /* pointer to list of start points */ +int *pwidthInit; /* pointer to list of n widths */ +int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + int iline; /* first line of tile to use */ + unsigned long *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register unsigned long *pdst; /* pointer to current word in bitmap */ + PixmapPtr pStipple; /* pointer to stipple we want to fill with */ + register int w; + int width, x, xrem, xSrc, ySrc; + unsigned long tmpSrc, tmpDst1, tmpDst2; + int stwidth, stippleWidth; + unsigned long *psrcS; + int rop, stiprop; + int stippleHeight; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + unsigned long fgfill, bgfill; + + if (!(pGC->planemask)) + return; + + n = nInit * miFindMaxBand( cfbGetCompositeClip(pGC) ); + if ( n == 0 ) + return; + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans( cfbGetCompositeClip(pGC), + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + rop = pGC->alu; + if (pGC->fillStyle == FillStippled) { + switch (rop) { + case GXand: + case GXcopy: + case GXnoop: + case GXor: + stiprop = rop; + break; + default: + stiprop = rop; + rop = GXcopy; + } + } + fgfill = PFILL(pGC->fgPixel); + bgfill = PFILL(pGC->bgPixel); + + /* + * OK, so what's going on here? We have two Drawables: + * + * The Stipple: + * Depth = 1 + * Width = stippleWidth + * Words per scanline = stwidth + * Pointer to pixels = pStipple->devPrivate.ptr + */ + pStipple = pGC->stipple; + + stwidth = pStipple->devKind / PGSZB; + stippleWidth = pStipple->drawable.width; + stippleHeight = pStipple->drawable.height; + + /* + * The Target: + * Depth = PSZ + * Width = determined from *pwidth + * Words per scanline = nlwidth + * Pointer to pixels = addrlBase + */ + + cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrlBase) + + /* this replaces rotating the stipple. Instead we just adjust the offset + * at which we start grabbing bits from the stipple. + * Ensure that ppt->x - xSrc >= 0 and ppt->y - ySrc >= 0, + * so that iline and xrem always stay within the stipple bounds. + */ + modulus (pGC->patOrg.x, stippleWidth, xSrc); + xSrc += pDrawable->x - stippleWidth; + modulus (pGC->patOrg.y, stippleHeight, ySrc); + ySrc += pDrawable->y - stippleHeight; + + while (n--) + { + iline = (ppt->y - ySrc) % stippleHeight; + x = ppt->x; + pdst = addrlBase + (ppt->y * nlwidth); + psrcS = (unsigned long *) pStipple->devPrivate.ptr + (iline * stwidth); + + if (*pwidth) + { + width = *pwidth; + while(width > 0) + { + int xtemp, tmpx; + register unsigned long *ptemp; + register unsigned long *pdsttmp; + /* + * Do a stripe through the stipple & destination w pixels + * wide. w is not more than: + * - the width of the destination + * - the width of the stipple + * - the distance between x and the next word + * boundary in the destination + * - the distance between x and the next word + * boundary in the stipple + */ + + /* width of dest/stipple */ + xrem = (x - xSrc) % stippleWidth; + w = min((stippleWidth - xrem), width); + /* dist to word bound in dest */ + w = min(w, PPW - (x & PIM)); + /* dist to word bound in stip */ + w = min(w, MFB_PPW - (x & MFB_PIM)); + + xtemp = (xrem & MFB_PIM); + ptemp = (unsigned long *)(psrcS + (xrem >> MFB_PWSH)); + tmpx = x & PIM; + pdsttmp = pdst + (x>>PWSH); + switch ( pGC->fillStyle ) { + case FillOpaqueStippled: + getstipplepixels(ptemp, xtemp, w, 0, &bgfill, &tmpDst1); + getstipplepixels(ptemp, xtemp, w, 1, &fgfill, &tmpDst2); + break; + case FillStippled: + /* Fill tmpSrc with the source pixels */ + getbits(pdsttmp, tmpx, w, tmpSrc); + getstipplepixels(ptemp, xtemp, w, 0, &tmpSrc, &tmpDst1); + if (rop != stiprop) { + putbitsrop(fgfill, 0, w, &tmpSrc, pGC->planemask, stiprop); + } else { + tmpSrc = fgfill; + } + getstipplepixels(ptemp, xtemp, w, 1, &tmpSrc, &tmpDst2); + break; + } + tmpDst2 |= tmpDst1; + putbitsrop(tmpDst2, tmpx, w, pdsttmp, pGC->planemask, rop); + x += w; + width -= w; + } + } + ppt++; + pwidth++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + +#endif /* PSZ == 8 */ + +#if PSZ == 8 + +void +cfb8Stipple32FS (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + DDXPointPtr ppt; /* pointer to list of start points */ + int *pwidth; /* pointer to list of n widths */ + unsigned long *src; /* pointer to bits in stipple, if needed */ + int stippleHeight; /* height of the stipple */ + PixmapPtr stipple; + + int nlwDst; /* width in longwords of the dest pixmap */ + int x,y,w; /* current span */ + unsigned long startmask; + unsigned long endmask; + register unsigned long *dst; /* pointer to bits we're writing */ + register int nlw; + unsigned long *dstTmp; + int nlwTmp; + + unsigned long *pbits; /* pointer to start of pixmap */ + register unsigned long xor; + register unsigned long mask; + register unsigned long bits; /* bits from stipple */ + int wEnd; + + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + cfbPrivGCPtr devPriv; + + devPriv = cfbGetGCPrivate(pGC); + cfb8CheckStipple (pGC->alu, pGC->fgPixel, pGC->planemask); + n = nInit * miFindMaxBand(devPriv->pCompositeClip); + if ( n == 0 ) + return; + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(devPriv->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + stipple = devPriv->pRotatedPixmap; + src = (unsigned long *)stipple->devPrivate.ptr; + stippleHeight = stipple->drawable.height; + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pbits) + + while (n--) + { + w = *pwidth++; + x = ppt->x; + y = ppt->y; + ppt++; + dst = pbits + (y * nlwDst) + (x >> PWSH); + if (((x & PIM) + w) <= PPW) + { + maskpartialbits(x, w, startmask); + endmask = 0; + nlw = 0; + } + else + { + maskbits (x, w, startmask, endmask, nlw); + } + bits = src[y % stippleHeight]; + RotBitsLeft (bits, (x & ((PGSZ-1) & ~PIM))); + if (cfb8StippleRRop == GXcopy) + { + xor = devPriv->xor; + if (w < (PGSZ*2)) + { + if (startmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + *dst = (*dst & ~(mask & startmask)) | + (xor & (mask & startmask)); + dst++; + RotBitsLeft (bits, PGSZB); + } + while (nlw--) + { + WriteBitGroup (dst,xor,GetBitGroup(bits)) + dst++; + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + *dst = (*dst & ~(mask & endmask)) | + (xor & (mask & endmask)); + } + } + else + { /* XXX constants probably not OK here */ + wEnd = 7 - (nlw & 7); + nlw = (nlw >> 3) + 1; + dstTmp = dst; + nlwTmp = nlw; + if (startmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + *dstTmp = (*dstTmp & ~(mask & startmask)) | + (xor & (mask & startmask)); + dstTmp++; + RotBitsLeft (bits, PGSZB); + } + w = 7 - wEnd; + while (w--) + { + dst = dstTmp; + dstTmp++; + nlw = nlwTmp; +#if defined(__GNUC__) && defined(mc68020) + mask = cfb8PixelMasks[GetBitGroup(bits)]; + xor = xor & mask; + mask = ~mask; + while (nlw--) + { + *dst = (*dst & mask) | xor; + dst += 8; + } + xor = devPriv->xor; +#else +#define SwitchBitsLoop(body) \ + while (nlw--) \ + { \ + body \ + dst += 8; \ + } + SwitchBitGroup(dst, xor, GetBitGroup(bits)); +#undef SwitchBitsLoop +#endif + NextBitGroup (bits); + } + nlwTmp--; + w = wEnd + 1; + if (endmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + dst = dstTmp + (nlwTmp << 3); + *dst = (*dst & ~(mask & endmask)) | + (xor & (mask & endmask)); + } + while (w--) + { + nlw = nlwTmp; + dst = dstTmp; + dstTmp++; +#if defined(__GNUC__) && defined(mc68020) + mask = cfb8PixelMasks[GetBitGroup(bits)]; + xor = xor & mask; + mask = ~mask; + while (nlw--) + { + *dst = (*dst & mask) | xor; + dst += 8; + } + xor = devPriv->xor; +#else +#define SwitchBitsLoop(body) \ + while (nlw--) \ + { \ + body \ + dst += 8; \ + } + SwitchBitGroup(dst, xor, GetBitGroup(bits)); +#undef SwitchBitsLoop +#endif + NextBitGroup (bits); + } + } + } + else + { + if (startmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, startmask); + dst++; + RotBitsLeft (bits, PGSZB); + } + while (nlw--) + { + RRopBitGroup(dst, GetBitGroup(bits)); + dst++; + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, endmask); + } + } + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + +void +cfb8OpaqueStipple32FS (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + DDXPointPtr ppt; /* pointer to list of start points */ + int *pwidth; /* pointer to list of n widths */ + unsigned long *src; /* pointer to bits in stipple, if needed */ + int stippleHeight; /* height of the stipple */ + PixmapPtr stipple; + + int nlwDst; /* width in longwords of the dest pixmap */ + int x,y,w; /* current span */ + unsigned long startmask; + unsigned long endmask; + register unsigned long *dst; /* pointer to bits we're writing */ + register int nlw; + unsigned long *dstTmp; + int nlwTmp; + + unsigned long *pbits; /* pointer to start of pixmap */ + register unsigned long xor; + register unsigned long mask; + register unsigned long bits; /* bits from stipple */ + int wEnd; + + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + cfbPrivGCPtr devPriv; + + devPriv = cfbGetGCPrivate(pGC); + + cfb8CheckOpaqueStipple(pGC->alu, pGC->fgPixel, pGC->bgPixel, pGC->planemask); + + n = nInit * miFindMaxBand(devPriv->pCompositeClip); + if ( n == 0 ) + return; + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(devPriv->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + stipple = devPriv->pRotatedPixmap; + src = (unsigned long *)stipple->devPrivate.ptr; + stippleHeight = stipple->drawable.height; + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pbits) + + while (n--) + { + w = *pwidth++; + x = ppt->x; + y = ppt->y; + ppt++; + dst = pbits + (y * nlwDst) + (x >> PWSH); + if (((x & PIM) + w) <= PPW) + { + maskpartialbits(x, w, startmask); + endmask = 0; + nlw = 0; + } + else + { + maskbits (x, w, startmask, endmask, nlw); + } + bits = src[y % stippleHeight]; + RotBitsLeft (bits, (x & ((PGSZ-1) & ~PIM))); + if (cfb8StippleRRop == GXcopy) + { + xor = devPriv->xor; + if (w < PGSZ*2) + { + if (startmask) + { + *dst = *dst & ~startmask | + GetPixelGroup (bits) & startmask; + dst++; + RotBitsLeft (bits, PGSZB); + } + while (nlw--) + { + *dst++ = GetPixelGroup(bits); + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + *dst = *dst & ~endmask | + GetPixelGroup (bits) & endmask; + } + } + else + { /* XXX consts probably not OK here */ + wEnd = 7 - (nlw & 7); + nlw = (nlw >> 3) + 1; + dstTmp = dst; + nlwTmp = nlw; + if (startmask) + { + *dstTmp = *dstTmp & ~startmask | + GetPixelGroup (bits) & startmask; + dstTmp++; + RotBitsLeft (bits, PGSZB); + } + w = 7 - wEnd; + while (w--) + { + nlw = nlwTmp; + dst = dstTmp; + dstTmp++; + xor = GetPixelGroup (bits); + while (nlw--) + { + *dst = xor; + dst += 8; + } + NextBitGroup (bits); + } + nlwTmp--; + w = wEnd + 1; + if (endmask) + { + dst = dstTmp + (nlwTmp << 3); + *dst = (*dst & ~endmask) | + GetPixelGroup (bits) & endmask; + } + while (w--) + { + nlw = nlwTmp; + dst = dstTmp; + dstTmp++; + xor = GetPixelGroup (bits); + while (nlw--) + { + *dst = xor; + dst += 8; + } + NextBitGroup (bits); + } + } + } + else + { + if (startmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, startmask); + dst++; + RotBitsLeft (bits, PGSZB); + } + while (nlw--) + { + RRopBitGroup(dst, GetBitGroup(bits)); + dst++; + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, endmask); + } + } + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + +#endif /* PSZ == 8 */ diff --git a/cfb/cfbgc.c b/cfb/cfbgc.c new file mode 100644 index 000000000..62e0cbd76 --- /dev/null +++ b/cfb/cfbgc.c @@ -0,0 +1,791 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: cfbgc.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "cfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "region.h" + +#include "mistruct.h" +#include "mibstore.h" +#include "migc.h" + +#include "cfbmskbits.h" +#include "cfb8bit.h" + +#if PSZ == 8 +# define useTEGlyphBlt cfbTEGlyphBlt8 +#else +# ifdef WriteBitGroup +# define useTEGlyphBlt cfbImageGlyphBlt8 +# else +# define useTEGlyphBlt cfbTEGlyphBlt +# endif +#endif + +#ifdef WriteBitGroup +# define useImageGlyphBlt cfbImageGlyphBlt8 +# define usePolyGlyphBlt cfbPolyGlyphBlt8 +#else +# define useImageGlyphBlt miImageGlyphBlt +# define usePolyGlyphBlt miPolyGlyphBlt +#endif + +#ifdef FOUR_BIT_CODE +# define usePushPixels cfbPushPixels8 +#else +#ifndef LOWMEMFTPT +# define usePushPixels mfbPushPixels +#else +# define usePushPixels miPushPixels +#endif /* ifndef LOWMEMFTPT */ +#endif + +#ifdef PIXEL_ADDR +# define ZeroPolyArc cfbZeroPolyArcSS8Copy +#else +# define ZeroPolyArc miZeroPolyArc +#endif + +GCFuncs cfbGCFuncs = { + cfbValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip, +}; + +GCOps cfbTEOps1Rect = { + cfbSolidSpansCopy, + cfbSetSpans, + cfbPutImage, + cfbCopyArea, + cfbCopyPlane, + cfbPolyPoint, +#ifdef PIXEL_ADDR + cfb8LineSS1Rect, + cfb8SegmentSS1Rect, +#else + cfbLineSS, + cfbSegmentSS, +#endif + miPolyRectangle, + ZeroPolyArc, + cfbFillPoly1RectCopy, + cfbPolyFillRect, + cfbPolyFillArcSolidCopy, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + useTEGlyphBlt, + usePolyGlyphBlt, + usePushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +GCOps cfbNonTEOps1Rect = { + cfbSolidSpansCopy, + cfbSetSpans, + cfbPutImage, + cfbCopyArea, + cfbCopyPlane, + cfbPolyPoint, +#ifdef PIXEL_ADDR + cfb8LineSS1Rect, + cfb8SegmentSS1Rect, +#else + cfbLineSS, + cfbSegmentSS, +#endif + miPolyRectangle, + ZeroPolyArc, + cfbFillPoly1RectCopy, + cfbPolyFillRect, + cfbPolyFillArcSolidCopy, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + useImageGlyphBlt, + usePolyGlyphBlt, + usePushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +GCOps cfbTEOps = { + cfbSolidSpansCopy, + cfbSetSpans, + cfbPutImage, + cfbCopyArea, + cfbCopyPlane, + cfbPolyPoint, + cfbLineSS, + cfbSegmentSS, + miPolyRectangle, + ZeroPolyArc, + miFillPolygon, + cfbPolyFillRect, + cfbPolyFillArcSolidCopy, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + useTEGlyphBlt, + usePolyGlyphBlt, + usePushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +GCOps cfbNonTEOps = { + cfbSolidSpansCopy, + cfbSetSpans, + cfbPutImage, + cfbCopyArea, + cfbCopyPlane, + cfbPolyPoint, + cfbLineSS, + cfbSegmentSS, + miPolyRectangle, +#ifdef PIXEL_ADDR + cfbZeroPolyArcSS8Copy, +#else + miZeroPolyArc, +#endif + miFillPolygon, + cfbPolyFillRect, + cfbPolyFillArcSolidCopy, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + useImageGlyphBlt, + usePolyGlyphBlt, + usePushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +GCOps * +cfbMatchCommon (pGC, devPriv) + GCPtr pGC; + cfbPrivGCPtr devPriv; +{ + if (pGC->lineWidth != 0) + return 0; + if (pGC->lineStyle != LineSolid) + return 0; + if (pGC->fillStyle != FillSolid) + return 0; + if (devPriv->rop != GXcopy) + return 0; + if (pGC->font && + FONTMAXBOUNDS(pGC->font,rightSideBearing) - + FONTMINBOUNDS(pGC->font,leftSideBearing) <= 32 && + FONTMINBOUNDS(pGC->font,characterWidth) >= 0) + { + if (TERMINALFONT(pGC->font) +#ifdef FOUR_BIT_CODE + && FONTMAXBOUNDS(pGC->font,characterWidth) >= PGSZB +#endif + ) +#ifdef NO_ONE_RECT + return &cfbTEOps1Rect; +#else + if (devPriv->oneRect) + return &cfbTEOps1Rect; + else + return &cfbTEOps; +#endif + else +#ifdef NO_ONE_RECT + return &cfbNonTEOps1Rect; +#else + if (devPriv->oneRect) + return &cfbNonTEOps1Rect; + else + return &cfbNonTEOps; +#endif + } + return 0; +} + +Bool +cfbCreateGC(pGC) + register GCPtr pGC; +{ + cfbPrivGC *pPriv; + + if (PixmapWidthPaddingInfo[pGC->depth].padPixelsLog2 == LOG2_BITMAP_PAD) + return (mfbCreateGC(pGC)); + pGC->clientClip = NULL; + pGC->clientClipType = CT_NONE; + + /* + * some of the output primitives aren't really necessary, since they + * will be filled in ValidateGC because of dix/CreateGC() setting all + * the change bits. Others are necessary because although they depend + * on being a color frame buffer, they don't change + */ + + pGC->ops = &cfbNonTEOps; + pGC->funcs = &cfbGCFuncs; + + /* cfb wants to translate before scan conversion */ + pGC->miTranslate = 1; + + pPriv = cfbGetGCPrivate(pGC); + pPriv->rop = pGC->alu; + pPriv->oneRect = FALSE; + pPriv->fExpose = TRUE; + pPriv->freeCompClip = FALSE; + pPriv->pRotatedPixmap = (PixmapPtr) NULL; + return TRUE; +} + +/* Clipping conventions + if the drawable is a window + CT_REGION ==> pCompositeClip really is the composite + CT_other ==> pCompositeClip is the window clip region + if the drawable is a pixmap + CT_REGION ==> pCompositeClip is the translated client region + clipped to the pixmap boundary + CT_other ==> pCompositeClip is the pixmap bounding box +*/ + +void +cfbValidateGC(pGC, changes, pDrawable) + register GCPtr pGC; + unsigned long changes; + DrawablePtr pDrawable; +{ + int mask; /* stateChanges */ + int index; /* used for stepping through bitfields */ + int new_rrop; + int new_line, new_text, new_fillspans, new_fillarea; + int new_rotate; + int xrot, yrot; + /* flags for changing the proc vector */ + cfbPrivGCPtr devPriv; + int oneRect; + + new_rotate = pGC->lastWinOrg.x != pDrawable->x || + pGC->lastWinOrg.y != pDrawable->y; + + pGC->lastWinOrg.x = pDrawable->x; + pGC->lastWinOrg.y = pDrawable->y; + devPriv = cfbGetGCPrivate(pGC); + + new_rrop = FALSE; + new_line = FALSE; + new_text = FALSE; + new_fillspans = FALSE; + new_fillarea = FALSE; + + /* + * if the client clip is different or moved OR the subwindowMode has + * changed OR the window's clip has changed since the last validation + * we need to recompute the composite clip + */ + + if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || + (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) + ) + { + miComputeCompositeClip (pGC, pDrawable); +#ifdef NO_ONE_RECT + devPriv->oneRect = FALSE; +#else + oneRect = REGION_NUM_RECTS(devPriv->pCompositeClip) == 1; + if (oneRect != devPriv->oneRect) + new_line = TRUE; + devPriv->oneRect = oneRect; +#endif + } + + mask = changes; + while (mask) { + index = lowbit (mask); + mask &= ~index; + + /* + * this switch acculmulates a list of which procedures might have + * to change due to changes in the GC. in some cases (e.g. + * changing one 16 bit tile for another) we might not really need + * a change, but the code is being paranoid. this sort of batching + * wins if, for example, the alu and the font have been changed, + * or any other pair of items that both change the same thing. + */ + switch (index) { + case GCFunction: + case GCForeground: + new_rrop = TRUE; + break; + case GCPlaneMask: + new_rrop = TRUE; + new_text = TRUE; + break; + case GCBackground: + break; + case GCLineStyle: + case GCLineWidth: + new_line = TRUE; + break; + case GCJoinStyle: + case GCCapStyle: + break; + case GCFillStyle: + new_text = TRUE; + new_fillspans = TRUE; + new_line = TRUE; + new_fillarea = TRUE; + break; + case GCFillRule: + break; + case GCTile: + new_fillspans = TRUE; + new_fillarea = TRUE; + break; + + case GCStipple: + if (pGC->stipple) + { + int width = pGC->stipple->drawable.width; + PixmapPtr nstipple; + + if ((width <= PGSZ) && !(width & (width - 1)) && + (nstipple = cfbCopyPixmap(pGC->stipple))) + { + cfbPadPixmap(nstipple); + (*pGC->pScreen->DestroyPixmap)(pGC->stipple); + pGC->stipple = nstipple; + } + } + new_fillspans = TRUE; + new_fillarea = TRUE; + break; + + case GCTileStipXOrigin: + new_rotate = TRUE; + break; + + case GCTileStipYOrigin: + new_rotate = TRUE; + break; + + case GCFont: + new_text = TRUE; + break; + case GCSubwindowMode: + break; + case GCGraphicsExposures: + break; + case GCClipXOrigin: + break; + case GCClipYOrigin: + break; + case GCClipMask: + break; + case GCDashOffset: + break; + case GCDashList: + break; + case GCArcMode: + break; + default: + break; + } + } + + /* + * If the drawable has changed, ensure suitable + * entries are in the proc vector. + */ + if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) { + new_fillspans = TRUE; /* deal with FillSpans later */ + } + + if (new_rotate || new_fillspans) + { + Bool new_pix = FALSE; + + xrot = pGC->patOrg.x + pDrawable->x; + yrot = pGC->patOrg.y + pDrawable->y; + + switch (pGC->fillStyle) + { + case FillTiled: + if (!pGC->tileIsPixel) + { + int width = pGC->tile.pixmap->drawable.width * PSZ; + + if ((width <= PGSZ) && !(width & (width - 1))) + { + cfbCopyRotatePixmap(pGC->tile.pixmap, + &devPriv->pRotatedPixmap, + xrot, yrot); + new_pix = TRUE; + } + } + break; +#ifdef FOUR_BIT_CODE + case FillStippled: + case FillOpaqueStippled: + { + int width = pGC->stipple->drawable.width; + + if ((width <= PGSZ) && !(width & (width - 1))) + { + mfbCopyRotatePixmap(pGC->stipple, + &devPriv->pRotatedPixmap, xrot, yrot); + new_pix = TRUE; + } + } + break; +#endif + } + if (!new_pix && devPriv->pRotatedPixmap) + { + (*pGC->pScreen->DestroyPixmap)(devPriv->pRotatedPixmap); + devPriv->pRotatedPixmap = (PixmapPtr) NULL; + } + } + + if (new_rrop) + { + int old_rrop; + + old_rrop = devPriv->rop; + devPriv->rop = cfbReduceRasterOp (pGC->alu, pGC->fgPixel, + pGC->planemask, + &devPriv->and, &devPriv->xor); + if (old_rrop == devPriv->rop) + new_rrop = FALSE; + else + { +#ifdef PIXEL_ADDR + new_line = TRUE; +#endif +#ifdef WriteBitGroup + new_text = TRUE; +#endif + new_fillspans = TRUE; + new_fillarea = TRUE; + } + } + + if (new_rrop || new_fillspans || new_text || new_fillarea || new_line) + { + GCOps *newops; + + if (newops = cfbMatchCommon (pGC, devPriv)) + { + if (pGC->ops->devPrivate.val) + miDestroyGCOps (pGC->ops); + pGC->ops = newops; + new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0; + } + else + { + if (!pGC->ops->devPrivate.val) + { + pGC->ops = miCreateGCOps (pGC->ops); + pGC->ops->devPrivate.val = 1; + } + } + } + + /* deal with the changes we've collected */ + if (new_line) + { + pGC->ops->FillPolygon = miFillPolygon; +#ifdef NO_ONE_RECT + if (pGC->fillStyle == FillSolid) + { + switch (devPriv->rop) { + case GXcopy: + pGC->ops->FillPolygon = cfbFillPoly1RectCopy; + break; + default: + pGC->ops->FillPolygon = cfbFillPoly1RectGeneral; + break; + } + } +#else + if (devPriv->oneRect && pGC->fillStyle == FillSolid) + { + switch (devPriv->rop) { + case GXcopy: + pGC->ops->FillPolygon = cfbFillPoly1RectCopy; + break; + default: + pGC->ops->FillPolygon = cfbFillPoly1RectGeneral; + break; + } + } +#endif + if (pGC->lineWidth == 0) + { +#ifdef PIXEL_ADDR + if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)) + { + switch (devPriv->rop) + { + case GXxor: + pGC->ops->PolyArc = cfbZeroPolyArcSS8Xor; + break; + case GXcopy: + pGC->ops->PolyArc = cfbZeroPolyArcSS8Copy; + break; + default: + pGC->ops->PolyArc = cfbZeroPolyArcSS8General; + break; + } + } + else +#endif + pGC->ops->PolyArc = miZeroPolyArc; + } + else + pGC->ops->PolyArc = miPolyArc; + pGC->ops->PolySegment = miPolySegment; + switch (pGC->lineStyle) + { + case LineSolid: + if(pGC->lineWidth == 0) + { + if (pGC->fillStyle == FillSolid) + { +#if defined(PIXEL_ADDR) && !defined(NO_ONE_RECT) + if (devPriv->oneRect && + ((pDrawable->x >= pGC->pScreen->width - 32768) && + (pDrawable->y >= pGC->pScreen->height - 32768))) + { + pGC->ops->Polylines = cfb8LineSS1Rect; + pGC->ops->PolySegment = cfb8SegmentSS1Rect; + } else +#endif +#ifdef NO_ONE_RECT + { + pGC->ops->Polylines = cfb8LineSS1Rect; + pGC->ops->PolySegment = cfb8SegmentSS1Rect; + } +#else + { + pGC->ops->Polylines = cfbLineSS; + pGC->ops->PolySegment = cfbSegmentSS; + } +#endif + } + else + pGC->ops->Polylines = miZeroLine; + } + else + pGC->ops->Polylines = miWideLine; + break; + case LineOnOffDash: + case LineDoubleDash: + if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) + { + pGC->ops->Polylines = cfbLineSD; + pGC->ops->PolySegment = cfbSegmentSD; + } else + pGC->ops->Polylines = miWideDash; + break; + } + } + + if (new_text && (pGC->font)) + { + if (FONTMAXBOUNDS(pGC->font,rightSideBearing) - + FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 || + FONTMINBOUNDS(pGC->font,characterWidth) < 0) + { + pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; + pGC->ops->ImageGlyphBlt = miImageGlyphBlt; + } + else + { +#ifdef WriteBitGroup + if (pGC->fillStyle == FillSolid) + { + if (devPriv->rop == GXcopy) + pGC->ops->PolyGlyphBlt = cfbPolyGlyphBlt8; + else +#ifdef FOUR_BIT_CODE + pGC->ops->PolyGlyphBlt = cfbPolyGlyphRop8; +#else + pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; +#endif + } + else +#endif + pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; + /* special case ImageGlyphBlt for terminal emulator fonts */ +#if !defined(WriteBitGroup) || PSZ == 8 + if (TERMINALFONT(pGC->font) && + (pGC->planemask & PMSK) == PMSK +#ifdef FOUR_BIT_CODE + && FONTMAXBOUNDS(pGC->font,characterWidth) >= PGSZB +#endif + ) + { + pGC->ops->ImageGlyphBlt = useTEGlyphBlt; + } + else +#endif + { +#ifdef WriteBitGroup + if (devPriv->rop == GXcopy && + pGC->fillStyle == FillSolid && + (pGC->planemask & PMSK) == PMSK) + pGC->ops->ImageGlyphBlt = cfbImageGlyphBlt8; + else +#endif + pGC->ops->ImageGlyphBlt = miImageGlyphBlt; + } + } + } + + + if (new_fillspans) { + switch (pGC->fillStyle) { + case FillSolid: + switch (devPriv->rop) { + case GXcopy: + pGC->ops->FillSpans = cfbSolidSpansCopy; + break; + case GXxor: + pGC->ops->FillSpans = cfbSolidSpansXor; + break; + default: + pGC->ops->FillSpans = cfbSolidSpansGeneral; + break; + } + break; + case FillTiled: + if (devPriv->pRotatedPixmap) + { + if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK) + pGC->ops->FillSpans = cfbTile32FSCopy; + else + pGC->ops->FillSpans = cfbTile32FSGeneral; + } + else + pGC->ops->FillSpans = cfbUnnaturalTileFS; + break; + case FillStippled: +#ifdef FOUR_BIT_CODE + if (devPriv->pRotatedPixmap) + pGC->ops->FillSpans = cfb8Stipple32FS; + else +#endif + pGC->ops->FillSpans = cfbUnnaturalStippleFS; + break; + case FillOpaqueStippled: +#ifdef FOUR_BIT_CODE + if (devPriv->pRotatedPixmap) + pGC->ops->FillSpans = cfb8OpaqueStipple32FS; + else +#endif + pGC->ops->FillSpans = cfbUnnaturalStippleFS; + break; + default: + FatalError("cfbValidateGC: illegal fillStyle\n"); + } + } /* end of new_fillspans */ + + if (new_fillarea) { +#ifndef FOUR_BIT_CODE + pGC->ops->PolyFillRect = miPolyFillRect; + if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) + { + pGC->ops->PolyFillRect = cfbPolyFillRect; + } +#endif +#ifdef FOUR_BIT_CODE +#ifndef LOWMEMFTPT + pGC->ops->PushPixels = mfbPushPixels; +#else + pGC->ops->PushPixels = miPushPixels; +#endif /* ifndef LOWMEMFTPT */ + if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy) + pGC->ops->PushPixels = cfbPushPixels8; +#endif + pGC->ops->PolyFillArc = miPolyFillArc; + if (pGC->fillStyle == FillSolid) + { + switch (devPriv->rop) + { + case GXcopy: + pGC->ops->PolyFillArc = cfbPolyFillArcSolidCopy; + break; + default: + pGC->ops->PolyFillArc = cfbPolyFillArcSolidGeneral; + break; + } + } + } +} diff --git a/cfb/cfbgetsp.c b/cfb/cfbgetsp.c new file mode 100644 index 000000000..a2c9966df --- /dev/null +++ b/cfb/cfbgetsp.c @@ -0,0 +1,164 @@ +/* $Xorg: cfbgetsp.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" + +#include "misc.h" +#include "region.h" +#include "gc.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" + +/* GetSpans -- for each span, gets bits from drawable starting at ppt[i] + * and continuing for pwidth[i] bits + * Each scanline returned will be server scanline padded, i.e., it will come + * out to an integral number of words. + */ +void +cfbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart) + DrawablePtr pDrawable; /* drawable from which to get bits */ + int wMax; /* largest value of all *pwidths */ + register DDXPointPtr ppt; /* points to start copying from */ + int *pwidth; /* list of number of bits to copy */ + int nspans; /* number of scanlines to copy */ + char *pchardstStart; /* where to put the bits */ +{ + PixelGroup *pdstStart = (PixelGroup *)pchardstStart; + register PixelGroup *pdst; /* where to put the bits */ + register PixelGroup *psrc; /* where to get the bits */ + register PixelGroup tmpSrc; /* scratch buffer for bits */ + PixelGroup *psrcBase; /* start of src bitmap */ + int widthSrc; /* width of pixmap in bytes */ + register DDXPointPtr pptLast; /* one past last point to get */ + int xEnd; /* last pixel to copy from */ + register int nstart; + int nend; + PixelGroup startmask, endmask; + int nlMiddle, nl, srcBit; + int w; + PixelGroup *pdstNext; + + switch (pDrawable->bitsPerPixel) { + case 1: + mfbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); + return; + case PSZ: + break; + default: + FatalError("cfbGetSpans: invalid depth\n"); + } + + + cfbGetLongWidthAndPointer (pDrawable, widthSrc, psrcBase) + +#ifdef PIXEL_ADDR + if ((nspans == 1) && (*pwidth == 1)) + { + tmpSrc = *((PixelType *)(psrcBase + (ppt->y * widthSrc)) + + ppt->x); +#if BITMAP_BIT_ORDER == MSBFirst + tmpSrc <<= (sizeof (unsigned long) - sizeof (PixelType)) * 8; +#endif + *pdstStart = tmpSrc; + return; + } +#endif + pdst = pdstStart; + pptLast = ppt + nspans; + while(ppt < pptLast) + { + xEnd = min(ppt->x + *pwidth, widthSrc << PWSH); + psrc = psrcBase + ppt->y * widthSrc + (ppt->x >> PWSH); + w = xEnd - ppt->x; + srcBit = ppt->x & PIM; + pdstNext = pdst + ((w + PPW - 1) >> PWSH); + + if (srcBit + w <= PPW) + { + getbits(psrc, srcBit, w, tmpSrc); + putbits(tmpSrc, 0, w, pdst, ~((unsigned long)0)); + pdst++; + } + else + { + maskbits(ppt->x, w, startmask, endmask, nlMiddle); + nstart = 0; + if (startmask) + { + nstart = PPW - srcBit; + getbits(psrc, srcBit, nstart, tmpSrc); + putbits(tmpSrc, 0, nstart, pdst, ~((unsigned long)0)); + if(srcBit + nstart >= PPW) + psrc++; + } + nl = nlMiddle; + while (nl--) + { + tmpSrc = *psrc; + putbits(tmpSrc, nstart, PPW, pdst, ~((unsigned long)0)); + psrc++; + pdst++; + } + if (endmask) + { + nend = xEnd & PIM; + getbits(psrc, 0, nend, tmpSrc); + putbits(tmpSrc, nstart, nend, pdst, ~((unsigned long)0)); + } + pdst = pdstNext; + } + ppt++; + pwidth++; + } +} diff --git a/cfb/cfbglblt8.c b/cfb/cfbglblt8.c new file mode 100644 index 000000000..b87bc8513 --- /dev/null +++ b/cfb/cfbglblt8.c @@ -0,0 +1,441 @@ +/* $Xorg: cfbglblt8.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/* + * Poly glyph blt. Accepts an arbitrary font <= 32 bits wide, in Copy mode + * only. + */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "cfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" + +#define BOX_OVERLAP(box1, box2, xoffset, yoffset) \ + ((box1)->x1 <= ((int) (box2)->x2 + (xoffset)) && \ + ((int) (box2)->x1 + (xoffset)) <= (box1)->x2 && \ + (box1)->y1 <= ((int) (box2)->y2 + (yoffset)) && \ + ((int) (box2)->y1 + (yoffset)) <= (box1)->y2) + +#define BOX_CONTAINS(box1, box2, xoffset, yoffset) \ + ((box1)->x1 <= ((int) (box2)->x1 + (xoffset)) && \ + ((int) (box2)->x2 + (xoffset)) <= (box1)->x2 && \ + (box1)->y1 <= ((int) (box2)->y1 + (yoffset)) && \ + ((int) (box2)->y2 + (yoffset)) <= (box1)->y2) + +#if defined(FOUR_BIT_CODE) || defined(WriteBitGroup) && !defined(GLYPHROP) + +#if GLYPHPADBYTES != 4 +#define USE_LEFTBITS +#endif + +#ifdef USE_LEFTBITS +typedef unsigned char *glyphPointer; +extern unsigned long endtab[]; + +#define GlyphBits(bits,width,dst) getleftbits(bits,width,dst); \ + (dst) &= widthMask; \ + (bits) += widthGlyph; +#define GlyphBitsS(bits,width,dst,off) GlyphBits(bits,width,dst); \ + dst = BitRight (dst, off); +#else +typedef CARD32 *glyphPointer; + +#define GlyphBits(bits,width,dst) dst = *bits++; +#define GlyphBitsS(bits,width,dst,off) dst = BitRight(*bits++, off); +#endif + +#ifdef GLYPHROP +#define cfbPolyGlyphBlt8 cfbPolyGlyphRop8 +#define cfbPolyGlyphBlt8Clipped cfbPolyGlyphRop8Clipped + +#undef WriteBitGroup +#define WriteBitGroup(dst,pixel,bits) RRopBitGroup(dst,bits) + +#endif + +static void cfbPolyGlyphBlt8Clipped(); + +#if defined(HAS_STIPPLE_CODE) && !defined(GLYPHROP) && !defined(USE_LEFTBITS) +#define USE_STIPPLE_CODE +#endif + +#if defined(__GNUC__) && !defined(GLYPHROP) && (defined(mc68020) || defined(mc68000) || defined(__mc68000__)) && !defined(USE_LEFTBITS) +#ifdef USE_STIPPLE_CODE +#undef USE_STIPPLE_CODE +#endif +#endif + +#define DST_INC (PGSZB >> PWSH) + +/* cfbStippleStack/cfbStippleStackTE are coded in assembly language. + * They are only provided on some architecures. + */ +#ifdef USE_STIPPLE_CODE +extern void cfbStippleStack (), cfbStippleStackTE (); +#endif + +void +cfbPolyGlyphBlt8 (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + register unsigned long c; +#ifndef GLYPHROP + register unsigned long pixel; +#endif + register unsigned long *dst; + register glyphPointer glyphBits; + register int xoff; + + FontPtr pfont = pGC->font; + CharInfoPtr pci; + unsigned long *dstLine; + unsigned long *pdstBase; + int hTmp; + int bwidthDst; + int widthDst; + int h; + int ew; + BoxRec bbox; /* for clipping */ + int widthDiff; + int w; + RegionPtr clip; + BoxPtr extents; +#ifdef USE_LEFTBITS + int widthGlyph; + unsigned long widthMask; +#endif +#ifndef STIPPLE +#ifdef USE_STIPPLE_CODE + void (*stipple)(); + + stipple = cfbStippleStack; + if (FONTCONSTMETRICS(pfont)) + stipple = cfbStippleStackTE; +#endif +#endif + + x += pDrawable->x; + y += pDrawable->y; + + /* compute an approximate (but covering) bounding box */ + bbox.x1 = 0; + if ((ppci[0]->metrics.leftSideBearing < 0)) + bbox.x1 = ppci[0]->metrics.leftSideBearing; + h = nglyph - 1; + w = ppci[h]->metrics.rightSideBearing; + while (--h >= 0) + w += ppci[h]->metrics.characterWidth; + bbox.x2 = w; + bbox.y1 = -FONTMAXBOUNDS(pfont,ascent); + bbox.y2 = FONTMAXBOUNDS(pfont,descent); + + clip = cfbGetCompositeClip(pGC); + extents = &clip->extents; + + if (!clip->data) + { + if (!BOX_CONTAINS(extents, &bbox, x, y)) + { + if (BOX_OVERLAP (extents, &bbox, x, y)) + cfbPolyGlyphBlt8Clipped(pDrawable, pGC, x, y, + nglyph, ppci, pglyphBase); + return; + } + } + else + { + /* check to make sure some of the text appears on the screen */ + if (!BOX_OVERLAP (extents, &bbox, x, y)) + return; + + bbox.x1 += x; + bbox.x2 += x; + bbox.y1 += y; + bbox.y2 += y; + + switch (RECT_IN_REGION(pGC->pScreen, clip, &bbox)) + { + case rgnPART: + cfbPolyGlyphBlt8Clipped(pDrawable, pGC, x, y, + nglyph, ppci, pglyphBase); + case rgnOUT: + return; + } + } + +#ifdef GLYPHROP + cfb8CheckStipple (pGC->alu, pGC->fgPixel, pGC->planemask); +#else + pixel = cfbGetGCPrivate(pGC)->xor; +#endif + + cfbGetTypedWidthAndPointer (pDrawable, bwidthDst, pdstBase, char, unsigned long) + + widthDst = bwidthDst / PGSZB; + while (nglyph--) + { + pci = *ppci++; + glyphBits = (glyphPointer) FONTGLYPHBITS(pglyphBase,pci); + xoff = x + pci->metrics.leftSideBearing; + dstLine = pdstBase + + (y - pci->metrics.ascent) * widthDst + (xoff >> PWSH); + x += pci->metrics.characterWidth; + if (hTmp = pci->metrics.descent + pci->metrics.ascent) + { + xoff &= PIM; +#ifdef STIPPLE + STIPPLE(dstLine,glyphBits,pixel,bwidthDst,hTmp,xoff); +#else +#ifdef USE_STIPPLE_CODE + (*stipple)(dstLine,glyphBits,pixel,bwidthDst,hTmp,xoff); +#else +#ifdef USE_LEFTBITS + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + widthGlyph = PADGLYPHWIDTHBYTES(w); + widthMask = endtab[w]; +#endif + do { + dst = dstLine; + dstLine = (unsigned long *) (((char *) dstLine) + bwidthDst); + GlyphBits(glyphBits, w, c) + WriteBitGroup(dst, pixel, GetBitGroup(BitRight(c,xoff))); + dst += DST_INC; + c = BitLeft(c,PGSZB - xoff); + while (c) + { + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst += DST_INC; + } + } while (--hTmp); +#endif /* USE_STIPPLE_CODE else */ +#endif /* STIPPLE else */ + } + } +} + +static void +cfbPolyGlyphBlt8Clipped (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + unsigned char *pglyphBase; /* start of array of glyphs */ +{ + register unsigned long c; +#ifndef GLYPHROP + register unsigned long pixel; +#endif + register unsigned long *dst; + register glyphPointer glyphBits; + register int xoff; + unsigned long c1; + + CharInfoPtr pci; + FontPtr pfont = pGC->font; + unsigned long *dstLine; + unsigned long *pdstBase; + CARD32 *cTmp, *clips; + int maxAscent, maxDescent; + int minLeftBearing; + int hTmp; + int widthDst; + int bwidthDst; + int ew; + int xG, yG; + BoxPtr pBox; + int numRects; + int widthDiff; + int w; + RegionPtr pRegion; + int yBand; +#ifdef GLYPHROP + unsigned long bits; +#endif +#ifdef USE_LEFTBITS + int widthGlyph; + unsigned long widthMask; +#endif + +#ifdef GLYPHROP + cfb8CheckStipple (pGC->alu, pGC->fgPixel, pGC->planemask); +#else + pixel = cfbGetGCPrivate(pGC)->xor; +#endif + + cfbGetTypedWidthAndPointer (pDrawable, bwidthDst, pdstBase, char, unsigned long) + + widthDst = bwidthDst / PGSZB; + maxAscent = FONTMAXBOUNDS(pfont,ascent); + maxDescent = FONTMAXBOUNDS(pfont,descent); + minLeftBearing = FONTMINBOUNDS(pfont,leftSideBearing); + + pRegion = cfbGetCompositeClip(pGC); + + pBox = REGION_RECTS(pRegion); + numRects = REGION_NUM_RECTS (pRegion); + while (numRects && pBox->y2 <= y - maxAscent) + { + ++pBox; + --numRects; + } + if (!numRects || pBox->y1 >= y + maxDescent) + return; + yBand = pBox->y1; + while (numRects && pBox->y1 == yBand && pBox->x2 <= x + minLeftBearing) + { + ++pBox; + --numRects; + } + if (!numRects) + return; + clips = (CARD32 *)ALLOCATE_LOCAL ((maxAscent + maxDescent) * + sizeof (CARD32)); + while (nglyph--) + { + pci = *ppci++; + glyphBits = (glyphPointer) FONTGLYPHBITS(pglyphBase,pci); + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + xG = x + pci->metrics.leftSideBearing; + yG = y - pci->metrics.ascent; + x += pci->metrics.characterWidth; + if (hTmp = pci->metrics.descent + pci->metrics.ascent) + { + dstLine = pdstBase + yG * widthDst + (xG >> PWSH); + xoff = xG & PIM; +#ifdef USE_LEFTBITS + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + widthGlyph = PADGLYPHWIDTHBYTES(w); + widthMask = endtab[w]; +#endif + switch (cfb8ComputeClipMasks32 (pBox, numRects, xG, yG, w, hTmp, clips)) + { + case rgnPART: +#ifdef USE_LEFTBITS + cTmp = clips; + do { + dst = dstLine; + dstLine = (unsigned long *) (((char *) dstLine) + bwidthDst); + GlyphBits(glyphBits, w, c) + c &= *cTmp++; + if (c) + { + WriteBitGroup(dst, pixel, GetBitGroup(BitRight(c,xoff))); + c = BitLeft(c,PGSZB - xoff); + dst += DST_INC; + while (c) + { + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst += DST_INC; + } + } + } while (--hTmp); + break; +#else /* !USE_LEFT_BITS */ + { + int h; + + h = hTmp; + do + { + --h; + clips[h] = clips[h] & glyphBits[h]; + } while (h); + } + glyphBits = clips; + /* fall through */ +#endif /* USE_LEFT_BITS */ + case rgnIN: +#ifdef STIPPLE + STIPPLE(dstLine,glyphBits,pixel,bwidthDst,hTmp,xoff); +#else +#ifdef USE_STIPPLE_CODE + cfbStippleStackTE(dstLine,glyphBits,pixel,bwidthDst,hTmp,xoff); +#else + do { + dst = dstLine; + dstLine = (unsigned long *) (((char *) dstLine) + bwidthDst); + GlyphBits(glyphBits, w, c) + if (c) + { + /* This code originally could read memory locations + * that were not mapped. Hence we have to check the + * trailing bits to see whether they are zero and if + * then skip them correctly. This is no problem for + * the GXcopy case, since there only the pixels that + * are non-zero are written ... + */ +#ifndef GLYPHROP + WriteBitGroup(dst, pixel, GetBitGroup(BitRight(c,xoff))); + c = BitLeft(c,PGSZB - xoff); + dst += DST_INC; +#else /* GLYPHROP */ + if (bits = GetBitGroup(BitRight(c,xoff))) + WriteBitGroup(dst, pixel, bits); + c = BitLeft(c,PGSZB - xoff); + dst += DST_INC; + + while (c && ((bits = GetBitGroup(c)) == 0)) + { + NextBitGroup(c); + dst += DST_INC; + } +#endif /* GLYPHROP */ + while (c) + { + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst += DST_INC; + } + } + } while (--hTmp); +#endif /* USE_STIPPLE_CODE else */ +#endif /* STIPPLE else */ + break; + } + } + } + DEALLOCATE_LOCAL (clips); +} + +#endif /* FOUR_BIT_CODE */ diff --git a/cfb/cfbhrzvert.c b/cfb/cfbhrzvert.c new file mode 100644 index 000000000..3fe9262ad --- /dev/null +++ b/cfb/cfbhrzvert.c @@ -0,0 +1,179 @@ +/*********************************************************** + +Copyright 1987,1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: cfbhrzvert.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ +#include "X.h" + +#include "gc.h" +#include "window.h" +#include "pixmap.h" +#include "region.h" + +#include "cfb.h" +#include "cfbmskbits.h" + +/* horizontal solid line + abs(len) > 1 +*/ +cfbHorzS(rop, and, xor, addrl, nlwidth, x1, y1, len) +register int rop; +register unsigned long and; +register unsigned long xor; +register unsigned long *addrl; /* pointer to base of bitmap */ +int nlwidth; /* width in longwords of bitmap */ +int x1; /* initial point */ +int y1; +int len; /* length of line */ +{ + register int nlmiddle; + register unsigned long startmask; + register unsigned long endmask; + + addrl = addrl + (y1 * nlwidth) + (x1 >> PWSH); + + /* all bits inside same longword */ + if ( ((x1 & PIM) + len) < PPW) + { + maskpartialbits(x1, len, startmask); + *addrl = DoMaskRRop (*addrl, and, xor, startmask); + } + else + { + maskbits(x1, len, startmask, endmask, nlmiddle); + if (rop == GXcopy) + { + if (startmask) + { + *addrl = (*addrl & ~startmask) | (xor & startmask); + addrl++; + } + while (nlmiddle--) + *addrl++ = xor; + if (endmask) + *addrl = (*addrl & ~endmask) | (xor & endmask); + } + else + { + if (startmask) + { + *addrl = DoMaskRRop (*addrl, and, xor, startmask); + addrl++; + } + if (rop == GXxor) + { + while (nlmiddle--) + *addrl++ ^= xor; + } + else + { + while (nlmiddle--) + { + *addrl = DoRRop (*addrl, and, xor); + addrl++; + } + } + if (endmask) + *addrl = DoMaskRRop (*addrl, and, xor, endmask); + } + } +} + +/* vertical solid line */ + +cfbVertS(rop, and, xor, addrl, nlwidth, x1, y1, len) +int rop; +register unsigned long and, xor; +register unsigned long *addrl; /* pointer to base of bitmap */ +register int nlwidth; /* width in longwords of bitmap */ +int x1, y1; /* initial point */ +register int len; /* length of line */ +{ +#ifdef PIXEL_ADDR + register PixelType *bits = (PixelType *) addrl; + + nlwidth <<= PWSH; + bits = bits + (y1 * nlwidth) + x1; + + /* + * special case copy and xor to avoid a test per pixel + */ + if (rop == GXcopy) + { + while (len--) + { + *bits = xor; + bits += nlwidth; + } + } + else if (rop == GXxor) + { + while (len--) + { + *bits ^= xor; + bits += nlwidth; + } + } + else + { + while (len--) + { + *bits = DoRRop(*bits, and, xor); + bits += nlwidth; + } + } +#else /* !PIXEL_ADDR */ + addrl = addrl + (y1 * nlwidth) + (x1 >> PWSH); + + and |= ~cfbmask[x1 & PIM]; + xor &= cfbmask[x1 & PIM]; + + while (len--) + { + *addrl = DoRRop (*addrl, and, xor); + addrl += nlwidth; + } +#endif +} diff --git a/cfb/cfbigblt8.c b/cfb/cfbigblt8.c new file mode 100644 index 000000000..7e20e2578 --- /dev/null +++ b/cfb/cfbigblt8.c @@ -0,0 +1,97 @@ +/* + * $Xorg: cfbigblt8.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "cfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" + +void +cfbImageGlyphBlt8 (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; + pointer pglyphBase; +{ + ExtentInfoRec info; /* used by QueryGlyphExtents() */ + xRectangle backrect; + int fillStyle; + int alu; + int fgPixel; + int rop; + int xor; + int and; + int pm; + cfbPrivGC *priv; + + QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info); + + if (info.overallWidth >= 0) + { + backrect.x = x; + backrect.width = info.overallWidth; + } + else + { + backrect.x = x + info.overallWidth; + backrect.width = -info.overallWidth; + } + backrect.y = y - FONTASCENT(pGC->font); + backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + + priv = cfbGetGCPrivate(pGC); + + /* this code cheats by knowing that ValidateGC isn't + * necessary for PolyFillRect + */ + + fgPixel = pGC->fgPixel; + + pGC->fgPixel = pGC->bgPixel; + priv->xor = PFILL(pGC->bgPixel); + + (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &backrect); + + pGC->fgPixel = fgPixel; + + priv->xor = PFILL(pGC->fgPixel); + + (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + +} diff --git a/cfb/cfbimage.c b/cfb/cfbimage.c new file mode 100644 index 000000000..af0fcc11d --- /dev/null +++ b/cfb/cfbimage.c @@ -0,0 +1,200 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: cfbimage.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ + +#include "X.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "servermd.h" + +#ifdef LOWMEMFTPT +#include "mi.h" +#endif /* ifdef LOWMEMFTPT */ + +void +cfbPutImage(pDraw, pGC, depth, x, y, w, h, leftPad, format, pImage) + DrawablePtr pDraw; + GCPtr pGC; + int depth, x, y, w, h; + int leftPad; + int format; + char *pImage; +{ + int bitsPerPixel; + PixmapPtr pPixmap; + + if ((w == 0) || (h == 0)) + return; + + if (format != XYPixmap) + { + pPixmap = GetScratchPixmapHeader(pDraw->pScreen, w+leftPad, h, depth, + BitsPerPixel(depth), PixmapBytePad(w+leftPad, depth), + (pointer)pImage); + if (!pPixmap) + return; + + cfbGetGCPrivate(pGC)->fExpose = FALSE; + if (format == ZPixmap) + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, pDraw, pGC, + leftPad, 0, w, h, x, y); + else + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, pDraw, pGC, + leftPad, 0, w, h, x, y, 1); + cfbGetGCPrivate(pGC)->fExpose = TRUE; + FreeScratchPixmapHeader(pPixmap); + } + else + { + unsigned long oldFg, oldBg; + XID gcv[3]; + unsigned long oldPlanemask; + unsigned long i; + long bytesPer; + + depth = pGC->depth; + oldPlanemask = pGC->planemask; + oldFg = pGC->fgPixel; + oldBg = pGC->bgPixel; + gcv[0] = ~0L; + gcv[1] = 0; + DoChangeGC(pGC, GCForeground | GCBackground, gcv, 0); + bytesPer = (long)h * BitmapBytePad(w + leftPad); + + for (i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer) + { + if (i & oldPlanemask) + { + gcv[0] = i; + DoChangeGC(pGC, GCPlaneMask, gcv, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad, + XYBitmap, pImage); + } + } + gcv[0] = oldPlanemask; + gcv[1] = oldFg; + gcv[2] = oldBg; + DoChangeGC(pGC, GCPlaneMask | GCForeground | GCBackground, gcv, 0); + } +} + +void +cfbGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine) + DrawablePtr pDrawable; + int sx, sy, w, h; + unsigned int format; + unsigned long planeMask; + char *pdstLine; +{ + BoxRec box; + DDXPointRec ptSrc; + RegionRec rgnDst; + ScreenPtr pScreen; + PixmapPtr pPixmap; + + if ((w == 0) || (h == 0)) + return; + if (pDrawable->bitsPerPixel == 1) + { +#ifndef LOWMEMFTPT + mfbGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); +#else + miGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); +#endif /* ifndef LOWMEMFTPT */ + return; + } + pScreen = pDrawable->pScreen; + if (format == ZPixmap) + { + pPixmap = GetScratchPixmapHeader(pScreen, w, h, + pDrawable->depth, pDrawable->bitsPerPixel, + PixmapBytePad(w,pDrawable->depth), (pointer)pdstLine); + if (!pPixmap) + return; + if ((planeMask & PMSK) != PMSK) + bzero((char *)pdstLine, pPixmap->devKind * h); + ptSrc.x = sx + pDrawable->x; + ptSrc.y = sy + pDrawable->y; + box.x1 = 0; + box.y1 = 0; + box.x2 = w; + box.y2 = h; + REGION_INIT(pScreen, &rgnDst, &box, 1); + cfbDoBitblt(pDrawable, (DrawablePtr)pPixmap, GXcopy, &rgnDst, + &ptSrc, planeMask); + REGION_UNINIT(pScreen, &rgnDst); + FreeScratchPixmapHeader(pPixmap); + } + else + { +#if PSZ == 8 + pPixmap = GetScratchPixmapHeader(pScreen, w, h, /*depth*/ 1, + /*bpp*/ 1, BitmapBytePad(w), (pointer)pdstLine); + if (!pPixmap) + return; + + ptSrc.x = sx + pDrawable->x; + ptSrc.y = sy + pDrawable->y; + box.x1 = 0; + box.y1 = 0; + box.x2 = w; + box.y2 = h; + REGION_INIT(pScreen, &rgnDst, &box, 1); + cfbCopyImagePlane (pDrawable, (DrawablePtr)pPixmap, GXcopy, &rgnDst, + &ptSrc, planeMask); + REGION_UNINIT(pScreen, &rgnDst); + FreeScratchPixmapHeader(pPixmap); +#else + miGetImage (pDrawable, sx, sy, w, h, format, planeMask, pdstLine); +#endif + } +} diff --git a/cfb/cfbline.c b/cfb/cfbline.c new file mode 100644 index 000000000..019d93720 --- /dev/null +++ b/cfb/cfbline.c @@ -0,0 +1,743 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: cfbline.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ +#include "X.h" + +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "mistruct.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "miline.h" + +/* single-pixel lines on a color frame buffer + + NON-SLOPED LINES + horizontal lines are always drawn left to right; we have to +move the endpoints right by one after they're swapped. + horizontal lines will be confined to a single band of a +region. the code finds that band (giving up if the lower +bound of the band is above the line we're drawing); then it +finds the first box in that band that contains part of the +line. we clip the line to subsequent boxes in that band. + vertical lines are always drawn top to bottom (y-increasing.) +this requires adding one to the y-coordinate of each endpoint +after swapping. + + SLOPED LINES + when clipping a sloped line, we bring the second point inside +the clipping box, rather than one beyond it, and then add 1 to +the length of the line before drawing it. this lets us use +the same box for finding the outcodes for both endpoints. since +the equation for clipping the second endpoint to an edge gives us +1 beyond the edge, we then have to move the point towards the +first point by one step on the major axis. + eventually, there will be a diagram here to explain what's going +on. the method uses Cohen-Sutherland outcodes to determine +outsideness, and a method similar to Pike's layers for doing the +actual clipping. + +*/ + +void +#ifdef POLYSEGMENT +cfbSegmentSS (pDrawable, pGC, nseg, pSeg) + DrawablePtr pDrawable; + GCPtr pGC; + int nseg; + register xSegment *pSeg; +#else +cfbLineSS (pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; /* number of points */ + DDXPointPtr pptInit; +#endif +{ + int nboxInit; + register int nbox; + BoxPtr pboxInit; + register BoxPtr pbox; +#ifndef POLYSEGMENT + register DDXPointPtr ppt; /* pointer to list of translated points */ +#endif + + unsigned int oc1; /* outcode of point 1 */ + unsigned int oc2; /* outcode of point 2 */ + + unsigned long *addrl; /* address of destination pixmap */ + int nlwidth; /* width in longwords of destination pixmap */ + int xorg, yorg; /* origin of window */ + + int adx; /* abs values of dx and dy */ + int ady; + int signdx; /* sign of dx and dy */ + int signdy; + int e, e1, e2; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + + /* a bunch of temporaries */ + int tmp; + register int y1, y2; + register int x1, x2; + RegionPtr cclip; + cfbPrivGCPtr devPriv; + unsigned long xor, and; + int alu; + + devPriv = cfbGetGCPrivate(pGC); + cclip = devPriv->pCompositeClip; + pboxInit = REGION_RECTS(cclip); + nboxInit = REGION_NUM_RECTS(cclip); + + cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl) + + alu = devPriv->rop; + xor = devPriv->xor; + and = devPriv->and; + xorg = pDrawable->x; + yorg = pDrawable->y; +#ifdef POLYSEGMENT + while (nseg--) +#else + ppt = pptInit; + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; + while(--npt) +#endif + { + nbox = nboxInit; + pbox = pboxInit; + +#ifdef POLYSEGMENT + x1 = pSeg->x1 + xorg; + y1 = pSeg->y1 + yorg; + x2 = pSeg->x2 + xorg; + y2 = pSeg->y2 + yorg; + pSeg++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) + { + xorg = x1; + yorg = y1; + } + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; +#endif + + if (x1 == x2) /* vertical line */ + { + /* make the line go top to bottom of screen, keeping + endpoint semantics + */ + if (y1 > y2) + { + register int tmp; + + tmp = y2; + y2 = y1 + 1; + y1 = tmp + 1; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + y1--; +#endif + } +#ifdef POLYSEGMENT + else if (pGC->capStyle != CapNotLast) + y2++; +#endif + /* get to first band that might contain part of line */ + while ((nbox) && (pbox->y2 <= y1)) + { + pbox++; + nbox--; + } + + if (nbox) + { + /* stop when lower edge of box is beyond end of line */ + while((nbox) && (y2 >= pbox->y1)) + { + if ((x1 >= pbox->x1) && (x1 < pbox->x2)) + { + int y1t, y2t; + /* this box has part of the line in it */ + y1t = max(y1, pbox->y1); + y2t = min(y2, pbox->y2); + if (y1t != y2t) + { + cfbVertS (alu, and, xor, + addrl, nlwidth, + x1, y1t, y2t-y1t); + } + } + nbox--; + pbox++; + } + } +#ifndef POLYSEGMENT + y2 = ppt->y + yorg; +#endif + } + else if (y1 == y2) /* horizontal line */ + { + /* force line from left to right, keeping + endpoint semantics + */ + if (x1 > x2) + { + register int tmp; + + tmp = x2; + x2 = x1 + 1; + x1 = tmp + 1; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + x1--; +#endif + } +#ifdef POLYSEGMENT + else if (pGC->capStyle != CapNotLast) + x2++; +#endif + + /* find the correct band */ + while( (nbox) && (pbox->y2 <= y1)) + { + pbox++; + nbox--; + } + + /* try to draw the line, if we haven't gone beyond it */ + if ((nbox) && (pbox->y1 <= y1)) + { + /* when we leave this band, we're done */ + tmp = pbox->y1; + while((nbox) && (pbox->y1 == tmp)) + { + int x1t, x2t; + + if (pbox->x2 <= x1) + { + /* skip boxes until one might contain start point */ + nbox--; + pbox++; + continue; + } + + /* stop if left of box is beyond right of line */ + if (pbox->x1 >= x2) + { + nbox = 0; + break; + } + + x1t = max(x1, pbox->x1); + x2t = min(x2, pbox->x2); + if (x1t != x2t) + { + cfbHorzS (alu, and, xor, + addrl, nlwidth, + x1t, y1, x2t-x1t); + } + nbox--; + pbox++; + } + } +#ifndef POLYSEGMENT + x2 = ppt->x + xorg; +#endif + } + else /* sloped line */ + { + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, + 1, 1, octant); + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + } + else + { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + SetYMajorOctant(octant); + } + + FIXUP_ERROR(e, octant, bias); + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + while(nbox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pbox); + OUTCODES(oc2, x2, y2, pbox); + if ((oc1 | oc2) == 0) + { + if (axis == X_AXIS) + len = adx; + else + len = ady; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + len++; +#endif + cfbBresS (alu, and, xor, + addrl, nlwidth, + signdx, signdy, axis, x1, y1, + e, e1, e2, len); + break; + } + else if (oc1 & oc2) + { + pbox++; + } + else + { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int clipdx, clipdy; + int err; + + if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1, + pbox->y2-1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) + { + pbox++; + continue; + } + + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); +#ifdef POLYSEGMENT + if (clip2 != 0 || pGC->capStyle != CapNotLast) + len++; +#else + len += (clip2 != 0); +#endif + if (len) + { + /* unwind bresenham error term to first point */ + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + err = e+((clipdy*e2) + ((clipdx-clipdy)*e1)); + else + err = e+((clipdx*e2) + ((clipdy-clipdx)*e1)); + } + else + err = e; + cfbBresS(alu, and, xor, + addrl, nlwidth, + signdx, signdy, axis, new_x1, new_y1, + err, e1, e2, len); + } + pbox++; + } + } /* while (nbox--) */ + } /* sloped line */ + } /* while (nline--) */ + +#ifndef POLYSEGMENT + /* paint the last point if the end style isn't CapNotLast. + (Assume that a projecting, butt, or round cap that is one + pixel wide is the same as the single pixel of the endpoint.) + */ + + if ((pGC->capStyle != CapNotLast) && + ((ppt->x + xorg != pptInit->x + pDrawable->x) || + (ppt->y + yorg != pptInit->y + pDrawable->y) || + (ppt == pptInit + 1))) + { + nbox = nboxInit; + pbox = pboxInit; + while (nbox--) + { + if ((x2 >= pbox->x1) && + (y2 >= pbox->y1) && + (x2 < pbox->x2) && + (y2 < pbox->y2)) + { + unsigned long mask; + unsigned long scrbits; + + mask = cfbmask[x2 & PIM]; + addrl += (y2 * nlwidth) + (x2 >> PWSH); + scrbits = *addrl; + *addrl = (scrbits & ~mask) | + (DoRRop (scrbits, and, xor) & mask); + break; + } + else + pbox++; + } + } +#endif +} + +/* + * Draw dashed 1-pixel lines. + */ + +void +#ifdef POLYSEGMENT +cfbSegmentSD (pDrawable, pGC, nseg, pSeg) + DrawablePtr pDrawable; + register GCPtr pGC; + int nseg; + register xSegment *pSeg; +#else +cfbLineSD( pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + register GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; /* number of points */ + DDXPointPtr pptInit; +#endif +{ + int nboxInit; + register int nbox; + BoxPtr pboxInit; + register BoxPtr pbox; +#ifndef POLYSEGMENT + register DDXPointPtr ppt; /* pointer to list of translated points */ +#endif + + register unsigned int oc1; /* outcode of point 1 */ + register unsigned int oc2; /* outcode of point 2 */ + + unsigned long *addrl; /* address of destination pixmap */ + int nlwidth; /* width in longwords of destination pixmap */ + int xorg, yorg; /* origin of window */ + + int adx; /* abs values of dx and dy */ + int ady; + int signdx; /* sign of dx and dy */ + int signdy; + int e, e1, e2; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + int x1, x2, y1, y2; + RegionPtr cclip; + cfbRRopRec rrops[2]; + unsigned char *pDash; + int dashOffset; + int numInDashList; + int dashIndex; + int isDoubleDash; + int dashIndexTmp, dashOffsetTmp; + int unclippedlen; + cfbPrivGCPtr devPriv; + + devPriv = cfbGetGCPrivate(pGC); + cclip = devPriv->pCompositeClip; + rrops[0].rop = devPriv->rop; + rrops[0].and = devPriv->and; + rrops[0].xor = devPriv->xor; + if (pGC->alu == GXcopy) + { + rrops[1].rop = GXcopy; + rrops[1].and = 0; + rrops[1].xor = PFILL (pGC->bgPixel); + } + else + { + rrops[1].rop = cfbReduceRasterOp (pGC->alu, + pGC->bgPixel, pGC->planemask, + &rrops[1].and, &rrops[1].xor); + } + pboxInit = REGION_RECTS(cclip); + nboxInit = REGION_NUM_RECTS(cclip); + + cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl) + + /* compute initial dash values */ + + pDash = (unsigned char *) pGC->dash; + numInDashList = pGC->numInDashList; + isDoubleDash = (pGC->lineStyle == LineDoubleDash); + dashIndex = 0; + dashOffset = 0; + miStepDash ((int)pGC->dashOffset, &dashIndex, pDash, + numInDashList, &dashOffset); + + xorg = pDrawable->x; + yorg = pDrawable->y; +#ifdef POLYSEGMENT + while (nseg--) +#else + ppt = pptInit; + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; + while(--npt) +#endif + { + nbox = nboxInit; + pbox = pboxInit; + +#ifdef POLYSEGMENT + x1 = pSeg->x1 + xorg; + y1 = pSeg->y1 + yorg; + x2 = pSeg->x2 + xorg; + y2 = pSeg->y2 + yorg; + pSeg++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) + { + xorg = x1; + yorg = y1; + } + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; +#endif + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + unclippedlen = adx; + } + else + { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + unclippedlen = ady; + SetYMajorOctant(octant); + } + + FIXUP_ERROR(e, octant, bias); + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + while(nbox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pbox); + OUTCODES(oc2, x2, y2, pbox); + if ((oc1 | oc2) == 0) + { +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + unclippedlen++; + dashIndexTmp = dashIndex; + dashOffsetTmp = dashOffset; + cfbBresD (rrops, + &dashIndexTmp, pDash, numInDashList, + &dashOffsetTmp, isDoubleDash, + addrl, nlwidth, + signdx, signdy, axis, x1, y1, + e, e1, e2, unclippedlen); + break; +#else + cfbBresD (rrops, + &dashIndex, pDash, numInDashList, + &dashOffset, isDoubleDash, + addrl, nlwidth, + signdx, signdy, axis, x1, y1, + e, e1, e2, unclippedlen); + goto dontStep; +#endif + } + else if (oc1 & oc2) + { + pbox++; + } + else /* have to clip */ + { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int clipdx, clipdy; + int err; + int dashIndexTmp, dashOffsetTmp; + + if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1, + pbox->y2-1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) + { + pbox++; + continue; + } + + dashIndexTmp = dashIndex; + dashOffsetTmp = dashOffset; + + if (clip1) + { + int dlen; + + if (axis == X_AXIS) + dlen = abs(new_x1 - x1); + else + dlen = abs(new_y1 - y1); + miStepDash (dlen, &dashIndexTmp, pDash, + numInDashList, &dashOffsetTmp); + } + + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); +#ifdef POLYSEGMENT + if (clip2 != 0 || pGC->capStyle != CapNotLast) + len++; +#else + len += (clip2 != 0); +#endif + if (len) + { + /* unwind bresenham error term to first point */ + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + err = e+((clipdy*e2) + ((clipdx-clipdy)*e1)); + else + err = e+((clipdx*e2) + ((clipdy-clipdx)*e1)); + } + else + err = e; + cfbBresD (rrops, + &dashIndexTmp, pDash, numInDashList, + &dashOffsetTmp, isDoubleDash, + addrl, nlwidth, + signdx, signdy, axis, new_x1, new_y1, + err, e1, e2, len); + } + pbox++; + } + } /* while (nbox--) */ +#ifndef POLYSEGMENT + /* + * walk the dash list around to the next line + */ + miStepDash (unclippedlen, &dashIndex, pDash, + numInDashList, &dashOffset); +dontStep: ; +#endif + } /* while (nline--) */ + +#ifndef POLYSEGMENT + /* paint the last point if the end style isn't CapNotLast. + (Assume that a projecting, butt, or round cap that is one + pixel wide is the same as the single pixel of the endpoint.) + */ + + if ((pGC->capStyle != CapNotLast) && + ((dashIndex & 1) == 0 || isDoubleDash) && + ((ppt->x + xorg != pptInit->x + pDrawable->x) || + (ppt->y + yorg != pptInit->y + pDrawable->y) || + (ppt == pptInit + 1))) + { + nbox = nboxInit; + pbox = pboxInit; + while (nbox--) + { + if ((x2 >= pbox->x1) && + (y2 >= pbox->y1) && + (x2 < pbox->x2) && + (y2 < pbox->y2)) + { + unsigned long mask; + int pix; + + pix = 0; + if (dashIndex & 1) + pix = 1; + mask = cfbmask[x2 & PIM]; + addrl += (y2 * nlwidth) + (x2 >> PWSH); + *addrl = DoMaskRRop (*addrl, rrops[pix].and, rrops[pix].xor, mask); + break; + } + else + pbox++; + } + } +#endif +} diff --git a/cfb/cfbmap.h b/cfb/cfbmap.h new file mode 100644 index 000000000..75a79eb1e --- /dev/null +++ b/cfb/cfbmap.h @@ -0,0 +1,187 @@ +/* + * $Xorg: cfbmap.h,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ + * +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * Map names around so that multiple depths can be supported simultaneously + */ + +/* a losing vendor cpp dumps core if we define NAME in terms of CATNAME */ + +#if PSZ != 8 +#if PSZ == 32 +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define NAME(subname) cfb32##subname +#else +#define NAME(subname) cfb32/**/subname +#endif +#endif + +#if PSZ == 16 +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define NAME(subname) cfb16##subname +#else +#define NAME(subname) cfb16/**/subname +#endif +#endif + +#if PSZ == 4 +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define NAME(subname) cfb4##subname +#else +#define NAME(subname) cfb4/**/subname +#endif +#endif + +#ifndef NAME +cfb can not hack PSZ yet +#endif + +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define CATNAME(prefix,subname) prefix##subname +#else +#define CATNAME(prefix,subname) prefix/**/subname +#endif + +#define cfbScreenPrivateIndex NAME(ScreenPrivateIndex) +#define QuartetBitsTable NAME(QuartetBitsTable) +#define QuartetPixelMaskTable NAME(QuartetPixelMaskTable) +#define cfbAllocatePrivates NAME(AllocatePrivates) +#define cfbBSFuncRec NAME(BSFuncRec) +#define cfbBitBlt NAME(BitBlt) +#define cfbBresD NAME(BresD) +#define cfbBresS NAME(BresS) +#define cfbChangeWindowAttributes NAME(ChangeWindowAttributes) +#define cfbCloseScreen NAME(CloseScreen) +#define cfbCopyArea NAME(CopyArea) +#define cfbCopyImagePlane NAME(CopyImagePlane) +#define cfbCopyPixmap NAME(CopyPixmap) +#define cfbCopyPlane NAME(CopyPlane) +#define cfbCopyRotatePixmap NAME(CopyRotatePixmap) +#define cfbCopyWindow NAME(CopyWindow) +#define cfbCreateGC NAME(CreateGC) +#define cfbCreatePixmap NAME(CreatePixmap) +#define cfbCreateWindow NAME(CreateWindow) +#define cfbCreateScreenResources NAME(CreateScreenResources) +#define cfbDestroyPixmap NAME(DestroyPixmap) +#define cfbDestroyWindow NAME(DestroyWindow) +#define cfbDoBitblt NAME(DoBitblt) +#define cfbDoBitbltCopy NAME(DoBitbltCopy) +#define cfbDoBitbltGeneral NAME(DoBitbltGeneral) +#define cfbDoBitbltOr NAME(DoBitbltOr) +#define cfbDoBitbltXor NAME(DoBitbltXor) +#define cfbFillBoxSolid NAME(FillBoxSolid) +#define cfbFillBoxTile32 NAME(FillBoxTile32) +#define cfbFillBoxTile32sCopy NAME(FillBoxTile32sCopy) +#define cfbFillBoxTile32sGeneral NAME(FillBoxTile32sGeneral) +#define cfbFillBoxTileOdd NAME(FillBoxTileOdd) +#define cfbFillBoxTileOddCopy NAME(FillBoxTileOddCopy) +#define cfbFillBoxTileOddGeneral NAME(FillBoxTileOddGeneral) +#define cfbFillPoly1RectCopy NAME(FillPoly1RectCopy) +#define cfbFillPoly1RectGeneral NAME(FillPoly1RectGeneral) +#define cfbFillRectSolidCopy NAME(FillRectSolidCopy) +#define cfbFillRectSolidGeneral NAME(FillRectSolidGeneral) +#define cfbFillRectSolidXor NAME(FillRectSolidXor) +#define cfbFillRectTile32Copy NAME(FillRectTile32Copy) +#define cfbFillRectTile32General NAME(FillRectTile32General) +#define cfbFillRectTileOdd NAME(FillRectTileOdd) +#define cfbFillSpanTile32sCopy NAME(FillSpanTile32sCopy) +#define cfbFillSpanTile32sGeneral NAME(FillSpanTile32sGeneral) +#define cfbFillSpanTileOddCopy NAME(FillSpanTileOddCopy) +#define cfbFillSpanTileOddGeneral NAME(FillSpanTileOddGeneral) +#define cfbFinishScreenInit NAME(FinishScreenInit) +#define cfbGCFuncs NAME(GCFuncs) +#define cfbGetImage NAME(GetImage) +#define cfbGetSpans NAME(GetSpans) +#define cfbHorzS NAME(HorzS) +#define cfbImageGlyphBlt8 NAME(ImageGlyphBlt8) +#define cfbLineSD NAME(LineSD) +#define cfbLineSS NAME(LineSS) +#define cfbMapWindow NAME(MapWindow) +#define cfbMatchCommon NAME(MatchCommon) +#define cfbNonTEOps NAME(NonTEOps) +#define cfbNonTEOps1Rect NAME(NonTEOps1Rect) +#define cfbPadPixmap NAME(PadPixmap) +#define cfbPaintWindow NAME(PaintWindow) +#define cfbPolyGlyphBlt8 NAME(PolyGlyphBlt8) +#define cfbPolyGlyphRop8 NAME(PolyGlyphRop8) +#define cfbPolyFillArcSolidCopy NAME(PolyFillArcSolidCopy) +#define cfbPolyFillArcSolidGeneral NAME(PolyFillArcSolidGeneral) +#define cfbPolyFillRect NAME(PolyFillRect) +#define cfbPolyPoint NAME(PolyPoint) +#define cfbPositionWindow NAME(PositionWindow) +#define cfbPutImage NAME(PutImage) +#define cfbReduceRasterOp NAME(ReduceRasterOp) +#define cfbRestoreAreas NAME(RestoreAreas) +#define cfbSaveAreas NAME(SaveAreas) +#define cfbScreenInit NAME(ScreenInit) +#define cfbSegmentSD NAME(SegmentSD) +#define cfbSegmentSS NAME(SegmentSS) +#define cfbSetScanline NAME(SetScanline) +#define cfbSetSpans NAME(SetSpans) +#define cfbSetupScreen NAME(SetupScreen) +#define cfbSolidSpansCopy NAME(SolidSpansCopy) +#define cfbSolidSpansGeneral NAME(SolidSpansGeneral) +#define cfbSolidSpansXor NAME(SolidSpansXor) +#define cfbStippleStack NAME(StippleStack) +#define cfbStippleStackTE NAME(StippleStackTE) +#define cfbTEGlyphBlt NAME(TEGlyphBlt) +#define cfbTEOps NAME(TEOps) +#define cfbTEOps1Rect NAME(TEOps1Rect) +#define cfbTile32FSCopy NAME(Tile32FSCopy) +#define cfbTile32FSGeneral NAME(Tile32FSGeneral) +#define cfbUnmapWindow NAME(UnmapWindow) +#define cfbUnnaturalStippleFS NAME(UnnaturalStippleFS) +#define cfbUnnaturalTileFS NAME(UnnaturalTileFS) +#define cfbValidateGC NAME(ValidateGC) +#define cfbVertS NAME(VertS) +#define cfbXRotatePixmap NAME(XRotatePixmap) +#define cfbYRotatePixmap NAME(YRotatePixmap) +#define cfbendpartial NAME(endpartial) +#define cfbendtab NAME(endtab) +#define cfbmask NAME(mask) +#define cfbrmask NAME(rmask) +#define cfbstartpartial NAME(startpartial) +#define cfbstarttab NAME(starttab) +#define cfb8LineSS1Rect NAME(LineSS1Rect) +#define cfb8SegmentSS1Rect NAME(SegmentSS1Rect) +#define cfb8ClippedLineCopy NAME(ClippedLineCopy) +#define cfb8ClippedLineXor NAME(ClippedLineXor) +#define cfb8ClippedLineGeneral NAME(ClippedLineGeneral ) +#define cfb8SegmentSS1RectCopy NAME(SegmentSS1RectCopy) +#define cfb8SegmentSS1RectXor NAME(SegmentSS1RectXor) +#define cfb8SegmentSS1RectGeneral NAME(SegmentSS1RectGeneral ) +#define cfb8SegmentSS1RectShiftCopy NAME(SegmentSS1RectShiftCopy) +#define cfb8LineSS1RectCopy NAME(LineSS1RectCopy) +#define cfb8LineSS1RectXor NAME(LineSS1RectXor) +#define cfb8LineSS1RectGeneral NAME(LineSS1RectGeneral ) +#define cfb8LineSS1RectPreviousCopy NAME(LineSS1RectPreviousCopy) +#define cfbZeroPolyArcSS8Copy NAME(ZeroPolyArcSSCopy) +#define cfbZeroPolyArcSS8Xor NAME(ZeroPolyArcSSXor) +#define cfbZeroPolyArcSS8General NAME(ZeroPolyArcSSGeneral) + +#endif /* PSZ != 8 */ diff --git a/cfb/cfbmskbits.c b/cfb/cfbmskbits.c new file mode 100644 index 000000000..4c26e3576 --- /dev/null +++ b/cfb/cfbmskbits.c @@ -0,0 +1,1210 @@ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ + +/* $Xorg: cfbmskbits.c,v 1.3 2000/08/17 19:48:14 cpqbld Exp $ */ + +/* + * ========================================================================== + * Converted to Color Frame Buffer by smarks@sun, April-May 1987. The "bit + * numbering" in the doc below really means "byte numbering" now. + * ========================================================================== + */ + +/* + these tables are used by several macros in the cfb code. + + the vax numbers everything left to right, so bit indices on the +screen match bit indices in longwords. the pc-rt and Sun number +bits on the screen the way they would be written on paper, +(i.e. msb to the left), and so a bit index n on the screen is +bit index 32-n in a longword + + see also cfbmskbits.h +*/ +#include +#include +#include +#include "cfb.h" +#include "cfbmskbits.h" + +#define _cfbBits(a) (PixelGroup)(a) + +#if (BITMAP_BIT_ORDER == MSBFirst) +#define cfbBits(v) _cfbBits(v) +#else /* BITMAP_BIT_ORDER == LSBFirst */ +#define cfbFlip2(a) ((((a) & 0x1) << 1) | (((a) & 0x2) >> 1)) +#define cfbFlip4(a) ((cfbFlip2(a) << 2) | cfbFlip2(a >> 2)) +#define cfbFlip8(a) ((cfbFlip4(a) << 4) | cfbFlip4(a >> 4)) +#define cfbFlip16(a) ((cfbFlip8(a) << 8) | cfbFlip8(a >> 8)) +#define cfbFlip32(a) ((cfbFlip16(a) << 16) | cfbFlip16(a >> 16)) +#if PGSZ == 32 +#define cfbBits(a) cfbFlip32(_cfbBits(a)) +#else /* PGSZ == 64 */ +#define cfbFlip64(a) ((cfbFlip32(a) << 32) | cfbFlip32(a >> 32)) +#define cfbBits(a) cfbFlip64(_cfbBits(a)) +#endif /* PGSZ */ +#endif /* BITMAP_BIT_ORDER */ + +/* NOTE: +the first element in starttab could be 0xffffffff. making it 0 +lets us deal with a full first word in the middle loop, rather +than having to do the multiple reads and masks that we'd +have to do if we thought it was partial. +*/ +#if PSZ == 4 +#if PGSZ == 32 +PixelGroup cfbstarttab[] = + { + cfbBits(0x00000000), + cfbBits(0x0FFFFFFF), + cfbBits(0x00FFFFFF), + cfbBits(0x000FFFFF), + cfbBits(0x0000FFFF), + cfbBits(0x00000FFF), + cfbBits(0x000000FF), + cfbBits(0x0000000F) + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x00000000), + cfbBits(0xF0000000), + cfbBits(0xFF000000), + cfbBits(0xFFF00000), + cfbBits(0xFFFF0000), + cfbBits(0xFFFFF000), + cfbBits(0xFFFFFF00), + cfbBits(0xFFFFFFF0) + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstarttab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0x0FFFFFFFFFFFFFFF), + cfbBits(0x00FFFFFFFFFFFFFF), + cfbBits(0x000FFFFFFFFFFFFF), + cfbBits(0x0000FFFFFFFFFFFF), + cfbBits(0x00000FFFFFFFFFFF), + cfbBits(0x000000FFFFFFFFFF), + cfbBits(0x0000000FFFFFFFFF), + cfbBits(0x00000000FFFFFFFF), + cfbBits(0x000000000FFFFFFF), + cfbBits(0x0000000000FFFFFF), + cfbBits(0x00000000000FFFFF), + cfbBits(0x000000000000FFFF), + cfbBits(0x0000000000000FFF), + cfbBits(0x00000000000000FF), + cfbBits(0x000000000000000F), + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0xF000000000000000), + cfbBits(0xFF00000000000000), + cfbBits(0xFFF0000000000000), + cfbBits(0xFFFF000000000000), + cfbBits(0xFFFFF00000000000), + cfbBits(0xFFFFFF0000000000), + cfbBits(0xFFFFFFF000000000), + cfbBits(0xFFFFFFFF00000000), + cfbBits(0xFFFFFFFFF0000000), + cfbBits(0xFFFFFFFFFF000000), + cfbBits(0xFFFFFFFFFFF00000), + cfbBits(0xFFFFFFFFFFFF0000), + cfbBits(0xFFFFFFFFFFFFF000), + cfbBits(0xFFFFFFFFFFFFFF00), + cfbBits(0xFFFFFFFFFFFFFFF0), + }; +#endif /* PGSZ */ +#endif /* PSZ == 4 */ + +#if PSZ == 8 +#if PGSZ == 32 +PixelGroup cfbstarttab[] = + { + cfbBits(0x00000000), + cfbBits(0x00FFFFFF), + cfbBits(0x0000FFFF), + cfbBits(0x000000FF) + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x00000000), + cfbBits(0xFF000000), + cfbBits(0xFFFF0000), + cfbBits(0xFFFFFF00) + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstarttab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0x00FFFFFFFFFFFFFF), + cfbBits(0x0000FFFFFFFFFFFF), + cfbBits(0x000000FFFFFFFFFF), + cfbBits(0x00000000FFFFFFFF), + cfbBits(0x0000000000FFFFFF), + cfbBits(0x000000000000FFFF), + cfbBits(0x00000000000000FF) + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0xFF00000000000000), + cfbBits(0xFFFF000000000000), + cfbBits(0xFFFFFF0000000000), + cfbBits(0xFFFFFFFF00000000), + cfbBits(0xFFFFFFFFFF000000), + cfbBits(0xFFFFFFFFFFFF0000), + cfbBits(0xFFFFFFFFFFFFFF00) + }; +#endif /* PGSZ */ +#endif /* PSZ == 8 */ + +#if PSZ == 16 +#if PGSZ == 32 +PixelGroup cfbstarttab[] = + { + cfbBits(0x00000000), + cfbBits(0x0000FFFF), + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x00000000), + cfbBits(0xFFFF0000), + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstarttab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0x0000FFFFFFFFFFFF), + cfbBits(0x00000000FFFFFFFF), + cfbBits(0x000000000000FFFF), + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0xFFFF000000000000), + cfbBits(0xFFFFFFFF00000000), + cfbBits(0xFFFFFFFFFFFF0000), + }; +#endif /* PGSZ */ +#endif + +#if PSZ == 32 +#if PGSZ == 32 +PixelGroup cfbstarttab[] = + { + cfbBits(0x00000000), + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x00000000), + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstarttab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0x00000000FFFFFFFF), + }; +PixelGroup cfbendtab[] = + { + cfbBits(0x0000000000000000), + cfbBits(0xFFFFFFFF00000000), + }; +#endif /* PGSZ */ +#endif /* PSZ == 32 */ + +/* a hack, for now, since the entries for 0 need to be all + 1 bits, not all zeros. + this means the code DOES NOT WORK for segments of length + 0 (which is only a problem in the horizontal line code.) +*/ +#if PSZ == 4 +#if PGSZ == 32 +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFF), + cfbBits(0x0FFFFFFF), + cfbBits(0x00FFFFFF), + cfbBits(0x000FFFFF), + cfbBits(0x0000FFFF), + cfbBits(0x00000FFF), + cfbBits(0x000000FF), + cfbBits(0x0000000F) + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFF), + cfbBits(0xF0000000), + cfbBits(0xFF000000), + cfbBits(0xFFF00000), + cfbBits(0xFFFF0000), + cfbBits(0xFFFFF000), + cfbBits(0xFFFFFF00), + cfbBits(0xFFFFFFF0) + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0x0FFFFFFFFFFFFFFF), + cfbBits(0x00FFFFFFFFFFFFFF), + cfbBits(0x000FFFFFFFFFFFFF), + cfbBits(0x0000FFFFFFFFFFFF), + cfbBits(0x00000FFFFFFFFFFF), + cfbBits(0x000000FFFFFFFFFF), + cfbBits(0x0000000FFFFFFFFF), + cfbBits(0x00000000FFFFFFFF), + cfbBits(0x000000000FFFFFFF), + cfbBits(0x0000000000FFFFFF), + cfbBits(0x00000000000FFFFF), + cfbBits(0x000000000000FFFF), + cfbBits(0x0000000000000FFF), + cfbBits(0x00000000000000FF), + cfbBits(0x000000000000000F), + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0xF000000000000000), + cfbBits(0xFF00000000000000), + cfbBits(0xFFF0000000000000), + cfbBits(0xFFFF000000000000), + cfbBits(0xFFFFF00000000000), + cfbBits(0xFFFFFF0000000000), + cfbBits(0xFFFFFFF000000000), + cfbBits(0xFFFFFFFF00000000), + cfbBits(0xFFFFFFFFF0000000), + cfbBits(0xFFFFFFFFFF000000), + cfbBits(0xFFFFFFFFFFF00000), + cfbBits(0xFFFFFFFFFFFF0000), + cfbBits(0xFFFFFFFFFFFFF000), + cfbBits(0xFFFFFFFFFFFFFF00), + cfbBits(0xFFFFFFFFFFFFFFF0), + }; +#endif /* PGSZ */ +#endif /* PSZ == 4 */ + +#if PSZ == 8 +#if PGSZ == 32 +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFF), + cfbBits(0x00FFFFFF), + cfbBits(0x0000FFFF), + cfbBits(0x000000FF) + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFF), + cfbBits(0xFF000000), + cfbBits(0xFFFF0000), + cfbBits(0xFFFFFF00) + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0x00FFFFFFFFFFFFFF), + cfbBits(0x0000FFFFFFFFFFFF), + cfbBits(0x000000FFFFFFFFFF), + cfbBits(0x00000000FFFFFFFF), + cfbBits(0x0000000000FFFFFF), + cfbBits(0x000000000000FFFF), + cfbBits(0x00000000000000FF), + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0xFF00000000000000), + cfbBits(0xFFFF000000000000), + cfbBits(0xFFFFFF0000000000), + cfbBits(0xFFFFFFFF00000000), + cfbBits(0xFFFFFFFFFF000000), + cfbBits(0xFFFFFFFFFFFF0000), + cfbBits(0xFFFFFFFFFFFFFF00), + }; +#endif /* PGSZ */ +#endif /* PSZ == 8 */ + +#if PSZ == 16 +#if PGSZ == 32 +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFF), + cfbBits(0x0000FFFF), + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFF), + cfbBits(0xFFFF0000), + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0x0000FFFFFFFFFFFF), + cfbBits(0x00000000FFFFFFFF), + cfbBits(0x000000000000FFFF), + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0xFFFF000000000000), + cfbBits(0xFFFFFFFF00000000), + cfbBits(0xFFFFFFFFFFFF0000), + }; +#endif /* PGSZ */ +#endif /* PSZ == 16 */ + +#if PSZ == 32 +#if PGSZ == 32 +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFF), + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFF), + }; +#else /* PGSZ == 64 */ +PixelGroup cfbstartpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0x00000000FFFFFFFF), + }; + +PixelGroup cfbendpartial[] = + { + cfbBits(0xFFFFFFFFFFFFFFFF), + cfbBits(0xFFFFFFFF00000000), + }; +#endif /* PGSZ */ +#endif /* PSZ == 32 */ + +/* used for masking bits in bresenham lines + mask[n] is used to mask out all but bit n in a longword (n is a +screen position). + rmask[n] is used to mask out the single bit at position n (n +is a screen posiotion.) +*/ + +#if PSZ == 4 +#if PGSZ == 32 +PixelGroup cfbmask[] = + { + cfbBits(0xF0000000), + cfbBits(0x0F000000), + cfbBits(0x00F00000), + cfbBits(0x000F0000), + cfbBits(0x0000F000), + cfbBits(0x00000F00), + cfbBits(0x000000F0), + cfbBits(0x0000000F) + }; +PixelGroup cfbrmask[] = + { + cfbBits(0x0FFFFFFF), + cfbBits(0xF0FFFFFF), + cfbBits(0xFF0FFFFF), + cfbBits(0xFFF0FFFF), + cfbBits(0xFFFF0FFF), + cfbBits(0xFFFFF0FF), + cfbBits(0xFFFFFF0F), + cfbBits(0xFFFFFFF0) + }; +#else /* PGSZ == 64 */ +PixelGroup cfbmask[] = + { + cfbBits(0xF000000000000000), + cfbBits(0x0F00000000000000), + cfbBits(0x00F0000000000000), + cfbBits(0x000F000000000000), + cfbBits(0x0000F00000000000), + cfbBits(0x00000F0000000000), + cfbBits(0x000000F000000000), + cfbBits(0x0000000F00000000), + cfbBits(0x00000000F0000000), + cfbBits(0x000000000F000000), + cfbBits(0x0000000000F00000), + cfbBits(0x00000000000F0000), + cfbBits(0x000000000000F000), + cfbBits(0x0000000000000F00), + cfbBits(0x00000000000000F0), + cfbBits(0x000000000000000F), + }; +PixelGroup cfbrmask[] = + { + cfbBits(0x0FFFFFFFFFFFFFFF), + cfbBits(0xF0FFFFFFFFFFFFFF), + cfbBits(0xFF0FFFFFFFFFFFFF), + cfbBits(0xFFF0FFFFFFFFFFFF), + cfbBits(0xFFFF0FFFFFFFFFFF), + cfbBits(0xFFFFF0FFFFFFFFFF), + cfbBits(0xFFFFFF0FFFFFFFFF), + cfbBits(0xFFFFFFF0FFFFFFFF), + cfbBits(0xFFFFFFFF0FFFFFFF), + cfbBits(0xFFFFFFFFF0FFFFFF), + cfbBits(0xFFFFFFFFFF0FFFFF), + cfbBits(0xFFFFFFFFFFF0FFFF), + cfbBits(0xFFFFFFFFFFFF0FFF), + cfbBits(0xFFFFFFFFFFFFF0FF), + cfbBits(0xFFFFFFFFFFFFFF0F), + cfbBits(0xFFFFFFFFFFFFFFF0), + }; +#endif /* PGSZ */ +#endif /* PSZ == 4 */ + +#if PSZ == 8 +#if PGSZ == 32 +PixelGroup cfbmask[] = + { + cfbBits(0xFF000000), + cfbBits(0x00FF0000), + cfbBits(0x0000FF00), + cfbBits(0x000000FF) + }; +PixelGroup cfbrmask[] = + { + cfbBits(0x00FFFFFF), + cfbBits(0xFF00FFFF), + cfbBits(0xFFFF00FF), + cfbBits(0xFFFFFF00) + }; +#else /* PGSZ == 64 */ +PixelGroup cfbmask[] = + { + cfbBits(0xFF00000000000000), + cfbBits(0x00FF000000000000), + cfbBits(0x0000FF0000000000), + cfbBits(0x000000FF00000000), + cfbBits(0x00000000FF000000), + cfbBits(0x0000000000FF0000), + cfbBits(0x000000000000FF00), + cfbBits(0x00000000000000FF), + }; +PixelGroup cfbrmask[] = + { + cfbBits(0x00FFFFFFFFFFFFFF), + cfbBits(0xFF00FFFFFFFFFFFF), + cfbBits(0xFFFF00FFFFFFFFFF), + cfbBits(0xFFFFFF00FFFFFFFF), + cfbBits(0xFFFFFFFF00FFFFFF), + cfbBits(0xFFFFFFFFFF00FFFF), + cfbBits(0xFFFFFFFFFFFF00FF), + cfbBits(0xFFFFFFFFFFFFFF00), + }; +#endif /* PGSZ */ +#endif /* PSZ == 8 */ + +#if PSZ == 16 +#if PGSZ == 32 +PixelGroup cfbmask[] = + { + cfbBits(0xFFFF0000), + cfbBits(0x0000FFFF), + }; +PixelGroup cfbrmask[] = + { + cfbBits(0x0000FFFF), + cfbBits(0xFFFF0000), + }; +#else /* PGSZ == 64 */ +PixelGroup cfbmask[] = + { + cfbBits(0xFFFF000000000000), + cfbBits(0x0000FFFF00000000), + cfbBits(0x00000000FFFF0000), + cfbBits(0x000000000000FFFF), + }; +PixelGroup cfbrmask[] = + { + cfbBits(0x0000FFFFFFFFFFFF), + cfbBits(0xFFFF0000FFFFFFFF), + cfbBits(0xFFFFFFFF0000FFFF), + cfbBits(0xFFFFFFFFFFFF0000), + }; +#endif /* PGSZ */ +#endif /* PSZ == 16 */ + +#if PSZ == 32 +#if PGSZ == 32 +PixelGroup cfbmask[] = + { + cfbBits(0xFFFFFFFF), + }; +PixelGroup cfbrmask[] = + { + cfbBits(0xFFFFFFFF), + }; +#else /* PGSZ == 64 */ +PixelGroup cfbmask[] = + { + cfbBits(0xFFFFFFFF00000000), + cfbBits(0x00000000FFFFFFFF), + }; +PixelGroup cfbrmask[] = + { + cfbBits(0x00000000FFFFFFFF), + cfbBits(0xFFFFFFFF00000000), + }; +#endif /* PGSZ */ +#endif /* PSZ == 32 */ + +/* + * QuartetBitsTable contains PPW+1 masks whose binary values are masks in the + * low order quartet that contain the number of bits specified in the + * index. This table is used by getstipplepixels. + */ +#if PSZ == 4 +PixelGroup QuartetBitsTable[] = { +#if PGSZ == 32 +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 00000000 */ + 0x00000080, /* 1 - 10000000 */ + 0x000000C0, /* 2 - 11000000 */ + 0x000000E0, /* 3 - 11100000 */ + 0x000000F0, /* 4 - 11110000 */ + 0x000000F8, /* 5 - 11111000 */ + 0x000000FC, /* 6 - 11111100 */ + 0x000000FE, /* 7 - 11111110 */ + 0x000000FF /* 8 - 11111111 */ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 00000000 */ + 0x00000001, /* 1 - 00000001 */ + 0x00000003, /* 2 - 00000011 */ + 0x00000007, /* 3 - 00000111 */ + 0x0000000F, /* 4 - 00001111 */ + 0x0000001F, /* 5 - 00011111 */ + 0x0000003F, /* 6 - 00111111 */ + 0x0000007F, /* 7 - 01111111 */ + 0x000000FF /* 8 - 11111111 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#else /* PGSZ == 64 */ +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 0000000000000000 */ + 0x00008000, /* 1 - 1000000000000000 */ + 0x0000C000, /* 2 - 1100000000000000 */ + 0x0000E000, /* 3 - 1110000000000000 */ + 0x0000F000, /* 4 - 1111000000000000 */ + 0x0000F800, /* 5 - 1111100000000000 */ + 0x0000FC00, /* 6 - 1111110000000000 */ + 0x0000FE00, /* 7 - 1111111000000000 */ + 0x0000FF00, /* 8 - 1111111100000000 */ + 0x0000FF80, /* 9 - 1111111110000000 */ + 0x0000FFC0, /* 10- 1111111111000000 */ + 0x0000FFE0, /* 11- 1111111111100000 */ + 0x0000FFF0, /* 12- 1111111111110000 */ + 0x0000FFF8, /* 13- 1111111111111000 */ + 0x0000FFFC, /* 14- 1111111111111100 */ + 0x0000FFFE, /* 15- 1111111111111110 */ + 0x0000FFFF, /* 16- 1111111111111111 */ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 0000000000000000 */ + 0x00000001, /* 1 - 0000000000000001 */ + 0x00000003, /* 2 - 0000000000000011 */ + 0x00000007, /* 3 - 0000000000000111 */ + 0x0000000F, /* 4 - 0000000000001111 */ + 0x0000001F, /* 5 - 0000000000011111 */ + 0x0000003F, /* 6 - 0000000000111111 */ + 0x0000007F, /* 7 - 0000000001111111 */ + 0x000000FF, /* 8 - 0000000011111111 */ + 0x000001FF, /* 9 - 0000000111111111 */ + 0x000003FF, /* 10- 0000001111111111 */ + 0x000007FF, /* 11- 0000011111111111 */ + 0x00000FFF, /* 12- 0000111111111111 */ + 0x00001FFF, /* 13- 0001111111111111 */ + 0x00003FFF, /* 14- 0011111111111111 */ + 0x00007FFF, /* 15- 0111111111111111 */ + 0x0000FFFF, /* 16- 1111111111111111 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#endif /* PGSZ */ +}; +#endif /* PSZ == 4 */ + +#if PSZ == 8 +PixelGroup QuartetBitsTable[] = { +#if PGSZ == 32 +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 0000 */ + 0x00000008, /* 1 - 1000 */ + 0x0000000C, /* 2 - 1100 */ + 0x0000000E, /* 3 - 1110 */ + 0x0000000F /* 4 - 1111 */ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 0000 */ + 0x00000001, /* 1 - 0001 */ + 0x00000003, /* 2 - 0011 */ + 0x00000007, /* 3 - 0111 */ + 0x0000000F /* 4 - 1111 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#else /* PGSZ == 64 */ +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 00000000 */ + 0x00000080, /* 1 - 10000000 */ + 0x000000C0, /* 2 - 11000000 */ + 0x000000E0, /* 3 - 11100000 */ + 0x000000F0, /* 4 - 11110000 */ + 0x000000F8, /* 5 - 11111000 */ + 0x000000FC, /* 6 - 11111100 */ + 0x000000FE, /* 7 - 11111110 */ + 0x000000FF /* 8 - 11111111 */ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 00000000 */ + 0x00000001, /* 1 - 00000001 */ + 0x00000003, /* 2 - 00000011 */ + 0x00000007, /* 3 - 00000111 */ + 0x0000000F, /* 4 - 10000111 */ + 0x0000001F, /* 5 - 00011111 */ + 0x0000003F, /* 6 - 00111111 */ + 0x0000007F, /* 7 - 01111111 */ + 0x000000FF /* 8 - 11111111 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#endif /* PGSZ */ +}; +#endif /* PSZ == 8 */ + +#if PSZ == 16 +PixelGroup QuartetBitsTable[] = { +#if PGSZ == 32 +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 00 */ + 0x00000002, /* 1 - 10 */ + 0x00000003, /* 2 - 11 */ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 00 */ + 0x00000001, /* 1 - 01 */ + 0x00000003, /* 2 - 11 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#else /* PGSZ == 64 */ +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 0000 */ + 0x00000008, /* 1 - 1000 */ + 0x0000000C, /* 2 - 1100 */ + 0x0000000E, /* 3 - 1110 */ + 0x0000000F, /* 4 - 1111 */ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 0000 */ + 0x00000001, /* 1 - 0001 */ + 0x00000003, /* 2 - 0011 */ + 0x00000007, /* 3 - 0111 */ + 0x0000000F, /* 4 - 1111 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#endif /* PGSZ */ +}; +#endif /* PSZ == 16 */ + +#if PSZ == 32 +PixelGroup QuartetBitsTable[] = { +#if PGSZ == 32 +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 0 */ + 0x00000001, /* 1 - 1 */ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 0 */ + 0x00000001, /* 1 - 1 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#else /* PGSZ == 64 */ +#if (BITMAP_BIT_ORDER == MSBFirst) + 0x00000000, /* 0 - 00 */ + 0x00000002, /* 1 - 10 */ + 0x00000003, /* 2 - 11*/ +#else /* (BITMAP_BIT_ORDER == LSBFirst */ + 0x00000000, /* 0 - 00 */ + 0x00000001, /* 1 - 01 */ + 0x00000003, /* 2 - 11 */ +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ +#endif /* PGSZ */ +}; +#endif /* PSZ == 32 */ + +/* + * QuartetPixelMaskTable is used by getstipplepixels to get a pixel mask + * corresponding to a quartet of bits. Note: the bit/byte order dependency + * is handled by QuartetBitsTable above. + */ +#if PSZ == 4 +#if PGSZ == 32 +PixelGroup QuartetPixelMaskTable[] = { + 0x00000000, + 0x0000000F, + 0x000000F0, + 0x000000FF, + 0x00000F00, + 0x00000F0F, + 0x00000FF0, + 0x00000FFF, + 0x0000F000, + 0x0000F00F, + 0x0000F0F0, + 0x0000F0FF, + 0x0000FF00, + 0x0000FF0F, + 0x0000FFF0, + 0x0000FFFF, + 0x000F0000, + 0x000F000F, + 0x000F00F0, + 0x000F00FF, + 0x000F0F00, + 0x000F0F0F, + 0x000F0FF0, + 0x000F0FFF, + 0x000FF000, + 0x000FF00F, + 0x000FF0F0, + 0x000FF0FF, + 0x000FFF00, + 0x000FFF0F, + 0x000FFFF0, + 0x000FFFFF, + 0x00F00000, + 0x00F0000F, + 0x00F000F0, + 0x00F000FF, + 0x00F00F00, + 0x00F00F0F, + 0x00F00FF0, + 0x00F00FFF, + 0x00F0F000, + 0x00F0F00F, + 0x00F0F0F0, + 0x00F0F0FF, + 0x00F0FF00, + 0x00F0FF0F, + 0x00F0FFF0, + 0x00F0FFFF, + 0x00FF0000, + 0x00FF000F, + 0x00FF00F0, + 0x00FF00FF, + 0x00FF0F00, + 0x00FF0F0F, + 0x00FF0FF0, + 0x00FF0FFF, + 0x00FFF000, + 0x00FFF00F, + 0x00FFF0F0, + 0x00FFF0FF, + 0x00FFFF00, + 0x00FFFF0F, + 0x00FFFFF0, + 0x00FFFFFF, + 0x0F000000, + 0x0F00000F, + 0x0F0000F0, + 0x0F0000FF, + 0x0F000F00, + 0x0F000F0F, + 0x0F000FF0, + 0x0F000FFF, + 0x0F00F000, + 0x0F00F00F, + 0x0F00F0F0, + 0x0F00F0FF, + 0x0F00FF00, + 0x0F00FF0F, + 0x0F00FFF0, + 0x0F00FFFF, + 0x0F0F0000, + 0x0F0F000F, + 0x0F0F00F0, + 0x0F0F00FF, + 0x0F0F0F00, + 0x0F0F0F0F, + 0x0F0F0FF0, + 0x0F0F0FFF, + 0x0F0FF000, + 0x0F0FF00F, + 0x0F0FF0F0, + 0x0F0FF0FF, + 0x0F0FFF00, + 0x0F0FFF0F, + 0x0F0FFFF0, + 0x0F0FFFFF, + 0x0FF00000, + 0x0FF0000F, + 0x0FF000F0, + 0x0FF000FF, + 0x0FF00F00, + 0x0FF00F0F, + 0x0FF00FF0, + 0x0FF00FFF, + 0x0FF0F000, + 0x0FF0F00F, + 0x0FF0F0F0, + 0x0FF0F0FF, + 0x0FF0FF00, + 0x0FF0FF0F, + 0x0FF0FFF0, + 0x0FF0FFFF, + 0x0FFF0000, + 0x0FFF000F, + 0x0FFF00F0, + 0x0FFF00FF, + 0x0FFF0F00, + 0x0FFF0F0F, + 0x0FFF0FF0, + 0x0FFF0FFF, + 0x0FFFF000, + 0x0FFFF00F, + 0x0FFFF0F0, + 0x0FFFF0FF, + 0x0FFFFF00, + 0x0FFFFF0F, + 0x0FFFFFF0, + 0x0FFFFFFF, + 0xF0000000, + 0xF000000F, + 0xF00000F0, + 0xF00000FF, + 0xF0000F00, + 0xF0000F0F, + 0xF0000FF0, + 0xF0000FFF, + 0xF000F000, + 0xF000F00F, + 0xF000F0F0, + 0xF000F0FF, + 0xF000FF00, + 0xF000FF0F, + 0xF000FFF0, + 0xF000FFFF, + 0xF00F0000, + 0xF00F000F, + 0xF00F00F0, + 0xF00F00FF, + 0xF00F0F00, + 0xF00F0F0F, + 0xF00F0FF0, + 0xF00F0FFF, + 0xF00FF000, + 0xF00FF00F, + 0xF00FF0F0, + 0xF00FF0FF, + 0xF00FFF00, + 0xF00FFF0F, + 0xF00FFFF0, + 0xF00FFFFF, + 0xF0F00000, + 0xF0F0000F, + 0xF0F000F0, + 0xF0F000FF, + 0xF0F00F00, + 0xF0F00F0F, + 0xF0F00FF0, + 0xF0F00FFF, + 0xF0F0F000, + 0xF0F0F00F, + 0xF0F0F0F0, + 0xF0F0F0FF, + 0xF0F0FF00, + 0xF0F0FF0F, + 0xF0F0FFF0, + 0xF0F0FFFF, + 0xF0FF0000, + 0xF0FF000F, + 0xF0FF00F0, + 0xF0FF00FF, + 0xF0FF0F00, + 0xF0FF0F0F, + 0xF0FF0FF0, + 0xF0FF0FFF, + 0xF0FFF000, + 0xF0FFF00F, + 0xF0FFF0F0, + 0xF0FFF0FF, + 0xF0FFFF00, + 0xF0FFFF0F, + 0xF0FFFFF0, + 0xF0FFFFFF, + 0xFF000000, + 0xFF00000F, + 0xFF0000F0, + 0xFF0000FF, + 0xFF000F00, + 0xFF000F0F, + 0xFF000FF0, + 0xFF000FFF, + 0xFF00F000, + 0xFF00F00F, + 0xFF00F0F0, + 0xFF00F0FF, + 0xFF00FF00, + 0xFF00FF0F, + 0xFF00FFF0, + 0xFF00FFFF, + 0xFF0F0000, + 0xFF0F000F, + 0xFF0F00F0, + 0xFF0F00FF, + 0xFF0F0F00, + 0xFF0F0F0F, + 0xFF0F0FF0, + 0xFF0F0FFF, + 0xFF0FF000, + 0xFF0FF00F, + 0xFF0FF0F0, + 0xFF0FF0FF, + 0xFF0FFF00, + 0xFF0FFF0F, + 0xFF0FFFF0, + 0xFF0FFFFF, + 0xFFF00000, + 0xFFF0000F, + 0xFFF000F0, + 0xFFF000FF, + 0xFFF00F00, + 0xFFF00F0F, + 0xFFF00FF0, + 0xFFF00FFF, + 0xFFF0F000, + 0xFFF0F00F, + 0xFFF0F0F0, + 0xFFF0F0FF, + 0xFFF0FF00, + 0xFFF0FF0F, + 0xFFF0FFF0, + 0xFFF0FFFF, + 0xFFFF0000, + 0xFFFF000F, + 0xFFFF00F0, + 0xFFFF00FF, + 0xFFFF0F00, + 0xFFFF0F0F, + 0xFFFF0FF0, + 0xFFFF0FFF, + 0xFFFFF000, + 0xFFFFF00F, + 0xFFFFF0F0, + 0xFFFFF0FF, + 0xFFFFFF00, + 0xFFFFFF0F, + 0xFFFFFFF0, + 0xFFFFFFFF, +}; +#else /* PGSZ == 64 */ +No QuartetPixelMaskTable for psz=PSZ +this would be a 64K entry table, a bit much I think. +Try breaking things in two: +mask = table[index&0xff00]<<32 | table[index&0xff] +#endif /* PGSZ */ +#endif /* PSZ == 4 */ + +#if PSZ == 8 +PixelGroup QuartetPixelMaskTable[] = { +#if PGSZ == 32 + 0x00000000, + 0x000000FF, + 0x0000FF00, + 0x0000FFFF, + 0x00FF0000, + 0x00FF00FF, + 0x00FFFF00, + 0x00FFFFFF, + 0xFF000000, + 0xFF0000FF, + 0xFF00FF00, + 0xFF00FFFF, + 0xFFFF0000, + 0xFFFF00FF, + 0xFFFFFF00, + 0xFFFFFFFF +#else /* PGSZ == 64 */ + 0x0000000000000000, 0x00000000000000FF, + 0x000000000000FF00, 0x000000000000FFFF, + 0x0000000000FF0000, 0x0000000000FF00FF, + 0x0000000000FFFF00, 0x0000000000FFFFFF, + 0x00000000FF000000, 0x00000000FF0000FF, + 0x00000000FF00FF00, 0x00000000FF00FFFF, + 0x00000000FFFF0000, 0x00000000FFFF00FF, + 0x00000000FFFFFF00, 0x00000000FFFFFFFF, + 0x000000FF00000000, 0x000000FF000000FF, + 0x000000FF0000FF00, 0x000000FF0000FFFF, + 0x000000FF00FF0000, 0x000000FF00FF00FF, + 0x000000FF00FFFF00, 0x000000FF00FFFFFF, + 0x000000FFFF000000, 0x000000FFFF0000FF, + 0x000000FFFF00FF00, 0x000000FFFF00FFFF, + 0x000000FFFFFF0000, 0x000000FFFFFF00FF, + 0x000000FFFFFFFF00, 0x000000FFFFFFFFFF, + 0x0000FF0000000000, 0x0000FF00000000FF, + 0x0000FF000000FF00, 0x0000FF000000FFFF, + 0x0000FF0000FF0000, 0x0000FF0000FF00FF, + 0x0000FF0000FFFF00, 0x0000FF0000FFFFFF, + 0x0000FF00FF000000, 0x0000FF00FF0000FF, + 0x0000FF00FF00FF00, 0x0000FF00FF00FFFF, + 0x0000FF00FFFF0000, 0x0000FF00FFFF00FF, + 0x0000FF00FFFFFF00, 0x0000FF00FFFFFFFF, + 0x0000FFFF00000000, 0x0000FFFF000000FF, + 0x0000FFFF0000FF00, 0x0000FFFF0000FFFF, + 0x0000FFFF00FF0000, 0x0000FFFF00FF00FF, + 0x0000FFFF00FFFF00, 0x0000FFFF00FFFFFF, + 0x0000FFFFFF000000, 0x0000FFFFFF0000FF, + 0x0000FFFFFF00FF00, 0x0000FFFFFF00FFFF, + 0x0000FFFFFFFF0000, 0x0000FFFFFFFF00FF, + 0x0000FFFFFFFFFF00, 0x0000FFFFFFFFFFFF, + 0x00FF000000000000, 0x00FF0000000000FF, + 0x00FF00000000FF00, 0x00FF00000000FFFF, + 0x00FF000000FF0000, 0x00FF000000FF00FF, + 0x00FF000000FFFF00, 0x00FF000000FFFFFF, + 0x00FF0000FF000000, 0x00FF0000FF0000FF, + 0x00FF0000FF00FF00, 0x00FF0000FF00FFFF, + 0x00FF0000FFFF0000, 0x00FF0000FFFF00FF, + 0x00FF0000FFFFFF00, 0x00FF0000FFFFFFFF, + 0x00FF00FF00000000, 0x00FF00FF000000FF, + 0x00FF00FF0000FF00, 0x00FF00FF0000FFFF, + 0x00FF00FF00FF0000, 0x00FF00FF00FF00FF, + 0x00FF00FF00FFFF00, 0x00FF00FF00FFFFFF, + 0x00FF00FFFF000000, 0x00FF00FFFF0000FF, + 0x00FF00FFFF00FF00, 0x00FF00FFFF00FFFF, + 0x00FF00FFFFFF0000, 0x00FF00FFFFFF00FF, + 0x00FF00FFFFFFFF00, 0x00FF00FFFFFFFFFF, + 0x00FFFF0000000000, 0x00FFFF00000000FF, + 0x00FFFF000000FF00, 0x00FFFF000000FFFF, + 0x00FFFF0000FF0000, 0x00FFFF0000FF00FF, + 0x00FFFF0000FFFF00, 0x00FFFF0000FFFFFF, + 0x00FFFF00FF000000, 0x00FFFF00FF0000FF, + 0x00FFFF00FF00FF00, 0x00FFFF00FF00FFFF, + 0x00FFFF00FFFF0000, 0x00FFFF00FFFF00FF, + 0x00FFFF00FFFFFF00, 0x00FFFF00FFFFFFFF, + 0x00FFFFFF00000000, 0x00FFFFFF000000FF, + 0x00FFFFFF0000FF00, 0x00FFFFFF0000FFFF, + 0x00FFFFFF00FF0000, 0x00FFFFFF00FF00FF, + 0x00FFFFFF00FFFF00, 0x00FFFFFF00FFFFFF, + 0x00FFFFFFFF000000, 0x00FFFFFFFF0000FF, + 0x00FFFFFFFF00FF00, 0x00FFFFFFFF00FFFF, + 0x00FFFFFFFFFF0000, 0x00FFFFFFFFFF00FF, + 0x00FFFFFFFFFFFF00, 0x00FFFFFFFFFFFFFF, + 0xFF00000000000000, 0xFF000000000000FF, + 0xFF0000000000FF00, 0xFF0000000000FFFF, + 0xFF00000000FF0000, 0xFF00000000FF00FF, + 0xFF00000000FFFF00, 0xFF00000000FFFFFF, + 0xFF000000FF000000, 0xFF000000FF0000FF, + 0xFF000000FF00FF00, 0xFF000000FF00FFFF, + 0xFF000000FFFF0000, 0xFF000000FFFF00FF, + 0xFF000000FFFFFF00, 0xFF000000FFFFFFFF, + 0xFF0000FF00000000, 0xFF0000FF000000FF, + 0xFF0000FF0000FF00, 0xFF0000FF0000FFFF, + 0xFF0000FF00FF0000, 0xFF0000FF00FF00FF, + 0xFF0000FF00FFFF00, 0xFF0000FF00FFFFFF, + 0xFF0000FFFF000000, 0xFF0000FFFF0000FF, + 0xFF0000FFFF00FF00, 0xFF0000FFFF00FFFF, + 0xFF0000FFFFFF0000, 0xFF0000FFFFFF00FF, + 0xFF0000FFFFFFFF00, 0xFF0000FFFFFFFFFF, + 0xFF00FF0000000000, 0xFF00FF00000000FF, + 0xFF00FF000000FF00, 0xFF00FF000000FFFF, + 0xFF00FF0000FF0000, 0xFF00FF0000FF00FF, + 0xFF00FF0000FFFF00, 0xFF00FF0000FFFFFF, + 0xFF00FF00FF000000, 0xFF00FF00FF0000FF, + 0xFF00FF00FF00FF00, 0xFF00FF00FF00FFFF, + 0xFF00FF00FFFF0000, 0xFF00FF00FFFF00FF, + 0xFF00FF00FFFFFF00, 0xFF00FF00FFFFFFFF, + 0xFF00FFFF00000000, 0xFF00FFFF000000FF, + 0xFF00FFFF0000FF00, 0xFF00FFFF0000FFFF, + 0xFF00FFFF00FF0000, 0xFF00FFFF00FF00FF, + 0xFF00FFFF00FFFF00, 0xFF00FFFF00FFFFFF, + 0xFF00FFFFFF000000, 0xFF00FFFFFF0000FF, + 0xFF00FFFFFF00FF00, 0xFF00FFFFFF00FFFF, + 0xFF00FFFFFFFF0000, 0xFF00FFFFFFFF00FF, + 0xFF00FFFFFFFFFF00, 0xFF00FFFFFFFFFFFF, + 0xFFFF000000000000, 0xFFFF0000000000FF, + 0xFFFF00000000FF00, 0xFFFF00000000FFFF, + 0xFFFF000000FF0000, 0xFFFF000000FF00FF, + 0xFFFF000000FFFF00, 0xFFFF000000FFFFFF, + 0xFFFF0000FF000000, 0xFFFF0000FF0000FF, + 0xFFFF0000FF00FF00, 0xFFFF0000FF00FFFF, + 0xFFFF0000FFFF0000, 0xFFFF0000FFFF00FF, + 0xFFFF0000FFFFFF00, 0xFFFF0000FFFFFFFF, + 0xFFFF00FF00000000, 0xFFFF00FF000000FF, + 0xFFFF00FF0000FF00, 0xFFFF00FF0000FFFF, + 0xFFFF00FF00FF0000, 0xFFFF00FF00FF00FF, + 0xFFFF00FF00FFFF00, 0xFFFF00FF00FFFFFF, + 0xFFFF00FFFF000000, 0xFFFF00FFFF0000FF, + 0xFFFF00FFFF00FF00, 0xFFFF00FFFF00FFFF, + 0xFFFF00FFFFFF0000, 0xFFFF00FFFFFF00FF, + 0xFFFF00FFFFFFFF00, 0xFFFF00FFFFFFFFFF, + 0xFFFFFF0000000000, 0xFFFFFF00000000FF, + 0xFFFFFF000000FF00, 0xFFFFFF000000FFFF, + 0xFFFFFF0000FF0000, 0xFFFFFF0000FF00FF, + 0xFFFFFF0000FFFF00, 0xFFFFFF0000FFFFFF, + 0xFFFFFF00FF000000, 0xFFFFFF00FF0000FF, + 0xFFFFFF00FF00FF00, 0xFFFFFF00FF00FFFF, + 0xFFFFFF00FFFF0000, 0xFFFFFF00FFFF00FF, + 0xFFFFFF00FFFFFF00, 0xFFFFFF00FFFFFFFF, + 0xFFFFFFFF00000000, 0xFFFFFFFF000000FF, + 0xFFFFFFFF0000FF00, 0xFFFFFFFF0000FFFF, + 0xFFFFFFFF00FF0000, 0xFFFFFFFF00FF00FF, + 0xFFFFFFFF00FFFF00, 0xFFFFFFFF00FFFFFF, + 0xFFFFFFFFFF000000, 0xFFFFFFFFFF0000FF, + 0xFFFFFFFFFF00FF00, 0xFFFFFFFFFF00FFFF, + 0xFFFFFFFFFFFF0000, 0xFFFFFFFFFFFF00FF, + 0xFFFFFFFFFFFFFF00, 0xFFFFFFFFFFFFFFFF, +#endif /* PGSZ */ +}; +#endif /* PSZ == 8 */ + +#if PSZ == 16 +PixelGroup QuartetPixelMaskTable[] = { +#if PGSZ == 32 + 0x00000000, + 0x0000FFFF, + 0xFFFF0000, + 0xFFFFFFFF, +#else /* PGSZ == 64 */ + 0x0000000000000000, 0x000000000000FFFF, + 0x00000000FFFF0000, 0x00000000FFFFFFFF, + 0x0000FFFF00000000, 0x0000FFFF0000FFFF, + 0x0000FFFFFFFF0000, 0x0000FFFFFFFFFFFF, + 0xFFFF000000000000, 0xFFFF00000000FFFF, + 0xFFFF0000FFFF0000, 0xFFFF0000FFFFFFFF, + 0xFFFFFFFF00000000, 0xFFFFFFFF0000FFFF, + 0xFFFFFFFFFFFF0000, 0xFFFFFFFFFFFFFFFF, +#endif /* PGSZ */ +}; +#endif /* PSZ == 16 */ + +#if PSZ == 32 +PixelGroup QuartetPixelMaskTable[] = { +#if PGSZ == 32 + 0x00000000, + 0xFFFFFFFF, +#else /* PGSZ == 64 */ + 0x0000000000000000, + 0x00000000FFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFFFFFFFFFFFFFF +#endif /* PGSZ */ +}; +#endif /* PSZ == 32 */ diff --git a/cfb/cfbmskbits.h b/cfb/cfbmskbits.h new file mode 100644 index 000000000..7de664157 --- /dev/null +++ b/cfb/cfbmskbits.h @@ -0,0 +1,672 @@ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ + +/* $Xorg: cfbmskbits.h,v 1.3 2000/08/17 19:48:14 cpqbld Exp $ */ +/* Optimizations for PSZ == 32 added by Kyle Marvin (marvin@vitec.com) */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" + +/* + * ========================================================================== + * Converted from mfb to support memory-mapped color framebuffer by smarks@sun, + * April-May 1987. + * + * The way I did the conversion was to consider each longword as an + * array of four bytes instead of an array of 32 one-bit pixels. So + * getbits() and putbits() retain much the same calling sequence, but + * they move bytes around instead of bits. Of course, this entails the + * removal of all of the one-bit-pixel dependencies from the other + * files, but the major bit-hacking stuff should be covered here. + * + * I've created some new macros that make it easier to understand what's + * going on in the pixel calculations, and that make it easier to change the + * pixel size. + * + * name explanation + * ---- ----------- + * PSZ pixel size (in bits) + * PGSZ pixel group size (in bits) + * PGSZB pixel group size (in bytes) + * PGSZBMSK mask with lowest PGSZB bits set to 1 + * PPW pixels per word (pixels per pixel group) + * PPWMSK mask with lowest PPW bits set to 1 + * PLST index of last pixel in a word (should be PPW-1) + * PIM pixel index mask (index within a pixel group) + * PWSH pixel-to-word shift (should be log2(PPW)) + * PMSK mask with lowest PSZ bits set to 1 + * + * + * Here are some sample values. In the notation cfbA,B: A is PSZ, and + * B is PGSZB. All the other values are derived from these + * two. This table does not show all combinations! + * + * name cfb8,4 cfb32,4 cfb8,8 cfb32,8 + * ---- ------ ------- ------ ------- + * PSZ 8 32 8 32 + * PGSZ 32 32 64 64 + * PGSZB 4 4 8 8 + * PGSZBMSK 0xF 0xF 0xFF 0xFF + * PPW 4 1 8 2 + * PPWMSK 0xF 0x1 0xFF 0x3 + * PLST 3 0 7 1 + * PIM 0x3 0x0 0x7 0x1 + * PWSH 2 0 3 1 + * PMSK 0xFF 0xFFFFFFFF 0xFF 0xFFFFFFFF + * + * + * I have also added a new macro, PFILL, that takes one pixel and + * replicates it throughout a word. This macro definition is dependent + * upon pixel and word size; it doesn't use macros like PPW and so + * forth. Examples: for monochrome, PFILL(1) => 0xffffffff, PFILL(0) => + * 0x00000000. For 8-bit color, PFILL(0x5d) => 0x5d5d5d5d. This macro + * is used primarily for replicating a plane mask into a word. + * + * Color framebuffers operations also support the notion of a plane + * mask. This mask determines which planes of the framebuffer can be + * altered; the others are left unchanged. I have added another + * parameter to the putbits and putbitsrop macros that is the plane + * mask. + * ========================================================================== + */ + +/* + * PSZ needs to be defined before we get here. Usually it comes from a + * -DPSZ=foo on the compilation command line. + */ + +/* + * PixelGroup is the data type used to operate on groups of pixels. + * We typedef it here to unsigned long with the assumption that you + * want to manipulate as many pixels at a time as you can. If unsigned + * long is not appropriate for your server, define it to something else + * before including this file. In this case you will also have to define + * PGSZB to the size in bytes of PixelGroup. + */ +#ifndef PixelGroup +typedef unsigned long PixelGroup; +#ifdef LONG64 +#define PGSZB 8 +#else +#define PGSZB 4 +#endif /* LONG64 */ +#endif /* PixelGroup */ + +#define PGSZ (PGSZB << 3) +#define PPW (PGSZ/PSZ) +#define PLST (PPW-1) +#define PIM PLST +#define PMSK (((PixelGroup)1 << PSZ) - 1) +#define PPWMSK (((PixelGroup)1 << PPW) - 1) /* instead of BITMSK */ +#define PGSZBMSK (((PixelGroup)1 << PGSZB) - 1) + +/* set PWSH = log2(PPW) using brute force */ + +#if PPW == 1 +#define PWSH 0 +#else +#if PPW == 2 +#define PWSH 1 +#else +#if PPW == 4 +#define PWSH 2 +#else +#if PPW == 8 +#define PWSH 3 +#else +#if PPW == 16 +#define PWSH 4 +#endif /* PPW == 16 */ +#endif /* PPW == 8 */ +#endif /* PPW == 4 */ +#endif /* PPW == 2 */ +#endif /* PPW == 1 */ + +/* Defining PIXEL_ADDR means that individual pixels are addressable by this + * machine (as type PixelType). A possible CFB architecture which supported + * 8-bits-per-pixel on a non byte-addressable machine would not have this + * defined. + * + * Defining FOUR_BIT_CODE means that cfb knows how to stipple on this machine; + * eventually, stippling code for 16 and 32 bit devices should be written + * which would allow them to also use FOUR_BIT_CODE. There isn't that + * much to do in those cases, but it would make them quite a bit faster. + */ + +#if PSZ == 8 +#define PIXEL_ADDR +typedef CARD8 PixelType; +#define FOUR_BIT_CODE +#endif + +#if PSZ == 16 +#define PIXEL_ADDR +typedef CARD16 PixelType; +#endif + +#if PSZ == 32 +#undef PMSK +#define PMSK 0xFFFFFFFF +#define PIXEL_ADDR +typedef CARD32 PixelType; +#endif + + +/* the following notes use the following conventions: +SCREEN LEFT SCREEN RIGHT +in this file and maskbits.c, left and right refer to screen coordinates, +NOT bit numbering in registers. + +cfbstarttab[n] + pixels[0,n-1] = 0's pixels[n,PPW-1] = 1's +cfbendtab[n] = + pixels[0,n-1] = 1's pixels[n,PPW-1] = 0's + +cfbstartpartial[], cfbendpartial[] + these are used as accelerators for doing putbits and masking out +bits that are all contained between longword boudaries. the extra +256 bytes of data seems a small price to pay -- code is smaller, +and narrow things (e.g. window borders) go faster. + +the names may seem misleading; they are derived not from which end +of the word the bits are turned on, but at which end of a scanline +the table tends to be used. + +look at the tables and macros to understand boundary conditions. +(careful readers will note that starttab[n] = ~endtab[n] for n != 0) + +----------------------------------------------------------------------- +these two macros depend on the screen's bit ordering. +in both of them x is a screen position. they are used to +combine bits collected from multiple longwords into a +single destination longword, and to unpack a single +source longword into multiple destinations. + +SCRLEFT(dst, x) + takes dst[x, PPW] and moves them to dst[0, PPW-x] + the contents of the rest of dst are 0 ONLY IF + dst is UNSIGNED. + is cast as an unsigned. + this is a right shift on the VAX, left shift on + Sun and pc-rt. + +SCRRIGHT(dst, x) + takes dst[0,x] and moves them to dst[PPW-x, PPW] + the contents of the rest of dst are 0 ONLY IF + dst is UNSIGNED. + this is a left shift on the VAX, right shift on + Sun and pc-rt. + + +the remaining macros are cpu-independent; all bit order dependencies +are built into the tables and the two macros above. + +maskbits(x, w, startmask, endmask, nlw) + for a span of width w starting at position x, returns +a mask for ragged pixels at start, mask for ragged pixels at end, +and the number of whole longwords between the ends. + +maskpartialbits(x, w, mask) + works like maskbits(), except all the pixels are in the + same longword (i.e. (x&0xPIM + w) <= PPW) + +mask32bits(x, w, startmask, endmask, nlw) + as maskbits, but does not calculate nlw. it is used by + cfbGlyphBlt to put down glyphs <= PPW bits wide. + +getbits(psrc, x, w, dst) + starting at position x in psrc (x < PPW), collect w + pixels and put them in the screen left portion of dst. + psrc is a longword pointer. this may span longword boundaries. + it special-cases fetching all w bits from one longword. + + +--------+--------+ +--------+ + | | m |n| | ==> | m |n| | + +--------+--------+ +--------+ + x x+w 0 w + psrc psrc+1 dst + m = PPW - x + n = w - m + + implementation: + get m pixels, move to screen-left of dst, zeroing rest of dst; + get n pixels from next word, move screen-right by m, zeroing + lower m pixels of word. + OR the two things together. + +putbits(src, x, w, pdst, planemask) + starting at position x in pdst, put down the screen-leftmost + w bits of src. pdst is a longword pointer. this may + span longword boundaries. + it special-cases putting all w bits into the same longword. + + +--------+ +--------+--------+ + | m |n| | ==> | | m |n| | + +--------+ +--------+--------+ + 0 w x x+w + dst pdst pdst+1 + m = PPW - x + n = w - m + + implementation: + get m pixels, shift screen-right by x, zero screen-leftmost x + pixels; zero rightmost m bits of *pdst and OR in stuff + from before the semicolon. + shift src screen-left by m, zero bits n-32; + zero leftmost n pixels of *(pdst+1) and OR in the + stuff from before the semicolon. + +putbitsrop(src, x, w, pdst, planemask, ROP) + like putbits but calls DoRop with the rasterop ROP (see cfb.h for + DoRop) + +getleftbits(psrc, w, dst) + get the leftmost w (w<=PPW) bits from *psrc and put them + in dst. this is used by the cfbGlyphBlt code for glyphs + <=PPW bits wide. +*/ + +#if (BITMAP_BIT_ORDER == MSBFirst) +#define BitRight(lw,n) ((lw) >> (n)) +#define BitLeft(lw,n) ((lw) << (n)) +#else /* (BITMAP_BIT_ORDER == LSBFirst) */ +#define BitRight(lw,n) ((lw) << (n)) +#define BitLeft(lw,n) ((lw) >> (n)) +#endif /* (BITMAP_BIT_ORDER == MSBFirst) */ + +#define SCRLEFT(lw, n) BitLeft (lw, (n) * PSZ) +#define SCRRIGHT(lw, n) BitRight(lw, (n) * PSZ) + +/* + * Note that the shift direction is independent of the byte ordering of the + * machine. The following is portable code. + */ +#if PPW == 16 +#define PFILL(p) ( ((p)&PMSK) | \ + ((p)&PMSK) << PSZ | \ + ((p)&PMSK) << 2*PSZ | \ + ((p)&PMSK) << 3*PSZ | \ + ((p)&PMSK) << 4*PSZ | \ + ((p)&PMSK) << 5*PSZ | \ + ((p)&PMSK) << 6*PSZ | \ + ((p)&PMSK) << 7*PSZ | \ + ((p)&PMSK) << 8*PSZ | \ + ((p)&PMSK) << 9*PSZ | \ + ((p)&PMSK) << 10*PSZ | \ + ((p)&PMSK) << 11*PSZ | \ + ((p)&PMSK) << 12*PSZ | \ + ((p)&PMSK) << 13*PSZ | \ + ((p)&PMSK) << 14*PSZ | \ + ((p)&PMSK) << 15*PSZ ) +#define PFILL2(p, pf) { \ + pf = (p) & PMSK; \ + pf |= (pf << PSZ); \ + pf |= (pf << 2*PSZ); \ + pf |= (pf << 4*PSZ); \ + pf |= (pf << 8*PSZ); \ +} +#endif /* PPW == 16 */ +#if PPW == 8 +#define PFILL(p) ( ((p)&PMSK) | \ + ((p)&PMSK) << PSZ | \ + ((p)&PMSK) << 2*PSZ | \ + ((p)&PMSK) << 3*PSZ | \ + ((p)&PMSK) << 4*PSZ | \ + ((p)&PMSK) << 5*PSZ | \ + ((p)&PMSK) << 6*PSZ | \ + ((p)&PMSK) << 7*PSZ ) +#define PFILL2(p, pf) { \ + pf = (p) & PMSK; \ + pf |= (pf << PSZ); \ + pf |= (pf << 2*PSZ); \ + pf |= (pf << 4*PSZ); \ +} +#endif +#if PPW == 4 +#define PFILL(p) ( ((p)&PMSK) | \ + ((p)&PMSK) << PSZ | \ + ((p)&PMSK) << 2*PSZ | \ + ((p)&PMSK) << 3*PSZ ) +#define PFILL2(p, pf) { \ + pf = (p) & PMSK; \ + pf |= (pf << PSZ); \ + pf |= (pf << 2*PSZ); \ +} +#endif +#if PPW == 2 +#define PFILL(p) ( ((p)&PMSK) | \ + ((p)&PMSK) << PSZ ) +#define PFILL2(p, pf) { \ + pf = (p) & PMSK; \ + pf |= (pf << PSZ); \ +} +#endif +#if PPW == 1 +#define PFILL(p) (p) +#define PFILL2(p,pf) (pf = (p)) +#endif + +/* + * Reduced raster op - using precomputed values, perform the above + * in three instructions + */ + +#define DoRRop(dst, and, xor) (((dst) & (and)) ^ (xor)) + +#define DoMaskRRop(dst, and, xor, mask) \ + (((dst) & ((and) | ~(mask))) ^ (xor & mask)) + +#if PSZ != 32 || PPW != 1 + +#define maskbits(x, w, startmask, endmask, nlw) \ + startmask = cfbstarttab[(x)&PIM]; \ + endmask = cfbendtab[((x)+(w)) & PIM]; \ + if (startmask) \ + nlw = (((w) - (PPW - ((x)&PIM))) >> PWSH); \ + else \ + nlw = (w) >> PWSH; + +#define maskpartialbits(x, w, mask) \ + mask = cfbstartpartial[(x) & PIM] & cfbendpartial[((x) + (w)) & PIM]; + +#define mask32bits(x, w, startmask, endmask) \ + startmask = cfbstarttab[(x)&PIM]; \ + endmask = cfbendtab[((x)+(w)) & PIM]; + + +#define getbits(psrc, x, w, dst) \ +if ( ((x) + (w)) <= PPW) \ +{ \ + dst = SCRLEFT(*(psrc), (x)); \ +} \ +else \ +{ \ + int m; \ + m = PPW-(x); \ + dst = (SCRLEFT(*(psrc), (x)) & cfbendtab[m]) | \ + (SCRRIGHT(*((psrc)+1), m) & cfbstarttab[m]); \ +} + + +#define putbits(src, x, w, pdst, planemask) \ +if ( ((x)+(w)) <= PPW) \ +{ \ + PixelGroup tmpmask; \ + maskpartialbits((x), (w), tmpmask); \ + tmpmask &= PFILL(planemask); \ + *(pdst) = (*(pdst) & ~tmpmask) | (SCRRIGHT(src, x) & tmpmask); \ +} \ +else \ +{ \ + unsigned long m; \ + unsigned long n; \ + PixelGroup pm = PFILL(planemask); \ + m = PPW-(x); \ + n = (w) - m; \ + *(pdst) = (*(pdst) & (cfbendtab[x] | ~pm)) | \ + (SCRRIGHT(src, x) & (cfbstarttab[x] & pm)); \ + *((pdst)+1) = (*((pdst)+1) & (cfbstarttab[n] | ~pm)) | \ + (SCRLEFT(src, m) & (cfbendtab[n] & pm)); \ +} +#if defined(__GNUC__) && defined(mc68020) +#undef getbits +#define FASTGETBITS(psrc, x, w, dst) \ + asm ("bfextu %3{%1:%2},%0" \ + : "=d" (dst) : "di" (x), "di" (w), "o" (*(char *)(psrc))) + +#define getbits(psrc,x,w,dst) \ +{ \ + FASTGETBITS(psrc, (x) * PSZ, (w) * PSZ, dst); \ + dst = SCRLEFT(dst,PPW-(w)); \ +} + +#define FASTPUTBITS(src, x, w, pdst) \ + asm ("bfins %3,%0{%1:%2}" \ + : "=o" (*(char *)(pdst)) \ + : "di" (x), "di" (w), "d" (src), "0" (*(char *) (pdst))) + +#undef putbits +#define putbits(src, x, w, pdst, planemask) \ +{ \ + if (planemask != PMSK) { \ + PixelGroup _m, _pm; \ + FASTGETBITS(pdst, (x) * PSZ , (w) * PSZ, _m); \ + PFILL2(planemask, _pm); \ + _m &= (~_pm); \ + _m |= (SCRRIGHT(src, PPW-(w)) & _pm); \ + FASTPUTBITS(_m, (x) * PSZ, (w) * PSZ, pdst); \ + } else { \ + FASTPUTBITS(SCRRIGHT(src, PPW-(w)), (x) * PSZ, (w) * PSZ, pdst); \ + } \ +} + + +#endif /* mc68020 */ + +#define putbitsrop(src, x, w, pdst, planemask, rop) \ +if ( ((x)+(w)) <= PPW) \ +{ \ + PixelGroup tmpmask; \ + PixelGroup t1, t2; \ + maskpartialbits((x), (w), tmpmask); \ + PFILL2(planemask, t1); \ + tmpmask &= t1; \ + t1 = SCRRIGHT((src), (x)); \ + DoRop(t2, rop, t1, *(pdst)); \ + *(pdst) = (*(pdst) & ~tmpmask) | (t2 & tmpmask); \ +} \ +else \ +{ \ + unsigned long m; \ + unsigned long n; \ + PixelGroup t1, t2; \ + PixelGroup pm; \ + PFILL2(planemask, pm); \ + m = PPW-(x); \ + n = (w) - m; \ + t1 = SCRRIGHT((src), (x)); \ + DoRop(t2, rop, t1, *(pdst)); \ + *(pdst) = (*(pdst) & (cfbendtab[x] | ~pm)) | (t2 & (cfbstarttab[x] & pm));\ + t1 = SCRLEFT((src), m); \ + DoRop(t2, rop, t1, *((pdst) + 1)); \ + *((pdst)+1) = (*((pdst)+1) & (cfbstarttab[n] | ~pm)) | \ + (t2 & (cfbendtab[n] & pm)); \ +} + +#else /* PSZ == 32 && PPW == 1*/ + +/* + * These macros can be optimized for 32-bit pixels since there is no + * need to worry about left/right edge masking. These macros were + * derived from the above using the following reductions: + * + * - x & PIW = 0 [since PIW = 0] + * - all masking tables are only indexed by 0 [ due to above ] + * - cfbstartab[0] and cfbendtab[0] = 0 [ no left/right edge masks] + * - cfbstartpartial[0] and cfbendpartial[0] = ~0 [no partial pixel mask] + * + * Macro reduction based upon constants cannot be performed automatically + * by the compiler since it does not know the contents of the masking + * arrays in cfbmskbits.c. + */ +#define maskbits(x, w, startmask, endmask, nlw) \ + startmask = endmask = 0; \ + nlw = (w); + +#define maskpartialbits(x, w, mask) \ + mask = 0xFFFFFFFF; + +#define mask32bits(x, w, startmask, endmask) \ + startmask = endmask = 0; + +/* + * For 32-bit operations, getbits(), putbits(), and putbitsrop() + * will only be invoked with x = 0 and w = PPW (1). The getbits() + * macro is only called within left/right edge logic, which doesn't + * happen for 32-bit pixels. + */ +#define getbits(psrc, x, w, dst) (dst) = *(psrc) + +#define putbits(src, x, w, pdst, planemask) \ + *(pdst) = (*(pdst) & ~planemask) | (src & planemask); + +#define putbitsrop(src, x, w, pdst, planemask, rop) \ +{ \ + PixelGroup t1; \ + DoRop(t1, rop, (src), *(pdst)); \ + *(pdst) = (*(pdst) & ~planemask) | (t1 & planemask); \ +} + +#endif /* PSZ != 32 */ + +/* + * Use these macros only when you're using the MergeRop stuff + * in ../mfb/mergerop.h + */ + +/* useful only when not spanning destination longwords */ +#define putbitsmropshort(src,x,w,pdst) {\ + PixelGroup _tmpmask; \ + PixelGroup _t1; \ + maskpartialbits ((x), (w), _tmpmask); \ + _t1 = SCRRIGHT((src), (x)); \ + *pdst = DoMaskMergeRop(_t1, *pdst, _tmpmask); \ +} + +/* useful only when spanning destination longwords */ +#define putbitsmroplong(src,x,w,pdst) { \ + PixelGroup _startmask, _endmask; \ + int _m; \ + PixelGroup _t1; \ + _m = PPW - (x); \ + _startmask = cfbstarttab[x]; \ + _endmask = cfbendtab[(w) - _m]; \ + _t1 = SCRRIGHT((src), (x)); \ + pdst[0] = DoMaskMergeRop(_t1,pdst[0],_startmask); \ + _t1 = SCRLEFT ((src),_m); \ + pdst[1] = DoMaskMergeRop(_t1,pdst[1],_endmask); \ +} + +#define putbitsmrop(src,x,w,pdst) \ +if ((x) + (w) <= PPW) {\ + putbitsmropshort(src,x,w,pdst); \ +} else { \ + putbitsmroplong(src,x,w,pdst); \ +} + +#if GETLEFTBITS_ALIGNMENT == 1 +#define getleftbits(psrc, w, dst) dst = *((unsigned int *) psrc) +#endif /* GETLEFTBITS_ALIGNMENT == 1 */ + +#define getglyphbits(psrc, x, w, dst) \ +{ \ + dst = BitLeft((unsigned) *(psrc), (x)); \ + if ( ((x) + (w)) > 32) \ + dst |= (BitRight((unsigned) *((psrc)+1), 32-(x))); \ +} +#if GETLEFTBITS_ALIGNMENT == 2 +#define getleftbits(psrc, w, dst) \ + { \ + if ( ((int)(psrc)) & 0x01 ) \ + getglyphbits( ((unsigned int *)(((char *)(psrc))-1)), 8, (w), (dst) ); \ + else \ + dst = *((unsigned int *) psrc); \ + } +#endif /* GETLEFTBITS_ALIGNMENT == 2 */ + +#if GETLEFTBITS_ALIGNMENT == 4 +#define getleftbits(psrc, w, dst) \ + { \ + int off, off_b; \ + off_b = (off = ( ((int)(psrc)) & 0x03)) << 3; \ + getglyphbits( \ + (unsigned int *)( ((char *)(psrc)) - off), \ + (off_b), (w), (dst) \ + ); \ + } +#endif /* GETLEFTBITS_ALIGNMENT == 4 */ + +/* + * getstipplepixels( psrcstip, x, w, ones, psrcpix, destpix ) + * + * Converts bits to pixels in a reasonable way. Takes w (1 <= w <= PPW) + * bits from *psrcstip, starting at bit x; call this a quartet of bits. + * Then, takes the pixels from *psrcpix corresponding to the one-bits (if + * ones is TRUE) or the zero-bits (if ones is FALSE) of the quartet + * and puts these pixels into destpix. + * + * Example: + * + * getstipplepixels( &(0x08192A3B), 17, 4, 1, &(0x4C5D6E7F), dest ) + * + * 0x08192A3B = 0000 1000 0001 1001 0010 1010 0011 1011 + * + * This will take 4 bits starting at bit 17, so the quartet is 0x5 = 0101. + * It will take pixels from 0x4C5D6E7F corresponding to the one-bits in this + * quartet, so dest = 0x005D007F. + * + * XXX Works with both byte order. + * XXX This works for all values of x and w within a doubleword. + */ +#if (BITMAP_BIT_ORDER == MSBFirst) +#define getstipplepixels( psrcstip, x, w, ones, psrcpix, destpix ) \ +{ \ + PixelGroup q; \ + int m; \ + if ((m = ((x) - ((PPW*PSZ)-PPW))) > 0) { \ + q = (*(psrcstip)) << m; \ + if ( (x)+(w) > (PPW*PSZ) ) \ + q |= *((psrcstip)+1) >> ((PPW*PSZ)-m); \ + } \ + else \ + q = (*(psrcstip)) >> -m; \ + q = QuartetBitsTable[(w)] & ((ones) ? q : ~q); \ + *(destpix) = (*(psrcpix)) & QuartetPixelMaskTable[q]; \ +} +#else /* BITMAP_BIT_ORDER == LSB */ +#define getstipplepixels( psrcstip, xt, w, ones, psrcpix, destpix ) \ +{ \ + PixelGroup q; \ + q = *(psrcstip) >> (xt); \ + if ( ((xt)+(w)) > (PPW*PSZ) ) \ + q |= (*((psrcstip)+1)) << ((PPW*PSZ)-(xt)); \ + q = QuartetBitsTable[(w)] & ((ones) ? q : ~q); \ + *(destpix) = (*(psrcpix)) & QuartetPixelMaskTable[q]; \ +} +#endif + +extern PixelGroup cfbstarttab[]; +extern PixelGroup cfbendtab[]; +extern PixelGroup cfbstartpartial[]; +extern PixelGroup cfbendpartial[]; +extern PixelGroup cfbrmask[]; +extern PixelGroup cfbmask[]; +extern PixelGroup QuartetBitsTable[]; +extern PixelGroup QuartetPixelMaskTable[]; diff --git a/cfb/cfbpixmap.c b/cfb/cfbpixmap.c new file mode 100644 index 000000000..37cec5c7d --- /dev/null +++ b/cfb/cfbpixmap.c @@ -0,0 +1,370 @@ +/* $Xorg: cfbpixmap.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* pixmap management + written by drewry, september 1986 + + on a monchrome device, a pixmap is a bitmap. +*/ + +#include "Xmd.h" +#include "servermd.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mi.h" +#include "cfb.h" +#include "cfbmskbits.h" + +extern unsigned long endtab[]; + +PixmapPtr +cfbCreatePixmap (pScreen, width, height, depth) + ScreenPtr pScreen; + int width; + int height; + int depth; +{ + PixmapPtr pPixmap; + int datasize; + int paddedWidth; + + paddedWidth = PixmapBytePad(width, depth); + datasize = height * paddedWidth; + pPixmap = AllocatePixmap(pScreen, datasize); + if (!pPixmap) + return NullPixmap; + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth); + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = paddedWidth; + pPixmap->refcnt = 1; +#ifdef PIXPRIV + pPixmap->devPrivate.ptr = datasize ? + (pointer)((char *)pPixmap + pScreen->totalPixmapSize) : NULL; +#else + pPixmap->devPrivate.ptr = (pointer)(pPixmap + 1); +#endif + return pPixmap; +} + +Bool +cfbDestroyPixmap(pPixmap) + PixmapPtr pPixmap; +{ + if(--pPixmap->refcnt) + return TRUE; + xfree(pPixmap); + return TRUE; +} + +PixmapPtr +cfbCopyPixmap(pSrc) + register PixmapPtr pSrc; +{ + register PixmapPtr pDst; + int size; + ScreenPtr pScreen; + + size = pSrc->drawable.height * pSrc->devKind; + pScreen = pSrc->drawable.pScreen; + pDst = (*pScreen->CreatePixmap) (pScreen, pSrc->drawable.width, + pSrc->drawable.height, pSrc->drawable.depth); + if (!pDst) + return NullPixmap; + memmove((char *)pDst->devPrivate.ptr, (char *)pSrc->devPrivate.ptr, size); + return pDst; +} + + +/* replicates a pattern to be a full 32 bits wide. + relies on the fact that each scnaline is longword padded. + doesn't do anything if pixmap is not a factor of 32 wide. + changes width field of pixmap if successful, so that the fast + cfbXRotatePixmap code gets used if we rotate the pixmap later. + cfbYRotatePixmap code gets used if we rotate the pixmap later. + + calculate number of times to repeat + for each scanline of pattern + zero out area to be filled with replicate + left shift and or in original as many times as needed +*/ +void +cfbPadPixmap(pPixmap) + PixmapPtr pPixmap; +{ + register int width = (pPixmap->drawable.width) * (pPixmap->drawable.bitsPerPixel); + register int h; + register unsigned long mask; + register unsigned long *p; + register unsigned long bits; /* real pattern bits */ + register int i; + int rep; /* repeat count for pattern */ + + if (width >= PGSZ) + return; + + rep = PGSZ/width; + if (rep*width != PGSZ) + return; + + mask = endtab[width]; + + p = (unsigned long *)(pPixmap->devPrivate.ptr); + for (h=0; h < pPixmap->drawable.height; h++) + { + *p &= mask; + bits = *p; + for(i=1; i>= width; +#else + bits <<= width; +#endif + *p |= bits; + } + p++; + } + pPixmap->drawable.width = PGSZ/(pPixmap->drawable.bitsPerPixel); +} + + +#ifdef notdef +/* + * cfb debugging routine -- assumes pixmap is 1 byte deep + */ +static cfbdumppixmap(pPix) + PixmapPtr pPix; +{ + unsigned int *pw; + char *psrc, *pdst; + int i, j; + char line[66]; + + ErrorF( "pPixmap: 0x%x\n", pPix); + ErrorF( "%d wide %d high\n", pPix->drawable.width, pPix->drawable.height); + if (pPix->drawable.width > 64) + { + ErrorF( "too wide to see\n"); + return; + } + + pw = (unsigned int *) pPix->devPrivate.ptr; + psrc = (char *) pw; + +/* + for ( i=0; idrawable.height; ++i ) + ErrorF( "0x%x\n", pw[i] ); +*/ + + for ( i = 0; i < pPix->drawable.height; ++i ) { + pdst = line; + for(j = 0; j < pPix->drawable.width; j++) { + *pdst++ = *psrc++ ? 'X' : ' ' ; + } + *pdst++ = '\n'; + *pdst++ = '\0'; + ErrorF( "%s", line); + } +} +#endif /* notdef */ + +/* Rotates pixmap pPix by w pixels to the right on the screen. Assumes that + * words are PGSZ bits wide, and that the least significant bit appears on the + * left. + */ +void +cfbXRotatePixmap(pPix, rw) + PixmapPtr pPix; + register int rw; +{ + register unsigned long *pw, *pwFinal; + register unsigned long t; + int rot; + + if (pPix == NullPixmap) + return; + + switch (((DrawablePtr) pPix)->bitsPerPixel) { + case PSZ: + break; + case 1: + mfbXRotatePixmap(pPix, rw); + return; + default: + ErrorF("cfbXRotatePixmap: unsupported bitsPerPixel %d\n", ((DrawablePtr) pPix)->bitsPerPixel); + return; + } + pw = (unsigned long *)pPix->devPrivate.ptr; + modulus (rw, (int) pPix->drawable.width, rot); + if(pPix->drawable.width == PPW) + { + pwFinal = pw + pPix->drawable.height; + while(pw < pwFinal) + { + t = *pw; + *pw++ = SCRRIGHT(t, rot) | + (SCRLEFT(t, (PPW-rot)) & cfbendtab[rot]); + } + } + else + { + ErrorF("cfb internal error: trying to rotate odd-sized pixmap.\n"); +#ifdef notdef + register unsigned long *pwTmp; + int size, tsize; + + tsize = PixmapBytePad(pPix->drawable.width - rot, pPix->drawable.depth); + pwTmp = (unsigned long *) ALLOCATE_LOCAL(pPix->drawable.height * tsize); + if (!pwTmp) + return; + /* divide pw (the pixmap) in two vertically at (w - rot) and swap */ + tsize >>= 2; + size = pPix->devKind >> SIZE0F(PixelGroup); + cfbQuickBlt((long *)pw, (long *)pwTmp, + 0, 0, 0, 0, + (int)pPix->drawable.width - rot, (int)pPix->drawable.height, + size, tsize); + cfbQuickBlt((long *)pw, (long *)pw, + (int)pPix->drawable.width - rot, 0, 0, 0, + rot, (int)pPix->drawable.height, + size, size); + cfbQuickBlt((long *)pwTmp, (long *)pw, + 0, 0, rot, 0, + (int)pPix->drawable.width - rot, (int)pPix->drawable.height, + tsize, size); + DEALLOCATE_LOCAL(pwTmp); +#endif + } +} + +/* Rotates pixmap pPix by h lines. Assumes that h is always less than + pPix->drawable.height + works on any width. + */ +void +cfbYRotatePixmap(pPix, rh) + register PixmapPtr pPix; + int rh; +{ + int nbyDown; /* bytes to move down to row 0; also offset of + row rh */ + int nbyUp; /* bytes to move up to line rh; also + offset of first line moved down to 0 */ + char *pbase; + char *ptmp; + int rot; + + if (pPix == NullPixmap) + return; + switch (((DrawablePtr) pPix)->bitsPerPixel) { + case PSZ: + break; + case 1: + mfbYRotatePixmap(pPix, rh); + return; + default: + ErrorF("cfbYRotatePixmap: unsupported bitsPerPixel %d\n", ((DrawablePtr) pPix)->bitsPerPixel); + return; + } + + modulus (rh, (int) pPix->drawable.height, rot); + pbase = (char *)pPix->devPrivate.ptr; + + nbyDown = rot * pPix->devKind; + nbyUp = (pPix->devKind * pPix->drawable.height) - nbyDown; + if(!(ptmp = (char *)ALLOCATE_LOCAL(nbyUp))) + return; + + memmove(ptmp, pbase, nbyUp); /* save the low rows */ + memmove(pbase, pbase+nbyUp, nbyDown); /* slide the top rows down */ + memmove(pbase+nbyDown, ptmp, nbyUp); /* move lower rows up to row rot */ + DEALLOCATE_LOCAL(ptmp); +} + +void +cfbCopyRotatePixmap(psrcPix, ppdstPix, xrot, yrot) + register PixmapPtr psrcPix, *ppdstPix; + int xrot, yrot; +{ + register PixmapPtr pdstPix; + + if ((pdstPix = *ppdstPix) && + (pdstPix->devKind == psrcPix->devKind) && + (pdstPix->drawable.height == psrcPix->drawable.height)) + { + memmove((char *)pdstPix->devPrivate.ptr, + (char *)psrcPix->devPrivate.ptr, + psrcPix->drawable.height * psrcPix->devKind); + pdstPix->drawable.width = psrcPix->drawable.width; + pdstPix->drawable.depth = psrcPix->drawable.depth; + pdstPix->drawable.bitsPerPixel = psrcPix->drawable.bitsPerPixel; + pdstPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + else + { + if (pdstPix) + /* FIX XBUG 6168 */ + (*pdstPix->drawable.pScreen->DestroyPixmap)(pdstPix); + *ppdstPix = pdstPix = cfbCopyPixmap(psrcPix); + if (!pdstPix) + return; + } + cfbPadPixmap(pdstPix); + if (xrot) + cfbXRotatePixmap(pdstPix, xrot); + if (yrot) + cfbYRotatePixmap(pdstPix, yrot); +} diff --git a/cfb/cfbply1rct.c b/cfb/cfbply1rct.c new file mode 100644 index 000000000..b1e5c8ff1 --- /dev/null +++ b/cfb/cfbply1rct.c @@ -0,0 +1,318 @@ +/* + * $Xorg: cfbply1rct.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +#include "X.h" + +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "mistruct.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfbrrop.h" + +void +RROP_NAME(cfbFillPoly1Rect) (pDrawable, pGC, shape, mode, count, ptsIn) + DrawablePtr pDrawable; + GCPtr pGC; + int shape; + int mode; + int count; + DDXPointPtr ptsIn; +{ + cfbPrivGCPtr devPriv; + int nwidth; + unsigned long *addrl, *addr; + int maxy; + int origin; + register int vertex1, vertex2; + int c; + BoxPtr extents; + int clip; + int y; + int *vertex1p, *vertex2p; + int *endp; + int x1, x2; + int dx1, dx2; + int dy1, dy2; + int e1, e2; + int step1, step2; + int sign1, sign2; + int h; + int l, r; + unsigned long mask, bits = ~((unsigned long)0); + int nmiddle; + RROP_DECLARE + + if (mode == CoordModePrevious) + { + miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn); + return; + } + + devPriv = cfbGetGCPrivate(pGC); +#ifdef NO_ONE_RECT + if (REGION_NUM_RECTS(devPriv->pCompositeClip) != 1) + { + miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn); + return; + } +#endif + origin = *((int *) &pDrawable->x); + vertex2 = origin - ((origin & 0x8000) << 1); + extents = &devPriv->pCompositeClip->extents; + RROP_FETCH_GCPRIV(devPriv); + vertex1 = *((int *) &extents->x1) - vertex2; + vertex2 = *((int *) &extents->x2) - vertex2 - 0x00010001; + clip = 0; + y = 32767; + maxy = 0; + vertex2p = (int *) ptsIn; + endp = vertex2p + count; + if (shape == Convex) + { + while (count--) + { + c = *vertex2p; + clip |= (c - vertex1) | (vertex2 - c); + c = intToY(c); + if (c < y) + { + y = c; + vertex1p = vertex2p; + } + vertex2p++; + if (c > maxy) + maxy = c; + } + } + else + { + int yFlip = 0; + dx1 = 1; + x2 = -1; + x1 = -1; + while (count--) + { + c = *vertex2p; + clip |= (c - vertex1) | (vertex2 - c); + c = intToY(c); + if (c < y) + { + y = c; + vertex1p = vertex2p; + } + vertex2p++; + if (c > maxy) + maxy = c; + if (c == x1) + continue; + if (dx1 > 0) + { + if (x2 < 0) + x2 = c; + else + dx2 = dx1 = (c - x1) >> 31; + } + else + if ((c - x1) >> 31 != dx1) + { + dx1 = ~dx1; + yFlip++; + } + x1 = c; + } + x1 = (x2 - c) >> 31; + if (x1 != dx1) + yFlip++; + if (x1 != dx2) + yFlip++; + if (yFlip != 2) + clip = 0x8000; + } + if (y == maxy) + return; + + if (clip & 0x80008000) + { + miFillPolygon (pDrawable, pGC, shape, mode, vertex2p - (int *) ptsIn, ptsIn); + return; + } + +#define AddrYPlus(a,y) (unsigned long *) (((unsigned char *) (a)) + (y) * nwidth) + + cfbGetTypedWidthAndPointer(pDrawable, nwidth, addrl, unsigned char, unsigned long); + addrl = AddrYPlus(addrl,y + pDrawable->y); + origin = intToX(origin); + vertex2p = vertex1p; + vertex2 = vertex1 = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; +#define Setup(c,x,vertex,dx,dy,e,sign,step) {\ + x = intToX(vertex); \ + if (dy = intToY(c) - y) { \ + dx = intToX(c) - x; \ + step = 0; \ + if (dx >= 0) \ + { \ + e = 0; \ + sign = 1; \ + if (dx >= dy) {\ + step = dx / dy; \ + dx = dx % dy; \ + } \ + } \ + else \ + { \ + e = 1 - dy; \ + sign = -1; \ + dx = -dx; \ + if (dx >= dy) { \ + step = - (dx / dy); \ + dx = dx % dy; \ + } \ + } \ + } \ + x += origin; \ + vertex = c; \ +} + +#define Step(x,dx,dy,e,sign,step) {\ + x += step; \ + if ((e += dx) > 0) \ + { \ + x += sign; \ + e -= dy; \ + } \ +} + for (;;) + { + if (y == intToY(vertex1)) + { + do + { + if (vertex1p == (int *) ptsIn) + vertex1p = endp; + c = *--vertex1p; + Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1) + } while (y >= intToY(vertex1)); + h = dy1; + } + else + { + Step(x1,dx1,dy1,e1,sign1,step1) + h = intToY(vertex1) - y; + } + if (y == intToY(vertex2)) + { + do + { + c = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2) + } while (y >= intToY(vertex2)); + if (dy2 < h) + h = dy2; + } + else + { + Step(x2,dx2,dy2,e2,sign2,step2) + if ((c = (intToY(vertex2) - y)) < h) + h = c; + } + /* fill spans for this segment */ + y += h; + for (;;) + { + l = x1; + r = x2; + nmiddle = x2 - x1; + if (nmiddle < 0) + { + nmiddle = -nmiddle; + l = x2; + r = x1; + } +#if PPW > 1 + c = l & PIM; + l -= c; +#endif + +#if PGSZ == 32 +#define LWRD_SHIFT 2 +#else /* PGSZ == 64 */ +#define LWRD_SHIFT 3 +#endif /* PGSZ */ + +#if PWSH > LWRD_SHIFT + l = l >> (PWSH - LWRD_SHIFT); +#endif +#if PWSH < LWRD_SHIFT + l = l << (LWRD_SHIFT - PWSH); +#endif + addr = (unsigned long *) (((char *) addrl) + l); +#if PPW > 1 + if (c + nmiddle < PPW) + { + mask = SCRRIGHT (bits,c) ^ SCRRIGHT (bits,c+nmiddle); + RROP_SOLID_MASK(addr,mask); + } + else + { + if (c) + { + mask = SCRRIGHT(bits, c); + RROP_SOLID_MASK(addr,mask); + nmiddle += c - PPW; + addr++; + } +#endif + nmiddle >>= PWSH; + while (--nmiddle >= 0) { + RROP_SOLID(addr); addr++; + } +#if PPW > 1 + if (mask = ~SCRRIGHT(bits, r & PIM)) + RROP_SOLID_MASK(addr,mask); + } +#endif + if (!--h) + break; + addrl = AddrYPlus (addrl, 1); + Step(x1,dx1,dy1,e1,sign1,step1) + Step(x2,dx2,dy2,e2,sign2,step2) + } + if (y == maxy) + break; + addrl = AddrYPlus (addrl, 1); + } +} diff --git a/cfb/cfbpntwin.c b/cfb/cfbpntwin.c new file mode 100644 index 000000000..bf53cb3f9 --- /dev/null +++ b/cfb/cfbpntwin.c @@ -0,0 +1,370 @@ +/* $Xorg: cfbpntwin.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "X.h" + +#include "windowstr.h" +#include "regionstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "mi.h" + +void +cfbPaintWindow(pWin, pRegion, what) + WindowPtr pWin; + RegionPtr pRegion; + int what; +{ + register cfbPrivWin *pPrivWin; + WindowPtr pBgWin; + + pPrivWin = cfbGetWindowPrivate(pWin); + + switch (what) { + case PW_BACKGROUND: + switch (pWin->backgroundState) { + case None: + break; + case ParentRelative: + do { + pWin = pWin->parent; + } while (pWin->backgroundState == ParentRelative); + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, + what); + break; + case BackgroundPixmap: + if (pPrivWin->fastBackground) + { + cfbFillBoxTile32 ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pPrivWin->pRotatedBackground); + } + else + { + cfbFillBoxTileOdd ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->background.pixmap, + (int) pWin->drawable.x, (int) pWin->drawable.y); + } + break; + case BackgroundPixel: + cfbFillBoxSolid ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->background.pixel); + break; + } + break; + case PW_BORDER: + if (pWin->borderIsPixel) + { + cfbFillBoxSolid ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->border.pixel); + } + else if (pPrivWin->fastBorder) + { + cfbFillBoxTile32 ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pPrivWin->pRotatedBorder); + } + else + { + for (pBgWin = pWin; + pBgWin->backgroundState == ParentRelative; + pBgWin = pBgWin->parent); + + cfbFillBoxTileOdd ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->border.pixmap, + (int) pBgWin->drawable.x, + (int) pBgWin->drawable.y); + } + break; + } +} + +/* + * Use the RROP macros in copy mode + */ + +#define RROP GXcopy +#include "cfbrrop.h" + +#ifdef RROP_UNROLL +# define Expand(left,right,leftAdjust) {\ + int part = nmiddle & RROP_UNROLL_MASK; \ + int widthStep; \ + widthStep = widthDst - nmiddle - leftAdjust; \ + nmiddle >>= RROP_UNROLL_SHIFT; \ + while (h--) { \ + left \ + pdst += part; \ + switch (part) { \ + RROP_UNROLL_CASE(pdst) \ + } \ + m = nmiddle; \ + while (m) { \ + pdst += RROP_UNROLL; \ + RROP_UNROLL_LOOP(pdst) \ + m--; \ + } \ + right \ + pdst += widthStep; \ + } \ +} + +#else +# define Expand(left, right, leftAdjust) { \ + int widthStep; \ + widthStep = widthDst - nmiddle - leftAdjust; \ + while (h--) { \ + left \ + m = nmiddle; \ + while (m--) {\ + RROP_SOLID(pdst); \ + pdst++; \ + } \ + right \ + pdst += widthStep; \ + } \ +} +#endif + +void +cfbFillBoxSolid (pDrawable, nBox, pBox, pixel) + DrawablePtr pDrawable; + int nBox; + BoxPtr pBox; + unsigned long pixel; +{ + unsigned long *pdstBase; + int widthDst; + register int h; + register unsigned long rrop_xor; + register unsigned long *pdst; + register unsigned long leftMask, rightMask; + int nmiddle; + register int m; + int w; + + cfbGetLongWidthAndPointer(pDrawable, widthDst, pdstBase); + + rrop_xor = PFILL(pixel); + for (; nBox; nBox--, pBox++) + { + pdst = pdstBase + pBox->y1 * widthDst; + h = pBox->y2 - pBox->y1; + w = pBox->x2 - pBox->x1; +#if PSZ == 8 + if (w == 1) + { + register char *pdstb = ((char *) pdst) + pBox->x1; + int incr = widthDst * PGSZB; + + while (h--) + { + *pdstb = rrop_xor; + pdstb += incr; + } + } + else + { +#endif + pdst += (pBox->x1 >> PWSH); + if ((pBox->x1 & PIM) + w <= PPW) + { + maskpartialbits(pBox->x1, w, leftMask); + while (h--) { + *pdst = (*pdst & ~leftMask) | (rrop_xor & leftMask); + pdst += widthDst; + } + } + else + { + maskbits (pBox->x1, w, leftMask, rightMask, nmiddle); + if (leftMask) + { + if (rightMask) + { + Expand (RROP_SOLID_MASK (pdst, leftMask); pdst++; , + RROP_SOLID_MASK (pdst, rightMask); , + 1) + } + else + { + Expand (RROP_SOLID_MASK (pdst, leftMask); pdst++;, + ;, + 1) + } + } + else + { + if (rightMask) + { + Expand (;, + RROP_SOLID_MASK (pdst, rightMask);, + 0) + } + else + { + Expand (;, + ;, + 0) + } + } + } +#if PSZ == 8 + } +#endif + } +} + +void +cfbFillBoxTile32 (pDrawable, nBox, pBox, tile) + DrawablePtr pDrawable; + int nBox; /* number of boxes to fill */ + BoxPtr pBox; /* pointer to list of boxes to fill */ + PixmapPtr tile; /* rotated, expanded tile */ +{ + register unsigned long rrop_xor; + register unsigned long *pdst; + register int m; + unsigned long *psrc; + int tileHeight; + + int widthDst; + int w; + int h; + register unsigned long leftMask; + register unsigned long rightMask; + int nmiddle; + int y; + int srcy; + + unsigned long *pdstBase; + + tileHeight = tile->drawable.height; + psrc = (unsigned long *)tile->devPrivate.ptr; + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase); + + while (nBox--) + { + w = pBox->x2 - pBox->x1; + h = pBox->y2 - pBox->y1; + y = pBox->y1; + pdst = pdstBase + (pBox->y1 * widthDst) + (pBox->x1 >> PWSH); + srcy = y % tileHeight; + +#define StepTile rrop_xor = psrc[srcy]; \ + ++srcy; \ + if (srcy == tileHeight) \ + srcy = 0; + + if ( ((pBox->x1 & PIM) + w) < PPW) + { + maskpartialbits(pBox->x1, w, leftMask); + rightMask = ~leftMask; + while (h--) + { + StepTile + *pdst = (*pdst & rightMask) | (rrop_xor & leftMask); + pdst += widthDst; + } + } + else + { + maskbits(pBox->x1, w, leftMask, rightMask, nmiddle); + + if (leftMask) + { + if (rightMask) + { + Expand (StepTile + RROP_SOLID_MASK(pdst, leftMask); pdst++;, + RROP_SOLID_MASK(pdst, rightMask);, + 1) + } + else + { + Expand (StepTile + RROP_SOLID_MASK(pdst, leftMask); pdst++;, + ;, + 1) + } + } + else + { + if (rightMask) + { + Expand (StepTile + , + RROP_SOLID_MASK(pdst, rightMask);, + 0) + } + else + { + Expand (StepTile + , + ;, + 0) + } + } + } + pBox++; + } +} diff --git a/cfb/cfbpolypnt.c b/cfb/cfbpolypnt.c new file mode 100644 index 000000000..bf2217fb1 --- /dev/null +++ b/cfb/cfbpolypnt.c @@ -0,0 +1,150 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: cfbpolypnt.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ + +#include "X.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "cfb.h" +#include "cfbmskbits.h" + +#define isClipped(c,ul,lr) ((((c) - (ul)) | ((lr) - (c))) & ClipMask) + +/* WARNING: pbox contains two shorts. This code assumes they are packed + * and can be referenced together as an INT32. + */ + +#define PointLoop(fill) { \ + for (nbox = REGION_NUM_RECTS(cclip), pbox = REGION_RECTS(cclip); \ + --nbox >= 0; \ + pbox++) \ + { \ + c1 = *((INT32 *) &pbox->x1) - off; \ + c2 = *((INT32 *) &pbox->x2) - off - 0x00010001; \ + for (ppt = (INT32 *) pptInit, i = npt; --i >= 0;) \ + { \ + pt = *ppt++; \ + if (!isClipped(pt,c1,c2)) { \ + fill \ + } \ + } \ + } \ +} + +void +cfbPolyPoint(pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int npt; + xPoint *pptInit; +{ + register INT32 pt; + register INT32 c1, c2; + register unsigned long ClipMask = 0x80008000; + register unsigned long xor; +#ifdef PIXEL_ADDR + register PixelType *addrp; + register int npwidth; + PixelType *addrpt; +#else + register unsigned long *addrl; + register int nlwidth; + register int xoffset; + unsigned long *addrlt; +#endif + register INT32 *ppt; + RegionPtr cclip; + int nbox; + register int i; + register BoxPtr pbox; + unsigned long and; + int rop = pGC->alu; + int off; + cfbPrivGCPtr devPriv; + xPoint *pptPrev; + + devPriv =cfbGetGCPrivate(pGC); + rop = devPriv->rop; + if (rop == GXnoop) + return; + cclip = devPriv->pCompositeClip; + xor = devPriv->xor; + if ((mode == CoordModePrevious) && (npt > 1)) + { + for (pptPrev = pptInit + 1, i = npt - 1; --i >= 0; pptPrev++) + { + pptPrev->x += (pptPrev-1)->x; + pptPrev->y += (pptPrev-1)->y; + } + } + off = *((int *) &pDrawable->x); + off -= (off & 0x8000) << 1; +#ifdef PIXEL_ADDR + cfbGetPixelWidthAndPointer(pDrawable, npwidth, addrp); + addrp = addrp + pDrawable->y * npwidth + pDrawable->x; + if (rop == GXcopy) + { + if (!(npwidth & (npwidth - 1))) + { + npwidth = ffs(npwidth) - 1; + PointLoop(*(addrp + (intToY(pt) << npwidth) + intToX(pt)) = xor;) + } +#ifdef sun + else if (npwidth == 1152) + { + register int y; + PointLoop(y = intToY(pt); *(addrp + (y << 10) + (y << 7) + intToX(pt)) = xor;) + } +#endif + else + { + PointLoop(*(addrp + intToY(pt) * npwidth + intToX(pt)) = xor;) + } + } + else + { + and = devPriv->and; + PointLoop( addrpt = addrp + intToY(pt) * npwidth + intToX(pt); + *addrpt = DoRRop (*addrpt, and, xor);) + } +#else /* !PIXEL_ADDR */ + cfbGetLongWidthAndPointer(pDrawable, nlwidth, addrl); + addrl = addrl + pDrawable->y * nlwidth + (pDrawable->x >> PWSH); + xoffset = pDrawable->x & PIM; + and = devPriv->and; + PointLoop( addrlt = addrl + intToY(pt) * nlwidth + + ((intToX(pt) + xoffset) >> PWSH); + *addrlt = DoRRop (*addrlt, + and | ~cfbmask[(intToX(pt) + xoffset) & PIM], + xor & cfbmask[(intToX(pt) + xoffset) & PIM]); + ) +#endif /* PIXEL_ADDR */ +} diff --git a/cfb/cfbpush8.c b/cfb/cfbpush8.c new file mode 100644 index 000000000..850de518d --- /dev/null +++ b/cfb/cfbpush8.c @@ -0,0 +1,184 @@ +/* + * Push Pixels for 8 bit displays. + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ +/* $Xorg: cfbpush8.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ + +#if PSZ == 8 + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" +#define MFB_CONSTS_ONLY +#include "maskbits.h" + +void +cfbPushPixels8 (pGC, pBitmap, pDrawable, dx, dy, xOrg, yOrg) + GCPtr pGC; + PixmapPtr pBitmap; + DrawablePtr pDrawable; + int dx, dy, xOrg, yOrg; +{ + register unsigned long *src, *dst; + register unsigned long pixel; + register unsigned long c, bits; + unsigned long *pdstLine, *psrcLine; + unsigned long *pdstBase; + int srcWidth; + int dstWidth; + int xoff; + int nBitmapLongs, nPixmapLongs; + int nBitmapTmp, nPixmapTmp; + unsigned long rightMask; + BoxRec bbox; + cfbPrivGCPtr devPriv; + + bbox.x1 = xOrg; + bbox.y1 = yOrg; + bbox.x2 = bbox.x1 + dx; + bbox.y2 = bbox.y1 + dy; + devPriv = cfbGetGCPrivate(pGC); + + switch (RECT_IN_REGION(pGC->pScreen, devPriv->pCompositeClip, &bbox)) + { + case rgnPART: +#ifndef LOWMEMFTPT + mfbPushPixels(pGC, pBitmap, pDrawable, dx, dy, xOrg, yOrg); +#else + miPushPixels(pGC, pBitmap, pDrawable, dx, dy, xOrg, yOrg); +#endif /* ifndef LOWMEMFTPT */ + case rgnOUT: + return; + } + + cfbGetLongWidthAndPointer (pDrawable, dstWidth, pdstBase) + + psrcLine = (unsigned long *) pBitmap->devPrivate.ptr; + srcWidth = (int) pBitmap->devKind >> PWSH; + + pixel = devPriv->xor; + xoff = xOrg & PIM; + nBitmapLongs = (dx + xoff) >> MFB_PWSH; + nPixmapLongs = (dx + PGSZB + xoff) >> PWSH; + + rightMask = ~cfb8BitLenMasks[((dx + xoff) & MFB_PIM)]; + + pdstLine = pdstBase + (yOrg * dstWidth) + (xOrg >> PWSH); + + while (dy--) + { + c = 0; + nPixmapTmp = nPixmapLongs; + nBitmapTmp = nBitmapLongs; + src = psrcLine; + dst = pdstLine; + while (nBitmapTmp--) + { + bits = *src++; + c |= BitRight (bits, xoff); + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + nPixmapTmp -= 8; + c = 0; + if (xoff) + c = BitLeft (bits, PGSZ - xoff); + } + if (BitLeft (rightMask, xoff)) + c |= BitRight (*src, xoff); + c &= rightMask; + switch (nPixmapTmp) { + case 8: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 7: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 6: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 5: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 4: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 3: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 2: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 1: + WriteBitGroup(dst, pixel, GetBitGroup(c)); + NextBitGroup(c); + dst++; + case 0: + break; + } + pdstLine += dstWidth; + psrcLine += srcWidth; + } +} + +#endif diff --git a/cfb/cfbrctstp8.c b/cfb/cfbrctstp8.c new file mode 100644 index 000000000..9b9db7462 --- /dev/null +++ b/cfb/cfbrctstp8.c @@ -0,0 +1,588 @@ +/* + * Fill 32 bit stippled rectangles for 8 bit frame buffers + */ +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Keith Packard, MIT X Consortium + +*/ + +/* $Xorg: cfbrctstp8.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ + +#if PSZ == 8 + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "gcstruct.h" +#include "window.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "windowstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" + +#define MFB_CONSTS_ONLY +#include "maskbits.h" + +void +cfb8FillRectOpaqueStippled32 (pDrawable, pGC, nBox, pBox) + DrawablePtr pDrawable; + GCPtr pGC; + int nBox; /* number of boxes to fill */ + register BoxPtr pBox; /* pointer to list of boxes to fill */ +{ + unsigned long *src; + int stippleHeight; + + int nlwDst; /* width in longwords of the dest pixmap */ + int w; /* width of current box */ + register int h; /* height of current box */ + unsigned long startmask; + unsigned long endmask; /* masks for reggedy bits at either end of line */ + int nlwMiddle; /* number of longwords between sides of boxes */ + register int nlw; /* loop version of nlwMiddle */ + unsigned long *dstLine; + register unsigned long *dst; /* pointer to bits we're writing */ + unsigned long *dstTmp; + int y; /* current scan line */ + + unsigned long *pbits;/* pointer to start of pixmap */ + register unsigned long bits; /* bits from stipple */ + int rot, lastStop, i; + register unsigned long xor, and; + cfbPrivGCPtr devPriv; + PixmapPtr stipple; + int wEnd; + + devPriv = cfbGetGCPrivate(pGC); + stipple = devPriv->pRotatedPixmap; + + cfb8CheckOpaqueStipple(pGC->alu, pGC->fgPixel, pGC->bgPixel, pGC->planemask); + + stippleHeight = stipple->drawable.height; + src = (unsigned long *)stipple->devPrivate.ptr; + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pbits) + + while (nBox--) + { + w = pBox->x2 - pBox->x1; + h = pBox->y2 - pBox->y1; + y = pBox->y1; + dstLine = pbits + (pBox->y1 * nlwDst) + ((pBox->x1 & ~PIM) >> PWSH); + if (((pBox->x1 & PIM) + w) <= PPW) + { + maskpartialbits(pBox->x1, w, startmask); + nlwMiddle = 0; + endmask = 0; + } + else + { + maskbits (pBox->x1, w, startmask, endmask, nlwMiddle); + } + rot = (pBox->x1 & ((PGSZ-1) & ~PIM)); + pBox++; + y = y % stippleHeight; + if (cfb8StippleRRop == GXcopy) + { + if (w < PGSZ*2) + { + while (h--) + { + bits = src[y]; + y++; + if (y == stippleHeight) + y = 0; + if (rot) + RotBitsLeft(bits,rot); + dst = dstLine; + dstLine += nlwDst; + if (startmask) + { + *dst = *dst & ~startmask | + GetPixelGroup (bits) & startmask; + dst++; + RotBitsLeft (bits, PGSZB); + } + nlw = nlwMiddle; + while (nlw--) + { + *dst++ = GetPixelGroup(bits); + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + *dst = *dst & ~endmask | + GetPixelGroup (bits) & endmask; + } + } + } + else + { + wEnd = 7 - (nlwMiddle & 7); + nlwMiddle = (nlwMiddle >> 3) + 1; + while (h--) + { + bits = src[y]; + y++; + if (y == stippleHeight) + y = 0; + if (rot != 0) + RotBitsLeft (bits, rot); + dstTmp = dstLine; + dstLine += nlwDst; + if (startmask) + { + *dstTmp = *dstTmp & ~startmask | + GetPixelGroup (bits) & startmask; + dstTmp++; + RotBitsLeft (bits, PGSZB); + } + w = 7 - wEnd; + while (w--) + { + nlw = nlwMiddle; + dst = dstTmp; + dstTmp++; + xor = GetPixelGroup (bits); + while (nlw--) + { + *dst = xor; + dst += 8; + } + NextBitGroup (bits); + } + nlwMiddle--; + w = wEnd + 1; + if (endmask) + { + dst = dstTmp + (nlwMiddle << 3); + *dst = (*dst & ~endmask) | + GetPixelGroup (bits) & endmask; + } + while (w--) + { + nlw = nlwMiddle; + dst = dstTmp; + dstTmp++; + xor = GetPixelGroup (bits); + while (nlw--) + { + *dst = xor; + dst += 8; + } + NextBitGroup (bits); + } + nlwMiddle++; + } + } + } + else + { + while (h--) + { + bits = src[y]; + y++; + if (y == stippleHeight) + y = 0; + if (rot) + RotBitsLeft(bits,rot); + dst = dstLine; + dstLine += nlwDst; + if (startmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, startmask); + dst++; + RotBitsLeft (bits, PGSZB); + } + nlw = nlwMiddle; + while (nlw--) + { + RRopBitGroup(dst, GetBitGroup(bits)); + dst++; + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, endmask); + } + } + } + } +} + +void +cfb8FillRectTransparentStippled32 (pDrawable, pGC, nBox, pBox) + DrawablePtr pDrawable; + GCPtr pGC; + int nBox; /* number of boxes to fill */ + BoxPtr pBox; /* pointer to list of boxes to fill */ +{ + int x, y, w, h; + int nlwMiddle, nlwDst, nlwTmp; + unsigned long startmask, endmask; + register unsigned long *dst; + unsigned long *dstLine, *pbits, *dstTmp; + unsigned long *src; + register unsigned long xor; + register unsigned long bits, mask; + int rot; + int wEnd; + cfbPrivGCPtr devPriv; + PixmapPtr stipple; + int stippleHeight; + register int nlw; + + devPriv = cfbGetGCPrivate(pGC); + stipple = devPriv->pRotatedPixmap; + src = (unsigned long *)stipple->devPrivate.ptr; + stippleHeight = stipple->drawable.height; + + cfb8CheckStipple (pGC->alu, pGC->fgPixel, pGC->planemask); + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pbits) + + while (nBox--) + { + x = pBox->x1; + w = pBox->x2 - x; + if (((x & PIM) + w) <= PPW) + { + maskpartialbits(x, w, startmask); + endmask = 0; + nlwMiddle = 0; + } + else + { + maskbits (x, w, startmask, endmask, nlwMiddle); + } + rot = (x & ((PGSZ-1) & ~PIM)); + y = pBox->y1; + dstLine = pbits + (y * nlwDst) + (x >> PWSH); + h = pBox->y2 - y; + pBox++; + y %= stippleHeight; + if (cfb8StippleRRop == GXcopy) + { + xor = devPriv->xor; + if (w < PGSZ*2) + { + while (h--) + { + bits = src[y]; + y++; + if (y == stippleHeight) + y = 0; + if (rot != 0) + RotBitsLeft (bits, rot); + dst = dstLine; + dstLine += nlwDst; + if (startmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + *dst = (*dst & ~(mask & startmask)) | + (xor & (mask & startmask)); + dst++; + RotBitsLeft (bits, PGSZB); + } + nlw = nlwMiddle; + while (nlw--) + { + WriteBitGroup (dst,xor,GetBitGroup(bits)) + dst++; + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + *dst = (*dst & ~(mask & endmask)) | + (xor & (mask & endmask)); + } + } + } + else + { + wEnd = 7 - (nlwMiddle & 7); + nlwMiddle = (nlwMiddle >> 3) + 1; + while (h--) + { + bits = src[y]; + y++; + if (y == stippleHeight) + y = 0; + if (rot != 0) + RotBitsLeft (bits, rot); + dstTmp = dstLine; + dstLine += nlwDst; + if (startmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + *dstTmp = (*dstTmp & ~(mask & startmask)) | + (xor & (mask & startmask)); + dstTmp++; + RotBitsLeft (bits, PGSZB); + } + w = 7 - wEnd; + while (w--) + { + nlw = nlwMiddle; + dst = dstTmp; + dstTmp++; +#if defined(__GNUC__) && defined(mc68020) + mask = cfb8PixelMasks[GetBitGroup(bits)]; + xor = xor & mask; + mask = ~mask; + while (nlw--) + { + *dst = (*dst & mask) | xor; + dst += 8; + } + xor = devPriv->xor; +#else +#define SwitchBitsLoop(body) \ + while (nlw--) \ + { \ + body \ + dst += 8; \ + } + SwitchBitGroup(dst, xor, GetBitGroup(bits)); +#undef SwitchBitsLoop +#endif + NextBitGroup (bits); + } + nlwMiddle--; + w = wEnd + 1; + if (endmask) + { + mask = cfb8PixelMasks[GetBitGroup(bits)]; + dst = dstTmp + (nlwMiddle << 3); + *dst = (*dst & ~(mask & endmask)) | + (xor & (mask & endmask)); + } + while (w--) + { + nlw = nlwMiddle; + dst = dstTmp; + dstTmp++; +#if defined(__GNUC__) && defined(mc68020) + mask = cfb8PixelMasks[GetBitGroup(bits)]; + xor = xor & mask; + mask = ~mask; + while (nlw--) + { + *dst = (*dst & mask) | xor; + dst += 8; + } + xor = devPriv->xor; +#else +#define SwitchBitsLoop(body) \ + while (nlw--) \ + { \ + body \ + dst += 8; \ + } + SwitchBitGroup(dst, xor, GetBitGroup(bits)); +#undef SwitchBitsLoop +#endif + NextBitGroup (bits); + } + nlwMiddle++; + } + } + } + else + { + while (h--) + { + bits = src[y]; + y++; + if (y == stippleHeight) + y = 0; + if (rot != 0) + RotBitsLeft (bits, rot); + dst = dstLine; + dstLine += nlwDst; + if (startmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, startmask); + dst++; + RotBitsLeft (bits, PGSZB); + } + nlw = nlwMiddle; + while (nlw--) + { + RRopBitGroup(dst, GetBitGroup(bits)); + dst++; + RotBitsLeft (bits, PGSZB); + } + if (endmask) + { + xor = GetBitGroup(bits); + *dst = MaskRRopPixels(*dst, xor, endmask); + } + } + } + } +} + + +void +cfb8FillRectStippledUnnatural (pDrawable, pGC, nBox, pBox) + DrawablePtr pDrawable; + GCPtr pGC; + int nBox; + register BoxPtr pBox; +{ + unsigned long *pdstBase; /* pointer to start of bitmap */ + unsigned long *pdstLine; /* current destination line */ + int nlwDst; /* width in longwords of bitmap */ + PixmapPtr pStipple; /* pointer to stipple we want to fill with */ + int nlwMiddle; + register int nlw; + int x, y, w, h, xrem, xSrc, ySrc; + int stwidth, stippleWidth; + int stippleHeight; + register unsigned long bits, inputBits; + register int partBitsLeft; + int nextPartBits; + int bitsLeft, bitsWhole; + register unsigned long *pdst; /* pointer to current word in bitmap */ + unsigned long *srcTemp, *srcStart; + unsigned long *psrcBase; + unsigned long startmask, endmask; + + if (pGC->fillStyle == FillStippled) + cfb8CheckStipple (pGC->alu, pGC->fgPixel, pGC->planemask); + else + cfb8CheckOpaqueStipple (pGC->alu, pGC->fgPixel, pGC->bgPixel, pGC->planemask); + + if (cfb8StippleRRop == GXnoop) + return; + + /* + * OK, so what's going on here? We have two Drawables: + * + * The Stipple: + * Depth = 1 + * Width = stippleWidth + * Words per scanline = stwidth + * Pointer to pixels = pStipple->devPrivate.ptr + */ + + pStipple = pGC->stipple; + + stwidth = pStipple->devKind >> PWSH; + stippleWidth = pStipple->drawable.width; + stippleHeight = pStipple->drawable.height; + psrcBase = (unsigned long *) pStipple->devPrivate.ptr; + + /* + * The Target: + * Depth = PSZ + * Width = determined from *pwidth + * Words per scanline = nlwDst + * Pointer to pixels = addrlBase + */ + + xSrc = pDrawable->x; + ySrc = pDrawable->y; + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pdstBase) + + /* this replaces rotating the stipple. Instead we just adjust the offset + * at which we start grabbing bits from the stipple. + * Ensure that ppt->x - xSrc >= 0 and ppt->y - ySrc >= 0, + * so that iline and xrem always stay within the stipple bounds. + */ + + xSrc += (pGC->patOrg.x % stippleWidth) - stippleWidth; + ySrc += (pGC->patOrg.y % stippleHeight) - stippleHeight; + + bitsWhole = stippleWidth; + + while (nBox--) + { + x = pBox->x1; + y = pBox->y1; + w = pBox->x2 - x; + h = pBox->y2 - y; + pBox++; + pdstLine = pdstBase + y * nlwDst + (x >> PWSH); + y = (y - ySrc) % stippleHeight; + srcStart = psrcBase + y * stwidth; + xrem = ((x & ~PIM) - xSrc) % stippleWidth; + if (((x & PIM) + w) < PPW) + { + maskpartialbits (x, w, startmask); + nlwMiddle = 0; + endmask = 0; + } + else + { + maskbits (x, w, startmask, endmask, nlwMiddle); + } + while (h--) + { + srcTemp = srcStart + (xrem >> MFB_PWSH); + bitsLeft = stippleWidth - (xrem & ~MFB_PIM); + NextUnnaturalStippleWord + NextSomeBits (inputBits, (xrem & MFB_PIM)); + partBitsLeft -= (xrem & MFB_PIM); + NextUnnaturalStippleBits + nlw = nlwMiddle; + pdst = pdstLine; + if (startmask) + { + *pdst = MaskRRopPixels(*pdst,bits,startmask); + pdst++; + NextUnnaturalStippleBits + } + while (nlw--) + { + *pdst = RRopPixels(*pdst,bits); + pdst++; + NextUnnaturalStippleBits + } + if (endmask) + *pdst = MaskRRopPixels(*pdst,bits,endmask); + pdstLine += nlwDst; + y++; + srcStart += stwidth; + if (y == stippleHeight) + { + y = 0; + srcStart = psrcBase; + } + } + } +} + +#endif /* PSZ == 8 */ diff --git a/cfb/cfbrrop.c b/cfb/cfbrrop.c new file mode 100644 index 000000000..69ec0278d --- /dev/null +++ b/cfb/cfbrrop.c @@ -0,0 +1,221 @@ +/* + * $Xorg: cfbrrop.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* cfb reduced rasterop computations */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "cfb.h" +#include "cfbmskbits.h" + +/* A description: + * + * There are four possible operations on each bit in the destination word, + * + * 1 2 3 4 + * + * 0 0 0 1 1 + * 1 0 1 0 1 + * + * On examination of the reduced rop equation (dst = (dst & and) ^ xor), + * these four fall to reduced rops as follows: + * + * and 0 1 1 0 + * xor 0 0 1 1 + * + * or, (if 'and' is expensive) (dst = (dst | or) ^ xor) + * + * or 1 0 0 1 + * xor 1 0 1 0 + * + * The trouble with using this later equation is that trivial + * rasterop reduction is more difficult; some common rasterops + * use complicated expressions of xor/and instead of the simple + * ones while other common rasterops are not made any simpler: + * + * GXcopy: *dst = ~xor instead of *dst = xor + * GXand: *dst = *dst & ~or instead of *dst = *dst & and + * GXor: *dst = *dst | or instead of *dst = *dst | xor + * GXxor: *dst = *dst ^ xor instead of *dst = *dst ^ xor + * + * If you're really set on using this second mechanism, the changes + * are pretty simple. + * + * All that remains is to provide a mechanism for computing and/xor values + * based on the raster op and foreground value. + * + * The 16 rops fall as follows, with the associated reduced + * rop and/xor and or/xor values. The values in parenthesis following the + * reduced values gives an equation using the source value for + * the reduced value, and is one of {0, src, ~src, 1} as appropriate. + * + * clear and andReverse copy + * src 0 1 0 1 0 1 0 1 + * dst 0 0 0 0 0 0 0 0 1 0 0 1 + * 1 0 0 1 0 1 1 0 0 1 0 1 + * + * and 0 0 (0) 0 1 (src) 0 1 (src) 0 0 (0) + * xor 0 0 (0) 0 0 (0) 0 1 (src) 0 1 (src) + * + * or 1 1 (1) 1 0 (~src) 1 0 (~src) 1 1 (1) + * xor 1 1 (1) 1 0 (~src) 1 1 (1) 1 0 (~src) + * + * andInverted noop xor or + * src 0 1 0 1 0 1 0 1 + * dst 0 0 0 0 0 0 0 0 1 0 0 1 + * 1 1 0 1 1 1 1 1 0 1 1 1 + * + * and 1 0 (~src) 1 1 (1) 1 1 (1) 1 0 (~src) + * xor 0 0 (0) 0 0 (0) 0 1 (src) 0 1 (src) + * + * or 0 1 (src) 0 0 (0) 0 0 (0) 0 1 (src) + * xor 0 1 (src) 0 0 (0) 0 1 (src) 0 0 (0) + * + * nor equiv invert orReverse + * src 0 1 0 1 0 1 0 1 + * dst 0 1 0 0 1 0 0 1 1 0 1 1 + * 1 0 0 1 0 1 1 0 0 1 0 1 + * + * and 1 0 (~src) 1 1 (1) 1 1 (1) 1 0 (~src) + * xor 1 0 (~src) 1 0 (~src) 1 1 (1) 1 1 (1) + * + * or 0 1 (src) 0 0 (0) 0 0 (0) 0 1 (src) + * xor 1 1 (1) 1 0 (~src) 1 1 (1) 1 0 (~src) + * + * copyInverted orInverted nand set + * src 0 1 0 1 0 1 0 1 + * dst 0 1 0 0 1 0 0 1 1 0 1 1 + * 1 1 0 1 1 1 1 1 0 1 1 1 + * + * and 0 0 (0) 0 1 (src) 0 1 (src) 0 0 (0) + * xor 1 0 (~src) 1 0 (~src) 1 1 (1) 1 1 (1) + * + * or 1 1 (1) 1 0 (~src) 1 0 (~src) 1 1 (1) + * xor 0 1 (src) 0 0 (0) 0 1 (src) 0 0 (0) + */ + +int +cfbReduceRasterOp (rop, fg, pm, andp, xorp) + int rop; + unsigned long fg, pm; + unsigned long *andp, *xorp; +{ + unsigned long and, xor; + int rrop; + + fg = PFILL (fg); + pm = PFILL (pm); + switch (rop) + { + case GXclear: + and = 0; + xor = 0; + break; + case GXand: + and = fg; + xor = 0; + break; + case GXandReverse: + and = fg; + xor = fg; + break; + case GXcopy: + and = 0; + xor = fg; + break; + case GXandInverted: + and = ~fg; + xor = 0; + break; + case GXnoop: + and = ~0; + xor = 0; + break; + case GXxor: + and = ~0; + xor = fg; + break; + case GXor: + and = ~fg; + xor = fg; + break; + case GXnor: + and = ~fg; + xor = ~fg; + break; + case GXequiv: + and = ~0; + xor = ~fg; + break; + case GXinvert: + and = ~0; + xor = ~0; + break; + case GXorReverse: + and = ~fg; + xor = ~0; + break; + case GXcopyInverted: + and = 0; + xor = ~fg; + break; + case GXorInverted: + and = fg; + xor = ~fg; + break; + case GXnand: + and = fg; + xor = ~0; + break; + case GXset: + and = 0; + xor = ~0; + break; + } + and |= ~pm; + xor &= pm; + *andp = and; + *xorp = xor; + /* check for some special cases to reduce computation */ + if (and == 0) + rrop = GXcopy; + /* nothing checks for GXnoop + else if (and == ~0 && xor == 0) + rrop = GXnoop; + */ + else if (and == ~0) + rrop = GXxor; + else if (xor == 0) + rrop = GXand; + else if ( (and ^ xor) == ~0) /* fix XBUG 6541 */ + rrop = GXor; + else + rrop = GXset; /* rop not reduced */ + return rrop; +} diff --git a/cfb/cfbrrop.h b/cfb/cfbrrop.h new file mode 100644 index 000000000..4423e040d --- /dev/null +++ b/cfb/cfbrrop.h @@ -0,0 +1,150 @@ +/* + * $Xorg: cfbrrop.h,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef GXcopy +#include "X.h" +#endif + +#define RROP_FETCH_GC(gc) \ + RROP_FETCH_GCPRIV(((cfbPrivGCPtr)(gc)->devPrivates[cfbGCPrivateIndex].ptr)) + +#ifndef RROP +#define RROP GXset +#endif + +#if RROP == GXcopy +#define RROP_DECLARE register unsigned long rrop_xor; +#define RROP_FETCH_GCPRIV(devPriv) rrop_xor = (devPriv)->xor; +#define RROP_SOLID(dst) (*(dst) = (rrop_xor)) +#define RROP_SOLID_MASK(dst,mask) (*(dst) = (*(dst) & ~(mask)) | ((rrop_xor) & (mask))) +#define RROP_NAME(prefix) RROP_NAME_CAT(prefix,Copy) +#endif /* GXcopy */ + +#if RROP == GXxor +#define RROP_DECLARE register unsigned long rrop_xor; +#define RROP_FETCH_GCPRIV(devPriv) rrop_xor = (devPriv)->xor; +#define RROP_SOLID(dst) (*(dst) ^= (rrop_xor)) +#define RROP_SOLID_MASK(dst,mask) (*(dst) ^= ((rrop_xor) & (mask))) +#define RROP_NAME(prefix) RROP_NAME_CAT(prefix,Xor) +#endif /* GXxor */ + +#if RROP == GXand +#define RROP_DECLARE register unsigned long rrop_and; +#define RROP_FETCH_GCPRIV(devPriv) rrop_and = (devPriv)->and; +#define RROP_SOLID(dst) (*(dst) &= (rrop_and)) +#define RROP_SOLID_MASK(dst,mask) (*(dst) &= ((rrop_and) | ~(mask))) +#define RROP_NAME(prefix) RROP_NAME_CAT(prefix,And) +#endif /* GXand */ + +#if RROP == GXor +#define RROP_DECLARE register unsigned long rrop_or; +#define RROP_FETCH_GCPRIV(devPriv) rrop_or = (devPriv)->xor; +#define RROP_SOLID(dst) (*(dst) |= (rrop_or)) +#define RROP_SOLID_MASK(dst,mask) (*(dst) |= ((rrop_or) & (mask))) +#define RROP_NAME(prefix) RROP_NAME_CAT(prefix,Or) +#endif /* GXor */ + +#if RROP == GXnoop +#define RROP_DECLARE +#define RROP_FETCH_GCPRIV(devPriv) +#define RROP_SOLID(dst) +#define RROP_SOLID_MASK(dst,mask) +#define RROP_NAME(prefix) RROP_NAME_CAT(prefix,Noop) +#endif /* GXnoop */ + +#if RROP == GXset +#define RROP_DECLARE register unsigned long rrop_and, rrop_xor; +#define RROP_FETCH_GCPRIV(devPriv) rrop_and = (devPriv)->and; \ + rrop_xor = (devPriv)->xor; +#define RROP_SOLID(dst) (*(dst) = DoRRop (*(dst), rrop_and, rrop_xor)) +#define RROP_SOLID_MASK(dst,mask) (*(dst) = DoMaskRRop (*(dst), rrop_and, rrop_xor, (mask))) +#define RROP_NAME(prefix) RROP_NAME_CAT(prefix,General) +#endif /* GXset */ + +#define RROP_UNROLL_CASE1(p,i) case (i): RROP_SOLID((p) - (i)); +#define RROP_UNROLL_CASE2(p,i) RROP_UNROLL_CASE1(p,(i)+1) RROP_UNROLL_CASE1(p,i) +#define RROP_UNROLL_CASE4(p,i) RROP_UNROLL_CASE2(p,(i)+2) RROP_UNROLL_CASE2(p,i) +#define RROP_UNROLL_CASE8(p,i) RROP_UNROLL_CASE4(p,(i)+4) RROP_UNROLL_CASE4(p,i) +#define RROP_UNROLL_CASE16(p,i) RROP_UNROLL_CASE8(p,(i)+8) RROP_UNROLL_CASE8(p,i) +#define RROP_UNROLL_CASE3(p) RROP_UNROLL_CASE2(p,2) RROP_UNROLL_CASE1(p,1) +#define RROP_UNROLL_CASE7(p) RROP_UNROLL_CASE4(p,4) RROP_UNROLL_CASE3(p) +#define RROP_UNROLL_CASE15(p) RROP_UNROLL_CASE8(p,8) RROP_UNROLL_CASE7(p) +#define RROP_UNROLL_CASE31(p) RROP_UNROLL_CASE16(p,16) RROP_UNROLL_CASE15(p) +#ifdef LONG64 +#define RROP_UNROLL_CASE63(p) RROP_UNROLL_CASE32(p,32) RROP_UNROLL_CASE31(p) +#endif /* LONG64 */ + +#define RROP_UNROLL_LOOP1(p,i) RROP_SOLID((p) + (i)); +#define RROP_UNROLL_LOOP2(p,i) RROP_UNROLL_LOOP1(p,(i)) RROP_UNROLL_LOOP1(p,(i)+1) +#define RROP_UNROLL_LOOP4(p,i) RROP_UNROLL_LOOP2(p,(i)) RROP_UNROLL_LOOP2(p,(i)+2) +#define RROP_UNROLL_LOOP8(p,i) RROP_UNROLL_LOOP4(p,(i)) RROP_UNROLL_LOOP4(p,(i)+4) +#define RROP_UNROLL_LOOP16(p,i) RROP_UNROLL_LOOP8(p,(i)) RROP_UNROLL_LOOP8(p,(i)+8) +#define RROP_UNROLL_LOOP32(p,i) RROP_UNROLL_LOOP16(p,(i)) RROP_UNROLL_LOOP16(p,(i)+16) +#ifdef LONG64 +#define RROP_UNROLL_LOOP64(p,i) RROP_UNROLL_LOOP32(p,(i)) RROP_UNROLL_LOOP32(p,(i)+32) +#endif /* LONG64 */ + +#if defined (FAST_CONSTANT_OFFSET_MODE) && defined (SHARED_IDCACHE) && (RROP == GXcopy) + +#ifdef LONG64 +#define RROP_UNROLL_SHIFT 6 +#define RROP_UNROLL_CASE(p) RROP_UNROLL_CASE63(p) +#define RROP_UNROLL_LOOP(p) RROP_UNROLL_LOOP64(p,-64) +#else /* not LONG64 */ +#define RROP_UNROLL_SHIFT 5 +#define RROP_UNROLL_CASE(p) RROP_UNROLL_CASE31(p) +#define RROP_UNROLL_LOOP(p) RROP_UNROLL_LOOP32(p,-32) +#endif /* LONG64 */ +#define RROP_UNROLL (1<>= RROP_UNROLL_SHIFT; \ + (pdst) += part * (sizeof (unsigned long) / sizeof (*pdst)); \ + switch (part) {\ + RROP_UNROLL_CASE((unsigned long *) (pdst)) \ + } \ + while (--(nmiddle) >= 0) { \ + (pdst) += RROP_UNROLL * (sizeof (unsigned long) / sizeof (*pdst)); \ + RROP_UNROLL_LOOP((unsigned long *) (pdst)) \ + } \ +} +#else +#define RROP_SPAN(pdst,nmiddle) \ + while (--(nmiddle) >= 0) { \ + RROP_SOLID((unsigned long *) (pdst)); \ + (pdst) += sizeof (unsigned long) / sizeof (*pdst); \ + } +#endif + +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define RROP_NAME_CAT(prefix,suffix) prefix##suffix +#else +#define RROP_NAME_CAT(prefix,suffix) prefix/**/suffix +#endif diff --git a/cfb/cfbscrinit.c b/cfb/cfbscrinit.c new file mode 100644 index 000000000..ad8bee4f5 --- /dev/null +++ b/cfb/cfbscrinit.c @@ -0,0 +1,195 @@ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ +/* $Xorg: cfbscrinit.c,v 1.3 2000/08/17 19:48:15 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "resource.h" +#include "colormap.h" +#include "colormapst.h" +#include "cfb.h" +#include "mi.h" +#include "mistruct.h" +#include "dix.h" +#include "cfbmskbits.h" +#include "mibstore.h" + + +miBSFuncRec cfbBSFuncRec = { + cfbSaveAreas, + cfbRestoreAreas, + (void (*)()) 0, + (PixmapPtr (*)()) 0, + (PixmapPtr (*)()) 0, +}; + +Bool +cfbCloseScreen (index, pScreen) + int index; + ScreenPtr pScreen; +{ + int d; + DepthPtr depths = pScreen->allowedDepths; + + for (d = 0; d < pScreen->numDepths; d++) + xfree (depths[d].vids); + xfree (depths); + xfree (pScreen->visuals); +#ifdef CFB_NEED_SCREEN_PRIVATE + xfree (pScreen->devPrivates[cfbScreenPrivateIndex].ptr); +#else + xfree (pScreen->devPrivate); +#endif + return TRUE; +} + +Bool +cfbSetupScreen(pScreen, pbits, xsize, ysize, dpix, dpiy, width) + register ScreenPtr pScreen; + pointer pbits; /* pointer to screen bitmap */ + int xsize, ysize; /* in pixels */ + int dpix, dpiy; /* dots per inch */ + int width; /* pixel width of frame buffer */ +{ + int i; + extern RegionPtr (*cfbPuntCopyPlane)(); + + if (!cfbAllocatePrivates(pScreen, (int *) 0, (int *) 0)) + return FALSE; + pScreen->defColormap = FakeClientID(0); + /* let CreateDefColormap do whatever it wants for pixels */ + pScreen->blackPixel = pScreen->whitePixel = (Pixel) 0; + pScreen->QueryBestSize = mfbQueryBestSize; + /* SaveScreen */ + pScreen->GetImage = cfbGetImage; + pScreen->GetSpans = cfbGetSpans; + pScreen->CreateWindow = cfbCreateWindow; + pScreen->DestroyWindow = cfbDestroyWindow; + pScreen->PositionWindow = cfbPositionWindow; + pScreen->ChangeWindowAttributes = cfbChangeWindowAttributes; + pScreen->RealizeWindow = cfbMapWindow; + pScreen->UnrealizeWindow = cfbUnmapWindow; + pScreen->PaintWindowBackground = cfbPaintWindow; + pScreen->PaintWindowBorder = cfbPaintWindow; + pScreen->CopyWindow = cfbCopyWindow; + pScreen->CreatePixmap = cfbCreatePixmap; + pScreen->DestroyPixmap = cfbDestroyPixmap; + pScreen->RealizeFont = mfbRealizeFont; + pScreen->UnrealizeFont = mfbUnrealizeFont; + pScreen->CreateGC = cfbCreateGC; + pScreen->CreateColormap = cfbInitializeColormap; + pScreen->DestroyColormap = (void (*)())NoopDDA; +#ifdef STATIC_COLOR + pScreen->InstallColormap = cfbInstallColormap; + pScreen->UninstallColormap = cfbUninstallColormap; + pScreen->ListInstalledColormaps = cfbListInstalledColormaps; + pScreen->StoreColors = (void (*)())NoopDDA; +#endif + pScreen->ResolveColor = cfbResolveColor; + pScreen->BitmapToRegion = mfbPixmapToRegion; + + mfbRegisterCopyPlaneProc (pScreen, cfbCopyPlane); + return TRUE; +} + +#ifdef CFB_NEED_SCREEN_PRIVATE +Bool +cfbCreateScreenResources(pScreen) + ScreenPtr pScreen; +{ + Bool retval; + + pointer oldDevPrivate = pScreen->devPrivate; + pScreen->devPrivate = pScreen->devPrivates[cfbScreenPrivateIndex].ptr; + retval = miCreateScreenResources(pScreen); + pScreen->devPrivates[cfbScreenPrivateIndex].ptr = pScreen->devPrivate; + pScreen->devPrivate = oldDevPrivate; + return retval; +} +#endif + +cfbFinishScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width) + register ScreenPtr pScreen; + pointer pbits; /* pointer to screen bitmap */ + int xsize, ysize; /* in pixels */ + int dpix, dpiy; /* dots per inch */ + int width; /* pixel width of frame buffer */ +{ + int i, j; +#ifdef CFB_NEED_SCREEN_PRIVATE + pointer oldDevPrivate; +#endif + VisualPtr visuals; + DepthPtr depths; + int nvisuals; + int ndepths; + int rootdepth; + VisualID defaultVisual; + + rootdepth = 0; + if (!cfbInitVisuals (&visuals, &depths, &nvisuals, &ndepths, &rootdepth, + &defaultVisual,((unsigned long)1<<(PSZ-1)), 8)) + return FALSE; +#ifdef CFB_NEED_SCREEN_PRIVATE + oldDevPrivate = pScreen->devPrivate; +#endif + if (! miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width, + rootdepth, ndepths, depths, + defaultVisual, nvisuals, visuals, + (miBSFuncPtr) 0)) + return FALSE; + /* overwrite miCloseScreen with our own */ + pScreen->CloseScreen = cfbCloseScreen; + /* init backing store here so we can overwrite CloseScreen without stepping + * on the backing store wrapped version */ + miInitializeBackingStore (pScreen, &cfbBSFuncRec); +#ifdef CFB_NEED_SCREEN_PRIVATE + pScreen->CreateScreenResources = cfbCreateScreenResources; + pScreen->devPrivates[cfbScreenPrivateIndex].ptr = pScreen->devPrivate; + pScreen->devPrivate = oldDevPrivate; +#endif + return TRUE; +} + +/* dts * (inch/dot) * (25.4 mm / inch) = mm */ +Bool +cfbScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width) + register ScreenPtr pScreen; + pointer pbits; /* pointer to screen bitmap */ + int xsize, ysize; /* in pixels */ + int dpix, dpiy; /* dots per inch */ + int width; /* pixel width of frame buffer */ +{ + if (!cfbSetupScreen(pScreen, pbits, xsize, ysize, dpix, dpiy, width)) + return FALSE; + return cfbFinishScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width); +} diff --git a/cfb/cfbsetsp.c b/cfb/cfbsetsp.c new file mode 100644 index 000000000..4a3d2fbfe --- /dev/null +++ b/cfb/cfbsetsp.c @@ -0,0 +1,280 @@ +/* $Xorg: cfbsetsp.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" + +#include "misc.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include + +/* cfbSetScanline -- copies the bits from psrc to the drawable starting at + * (xStart, y) and continuing to (xEnd, y). xOrigin tells us where psrc + * starts on the scanline. (I.e., if this scanline passes through multiple + * boxes, we may not want to start grabbing bits at psrc but at some offset + * further on.) + */ +cfbSetScanline(y, xOrigin, xStart, xEnd, psrc, alu, pdstBase, widthDst, planemask) + int y; + int xOrigin; /* where this scanline starts */ + int xStart; /* first bit to use from scanline */ + int xEnd; /* last bit to use from scanline + 1 */ + register unsigned int *psrc; + register int alu; /* raster op */ + int *pdstBase; /* start of the drawable */ + int widthDst; /* width of drawable in words */ + unsigned long planemask; +{ + int w; /* width of scanline in bits */ + register int *pdst; /* where to put the bits */ + register int tmpSrc; /* scratch buffer to collect bits in */ + int dstBit; /* offset in bits from beginning of + * word */ + register int nstart; /* number of bits from first partial */ + register int nend; /* " " last partial word */ + int offSrc; + int startmask, endmask, nlMiddle, nl; + DeclareMergeRop() + + InitializeMergeRop(alu,planemask); + pdst = pdstBase + (y * widthDst) + (xStart >> PWSH); + psrc += (xStart - xOrigin) >> PWSH; + offSrc = (xStart - xOrigin) & PIM; + w = xEnd - xStart; + dstBit = xStart & PIM; + + if (dstBit + w <= PPW) + { + maskpartialbits(dstBit, w, startmask); + endmask = 0; + nlMiddle = 0; + } + else + { + maskbits(xStart, w, startmask, endmask, nlMiddle); + } + if (startmask) + nstart = PPW - dstBit; + else + nstart = 0; + if (endmask) + nend = xEnd & PIM; + else + nend = 0; + if (startmask) + { + getbits(psrc, offSrc, nstart, tmpSrc); + putbitsmropshort(tmpSrc, dstBit, nstart, pdst); + pdst++; + offSrc += nstart; + if (offSrc > PLST) + { + psrc++; + offSrc -= PPW; + } + } + nl = nlMiddle; + while (nl--) + { + getbits(psrc, offSrc, PPW, tmpSrc); + *pdst = DoMergeRop(tmpSrc, *pdst); + pdst++; + psrc++; + } + if (endmask) + { + getbits(psrc, offSrc, nend, tmpSrc); + putbitsmropshort(tmpSrc, 0, nend, pdst); + } +} + + + +/* SetSpans -- for each span copy pwidth[i] bits from psrc to pDrawable at + * ppt[i] using the raster op from the GC. If fSorted is TRUE, the scanlines + * are in increasing Y order. + * Source bit lines are server scanline padded so that they always begin + * on a word boundary. + */ +void +cfbSetSpans(pDrawable, pGC, pcharsrc, ppt, pwidth, nspans, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + char *pcharsrc; + register DDXPointPtr ppt; + int *pwidth; + int nspans; + int fSorted; +{ + unsigned int *psrc = (unsigned int *)pcharsrc; + unsigned long *pdstBase; /* start of dst bitmap */ + int widthDst; /* width of bitmap in words */ + register BoxPtr pbox, pboxLast, pboxTest; + register DDXPointPtr pptLast; + int alu; + RegionPtr prgnDst; + int xStart, xEnd; + int yMax; + + alu = pGC->alu; + prgnDst = cfbGetCompositeClip(pGC); + pptLast = ppt + nspans; + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase) + + yMax = (int) pDrawable->y + (int) pDrawable->height; + + pbox = REGION_RECTS(prgnDst); + pboxLast = pbox + REGION_NUM_RECTS(prgnDst); + + if(fSorted) + { + /* scan lines sorted in ascending order. Because they are sorted, we + * don't have to check each scanline against each clip box. We can be + * sure that this scanline only has to be clipped to boxes at or after the + * beginning of this y-band + */ + pboxTest = pbox; + while(ppt < pptLast) + { + pbox = pboxTest; + if(ppt->y >= yMax) + break; + while(pbox < pboxLast) + { + if(pbox->y1 > ppt->y) + { + /* scanline is before clip box */ + break; + } + else if(pbox->y2 <= ppt->y) + { + /* clip box is before scanline */ + pboxTest = ++pbox; + continue; + } + else if(pbox->x1 > ppt->x + *pwidth) + { + /* clip box is to right of scanline */ + break; + } + else if(pbox->x2 <= ppt->x) + { + /* scanline is to right of clip box */ + pbox++; + continue; + } + + /* at least some of the scanline is in the current clip box */ + xStart = max(pbox->x1, ppt->x); + xEnd = min(ppt->x + *pwidth, pbox->x2); + cfbSetScanline(ppt->y, ppt->x, xStart, xEnd, psrc, alu, + (int *)pdstBase, widthDst, pGC->planemask); + if(ppt->x + *pwidth <= pbox->x2) + { + /* End of the line, as it were */ + break; + } + else + pbox++; + } + /* We've tried this line against every box; it must be outside them + * all. move on to the next point */ + ppt++; + psrc += PixmapWidthInPadUnits(*pwidth, pDrawable->depth); + pwidth++; + } + } + else + { + /* scan lines not sorted. We must clip each line against all the boxes */ + while(ppt < pptLast) + { + if(ppt->y >= 0 && ppt->y < yMax) + { + + for(pbox = REGION_RECTS(prgnDst); pbox< pboxLast; pbox++) + { + if(pbox->y1 > ppt->y) + { + /* rest of clip region is above this scanline, + * skip it */ + break; + } + if(pbox->y2 <= ppt->y) + { + /* clip box is below scanline */ + pbox++; + break; + } + if(pbox->x1 <= ppt->x + *pwidth && + pbox->x2 > ppt->x) + { + xStart = max(pbox->x1, ppt->x); + xEnd = min(pbox->x2, ppt->x + *pwidth); + cfbSetScanline(ppt->y, ppt->x, xStart, xEnd, psrc, alu, + (int *)pdstBase, widthDst, pGC->planemask); + } + + } + } + psrc += PixmapWidthInPadUnits(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } + } +} + diff --git a/cfb/cfbsolid.c b/cfb/cfbsolid.c new file mode 100644 index 000000000..ead63a757 --- /dev/null +++ b/cfb/cfbsolid.c @@ -0,0 +1,296 @@ +/* + * $Xorg: cfbsolid.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "gcstruct.h" +#include "window.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "windowstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfbrrop.h" + +#include "mi.h" +#include "mispans.h" + +#if defined(FAST_CONSTANT_OFFSET_MODE) && (RROP != GXcopy) +# define Expand(left,right,leftAdjust) {\ + int part = nmiddle & 3; \ + int widthStep; \ + widthStep = widthDst - nmiddle - leftAdjust; \ + nmiddle >>= 2; \ + pdst = pdstRect; \ + while (h--) { \ + left \ + pdst += part; \ + switch (part) { \ + RROP_UNROLL_CASE3(pdst) \ + } \ + m = nmiddle; \ + while (m) { \ + pdst += 4; \ + RROP_UNROLL_LOOP4(pdst,-4) \ + m--; \ + } \ + right \ + pdst += widthStep; \ + } \ +} +#else +# ifdef RROP_UNROLL +# define Expand(left,right,leftAdjust) {\ + int part = nmiddle & RROP_UNROLL_MASK; \ + int widthStep; \ + widthStep = widthDst - nmiddle - leftAdjust; \ + nmiddle >>= RROP_UNROLL_SHIFT; \ + pdst = pdstRect; \ + while (h--) { \ + left \ + pdst += part; \ + switch (part) { \ + RROP_UNROLL_CASE(pdst) \ + } \ + m = nmiddle; \ + while (m) { \ + pdst += RROP_UNROLL; \ + RROP_UNROLL_LOOP(pdst) \ + m--; \ + } \ + right \ + pdst += widthStep; \ + } \ +} + +# else +# define Expand(left, right, leftAdjust) { \ + while (h--) { \ + pdst = pdstRect; \ + left \ + m = nmiddle; \ + while (m--) {\ + RROP_SOLID(pdst); \ + pdst++; \ + } \ + right \ + pdstRect += widthDst; \ + } \ +} +# endif +#endif + + +void +RROP_NAME(cfbFillRectSolid) (pDrawable, pGC, nBox, pBox) + DrawablePtr pDrawable; + GCPtr pGC; + int nBox; + BoxPtr pBox; +{ + register int m; + register unsigned long *pdst; + RROP_DECLARE + register unsigned long leftMask, rightMask; + unsigned long *pdstBase, *pdstRect; + int nmiddle; + int h; + int w; + int widthDst; + cfbPrivGCPtr devPriv; + + devPriv = cfbGetGCPrivate(pGC); + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase) + + RROP_FETCH_GC(pGC) + + for (; nBox; nBox--, pBox++) + { + pdstRect = pdstBase + pBox->y1 * widthDst; + h = pBox->y2 - pBox->y1; + w = pBox->x2 - pBox->x1; +#if PSZ == 8 + if (w == 1) + { + register char *pdstb = ((char *) pdstRect) + pBox->x1; + int incr = widthDst * PGSZB; + + while (h--) + { + RROP_SOLID (pdstb); + pdstb += incr; + } + } + else + { +#endif + pdstRect += (pBox->x1 >> PWSH); + if ((pBox->x1 & PIM) + w <= PPW) + { + maskpartialbits(pBox->x1, w, leftMask); + pdst = pdstRect; + while (h--) { + RROP_SOLID_MASK (pdst, leftMask); + pdst += widthDst; + } + } + else + { + maskbits (pBox->x1, w, leftMask, rightMask, nmiddle); + if (leftMask) + { + if (rightMask) /* left mask and right mask */ + { + Expand(RROP_SOLID_MASK (pdst, leftMask); pdst++;, + RROP_SOLID_MASK (pdst, rightMask);, 1) + } + else /* left mask and no right mask */ + { + Expand(RROP_SOLID_MASK (pdst, leftMask); pdst++;, + ;, 1) + } + } + else + { + if (rightMask) /* no left mask and right mask */ + { + Expand(;, + RROP_SOLID_MASK (pdst, rightMask);, 0) + } + else /* no left mask and no right mask */ + { + Expand(;, + ;, 0) + } + } + } +#if PSZ == 8 + } +#endif + } +} + +void +RROP_NAME(cfbSolidSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + unsigned long *pdstBase; + int widthDst; + + RROP_DECLARE + + register unsigned long *pdst; + register int nlmiddle; + register unsigned long startmask, endmask; + register int w; + int x; + + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + DDXPointPtr ppt; /* pointer to list of start points */ + int *pwidthFree;/* copies of the pointers to free */ + DDXPointPtr pptFree; + int *pwidth; + cfbPrivGCPtr devPriv; + + devPriv = cfbGetGCPrivate(pGC); + RROP_FETCH_GCPRIV(devPriv) + n = nInit * miFindMaxBand(devPriv->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(devPriv->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase) + + while (n--) + { + x = ppt->x; + pdst = pdstBase + (ppt->y * widthDst); + ++ppt; + w = *pwidth++; + if (!w) + continue; +#if PSZ == 8 + if (w <= PGSZB) + { + register char *addrb; + + addrb = ((char *) pdst) + x; + while (w--) + { + RROP_SOLID (addrb); + addrb++; + } + } +#else + if ((x & PIM) + w <= PPW) + { + pdst += x >> PWSH; + maskpartialbits (x, w, startmask); + RROP_SOLID_MASK (pdst, startmask); + } +#endif + else + { + pdst += x >> PWSH; + maskbits (x, w, startmask, endmask, nlmiddle); + if (startmask) + { + RROP_SOLID_MASK (pdst, startmask); + ++pdst; + } + + RROP_SPAN(pdst,nlmiddle) + if (endmask) + { + RROP_SOLID_MASK (pdst, endmask); + } + } + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} diff --git a/cfb/cfbteblt8.c b/cfb/cfbteblt8.c new file mode 100644 index 000000000..7653e770b --- /dev/null +++ b/cfb/cfbteblt8.c @@ -0,0 +1,583 @@ +/* + * TEGblt - ImageText expanded glyph fonts only. For + * 8 bit displays, in Copy mode with no clipping. + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/* $Xorg: cfbteblt8.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */ + +#if PSZ == 8 + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "cfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" + +/* + * this code supports up to 5 characters at a time. The performance + * differences between 4 and 5 is usually small (~7% on PMAX) and + * frequently negative (SPARC and Sun3), so this file is compiled + * only once for now. If you want to use the other options, you'll + * need to hack cfbgc.c as well. + */ + +#ifndef NGLYPHS +#define NGLYPHS 4 +#define DO_COMMON +#endif + +#ifdef DO_COMMON +#define CFBTEGBLT8 cfbTEGlyphBlt8 +#endif + +/* + * On little-endian machines (or where fonts are padded to 32-bit + * boundaries) we can use some magic to avoid the expense of getleftbits + */ + +#if ((BITMAP_BIT_ORDER == LSBFirst && NGLYPHS >= 4) || GLYPHPADBYTES == 4) + +#if GLYPHPADBYTES == 1 +typedef unsigned char *glyphPointer; +#define USE_LEFTBITS +#endif + +#if GLYPHPADBYTES == 2 +typedef unsigned short *glyphPointer; +#define USE_LEFTBITS +#endif + +#if GLYPHPADBYTES == 4 +typedef unsigned int *glyphPointer; +#endif + +#define GetBitsL c = BitLeft (*leftChar++, lshift) +#define NGetBits1S(r) c = BitRight(*char1++ r, xoff1) +#define NGetBits1L(r) GetBitsL | BitRight(*char1++ r, xoff1) +#define NGetBits1U(r) c = *char1++ r +#define NGetBits2S(r) NGetBits1S(| BitRight(*char2++ r, widthGlyph)) +#define NGetBits2L(r) NGetBits1L(| BitRight(*char2++ r, widthGlyph)) +#define NGetBits2U(r) NGetBits1U(| BitRight(*char2++ r, widthGlyph)) +#define NGetBits3S(r) NGetBits2S(| BitRight(*char3++ r, widthGlyph)) +#define NGetBits3L(r) NGetBits2L(| BitRight(*char3++ r, widthGlyph)) +#define NGetBits3U(r) NGetBits2U(| BitRight(*char3++ r, widthGlyph)) +#define NGetBits4S(r) NGetBits3S(| BitRight(*char4++ r, widthGlyph)) +#define NGetBits4L(r) NGetBits3L(| BitRight(*char4++ r, widthGlyph)) +#define NGetBits4U(r) NGetBits3U(| BitRight(*char4++ r, widthGlyph)) +#define NGetBits5S(r) NGetBits4S(| BitRight(*char5++ r, widthGlyph)) +#define NGetBits5L(r) NGetBits4L(| BitRight(*char5++ r, widthGlyph)) +#define NGetBits5U(r) NGetBits4U(| BitRight(*char5++ r, widthGlyph)) +#define GetBits1S c = BitRight(*char1++, xoff1) +#define GetBits1L GetBitsL | BitRight(*char1++, xoff1) +#define GetBits1U c = *char1++ +#define GetBits2S NGetBits1S(| BitRight(*char2++, widthGlyph)) +#define GetBits2L NGetBits1L(| BitRight(*char2++, widthGlyph)) +#define GetBits2U NGetBits1U(| BitRight(*char2++, widthGlyph)) +#define GetBits3S NGetBits2S(| BitRight(*char3++, widthGlyph)) +#define GetBits3L NGetBits2L(| BitRight(*char3++, widthGlyph)) +#define GetBits3U NGetBits2U(| BitRight(*char3++, widthGlyph)) +#define GetBits4S NGetBits3S(| BitRight(*char4++, widthGlyph)) +#define GetBits4L NGetBits3L(| BitRight(*char4++, widthGlyph)) +#define GetBits4U NGetBits3U(| BitRight(*char4++, widthGlyph)) +#define GetBits5S NGetBits4S(| BitRight(*char5++, widthGlyph)) +#define GetBits5L NGetBits4L(| BitRight(*char5++, widthGlyph)) +#define GetBits5U NGetBits4U(| BitRight(*char5++, widthGlyph)) + +#else + +typedef unsigned int *glyphPointer; + +#define USE_LEFTBITS +#define ALL_LEFTBITS + +#define GetBitsL WGetBitsL +#define GetBits1S WGetBits1S +#define GetBits1L WGetBits1L +#define GetBits1U WGetBits1U + +#define GetBits2S GetBits1S Get1Bits (char2, tmpSrc) \ + c |= BitRight(tmpSrc, xoff2); +#define GetBits2L GetBits1L Get1Bits (char2, tmpSrc) \ + c |= BitRight(tmpSrc, xoff2); +#define GetBits2U GetBits1U Get1Bits (char2, tmpSrc) \ + c |= BitRight(tmpSrc, xoff2); + +#define GetBits3S GetBits2S Get1Bits (char3, tmpSrc) \ + c |= BitRight(tmpSrc, xoff3); +#define GetBits3L GetBits2L Get1Bits (char3, tmpSrc) \ + c |= BitRight(tmpSrc, xoff3); +#define GetBits3U GetBits2U Get1Bits (char3, tmpSrc) \ + c |= BitRight(tmpSrc, xoff3); + +#define GetBits4S GetBits3S Get1Bits (char4, tmpSrc) \ + c |= BitRight(tmpSrc, xoff4); +#define GetBits4L GetBits3L Get1Bits (char4, tmpSrc) \ + c |= BitRight(tmpSrc, xoff4); +#define GetBits4U GetBits3U Get1Bits (char4, tmpSrc) \ + c |= BitRight(tmpSrc, xoff4); + +#define GetBits5S GetBits4S Get1Bits (char5, tmpSrc) \ + c |= BitRight(tmpSrc, xoff5); +#define GetBits5L GetBits4L Get1Bits (char5, tmpSrc) \ + c |= BitRight(tmpSrc, xoff5); +#define GetBits5U GetBits4U Get1Bits (char5, tmpSrc) \ + c |= BitRight(tmpSrc, xoff5); + +#endif + +#ifdef USE_LEFTBITS +extern unsigned long endtab[]; + +#define IncChar(c) (c = (glyphPointer) (((char *) c) + glyphBytes)) + +#define Get1Bits(ch,dst) glyphbits (ch, widthGlyph, glyphMask, dst); \ + IncChar (ch); + +#define glyphbits(bits,width,mask,dst) getleftbits(bits,width,dst); \ + dst &= mask; + +#define WGetBitsL Get1Bits(leftChar,c); \ + c = BitLeft (c, lshift); +#define WGetBits1S Get1Bits (char1, c) \ + c = BitRight (c, xoff1); +#define WGetBits1L WGetBitsL Get1Bits (char1, tmpSrc) \ + c |= BitRight (tmpSrc, xoff1); +#define WGetBits1U Get1Bits (char1, c) + +#else +#define WGetBitsL GetBitsL +#define WGetBits1S GetBits1S +#define WGetBits1L GetBits1L +#define WGetBits1U GetBits1U +#endif + +#if NGLYPHS == 2 +# define GetBitsNS GetBits2S +# define GetBitsNL GetBits2L +# define GetBitsNU GetBits2U +# define LastChar char2 +#ifndef CFBTEGBLT8 +# define CFBTEGBLT8 cfbTEGlyphBlt8x2 +#endif +#endif +#if NGLYPHS == 3 +# define GetBitsNS GetBits3S +# define GetBitsNL GetBits3L +# define GetBitsNU GetBits3U +# define LastChar char3 +#ifndef CFBTEGBLT8 +# define CFBTEGBLT8 cfbTEGlyphBlt8x3 +#endif +#endif +#if NGLYPHS == 4 +# define GetBitsNS GetBits4S +# define GetBitsNL GetBits4L +# define GetBitsNU GetBits4U +# define LastChar char4 +#ifndef CFBTEGBLT8 +# define CFBTEGBLT8 cfbTEGlyphBlt8x4 +#endif +#endif +#if NGLYPHS == 5 +# define GetBitsNS GetBits5S +# define GetBitsNL GetBits5L +# define GetBitsNU GetBits5U +# define LastChar char5 +#ifndef CFBTEGBLT8 +# define CFBTEGBLT8 cfbTEGlyphBlt8x5 +#endif +#endif + +/* another ugly giant macro */ +#define SwitchEm switch (ew) \ + { \ + case 0: \ + break; \ + case 1: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 \ + Loop \ + } \ + break; \ + case 2: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 FirstStep StoreBits(1) \ + Loop \ + } \ + break; \ + case 3: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 FirstStep StoreBits(1) Step StoreBits(2) \ + Loop \ + } \ + break; \ + case 4: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 FirstStep StoreBits(1) Step \ + StoreBits(2) Step StoreBits(3) \ + Loop \ + } \ + break; \ + case 5: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 FirstStep StoreBits(1) Step \ + StoreBits(2) Step StoreBits(3) Step \ + StoreBits(4) \ + Loop \ + } \ + break; \ + case 6: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 FirstStep StoreBits(1) Step \ + StoreBits(2) Step StoreBits(3) Step \ + StoreBits(4) Step StoreBits(5) \ + Loop \ + } \ + break; \ + case 7: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 FirstStep StoreBits(1) Step \ + StoreBits(2) Step StoreBits(3) Step \ + StoreBits(4) Step StoreBits(5) Step \ + StoreBits(6) \ + Loop \ + } \ + break; \ + case 8: \ + while (hTmp--) { \ + GetBits; \ + StoreBits0 FirstStep StoreBits(1) Step \ + StoreBits(2) Step StoreBits(3) Step \ + StoreBits(4) Step StoreBits(5) Step \ + StoreBits(6) Step StoreBits(7) \ + Loop \ + } \ + break; \ + } + +#ifdef FAST_CONSTANT_OFFSET_MODE +#define StorePixels(o,p) dst[o] = p +#define Loop dst += widthDst; +#else +#define StorePixels(o,p) *dst++ = (p) +#define Loop dst += widthLeft; +#endif + +#define Step NextBitGroup(c); + +#if (BITMAP_BIT_ORDER == MSBFirst) +#define StoreBits(o) StorePixels(o,GetPixelGroup(c)); +#define FirstStep Step +#else +#if PGSZ == 64 +#define StoreBits(o) StorePixels(o,cfb8Pixels[(c) & PGSZBMSK]); +#define FirstStep Step +#else /* PGSZ == 32 */ +#define StoreBits(o) StorePixels(o,*((unsigned long *) (((char *) cfb8Pixels) + (c & 0x3c)))); +#define FirstStep c = BitLeft (c, 2); +#endif /* PGSZ */ +#endif /* BITMAP_BIT_ORDER */ + + +void +CFBTEGBLT8 (pDrawable, pGC, xInit, yInit, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GC *pGC; + int xInit, yInit; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + register unsigned long c; + register unsigned long *dst; + register unsigned long leftMask, rightMask; + register int hTmp; + register int xoff1; + register glyphPointer char1; + register glyphPointer char2; +#if NGLYPHS >= 3 + register glyphPointer char3; +#endif +#if NGLYPHS >= 4 + register glyphPointer char4; +#endif +#if NGLYPHS >= 5 + register glyphPointer char5; +#endif +#ifdef ALL_LEFTBITS + int xoff2, xoff3, xoff4, xoff5; +#endif + + FontPtr pfont = pGC->font; + unsigned long *dstLine; + glyphPointer oldRightChar; + unsigned long *pdstBase; + glyphPointer leftChar; + int widthDst, widthLeft; + int widthGlyph; + int h; + int ew; + int x, y; + BoxRec bbox; /* for clipping */ + int lshift; + int widthGlyphs; +#ifdef USE_LEFTBITS + register unsigned long glyphMask; + register unsigned long tmpSrc; + register int glyphBytes; +#endif + + widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); + h = FONTASCENT(pfont) + FONTDESCENT(pfont); + if (!h) + return; + x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x; + y = yInit - FONTASCENT(pfont) + pDrawable->y; + bbox.x1 = x; + bbox.x2 = x + (widthGlyph * nglyph); + bbox.y1 = y; + bbox.y2 = y + h; + + switch (RECT_IN_REGION(pGC->pScreen, cfbGetCompositeClip(pGC), &bbox)) + { + case rgnPART: + cfbImageGlyphBlt8(pDrawable, pGC, xInit, yInit, nglyph, ppci, pglyphBase); + case rgnOUT: + return; + } + + if (!cfb8CheckPixels (pGC->fgPixel, pGC->bgPixel)) + cfb8SetPixels (pGC->fgPixel, pGC->bgPixel); + + leftChar = 0; + + cfbGetLongWidthAndPointer(pDrawable, widthDst, pdstBase) + +#if NGLYPHS == 2 + widthGlyphs = widthGlyph << 1; +#else +#if NGLYPHS == 4 + widthGlyphs = widthGlyph << 2; +#else + widthGlyphs = widthGlyph * NGLYPHS; +#endif +#endif + +#ifdef USE_LEFTBITS + glyphMask = endtab[widthGlyph]; + glyphBytes = GLYPHWIDTHBYTESPADDED(*ppci); +#endif + + pdstBase += y * widthDst; +#ifdef DO_COMMON + if (widthGlyphs <= 32) +#endif + while (nglyph >= NGLYPHS) + { + nglyph -= NGLYPHS; + hTmp = h; + dstLine = pdstBase + (x >> PWSH); + xoff1 = x & PIM; + char1 = (glyphPointer) FONTGLYPHBITS(pglyphBase, *ppci++); + char2 = (glyphPointer) FONTGLYPHBITS(pglyphBase, *ppci++); +#ifdef ALL_LEFTBITS + xoff2 = xoff1 + widthGlyph; +#endif +#if NGLYPHS >= 3 + char3 = (glyphPointer) FONTGLYPHBITS(pglyphBase, *ppci++); +#ifdef ALL_LEFTBITS + xoff3 = xoff2 + widthGlyph; +#endif +#endif +#if NGLYPHS >= 4 + char4 = (glyphPointer) FONTGLYPHBITS(pglyphBase, *ppci++); +#ifdef ALL_LEFTBITS + xoff4 = xoff3 + widthGlyph; +#endif +#endif +#if NGLYPHS >= 5 + char5 = (glyphPointer) FONTGLYPHBITS(pglyphBase, *ppci++); +#ifdef ALL_LEFTBITS + xoff5 = xoff4 + widthGlyph; +#endif +#endif + oldRightChar = LastChar; + dst = dstLine; + if (xoff1) + { + ew = ((widthGlyphs - (PGSZB - xoff1)) >> PWSH) + 1; +#ifndef FAST_CONSTANT_OFFSET_MODE + widthLeft = widthDst - ew; +#endif + if (!leftChar) + { + leftMask = cfbendtab[xoff1]; + rightMask = cfbstarttab[xoff1]; + +#define StoreBits0 StorePixels (0,dst[0] & leftMask | \ + GetPixelGroup(c) & rightMask); +#define GetBits GetBitsNS + + SwitchEm + +#undef GetBits +#undef StoreBits0 + + } + else + { + lshift = widthGlyph - xoff1; + +#define StoreBits0 StorePixels (0,GetPixelGroup(c)); +#define GetBits GetBitsNL + + SwitchEm + +#undef GetBits +#undef StoreBits0 + + } + } + else + { +#if NGLYPHS == 4 && PGSZ == 32 + ew = widthGlyph; /* widthGlyphs >> 2 */ +#else + ew = widthGlyphs >> PWSH; +#endif +#ifndef FAST_CONSTANT_OFFSET_MODE + widthLeft = widthDst - ew; +#endif + +#define StoreBits0 StorePixels (0,GetPixelGroup(c)); +#define GetBits GetBitsNU + + SwitchEm + +#undef GetBits +#undef StoreBits0 + + } + x += widthGlyphs; + leftChar = oldRightChar; + } + while (nglyph--) + { + xoff1 = x & PIM; + char1 = (glyphPointer) FONTGLYPHBITS(pglyphBase, *ppci++); + hTmp = h; + dstLine = pdstBase + (x >> PWSH); + oldRightChar = char1; + dst = dstLine; + if (xoff1) + { + ew = ((widthGlyph - (PGSZB - xoff1)) >> PWSH) + 1; +#ifndef FAST_CONSTANT_OFFSET_MODE + widthLeft = widthDst - ew; +#endif + if (!leftChar) + { + leftMask = cfbendtab[xoff1]; + rightMask = cfbstarttab[xoff1]; + +#define StoreBits0 StorePixels (0,dst[0] & leftMask | GetPixelGroup(c) & rightMask); +#define GetBits WGetBits1S + + SwitchEm +#undef GetBits +#undef StoreBits0 + + } + else + { + lshift = widthGlyph - xoff1; + +#define StoreBits0 StorePixels (0,GetPixelGroup(c)); +#define GetBits WGetBits1L + + SwitchEm +#undef GetBits +#undef StoreBits0 + + } + } + else + { + ew = widthGlyph >> PWSH; + +#ifndef FAST_CONSTANT_OFFSET_MODE + widthLeft = widthDst - ew; +#endif + +#define StoreBits0 StorePixels (0,GetPixelGroup(c)); +#define GetBits WGetBits1U + + SwitchEm + +#undef GetBits +#undef StoreBits0 + + } + x += widthGlyph; + leftChar = oldRightChar; + } + /* + * draw the tail of the last character + */ + xoff1 = x & PIM; + if (xoff1) + { + rightMask = cfbstarttab[xoff1]; + leftMask = cfbendtab[xoff1]; + lshift = widthGlyph - xoff1; + dst = pdstBase + (x >> PWSH); + hTmp = h; + while (hTmp--) + { + GetBitsL; + *dst = (*dst & rightMask) | (GetPixelGroup(c) & leftMask); + dst += widthDst; + } + } +} +#endif /* PSZ == 8 */ diff --git a/cfb/cfbtegblt.c b/cfb/cfbtegblt.c new file mode 100644 index 000000000..383926619 --- /dev/null +++ b/cfb/cfbtegblt.c @@ -0,0 +1,201 @@ +/* $Xorg: cfbtegblt.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "cfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cfbmskbits.h" +#include "mi.h" +#define MFB_CONSTS_ONLY +#include "maskbits.h" + +/* + this works for fonts with glyphs <= 32 bits wide, on an + arbitrarily deep display. Use cfbTEGlyphBlt8 for 8 bit displays. + + This should be called only with a terminal-emulator font; +this means that the FIXED_METRICS flag is set, and that +glyphbounds == charbounds. + + in theory, this goes faster; even if it doesn't, it reduces the +flicker caused by writing a string over itself with image text (since +the background gets repainted per character instead of per string.) +this seems to be important for some converted X10 applications. + + Image text looks at the bits in the glyph and the fg and bg in the +GC. it paints a rectangle, as defined in the protocol dcoument, +and the paints the characters. + +*/ + +void +cfbTEGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GC *pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + FontPtr pfont = pGC->font; + int widthDst; + unsigned long *pdstBase; /* pointer to longword with top row + of current glyph */ + + int w; /* width of glyph and char */ + int h; /* height of glyph and char */ + register int xpos=x; /* current x%32 */ + int ypos=y; /* current y%32 */ + register unsigned char *pglyph; + int widthGlyph; + + register unsigned long *pdst;/* pointer to current longword in dst */ + int hTmp; /* counter for height */ + BoxRec bbox; /* for clipping */ + + register int wtmp,xtemp,width; + unsigned long bgfill,fgfill,*ptemp,tmpDst1,tmpDst2,*pdtmp; + int tmpx; + + xpos += pDrawable->x; + ypos += pDrawable->y; + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase) + + wtmp = FONTMAXBOUNDS(pfont,characterWidth); + h = FONTASCENT(pfont) + FONTDESCENT(pfont); + widthGlyph = GLYPHWIDTHBYTESPADDED(*ppci); + + xpos += FONTMAXBOUNDS(pfont,leftSideBearing); + ypos -= FONTASCENT(pfont); + + bbox.x1 = xpos; + bbox.x2 = xpos + (wtmp * nglyph); + bbox.y1 = ypos; + bbox.y2 = ypos + h; + + fgfill = PFILL(pGC->fgPixel); + bgfill = PFILL(pGC->bgPixel); + + switch (RECT_IN_REGION(pGC->pScreen, cfbGetCompositeClip(pGC), &bbox)) + { + case rgnOUT: + break; + case rgnPART: + /* this is the WRONG thing to do, but it works. + calling the non-terminal text is easy, but slow, given + what we know about the font. + + the right thing to do is something like: + for each clip rectangle + compute at which row the glyph starts to be in it, + and at which row the glyph ceases to be in it + compute which is the first glyph inside the left + edge, and the last one inside the right edge + draw a fractional first glyph, using only + the rows we know are in + draw all the whole glyphs, using the appropriate rows + draw any pieces of the last glyph, using the right rows + + this way, the code would take advantage of knowing that + all glyphs are the same height and don't overlap. + + one day... + */ + miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + break; + case rgnIN: + + pdtmp = pdstBase + (widthDst * ypos); + while(nglyph--) + { + + pglyph = FONTGLYPHBITS(pglyphBase, *ppci++); + pdst = pdtmp; + hTmp = h; + + while (hTmp--) + { + x = xpos; + width = wtmp; + xtemp = 0; + + while (width > 0) + { + tmpx = x & PIM; + w = min(width, PPW - tmpx); + w = min(w, (PGSZ - xtemp)); + + ptemp = (unsigned long *)(pglyph + (xtemp >> MFB_PWSH)); + getstipplepixels(ptemp,xtemp,w,0,&bgfill,&tmpDst1); + getstipplepixels(ptemp,xtemp,w,1,&fgfill,&tmpDst2); + + { + unsigned long tmpDst = tmpDst1 | tmpDst2; + unsigned long *pdsttmp = pdst + (x >> PWSH); + putbits(tmpDst,tmpx,w,pdsttmp,pGC->planemask); + } + x += w; + xtemp += w; + width -= w; + } + pglyph += widthGlyph; + pdst += widthDst; + } + xpos += wtmp; + } + break; + } +} diff --git a/cfb/cfbtile32.c b/cfb/cfbtile32.c new file mode 100644 index 000000000..544857a25 --- /dev/null +++ b/cfb/cfbtile32.c @@ -0,0 +1,352 @@ +/* + * Fill 32 bit tiled rectangles. Used by both PolyFillRect and PaintWindow. + * no depth dependencies. + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/* $Xorg: cfbtile32.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "gcstruct.h" +#include "window.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "windowstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" + +#include "mergerop.h" + +#include "mi.h" +#include "mispans.h" + +#ifdef sparc +#define SHARED_IDCACHE +#endif + +#define STORE(p) (*(p) = MROP_PREBUILT_SOLID(srcpix,*(p))) + +#if (MROP == Mcopy) && defined(FAST_CONSTANT_OFFSET_MODE) && defined(SHARED_IDCACHE) +# define Expand(left,right) {\ + int part = nlwMiddle & ((PGSZB*2)-1); \ + nlwMiddle >>= PWSH + 1; \ + while (h--) { \ + srcpix = psrc[srcy]; \ + MROP_PREBUILD(srcpix); \ + ++srcy; \ + if (srcy == tileHeight) \ + srcy = 0; \ + left \ + p += part; \ + switch (part) { \ + case 7: \ + STORE(p - 7); \ + case 6: \ + STORE(p - 6); \ + case 5: \ + STORE(p - 5); \ + case 4: \ + STORE(p - 4); \ + case 3: \ + STORE(p - 3); \ + case 2: \ + STORE(p - 2); \ + case 1: \ + STORE(p - 1); \ + } \ + nlw = nlwMiddle; \ + while (nlw) { \ + STORE (p + 0); \ + STORE (p + 1); \ + STORE (p + 2); \ + STORE (p + 3); \ + STORE (p + 4); \ + STORE (p + 5); \ + STORE (p + 6); \ + STORE (p + 7); \ + p += 8; \ + nlw--; \ + } \ + right \ + p += nlwExtra; \ + } \ +} +#else +#define Expand(left,right) {\ + while (h--) { \ + srcpix = psrc[srcy]; \ + MROP_PREBUILD(srcpix); \ + ++srcy; \ + if (srcy == tileHeight) \ + srcy = 0; \ + left \ + nlw = nlwMiddle; \ + while (nlw--) \ + { \ + STORE(p); \ + p++; \ + } \ + right \ + p += nlwExtra; \ + } \ +} +#endif + +void +MROP_NAME(cfbFillRectTile32) (pDrawable, pGC, nBox, pBox) + DrawablePtr pDrawable; + GCPtr pGC; + int nBox; /* number of boxes to fill */ + BoxPtr pBox; /* pointer to list of boxes to fill */ +{ + register unsigned long srcpix; + unsigned long *psrc; /* pointer to bits in tile, if needed */ + int tileHeight; /* height of the tile */ + + int nlwDst; /* width in longwords of the dest pixmap */ + int w; /* width of current box */ + register int h; /* height of current box */ + register unsigned long startmask; + register unsigned long endmask; /* masks for reggedy bits at either end of line */ + int nlwMiddle; /* number of longwords between sides of boxes */ + int nlwExtra; /* to get from right of box to left of next span */ + register int nlw; /* loop version of nlwMiddle */ + register unsigned long *p; /* pointer to bits we're writing */ + int y; /* current scan line */ + int srcy; /* current tile position */ + + unsigned long *pbits;/* pointer to start of pixmap */ + PixmapPtr tile; /* rotated, expanded tile */ + MROP_DECLARE_REG() + MROP_PREBUILT_DECLARE() + + tile = cfbGetGCPrivate(pGC)->pRotatedPixmap; + tileHeight = tile->drawable.height; + psrc = (unsigned long *)tile->devPrivate.ptr; + + MROP_INITIALIZE(pGC->alu, pGC->planemask); + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pbits) + + while (nBox--) + { + w = pBox->x2 - pBox->x1; + h = pBox->y2 - pBox->y1; + y = pBox->y1; + p = pbits + (y * nlwDst) + (pBox->x1 >> PWSH); + srcy = y % tileHeight; + + if ( ((pBox->x1 & PIM) + w) <= PPW) + { + maskpartialbits(pBox->x1, w, startmask); + nlwExtra = nlwDst; + while (h--) + { + srcpix = psrc[srcy]; + MROP_PREBUILD(srcpix); + ++srcy; + if (srcy == tileHeight) + srcy = 0; + *p = MROP_PREBUILT_MASK (srcpix, *p, startmask); + p += nlwExtra; + } + } + else + { + maskbits(pBox->x1, w, startmask, endmask, nlwMiddle); + nlwExtra = nlwDst - nlwMiddle; + + if (startmask) + { + nlwExtra -= 1; + if (endmask) + { + Expand(*p = MROP_PREBUILT_MASK(srcpix, *p, startmask); p++;, + *p = MROP_PREBUILT_MASK(srcpix, *p, endmask);) + } + else + { + Expand(*p = MROP_PREBUILT_MASK(srcpix, *p, startmask); p++;, + ;) + } + } + else + { + if (endmask) + { + Expand(;, + *p = MROP_PREBUILT_MASK(srcpix, *p, endmask);) + } + else + { + Expand(;, + ;) + } + } + } + pBox++; + } +} + +void +MROP_NAME(cfbTile32FS)(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + DDXPointPtr ppt; /* pointer to list of start points */ + int *pwidth;/* pointer to list of n widths */ + unsigned long *pbits; /* pointer to start of bitmap */ + int nlwDst; /* width in longwords of bitmap */ + register unsigned long *p; /* pointer to current longword in bitmap */ + register int w; /* current span width */ + register int nlw; + register int x; + register unsigned long startmask; + register unsigned long endmask; + register unsigned long srcpix; + int y; + int *pwidthFree;/* copies of the pointers to free */ + DDXPointPtr pptFree; + PixmapPtr tile; + unsigned long *psrc; /* pointer to bits in tile */ + int tileHeight;/* height of the tile */ + MROP_DECLARE_REG () + MROP_PREBUILT_DECLARE() + + n = nInit * miFindMaxBand( cfbGetCompositeClip(pGC) ); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans( cfbGetCompositeClip(pGC), + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + tile = cfbGetGCPrivate(pGC)->pRotatedPixmap; + tileHeight = tile->drawable.height; + psrc = (unsigned long *)tile->devPrivate.ptr; + + MROP_INITIALIZE(pGC->alu, pGC->planemask); + + cfbGetLongWidthAndPointer (pDrawable, nlwDst, pbits) + +#if MROP == Mcopy + if (!(tileHeight & (tileHeight-1))) + { + tileHeight--; + while (n--) + { + x = ppt->x; + y = ppt->y; + ++ppt; + w = *pwidth++; + p = pbits + (y * nlwDst) + (x >> PWSH); + srcpix = psrc[y & tileHeight]; + MROP_PREBUILD(srcpix); + + if ((x & PIM) + w < PPW) + { + maskpartialbits(x, w, startmask); + *p = MROP_PREBUILT_MASK (srcpix, *p, startmask); + } + else + { + maskbits(x, w, startmask, endmask, nlw); + if (startmask) + { + *p = MROP_PREBUILT_MASK(srcpix, *p, startmask); + p++; + } + while (nlw--) + { + STORE(p); + ++p; + } + if (endmask) + { + *p = MROP_PREBUILT_MASK(srcpix, *p, endmask); + } + } + } + } + else +#endif + { + while (n--) + { + x = ppt->x; + y = ppt->y; + ++ppt; + w = *pwidth++; + p = pbits + (y * nlwDst) + (x >> PWSH); + srcpix = psrc[y % tileHeight]; + MROP_PREBUILD(srcpix); + + if ((x & PIM) + w < PPW) + { + maskpartialbits(x, w, startmask); + *p = MROP_PREBUILT_MASK (srcpix, *p, startmask); + } + else + { + maskbits(x, w, startmask, endmask, nlw); + if (startmask) + { + *p = MROP_PREBUILT_MASK(srcpix, *p, startmask); + p++; + } + while (nlw--) + { + STORE(p); + ++p; + } + if (endmask) + { + *p = MROP_PREBUILT_MASK(srcpix, *p, endmask); + } + } + } + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} diff --git a/cfb/cfbtileodd.c b/cfb/cfbtileodd.c new file mode 100644 index 000000000..2307f6b55 --- /dev/null +++ b/cfb/cfbtileodd.c @@ -0,0 +1,1080 @@ +/* + * Fill odd tiled rectangles and spans. + * no depth dependencies. + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/* $Xorg: cfbtileodd.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "gcstruct.h" +#include "window.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "windowstr.h" + +#include "cfb.h" +#include "cfbmskbits.h" +#include "cfb8bit.h" + +#include "mergerop.h" + +#if PGSZ == 32 +#define LEFTSHIFT_AMT (5 - PWSH) +#else /* PGSZ == 64 */ +#define LEFTSHIFT_AMT (6 - PWSH) +#endif /* PGSZ */ + +#define LastTileBits {\ + tmp = bits; \ + if (tileEndPart) \ + bits = (*pSrc & tileEndMask) | BitRight (*pSrcLine, tileEndLeftShift); \ + else \ + bits = *pSrc; \ +} + +#define ResetTileBits {\ + pSrc = pSrcLine; \ + nlwSrc = widthSrc;\ + if (tileEndPart) { \ + if (PPW - xoff + tileEndPart <= PPW) {\ + bits = *pSrc++; \ + nlwSrc--; \ + } else \ + bits = BitLeft(tmp, tileEndLeftShift) | \ + BitRight(bits, tileEndRightShift); \ + xoff = (xoff + xoffStep) & PIM; \ + leftShift = xoff << LEFTSHIFT_AMT; \ + rightShift = PGSZ - leftShift; \ + }\ +} + +#define NextTileBits {\ + if (nlwSrc == 1) {\ + LastTileBits\ + } else { \ + if (nlwSrc == 0) {\ + ResetTileBits\ + } \ + if (nlwSrc == 1) {\ + LastTileBits\ + } else {\ + tmp = bits; \ + bits = *pSrc++; \ + }\ + }\ + nlwSrc--; \ +} + +void +MROP_NAME(cfbFillBoxTileOdd) (pDrawable, nBox, pBox, tile, xrot, yrot, alu, planemask) + DrawablePtr pDrawable; + int nBox; /* number of boxes to fill */ + register BoxPtr pBox; /* pointer to list of boxes to fill */ + PixmapPtr tile; /* tile */ + int xrot, yrot; + int alu; + unsigned long planemask; +{ + int tileWidth; /* width of tile in pixels */ + int tileHeight; /* height of the tile */ + int widthSrc; + + int widthDst; /* width in longwords of the dest pixmap */ + int w; /* width of current box */ + int h; /* height of current box */ + unsigned long startmask; + unsigned long endmask;/* masks for reggedy bits at either end of line */ + int nlwMiddle; /* number of longwords between sides of boxes */ + int nlwSrc; /* number of whole longwords in source */ + + register int nlw; /* loop version of nlwMiddle */ + int srcy; /* current tile y position */ + int srcx; /* current tile x position */ + int xoffDst, xoffSrc; + int leftShift, rightShift; + + MROP_DECLARE_REG() + + unsigned long *pDstBase; /* pointer to start of dest */ + unsigned long *pDstLine; /* poitner to start of dest box */ + unsigned long *pSrcBase; /* pointer to start of source */ + unsigned long *pSrcLine; /* pointer to start of source line */ + register unsigned long *pDst; + register unsigned long *pSrc; + register unsigned long bits, tmp; + register int nlwPart; + int xoffStart, xoff; + int leftShiftStart, rightShiftStart, nlwSrcStart; + unsigned long tileEndMask; + int tileEndLeftShift, tileEndRightShift; + int xoffStep; + int tileEndPart; + int needFirst; + unsigned long narrow[2]; + unsigned long narrowMask; + int narrowShift; + Bool narrowTile; + + MROP_INITIALIZE (alu, planemask) + + tileHeight = tile->drawable.height; + tileWidth = tile->drawable.width; + widthSrc = tile->devKind / PGSZB; + narrowTile = FALSE; + if (widthSrc == 1) + { + narrowShift = tileWidth; + narrowMask = cfbendpartial [tileWidth]; + tileWidth *= 2; + widthSrc = 2; + narrowTile = TRUE; + } + pSrcBase = (unsigned long *)tile->devPrivate.ptr; + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pDstBase) + + tileEndPart = tileWidth & PIM; + tileEndMask = cfbendpartial[tileEndPart]; + tileEndLeftShift = (tileEndPart) << LEFTSHIFT_AMT; + tileEndRightShift = PGSZ - tileEndLeftShift; + xoffStep = PPW - tileEndPart; + /* + * current assumptions: tile > 32 bits wide. + */ + while (nBox--) + { + w = pBox->x2 - pBox->x1; + h = pBox->y2 - pBox->y1; + modulus (pBox->x1 - xrot, tileWidth, srcx); + modulus (pBox->y1 - yrot, tileHeight, srcy); + xoffDst = pBox->x1 & PIM; + if (xoffDst + w < PPW) + { + maskpartialbits(pBox->x1, w, startmask); + endmask = 0; + nlwMiddle = 0; + } + else + { + maskbits (pBox->x1, w, startmask, endmask, nlwMiddle) + } + pDstLine = pDstBase + (pBox->y1 * widthDst) + (pBox->x1 >> PWSH); + pSrcLine = pSrcBase + (srcy * widthSrc); + xoffSrc = srcx & PIM; + if (xoffSrc >= xoffDst) + { + xoffStart = xoffSrc - xoffDst; + needFirst = 1; + } + else + { + xoffStart = PPW - (xoffDst - xoffSrc); + needFirst = 0; + } + leftShiftStart = (xoffStart) << LEFTSHIFT_AMT; + rightShiftStart = PGSZ - leftShiftStart; + nlwSrcStart = widthSrc - (srcx >> PWSH); + while (h--) + { + /* XXX only works when narrowShift >= PPW/2 */ + if (narrowTile) + { + tmp = pSrcBase[srcy] & narrowMask; /* source width == 1 */ + narrow[0] = tmp | SCRRIGHT (tmp, narrowShift); + narrow[1] = SCRLEFT (tmp, PPW - narrowShift) | + SCRRIGHT(tmp, 2 * narrowShift - PPW); + pSrcLine = narrow; + } + xoff = xoffStart; + leftShift = leftShiftStart; + rightShift = rightShiftStart; + nlwSrc = nlwSrcStart; + pSrc = pSrcLine + (srcx >> PWSH); + pDst = pDstLine; + bits = 0; + if (needFirst) + { + NextTileBits + } + if (startmask) + { + NextTileBits + tmp = BitLeft(tmp, leftShift); + if (rightShift != PGSZ) + tmp |= BitRight(bits,rightShift); + *pDst = MROP_MASK (tmp, *pDst, startmask); + ++pDst; + } + nlw = nlwMiddle; + while (nlw) + { +#if MROP == Mcopy + if (nlwSrc > 1) + { + nlwPart = nlw; + if (nlwPart >= nlwSrc) + nlwPart = nlwSrc - 1; + nlw -= nlwPart; + nlwSrc -= nlwPart; + if (rightShift != PGSZ) + { + while (nlwPart--) + { + tmp = bits; + bits = *pSrc++; + *pDst = MROP_SOLID(BitLeft(tmp, leftShift) | + BitRight (bits, rightShift), + *pDst); + ++pDst; + } + } + else + { + if (nlwPart) + { + *pDst = MROP_SOLID (bits, *pDst); + ++pDst; + nlwPart--; + while (nlwPart--) + { + *pDst = MROP_SOLID(*pSrc, *pDst); + ++pDst; ++pSrc; + } + bits = *pSrc++; + } + } + } + else +#endif + { + NextTileBits + if (rightShift != PGSZ) + { + *pDst = MROP_SOLID(BitLeft(tmp, leftShift) | + BitRight(bits, rightShift), + *pDst); + } + else + { + *pDst = MROP_SOLID (tmp, *pDst); + } + ++pDst; + nlw--; + } + } + if (endmask) + { + NextTileBits + if (rightShift == PGSZ) + bits = 0; + *pDst = MROP_MASK (BitLeft(tmp, leftShift) | + BitRight(bits,rightShift), + *pDst, endmask); + } + pDstLine += widthDst; + pSrcLine += widthSrc; + if (++srcy == tileHeight) + { + srcy = 0; + pSrcLine = pSrcBase; + } + } + pBox++; + } +} + +void +MROP_NAME(cfbFillSpanTileOdd) (pDrawable, n, ppt, pwidth, tile, xrot, yrot, alu, planemask) + DrawablePtr pDrawable; + int n; + DDXPointPtr ppt; + int *pwidth; + PixmapPtr tile; + int xrot, yrot; + int alu; + unsigned long planemask; +{ + int tileWidth; /* width of tile in pixels */ + int tileHeight; /* height of the tile */ + int widthSrc; + + int widthDst; /* width in longwords of the dest pixmap */ + int w; /* width of current span */ + unsigned long startmask; + unsigned long endmask; /* masks for reggedy bits at either end of line */ + int nlwSrc; /* number of whole longwords in source */ + + register int nlw; /* loop version of nlwMiddle */ + int srcy; /* current tile y position */ + int srcx; /* current tile x position */ + int xoffDst, xoffSrc; + int leftShift, rightShift; + + MROP_DECLARE_REG() + + unsigned long *pDstBase; /* pointer to start of dest */ + unsigned long *pDstLine; /* poitner to start of dest box */ + unsigned long *pSrcBase; /* pointer to start of source */ + unsigned long *pSrcLine; /* pointer to start of source line */ + register unsigned long *pDst; + register unsigned long *pSrc; + register unsigned long bits, tmp; + register int nlwPart; + int xoffStart, xoff; + int leftShiftStart, rightShiftStart, nlwSrcStart; + unsigned long tileEndMask; + int tileEndLeftShift, tileEndRightShift; + int xoffStep; + int tileEndPart; + int needFirst; + unsigned long narrow[2]; + unsigned long narrowMask; + int narrowShift; + Bool narrowTile; + + MROP_INITIALIZE (alu, planemask) + + tileHeight = tile->drawable.height; + tileWidth = tile->drawable.width; + widthSrc = tile->devKind / PGSZB; + narrowTile = FALSE; + if (widthSrc == 1) + { + narrowShift = tileWidth; + narrowMask = cfbendpartial [tileWidth]; + tileWidth *= 2; + widthSrc = 2; + narrowTile = TRUE; + } + pSrcBase = (unsigned long *)tile->devPrivate.ptr; + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pDstBase) + + tileEndPart = tileWidth & PIM; + tileEndMask = cfbendpartial[tileEndPart]; + tileEndLeftShift = (tileEndPart) << LEFTSHIFT_AMT; + tileEndRightShift = PGSZ - tileEndLeftShift; + xoffStep = PPW - tileEndPart; + while (n--) + { + w = *pwidth++; + modulus (ppt->x - xrot, tileWidth, srcx); + modulus (ppt->y - yrot, tileHeight, srcy); + xoffDst = ppt->x & PIM; + if (xoffDst + w < PPW) + { + maskpartialbits(ppt->x, w, startmask); + endmask = 0; + nlw = 0; + } + else + { + maskbits (ppt->x, w, startmask, endmask, nlw) + } + pDstLine = pDstBase + (ppt->y * widthDst) + (ppt->x >> PWSH); + pSrcLine = pSrcBase + (srcy * widthSrc); + xoffSrc = srcx & PIM; + if (xoffSrc >= xoffDst) + { + xoffStart = xoffSrc - xoffDst; + needFirst = 1; + } + else + { + xoffStart = PPW - (xoffDst - xoffSrc); + needFirst = 0; + } + leftShiftStart = (xoffStart) << LEFTSHIFT_AMT; + rightShiftStart = PGSZ - leftShiftStart; + nlwSrcStart = widthSrc - (srcx >> PWSH); + /* XXX only works when narrowShift >= PPW/2 */ + if (narrowTile) + { + tmp = pSrcBase[srcy] & narrowMask; /* source width == 1 */ + narrow[0] = tmp | SCRRIGHT (tmp, narrowShift); + narrow[1] = SCRLEFT (tmp, PPW - narrowShift) | + SCRRIGHT(tmp, 2 * narrowShift - PPW); + pSrcLine = narrow; + } + xoff = xoffStart; + leftShift = leftShiftStart; + rightShift = rightShiftStart; + nlwSrc = nlwSrcStart; + pSrc = pSrcLine + (srcx >> PWSH); + pDst = pDstLine; + bits = 0; + if (needFirst) + { + NextTileBits + } + if (startmask) + { + NextTileBits + tmp = BitLeft(tmp, leftShift); + if (rightShift != PGSZ) + tmp |= BitRight(bits,rightShift); + *pDst = MROP_MASK (tmp, *pDst, startmask); + ++pDst; + } + while (nlw) + { +#if MROP == Mcopy + if (nlwSrc > 1) + { + nlwPart = nlw; + if (nlwPart >= nlwSrc) + nlwPart = nlwSrc - 1; + nlw -= nlwPart; + nlwSrc -= nlwPart; + if (rightShift != PGSZ) + { + while (nlwPart--) + { + tmp = bits; + bits = *pSrc++; + *pDst = MROP_SOLID(BitLeft(tmp, leftShift) | + BitRight (bits, rightShift), + *pDst); + ++pDst; + } + } + else + { + if (nlwPart) + { + *pDst = MROP_SOLID (bits, *pDst); + ++pDst; + nlwPart--; + while (nlwPart--) + { + *pDst = MROP_SOLID(*pSrc, *pDst); + ++pDst; ++pSrc; + } + bits = *pSrc++; + } + } + } + else +#endif + { + NextTileBits + if (rightShift != PGSZ) + { + *pDst = MROP_SOLID(BitLeft(tmp, leftShift) | + BitRight(bits, rightShift), + *pDst); + ++pDst; + } + else + { + *pDst = MROP_SOLID (tmp, *pDst); + ++pDst; + } + nlw--; + } + } + if (endmask) + { + NextTileBits + if (rightShift == PGSZ) + bits = 0; + *pDst = MROP_MASK (BitLeft(tmp, leftShift) | + BitRight(bits,rightShift), + *pDst, endmask); + } + ppt++; + } +} + +# include "fastblt.h" + +#define IncSrcPtr psrc++; if (!--srcRemaining) { srcRemaining = widthSrc; psrc = psrcStart; } + +void +MROP_NAME(cfbFillBoxTile32s) (pDrawable, nBox, pBox, tile, xrot, yrot, alu, planemask) + DrawablePtr pDrawable; + int nBox; /* number of boxes to fill */ + register BoxPtr pBox; /* pointer to list of boxes to fill */ + PixmapPtr tile; /* tile */ + int xrot, yrot; + int alu; + unsigned long planemask; +{ + int tileWidth; /* width of tile */ + int tileHeight; /* height of the tile */ + int widthSrc; /* width in longwords of the source tile */ + + int widthDst; /* width in longwords of the dest pixmap */ + int w; /* width of current box */ + int h; /* height of current box */ + unsigned long startmask; + unsigned long endmask;/* masks for reggedy bits at either end of line */ + int nlMiddle; /* number of longwords between sides of boxes */ + + register int nl; /* loop version of nlMiddle */ + int srcy; /* current tile y position */ + int srcx; /* current tile x position */ + int srcRemaining; /* number of longwords remaining in source */ + int xoffDst, xoffSrc; + int srcStart; /* number of longwords source offset at left of box */ + int leftShift, rightShift; + + MROP_DECLARE_REG() + + unsigned long *pdstBase; /* pointer to start of dest */ + unsigned long *pdstLine; /* poitner to start of dest box */ + unsigned long *psrcBase; /* pointer to start of source */ + unsigned long *psrcLine; /* pointer to fetch point of source */ + unsigned long *psrcStart; /* pointer to start of source line */ + register unsigned long *pdst; + register unsigned long *psrc; + register unsigned long bits, bits1; + register int nlTemp; + + MROP_INITIALIZE (alu, planemask) + + psrcBase = (unsigned long *)tile->devPrivate.ptr; + tileHeight = tile->drawable.height; + tileWidth = tile->drawable.width; + widthSrc = tileWidth >> PWSH; + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase) + + while (nBox--) + { + w = pBox->x2 - pBox->x1; + h = pBox->y2 - pBox->y1; + + /* set up source */ + modulus (pBox->x1 - xrot, tileWidth, srcx); + modulus (pBox->y1 - yrot, tileHeight, srcy); + xoffSrc = srcx & PIM; + srcStart = (srcx >> PWSH); + psrcStart = psrcBase + (srcy * widthSrc); + psrcLine = psrcStart + srcStart; + + /* set up dest */ + xoffDst = pBox->x1 & PIM; + pdstLine = pdstBase + (pBox->y1 * widthDst) + (pBox->x1 >> PWSH); + /* set up masks */ + if (xoffDst + w < PPW) + { + maskpartialbits(pBox->x1, w, startmask); + endmask = 0; + nlMiddle = 0; + } + else + { + maskbits (pBox->x1, w, startmask, endmask, nlMiddle) + } + if (xoffSrc == xoffDst) + { + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + srcRemaining = widthSrc - srcStart; + if (startmask) + { + *pdst = MROP_MASK (*psrc, *pdst, startmask); + pdst++; + IncSrcPtr + } + nlTemp = nlMiddle; + while (nlTemp) + { + nl = nlTemp; + if (nl > srcRemaining) + nl = srcRemaining; + + nlTemp -= nl; + srcRemaining -= nl; + +#if MROP == Mcopy +#ifdef LARGE_INSTRUCTION_CACHE +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); +#define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); + +#define LoopReset \ +pdst += UNROLL; \ +psrc += UNROLL; + +#else + +#define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++; +#define BodyEven(n) BodyOdd(n) + +#define LoopReset ; + +#endif + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL(nl, label1, + *pdst = MROP_SOLID (*psrc, *pdst); + pdst++; psrc++;) +#endif +#else + while (nl--) { + *pdst = MROP_SOLID (*psrc, *pdst); + pdst++; psrc++; + } +#endif + if (!srcRemaining) + { + srcRemaining = widthSrc; + psrc = psrcStart; + } + } + if (endmask) + { + *pdst = MROP_MASK (*psrc, *pdst, endmask); + } + pdstLine += widthDst; + psrcLine += widthSrc; + psrcStart += widthSrc; + if (++srcy == tileHeight) + { + psrcStart = psrcBase; + psrcLine = psrcStart + srcStart; + srcy = 0; + } + } + } + else + { + if (xoffSrc > xoffDst) + { + leftShift = (xoffSrc - xoffDst) << LEFTSHIFT_AMT; + rightShift = PGSZ - leftShift; + } + else + { + rightShift = (xoffDst - xoffSrc) << LEFTSHIFT_AMT; + leftShift = PGSZ - rightShift; + } + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + bits = 0; + srcRemaining = widthSrc - srcStart; + if (xoffSrc > xoffDst) + { + bits = *psrc; + IncSrcPtr + } + if (startmask) + { + bits1 = BitLeft(bits,leftShift); + bits = *psrc; + IncSrcPtr + bits1 |= BitRight(bits,rightShift); + *pdst = MROP_MASK(bits1, *pdst, startmask); + pdst++; + } + nlTemp = nlMiddle; + while (nlTemp) + { + nl = nlTemp; + if (nl > srcRemaining) + nl = srcRemaining; + + nlTemp -= nl; + srcRemaining -= nl; + +#if MROP == Mcopy +#ifdef LARGE_INSTRUCTION_CACHE + bits1 = bits; + +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) \ + bits = psrc[-n]; \ + pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]); + +#define BodyEven(n) \ + bits1 = psrc[-n]; \ + pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]); + +#define LoopReset \ + pdst += UNROLL; \ + psrc += UNROLL; + +#else + +#define BodyOdd(n) \ + bits = *psrc++; \ + *pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \ + pdst++; + +#define BodyEven(n) \ + bits1 = *psrc++; \ + *pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \ + pdst++; + +#define LoopReset ; + +#endif /* !FAST_CONSTANT_OFFSET_MODE */ + + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL (nl,label2, + bits1 = BitLeft(bits, leftShift); + bits = *psrc++; + *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst); + pdst++; + ) +#endif +#else + while (nl--) { + bits1 = BitLeft(bits, leftShift); + bits = *psrc++; + *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst); + pdst++; + } +#endif + if (!srcRemaining) + { + srcRemaining = widthSrc; + psrc = psrcStart; + } + } + + if (endmask) + { + bits1 = BitLeft(bits, leftShift); + if (BitLeft(endmask, rightShift)) + { + bits = *psrc; + bits1 |= BitRight(bits, rightShift); + } + *pdst = MROP_MASK (bits1, *pdst, endmask); + } + pdstLine += widthDst; + psrcLine += widthSrc; + psrcStart += widthSrc; + if (++srcy == tileHeight) + { + psrcStart = psrcBase; + psrcLine = psrcStart + srcStart; + srcy = 0; + } + } + } + pBox++; + } +} + +void +MROP_NAME(cfbFillSpanTile32s) (pDrawable, n, ppt, pwidth, tile, xrot, yrot, alu, planemask) + DrawablePtr pDrawable; + int n; + DDXPointPtr ppt; + int *pwidth; + PixmapPtr tile; + int xrot, yrot; + int alu; + unsigned long planemask; +{ + int tileWidth; /* width of tile */ + int tileHeight; /* height of the tile */ + int widthSrc; /* width in longwords of the source tile */ + + int widthDst; /* width in longwords of the dest pixmap */ + int w; /* width of current box */ + unsigned long startmask; + unsigned long endmask;/* masks for reggedy bits at either end of line */ + int nlMiddle; /* number of longwords between sides of boxes */ + + register int nl; /* loop version of nlMiddle */ + int srcy; /* current tile y position */ + int srcx; /* current tile x position */ + int srcRemaining; /* number of longwords remaining in source */ + int xoffDst, xoffSrc; + int srcStart; /* number of longwords source offset at left of box */ + int leftShift, rightShift; + + MROP_DECLARE_REG() + + unsigned long *pdstBase; /* pointer to start of dest */ + unsigned long *pdstLine; /* poitner to start of dest box */ + unsigned long *psrcBase; /* pointer to start of source */ + unsigned long *psrcLine; /* pointer to fetch point of source */ + unsigned long *psrcStart; /* pointer to start of source line */ + register unsigned long *pdst; + register unsigned long *psrc; + register unsigned long bits, bits1; + register int nlTemp; + + MROP_INITIALIZE (alu, planemask) + + psrcBase = (unsigned long *)tile->devPrivate.ptr; + tileHeight = tile->drawable.height; + tileWidth = tile->drawable.width; + widthSrc = tileWidth >> PWSH; + + cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase) + + while (n--) + { + w = *pwidth++; + + /* set up source */ + modulus (ppt->x - xrot, tileWidth, srcx); + modulus (ppt->y - yrot, tileHeight, srcy); + xoffSrc = srcx & PIM; + srcStart = (srcx >> PWSH); + psrcStart = psrcBase + (srcy * widthSrc); + psrcLine = psrcStart + srcStart; + + /* set up dest */ + xoffDst = ppt->x & PIM; + pdstLine = pdstBase + (ppt->y * widthDst) + (ppt->x >> PWSH); + /* set up masks */ + if (xoffDst + w < PPW) + { + maskpartialbits(ppt->x, w, startmask); + endmask = 0; + nlMiddle = 0; + } + else + { + maskbits (ppt->x, w, startmask, endmask, nlMiddle) + } + + if (xoffSrc == xoffDst) + { + psrc = psrcLine; + pdst = pdstLine; + srcRemaining = widthSrc - srcStart; + if (startmask) + { + *pdst = MROP_MASK (*psrc, *pdst, startmask); + pdst++; + IncSrcPtr + } + nlTemp = nlMiddle; + while (nlTemp) + { + nl = nlTemp; + if (nl > srcRemaining) + nl = srcRemaining; + + nlTemp -= nl; + srcRemaining -= nl; + +#if MROP == Mcopy +#ifdef LARGE_INSTRUCTION_CACHE +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); +#define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); + +#define LoopReset \ +pdst += UNROLL; \ +psrc += UNROLL; + +#else + +#define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++; +#define BodyEven(n) BodyOdd(n) + +#define LoopReset ; + +#endif + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL(nl, label1, + *pdst = MROP_SOLID (*psrc, *pdst); + pdst++; psrc++;) +#endif +#else + while (nl--) { + *pdst = MROP_SOLID (*psrc, *pdst); + pdst++; psrc++; + } +#endif + if (!srcRemaining) + { + srcRemaining = widthSrc; + psrc = psrcStart; + } + } + if (endmask) + { + *pdst = MROP_MASK (*psrc, *pdst, endmask); + } + } + else + { + if (xoffSrc > xoffDst) + { + leftShift = (xoffSrc - xoffDst) << LEFTSHIFT_AMT; + rightShift = PGSZ - leftShift; + } + else + { + rightShift = (xoffDst - xoffSrc) << LEFTSHIFT_AMT; + leftShift = PGSZ - rightShift; + } + psrc = psrcLine; + pdst = pdstLine; + bits = 0; + srcRemaining = widthSrc - srcStart; + if (xoffSrc > xoffDst) + { + bits = *psrc; + IncSrcPtr + } + if (startmask) + { + bits1 = BitLeft(bits,leftShift); + bits = *psrc; + IncSrcPtr + bits1 |= BitRight(bits,rightShift); + *pdst = MROP_MASK(bits1, *pdst, startmask); + pdst++; + } + nlTemp = nlMiddle; + while (nlTemp) + { + nl = nlTemp; + if (nl > srcRemaining) + nl = srcRemaining; + + nlTemp -= nl; + srcRemaining -= nl; + +#if MROP == Mcopy +#ifdef LARGE_INSTRUCTION_CACHE + bits1 = bits; + +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) \ +bits = psrc[-n]; \ +pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]); + +#define BodyEven(n) \ +bits1 = psrc[-n]; \ +pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]); + +#define LoopReset \ +pdst += UNROLL; \ +psrc += UNROLL; + +#else + +#define BodyOdd(n) \ +bits = *psrc++; \ +*pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \ +pdst++; + +#define BodyEven(n) \ +bits1 = *psrc++; \ +*pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \ +pdst++; + +#define LoopReset ; + +#endif /* !FAST_CONSTANT_OFFSET_MODE */ + + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL (nl,label2, + bits1 = BitLeft(bits, leftShift); + bits = *psrc++; + *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst); + pdst++; + ) +#endif +#else + while (nl--) { + bits1 = BitLeft(bits,leftShift); + bits = *psrc++; + *pdst = MROP_SOLID(bits1|BitRight(bits,rightShift), *pdst); + pdst++; + } +#endif + if (!srcRemaining) + { + srcRemaining = widthSrc; + psrc = psrcStart; + } + } + + if (endmask) + { + bits1 = BitLeft(bits, leftShift); + if (BitLeft(endmask, rightShift)) + { + bits = *psrc; + bits1 |= BitRight(bits, rightShift); + } + *pdst = MROP_MASK (bits1, *pdst, endmask); + } + } + ppt++; + } +} diff --git a/cfb/cfbwindow.c b/cfb/cfbwindow.c new file mode 100644 index 000000000..244aa412b --- /dev/null +++ b/cfb/cfbwindow.c @@ -0,0 +1,334 @@ +/* $Xorg: cfbwindow.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "cfb.h" +#include "mistruct.h" +#include "regionstr.h" +#include "cfbmskbits.h" + +extern WindowPtr *WindowTable; + +Bool +cfbCreateWindow(pWin) + WindowPtr pWin; +{ + cfbPrivWin *pPrivWin; + + pPrivWin = cfbGetWindowPrivate(pWin); + pPrivWin->pRotatedBorder = NullPixmap; + pPrivWin->pRotatedBackground = NullPixmap; + pPrivWin->fastBackground = FALSE; + pPrivWin->fastBorder = FALSE; + pPrivWin->oldRotate.x = 0; + pPrivWin->oldRotate.y = 0; + +#ifdef PIXMAP_PER_WINDOW + /* Setup pointer to Screen pixmap */ + pWin->devPrivates[frameWindowPrivateIndex].ptr = + (pointer) cfbGetScreenPixmap(pWin->drawable.pScreen); +#endif + + return TRUE; +} + +Bool +cfbDestroyWindow(pWin) + WindowPtr pWin; +{ + cfbPrivWin *pPrivWin; + + pPrivWin = cfbGetWindowPrivate(pWin); + + if (pPrivWin->pRotatedBorder) + (*pWin->drawable.pScreen->DestroyPixmap)(pPrivWin->pRotatedBorder); + if (pPrivWin->pRotatedBackground) + (*pWin->drawable.pScreen->DestroyPixmap)(pPrivWin->pRotatedBackground); + return(TRUE); +} + +/*ARGSUSED*/ +Bool +cfbMapWindow(pWindow) + WindowPtr pWindow; +{ + return(TRUE); +} + +/* (x, y) is the upper left corner of the window on the screen + do we really need to pass this? (is it a;ready in pWin->absCorner?) + we only do the rotation for pixmaps that are 32 bits wide (padded +or otherwise.) + cfbChangeWindowAttributes() has already put a copy of the pixmap +in pPrivWin->pRotated* +*/ +/*ARGSUSED*/ +Bool +cfbPositionWindow(pWin, x, y) + WindowPtr pWin; + int x, y; +{ + cfbPrivWin *pPrivWin; + int setxy = 0; + + pPrivWin = cfbGetWindowPrivate(pWin); + if (pWin->backgroundState == BackgroundPixmap && pPrivWin->fastBackground) + { + cfbXRotatePixmap(pPrivWin->pRotatedBackground, + pWin->drawable.x - pPrivWin->oldRotate.x); + cfbYRotatePixmap(pPrivWin->pRotatedBackground, + pWin->drawable.y - pPrivWin->oldRotate.y); + setxy = 1; + } + + if (!pWin->borderIsPixel && pPrivWin->fastBorder) + { + while (pWin->backgroundState == ParentRelative) + pWin = pWin->parent; + cfbXRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.x - pPrivWin->oldRotate.x); + cfbYRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.y - pPrivWin->oldRotate.y); + setxy = 1; + } + if (setxy) + { + pPrivWin->oldRotate.x = pWin->drawable.x; + pPrivWin->oldRotate.y = pWin->drawable.y; + } + return (TRUE); +} + +/*ARGSUSED*/ +Bool +cfbUnmapWindow(pWindow) + WindowPtr pWindow; +{ + return (TRUE); +} + +/* UNCLEAN! + this code calls the bitblt helper code directly. + + cfbCopyWindow copies only the parts of the destination that are +visible in the source. +*/ + + +void +cfbCopyWindow(pWin, ptOldOrg, prgnSrc) + WindowPtr pWin; + DDXPointRec ptOldOrg; + RegionPtr prgnSrc; +{ + DDXPointPtr pptSrc; + register DDXPointPtr ppt; + RegionRec rgnDst; + register BoxPtr pbox; + register int dx, dy; + register int i, nbox; + WindowPtr pwinRoot; + + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + REGION_INIT(pWin->drawable.pScreen, &rgnDst, NullBox, 0); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); + REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + pbox = REGION_RECTS(&rgnDst); + nbox = REGION_NUM_RECTS(&rgnDst); + if(!nbox || !(pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) + { + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); + return; + } + ppt = pptSrc; + + for (i = nbox; --i >= 0; ppt++, pbox++) + { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + cfbDoBitbltCopy((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + GXcopy, &rgnDst, pptSrc, ~0L); + DEALLOCATE_LOCAL(pptSrc); + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); +} + + + +/* swap in correct PaintWindow* routine. If we can use a fast output +routine (i.e. the pixmap is paddable to 32 bits), also pre-rotate a copy +of it in devPrivates[cfbWindowPrivateIndex].ptr. +*/ +Bool +cfbChangeWindowAttributes(pWin, mask) + WindowPtr pWin; + unsigned long mask; +{ + register unsigned long index; + register cfbPrivWin *pPrivWin; + int width; + WindowPtr pBgWin; + + pPrivWin = cfbGetWindowPrivate(pWin); + + /* + * When background state changes from ParentRelative and + * we had previously rotated the fast border pixmap to match + * the parent relative origin, rerotate to match window + */ + if (mask & (CWBackPixmap | CWBackPixel) && + pWin->backgroundState != ParentRelative && + pPrivWin->fastBorder && + (pPrivWin->oldRotate.x != pWin->drawable.x || + pPrivWin->oldRotate.y != pWin->drawable.y)) + { + cfbXRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.x - pPrivWin->oldRotate.x); + cfbYRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.y - pPrivWin->oldRotate.y); + pPrivWin->oldRotate.x = pWin->drawable.x; + pPrivWin->oldRotate.y = pWin->drawable.y; + } + while(mask) + { + index = lowbit (mask); + mask &= ~index; + switch(index) + { + case CWBackPixmap: + if (pWin->backgroundState == None) + { + pPrivWin->fastBackground = FALSE; + } + else if (pWin->backgroundState == ParentRelative) + { + pPrivWin->fastBackground = FALSE; + /* Rotate border to match parent origin */ + if (pPrivWin->pRotatedBorder) { + for (pBgWin = pWin->parent; + pBgWin->backgroundState == ParentRelative; + pBgWin = pBgWin->parent); + cfbXRotatePixmap(pPrivWin->pRotatedBorder, + pBgWin->drawable.x - pPrivWin->oldRotate.x); + cfbYRotatePixmap(pPrivWin->pRotatedBorder, + pBgWin->drawable.y - pPrivWin->oldRotate.y); + pPrivWin->oldRotate.x = pBgWin->drawable.x; + pPrivWin->oldRotate.y = pBgWin->drawable.y; + } + } + else if (((width = (pWin->background.pixmap->drawable.width * PSZ)) + <= PGSZ) && !(width & (width - 1))) + { + cfbCopyRotatePixmap(pWin->background.pixmap, + &pPrivWin->pRotatedBackground, + pWin->drawable.x, + pWin->drawable.y); + if (pPrivWin->pRotatedBackground) + { + pPrivWin->fastBackground = TRUE; + pPrivWin->oldRotate.x = pWin->drawable.x; + pPrivWin->oldRotate.y = pWin->drawable.y; + } + else + { + pPrivWin->fastBackground = FALSE; + } + } + else + { + pPrivWin->fastBackground = FALSE; + } + break; + + case CWBackPixel: + pPrivWin->fastBackground = FALSE; + break; + + case CWBorderPixmap: + if (((width = (pWin->border.pixmap->drawable.width * PSZ)) <= PGSZ) && + !(width & (width - 1))) + { + for (pBgWin = pWin; + pBgWin->backgroundState == ParentRelative; + pBgWin = pBgWin->parent); + cfbCopyRotatePixmap(pWin->border.pixmap, + &pPrivWin->pRotatedBorder, + pBgWin->drawable.x, + pBgWin->drawable.y); + if (pPrivWin->pRotatedBorder) + { + pPrivWin->fastBorder = TRUE; + pPrivWin->oldRotate.x = pBgWin->drawable.x; + pPrivWin->oldRotate.y = pBgWin->drawable.y; + } + else + { + pPrivWin->fastBorder = FALSE; + } + } + else + { + pPrivWin->fastBorder = FALSE; + } + break; + case CWBorderPixel: + pPrivWin->fastBorder = FALSE; + break; + } + } + return (TRUE); +} + diff --git a/cfb/cfbzerarc.c b/cfb/cfbzerarc.c new file mode 100644 index 000000000..37b7023d5 --- /dev/null +++ b/cfb/cfbzerarc.c @@ -0,0 +1,218 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: cfbzerarc.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ + +/* Derived from: + * "Algorithm for drawing ellipses or hyperbolae with a digital plotter" + * by M. L. V. Pitteway + * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289 + */ + +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "cfb.h" +#include "cfbmskbits.h" +#include "mizerarc.h" +#include "cfbrrop.h" +#include "mi.h" + +#ifdef PIXEL_ADDR + +static void +RROP_NAME(cfbZeroArcSS8) (pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + miZeroArcRec info; + Bool do360; + register int x; + PixelType *addrp; + register PixelType *yorgp, *yorgop; + RROP_DECLARE + register int yoffset; + int npwidth, dyoffset; + register int y, a, b, d, mask; + register int k1, k3, dx, dy; + + cfbGetPixelWidthAndPointer(pDraw,npwidth, addrp) + + RROP_FETCH_GC (pGC); + do360 = miZeroArcSetup(arc, &info, TRUE); + yorgp = addrp + ((info.yorg + pDraw->y) * npwidth); + yorgop = addrp + ((info.yorgo + pDraw->y) * npwidth); + info.xorg += pDraw->x; + info.xorgo += pDraw->x; + MIARCSETUP(); + yoffset = y ? npwidth : 0; + dyoffset = 0; + mask = info.initialMask; + if (!(arc->width & 1)) + { + if (mask & 2) + RROP_SOLID((yorgp + info.xorgo)); + if (mask & 8) + RROP_SOLID((yorgop + info.xorgo)); + } + if (!info.end.x || !info.end.y) + { + mask = info.end.mask; + info.end = info.altend; + } + if (do360 && (arc->width == arc->height) && !(arc->width & 1)) + { + register int xoffset = npwidth; + PixelType *yorghb = yorgp + (info.h * npwidth) + info.xorg; + PixelType *yorgohb = yorghb - info.h; + + yorgp += info.xorg; + yorgop += info.xorg; + yorghb += info.h; + while (1) + { + RROP_SOLID(yorgp + yoffset + x); + RROP_SOLID(yorgp + yoffset - x); + RROP_SOLID(yorgop - yoffset - x); + RROP_SOLID(yorgop - yoffset + x); + if (a < 0) + break; + RROP_SOLID(yorghb - xoffset - y); + RROP_SOLID(yorgohb - xoffset + y); + RROP_SOLID(yorgohb + xoffset + y); + RROP_SOLID(yorghb + xoffset - y); + xoffset += npwidth; + MIARCCIRCLESTEP(yoffset += npwidth;); + } + yorgp -= info.xorg; + yorgop -= info.xorg; + x = info.w; + yoffset = info.h * npwidth; + } + else if (do360) + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(dyoffset = npwidth;); + RROP_SOLID(yorgp + yoffset + info.xorg + x); + RROP_SOLID(yorgp + yoffset + info.xorgo - x); + RROP_SOLID(yorgop - yoffset + info.xorgo - x); + RROP_SOLID(yorgop - yoffset + info.xorg + x); + MIARCSTEP(yoffset += dyoffset;, yoffset += npwidth;); + } + } + else + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(dyoffset = npwidth;); + if ((x == info.start.x) || (y == info.start.y)) + { + mask = info.start.mask; + info.start = info.altstart; + } + if (mask & 1) + RROP_SOLID(yorgp + yoffset + info.xorg + x); + if (mask & 2) + RROP_SOLID(yorgp + yoffset + info.xorgo - x); + if (mask & 4) + RROP_SOLID(yorgop - yoffset + info.xorgo - x); + if (mask & 8) + RROP_SOLID(yorgop - yoffset + info.xorg + x); + if ((x == info.end.x) || (y == info.end.y)) + { + mask = info.end.mask; + info.end = info.altend; + } + MIARCSTEP(yoffset += dyoffset;, yoffset += npwidth;); + } + } + if ((x == info.start.x) || (y == info.start.y)) + mask = info.start.mask; + if (mask & 1) + RROP_SOLID(yorgp + yoffset + info.xorg + x); + if (mask & 4) + RROP_SOLID(yorgop - yoffset + info.xorgo - x); + if (arc->height & 1) + { + if (mask & 2) + RROP_SOLID(yorgp + yoffset + info.xorgo - x); + if (mask & 8) + RROP_SOLID(yorgop - yoffset + info.xorg + x); + } +} + +void +RROP_NAME (cfbZeroPolyArcSS8) (pDraw, pGC, narcs, parcs) + register DrawablePtr pDraw; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + register xArc *arc; + register int i; + BoxRec box; + int x2, y2; + RegionPtr cclip; + + cclip = cfbGetCompositeClip(pGC); + for (arc = parcs, i = narcs; --i >= 0; arc++) + { + if (miCanZeroArc(arc)) + { + box.x1 = arc->x + pDraw->x; + box.y1 = arc->y + pDraw->y; + /* + * Because box.x2 and box.y2 get truncated to 16 bits, and the + * RECT_IN_REGION test treats the resulting number as a signed + * integer, the RECT_IN_REGION test alone can go the wrong way. + * This can result in a server crash because the rendering + * routines in this file deal directly with cpu addresses + * of pixels to be stored, and do not clip or otherwise check + * that all such addresses are within their respective pixmaps. + * So we only allow the RECT_IN_REGION test to be used for + * values that can be expressed correctly in a signed short. + */ + x2 = box.x1 + (int)arc->width + 1; + box.x2 = x2; + y2 = box.y1 + (int)arc->height + 1; + box.y2 = y2; + if ( (x2 <= MAXSHORT) && (y2 <= MAXSHORT) && + (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) ) + RROP_NAME (cfbZeroArcSS8) (pDraw, pGC, arc); + else + miZeroPolyArc(pDraw, pGC, 1, arc); + } + else + miPolyArc(pDraw, pGC, 1, arc); + } +} + +#endif diff --git a/cfb/stip68kgnu.h b/cfb/stip68kgnu.h new file mode 100644 index 000000000..9b2c7a1b3 --- /dev/null +++ b/cfb/stip68kgnu.h @@ -0,0 +1,128 @@ +/* + * $Xorg: stip68kgnu.h,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * Stipple stack macro for 68k GCC + * + * Note - this macro can nott describe the full extent of the + * modifications made to the arguments (GCC does not allow enough + * arguments to __asm statements). Therefore, it is possible + * (though unlikely) that future magic versions of GCC may + * miscompile this somehow. In particular, (stipple) is modified + * by the macro, yet not listed as an output value. + */ + +#define STIPPLE(addr,stipple,value,width,count,shift) \ + __asm volatile ( \ + "subqw #1,%1\n\ + lea 0f,a1\n\ + movew #28,d2\n\ + addl %7,d2\n\ + movew #28,d3\n\ + subql #4,%7\n\ + negl %7\n\ +1:\n\ + movel %0,a0\n\ + addl %5,%0\n\ + movel %3@+,d1\n\ + beq 3f\n\ + movel d1,d0\n\ + lsrl d2,d0\n\ + lsll #5,d0\n\ + lsll %7,d1\n\ + jmp a1@(d0:l)\n\ +2:\n\ + addl #4,a0\n\ + movel d1,d0\n\ + lsrl d3,d0\n\ + lsll #5,d0\n\ + lsll #4,d1\n\ + jmp a1@(d0:l)\n\ +0:\n\ + bne 2b ; dbra %1,1b ; bra 4f\n\ + . = 0b + 0x20\n\ + moveb %4,a0@(3)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f\n\ + . = 0b + 0x40\n\ + moveb %4,a0@(2)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f\n\ + . = 0b + 0x60\n\ + movew %4,a0@(2)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f\n\ + . = 0b + 0x80\n\ + moveb %4,a0@(1)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0xa0\n\ + moveb %4,a0@(3) ; moveb %4,a0@(1)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0xc0\n\ + movew %4,a0@(1)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0xe0\n\ + movew %4,a0@(2) ; moveb %4,a0@(1)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x100\n\ + moveb %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x120\n\ + moveb %4,a0@(3) ; moveb %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x140\n\ + moveb %4,a0@(2) ; moveb %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x160\n\ + movew %4,a0@(2) ; moveb %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x180\n\ + movew %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x1a0\n\ + moveb %4,a0@(3) ; movew %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x1c0\n\ + moveb %4,a0@(2) ; movew %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; dbra %1,1b ; bra 4f ;\n\ + . = 0b + 0x1e0\n\ + movel %4,a0@(0)\n\ + andl d1,d1 ; bne 2b ; \n\ +3: dbra %1,1b ; \n\ +4:\n"\ + : "=a" (addr), /* %0 */ \ + "=d" (count) /* %1 */ \ + : "0" (addr), /* %2 */ \ + "a" (stipple), /* %3 */ \ + "d" (value), /* %4 */ \ + "a" (width), /* %5 */ \ + "1" (count), /* %6 */ \ + "d" (shift) /* %7 */ \ + : /* ctemp */ "d0", \ + /* c */ "d1", \ + /* lshift */ "d2", \ + /* rshift */ "d3", \ + /* atemp */ "a0", \ + /* case */ "a1") diff --git a/cfb/stipmips.s b/cfb/stipmips.s new file mode 100644 index 000000000..c42d9b5ae --- /dev/null +++ b/cfb/stipmips.s @@ -0,0 +1,281 @@ +/* + * $Xorg: stipmips.s,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * MIPS assembly code for optimized text rendering. + * + * Other stippling could be done in assembly, but the payoff is + * not nearly as large. Mostly because large areas are heavily + * optimized already. + */ + +#ifdef MIPSEL +# define BitsR sll +# define BitsL srl +# define BO(o) o +# define HO(o) o +# define WO(o) o +# define FourBits(dest,bits) and dest, bits, 0xf +#else +# define BitsR srl +# define BitsL sll +# define BO(o) 3-o +# define HO(o) 2-o +# define WO(o) o +# define FourBits(dest,bits) srl dest, bits, 28 +#endif + +/* reordering instructions would be fatal here */ + .set noreorder + + +/* + * cfbStippleStack(addr, stipple, value, stride, Count, Shift) + * 4 5 6 7 16(sp) 20(sp) + * + * Apply successive 32-bit stipples starting at addr, addr+stride, ... + * + * Used for text rendering, but only when no data could be lost + * when the stipple is shifted left by Shift bits + */ +/* arguments */ +#define addr $4 +#define stipple $5 +#define value $6 +#define stride $7 +#define Count 16($sp) +#define Shift 20($sp) + +/* local variables */ +#define count $14 +#define shift $13 +#define atemp $12 +#define bits $11 +#define lshift $9 +#define sbase $8 +#define stemp $2 + +#define CASE_SIZE 5 /* case blocks are 2^5 bytes each */ +#define CASE_MASK 0x1e0 /* first case mask */ + +#define ForEachLine $200 +#define NextLine $201 +#define NextLine1 $202 +#define CaseBegin $203 +#define ForEachBits $204 +#define ForEachBits1 $205 +#define NextBits $206 + +#ifdef TETEXT +#define cfbStippleStack cfbStippleStackTE +#endif + + .globl cfbStippleStack + .ent cfbStippleStack 2 +cfbStippleStack: + .frame $sp, 0, $31 + lw count, Count /* fetch stack params */ + la sbase,CaseBegin /* load up switch table */ + lw shift, Shift + li lshift, 4 /* compute offset within */ + subu lshift, lshift, shift /* stipple of remaining bits */ +#ifdef MIPSEL + addu shift, shift, CASE_SIZE /* first shift for LSB */ +#else + addu shift, shift, 28-CASE_SIZE /* first shift for MSB */ +#endif + /* do ... while (--count > 0); */ +ForEachLine: + lw bits, 0(stipple) /* get stipple bits */ + move atemp, addr /* set up for this line */ +#ifdef TETEXT + /* Terminal emulator fonts are expanded and have many 0 rows */ + beqz bits, NextLine /* skip out early on 0 */ +#endif + addu addr, addr, stride /* step for the loop */ + BitsR stemp, bits, shift /* get first bits */ + and stemp, stemp, CASE_MASK /* compute first branch */ + addu stemp, stemp, sbase /* ... */ + j stemp /* ... */ + BitsL bits, bits, lshift /* set remaining bits */ + +ForEachBits: + addu atemp, atemp, 4 +ForEachBits1: + FourBits(stemp, bits) /* compute jump for */ + sll stemp, stemp, CASE_SIZE /* next four bits */ + addu stemp, stemp, sbase /* ... */ + j stemp /* ... */ + BitsL bits, bits, 4 /* step for remaining bits */ +CaseBegin: + bnez bits, ForEachBits1 /* 0 */ + addu atemp, atemp, 4 +NextLine: + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + bnez bits, ForEachBits /* 1 */ + sb value, BO(0)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + bnez bits, ForEachBits /* 2 */ + sb value, BO(1)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + bnez bits, ForEachBits /* 3 */ + sh value, HO(0)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + bnez bits, ForEachBits /* 4 */ + sb value, BO(2)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + sb value, BO(0)(atemp) /* 5 */ + bnez bits, ForEachBits + sb value, BO(2)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + + sb value, BO(1)(atemp) /* 6 */ + bnez bits, ForEachBits + sb value, BO(2)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + + bnez bits, ForEachBits /* 7 */ + swl value, BO(2)(atemp) /* untested on MSB */ + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + bnez bits, ForEachBits /* 8 */ + sb value, BO(3)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + sb value, BO(0)(atemp) /* 9 */ + bnez bits, ForEachBits + sb value, BO(3)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + + sb value, BO(1)(atemp) /* a */ + bnez bits, ForEachBits + sb value, BO(3)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + + sh value, HO(0)(atemp) /* b */ + bnez bits, ForEachBits + sb value, BO(3)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + + bnez bits, ForEachBits /* c */ + sh value, HO(2)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + sb value, BO(0)(atemp) /* d */ + bnez bits, ForEachBits + sh value, HO(2)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + + bnez bits, ForEachBits /* e */ + swr value, BO(1)(atemp) /* untested on MSB */ + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + bnez bits, ForEachBits /* f */ + sw value, WO(0)(atemp) + addu count, count, -1 + bnez count, ForEachLine + addu stipple, stipple, 4 + j $31 + nop + nop + + .end cfbStippleStack diff --git a/cfb/stipsparc.s b/cfb/stipsparc.s new file mode 100644 index 000000000..2c417599e --- /dev/null +++ b/cfb/stipsparc.s @@ -0,0 +1,280 @@ +/* + * $Xorg: stipsparc.s,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * SPARC assembly code for optimized text rendering. + * + * Other stippling could be done in assembly, but the payoff is + * not nearly as large. Mostly because large areas are heavily + * optimized already. + */ + +/* not that I expect to ever see an LSB SPARC, but ... */ +#ifdef LITTLE_ENDIAN +# define BitsR sll +# define BitsL srl +# define BO(o) o +# define HO(o) o +# define WO(o) o +# define FourBits(dest,bits) and bits, 0xf, dest +#else +# define BitsR srl +# define BitsL sll +# define BO(o) 3-o +# define HO(o) 2-o +# define WO(o) o +# define FourBits(dest,bits) srl bits, 28, dest +#endif + +/* + * cfbStippleStack(addr, stipple, value, stride, Count, Shift) + * 4 5 6 7 16(sp) 20(sp) + * + * Apply successive 32-bit stipples starting at addr, addr+stride, ... + * + * Used for text rendering, but only when no data could be lost + * when the stipple is shifted left by Shift bits + */ +/* arguments */ +#define addr %i0 +#define stipple %i1 +#define value %i2 +#define stride %i3 +#define count %i4 +#define shift %i5 + +/* local variables */ +#define atemp %l0 +#define bits %l1 +#define lshift %l2 +#define sbase %l3 +#define stemp %l4 + +#define CASE_SIZE 5 /* case blocks are 2^5 bytes each */ +#define CASE_MASK 0x1e0 /* first case mask */ + +#define ForEachLine LY1 +#define NextLine LY2 +#define CaseBegin LY3 +#define ForEachBits LY4 +#define NextBits LY5 + +#ifdef SVR4 +#ifdef TETEXT +#define _cfbStippleStack cfbStippleStackTE +#else +#define _cfbStippleStack cfbStippleStack +#endif +#else +#ifdef TETEXT +#define _cfbStippleStack _cfbStippleStackTE +#endif +#endif + .seg "text" + .proc 16 + .globl _cfbStippleStack +_cfbStippleStack: + save %sp,-64,%sp + sethi %hi(CaseBegin),sbase /* load up switch table */ + or sbase,%lo(CaseBegin),sbase + + mov 4,lshift /* compute offset within */ + sub lshift, shift, lshift /* stipple of remaining bits */ +#ifdef LITTLE_ENDIAN + inc CASE_SIZE, shift /* first shift for LSB */ +#else + inc 28-CASE_SIZE, shift /* first shift for MSB */ +#endif + /* do ... while (--count > 0); */ +ForEachLine: + ld [stipple],bits /* get stipple bits */ + mov addr,atemp /* set up for this line */ +#ifdef TETEXT + /* Terminal emulator fonts are expanded and have many 0 rows */ + tst bits + bz NextLine /* skip out early on 0 */ +#endif + add addr, stride, addr /* step for the loop */ + BitsR bits, shift, stemp /* get first bits */ + and stemp, CASE_MASK, stemp /* compute first jump */ + BitsL bits, lshift, bits /* set remaining bits */ + jmp sbase+stemp /* ... */ + tst bits + +ForEachBits: + inc 4, atemp +ForEachBits1: + FourBits(stemp, bits) /* compute jump for */ + sll stemp, CASE_SIZE, stemp /* these four bits */ + BitsL bits, 4, bits /* step for remaining bits */ + jmp sbase+stemp /* jump */ + tst bits +CaseBegin: + bnz,a ForEachBits1 /* 0 */ + inc 4, atemp +NextLine: + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + bnz ForEachBits /* 1 */ + stb value, [atemp+BO(0)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + bnz ForEachBits /* 2 */ + stb value, [atemp+BO(1)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + bnz ForEachBits /* 3 */ + sth value, [atemp+HO(0)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + bnz ForEachBits /* 4 */ + stb value, [atemp+BO(2)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + stb value, [atemp+BO(0)] /* 5 */ + bnz ForEachBits + stb value, [atemp+BO(2)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + stb value, [atemp+BO(1)] /* 6 */ + bnz ForEachBits + stb value, [atemp+BO(2)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + sth value, [atemp+HO(0)] /* 7 */ + bnz ForEachBits + stb value, [atemp+BO(2)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + bnz ForEachBits /* 8 */ + stb value, [atemp+BO(3)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + stb value, [atemp+BO(0)] /* 9 */ + bnz ForEachBits + stb value, [atemp+BO(3)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + stb value, [atemp+BO(1)] /* a */ + bnz ForEachBits + stb value, [atemp+BO(3)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + sth value, [atemp+HO(0)] /* b */ + bnz ForEachBits + stb value, [atemp+BO(3)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + bnz ForEachBits /* c */ + sth value, [atemp+HO(2)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + stb value, [atemp+BO(0)] /* d */ + bnz ForEachBits + sth value, [atemp+HO(2)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + stb value, [atemp+BO(1)] /* e */ + bnz ForEachBits + sth value, [atemp+HO(2)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + bnz ForEachBits /* f */ + st value, [atemp+WO(0)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore diff --git a/cfb/stipsprc32.s b/cfb/stipsprc32.s new file mode 100644 index 000000000..ce2b949b2 --- /dev/null +++ b/cfb/stipsprc32.s @@ -0,0 +1,281 @@ +/* + * $Xorg: stipsprc32.s,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * SPARC assembly code for optimized text rendering. + * + * Other stippling could be done in assembly, but the payoff is + * not nearly as large. Mostly because large areas are heavily + * optimized already. + */ + +/* not that I expect to ever see an LSB SPARC, but ... */ +#ifdef LITTLE_ENDIAN +# define BitsR sll +# define BitsL srl +# define WO(o) 3-o +# define FourBits(dest,bits) and bits, 0xf, dest +#else +# define BitsR srl +# define BitsL sll +# define WO(o) o +# define FourBits(dest,bits) srl bits, 28, dest +#endif + +/* + * cfb32StippleStack(addr, stipple, value, stride, Count, Shift) + * 4 5 6 7 16(sp) 20(sp) + * + * Apply successive 32-bit stipples starting at addr, addr+stride, ... + * + * Used for text rendering, but only when no data could be lost + * when the stipple is shifted left by Shift bits + */ +/* arguments */ +#define addr %i0 +#define stipple %i1 +#define value %i2 +#define stride %i3 +#define count %i4 +#define shift %i5 + +/* local variables */ +#define atemp %l0 +#define bits %l1 +#define lshift %l2 +#define sbase %l3 +#define stemp %l4 + +#define CASE_SIZE 5 /* case blocks are 2^5 bytes each */ +#define CASE_MASK 0x1e0 /* first case mask */ + +#define ForEachLine LY1 +#define NextLine LY2 +#define CaseBegin LY3 +#define ForEachBits LY4 +#define NextBits LY5 + +#ifdef SVR4 +#ifdef TETEXT +#define _cfb32StippleStack cfb32StippleStackTE +#else +#define _cfb32StippleStack cfb32StippleStack +#endif +#else +#ifdef TETEXT +#define _cfb32StippleStack _cfb32StippleStackTE +#endif +#endif + + .seg "text" + .proc 16 + .globl _cfb32StippleStack +_cfb32StippleStack: + save %sp,-64,%sp + sethi %hi(CaseBegin),sbase /* load up switch table */ + or sbase,%lo(CaseBegin),sbase + + mov 4,lshift /* compute offset within */ + sub lshift, shift, lshift /* stipple of remaining bits */ +#ifdef LITTLE_ENDIAN + inc CASE_SIZE, shift /* first shift for LSB */ +#else + inc 28-CASE_SIZE, shift /* first shift for MSB */ +#endif + /* do ... while (--count > 0); */ +ForEachLine: + ld [stipple],bits /* get stipple bits */ + mov addr,atemp /* set up for this line */ +#ifdef TETEXT + /* Terminal emulator fonts are expanded and have many 0 rows */ + tst bits + bz NextLine /* skip out early on 0 */ +#endif + add addr, stride, addr /* step for the loop */ + BitsR bits, shift, stemp /* get first bits */ + and stemp, CASE_MASK, stemp /* compute first jump */ + BitsL bits, lshift, bits /* set remaining bits */ + jmp sbase+stemp /* ... */ + tst bits + +ForEachBits: + inc 16, atemp +ForEachBits1: + FourBits(stemp, bits) /* compute jump for */ + sll stemp, CASE_SIZE, stemp /* these four bits */ + BitsL bits, 4, bits /* step for remaining bits */ + jmp sbase+stemp /* jump */ + tst bits +CaseBegin: + bnz,a ForEachBits1 /* 0 */ + inc 16, atemp +NextLine: + deccc 1, count +NextLine1: + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + bnz ForEachBits /* 1 */ + st value, [atemp+WO(12)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + bnz ForEachBits /* 2 */ + st value, [atemp+WO(8)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + st value, [atemp+WO(8)] /* 3 */ + bnz ForEachBits + st value, [atemp+WO(12)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + bnz ForEachBits /* 4 */ + st value, [atemp+WO(4)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + st value, [atemp+WO(4)] /* 5 */ + bnz ForEachBits + st value, [atemp+WO(12)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + st value, [atemp+WO(4)] /* 6 */ + bnz ForEachBits + st value, [atemp+WO(8)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + st value, [atemp+WO(4)] /* 7 */ + st value, [atemp+WO(8)] + bnz ForEachBits + st value, [atemp+WO(12)] + b NextLine1 + deccc 1, count + nop + nop + + bnz ForEachBits /* 8 */ + st value, [atemp+WO(0)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + nop + + st value, [atemp+WO(0)] /* 9 */ + bnz ForEachBits + st value, [atemp+WO(12)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + st value, [atemp+WO(0)] /* a */ + bnz ForEachBits + st value, [atemp+WO(8)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + st value, [atemp+WO(0)] /* b */ + st value, [atemp+WO(8)] + bnz ForEachBits + st value, [atemp+WO(12)] + b NextLine1 + deccc 1, count + nop + nop + + st value, [atemp+WO(0)] /* c */ + bnz ForEachBits + st value, [atemp+WO(4)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore + + st value, [atemp+WO(0)] /* d */ + st value, [atemp+WO(4)] + bnz ForEachBits + st value, [atemp+WO(12)] + b NextLine1 + deccc 1, count + nop + nop + + st value, [atemp+WO(0)] /* e */ + st value, [atemp+WO(4)] + bnz ForEachBits + st value, [atemp+WO(8)] + b NextLine1 + deccc 1, count + nop + nop + + st value, [atemp+WO(0)] /* f */ + st value, [atemp+WO(4)] + st value, [atemp+WO(8)] + bnz ForEachBits + st value, [atemp+WO(12)] + deccc 1, count + bnz,a ForEachLine + inc 4, stipple + ret + restore diff --git a/dbe/dbe.c b/dbe/dbe.c new file mode 100644 index 000000000..96fdac409 --- /dev/null +++ b/dbe/dbe.c @@ -0,0 +1,1977 @@ +/* $Xorg: dbe.c,v 1.3 2000/08/17 19:48:16 cpqbld Exp $ */ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the Hewlett-Packard + * Company shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the Hewlett-Packard Company. + * + * DIX DBE code + * + *****************************************************************************/ + + +/* INCLUDES */ + +#include "X.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "dixstruct.h" +#define NEED_DBE_PROTOCOL +#include "dbestruct.h" +#include "midbe.h" + + +/* GLOBALS */ + +/* Per-screen initialization functions [init'ed by DbeRegisterFunction()] */ +static Bool (* DbeInitFunct[MAXSCREENS])(); /* pScreen, pDbeScreenPriv */ + +/* These are static globals copied to DBE's screen private for use by DDX */ +static int dbeScreenPrivIndex; +static int dbeWindowPrivIndex; + +/* These are static globals copied to DBE's screen private for use by DDX */ +static RESTYPE dbeDrawableResType; +static RESTYPE dbeWindowPrivResType; + +/* This global is used by DbeAllocWinPrivPrivIndex() */ +static int winPrivPrivCount = 0; + +/* Used to generate DBE's BadBuffer error. */ +static int dbeErrorBase; + +/* Used by DbeRegisterFunction() to initialize the initialization function + * table only once per server lifetime. + */ +static Bool firstRegistrationPass = TRUE; + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeValidateBuffer + * + * Description: + * + * This function is called from VALIDATE_DRAWABLE_AND_GC and from + * various places in dispatch.c if the server has been compiled with + * the flags -DNEED_DBE_BUF_BITS and -DNEED_DBE_BUF_VALIDATE. + * When pWin->dstBuffer changes, this function will be called with pWin + * as the first argument, the drawable ID that was specified as the + * second argument (could be a back buffer id), and True for the third + * argument. + * When pWin->srcBuffer changes, the third argument will be False, and + * the first two arguments are as described for dstBuffer. + * + * This function should prepare the hardware to access the specified + * buffer for reads (if dstbuf is False) or writes (if dstbuf is True). + * + *****************************************************************************/ + +void +DbeValidateBuffer(pWin, drawID, dstbuf) + WindowPtr pWin; + XID drawID; + Bool dstbuf; +{ + DbeScreenPrivPtr pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); + if (pDbeScreenPriv->ValidateBuffer) + (*pDbeScreenPriv->ValidateBuffer)(pWin, drawID, dstbuf); +} + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeRegisterFunction + * + * Description: + * + * This function registers the DBE init function for the specified screen. + * + *****************************************************************************/ + +void +DbeRegisterFunction(pScreen, funct) + ScreenPtr pScreen; + Bool (*funct)(); +{ + int i; + + /* Initialize the initialization function table if it has not been + * initialized already. + */ + if (firstRegistrationPass) + { + for (i = 0; i < MAXSCREENS; i++) + { + DbeInitFunct[i] = NULL; + } + + firstRegistrationPass = FALSE; + } + + DbeInitFunct[pScreen->myNum] = funct; + +} /* DbeRegisterFunction() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeAllocWinPriv + * + * Description: + * + * This function was cloned from AllocateWindow() in window.c. + * This function allocates a window priv structure to be associated + * with a double-buffered window. + * + *****************************************************************************/ +static DbeWindowPrivPtr +DbeAllocWinPriv(pScreen) + ScreenPtr pScreen; +{ + DbeWindowPrivPtr pDbeWindowPriv; + DbeScreenPrivPtr pDbeScreenPriv; + register char *ptr; + register DevUnion *ppriv; + register unsigned int *sizes; + register unsigned int size; + register int i; + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + pDbeWindowPriv = (DbeWindowPrivPtr)xalloc(pDbeScreenPriv->totalWinPrivSize); + + if (pDbeWindowPriv) + { + ppriv = (DevUnion *)(pDbeWindowPriv + 1); + pDbeWindowPriv->devPrivates = ppriv; + sizes = pDbeScreenPriv->winPrivPrivSizes; + ptr = (char *)(ppriv + pDbeScreenPriv->winPrivPrivLen); + for (i = pDbeScreenPriv->winPrivPrivLen; --i >= 0; ppriv++, sizes++) + { + if (size = *sizes) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + + return(pDbeWindowPriv); + +} /* DbeAllocWinPriv() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeFallbackAllocWinPriv + * + * Description: + * + * This is a fallback function for AllocWinPriv(). + * + *****************************************************************************/ + +static DbeWindowPrivPtr +DbeFallbackAllocWinPriv(pScreen) + ScreenPtr pScreen; +{ + return (NULL); + +} /* DbeFallbackAllocWinPriv() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeAllocWinPrivPrivIndex + * + * Description: + * + * This function was cloned from AllocateWindowPrivateIndex() in window.c. + * This function allocates a new window priv priv index by simply returning + * an incremented private counter. + * + *****************************************************************************/ + +static int +DbeAllocWinPrivPrivIndex() +{ + return winPrivPrivCount++; + +} /* DbeAllocWinPrivPrivIndex() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeAllocWinPrivPriv + * + * Description: + * + * This function was cloned from AllocateWindowPrivate() in privates.c. + * This function allocates a private structure to be hung off + * a window private. + * + *****************************************************************************/ + +static Bool +DbeAllocWinPrivPriv(pScreen, index, amount) + register ScreenPtr pScreen; + int index; + unsigned int amount; +{ + DbeScreenPrivPtr pDbeScreenPriv; + unsigned int oldamount; + + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (index >= pDbeScreenPriv->winPrivPrivLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(pDbeScreenPriv->winPrivPrivSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + { + return(FALSE); + } + + while (pDbeScreenPriv->winPrivPrivLen <= index) + { + nsizes[pDbeScreenPriv->winPrivPrivLen++] = 0; + pDbeScreenPriv->totalWinPrivSize += sizeof(DevUnion); + } + + pDbeScreenPriv->winPrivPrivSizes = nsizes; + } + + oldamount = pDbeScreenPriv->winPrivPrivSizes[index]; + + if (amount > oldamount) + { + pDbeScreenPriv->winPrivPrivSizes[index] = amount; + pDbeScreenPriv->totalWinPrivSize += (amount - oldamount); + } + return(TRUE); + +} /* DbeAllocWinPrivPriv() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeStubScreen + * + * Description: + * + * This is function stubs the function pointers in the given DBE screen + * private and increments the number of stubbed screens. + * + *****************************************************************************/ + +static void +DbeStubScreen(pDbeScreenPriv, nStubbedScreens) + DbeScreenPrivPtr pDbeScreenPriv; + int *nStubbedScreens; +{ + /* Stub DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = NULL; + pDbeScreenPriv->AllocWinPriv = NULL; + pDbeScreenPriv->AllocWinPrivPrivIndex = NULL; + pDbeScreenPriv->AllocWinPrivPriv = NULL; + + /* Do not unwrap PositionWindow nor DestroyWindow. If the DDX + * initialization function failed, we assume that it did not wrap + * PositionWindow. Also, DestroyWindow is only wrapped if the DDX + * initialization function succeeded. + */ + + /* Stub DDX. */ + pDbeScreenPriv->GetVisualInfo = NULL; + pDbeScreenPriv->AllocBackBufferName = NULL; + pDbeScreenPriv->SwapBuffers = NULL; + pDbeScreenPriv->BeginIdiom = NULL; + pDbeScreenPriv->EndIdiom = NULL; + pDbeScreenPriv->WinPrivDelete = NULL; + pDbeScreenPriv->ResetProc = NULL; + pDbeScreenPriv->ValidateBuffer = NULL; + + (*nStubbedScreens)++; + +} /* DbeStubScreen() */ + + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetVersion + * + * Description: + * + * This function is for processing a DbeGetVersion request. + * This request returns the major and minor version numbers of this + * extension. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetVersion(client) + ClientPtr client; +{ + REQUEST(xDbeGetVersionReq); + xDbeGetVersionReply rep; + register int n; + + + REQUEST_SIZE_MATCH(xDbeGetVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = DBE_MAJOR_VERSION; + rep.minorVersion = DBE_MINOR_VERSION; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + } + + WriteToClient(client, sizeof(xDbeGetVersionReply), (char *)&rep); + + return(client->noClientException); + +} /* ProcDbeGetVersion() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeAllocateBackBufferName + * + * Description: + * + * This function is for processing a DbeAllocateBackBufferName request. + * This request allocates a drawable ID used to refer to the back buffer + * of a window. + * + * Return Values: + * + * BadAlloc - server can not allocate resources + * BadIDChoice - id is out of range for client; id is already in use + * BadMatch - window is not an InputOutput window; + * visual of window is not on list returned by + * DBEGetVisualInfo; + * BadValue - invalid swap action is specified + * BadWindow - window is not a valid window + * Success + * + *****************************************************************************/ + +static int +ProcDbeAllocateBackBufferName(client) + ClientPtr client; +{ + REQUEST(xDbeAllocateBackBufferNameReq); + WindowPtr pWin; + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + XdbeScreenVisualInfo scrVisInfo; + register int i; + Bool visualMatched = FALSE; + xDbeSwapAction swapAction; + VisualID visual; + int status; + + + REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); + + /* The window must be valid. */ + if (!(pWin = SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess))) + { + return(BadWindow); + } + + /* The window must be InputOutput. */ + if (pWin->drawable.class != InputOutput) + { + return(BadMatch); + } + + /* The swap action must be valid. */ + swapAction = stuff->swapAction; /* use local var for performance. */ + if ((swapAction != XdbeUndefined ) && + (swapAction != XdbeBackground) && + (swapAction != XdbeUntouched ) && + (swapAction != XdbeCopied )) + { + return(BadValue); + } + + /* The id must be in range and not already in use. */ + LEGAL_NEW_RESOURCE(stuff->buffer, client); + + /* The visual of the window must be in the list returned by + * GetVisualInfo. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); + if (!pDbeScreenPriv->GetVisualInfo) + return(BadMatch); /* screen doesn't support double buffering */ + + if (!(*pDbeScreenPriv->GetVisualInfo)(pWin->drawable.pScreen, &scrVisInfo)) + { + /* GetVisualInfo() failed to allocate visual info data. */ + return(BadAlloc); + } + + /* See if the window's visual is on the list. */ + visual = wVisual(pWin); + for (i = 0; (i < scrVisInfo.count) && !visualMatched; i++) + { + if (scrVisInfo.visinfo[i].visual == visual) + { + visualMatched = TRUE; + } + } + + /* Free what was allocated by the GetVisualInfo() call above. */ + xfree(scrVisInfo.visinfo); + + if (!visualMatched) + { + return(BadMatch); + } + + if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL) + { + /* There is no buffer associated with the window. + * Allocate a window priv. + */ + + if (!(pDbeWindowPriv = + (*pDbeScreenPriv->AllocWinPriv)(pWin->drawable.pScreen))) + { + return(BadAlloc); + } + + /* Make the window priv a DBE window priv resource. */ + if (!AddResource(stuff->buffer, dbeWindowPrivResType, + (pointer)pDbeWindowPriv)) + { + xfree(pDbeWindowPriv); + return(BadAlloc); + } + + /* Fill out window priv information. */ + pDbeWindowPriv->pWindow = pWin; + pDbeWindowPriv->width = pWin->drawable.width; + pDbeWindowPriv->height = pWin->drawable.height; + pDbeWindowPriv->x = pWin->drawable.x; + pDbeWindowPriv->y = pWin->drawable.y; + pDbeWindowPriv->nBufferIDs = 0; + + /* Set the buffer ID array pointer to the initial (static) array). */ + pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; + + /* Initialize the buffer ID list. */ + pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; + pDbeWindowPriv->IDs[0] = stuff->buffer; + for (i = 1; i < DBE_INIT_MAX_IDS; i++) + { + pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; + } + + + /* Actually connect the window priv to the window. */ + pWin->devPrivates[dbeWindowPrivIndex].ptr = (pointer)pDbeWindowPriv; + + } /* if -- There is no buffer associated with the window. */ + + else + { + /* A buffer is already associated with the window. + * Add the new buffer ID to the array, reallocating the array memory + * if necessary. + */ + + /* Determine if there is a free element in the ID array. */ + for (i = 0; i < pDbeWindowPriv->maxAvailableIDs; i++) + { + if (pDbeWindowPriv->IDs[i] == DBE_FREE_ID_ELEMENT) + { + /* There is still room in the ID array. */ + break; + } + } + + if (i == pDbeWindowPriv->maxAvailableIDs) + { + /* No more room in the ID array -- reallocate another array. */ + XID *pIDs; + + + /* Setup an array pointer for the realloc operation below. */ + if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) + { + /* We will malloc a new array. */ + pIDs = NULL; + } + else + { + /* We will realloc a new array. */ + pIDs = pDbeWindowPriv->IDs; + } + + /* malloc/realloc a new array and initialize all elements to 0. */ + pDbeWindowPriv->IDs = (XID *)xrealloc(pIDs, + (pDbeWindowPriv->maxAvailableIDs+DBE_INCR_MAX_IDS)*sizeof(XID)); + if (!pDbeWindowPriv->IDs) + { + return(BadAlloc); + } + memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0, + (pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS - + pDbeWindowPriv->nBufferIDs) * sizeof(XID)); + + if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) + { + /* We just went from using the initial (static) array to a + * newly allocated array. Copy the IDs from the initial array + * to the new array. + */ + memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs, + DBE_INIT_MAX_IDS * sizeof(XID)); + } + + pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS; + } + + /* Finally, record the buffer ID in the array. */ + pDbeWindowPriv->IDs[i] = stuff->buffer; + + /* Associate the new ID with an existing window priv. */ + if (!AddResource(stuff->buffer, dbeWindowPrivResType, + (pointer)pDbeWindowPriv)) + { + pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; + return(BadAlloc); + } + + } /* else -- A buffer is already associated with the window. */ + + + /* Call the DDX routine to allocate the back buffer. */ + status = (*pDbeScreenPriv->AllocBackBufferName)(pWin, stuff->buffer, + stuff->swapAction); + + if ((status != Success) && (pDbeWindowPriv->nBufferIDs == 0)) + { + /* The DDX buffer allocation routine failed for the first buffer of + * this window. + */ + xfree(pDbeWindowPriv); + return(status); + } + + /* Increment the number of buffers (XIDs) associated with this window. */ + pDbeWindowPriv->nBufferIDs++; + + /* Set swap action on all calls. */ + pDbeWindowPriv->swapAction = stuff->swapAction; + + + return(status); + +} /* ProcDbeAllocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeDeallocateBackBufferName + * + * Description: + * + * This function is for processing a DbeDeallocateBackBufferName request. + * This request frees a drawable ID that was obtained by a + * DbeAllocateBackBufferName request. + * + * Return Values: + * + * BadBuffer - buffer to deallocate is not associated with a window + * Success + * + *****************************************************************************/ + +static int +ProcDbeDeallocateBackBufferName(client) + ClientPtr client; +{ + REQUEST(xDbeDeallocateBackBufferNameReq); + DbeWindowPrivPtr pDbeWindowPriv; + int i; + + + REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); + + /* Buffer name must be valid */ + if (!(pDbeWindowPriv = (DbeWindowPrivPtr)SecurityLookupIDByType(client, + stuff->buffer, dbeWindowPrivResType, SecurityDestroyAccess)) || + !(SecurityLookupIDByType(client, stuff->buffer, dbeDrawableResType, + SecurityDestroyAccess))) + { + client->errorValue = stuff->buffer; + return(dbeErrorBase + DbeBadBuffer); + } + + /* Make sure that the id is valid for the window. + * This is paranoid code since we already looked up the ID by type + * above. + */ + + for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) + { + /* Loop through the ID list to find the ID. */ + if (pDbeWindowPriv->IDs[i] == stuff->buffer) + { + break; + } + } + + if (i == pDbeWindowPriv->nBufferIDs) + { + /* We did not find the ID in the ID list. */ + client->errorValue = stuff->buffer; + return(dbeErrorBase + DbeBadBuffer); + } + + FreeResource(stuff->buffer, RT_NONE); + + return(Success); + +} /* ProcDbeDeallocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeSwapBuffers + * + * Description: + * + * This function is for processing a DbeSwapBuffers request. + * This request swaps the buffers for all windows listed, applying the + * appropriate swap action for each window. + * + * Return Values: + * + * BadAlloc - local allocation failed; this return value is not defined + * by the protocol + * BadMatch - a window in request is not double-buffered; a window in + * request is listed more than once + * BadValue - invalid swap action is specified; no swap action is + * specified + * BadWindow - a window in request is not valid + * Success + * + *****************************************************************************/ + +static int +ProcDbeSwapBuffers(client) + ClientPtr client; +{ + REQUEST(xDbeSwapBuffersReq); + WindowPtr pWin; + DbeScreenPrivPtr pDbeScreenPriv; + DbeSwapInfoPtr swapInfo; + xDbeSwapInfo *dbeSwapInfo; + int error; + register int i, j; + int nStuff; + + + REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); + nStuff = stuff->n; /* use local variable for performance. */ + + if (nStuff == 0) + { + return(Success); + } + + /* Get to the swap info appended to the end of the request. */ + dbeSwapInfo = (xDbeSwapInfo *)&stuff[1]; + + /* Allocate array to record swap information. */ + swapInfo = (DbeSwapInfoPtr)ALLOCATE_LOCAL(nStuff * sizeof(DbeSwapInfoRec)); + if (swapInfo == NULL) + { + return(BadAlloc); + } + + + for (i = 0; i < nStuff; i++) + { + /* Check all windows to swap. */ + + /* Each window must be a valid window - BadWindow. */ + if (!(pWin = SecurityLookupWindow(dbeSwapInfo[i].window, client, + SecurityWriteAccess))) + { + DEALLOCATE_LOCAL(swapInfo); + return(BadWindow); + } + + /* Each window must be double-buffered - BadMatch. */ + if (DBE_WINDOW_PRIV(pWin) == NULL) + { + DEALLOCATE_LOCAL(swapInfo); + return(BadMatch); + } + + /* Each window must only be specified once - BadMatch. */ + for (j = i + 1; j < nStuff; j++) + { + if (dbeSwapInfo[i].window == dbeSwapInfo[j].window) + { + DEALLOCATE_LOCAL(swapInfo); + return(BadMatch); + } + } + + /* Each swap action must be valid - BadValue. */ + if ((dbeSwapInfo[i].swapAction != XdbeUndefined ) && + (dbeSwapInfo[i].swapAction != XdbeBackground) && + (dbeSwapInfo[i].swapAction != XdbeUntouched ) && + (dbeSwapInfo[i].swapAction != XdbeCopied )) + { + DEALLOCATE_LOCAL(swapInfo); + return(BadValue); + } + + /* Everything checks out OK. Fill in the swap info array. */ + swapInfo[i].pWindow = pWin; + swapInfo[i].swapAction = dbeSwapInfo[i].swapAction; + + } /* for (i = 0; i < nStuff; i++) */ + + + /* Call the DDX routine to perform the swap(s). The DDX routine should + * scan the swap list (swap info), swap any buffers that it knows how to + * handle, delete them from the list, and update nStuff to indicate how + * many windows it did not handle. + * + * This scheme allows a range of sophistication in the DDX SwapBuffers() + * implementation. Naive implementations could just swap the first buffer + * in the list, move the last buffer to the front, decrement nStuff, and + * return. The next level of sophistication could be to scan the whole + * list for windows on the same screen. Up another level, the DDX routine + * could deal with cross-screen synchronization. + */ + + while (nStuff > 0) + { + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow); + error = (*pDbeScreenPriv->SwapBuffers)(client, &nStuff, swapInfo); + if (error != Success) + { + DEALLOCATE_LOCAL(swapInfo); + return(error); + } + } + + DEALLOCATE_LOCAL(swapInfo); + return(Success); + +} /* ProcDbeSwapBuffers() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeBeginIdiom + * + * Description: + * + * This function is for processing a DbeBeginIdiom request. + * This request informs the server that a complex swap will immediately + * follow this request. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeBeginIdiom(client) + ClientPtr client; +{ + REQUEST(xDbeBeginIdiomReq); + DbeScreenPrivPtr pDbeScreenPriv; + register int i; + + + REQUEST_SIZE_MATCH(xDbeBeginIdiomReq); + + for (i = 0; i < screenInfo.numScreens; i++) + { + pDbeScreenPriv = DBE_SCREEN_PRIV(screenInfo.screens[i]); + + /* Call the DDX begin idiom procedure if there is one. */ + if (pDbeScreenPriv->BeginIdiom) + { + (*pDbeScreenPriv->BeginIdiom)(client); + } + } + + return(Success); + +} /* ProcDbeBeginIdiom() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetVisualInfo + * + * Description: + * + * This function is for processing a ProcDbeGetVisualInfo request. + * This request returns information about which visuals support + * double buffering. + * + * Return Values: + * + * BadDrawable - value in screen specifiers is not a valid drawable + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetVisualInfo(client) + ClientPtr client; +{ + REQUEST(xDbeGetVisualInfoReq); + DbeScreenPrivPtr pDbeScreenPriv; + xDbeGetVisualInfoReply rep; + Drawable *drawables; + DrawablePtr *pDrawables = NULL; + register int i, j, n; + register int count; /* number of visual infos in reply */ + register int length; /* length of reply */ + ScreenPtr pScreen; + XdbeScreenVisualInfo *pScrVisInfo; + + + REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); + + /* Make sure any specified drawables are valid. */ + if (stuff->n != 0) + { + if (!(pDrawables = (DrawablePtr *)ALLOCATE_LOCAL(stuff->n * + sizeof(DrawablePtr)))) + { + return(BadAlloc); + } + + drawables = (Drawable *)&stuff[1]; + + for (i = 0; i < stuff->n; i++) + { + if (!(pDrawables[i] = (DrawablePtr)SecurityLookupDrawable( + drawables[i], client, SecurityReadAccess))) + { + DEALLOCATE_LOCAL(pDrawables); + return(BadDrawable); + } + } + } + + count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n; + if (!(pScrVisInfo = (XdbeScreenVisualInfo *)xalloc(count * + sizeof(XdbeScreenVisualInfo)))) + { + if (pDrawables) + { + DEALLOCATE_LOCAL(pDrawables); + } + + return(BadAlloc); + } + + length = 0; + + for (i = 0; i < count; i++) + { + pScreen = (stuff->n == 0) ? screenInfo.screens[i] : + pDrawables[i]->pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (!(*pDbeScreenPriv->GetVisualInfo)(pScreen, &pScrVisInfo[i])) + { + /* We failed to alloc pScrVisInfo[i].visinfo. */ + + /* Free visinfos that we allocated for previous screen infos.*/ + for (j = 0; j < i; j++) + { + xfree(pScrVisInfo[j].visinfo); + } + + /* Free pDrawables if we needed to allocate it above. */ + if (pDrawables) + { + DEALLOCATE_LOCAL(pDrawables); + } + + return(BadAlloc); + } + + /* Account for n, number of xDbeVisInfo items in list. */ + length += sizeof(CARD32); + + /* Account for n xDbeVisInfo items */ + length += pScrVisInfo[i].count * sizeof(xDbeVisInfo); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = length; + rep.m = count; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.m, n); + } + + /* Send off reply. */ + WriteToClient(client, sizeof(xDbeGetVisualInfoReply), (char *)&rep); + + for (i = 0; i < count; i++) + { + CARD32 data32; + + /* For each screen in the reply, send off the visual info */ + + /* Send off number of visuals. */ + data32 = (CARD32)pScrVisInfo[i].count; + + if (client->swapped) + { + swapl(&data32, n); + } + + WriteToClient(client, sizeof(CARD32), (char *)&data32); + + /* Now send off visual info items. */ + for (j = 0; j < pScrVisInfo[i].count; j++) + { + xDbeVisInfo visInfo; + + /* Copy the data in the client data structure to a protocol + * data structure. We will send data to the client from the + * protocol data structure. + */ + + visInfo.visualID = (CARD32)pScrVisInfo[i].visinfo[j].visual; + visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth; + visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel; + + if (client->swapped) + { + swapl(&visInfo.visualID, n); + + /* We do not need to swap depth and perfLevel since they are + * already 1 byte quantities. + */ + } + + /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */ + WriteToClient(client, 2*sizeof(CARD32), (char *)&visInfo.visualID); + } + } + + /* Clean up memory. */ + for (i = 0; i < count; i++) + { + xfree(pScrVisInfo[i].visinfo); + } + xfree(pScrVisInfo); + + if (pDrawables) + { + DEALLOCATE_LOCAL(pDrawables); + } + + return(client->noClientException); + +} /* ProcDbeGetVisualInfo() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetbackBufferAttributes + * + * Description: + * + * This function is for processing a ProcDbeGetbackBufferAttributes + * request. This request returns information about a back buffer. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetBackBufferAttributes(client) + ClientPtr client; +{ + REQUEST(xDbeGetBackBufferAttributesReq); + xDbeGetBackBufferAttributesReply rep; + DbeWindowPrivPtr pDbeWindowPriv; + int n; + + + REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); + + if (!(pDbeWindowPriv = (DbeWindowPrivPtr)SecurityLookupIDByType(client, + stuff->buffer, dbeWindowPrivResType, SecurityReadAccess))) + { + rep.attributes = None; + } + else + { + rep.attributes = pDbeWindowPriv->pWindow->drawable.id; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.attributes, n); + } + + WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), + (char *)&rep); + return(client->noClientException); + +} /* ProcDbeGetbackBufferAttributes() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeDispatch + * + * Description: + * + * This function dispatches DBE requests. + * + *****************************************************************************/ + +static int +ProcDbeDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + + switch (stuff->data) + { + case X_DbeGetVersion: + return(ProcDbeGetVersion(client)); + + case X_DbeAllocateBackBufferName: + return(ProcDbeAllocateBackBufferName(client)); + + case X_DbeDeallocateBackBufferName: + return(ProcDbeDeallocateBackBufferName(client)); + + case X_DbeSwapBuffers: + return(ProcDbeSwapBuffers(client)); + + case X_DbeBeginIdiom: + return(ProcDbeBeginIdiom(client)); + + case X_DbeEndIdiom: + return(Success); + + case X_DbeGetVisualInfo: + return(ProcDbeGetVisualInfo(client)); + + case X_DbeGetBackBufferAttributes: + return(ProcDbeGetBackBufferAttributes(client)); + + default: + return(BadRequest); + } + +} /* ProcDbeDispatch() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetVersion + * + * Description: + * + * This function is for processing a DbeGetVersion request on a swapped + * server. This request returns the major and minor version numbers of + * this extension. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetVersion(client) + ClientPtr client; +{ + REQUEST(xDbeGetVersionReq); + register int n; + + + swaps(&stuff->length, n); + return(ProcDbeGetVersion(client)); + +} /* SProcDbeGetVersion() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeAllocateBackBufferName + * + * Description: + * + * This function is for processing a DbeAllocateBackBufferName request on + * a swapped server. This request allocates a drawable ID used to refer + * to the back buffer of a window. + * + * Return Values: + * + * BadAlloc - server can not allocate resources + * BadIDChoice - id is out of range for client; id is already in use + * BadMatch - window is not an InputOutput window; + * visual of window is not on list returned by + * DBEGetVisualInfo; + * BadValue - invalid swap action is specified + * BadWindow - window is not a valid window + * Success + * + *****************************************************************************/ + +static int +SProcDbeAllocateBackBufferName(client) + ClientPtr client; +{ + REQUEST(xDbeAllocateBackBufferNameReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); + + swapl(&stuff->window, n); + swapl(&stuff->buffer, n); + /* stuff->swapAction is a byte. We do not need to swap this field. */ + + return(ProcDbeAllocateBackBufferName(client)); + +} /* SProcDbeAllocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeDeallocateBackBufferName + * + * Description: + * + * This function is for processing a DbeDeallocateBackBufferName request + * on a swapped server. This request frees a drawable ID that was + * obtained by a DbeAllocateBackBufferName request. + * + * Return Values: + * + * BadBuffer - buffer to deallocate is not associated with a window + * Success + * + *****************************************************************************/ + +static int +SProcDbeDeallocateBackBufferName(client) + ClientPtr client; +{ + REQUEST (xDbeDeallocateBackBufferNameReq); + register int n; + + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); + + swapl(&stuff->buffer, n); + + return(ProcDbeDeallocateBackBufferName(client)); + +} /* SProcDbeDeallocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeSwapBuffers + * + * Description: + * + * This function is for processing a DbeSwapBuffers request on a swapped + * server. This request swaps the buffers for all windows listed, + * applying the appropriate swap action for each window. + * + * Return Values: + * + * BadMatch - a window in request is not double-buffered; a window in + * request is listed more than once; all windows in request do + * not have the same root + * BadValue - invalid swap action is specified + * BadWindow - a window in request is not valid + * Success + * + *****************************************************************************/ + +static int +SProcDbeSwapBuffers(client) + ClientPtr client; +{ + REQUEST(xDbeSwapBuffersReq); + register int i, n; + xDbeSwapInfo *pSwapInfo; + + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); + + swapl(&stuff->n, n); + + if (stuff->n != 0) + { + pSwapInfo = (xDbeSwapInfo *)stuff+1; + + /* The swap info following the fix part of this request is a window(32) + * followed by a 1 byte swap action and then 3 pad bytes. We only need + * to swap the window information. + */ + for (i = 0; i < stuff->n; i++) + { + swapl(&pSwapInfo->window, n); + } + } + + return(ProcDbeSwapBuffers(client)); + +} /* SProcDbeSwapBuffers() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeBeginIdiom + * + * Description: + * + * This function is for processing a DbeBeginIdiom request on a swapped + * server. This request informs the server that a complex swap will + * immediately follow this request. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeBeginIdiom(client) + ClientPtr client; +{ + REQUEST(xDbeBeginIdiomReq); + register int n; + + swaps(&stuff->length, n); + return(ProcDbeBeginIdiom(client)); + +} /* SProcDbeBeginIdiom() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetVisualInfo + * + * Description: + * + * This function is for processing a ProcDbeGetVisualInfo request on a + * swapped server. This request returns information about which visuals + * support double buffering. + * + * Return Values: + * + * BadDrawable - value in screen specifiers is not a valid drawable + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetVisualInfo(client) + ClientPtr client; +{ + REQUEST(xDbeGetVisualInfoReq); + register int n; + + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); + + swapl(&stuff->n, n); + SwapRestL(stuff); + + return(ProcDbeGetVisualInfo(client)); + +} /* SProcDbeGetVisualInfo() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetbackBufferAttributes + * + * Description: + * + * This function is for processing a ProcDbeGetbackBufferAttributes + * request on a swapped server. This request returns information about a + * back buffer. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetBackBufferAttributes(client) + ClientPtr client; +{ + REQUEST (xDbeGetBackBufferAttributesReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); + + swapl(&stuff->buffer, n); + + return(ProcDbeGetBackBufferAttributes(client)); + +} /* SProcDbeGetBackBufferAttributes() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeDispatch + * + * Description: + * + * This function dispatches DBE requests on a swapped server. + * + *****************************************************************************/ + +static int +SProcDbeDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + + switch (stuff->data) + { + case X_DbeGetVersion: + return(SProcDbeGetVersion(client)); + + case X_DbeAllocateBackBufferName: + return(SProcDbeAllocateBackBufferName(client)); + + case X_DbeDeallocateBackBufferName: + return(SProcDbeDeallocateBackBufferName(client)); + + case X_DbeSwapBuffers: + return(SProcDbeSwapBuffers(client)); + + case X_DbeBeginIdiom: + return(SProcDbeBeginIdiom(client)); + + case X_DbeEndIdiom: + return(Success); + + case X_DbeGetVisualInfo: + return(SProcDbeGetVisualInfo(client)); + + case X_DbeGetBackBufferAttributes: + return(SProcDbeGetBackBufferAttributes(client)); + + default: + return (BadRequest); + } + +} /* SProcDbeDispatch() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeSetupBackgroundPainter + * + * Description: + * + * This function sets up pGC to clear pixmaps. + * + * Return Values: + * + * TRUE - setup was successful + * FALSE - the window's background state is NONE + * + *****************************************************************************/ + +static Bool +DbeSetupBackgroundPainter(pWin, pGC) + WindowPtr pWin; + GCPtr pGC; +{ + pointer gcvalues[4]; + int ts_x_origin, ts_y_origin; + PixUnion background; + int backgroundState; + Mask gcmask; + + + /* First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + ts_x_origin = ts_y_origin = 0; + while (pWin->backgroundState == ParentRelative) + { + ts_x_origin -= pWin->origin.x; + ts_y_origin -= pWin->origin.y; + + pWin = pWin->parent; + } + backgroundState = pWin->backgroundState; + background = pWin->background; + + switch (backgroundState) + { + case BackgroundPixel: + gcvalues[0] = (pointer)background.pixel; + gcvalues[1] = (pointer)FillSolid; + gcmask = GCForeground|GCFillStyle; + break; + + case BackgroundPixmap: + gcvalues[0] = (pointer)FillTiled; + gcvalues[1] = (pointer)background.pixmap; + gcvalues[2] = (pointer)ts_x_origin; + gcvalues[3] = (pointer)ts_y_origin; + gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; + break; + + default: + /* pWin->backgroundState == None */ + return(FALSE); + } + + if (DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE) != 0) + { + return(FALSE); + } + + return(TRUE); + +} /* DbeSetupBackgroundPainter() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeDrawableDelete + * + * Description: + * + * This is the resource delete function for dbeDrawableResType. + * It is registered when the drawable resource type is created in + * DbeExtensionInit(). + * + * To make resource deletion simple, we do not do anything in this function + * and leave all resource deleteion to DbeWindowPrivDelete(), which will + * eventually be called or already has been called. Deletion functions are + * not guaranteed to be called in any particular order. + * + *****************************************************************************/ +static int +DbeDrawableDelete(pDrawable, id) + pointer pDrawable; + XID id; +{ + return(Success); + +} /* DbeDrawableDelete() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeWindowPrivDelete + * + * Description: + * + * This is the resource delete function for dbeWindowPrivResType. + * It is registered when the drawable resource type is created in + * DbeExtensionInit(). + * + *****************************************************************************/ +static int +DbeWindowPrivDelete(pDbeWinPriv, id) + pointer pDbeWinPriv; + XID id; +{ + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr)pDbeWinPriv; + int i; + + + /* + ************************************************************************** + ** Remove the buffer ID from the ID array. + ************************************************************************** + */ + + /* Find the ID in the ID array. */ + i = 0; + while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id)) + { + i++; + } + + if (i == pDbeWindowPriv->nBufferIDs) + { + /* We did not find the ID in the array. We should never get here. */ + return(BadValue); + } + + /* Remove the ID from the array. */ + + if (i < (pDbeWindowPriv->nBufferIDs - 1)) + { + /* Compress the buffer ID array, overwriting the ID in the process. */ + memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i+1], + (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID)); + } + else + { + /* We are removing the last ID in the array, in which case, the + * assignement below is all that we need to do. + */ + } + pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT; + + pDbeWindowPriv->nBufferIDs--; + + /* If an extended array was allocated, then check to see if the remaining + * buffer IDs will fit in the static array. + */ + + if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) && + (pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS)) + { + /* Copy the IDs back into the static array. */ + memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs, + DBE_INIT_MAX_IDS * sizeof(XID)); + + /* Free the extended array; use the static array. */ + xfree(pDbeWindowPriv->IDs); + pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; + pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; + } + + + /* + ************************************************************************** + ** Perform DDX level tasks. + ************************************************************************** + */ + + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV( + (DbeWindowPrivPtr)pDbeWindowPriv); + (*pDbeScreenPriv->WinPrivDelete)((DbeWindowPrivPtr)pDbeWindowPriv, id); + + + /* + ************************************************************************** + ** Perform miscellaneous tasks if this is the last buffer associated + ** with the window. + ************************************************************************** + */ + + if (pDbeWindowPriv->nBufferIDs == 0) + { + /* Reset the DBE window priv pointer. */ + pDbeWindowPriv->pWindow->devPrivates[dbeWindowPrivIndex].ptr = + (pointer)NULL; + + /* We are done with the window priv. */ + xfree(pDbeWindowPriv); + } + + return(Success); + +} /* DbeWindowPrivDelete() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeResetProc + * + * Description: + * + * This routine is called at the end of every server generation. + * It deallocates any memory reserved for the extension and performs any + * other tasks related to shutting down the extension. + * + *****************************************************************************/ +static void +DbeResetProc(extEntry) + ExtensionEntry *extEntry; +{ + int i; + ScreenPtr pScreen; + DbeScreenPrivPtr pDbeScreenPriv; + + + if (dbeScreenPrivIndex < 0) + { + return; + } + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (pDbeScreenPriv) + { + /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit().*/ + pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; + + if (pDbeScreenPriv->ResetProc) + (*pDbeScreenPriv->ResetProc)(pScreen); + + if (pDbeScreenPriv->winPrivPrivSizes) + { + xfree(pDbeScreenPriv->winPrivPrivSizes); + } + + xfree(pDbeScreenPriv); + } + } + + /* We want to init the initialization function table after every server + * reset in DbeRegisterFunction(). + */ + firstRegistrationPass = TRUE; + +} /* DbeResetProc() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeDestroyWindow + * + * Description: + * + * This is the wrapper for pScreen->DestroyWindow. + * This function frees buffer resources for a window before it is + * destroyed. + * + *****************************************************************************/ + +static Bool +DbeDestroyWindow(pWin) + WindowPtr pWin; +{ + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + ScreenPtr pScreen; + Bool ret; + + + /* + ************************************************************************** + ** 1. Unwrap the member routine. + ************************************************************************** + */ + + pScreen = pWin->drawable.pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; + + /* + ************************************************************************** + ** 2. Do any work necessary before the member routine is called. + ** + ** Call the window priv delete function for all buffer IDs associated + ** with this window. + ************************************************************************** + */ + + if (pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) + { + while (pDbeWindowPriv) + { + /* *DbeWinPrivDelete() will free the window private and set it to + * NULL if there are no more buffer IDs associated with this + * window. + */ + FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); + pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); + } + } + + /* + ************************************************************************** + ** 3. Call the member routine, saving its result if necessary. + ************************************************************************** + */ + + ret = (*pScreen->DestroyWindow)(pWin); + + /* + ************************************************************************** + ** 4. Rewrap the member routine, restoring the wrapper value first in case + ** the wrapper (or something that it wrapped) change this value. + ************************************************************************** + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + + /* + ************************************************************************** + ** 5. Do any work necessary after the member routine has been called. + ** + ** In this case we do not need to do anything. + ************************************************************************** + */ + + return(ret); + +} /* DbeDestroyWindow() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeExtensionInit + * + * Description: + * + * Called from InitExtensions in main() + * + *****************************************************************************/ + +void +DbeExtensionInit() +{ + ExtensionEntry *extEntry; + register int i, j; + ScreenPtr pScreen; + DbeScreenPrivPtr pDbeScreenPriv; + int nStubbedScreens = 0; + Bool ddxInitSuccess; + + + /* Allocate private pointers in windows and screens. */ + + if ((dbeScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) + { + return; + } + + if ((dbeWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) + { + return; + } + + /* Initialize the priv priv counts between server generations. */ + winPrivPrivCount = 0; + + /* Create the resource types. */ + dbeDrawableResType = + CreateNewResourceType(DbeDrawableDelete) | RC_CACHED | RC_DRAWABLE; + dbeWindowPrivResType = + CreateNewResourceType(DbeWindowPrivDelete); + + for (i = 0; i < screenInfo.numScreens; i++) + { + /* For each screen, set up DBE screen privates and init DIX and DDX + * interface. + */ + + pScreen = screenInfo.screens[i]; + + if (!AllocateWindowPrivate(pScreen, dbeWindowPrivIndex, 0) || + !(pDbeScreenPriv = + (DbeScreenPrivPtr)Xcalloc(sizeof(DbeScreenPrivRec)))) + { + /* If we can not alloc a window or screen private, + * then free any privates that we already alloc'ed and return + */ + + for (j = 0; j < i; j++) + { + xfree(screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex].ptr); + screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex].ptr = NULL; + } + return; + } + + pScreen->devPrivates[dbeScreenPrivIndex].ptr = (pointer)pDbeScreenPriv; + + /* Store the DBE priv priv size info for later use when allocating + * priv privs at the driver level. + */ + pDbeScreenPriv->winPrivPrivLen = 0; + pDbeScreenPriv->winPrivPrivSizes = (unsigned *)NULL; + pDbeScreenPriv->totalWinPrivSize = sizeof(DbeWindowPrivRec); + + /* Copy the resource types */ + pDbeScreenPriv->dbeDrawableResType = dbeDrawableResType; + pDbeScreenPriv->dbeWindowPrivResType = dbeWindowPrivResType; + + /* Copy the private indices */ + pDbeScreenPriv->dbeScreenPrivIndex = dbeScreenPrivIndex; + pDbeScreenPriv->dbeWindowPrivIndex = dbeWindowPrivIndex; + + if(DbeInitFunct[i]) + { + /* This screen supports DBE. */ + + /* Setup DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; + pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv; + pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex; + pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv; + + /* Setup DDX. */ + ddxInitSuccess = (*DbeInitFunct[i])(pScreen, pDbeScreenPriv); + + /* DDX DBE initialization may have the side affect of + * reallocating pDbeScreenPriv, so we need to update it. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (ddxInitSuccess) + { + /* Wrap DestroyWindow. The DDX initialization function + * already wrapped PositionWindow for us. + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + } + else + { + /* DDX initialization failed. Stub the screen. */ + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); + } + } + else + { + /* This screen does not support DBE. */ + +#ifndef DISABLE_MI_DBE_BY_DEFAULT + /* Setup DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; + pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv; + pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex; + pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv; + + /* Setup DDX. */ + ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv); + + /* DDX DBE initialization may have the side affect of + * reallocating pDbeScreenPriv, so we need to update it. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (ddxInitSuccess) + { + /* Wrap DestroyWindow. The DDX initialization function + * already wrapped PositionWindow for us. + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + } + else + { + /* DDX initialization failed. Stub the screen. */ + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); + } +#else + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); +#endif + + } /* else -- this screen does not support DBE. */ + + } /* for (i = 0; i < screenInfo.numScreens; i++) */ + + + if (nStubbedScreens == screenInfo.numScreens) + { + /* All screens stubbed. Clean up and return. */ + + for (i = 0; i < screenInfo.numScreens; i++) + { + xfree(screenInfo.screens[i]->devPrivates[dbeScreenPrivIndex].ptr); + pScreen->devPrivates[dbeScreenPrivIndex].ptr = NULL; + } + return; + } + + + /* Now add the extension. */ + extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents, + DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch, + DbeResetProc, StandardMinorOpcode); + + dbeErrorBase = extEntry->errorBase; + +} /* DbeExtensionInit() */ + + diff --git a/dbe/dbestruct.h b/dbe/dbestruct.h new file mode 100644 index 000000000..c429cede8 --- /dev/null +++ b/dbe/dbestruct.h @@ -0,0 +1,261 @@ +/* $Xorg: dbestruct.h,v 1.3 2000/08/17 19:48:16 cpqbld Exp $ */ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the Hewlett-Packard + * Company shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the Hewlett-Packard Company. + * + * Header file for DIX-related DBE + * + *****************************************************************************/ + + +#ifndef DBE_STRUCT_H +#define DBE_STRUCT_H + + +/* INCLUDES */ + +#define NEED_DBE_PROTOCOL +#include "Xdbeproto.h" +#include "windowstr.h" + + +/* DEFINES */ + +#define DBE_SCREEN_PRIV(pScreen) \ + ((dbeScreenPrivIndex < 0) ? \ + NULL : \ + ((DbeScreenPrivPtr)((pScreen)->devPrivates[dbeScreenPrivIndex].ptr))) + +#define DBE_SCREEN_PRIV_FROM_DRAWABLE(pDrawable) \ + DBE_SCREEN_PRIV((pDrawable)->pScreen) + +#define DBE_SCREEN_PRIV_FROM_WINDOW_PRIV(pDbeWindowPriv) \ + DBE_SCREEN_PRIV((pDbeWindowPriv)->pWindow->drawable.pScreen) + +#define DBE_SCREEN_PRIV_FROM_WINDOW(pWindow) \ + DBE_SCREEN_PRIV((pWindow)->drawable.pScreen) + +#define DBE_SCREEN_PRIV_FROM_PIXMAP(pPixmap) \ + DBE_SCREEN_PRIV((pPixmap)->drawable.pScreen) + +#define DBE_SCREEN_PRIV_FROM_GC(pGC)\ + DBE_SCREEN_PRIV((pGC)->pScreen) + +#define DBE_WINDOW_PRIV(pWindow)\ + ((dbeWindowPrivIndex < 0) ? \ + NULL : \ + ((DbeWindowPrivPtr)(pWindow->devPrivates[dbeWindowPrivIndex].ptr))) + +/* Initial size of the buffer ID array in the window priv. */ +#define DBE_INIT_MAX_IDS 2 + +/* Reallocation increment for the buffer ID array. */ +#define DBE_INCR_MAX_IDS 4 + +/* Marker for free elements in the buffer ID array. */ +#define DBE_FREE_ID_ELEMENT 0 + + +/* TYPEDEFS */ + +/* Record used to pass swap information between DIX and DDX swapping + * procedures. + */ +typedef struct _DbeSwapInfoRec +{ + WindowPtr pWindow; + unsigned char swapAction; + +} DbeSwapInfoRec, *DbeSwapInfoPtr; + +/* + ****************************************************************************** + ** Per-window data + ****************************************************************************** + */ + +typedef struct _DbeWindowPrivRec +{ + /* A pointer to the window with which the DBE window private (buffer) is + * associated. + */ + WindowPtr pWindow; + + /* Last known swap action for this buffer. Legal values for this field + * are XdbeUndefined, XdbeBackground, XdbeUntouched, and XdbeCopied. + */ + unsigned char swapAction; + + /* Last known buffer size. + */ + unsigned short width, height; + + /* Coordinates used for static gravity when the window is positioned. + */ + short x, y; + + /* Number of XIDs associated with this buffer. + */ + int nBufferIDs; + + /* Capacity of the current buffer ID array, IDs. */ + int maxAvailableIDs; + + /* Pointer to the array of buffer IDs. This initially points to initIDs. + * When the static limit of the initIDs array is reached, the array is + * reallocated and this pointer is set to the new array instead of initIDs. + */ + XID *IDs; + + /* Initial array of buffer IDs. We are defining the XID array within the + * window priv to optimize for data locality. In most cases, only one + * buffer will be associated with a window. Having the array declared + * here can prevent us from accessing the data in another memory page, + * possibly resulting in a page swap and loss of performance. Initially we + * will use this array to store buffer IDs. For situations where we have + * more IDs than can fit in this static array, we will allocate a larger + * array to use, possibly suffering a performance loss. + */ + XID initIDs[DBE_INIT_MAX_IDS]; + + /* Device-specific private information. + */ + DevUnion *devPrivates; + +} DbeWindowPrivRec, *DbeWindowPrivPtr; + + +/* + ****************************************************************************** + ** Per-screen data + ****************************************************************************** + */ + +typedef struct _DbeScreenPrivRec +{ + /* Info for creating window privs */ + int winPrivPrivLen; /* Length of privs in DbeWindowPrivRec */ + unsigned int *winPrivPrivSizes; /* Array of private record sizes */ + unsigned int totalWinPrivSize; /* PrivRec + size of all priv priv ptrs */ + + /* Resources created by DIX to be used by DDX */ + RESTYPE dbeDrawableResType; + RESTYPE dbeWindowPrivResType; + + /* Private indices created by DIX to be used by DDX */ + int dbeScreenPrivIndex; + int dbeWindowPrivIndex; + + /* Wrapped functions + * It is the responsibilty of the DDX layer to wrap PositionWindow(). + * DbeExtensionInit wraps DestroyWindow(). + */ + PositionWindowProcPtr PositionWindow; + DestroyWindowProcPtr DestroyWindow; + + /* Per-screen DIX routines */ + Bool (*SetupBackgroundPainter)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/, + GCPtr /*pGC*/ +#endif +); + DbeWindowPrivPtr (*AllocWinPriv)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/ +#endif +); + int (*AllocWinPrivPrivIndex)( +#if NeedNestedPrototypes + void +#endif +); + Bool (*AllocWinPrivPriv)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*index*/, + unsigned /*amount*/ +#endif +); + + /* Per-screen DDX routines */ + Bool (*GetVisualInfo)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + XdbeScreenVisualInfo * /*pVisInfo*/ +#endif +); + int (*AllocBackBufferName)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/, + XID /*bufId*/, + int /*swapAction*/ +#endif +); + int (*SwapBuffers)( +#if NeedNestedPrototypes + ClientPtr /*client*/, + int * /*pNumWindows*/, + DbeSwapInfoPtr /*swapInfo*/ +#endif +); + void (*BeginIdiom)( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); + void (*EndIdiom)( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); + void (*WinPrivDelete)( +#if NeedNestedPrototypes + DbeWindowPrivPtr /*pDbeWindowPriv*/, + XID /*bufId*/ +#endif +); + void (*ResetProc)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/ +#endif +); + void (*ValidateBuffer)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/, + XID /*bufId*/, + Bool /*dstbuffer*/ +#endif +); + + /* Device-specific private information. + */ + DevUnion *devPrivates; + +} DbeScreenPrivRec, *DbeScreenPrivPtr; + +#endif /* DBE_STRUCT_H */ diff --git a/dbe/midbe.c b/dbe/midbe.c new file mode 100644 index 000000000..5f6a48b32 --- /dev/null +++ b/dbe/midbe.c @@ -0,0 +1,848 @@ +/* $Xorg: midbe.c,v 1.3 2000/08/17 19:48:16 cpqbld Exp $ */ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the Hewlett-Packard + * Company shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the Hewlett-Packard Company. + * + * Machine-independent DBE code + * + *****************************************************************************/ + + +/* INCLUDES */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "dbestruct.h" +#include "midbestr.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" + + +/* DEFINES */ + + +/* TYPEDEFS */ + + +/* GLOBALS */ + +static int miDbePrivPrivGeneration = 0; +static int miDbeWindowPrivPrivIndex = -1; +static int miDbeScreenPrivPrivIndex = -1; +RESTYPE dbeDrawableResType; +RESTYPE dbeWindowPrivResType; +int dbeScreenPrivIndex = -1; +int dbeWindowPrivIndex = -1; + + + +/****************************************************************************** + * + * DBE MI Procedure: miDbeGetVisualInfo + * + * Description: + * + * This is the MI function for the DbeGetVisualInfo request. This function + * is called through pDbeScreenPriv->GetVisualInfo. This function is also + * called for the DbeAllocateBackBufferName request at the extension level; + * it is called by ProcDbeAllocateBackBufferName() in dbe.c. + * + * If memory allocation fails or we can not get the visual info, this + * function returns FALSE. Otherwise, it returns TRUE for success. + * + *****************************************************************************/ + +static Bool +miDbeGetVisualInfo(pScreen, pScrVisInfo) + ScreenPtr pScreen; + XdbeScreenVisualInfo *pScrVisInfo; +{ + register int i, j, k; + register int count; + DepthPtr pDepth; + XdbeVisualInfo *visInfo; + + + /* Determine number of visuals for this screen. */ + for (i = 0, count = 0; i < pScreen->numDepths; i++) + { + count += pScreen->allowedDepths[i].numVids; + } + + /* Allocate an array of XdbeVisualInfo items. */ + if (!(visInfo = (XdbeVisualInfo *)xalloc(count * sizeof(XdbeVisualInfo)))) + { + return(FALSE); /* memory alloc failure */ + } + + for (i = 0, k = 0; i < pScreen->numDepths; i++) + { + /* For each depth of this screen, get visual information. */ + + pDepth = &pScreen->allowedDepths[i]; + + for (j = 0; j < pDepth->numVids; j++) + { + /* For each visual for this depth of this screen, get visual ID + * and visual depth. Since this is MI code, we will always return + * the same performance level for all visuals (0). A higher + * performance level value indicates higher performance. + */ + visInfo[k].visual = pDepth->vids[j]; + visInfo[k].depth = pDepth->depth; + visInfo[k].perflevel = 0; + k++; + } + } + + /* Record the number of visuals and point visual_depth to + * the array of visual info. + */ + pScrVisInfo->count = count; + pScrVisInfo->visinfo = visInfo; + + return(TRUE); /* success */ + +} /* miDbeGetVisualInfo() */ + + +/****************************************************************************** + * + * DBE MI Procedure: miAllocBackBufferName + * + * Description: + * + * This is the MI function for the DbeAllocateBackBufferName request. + * + *****************************************************************************/ + +static int +miDbeAllocBackBufferName(pWin, bufId, swapAction) + WindowPtr pWin; + XID bufId; + int swapAction; +{ + ScreenPtr pScreen; + DbeWindowPrivPtr pDbeWindowPriv; + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + DbeScreenPrivPtr pDbeScreenPriv; + GCPtr pGC; + xRectangle clearRect; + + + pScreen = pWin->drawable.pScreen; + pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); + + if (pDbeWindowPriv->nBufferIDs == 0) + { + /* There is no buffer associated with the window. + * We have to create the window priv priv. Remember, the window + * priv was created at the DIX level, so all we need to do is + * create the priv priv and attach it to the priv. + */ + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + /* Setup the window priv priv. */ + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + pDbeWindowPrivPriv->pDbeWindowPriv = pDbeWindowPriv; + + /* Get a front pixmap. */ + if (!(pDbeWindowPrivPriv->pFrontBuffer = + (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width, + pDbeWindowPriv->height, + pWin->drawable.depth))) + { + return(BadAlloc); + } + + /* Get a back pixmap. */ + if (!(pDbeWindowPrivPriv->pBackBuffer = + (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width, + pDbeWindowPriv->height, + pWin->drawable.depth))) + { + (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer); + return(BadAlloc); + } + + + /* Make the back pixmap a DBE drawable resource. */ + if (!AddResource(bufId, dbeDrawableResType, + (pointer)pDbeWindowPrivPriv->pBackBuffer)) + { + /* free the buffer and the drawable resource */ + FreeResource(bufId, RT_NONE); + return(BadAlloc); + } + + + /* Attach the priv priv to the priv. */ + pDbeWindowPriv->devPrivates[miDbeWindowPrivPrivIndex].ptr = + (pointer)pDbeWindowPrivPriv; + + + /* Clear the back buffer. */ + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) + { + ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC); + clearRect.x = clearRect.y = 0; + clearRect.width = pDbeWindowPrivPriv->pBackBuffer->drawable.width; + clearRect.height = pDbeWindowPrivPriv->pBackBuffer->drawable.height; + (*pGC->ops->PolyFillRect)( + (DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC, 1, + &clearRect); + } + FreeScratchGC(pGC); + + } /* if no buffer associated with the window */ + + else + { + /* A buffer is already associated with the window. + * Place the new buffer ID information at the head of the ID list. + */ + + /* Associate the new ID with an existing pixmap. */ + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + if (!AddResource(bufId, dbeDrawableResType, + (pointer)pDbeWindowPrivPriv->pBackBuffer)) + { + return(BadAlloc); + } + + } + + return(Success); + +} /* miDbeAllocBackBufferName() */ + + +/****************************************************************************** + * + * DBE MI Procedure: miDbeAliasBuffers + * + * Description: + * + * This function associates all XIDs of a buffer with the back pixmap + * stored in the window priv. + * + *****************************************************************************/ + +static void +miDbeAliasBuffers(pDbeWindowPriv) + DbeWindowPrivPtr pDbeWindowPriv; +{ + int i; + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv = + MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + + for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) + { + ChangeResourceValue(pDbeWindowPriv->IDs[i], dbeDrawableResType, + (pointer)pDbeWindowPrivPriv->pBackBuffer); + } + +} /* miDbeAliasBuffers() */ + + +/****************************************************************************** + * + * DBE MI Procedure: miDbeSwapBuffers + * + * Description: + * + * This is the MI function for the DbeSwapBuffers request. + * + *****************************************************************************/ + +static int +miDbeSwapBuffers(client, pNumWindows, swapInfo) + ClientPtr client; + int *pNumWindows; + DbeSwapInfoPtr swapInfo; +{ + DbeScreenPrivPtr pDbeScreenPriv; + GCPtr pGC; + WindowPtr pWin; + register int i; + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + PixmapPtr pTmpBuffer; + xRectangle clearRect; + + + pWin = swapInfo[0].pWindow; + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin); + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + + /* + ********************************************************************** + ** Setup before swap. + ********************************************************************** + */ + + switch(swapInfo[0].swapAction) + { + case XdbeUndefined: + break; + + case XdbeBackground: + break; + + case XdbeUntouched: + ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer, pGC); + (*pGC->ops->CopyArea)((DrawablePtr)pWin, + (DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer, + pGC, 0, 0, pWin->drawable.width, + pWin->drawable.height, 0, 0); + break; + + case XdbeCopied: + break; + + } + + /* + ********************************************************************** + ** Swap. + ********************************************************************** + */ + + ValidateGC((DrawablePtr)pWin, pGC); + (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, + (DrawablePtr)pWin, pGC, 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + + /* + ********************************************************************** + ** Tasks after swap. + ********************************************************************** + */ + + switch(swapInfo[0].swapAction) + { + case XdbeUndefined: + break; + + case XdbeBackground: + if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) + { + ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC); + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = + pDbeWindowPrivPriv->pBackBuffer->drawable.width; + clearRect.height = + pDbeWindowPrivPriv->pBackBuffer->drawable.height; + (*pGC->ops->PolyFillRect)( + (DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, + pGC, 1, &clearRect); + } + break; + + case XdbeUntouched: + /* Swap pixmap pointers. */ + pTmpBuffer = pDbeWindowPrivPriv->pBackBuffer; + pDbeWindowPrivPriv->pBackBuffer = + pDbeWindowPrivPriv->pFrontBuffer; + pDbeWindowPrivPriv->pFrontBuffer = pTmpBuffer; + + miDbeAliasBuffers(pDbeWindowPrivPriv->pDbeWindowPriv); + + break; + + case XdbeCopied: + break; + + } + + /* Remove the swapped window from the swap information array and decrement + * pNumWindows to indicate to the DIX level how many windows were actually + * swapped. + */ + + if (*pNumWindows > 1) + { + /* We were told to swap more than one window, but we only swapped the + * first one. Remove the first window in the list by moving the last + * window to the beginning. + */ + swapInfo[0].pWindow = swapInfo[*pNumWindows - 1].pWindow; + swapInfo[0].swapAction = swapInfo[*pNumWindows - 1].swapAction; + + /* Clear the last window information just to be safe. */ + swapInfo[*pNumWindows - 1].pWindow = (WindowPtr)NULL; + swapInfo[*pNumWindows - 1].swapAction = 0; + } + else + { + /* Clear the window information just to be safe. */ + swapInfo[0].pWindow = (WindowPtr)NULL; + swapInfo[0].swapAction = 0; + } + + (*pNumWindows)--; + + FreeScratchGC(pGC); + + return(Success); + +} /* miSwapBuffers() */ + + +/****************************************************************************** + * + * DBE MI Procedure: miDbeWinPrivDelete + * + * Description: + * + * This is the MI function for deleting the dbeWindowPrivResType resource. + * This function is invoked indirectly by calling FreeResource() to free + * the resources associated with a DBE buffer ID. There are 5 ways that + * miDbeWinPrivDelete() can be called by FreeResource(). They are: + * + * - A DBE window is destroyed, in which case the DbeDestroyWindow() + * wrapper is invoked. The wrapper calls FreeResource() for all DBE + * buffer IDs. + * + * - miDbeAllocBackBufferName() calls FreeResource() to clean up resources + * after a buffer allocation failure. + * + * - The PositionWindow wrapper, miDbePositionWindow(), calls + * FreeResource() when it fails to create buffers of the new size. + * FreeResource() is called for all DBE buffer IDs. + * + * - FreeClientResources() calls FreeResource() when a client dies or the + * the server resets. + * + * When FreeResource() is called for a DBE buffer ID, the delete function + * for the only other type of DBE resource, dbeDrawableResType, is also + * invoked. This delete function (DbeDrawableDelete) is a NOOP to make + * resource deletion easier. It is not guaranteed which delete function is + * called first. Hence, we will let miDbeWinPrivDelete() free all DBE + * resources. + * + * This function deletes/frees the following stuff associated with + * the window private: + * + * - the ID node in the ID list representing the passed in ID. + * + * In addition, pDbeWindowPriv->nBufferIDs is decremented. + * + * If this function is called for the last/only buffer ID for a window, + * these are additionally deleted/freed: + * + * - the front and back pixmaps + * - the window priv itself + * + *****************************************************************************/ + +static void +miDbeWinPrivDelete(pDbeWindowPriv, bufId) + DbeWindowPrivPtr pDbeWindowPriv; + XID bufId; +{ + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + + + if (pDbeWindowPriv->nBufferIDs != 0) + { + /* We still have at least one more buffer ID associated with this + * window. + */ + return; + } + + + /* We have no more buffer IDs associated with this window. We need to + * free some stuff. + */ + + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + + /* Destroy the front and back pixmaps. */ + if (pDbeWindowPrivPriv->pFrontBuffer) + { + (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)( + pDbeWindowPrivPriv->pFrontBuffer); + } + if (pDbeWindowPrivPriv->pBackBuffer) + { + (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)( + pDbeWindowPrivPriv->pBackBuffer); + } + +} /* miDbeWinPrivDelete() */ + + +/****************************************************************************** + * + * DBE MI Procedure: miDbePositionWindow + * + * Description: + * + * This function was cloned from miMbxPositionWindow() in mimultibuf.c. + * This function resizes the buffer when the window is resized. + * + *****************************************************************************/ + +static Bool +miDbePositionWindow(pWin, x, y) + WindowPtr pWin; + int x; + int y; +{ + ScreenPtr pScreen; + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + int width, height; + int dx, dy, dw, dh; + int sourcex, sourcey; + int destx, desty; + int savewidth, saveheight; + PixmapPtr pFrontBuffer; + PixmapPtr pBackBuffer; + Bool clear; + GCPtr pGC; + xRectangle clearRect; + Bool ret; + + + /* + ************************************************************************** + ** 1. Unwrap the member routine. + ************************************************************************** + */ + + pScreen = pWin->drawable.pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + pScreen->PositionWindow = pDbeScreenPriv->PositionWindow; + + /* + ************************************************************************** + ** 2. Do any work necessary before the member routine is called. + ** + ** In this case we do not need to do anything. + ************************************************************************** + */ + + /* + ************************************************************************** + ** 3. Call the member routine, saving its result if necessary. + ************************************************************************** + */ + + ret = (*pScreen->PositionWindow)(pWin, x, y); + + /* + ************************************************************************** + ** 4. Rewrap the member routine, restoring the wrapper value first in case + ** the wrapper (or something that it wrapped) change this value. + ************************************************************************** + */ + + pDbeScreenPriv->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = miDbePositionWindow; + + /* + ************************************************************************** + ** 5. Do any work necessary after the member routine has been called. + ************************************************************************** + */ + + if (!(pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) + { + return(ret); + } + + if (pDbeWindowPriv->width == pWin->drawable.width && + pDbeWindowPriv->height == pWin->drawable.height) + { + return(ret); + } + + width = pWin->drawable.width; + height = pWin->drawable.height; + + dx = pWin->drawable.x - pDbeWindowPriv->x; + dy = pWin->drawable.y - pDbeWindowPriv->y; + dw = width - pDbeWindowPriv->width; + dh = height - pDbeWindowPriv->height; + + GravityTranslate (0, 0, -dx, -dy, dw, dh, pWin->bitGravity, &destx, &desty); + + clear = ((pDbeWindowPriv->width < (unsigned short)width ) || + (pDbeWindowPriv->height < (unsigned short)height) || + (pWin->bitGravity == ForgetGravity)); + + sourcex = 0; + sourcey = 0; + savewidth = pDbeWindowPriv->width; + saveheight = pDbeWindowPriv->height; + + /* Clip rectangle to source and destination. */ + if (destx < 0) + { + savewidth += destx; + sourcex -= destx; + destx = 0; + } + + if (destx + savewidth > width) + { + savewidth = width - destx; + } + + if (desty < 0) + { + saveheight += desty; + sourcey -= desty; + desty = 0; + } + + if (desty + saveheight > height) + { + saveheight = height - desty; + } + + pDbeWindowPriv->width = width; + pDbeWindowPriv->height = height; + pDbeWindowPriv->x = pWin->drawable.x; + pDbeWindowPriv->y = pWin->drawable.y; + + pGC = GetScratchGC (pWin->drawable.depth, pScreen); + + if (clear) + { + if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) + { + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = width; + clearRect.height = height; + } + else + { + clear = FALSE; + } + } + + /* Create DBE buffer pixmaps equal to size of resized window. */ + pFrontBuffer = (*pScreen->CreatePixmap)(pScreen, width, height, + pWin->drawable.depth); + + pBackBuffer = (*pScreen->CreatePixmap)(pScreen, width, height, + pWin->drawable.depth); + + if (!pFrontBuffer || !pBackBuffer) + { + /* We failed at creating 1 or 2 of the pixmaps. */ + + if (pFrontBuffer) + { + (*pScreen->DestroyPixmap)(pFrontBuffer); + } + + if (pBackBuffer) + { + (*pScreen->DestroyPixmap)(pBackBuffer); + } + + /* Destroy all buffers for this window. */ + while (pDbeWindowPriv) + { + /* DbeWindowPrivDelete() will free the window private if there no + * more buffer IDs associated with this window. + */ + FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); + pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); + } + + FreeScratchGC(pGC); + return(FALSE); + } + + else + { + /* Clear out the new DBE buffer pixmaps. */ + + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + + + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + ValidateGC((DrawablePtr)pFrontBuffer, pGC); + + /* I suppose this could avoid quite a bit of work if + * it computed the minimal area required. + */ + if (clear) + { + (*pGC->ops->PolyFillRect)((DrawablePtr)pFrontBuffer, pGC, 1, + &clearRect); + (*pGC->ops->PolyFillRect)((DrawablePtr)pBackBuffer , pGC, 1, + &clearRect); + } + + /* Copy the contents of the old DBE pixmaps to the new pixmaps. */ + if (pWin->bitGravity != ForgetGravity) + { + (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer, + (DrawablePtr)pFrontBuffer, pGC, sourcex, + sourcey, savewidth, saveheight, destx, desty); + (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, + (DrawablePtr)pBackBuffer, pGC, sourcex, + sourcey, savewidth, saveheight, destx, desty); + } + + /* Destroy the old pixmaps, and point the DBE window priv to the new + * pixmaps. + */ + + (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer); + (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pBackBuffer); + + pDbeWindowPrivPriv->pFrontBuffer = pFrontBuffer; + pDbeWindowPrivPriv->pBackBuffer = pBackBuffer; + + /* Make sure all XID are associated with the new back pixmap. */ + miDbeAliasBuffers(pDbeWindowPriv); + + FreeScratchGC(pGC); + } + + return(ret); + +} /* miDbePositionWindow() */ + + +/****************************************************************************** + * + * DBE MI Procedure: miDbeResetProc + * + * Description: + * + * This function is called from DbeResetProc(), which is called at the end + * of every server generation. This function peforms any MI-specific + * shutdown tasks. + * + *****************************************************************************/ + +static void +miDbeResetProc(pScreen) + ScreenPtr pScreen; +{ + DbeScreenPrivPtr pDbeScreenPriv; + + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + /* Unwrap wrappers */ + pScreen->PositionWindow = pDbeScreenPriv->PositionWindow; + +} /* miDbeResetProc() */ + + +/****************************************************************************** + * + * DBE MI Procedure: miDbeInit + * + * Description: + * + * This is the MI initialization function called by DbeExtensionInit(). + * + *****************************************************************************/ + +Bool +miDbeInit(pScreen, pDbeScreenPriv) + ScreenPtr pScreen; + DbeScreenPrivPtr pDbeScreenPriv; +{ + /* Copy resource types created by DIX */ + dbeDrawableResType = pDbeScreenPriv->dbeDrawableResType; + dbeWindowPrivResType = pDbeScreenPriv->dbeWindowPrivResType; + + /* Copy private indices created by DIX */ + dbeScreenPrivIndex = pDbeScreenPriv->dbeScreenPrivIndex; + dbeWindowPrivIndex = pDbeScreenPriv->dbeWindowPrivIndex; + + /* Reset the window priv privs if generations do not match. */ + if (miDbePrivPrivGeneration != serverGeneration) + { + /* + ********************************************************************** + ** Allocate the window priv priv. + ********************************************************************** + */ + + miDbeWindowPrivPrivIndex = (*pDbeScreenPriv->AllocWinPrivPrivIndex)(); + + if (!(*pDbeScreenPriv->AllocWinPrivPriv)(pScreen, + miDbeWindowPrivPrivIndex, sizeof(MiDbeWindowPrivPrivRec))) + { + return(FALSE); + } + + /* Make sure we only do this code once. */ + miDbePrivPrivGeneration = serverGeneration; + + } /* if -- Reset priv privs. */ + + /* Wrap functions. */ + pDbeScreenPriv->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = miDbePositionWindow; + + /* Initialize the per-screen DBE function pointers. */ + pDbeScreenPriv->GetVisualInfo = miDbeGetVisualInfo; + pDbeScreenPriv->AllocBackBufferName = miDbeAllocBackBufferName; + pDbeScreenPriv->SwapBuffers = miDbeSwapBuffers; + pDbeScreenPriv->BeginIdiom = 0; + pDbeScreenPriv->EndIdiom = 0; + pDbeScreenPriv->ResetProc = miDbeResetProc; + pDbeScreenPriv->WinPrivDelete = miDbeWinPrivDelete; + + /* The mi implementation doesn't need buffer validation. */ + pDbeScreenPriv->ValidateBuffer = (void (*)())NoopDDA; + + return(TRUE); + +} /* miDbeInit() */ diff --git a/dbe/midbe.h b/dbe/midbe.h new file mode 100644 index 000000000..7b91a6697 --- /dev/null +++ b/dbe/midbe.h @@ -0,0 +1,48 @@ +/* $Xorg: midbe.h,v 1.3 2000/08/17 19:48:16 cpqbld Exp $ */ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the Hewlett-Packard + * Company shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the Hewlett-Packard Company. + * + * Header file for users of machine-independent DBE code + * + *****************************************************************************/ + + +#ifndef MIDBE_H +#define MIDBE_H + +/* EXTERNS */ + +extern Bool miDbeInit( +#if NeedFunctionPrototypes + ScreenPtr pScreen, + DbeScreenPrivPtr pDbeScreenPriv +#endif +); + +#endif /* MIDBE_H */ + diff --git a/dbe/midbestr.h b/dbe/midbestr.h new file mode 100644 index 000000000..8c351072e --- /dev/null +++ b/dbe/midbestr.h @@ -0,0 +1,96 @@ +/* $Xorg: midbestr.h,v 1.3 2000/08/17 19:48:16 cpqbld Exp $ */ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the Hewlett-Packard + * Company shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the Hewlett-Packard Company. + * + * Header file for users of machine-independent DBE code + * + *****************************************************************************/ + + +#ifndef MIDBE_STRUCT_H +#define MIDBE_STRUCT_H + + +/* DEFINES */ + +#define MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv) \ + (((miDbeWindowPrivPrivIndex < 0) || (!pDbeWindowPriv)) ? \ + NULL : \ + ((MiDbeWindowPrivPrivPtr) \ + ((pDbeWindowPriv)->devPrivates[miDbeWindowPrivPrivIndex].ptr))) + +#define MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin)\ + MI_DBE_WINDOW_PRIV_PRIV(DBE_WINDOW_PRIV(pWin)) + +#define MI_DBE_SCREEN_PRIV_PRIV(pDbeScreenPriv) \ + (((miDbeScreenPrivPrivIndex < 0) || (!pDbeScreenPriv)) ? \ + NULL : \ + ((MiDbeScreenPrivPrivPtr) \ + ((pDbeScreenPriv)->devPrivates[miDbeScreenPrivPrivIndex].ptr))) + + +/* TYPEDEFS */ + +typedef struct _MiDbeWindowPrivPrivRec +{ + /* Place machine-specific fields in here. + * Since this is mi code, we do not really have machine-specific fields. + */ + + /* Pointer to a drawable that contains the contents of the back buffer. + */ + PixmapPtr pBackBuffer; + + /* Pointer to a drawable that contains the contents of the front buffer. + * This pointer is only used for the XdbeUntouched swap action. For that + * swap action, we need to copy the front buffer (window) contents into + * this drawable, copy the contents of current back buffer drawable (the + * back buffer) into the window, swap the front and back drawable pointers, + * and then swap the drawable/resource associations in the resource + * database. + */ + PixmapPtr pFrontBuffer; + + /* Pointer back to our window private with which we are associated. */ + DbeWindowPrivPtr pDbeWindowPriv; + +} MiDbeWindowPrivPrivRec, *MiDbeWindowPrivPrivPtr; + +typedef struct _MiDbeScreenPrivPrivRec +{ + /* Place machine-specific fields in here. + * Since this is mi code, we do not really have machine-specific fields. + */ + + /* Pointer back to our screen private with which we are associated. */ + DbeScreenPrivPtr pDbeScreenPriv; + +} MiDbeScreenPrivPrivRec, *MiDbeScreenPrivPrivPtr; + +#endif /* MIDBE_STRUCT_H */ + diff --git a/dix/BuiltInAtoms b/dix/BuiltInAtoms new file mode 100644 index 000000000..910c62706 --- /dev/null +++ b/dix/BuiltInAtoms @@ -0,0 +1,329 @@ +File: .../x11/server/dix/BuiltInAtoms + +This file is of a fixed format and is used to generate both the file +include/XAtom.h and dix/initatoms.c. Neither of those files should be +edited directly. Changing the atoms in this file, or even the order in +which they occur, is equivalent to forcing a new (minor) version number +on the server. Take care. + +The format of the file is that each built in atom starts in column 1 +with no text, other than spaces and tabs, on that line other than a +mandatory trailing "@" at the end of the line. For each atom (Foo) +below the defines will be of the form + #define XA_Foo +and the string value of the atom will be "Foo". + +The comment lines in this file are not guaranteed to be accurate. To see the +current truth, look at the Xlib documentation as well as the protocol spec. + +Atoms occur in five distinct name spaces within the protocol. Any particular +atom may or may not have some client interpretation within each of the name +spaces. For each of the built in atoms, the intended semantics and the space +within which it is defined is indicated. + +Those name spaces are + Property names + Property types + Selections + Font properties + Type of a ClientMessage event (none built into server) + +For the font properties mentioned here, see the spec for more information. + + -- Selections -- + +PRIMARY @ + Selection. +SECONDARY @ + Selection. + + -- Property types and names -- + +ARC @ + Property type: + x, y: INT16 + width, height: CARD16, + angle1, angle2: INT16 +ATOM @ + Property type: + atom: ATOM +BITMAP @ + Property type: + bitmap: PIXMAP + This is asserted to be of depth 1. +CARDINAL @ + Property type: + card: CARD32 or CARD16 or CARD8 + the datum size is dependent on the property format +COLORMAP @ + Property type: + colormap: COLORMAP +CURSOR @ + Property type: + cursor: CURSOR +CUT_BUFFER0 @ +CUT_BUFFER1 @ +CUT_BUFFER2 @ +CUT_BUFFER3 @ +CUT_BUFFER4 @ +CUT_BUFFER5 @ +CUT_BUFFER6 @ +CUT_BUFFER7 @ + Property name: (type: STRING) + Used to implement cut buffer ring, in particular Andrew uses + this mechanism. Anyone else using this sort of IPC mechanism + should use these properties. + + Data is normally fetched and stored out of CUT_BUFFER0; the + RotateProperties request is used to rotate these buffers. +DRAWABLE @ + Property type: + drawable: DRAWABLE +FONT @ + Property type: + font: FONT +INTEGER @ + Property type: + card: INT32 or INT16 or INT8 + the datum size is dependent on the property format +PIXMAP @ + Property type: + pixmap: PIXMAP +POINT @ + Property type: + x, y: INT16 +RECTANGLE @ + Property type: + x, y: INT16 + width, height: CARD16 +RESOURCE_MANAGER @ + Property name: (type: STRING) + Contents of the user's resource manager data base. +RGB_COLOR_MAP @ + Property type: + colormap: COLORMAP + red-max: CARD32 + red-mult: CARD32 + green-max: CARD32 + green-mult: CARD32 + blue-max: CARD32 + blue-mult: CARD32 + base-pixel: CARD32 + + The fields `red_max', `green_max', and `blue_max' give the maximum + red, green, and blue values, respectively. Each color + coefficient ranges from 0 to its max, inclusive. For example, + a common colormap allocation is 3/3/2: 3 planes for red, 3 + planes for green, and 2 planes for blue. Such a colormap would + have red_max == 7, green_max = 7, and blue_max = 3. An alternate + allocation that uses only 216 colors is red_max = 5, green_max = + 5, and blue_max = 5. + + The fields `red_mult', `green_mult', and `blue_mult' give the + scale factors used to compose a full pixel value. (See next + paragraph.) For a 3/3/2 allocation red_mult might be 32, + green_mult might be 4, and blue_mult might be 1. For a + 6-colors-each allocation, red_mult might be 36, green_mult might + be 6, and blue_mult might be 1. + + The field `base_pixel' gives the base pixel value used to + compose a full pixel value. Normally base_pixel is obtained + from a call to XAllocColorPlanes(). Given integer red, green, + and blue coefficients in their appropriate ranges, one can + compute a corresponding pixel value with the expression: + + r * red_mult + g * green_mult + b * blue_mult + base_pixel + + For gray-scale colormaps, only the colormap, red_max, red_mult, + and base_pixel fields are defined; the other fields are + ignored. To compute a gray-scale pixel value, use: + + gray * red_mult + base_pixel + + This is provided to allow applications to share color maps. + +RGB_BEST_MAP @ +RGB_BLUE_MAP @ +RGB_DEFAULT_MAP @ +RGB_GRAY_MAP @ +RGB_GREEN_MAP @ +RGB_RED_MAP @ + Property name: (type: RGB_COLOR_MAP) + The needs of most applications can be met with five colormaps. + Polite applications may need only a small RGB space, and can + use a portion of the default color map. Applications doing + high-quality RGB rendering will need an entire colormap, + filled with as large an RGB space as possible, e.g. 332. For + color separations, an application may need maximum device + resolution for each of red, green, and blue, even if this + requires three renderings with three colormaps. + + Each of the above five names would be used for sharing color + maps. +STRING @ + Property type: + sequence of Bytes +VISUALID @ + Property type: + visual: VISUALID +WINDOW @ + Property type: + window: WINDOW +WM_COMMAND @ + Property name: (type: STRING) + Command line arguments used to invoke this application. The + arguments are delimited by null characters (ASCII 0). +WM_HINTS @ + Property type: + flags: CARD32 + input: BOOL32 + initial-state: CARD32 + icon-pixmap: PIXMAP + icon-window: WINDOW + icon_mask: BITMAP + icon-x, icon-y: INT32 + flags contains the following bits + 0x00000001 input hint + 0x00000002 state hint + 0x00000004 icon pixmap hint + 0x00000008 icon window hint + 0x00000010 icon position hint + values for initial-state + 0 unspecified -> application does not + care and WM should pick one. + 1 normal + 2 zoomed + 3 iconic + 4 inactive -> application believes + itself to be seldomly used. WM may wish to + place it on an inactive menu. + This type is potentially extensible. The order is critical; + append to the end only. + Property name: (type: WM_HINTS) + Additional hints set by the client for use by the window + manager. +WM_CLIENT_MACHINE @ + Property name: (type: STRING) + used to communicate with the window manager. The host name + of the machine the client is running on may be set here. +WM_ICON_NAME @ + Property name: (type: STRING) + what the application would like the label to be for + the iconic form of the window. +WM_ICON_SIZE @ + Property type: + minWidth, min-height: CARD32 + maxWidth, max-height: CARD32 + widthInc, height-inc: CARD32 + Property name: (type: ICON_SIZE) + The window manager may set this property on the root window + to specify the icon sizes it allows. +WM_NAME @ + Property name: (type: STRING) + used to communicate with the window manager. This is + what the application would like the label for the window. +WM_NORMAL_HINTS @ + Property name: (type: SIZE_HINTS) + used to communicate with the window manager. This is size + hints for a window in its "normal" state. +WM_SIZE_HINTS @ + Property type: + flags: CARD32 + x, y: INT32 + width, height: CARD32 + min-width, min-height: CARD32 + max-width, max-height: CARD32 + width-inc, height-inc: CARD32 + min-aspect-x, min-aspect-y: CARD32 + max-aspect-x, max-aspect-y: CARD32 + flags contains the following bits + 0x00000001 user specified x and y + 0x00000002 user specified width and height + 0x00000004 program specified position + 0x00000008 program specified size + 0x00000010 program specified minimum size + 0x00000020 program specified maximum size + 0x00000040 program specified resize increment + 0x00000080 program specified aspect ratio + This type is potentially extensible. The order is critical; + append to the end only. +WM_ZOOM_HINTS @ + Property name: (type: SIZE_HINTS) + used to communicate with the window manager. This is size + hints for a window in its "zoomed" state. + + -- Font properties -- + +MIN_SPACE @ + Font property: CARD32 +NORM_SPACE @ + Font property: CARD32 +MAX_SPACE @ + Font property: CARD32 +END_SPACE @ + Font property: CARD32 +SUPERSCRIPT_X @ + Font property: INT32 +SUPERSCRIPT_Y @ + Font property: INT32 +SUBSCRIPT_X @ + Font property: INT32 +SUBSCRIPT_Y @ + Font property: INT32 +UNDERLINE_POSITION @ + Font property: INT32 +UNDERLINE_THICKNESS @ + Font property: CARD32 +STRIKEOUT_ASCENT @ + Font property: INT32 +STRIKEOUT_DESCENT @ + Font property: INT32 +ITALIC_ANGLE @ + Font property: INT32 +X_HEIGHT @ + Font property: INT32 +QUAD_WIDTH @ + Font property: INT32 +WEIGHT @ + Font property: CARD32 +POINT_SIZE @ + Font property: CARD32 +RESOLUTION @ + Font property: CARD32 + +The following optional properties on fonts have values that are atoms. The +atom print name is the useful information. + +COPYRIGHT @ + of the font distribution +NOTICE @ + trademark/copyright of the character shapes +FONT_NAME @ + name of this particular instance of a font +FAMILY_NAME @ + name of the 'font family' to which it belongs +FULL_NAME @ + full text name of the font + +The following aren't in order but putting them at the end avoids encoding +changes. + +CAP_HEIGHT @ + Font property: CARD32 + + +WM_CLASS @ + Property name: (type: STRING) + Used (possibly by some window managers; definitely by + session managers) to look up resources in the resource + data base on behalf of the client who set this property. + There are 2 elements: + {char *resource_name; char *resource_class;} + delimited by a null character (ascii 0) + +WM_TRANSIENT_FOR @ + Property name: (type: WINDOW) + Used by transient top-level windows, such as dialog + boxes, to point to their logical "parents". The window + manager can then take down the dialog boxes when the + "parent" gets iconified, for instance. diff --git a/dix/CHANGES b/dix/CHANGES new file mode 100644 index 000000000..d8fb7c31a --- /dev/null +++ b/dix/CHANGES @@ -0,0 +1,17 @@ +The following changes have been made to this directory since R3 (for +a full description, see doc/Server/r4.tbl.ms): + + o Windows restructured (memory reduction, devPrivates and speedups) + o GCs restructured (memory reduction, devPrivates and wrappers) + o Screens restructured (window ops merged in, devPrivates) + o Pixmaps restructured (drawable changes mostly) + o Cursors restructured (shares glyph bits now) + o Visuals restructured (screen index removed, fields rearranged) + o Devices restructured (input extension changes) + o Out of memory changes. Many interfaces now return OutOfMemory + status. + o Synchronous grab code rewritten. Should conform to our + understanding of the protocol now. Be careful when time + stamping events (don't allow time to run backwards). + o Resource types redesigned and rewritten. + o Internal fake color allocation routine for software cursors. diff --git a/dix/atom.c b/dix/atom.c new file mode 100644 index 000000000..d5c53d2e2 --- /dev/null +++ b/dix/atom.c @@ -0,0 +1,211 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: atom.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ + +#include "X.h" +#include "Xatom.h" +#include "misc.h" +#include "resource.h" + +#define InitialTableSize 100 + +typedef struct _Node { + struct _Node *left, *right; + Atom a; + unsigned int fingerPrint; + char *string; +} NodeRec, *NodePtr; + +static Atom lastAtom = None; +static NodePtr atomRoot = (NodePtr)NULL; +static unsigned long tableLength; +static NodePtr *nodeTable; + +Atom +MakeAtom(string, len, makeit) + char *string; + unsigned len; + Bool makeit; +{ + register NodePtr * np; + unsigned i; + int comp; + register unsigned int fp = 0; + + np = &atomRoot; + for (i = 0; i < (len+1)/2; i++) + { + fp = fp * 27 + string[i]; + fp = fp * 27 + string[len - 1 - i]; + } + while (*np != (NodePtr) NULL) + { + if (fp < (*np)->fingerPrint) + np = &((*np)->left); + else if (fp > (*np)->fingerPrint) + np = &((*np)->right); + else + { /* now start testing the strings */ + comp = strncmp(string, (*np)->string, (int)len); + if ((comp < 0) || ((comp == 0) && (len < strlen((*np)->string)))) + np = &((*np)->left); + else if (comp > 0) + np = &((*np)->right); + else + return(*np)->a; + } + } + if (makeit) + { + register NodePtr nd; + + nd = (NodePtr) xalloc(sizeof(NodeRec)); + if (!nd) + return BAD_RESOURCE; + if (lastAtom < XA_LAST_PREDEFINED) + { + nd->string = string; + } + else + { + nd->string = (char *) xalloc(len + 1); + if (!nd->string) { + xfree(nd); + return BAD_RESOURCE; + } + strncpy(nd->string, string, (int)len); + nd->string[len] = 0; + } + if ((lastAtom + 1) >= tableLength) { + NodePtr *table; + + table = (NodePtr *) xrealloc(nodeTable, + tableLength * (2 * sizeof(NodePtr))); + if (!table) { + if (nd->string != string) + xfree(nd->string); + xfree(nd); + return BAD_RESOURCE; + } + tableLength <<= 1; + nodeTable = table; + } + *np = nd; + nd->left = nd->right = (NodePtr) NULL; + nd->fingerPrint = fp; + nd->a = (++lastAtom); + *(nodeTable+lastAtom) = nd; + return nd->a; + } + else + return None; +} + +Bool +ValidAtom(atom) + Atom atom; +{ + return (atom != None) && (atom <= lastAtom); +} + +char * +NameForAtom(atom) + Atom atom; +{ + NodePtr node; + if (atom > lastAtom) return 0; + if ((node = nodeTable[atom]) == (NodePtr)NULL) return 0; + return node->string; +} + +void +AtomError() +{ + FatalError("initializing atoms"); +} + +void +FreeAtom(patom) + NodePtr patom; +{ + if(patom->left) + FreeAtom(patom->left); + if(patom->right) + FreeAtom(patom->right); + if (patom->a > XA_LAST_PREDEFINED) + xfree(patom->string); + xfree(patom); +} + +void +FreeAllAtoms() +{ + if(atomRoot == (NodePtr)NULL) + return; + FreeAtom(atomRoot); + atomRoot = (NodePtr)NULL; + xfree(nodeTable); + nodeTable = (NodePtr *)NULL; + lastAtom = None; +} + +void +InitAtoms() +{ + FreeAllAtoms(); + tableLength = InitialTableSize; + nodeTable = (NodePtr *)xalloc(InitialTableSize*sizeof(NodePtr)); + if (!nodeTable) + AtomError(); + nodeTable[None] = (NodePtr)NULL; + MakePredeclaredAtoms(); + if (lastAtom != XA_LAST_PREDEFINED) + AtomError (); +} + + diff --git a/dix/buildatoms b/dix/buildatoms new file mode 100644 index 000000000..bedec5886 --- /dev/null +++ b/dix/buildatoms @@ -0,0 +1,42 @@ +#!/bin/sh +hfile=../../X11/Xatom.h +cfile=initatoms.c +rm -f $hfile $cfile +umask 222 +awk ' +BEGIN { + hfile = "'$hfile'"; + cfile = "'$cfile'"; + hformat = "#define XA_%s ((Atom) %d)\n"; + printf("#ifndef XATOM_H\n") > hfile; + printf("#define XATOM_H 1\n\n") > hfile; + printf("/* THIS IS A GENERATED FILE\n") > hfile; + printf(" *\n") > hfile; + printf(" * Do not change! Changing this file implies a protocol change!\n") > hfile; + printf(" */\n\n") > hfile; + + printf("/* THIS IS A GENERATED FILE\n") > cfile; + printf(" *\n") > cfile; + printf(" * Do not change! Changing this file implies a protocol change!\n") > cfile; + printf(" */\n\n") > cfile; + printf("#include \"X.h\"\n") > cfile; + printf("#include \"Xatom.h\"\n") > cfile; + printf("extern Atom MakeAtom();\n") > cfile; + printf("MakePredeclaredAtoms()\n") > cfile; + printf("{\n") > cfile; + + } + +NF == 2 && $2 == "@" { + printf(hformat, $1, ++atomno) > hfile ; + printf(" if (MakeAtom(\"%s\", %d, 1) != XA_%s) AtomError();\n", $1, length($1), $1) > cfile ; + } + +END { + printf("\n") > hfile; + printf(hformat, "LAST_PREDEFINED", atomno) > hfile ; + printf("#endif /* XATOM_H */\n") > hfile; + printf("}\n") > cfile ; + } +' BuiltInAtoms +exit 0 diff --git a/dix/colormap.c b/dix/colormap.c new file mode 100644 index 000000000..610ea01ca --- /dev/null +++ b/dix/colormap.c @@ -0,0 +1,2869 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: colormap.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "misc.h" +#include "dix.h" +#include "colormapst.h" +#include "os.h" +#include "scrnintstr.h" +#include "resource.h" +#include "windowstr.h" + +extern XID clientErrorValue; + +static Pixel FindBestPixel( +#if NeedFunctionPrototypes + EntryPtr /*pentFirst*/, + int /*size*/, + xrgb * /*prgb*/, + int /*channel*/ +#endif +); + +static int AllComp( +#if NeedFunctionPrototypes + EntryPtr /*pent*/, + xrgb * /*prgb*/ +#endif +); + +static int RedComp( +#if NeedFunctionPrototypes + EntryPtr /*pent*/, + xrgb * /*prgb*/ +#endif +); + +static int GreenComp( +#if NeedFunctionPrototypes + EntryPtr /*pent*/, + xrgb * /*prgb*/ +#endif +); + +static int BlueComp( +#if NeedFunctionPrototypes + EntryPtr /*pent*/, + xrgb * /*prgb*/ +#endif +); + +static void FreePixels( +#if NeedFunctionPrototypes + register ColormapPtr /*pmap*/, + register int /*client*/ +#endif +); + +static void CopyFree( +#if NeedFunctionPrototypes + int /*channel*/, + int /*client*/, + ColormapPtr /*pmapSrc*/, + ColormapPtr /*pmapDst*/ +#endif +); + +static void FreeCell( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + Pixel /*i*/, + int /*channel*/ +#endif +); + +static void UpdateColors( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/ +#endif +); + +static int AllocDirect( +#if NeedFunctionPrototypes + int /*client*/, + ColormapPtr /*pmap*/, + int /*c*/, + int /*r*/, + int /*g*/, + int /*b*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*prmask*/, + Pixel * /*pgmask*/, + Pixel * /*pbmask*/ +#endif +); + +static int AllocPseudo( +#if NeedFunctionPrototypes + int /*client*/, + ColormapPtr /*pmap*/, + int /*c*/, + int /*r*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*pmask*/, + Pixel ** /*pppixFirst*/ +#endif +); + +static Bool AllocCP( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + EntryPtr /*pentFirst*/, + int /*count*/, + int /*planes*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*pMask*/ +#endif +); + +static Bool AllocShared( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + Pixel * /*ppix*/, + int /*c*/, + int /*r*/, + int /*g*/, + int /*b*/, + Pixel /*rmask*/, + Pixel /*gmask*/, + Pixel /*bmask*/, + Pixel * /*ppixFirst*/ +#endif +); + +static int FreeCo( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + int /*client*/, + int /*color*/, + int /*npixIn*/, + Pixel * /*ppixIn*/, + Pixel /*mask*/ +#endif +); + +static int TellNoMap( +#if NeedFunctionPrototypes + WindowPtr /*pwin*/, + Colormap * /*pmid*/ +#endif +); + +static void FindColorInRootCmap ( +#if NeedFunctionPrototypes + ColormapPtr /* pmap */, + EntryPtr /* pentFirst */, + int /* size */, + xrgb* /* prgb */, + Pixel* /* pPixel */, + int /* channel */, + ColorCompareProcPtr /* comp */ +#endif +); + +#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1) +#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1) +#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1) +#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask) + +/* GetNextBitsOrBreak(bits, mask, base) -- + * (Suggestion: First read the macro, then read this explanation. + * + * Either generate the next value to OR in to a pixel or break out of this + * while loop + * + * This macro is used when we're trying to generate all 2^n combinations of + * bits in mask. What we're doing here is counting in binary, except that + * the bits we use to count may not be contiguous. This macro will be + * called 2^n times, returning a different value in bits each time. Then + * it will cause us to break out of a surrounding loop. (It will always be + * called from within a while loop.) + * On call: mask is the value we want to find all the combinations for + * base has 1 bit set where the least significant bit of mask is set + * + * For example,if mask is 01010, base should be 0010 and we count like this: + * 00010 (see this isn't so hard), + * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so + * we add that to bits getting (0100 + 0100) = + * 01000 for our next value. + * then we add 0010 to get + * 01010 and we're done (easy as 1, 2, 3) + */ +#define GetNextBitsOrBreak(bits, mask, base) \ + if((bits) == (mask)) \ + break; \ + (bits) += (base); \ + while((bits) & ~(mask)) \ + (bits) += ((bits) & ~(mask)); +/* ID of server as client */ +#define SERVER_ID 0 + +typedef struct _colorResource +{ + Colormap mid; + int client; +} colorResource; + +/* Invariants: + * refcnt == 0 means entry is empty + * refcnt > 0 means entry is useable by many clients, so it can't be changed + * refcnt == AllocPrivate means entry owned by one client only + * fShared should only be set if refcnt == AllocPrivate, and only in red map + */ + + +/* Create and initialize the color map */ +int +CreateColormap (mid, pScreen, pVisual, ppcmap, alloc, client) + Colormap mid; /* resource to use for this colormap */ + ScreenPtr pScreen; + VisualPtr pVisual; + ColormapPtr *ppcmap; + int alloc; /* 1 iff all entries are allocated writeable */ + int client; +{ + int class, size; + unsigned long sizebytes; + ColormapPtr pmap; + register EntryPtr pent; + int i; + register Pixel *ppix, **pptr; + extern int colormapPrivateCount; + + class = pVisual->class; + if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID)) + return (BadMatch); + + size = pVisual->ColormapEntries; + sizebytes = (size * sizeof(Entry)) + + (MAXCLIENTS * sizeof(Pixel *)) + + (MAXCLIENTS * sizeof(int)); + if ((class | DynamicClass) == DirectColor) + sizebytes *= 3; + sizebytes += sizeof(ColormapRec); + pmap = (ColormapPtr) xalloc(sizebytes); + if (!pmap) + return (BadAlloc); + pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec)); + sizebytes = size * sizeof(Entry); + pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes); + pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed + + (MAXCLIENTS * sizeof(Pixel *))); + pmap->mid = mid; + pmap->flags = 0; /* start out with all flags clear */ + if(mid == pScreen->defColormap) + pmap->flags |= IsDefault; + pmap->pScreen = pScreen; + pmap->pVisual = pVisual; + pmap->class = class; + if ((class | DynamicClass) == DirectColor) + size = NUMRED(pVisual); + pmap->freeRed = size; + bzero ((char *) pmap->red, (int)sizebytes); + bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int)); + for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; ) + *pptr = (Pixel *)NULL; + if (alloc == AllocAll) + { + if (class & DynamicClass) + pmap->flags |= AllAllocated; + for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--) + pent->refcnt = AllocPrivate; + pmap->freeRed = 0; + ppix = (Pixel *)xalloc(size * sizeof(Pixel)); + if (!ppix) + { + xfree(pmap); + return (BadAlloc); + } + pmap->clientPixelsRed[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsRed[client] = size; + } + + if ((class | DynamicClass) == DirectColor) + { + pmap->freeGreen = NUMGREEN(pVisual); + pmap->green = (EntryPtr)((char *)pmap->numPixelsRed + + (MAXCLIENTS * sizeof(int))); + pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes); + pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen + + (MAXCLIENTS * sizeof(Pixel *))); + pmap->freeBlue = NUMBLUE(pVisual); + pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen + + (MAXCLIENTS * sizeof(int))); + pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes); + pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue + + (MAXCLIENTS * sizeof(Pixel *))); + + bzero ((char *) pmap->green, (int)sizebytes); + bzero ((char *) pmap->blue, (int)sizebytes); + + memmove((char *) pmap->clientPixelsGreen, + (char *) pmap->clientPixelsRed, + MAXCLIENTS * sizeof(Pixel *)); + memmove((char *) pmap->clientPixelsBlue, + (char *) pmap->clientPixelsRed, + MAXCLIENTS * sizeof(Pixel *)); + bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int)); + bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int)); + + /* If every cell is allocated, mark its refcnt */ + if (alloc == AllocAll) + { + size = pmap->freeGreen; + for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--) + pent->refcnt = AllocPrivate; + pmap->freeGreen = 0; + ppix = (Pixel *) xalloc(size * sizeof(Pixel)); + if (!ppix) + { + xfree(pmap->clientPixelsRed[client]); + xfree(pmap); + return(BadAlloc); + } + pmap->clientPixelsGreen[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsGreen[client] = size; + + size = pmap->freeBlue; + for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--) + pent->refcnt = AllocPrivate; + pmap->freeBlue = 0; + ppix = (Pixel *) xalloc(size * sizeof(Pixel)); + if (!ppix) + { + xfree(pmap->clientPixelsGreen[client]); + xfree(pmap->clientPixelsRed[client]); + xfree(pmap); + return(BadAlloc); + } + pmap->clientPixelsBlue[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsBlue[client] = size; + } + } + if (!AddResource(mid, RT_COLORMAP, (pointer)pmap)) + return (BadAlloc); + /* If the device wants a chance to initialize the colormap in any way, + * this is it. In specific, if this is a Static colormap, this is the + * time to fill in the colormap's values */ + pmap->flags |= BeingCreated; + + + /* + * Allocate the array of devPrivate's for this colormap. + */ + + if (colormapPrivateCount == 0) + pmap->devPrivates = NULL; + else + { + pmap->devPrivates = (DevUnion *) xalloc ( + colormapPrivateCount * sizeof(DevUnion)); + + if (!pmap->devPrivates) + { + FreeResource (mid, RT_NONE); + return BadAlloc; + } + } + + if (!(*pScreen->CreateColormap)(pmap)) + { + FreeResource (mid, RT_NONE); + return BadAlloc; + } + pmap->flags &= ~BeingCreated; + *ppcmap = pmap; + return (Success); +} + +int +FreeColormap (value, mid) + pointer value; /* must conform to DeleteType */ + XID mid; +{ + int i; + register EntryPtr pent; + ColormapPtr pmap = (ColormapPtr)value; + + if(CLIENT_ID(mid) != SERVER_ID) + { + (*pmap->pScreen->UninstallColormap) (pmap); + WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid); + } + + /* This is the device's chance to undo anything it needs to, especially + * to free any storage it allocated */ + (*pmap->pScreen->DestroyColormap)(pmap); + + if(pmap->clientPixelsRed) + { + for(i = 0; i < MAXCLIENTS; i++) + xfree(pmap->clientPixelsRed[i]); + } + + if ((pmap->class == PseudoColor) || (pmap->class == GrayScale)) + { + for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1]; + pent >= pmap->red; + pent--) + { + if(pent->fShared) + { + if (--pent->co.shco.red->refcnt == 0) + xfree(pent->co.shco.red); + if (--pent->co.shco.green->refcnt == 0) + xfree(pent->co.shco.green); + if (--pent->co.shco.blue->refcnt == 0) + xfree(pent->co.shco.blue); + } + } + } + if((pmap->class | DynamicClass) == DirectColor) + { + for(i = 0; i < MAXCLIENTS; i++) + { + xfree(pmap->clientPixelsGreen[i]); + xfree(pmap->clientPixelsBlue[i]); + } + } + + if (pmap->devPrivates) + xfree(pmap->devPrivates); + + xfree(pmap); + return(Success); +} + +/* Tell window that pmid has disappeared */ +static int +TellNoMap (pwin, pmid) + WindowPtr pwin; + Colormap *pmid; +{ + xEvent xE; + if (wColormap(pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = None; + xE.u.colormap.new = TRUE; + xE.u.colormap.state = ColormapUninstalled; + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + if (pwin->optional) { + pwin->optional->colormap = None; + CheckWindowOptionalNeed (pwin); + } + } + + return (WT_WALKCHILDREN); +} + +/* Tell window that pmid got uninstalled */ +int +TellLostMap (pwin, value) + WindowPtr pwin; + pointer value; +{ + Colormap *pmid = (Colormap *)value; + xEvent xE; + if (wColormap(pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = *pmid; + xE.u.colormap.new = FALSE; + xE.u.colormap.state = ColormapUninstalled; + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + } + + return (WT_WALKCHILDREN); +} + +/* Tell window that pmid got installed */ +int +TellGainedMap (pwin, value) + WindowPtr pwin; + pointer value; +{ + Colormap *pmid = (Colormap *)value; + xEvent xE; + if (wColormap (pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = *pmid; + xE.u.colormap.new = FALSE; + xE.u.colormap.state = ColormapInstalled; + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + } + + return (WT_WALKCHILDREN); +} + + +int +CopyColormapAndFree (mid, pSrc, client) + Colormap mid; + ColormapPtr pSrc; + int client; +{ + ColormapPtr pmap = (ColormapPtr) NULL; + int result, alloc, size; + Colormap midSrc; + ScreenPtr pScreen; + VisualPtr pVisual; + + pScreen = pSrc->pScreen; + pVisual = pSrc->pVisual; + midSrc = pSrc->mid; + alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ? + AllocAll : AllocNone; + size = pVisual->ColormapEntries; + + /* If the create returns non-0, it failed */ + result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client); + if(result != Success) + return(result); + if(alloc == AllocAll) + { + memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry)); + if((pmap->class | DynamicClass) == DirectColor) + { + memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry)); + memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry)); + } + pSrc->flags &= ~AllAllocated; + FreePixels(pSrc, client); + UpdateColors(pmap); + return(Success); + } + + CopyFree(REDMAP, client, pSrc, pmap); + if ((pmap->class | DynamicClass) == DirectColor) + { + CopyFree(GREENMAP, client, pSrc, pmap); + CopyFree(BLUEMAP, client, pSrc, pmap); + } + if (pmap->class & DynamicClass) + UpdateColors(pmap); + /* XXX should worry about removing any RT_CMAPENTRY resource */ + return(Success); +} + +/* Helper routine for freeing large numbers of cells from a map */ +static void +CopyFree (channel, client, pmapSrc, pmapDst) + int channel, client; + ColormapPtr pmapSrc, pmapDst; +{ + int z, npix, oldFree; + EntryPtr pentSrcFirst, pentDstFirst; + EntryPtr pentSrc, pentDst; + Pixel *ppix; + int nalloc; + + switch(channel) + { + case REDMAP: + ppix = (pmapSrc->clientPixelsRed)[client]; + npix = (pmapSrc->numPixelsRed)[client]; + pentSrcFirst = pmapSrc->red; + pentDstFirst = pmapDst->red; + oldFree = pmapSrc->freeRed; + break; + case GREENMAP: + ppix = (pmapSrc->clientPixelsGreen)[client]; + npix = (pmapSrc->numPixelsGreen)[client]; + pentSrcFirst = pmapSrc->green; + pentDstFirst = pmapDst->green; + oldFree = pmapSrc->freeGreen; + break; + case BLUEMAP: + ppix = (pmapSrc->clientPixelsBlue)[client]; + npix = (pmapSrc->numPixelsBlue)[client]; + pentSrcFirst = pmapSrc->blue; + pentDstFirst = pmapDst->blue; + oldFree = pmapSrc->freeBlue; + break; + } + nalloc = 0; + if (pmapSrc->class & DynamicClass) + { + for(z = npix; --z >= 0; ppix++) + { + /* Copy entries */ + pentSrc = pentSrcFirst + *ppix; + pentDst = pentDstFirst + *ppix; + if (pentDst->refcnt > 0) + { + pentDst->refcnt++; + } + else + { + *pentDst = *pentSrc; + nalloc++; + if (pentSrc->refcnt > 0) + pentDst->refcnt = 1; + else + pentSrc->fShared = FALSE; + } + FreeCell(pmapSrc, *ppix, channel); + } + } + + /* Note that FreeCell has already fixed pmapSrc->free{Color} */ + switch(channel) + { + case REDMAP: + pmapDst->freeRed -= nalloc; + (pmapDst->clientPixelsRed)[client] = + (pmapSrc->clientPixelsRed)[client]; + (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL; + (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client]; + (pmapSrc->numPixelsRed)[client] = 0; + break; + case GREENMAP: + pmapDst->freeGreen -= nalloc; + (pmapDst->clientPixelsGreen)[client] = + (pmapSrc->clientPixelsGreen)[client]; + (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL; + (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client]; + (pmapSrc->numPixelsGreen)[client] = 0; + break; + case BLUEMAP: + pmapDst->freeBlue -= nalloc; + pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client]; + pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL; + pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client]; + pmapSrc->numPixelsBlue[client] = 0; + break; + } +} + +/* Free the ith entry in a color map. Must handle freeing of + * colors allocated through AllocColorPlanes */ +static void +FreeCell (pmap, i, channel) + ColormapPtr pmap; + Pixel i; + int channel; +{ + EntryPtr pent; + int *pCount; + + + switch (channel) + { + case PSEUDOMAP: + case REDMAP: + pent = (EntryPtr) &pmap->red[i]; + pCount = &pmap->freeRed; + break; + case GREENMAP: + pent = (EntryPtr) &pmap->green[i]; + pCount = &pmap->freeGreen; + break; + case BLUEMAP: + pent = (EntryPtr) &pmap->blue[i]; + pCount = &pmap->freeBlue; + break; + } + /* If it's not privately allocated and it's not time to free it, just + * decrement the count */ + if (pent->refcnt > 1) + pent->refcnt--; + else + { + /* If the color type is shared, find the sharedcolor. If decremented + * refcnt is 0, free the shared cell. */ + if (pent->fShared) + { + if(--pent->co.shco.red->refcnt == 0) + xfree(pent->co.shco.red); + if(--pent->co.shco.green->refcnt == 0) + xfree(pent->co.shco.green); + if(--pent->co.shco.blue->refcnt == 0) + xfree(pent->co.shco.blue); + pent->fShared = FALSE; + } + pent->refcnt = 0; + *pCount += 1; + } +} + +static void +UpdateColors (pmap) + ColormapPtr pmap; +{ + xColorItem *defs; + register xColorItem *pdef; + register EntryPtr pent; + register VisualPtr pVisual; + int i, n, size; + + pVisual = pmap->pVisual; + size = pVisual->ColormapEntries; + defs = (xColorItem *)ALLOCATE_LOCAL(size * sizeof(xColorItem)); + if (!defs) + return; + n = 0; + pdef = defs; + if (pmap->class == DirectColor) + { + for (i = 0; i < size; i++) + { + if (!pmap->red[i].refcnt && + !pmap->green[i].refcnt && + !pmap->blue[i].refcnt) + continue; + pdef->pixel = ((Pixel)i << pVisual->offsetRed) | + ((Pixel)i << pVisual->offsetGreen) | + ((Pixel)i << pVisual->offsetBlue); + pdef->red = pmap->red[i].co.local.red; + pdef->green = pmap->green[i].co.local.green; + pdef->blue = pmap->blue[i].co.local.blue; + pdef->flags = DoRed|DoGreen|DoBlue; + pdef++; + n++; + } + } + else + { + for (i = 0, pent = pmap->red; i < size; i++, pent++) + { + if (!pent->refcnt) + continue; + pdef->pixel = i; + if(pent->fShared) + { + pdef->red = pent->co.shco.red->color; + pdef->green = pent->co.shco.green->color; + pdef->blue = pent->co.shco.blue->color; + } + else + { + pdef->red = pent->co.local.red; + pdef->green = pent->co.local.green; + pdef->blue = pent->co.local.blue; + } + pdef->flags = DoRed|DoGreen|DoBlue; + pdef++; + n++; + } + } + if (n) + (*pmap->pScreen->StoreColors)(pmap, n, defs); + DEALLOCATE_LOCAL(defs); +} + +/* Get a read-only color from a ColorMap (probably slow for large maps) + * Returns by changing the value in pred, pgreen, pblue and pPix + */ +int +AllocColor (pmap, pred, pgreen, pblue, pPix, client) + ColormapPtr pmap; + unsigned short *pred, *pgreen, *pblue; + Pixel *pPix; + int client; +{ + Pixel pixR, pixG, pixB; + int entries; + xrgb rgb; + int class; + VisualPtr pVisual; + int npix; + Pixel *ppix; + + pVisual = pmap->pVisual; + (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual); + rgb.red = *pred; + rgb.green = *pgreen; + rgb.blue = *pblue; + class = pmap->class; + entries = pVisual->ColormapEntries; + + /* If the colormap is being created, then we want to be able to change + * the colormap, even if it's a static type. Otherwise, we'd never be + * able to initialize static colormaps + */ + if(pmap->flags & BeingCreated) + class |= DynamicClass; + + /* If this is one of the static storage classes, and we're not initializing + * it, the best we can do is to find the closest color entry to the + * requested one and return that. + */ + switch (class) { + case StaticColor: + case StaticGray: + /* Look up all three components in the same pmap */ + *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); + *pred = pmap->red[pixR].co.local.red; + *pgreen = pmap->red[pixR].co.local.green; + *pblue = pmap->red[pixR].co.local.blue; + npix = pmap->numPixelsRed[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixR; + pmap->clientPixelsRed[client] = ppix; + pmap->numPixelsRed[client]++; + break; + + case TrueColor: + /* Look up each component in its own map, then OR them together */ + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); + *pPix = (pixR << pVisual->offsetRed) | + (pixG << pVisual->offsetGreen) | + (pixB << pVisual->offsetBlue); + *pred = pmap->red[pixR].co.local.red; + *pgreen = pmap->green[pixG].co.local.green; + *pblue = pmap->blue[pixB].co.local.blue; + npix = pmap->numPixelsRed[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixR; + pmap->clientPixelsRed[client] = ppix; + npix = pmap->numPixelsGreen[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixG; + pmap->clientPixelsGreen[client] = ppix; + npix = pmap->numPixelsBlue[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixB; + pmap->clientPixelsBlue[client] = ppix; + pmap->numPixelsRed[client]++; + pmap->numPixelsGreen[client]++; + pmap->numPixelsBlue[client]++; + break; + + case GrayScale: + case PseudoColor: + if (pmap->mid != pmap->pScreen->defColormap && + pmap->pVisual->vid == pmap->pScreen->rootVisual) + { + ColormapPtr prootmap = (ColormapPtr) + SecurityLookupIDByType (clients[client], pmap->pScreen->defColormap, + RT_COLORMAP, SecurityReadAccess); + + if (pmap->class == prootmap->class) + FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, + pPix, PSEUDOMAP, AllComp); + } + if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP, + client, AllComp) != Success) + return (BadAlloc); + break; + + case DirectColor: + if (pmap->mid != pmap->pScreen->defColormap && + pmap->pVisual->vid == pmap->pScreen->rootVisual) + { + ColormapPtr prootmap = (ColormapPtr) + SecurityLookupIDByType (clients[client], pmap->pScreen->defColormap, + RT_COLORMAP, SecurityReadAccess); + + if (pmap->class == prootmap->class) + { + pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; + FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, + &pixR, REDMAP, RedComp); + pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; + FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb, + &pixG, GREENMAP, GreenComp); + pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; + FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb, + &pixB, BLUEMAP, BlueComp); + *pPix = pixR | pixG | pixB; + } + } + + pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; + if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, + client, RedComp) != Success) + return (BadAlloc); + pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; + if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, + GREENMAP, client, GreenComp) != Success) + { + (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); + return (BadAlloc); + } + pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; + if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, + client, BlueComp) != Success) + { + (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0); + (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); + return (BadAlloc); + } + *pPix = pixR | pixG | pixB; + break; + } + + /* if this is the client's first pixel in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((pmap->numPixelsRed[client] == 1) && + (CLIENT_ID(pmap->mid) != client) && + !(pmap->flags & BeingCreated)) + { + colorResource *pcr; + + pcr = (colorResource *) xalloc(sizeof(colorResource)); + if (!pcr) + { + (void)FreeColors(pmap, client, 1, pPix, (Pixel)0); + return (BadAlloc); + } + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + return (BadAlloc); + } + return (Success); +} + +/* + * FakeAllocColor -- fake an AllocColor request by + * returning a free pixel if availible, otherwise returning + * the closest matching pixel. This is used by the mi + * software sprite code to recolor cursors. A nice side-effect + * is that this routine will never return failure. + */ + +void +FakeAllocColor (pmap, item) + register ColormapPtr pmap; + register xColorItem *item; +{ + Pixel pixR, pixG, pixB; + Pixel temp; + int entries; + xrgb rgb; + int class; + register VisualPtr pVisual; + + pVisual = pmap->pVisual; + rgb.red = item->red; + rgb.green = item->green; + rgb.blue = item->blue; + (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual); + class = pmap->class; + entries = pVisual->ColormapEntries; + + switch (class) { + case GrayScale: + case PseudoColor: + item->pixel = 0; + if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP, + -1, AllComp) == Success) { + item->pixel = temp; + break; + } + /* fall through ... */ + case StaticColor: + case StaticGray: + item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); + break; + + case DirectColor: + /* Look up each component in its own map, then OR them together */ + pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed; + pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen; + pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, + -1, RedComp) != Success) + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP) + << pVisual->offsetRed; + if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, + GREENMAP, -1, GreenComp) != Success) + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, + GREENMAP) << pVisual->offsetGreen; + if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, + -1, BlueComp) != Success) + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP) + << pVisual->offsetBlue; + item->pixel = pixR | pixG | pixB; + break; + + case TrueColor: + /* Look up each component in its own map, then OR them together */ + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); + item->pixel = (pixR << pVisual->offsetRed) | + (pixG << pVisual->offsetGreen) | + (pixB << pVisual->offsetBlue); + break; + } +} + +/* free a pixel value obtained from FakeAllocColor */ +void +FakeFreeColor(pmap, pixel) + register ColormapPtr pmap; + Pixel pixel; +{ + register VisualPtr pVisual; + Pixel pixR, pixG, pixB; + + switch (pmap->class) { + case GrayScale: + case PseudoColor: + if (pmap->red[pixel].refcnt == AllocTemporary) + pmap->red[pixel].refcnt = 0; + break; + case DirectColor: + pVisual = pmap->pVisual; + pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed; + pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; + pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (pmap->red[pixR].refcnt == AllocTemporary) + pmap->red[pixR].refcnt = 0; + if (pmap->green[pixG].refcnt == AllocTemporary) + pmap->green[pixG].refcnt = 0; + if (pmap->blue[pixB].refcnt == AllocTemporary) + pmap->blue[pixB].refcnt = 0; + break; + } +} + +typedef unsigned short BigNumUpper; +typedef unsigned long BigNumLower; + +#define BIGNUMLOWERBITS 24 +#define BIGNUMUPPERBITS 16 +#define BIGNUMLOWER (1 << BIGNUMLOWERBITS) +#define BIGNUMUPPER (1 << BIGNUMUPPERBITS) +#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS) +#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1)) + +typedef struct _bignum { + BigNumUpper upper; + BigNumLower lower; +} BigNumRec, *BigNumPtr; + +#define BigNumGreater(x,y) ((x)->upper > (y)->upper ||\ + (x)->upper == (y)->upper && (x)->lower > (y)->lower) + +#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \ + ((r)->lower = LOWERPART(u))) + +#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \ + ((r)->lower = BIGNUMLOWER-1)) + +static void +BigNumAdd (x, y, r) + BigNumPtr x, y, r; +{ + BigNumLower lower, carry = 0; + + lower = x->lower + y->lower; + if (lower >= BIGNUMLOWER) { + lower -= BIGNUMLOWER; + carry = 1; + } + r->lower = lower; + r->upper = x->upper + y->upper + carry; +} + +static Pixel +FindBestPixel(pentFirst, size, prgb, channel) + EntryPtr pentFirst; + int size; + xrgb *prgb; + int channel; +{ + EntryPtr pent; + Pixel pixel, final; + long dr, dg, db; + unsigned long sq; + BigNumRec minval, sum, temp; + + final = 0; + MaxBigNum(&minval); + /* look for the minimal difference */ + for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++) + { + dr = dg = db = 0; + switch(channel) + { + case PSEUDOMAP: + dg = (long) pent->co.local.green - prgb->green; + db = (long) pent->co.local.blue - prgb->blue; + case REDMAP: + dr = (long) pent->co.local.red - prgb->red; + break; + case GREENMAP: + dg = (long) pent->co.local.green - prgb->green; + break; + case BLUEMAP: + db = (long) pent->co.local.blue - prgb->blue; + break; + } + sq = dr * dr; + UnsignedToBigNum (sq, &sum); + sq = dg * dg; + UnsignedToBigNum (sq, &temp); + BigNumAdd (&sum, &temp, &sum); + sq = db * db; + UnsignedToBigNum (sq, &temp); + BigNumAdd (&sum, &temp, &sum); + if (BigNumGreater (&minval, &sum)) + { + final = pixel; + minval = sum; + } + } + return(final); +} + +static void +FindColorInRootCmap (pmap, pentFirst, size, prgb, pPixel, channel, comp) + ColormapPtr pmap; + EntryPtr pentFirst; + int size; + xrgb* prgb; + Pixel* pPixel; + int channel; + ColorCompareProcPtr comp; +{ + EntryPtr pent; + Pixel pixel; + int count; + + if ((pixel = *pPixel) >= size) + pixel = 0; + for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++) + { + if (pent->refcnt > 0 && (*comp) (pent, prgb)) + { + switch (channel) + { + case REDMAP: + pixel <<= pmap->pVisual->offsetRed; + break; + case GREENMAP: + pixel <<= pmap->pVisual->offsetGreen; + break; + case BLUEMAP: + pixel <<= pmap->pVisual->offsetBlue; + break; + default: /* PSEUDOMAP */ + break; + } + *pPixel = pixel; + } + } +} + +/* Tries to find a color in pmap that exactly matches the one requested in prgb + * if it can't it allocates one. + * Starts looking at pentFirst + *pPixel, so if you want a specific pixel, + * load *pPixel with that value, otherwise set it to 0 + */ +int +FindColor (pmap, pentFirst, size, prgb, pPixel, channel, client, comp) + ColormapPtr pmap; + EntryPtr pentFirst; + int size; + xrgb *prgb; + Pixel *pPixel; + int channel; + int client; + ColorCompareProcPtr comp; +{ + EntryPtr pent; + Bool foundFree; + Pixel pixel, Free; + int npix, count, *nump; + Pixel **pixp, *ppix; + xColorItem def; + + foundFree = FALSE; + + if((pixel = *pPixel) >= size) + pixel = 0; + /* see if there is a match, and also look for a free entry */ + for (pent = pentFirst + pixel, count = size; --count >= 0; ) + { + if (pent->refcnt > 0) + { + if ((*comp) (pent, prgb)) + { + if (client >= 0) + pent->refcnt++; + *pPixel = pixel; + switch(channel) + { + case REDMAP: + *pPixel <<= pmap->pVisual->offsetRed; + case PSEUDOMAP: + break; + case GREENMAP: + *pPixel <<= pmap->pVisual->offsetGreen; + break; + case BLUEMAP: + *pPixel <<= pmap->pVisual->offsetBlue; + break; + } + goto gotit; + } + } + else if (!foundFree && pent->refcnt == 0) + { + Free = pixel; + foundFree = TRUE; + /* If we're initializing the colormap, then we are looking for + * the first free cell we can find, not to minimize the number + * of entries we use. So don't look any further. */ + if(pmap->flags & BeingCreated) + break; + } + pixel++; + if(pixel >= size) + { + pent = pentFirst; + pixel = 0; + } + else + pent++; + } + + /* If we got here, we didn't find a match. If we also didn't find + * a free entry, we're out of luck. Otherwise, we'll usurp a free + * entry and fill it in */ + if (!foundFree) + return (BadAlloc); + pent = pentFirst + Free; + pent->fShared = FALSE; + pent->refcnt = (client >= 0) ? 1 : AllocTemporary; + + switch (channel) + { + case PSEUDOMAP: + pent->co.local.red = prgb->red; + pent->co.local.green = prgb->green; + pent->co.local.blue = prgb->blue; + def.red = prgb->red; + def.green = prgb->green; + def.blue = prgb->blue; + def.flags = (DoRed|DoGreen|DoBlue); + if (client >= 0) + pmap->freeRed--; + def.pixel = Free; + break; + + case REDMAP: + pent->co.local.red = prgb->red; + def.red = prgb->red; + def.green = pmap->green[0].co.local.green; + def.blue = pmap->blue[0].co.local.blue; + def.flags = DoRed; + if (client >= 0) + pmap->freeRed--; + def.pixel = Free << pmap->pVisual->offsetRed; + break; + + case GREENMAP: + pent->co.local.green = prgb->green; + def.red = pmap->red[0].co.local.red; + def.green = prgb->green; + def.blue = pmap->blue[0].co.local.blue; + def.flags = DoGreen; + if (client >= 0) + pmap->freeGreen--; + def.pixel = Free << pmap->pVisual->offsetGreen; + break; + + case BLUEMAP: + pent->co.local.blue = prgb->blue; + def.red = pmap->red[0].co.local.red; + def.green = pmap->green[0].co.local.green; + def.blue = prgb->blue; + def.flags = DoBlue; + if (client >= 0) + pmap->freeBlue--; + def.pixel = Free << pmap->pVisual->offsetBlue; + break; + } + (*pmap->pScreen->StoreColors) (pmap, 1, &def); + pixel = Free; + *pPixel = def.pixel; + +gotit: + if (pmap->flags & BeingCreated || client == -1) + return(Success); + /* Now remember the pixel, for freeing later */ + switch (channel) + { + case PSEUDOMAP: + case REDMAP: + nump = pmap->numPixelsRed; + pixp = pmap->clientPixelsRed; + break; + + case GREENMAP: + nump = pmap->numPixelsGreen; + pixp = pmap->clientPixelsGreen; + break; + + case BLUEMAP: + nump = pmap->numPixelsBlue; + pixp = pmap->clientPixelsBlue; + break; + } + npix = nump[client]; + ppix = (Pixel *) xrealloc (pixp[client], (npix + 1) * sizeof(Pixel)); + if (!ppix) + { + pent->refcnt--; + if (!pent->fShared) + switch (channel) + { + case PSEUDOMAP: + case REDMAP: + pmap->freeRed++; + break; + case GREENMAP: + pmap->freeGreen++; + break; + case BLUEMAP: + pmap->freeBlue++; + break; + } + return(BadAlloc); + } + ppix[npix] = pixel; + pixp[client] = ppix; + nump[client]++; + + return(Success); +} + +/* Comparison functions -- passed to FindColor to determine if an + * entry is already the color we're looking for or not */ +static int +AllComp (pent, prgb) + EntryPtr pent; + xrgb *prgb; +{ + if((pent->co.local.red == prgb->red) && + (pent->co.local.green == prgb->green) && + (pent->co.local.blue == prgb->blue) ) + return (1); + return (0); +} + +static int +RedComp (pent, prgb) + EntryPtr pent; + xrgb *prgb; +{ + if (pent->co.local.red == prgb->red) + return (1); + return (0); +} + +static int +GreenComp (pent, prgb) + EntryPtr pent; + xrgb *prgb; +{ + if (pent->co.local.green == prgb->green) + return (1); + return (0); +} + +static int +BlueComp (pent, prgb) + EntryPtr pent; + xrgb *prgb; +{ + if (pent->co.local.blue == prgb->blue) + return (1); + return (0); +} + + +/* Read the color value of a cell */ + +int +QueryColors (pmap, count, ppixIn, prgbList) + ColormapPtr pmap; + int count; + Pixel *ppixIn; + xrgb *prgbList; +{ + Pixel *ppix, pixel; + xrgb *prgb; + VisualPtr pVisual; + EntryPtr pent; + Pixel i; + int errVal = Success; + + pVisual = pmap->pVisual; + if ((pmap->class | DynamicClass) == DirectColor) + { + int numred, numgreen, numblue; + Pixel rgbbad; + + numred = NUMRED(pVisual); + numgreen = NUMGREEN(pVisual); + numblue = NUMBLUE(pVisual); + rgbbad = ~RGBMASK(pVisual); + for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) + { + pixel = *ppix; + if (pixel & rgbbad) { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + i = (pixel & pVisual->redMask) >> pVisual->offsetRed; + if (i >= numred) + { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + prgb->red = pmap->red[i].co.local.red; + i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; + if (i >= numgreen) + { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + prgb->green = pmap->green[i].co.local.green; + i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (i >= numblue) + { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + prgb->blue = pmap->blue[i].co.local.blue; + } + } + else + { + for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) + { + pixel = *ppix; + if (pixel >= pVisual->ColormapEntries) + { + clientErrorValue = pixel; + errVal = BadValue; + } + else + { + pent = (EntryPtr)&pmap->red[pixel]; + if (pent->fShared) + { + prgb->red = pent->co.shco.red->color; + prgb->green = pent->co.shco.green->color; + prgb->blue = pent->co.shco.blue->color; + } + else + { + prgb->red = pent->co.local.red; + prgb->green = pent->co.local.green; + prgb->blue = pent->co.local.blue; + } + } + } + } + return (errVal); +} + +static void +FreePixels(pmap, client) + register ColormapPtr pmap; + register int client; +{ + register Pixel *ppix, *ppixStart; + register int n; + int class; +#ifdef LBX + Bool grabbed; + Bool zeroRefCount; + Bool anyRefCountReachedZero = 0; +#endif + + class = pmap->class; + ppixStart = pmap->clientPixelsRed[client]; + if (class & DynamicClass) + { + n = pmap->numPixelsRed[client]; +#ifdef LBX + grabbed = LbxCheckCmapGrabbed (pmap); + if (grabbed) + { + /* + * If the colormap is grabbed by a proxy, the server must + * notify the proxy of all cells that are freed (the refcount + * has reached zero on these cells). + */ + + LbxBeginFreeCellsEvent (pmap); + LbxSortPixelList (ppixStart, n); + } +#endif + for (ppix = ppixStart; --n >= 0; ) + { + FreeCell(pmap, *ppix, REDMAP); +#ifdef LBX + /* + * Only PSEUDO colormaps are grabbed by LBX proxies. + * Check if the ref count reached zero on this pixel. + */ + + zeroRefCount = pmap->red[*ppix].refcnt == 0; + if (zeroRefCount) + anyRefCountReachedZero = 1; + + if (grabbed && zeroRefCount) + LbxAddFreeCellToEvent (pmap, *ppix); +#endif + ppix++; + } +#ifdef LBX + if (grabbed) + LbxEndFreeCellsEvent (pmap); + else if (anyRefCountReachedZero) + { + /* + * We only send LbxFreeCell events to a proxy that has the colormap + * grabbed. If the colormap is not grabbed, the proxy that last + * had the colormap grabbed will not be able to do a smart grab + * in the future. A smart grab can only occur if the proxy is kept + * up to date on every alloc/free change in the colormap. + */ + + LbxDisableSmartGrab (pmap); + } +#endif + } + + xfree(ppixStart); + pmap->clientPixelsRed[client] = (Pixel *) NULL; + pmap->numPixelsRed[client] = 0; + if ((class | DynamicClass) == DirectColor) + { + ppixStart = pmap->clientPixelsGreen[client]; + if (class & DynamicClass) + for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;) + FreeCell(pmap, *ppix++, GREENMAP); + xfree(ppixStart); + pmap->clientPixelsGreen[client] = (Pixel *) NULL; + pmap->numPixelsGreen[client] = 0; + + ppixStart = pmap->clientPixelsBlue[client]; + if (class & DynamicClass) + for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; ) + FreeCell(pmap, *ppix++, BLUEMAP); + xfree(ppixStart); + pmap->clientPixelsBlue[client] = (Pixel *) NULL; + pmap->numPixelsBlue[client] = 0; + } +} + +/* Free all of a client's colors and cells */ +/*ARGSUSED*/ +int +FreeClientPixels (value, fakeid) + pointer value; /* must conform to DeleteType */ + XID fakeid; +{ + ColormapPtr pmap; + colorResource *pcr = (colorResource *)value; + + pmap = (ColormapPtr) LookupIDByType(pcr->mid, RT_COLORMAP); + if (pmap) + FreePixels(pmap, pcr->client); + xfree(pcr); + return Success; +} + +int +AllocColorCells (client, pmap, colors, planes, contig, ppix, masks) + int client; + ColormapPtr pmap; + int colors, planes; + Bool contig; + Pixel *ppix; + Pixel *masks; +{ + Pixel rmask, gmask, bmask, *ppixFirst, r, g, b; + int n, class; + int ok; + int oldcount; + colorResource *pcr = (colorResource *)NULL; + + class = pmap->class; + if (!(class & DynamicClass)) + return (BadAlloc); /* Shouldn't try on this type */ + oldcount = pmap->numPixelsRed[client]; + if (pmap->class == DirectColor) + oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; + if (!oldcount && (CLIENT_ID(pmap->mid) != client)) + { + pcr = (colorResource *) xalloc(sizeof(colorResource)); + if (!pcr) + return (BadAlloc); + } + + if (pmap->class == DirectColor) + { + ok = AllocDirect (client, pmap, colors, planes, planes, planes, + contig, ppix, &rmask, &gmask, &bmask); + if(ok == Success) + { + for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b) + { + while(!(rmask & r)) + r += r; + while(!(gmask & g)) + g += g; + while(!(bmask & b)) + b += b; + *masks++ = r | g | b; + } + } + } + else + { + ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask, + &ppixFirst); + if(ok == Success) + { + for (r = 1, n = planes; --n >= 0; r += r) + { + while(!(rmask & r)) + r += r; + *masks++ = r; + } + } + } + + /* if this is the client's first pixels in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((ok == Success) && pcr) + { + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + ok = BadAlloc; + } else if (pcr) + xfree(pcr); + + return (ok); +} + + +int +AllocColorPlanes (client, pmap, colors, r, g, b, contig, pixels, + prmask, pgmask, pbmask) + int client; + ColormapPtr pmap; + int colors, r, g, b; + Bool contig; + Pixel *pixels; + Pixel *prmask, *pgmask, *pbmask; +{ + int ok; + Pixel mask, *ppixFirst; + register Pixel shift; + register int i; + int class; + int oldcount; + colorResource *pcr = (colorResource *)NULL; + + class = pmap->class; + if (!(class & DynamicClass)) + return (BadAlloc); /* Shouldn't try on this type */ + oldcount = pmap->numPixelsRed[client]; + if (class == DirectColor) + oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; + if (!oldcount && (CLIENT_ID(pmap->mid) != client)) + { + pcr = (colorResource *) xalloc(sizeof(colorResource)); + if (!pcr) + return (BadAlloc); + } + + if (class == DirectColor) + { + ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels, + prmask, pgmask, pbmask); + } + else + { + /* Allocate the proper pixels */ + /* XXX This is sort of bad, because of contig is set, we force all + * r + g + b bits to be contiguous. Should only force contiguity + * per mask + */ + ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels, + &mask, &ppixFirst); + + if(ok == Success) + { + /* now split that mask into three */ + *prmask = *pgmask = *pbmask = 0; + shift = 1; + for (i = r; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *prmask |= shift; + } + for (i = g; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *pgmask |= shift; + } + for (i = b; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *pbmask |= shift; + } + + /* set up the shared color cells */ + if (!AllocShared(pmap, pixels, colors, r, g, b, + *prmask, *pgmask, *pbmask, ppixFirst)) + { + (void)FreeColors(pmap, client, colors, pixels, mask); + ok = BadAlloc; + } + } + } + + /* if this is the client's first pixels in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((ok == Success) && pcr) + { + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + ok = BadAlloc; + } else if (pcr) + xfree(pcr); + + return (ok); +} + +static int +AllocDirect (client, pmap, c, r, g, b, contig, pixels, prmask, pgmask, pbmask) + int client; + ColormapPtr pmap; + int c, r, g, b; + Bool contig; + Pixel *pixels; + Pixel *prmask, *pgmask, *pbmask; +{ + Pixel *ppixRed, *ppixGreen, *ppixBlue; + Pixel *ppix, *pDst, *p; + int npix, npixR, npixG, npixB; + Bool okR, okG, okB; + Pixel *rpix, *gpix, *bpix; + + npixR = c << r; + npixG = c << g; + npixB = c << b; + if ((r >= 32) || (g >= 32) || (b >= 32) || + (npixR > pmap->freeRed) || (npixR < c) || + (npixG > pmap->freeGreen) || (npixG < c) || + (npixB > pmap->freeBlue) || (npixB < c)) + return BadAlloc; + + /* start out with empty pixels */ + for(p = pixels; p < pixels + c; p++) + *p = 0; + + ppixRed = (Pixel *)ALLOCATE_LOCAL(npixR * sizeof(Pixel)); + ppixGreen = (Pixel *)ALLOCATE_LOCAL(npixG * sizeof(Pixel)); + ppixBlue = (Pixel *)ALLOCATE_LOCAL(npixB * sizeof(Pixel)); + if (!ppixRed || !ppixGreen || !ppixBlue) + { + if (ppixBlue) DEALLOCATE_LOCAL(ppixBlue); + if (ppixGreen) DEALLOCATE_LOCAL(ppixGreen); + if (ppixRed) DEALLOCATE_LOCAL(ppixRed); + return(BadAlloc); + } + + okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask); + okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask); + okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask); + + if (okR && okG && okB) + { + rpix = (Pixel *) xrealloc(pmap->clientPixelsRed[client], + (pmap->numPixelsRed[client] + (c << r)) * + sizeof(Pixel)); + if (rpix) + pmap->clientPixelsRed[client] = rpix; + gpix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client], + (pmap->numPixelsGreen[client] + (c << g)) * + sizeof(Pixel)); + if (gpix) + pmap->clientPixelsGreen[client] = gpix; + bpix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client], + (pmap->numPixelsBlue[client] + (c << b)) * + sizeof(Pixel)); + if (bpix) + pmap->clientPixelsBlue[client] = bpix; + } + + if (!okR || !okG || !okB || !rpix || !gpix || !bpix) + { + if (okR) + for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++) + pmap->red[*ppix].refcnt = 0; + if (okG) + for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++) + pmap->green[*ppix].refcnt = 0; + if (okB) + for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++) + pmap->blue[*ppix].refcnt = 0; + DEALLOCATE_LOCAL(ppixBlue); + DEALLOCATE_LOCAL(ppixGreen); + DEALLOCATE_LOCAL(ppixRed); + return(BadAlloc); + } + + *prmask <<= pmap->pVisual->offsetRed; + *pgmask <<= pmap->pVisual->offsetGreen; + *pbmask <<= pmap->pVisual->offsetBlue; + + ppix = rpix + pmap->numPixelsRed[client]; + for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++) + { + *ppix++ = *p; + if(p < ppixRed + c) + *pDst++ |= *p << pmap->pVisual->offsetRed; + } + pmap->numPixelsRed[client] += npixR; + pmap->freeRed -= npixR; + + ppix = gpix + pmap->numPixelsGreen[client]; + for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++) + { + *ppix++ = *p; + if(p < ppixGreen + c) + *pDst++ |= *p << pmap->pVisual->offsetGreen; + } + pmap->numPixelsGreen[client] += npixG; + pmap->freeGreen -= npixG; + + ppix = bpix + pmap->numPixelsBlue[client]; + for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++) + { + *ppix++ = *p; + if(p < ppixBlue + c) + *pDst++ |= *p << pmap->pVisual->offsetBlue; + } + pmap->numPixelsBlue[client] += npixB; + pmap->freeBlue -= npixB; + + DEALLOCATE_LOCAL(ppixBlue); + DEALLOCATE_LOCAL(ppixGreen); + DEALLOCATE_LOCAL(ppixRed); + + return (Success); +} + +static int +AllocPseudo (client, pmap, c, r, contig, pixels, pmask, pppixFirst) + int client; + ColormapPtr pmap; + int c, r; + Bool contig; + Pixel *pixels; + Pixel *pmask; + Pixel **pppixFirst; +{ + Pixel *ppix, *p, *pDst, *ppixTemp; + int npix; + Bool ok; + + npix = c << r; + if ((r >= 32) || (npix > pmap->freeRed) || (npix < c)) + return(BadAlloc); + if(!(ppixTemp = (Pixel *)ALLOCATE_LOCAL(npix * sizeof(Pixel)))) + return(BadAlloc); + ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask); + + if (ok) + { + + /* all the allocated pixels are added to the client pixel list, + * but only the unique ones are returned to the client */ + ppix = (Pixel *)xrealloc(pmap->clientPixelsRed[client], + (pmap->numPixelsRed[client] + npix) * sizeof(Pixel)); + if (!ppix) + { + for (p = ppixTemp; p < ppixTemp + npix; p++) + pmap->red[*p].refcnt = 0; + return (BadAlloc); + } + pmap->clientPixelsRed[client] = ppix; + ppix += pmap->numPixelsRed[client]; + *pppixFirst = ppix; + pDst = pixels; + for (p = ppixTemp; p < ppixTemp + npix; p++) + { + *ppix++ = *p; + if(p < ppixTemp + c) + *pDst++ = *p; + } + pmap->numPixelsRed[client] += npix; + pmap->freeRed -= npix; + } + DEALLOCATE_LOCAL(ppixTemp); + return (ok ? Success : BadAlloc); +} + +/* Allocates count << planes pixels from colormap pmap for client. If + * contig, then the plane mask is made of consecutive bits. Returns + * all count << pixels in the array pixels. The first count of those + * pixels are the unique pixels. *pMask has the mask to Or with the + * unique pixels to get the rest of them. + * + * Returns True iff all pixels could be allocated + * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE + * (see AllocShared for why we care) + */ +static Bool +AllocCP (pmap, pentFirst, count, planes, contig, pixels, pMask) + ColormapPtr pmap; + EntryPtr pentFirst; + int count, planes; + Bool contig; + Pixel *pixels, *pMask; + +{ + EntryPtr ent; + Pixel pixel, base, entries, maxp, save; + int dplanes, found; + Pixel *ppix; + Pixel mask; + Pixel finalmask; + + dplanes = pmap->pVisual->nplanes; + + /* Easy case. Allocate pixels only */ + if (planes == 0) + { + /* allocate writable entries */ + ppix = pixels; + ent = pentFirst; + pixel = 0; + while (--count >= 0) + { + /* Just find count unallocated cells */ + while (ent->refcnt) + { + ent++; + pixel++; + } + ent->refcnt = AllocPrivate; + *ppix++ = pixel; + ent->fShared = FALSE; + } + *pMask = 0; + return (TRUE); + } + else if (planes > dplanes) + { + return (FALSE); + } + + /* General case count pixels * 2 ^ planes cells to be allocated */ + + /* make room for new pixels */ + ent = pentFirst; + + /* first try for contiguous planes, since it's fastest */ + for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1); + --dplanes >= 0; + mask += mask, base += base) + { + ppix = pixels; + found = 0; + pixel = 0; + entries = pmap->pVisual->ColormapEntries - mask; + while (pixel < entries) + { + save = pixel; + maxp = pixel + mask + base; + /* check if all are free */ + while (pixel != maxp && ent[pixel].refcnt == 0) + pixel += base; + if (pixel == maxp) + { + /* this one works */ + *ppix++ = save; + found++; + if (found == count) + { + /* found enough, allocate them all */ + while (--count >= 0) + { + pixel = pixels[count]; + maxp = pixel + mask; + while (1) + { + ent[pixel].refcnt = AllocPrivate; + ent[pixel].fShared = FALSE; + if (pixel == maxp) + break; + pixel += base; + *ppix++ = pixel; + } + } + *pMask = mask; + return (TRUE); + } + } + pixel = save + 1; + if (pixel & mask) + pixel += mask; + } + } + + dplanes = pmap->pVisual->nplanes; + if (contig || planes == 1 || dplanes < 3) + return (FALSE); + + /* this will be very slow for large maps, need a better algorithm */ + + /* + we can generate the smallest and largest numbers that fits in dplanes + bits and contain exactly planes bits set as follows. First, we need to + check that it is possible to generate such a mask at all. + (Non-contiguous masks need one more bit than contiguous masks). Then + the smallest such mask consists of the rightmost planes-1 bits set, then + a zero, then a one in position planes + 1. The formula is + (3 << (planes-1)) -1 + The largest such masks consists of the leftmost planes-1 bits set, then + a zero, then a one bit in position dplanes-planes-1. If dplanes is + smaller than 32 (the number of bits in a word) then the formula is: + (1<>> + + */ + + finalmask = + (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) + + (((Pixel)1)<<(dplanes-planes-1)); + for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++) + { + /* next 3 magic statements count number of ones (HAKMEM #169) */ + pixel = (mask >> 1) & 033333333333; + pixel = mask - pixel - ((pixel >> 1) & 033333333333); + if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes) + continue; + ppix = pixels; + found = 0; + entries = pmap->pVisual->ColormapEntries - mask; + base = lowbit (mask); + for (pixel = 0; pixel < entries; pixel++) + { + if (pixel & mask) + continue; + maxp = 0; + /* check if all are free */ + while (ent[pixel + maxp].refcnt == 0) + { + GetNextBitsOrBreak(maxp, mask, base); + } + if ((maxp < mask) || (ent[pixel + mask].refcnt != 0)) + continue; + /* this one works */ + *ppix++ = pixel; + found++; + if (found < count) + continue; + /* found enough, allocate them all */ + while (--count >= 0) + { + pixel = (pixels)[count]; + maxp = 0; + while (1) + { + ent[pixel + maxp].refcnt = AllocPrivate; + ent[pixel + maxp].fShared = FALSE; + GetNextBitsOrBreak(maxp, mask, base); + *ppix++ = pixel + maxp; + } + } + + *pMask = mask; + return (TRUE); + } + } + return (FALSE); +} + +static Bool +AllocShared (pmap, ppix, c, r, g, b, rmask, gmask, bmask, ppixFirst) + ColormapPtr pmap; + Pixel *ppix; + int c, r, g, b; + Pixel rmask, gmask, bmask; + Pixel *ppixFirst; /* First of the client's new pixels */ +{ + Pixel *pptr, *cptr; + int npix, z, npixClientNew, npixShared; + Pixel basemask, base, bits, common; + SHAREDCOLOR *pshared, **ppshared, **psharedList; + + npixClientNew = c << (r + g + b); + npixShared = (c << r) + (c << g) + (c << b); + psharedList = (SHAREDCOLOR **)ALLOCATE_LOCAL(npixShared * + sizeof(SHAREDCOLOR *)); + if (!psharedList) + return FALSE; + ppshared = psharedList; + for (z = npixShared; --z >= 0; ) + { + if (!(ppshared[z] = (SHAREDCOLOR *)xalloc(sizeof(SHAREDCOLOR)))) + { + for (z++ ; z < npixShared; z++) + xfree(ppshared[z]); + return FALSE; + } + } + for(pptr = ppix, npix = c; --npix >= 0; pptr++) + { + basemask = ~(gmask | bmask); + common = *pptr & basemask; + if (rmask) + { + bits = 0; + base = lowbit (rmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].fShared = TRUE; + pmap->red[*cptr].co.shco.red = pshared; + } + } + GetNextBitsOrBreak(bits, rmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].fShared = TRUE; + pmap->red[*cptr].co.shco.red = pshared; + } + } + } + basemask = ~(rmask | bmask); + common = *pptr & basemask; + if (gmask) + { + bits = 0; + base = lowbit (gmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (r + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].co.shco.green = pshared; + } + } + GetNextBitsOrBreak(bits, gmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].co.shco.green = pshared; + } + } + } + basemask = ~(rmask | gmask); + common = *pptr & basemask; + if (bmask) + { + bits = 0; + base = lowbit (bmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (r + g); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].co.shco.blue = pshared; + } + } + GetNextBitsOrBreak(bits, bmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].co.shco.blue = pshared; + } + } + } + } + DEALLOCATE_LOCAL(psharedList); + return TRUE; +} + + +/* Free colors and/or cells (probably slow for large numbers) */ + +int +FreeColors (pmap, client, count, pixels, mask) + ColormapPtr pmap; + int client, count; + Pixel *pixels; + Pixel mask; +{ + int rval, result, class; + Pixel rmask; + + class = pmap->class; + if (pmap->flags & AllAllocated) + return(BadAccess); + if ((class | DynamicClass) == DirectColor) + { + rmask = mask & RGBMASK(pmap->pVisual); + result = FreeCo(pmap, client, REDMAP, count, pixels, + mask & pmap->pVisual->redMask); + /* If any of the three calls fails, we must report that, if more + * than one fails, it's ok that we report the last one */ + rval = FreeCo(pmap, client, GREENMAP, count, pixels, + mask & pmap->pVisual->greenMask); + if(rval != Success) + result = rval; + rval = FreeCo(pmap, client, BLUEMAP, count, pixels, + mask & pmap->pVisual->blueMask); + if(rval != Success) + result = rval; + } + else + { + rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1); + result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask); + } + if ((mask != rmask) && count) + { + clientErrorValue = *pixels | mask; + result = BadValue; + } + /* XXX should worry about removing any RT_CMAPENTRY resource */ + return (result); +} + +/* Helper for FreeColors -- frees all combinations of *newpixels and mask bits + * which the client has allocated in channel colormap cells of pmap. + * doesn't change newpixels if it doesn't need to */ +static int +FreeCo (pmap, client, color, npixIn, ppixIn, mask) + ColormapPtr pmap; /* which colormap head */ + int client; + int color; /* which sub-map, eg RED, BLUE, PSEUDO */ + int npixIn; /* number of pixels passed in */ + Pixel *ppixIn; /* list of base pixels */ + Pixel mask; /* mask client gave us */ +{ + + Pixel *ppixClient, pixTest; + int npixClient, npixNew, npix; + Pixel bits, base, cmask, rgbbad; + Pixel *pptr, *cptr; + int n, zapped; + int errVal = Success; + int offset, numents; +#ifdef LBX + Bool grabbed; + Bool zeroRefCount; + Bool anyRefCountReachedZero = 0; +#endif + + if (npixIn == 0) + return (errVal); + bits = 0; + zapped = 0; + base = lowbit (mask); + + switch(color) + { + case REDMAP: + cmask = pmap->pVisual->redMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetRed; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsRed[client]; + npixClient = pmap->numPixelsRed[client]; + break; + case GREENMAP: + cmask = pmap->pVisual->greenMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetGreen; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsGreen[client]; + npixClient = pmap->numPixelsGreen[client]; + break; + case BLUEMAP: + cmask = pmap->pVisual->blueMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetBlue; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsBlue[client]; + npixClient = pmap->numPixelsBlue[client]; + break; + case PSEUDOMAP: + cmask = ~((Pixel)0); + rgbbad = 0; + offset = 0; + numents = pmap->pVisual->ColormapEntries; + ppixClient = pmap->clientPixelsRed[client]; + npixClient = pmap->numPixelsRed[client]; + break; + } + +#ifdef LBX + grabbed = LbxCheckCmapGrabbed (pmap); + + if (grabbed) + { + /* + * If the colormap is grabbed by a proxy, the server must + * notify the proxy of all cells that are freed (the refcount + * has reached zero on these cells). + */ + + LbxBeginFreeCellsEvent (pmap); + LbxSortPixelList (ppixIn, npixIn); + } +#endif + + /* zap all pixels which match */ + while (1) + { + /* go through pixel list */ + for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++) + { + pixTest = ((*pptr | bits) & cmask) >> offset; + if ((pixTest >= numents) || (*pptr & rgbbad)) + { + clientErrorValue = *pptr | bits; + errVal = BadValue; + continue; + } + + /* find match in client list */ + for (cptr = ppixClient, npix = npixClient; + --npix >= 0 && *cptr != pixTest; + cptr++) ; + + if (npix >= 0) + { + if (pmap->class & DynamicClass) + { + FreeCell(pmap, pixTest, color); +#ifdef LBX + /* + * Only PSEUDO colormaps are grabbed by LBX proxies. + * Check if the ref count reached zero on this pixel. + */ + + zeroRefCount = pmap->red[pixTest].refcnt == 0; + if (zeroRefCount) + anyRefCountReachedZero = 1; + + if (grabbed && zeroRefCount) + LbxAddFreeCellToEvent (pmap, pixTest); +#endif + } + *cptr = ~((Pixel)0); + zapped++; + } + else + errVal = BadAccess; + } + /* generate next bits value */ + GetNextBitsOrBreak(bits, mask, base); + } + +#ifdef LBX + if (grabbed) + LbxEndFreeCellsEvent (pmap); + else if (anyRefCountReachedZero) + { + /* + * We only send LbxFreeCell events to a proxy that has the colormap + * grabbed. If the colormap is not grabbed, the proxy that last + * had the colormap grabbed will not be able to do a smart grab + * in the future. A smart grab can only occur if the proxy is kept + * up to date on every alloc/free change in the colormap. + */ + + LbxDisableSmartGrab (pmap); + } +#endif + + /* delete freed pixels from client pixel list */ + if (zapped) + { + npixNew = npixClient - zapped; + if (npixNew) + { + /* Since the list can only get smaller, we can do a copy in + * place and then realloc to a smaller size */ + pptr = cptr = ppixClient; + + /* If we have all the new pixels, we don't have to examine the + * rest of the old ones */ + for(npix = 0; npix < npixNew; cptr++) + { + if (*cptr != ~((Pixel)0)) + { + *pptr++ = *cptr; + npix++; + } + } + pptr = (Pixel *)xrealloc(ppixClient, npixNew * sizeof(Pixel)); + if (pptr) + ppixClient = pptr; + npixClient = npixNew; + } + else + { + npixClient = 0; + xfree(ppixClient); + ppixClient = (Pixel *)NULL; + } + switch(color) + { + case PSEUDOMAP: + case REDMAP: + pmap->clientPixelsRed[client] = ppixClient; + pmap->numPixelsRed[client] = npixClient; + break; + case GREENMAP: + pmap->clientPixelsGreen[client] = ppixClient; + pmap->numPixelsGreen[client] = npixClient; + break; + case BLUEMAP: + pmap->clientPixelsBlue[client] = ppixClient; + pmap->numPixelsBlue[client] = npixClient; + break; + } + } + return (errVal); +} + + + +/* Redefine color values */ +int +StoreColors (pmap, count, defs) + ColormapPtr pmap; + int count; + xColorItem *defs; +{ + register Pixel pix; + register xColorItem *pdef; + register EntryPtr pent, pentT, pentLast; + register VisualPtr pVisual; + SHAREDCOLOR *pred, *pgreen, *pblue; + int n, ChgRed, ChgGreen, ChgBlue, idef; + int class, errVal = Success; + int ok; + + + class = pmap->class; + if(!(class & DynamicClass) && !(pmap->flags & BeingCreated)) + { + return(BadAccess); + } + pVisual = pmap->pVisual; + + idef = 0; + if((class | DynamicClass) == DirectColor) + { + int numred, numgreen, numblue; + Pixel rgbbad; + + numred = NUMRED(pVisual); + numgreen = NUMGREEN(pVisual); + numblue = NUMBLUE(pVisual); + rgbbad = ~RGBMASK(pVisual); + for (pdef = defs, n = 0; n < count; pdef++, n++) + { + ok = TRUE; + (*pmap->pScreen->ResolveColor) + (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); + + if (pdef->pixel & rgbbad) + { + errVal = BadValue; + clientErrorValue = pdef->pixel; + continue; + } + pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed; + if (pix >= numred) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->red[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoRed) + { + pmap->red[pix].co.local.red = pdef->red; + } + else + { + pdef->red = pmap->red[pix].co.local.red; + } + + pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen; + if (pix >= numgreen) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->green[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoGreen) + { + pmap->green[pix].co.local.green = pdef->green; + } + else + { + pdef->green = pmap->green[pix].co.local.green; + } + + pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (pix >= numblue) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->blue[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoBlue) + { + pmap->blue[pix].co.local.blue = pdef->blue; + } + else + { + pdef->blue = pmap->blue[pix].co.local.blue; + } + /* If this is an o.k. entry, then it gets added to the list + * to be sent to the hardware. If not, skip it. Once we've + * skipped one, we have to copy all the others. + */ + if(ok) + { + if(idef != n) + defs[idef] = defs[n]; + idef++; + } else + clientErrorValue = pdef->pixel; + } + } + else + { + for (pdef = defs, n = 0; n < count; pdef++, n++) + { + + ok = TRUE; + if (pdef->pixel >= pVisual->ColormapEntries) + { + clientErrorValue = pdef->pixel; + errVal = BadValue; + ok = FALSE; + } + else if (pmap->red[pdef->pixel].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + + /* If this is an o.k. entry, then it gets added to the list + * to be sent to the hardware. If not, skip it. Once we've + * skipped one, we have to copy all the others. + */ + if(ok) + { + if(idef != n) + defs[idef] = defs[n]; + idef++; + } + else + continue; + + (*pmap->pScreen->ResolveColor) + (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); + + pent = &pmap->red[pdef->pixel]; + + if(pdef->flags & DoRed) + { + if(pent->fShared) + { + pent->co.shco.red->color = pdef->red; + if (pent->co.shco.red->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.red = pdef->red; + } + else + { + if(pent->fShared) + pdef->red = pent->co.shco.red->color; + else + pdef->red = pent->co.local.red; + } + if(pdef->flags & DoGreen) + { + if(pent->fShared) + { + pent->co.shco.green->color = pdef->green; + if (pent->co.shco.green->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.green = pdef->green; + } + else + { + if(pent->fShared) + pdef->green = pent->co.shco.green->color; + else + pdef->green = pent->co.local.green; + } + if(pdef->flags & DoBlue) + { + if(pent->fShared) + { + pent->co.shco.blue->color = pdef->blue; + if (pent->co.shco.blue->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.blue = pdef->blue; + } + else + { + if(pent->fShared) + pdef->blue = pent->co.shco.blue->color; + else + pdef->blue = pent->co.local.blue; + } + + if(!ok) + { + /* have to run through the colormap and change anybody who + * shares this value */ + pred = pent->co.shco.red; + pgreen = pent->co.shco.green; + pblue = pent->co.shco.blue; + ChgRed = pdef->flags & DoRed; + ChgGreen = pdef->flags & DoGreen; + ChgBlue = pdef->flags & DoBlue; + pentLast = pmap->red + pVisual->ColormapEntries; + + for(pentT = pmap->red; pentT < pentLast; pentT++) + { + if(pentT->fShared && (pentT != pent)) + { + xColorItem defChg; + + /* There are, alas, devices in this world too dumb + * to read their own hardware colormaps. Sick, but + * true. So we're going to be really nice and load + * the xColorItem with the proper value for all the + * fields. We will only set the flags for those + * fields that actually change. Smart devices can + * arrange to change only those fields. Dumb devices + * can rest assured that we have provided for them, + * and can change all three fields */ + + defChg.flags = 0; + if(ChgRed && pentT->co.shco.red == pred) + { + defChg.flags |= DoRed; + } + if(ChgGreen && pentT->co.shco.green == pgreen) + { + defChg.flags |= DoGreen; + } + if(ChgBlue && pentT->co.shco.blue == pblue) + { + defChg.flags |= DoBlue; + } + if(defChg.flags != 0) + { + defChg.pixel = pentT - pmap->red; + defChg.red = pentT->co.shco.red->color; + defChg.green = pentT->co.shco.green->color; + defChg.blue = pentT->co.shco.blue->color; + (*pmap->pScreen->StoreColors) (pmap, 1, &defChg); + } + } + } + + } + } + } + /* Note that we use idef, the count of acceptable entries, and not + * count, the count of proposed entries */ + if (idef != 0) + ( *pmap->pScreen->StoreColors) (pmap, idef, defs); + return (errVal); +} + +int +IsMapInstalled(map, pWin) + Colormap map; + WindowPtr pWin; +{ + Colormap *pmaps; + int imap, nummaps, found; + + pmaps = (Colormap *) ALLOCATE_LOCAL( + pWin->drawable.pScreen->maxInstalledCmaps * sizeof(Colormap)); + if(!pmaps) + return(FALSE); + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, pmaps); + found = FALSE; + for(imap = 0; imap < nummaps; imap++) + { + if(pmaps[imap] == map) + { + found = TRUE; + break; + } + } + DEALLOCATE_LOCAL(pmaps); + return (found); +} diff --git a/dix/cursor.c b/dix/cursor.c new file mode 100644 index 000000000..fe0ceabe0 --- /dev/null +++ b/dix/cursor.c @@ -0,0 +1,399 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + + +/* $Xorg: cursor.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "scrnintstr.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "dixfontstr.h" +#include "opaque.h" + +typedef struct _GlyphShare { + FontPtr font; + unsigned short sourceChar; + unsigned short maskChar; + CursorBitsPtr bits; + struct _GlyphShare *next; +} GlyphShare, *GlyphSharePtr; + +static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL; + +static void +FreeCursorBits(bits) + CursorBitsPtr bits; +{ + if (--bits->refcnt > 0) + return; + xfree(bits->source); + xfree(bits->mask); + if (bits->refcnt == 0) + { + register GlyphSharePtr *prev, this; + + for (prev = &sharedGlyphs; + (this = *prev) && (this->bits != bits); + prev = &this->next) + ; + if (this) + { + *prev = this->next; + CloseFont(this->font, (Font)0); + xfree(this); + } + xfree(bits); + } +} + +/* + * To be called indirectly by DeleteResource; must use exactly two args + */ +/*ARGSUSED*/ +int +FreeCursor(value, cid) + pointer value; /* must conform to DeleteType */ + XID cid; +{ + int nscr; + CursorPtr pCurs = (CursorPtr)value; + + ScreenPtr pscr; + + if ( --pCurs->refcnt > 0) + return(Success); + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + (void)( *pscr->UnrealizeCursor)( pscr, pCurs); + } + FreeCursorBits(pCurs->bits); + xfree( pCurs); + return(Success); +} + +/* + * does nothing about the resource table, just creates the data structure. + * does not copy the src and mask bits + */ +CursorPtr +AllocCursor(psrcbits, pmaskbits, cm, + foreRed, foreGreen, foreBlue, backRed, backGreen, backBlue) + unsigned char * psrcbits; /* server-defined padding */ + unsigned char * pmaskbits; /* server-defined padding */ + CursorMetricPtr cm; + unsigned foreRed, foreGreen, foreBlue; + unsigned backRed, backGreen, backBlue; +{ + CursorBitsPtr bits; + CursorPtr pCurs; + int nscr; + ScreenPtr pscr; + + pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + if (!pCurs) + { + xfree(psrcbits); + xfree(pmaskbits); + return (CursorPtr)NULL; + } + bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec)); + bits->source = psrcbits; + bits->mask = pmaskbits; + bits->width = cm->width; + bits->height = cm->height; + bits->xhot = cm->xhot; + bits->yhot = cm->yhot; + bits->refcnt = -1; + + pCurs->bits = bits; + pCurs->refcnt = 1; + + pCurs->foreRed = foreRed; + pCurs->foreGreen = foreGreen; + pCurs->foreBlue = foreBlue; + + pCurs->backRed = backRed; + pCurs->backGreen = backGreen; + pCurs->backBlue = backBlue; + + /* + * realize the cursor for every screen + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + if (!( *pscr->RealizeCursor)( pscr, pCurs)) + { + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + ( *pscr->UnrealizeCursor)( pscr, pCurs); + } + FreeCursorBits(bits); + xfree(pCurs); + return (CursorPtr)NULL; + } + } + return pCurs; +} + +int +AllocGlyphCursor(source, sourceChar, mask, maskChar, + foreRed, foreGreen, foreBlue, backRed, backGreen, backBlue, + ppCurs, client) + Font source, mask; + unsigned int sourceChar, maskChar; + unsigned foreRed, foreGreen, foreBlue; + unsigned backRed, backGreen, backBlue; + CursorPtr *ppCurs; + ClientPtr client; +{ + FontPtr sourcefont, maskfont; + unsigned char *srcbits; + unsigned char *mskbits; + CursorMetricRec cm; + int res; + CursorBitsPtr bits; + CursorPtr pCurs; + int nscr; + ScreenPtr pscr; + GlyphSharePtr pShare; + + sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT, + SecurityReadAccess); + maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT, + SecurityReadAccess); + + if (!sourcefont) + { + client->errorValue = source; + return(BadFont); + } + if (!maskfont && (mask != None)) + { + client->errorValue = mask; + return(BadFont); + } + if (sourcefont != maskfont) + pShare = (GlyphSharePtr)NULL; + else + { + for (pShare = sharedGlyphs; + pShare && + ((pShare->font != sourcefont) || + (pShare->sourceChar != sourceChar) || + (pShare->maskChar != maskChar)); + pShare = pShare->next) + ; + } + if (pShare) + { + pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + if (!pCurs) + return BadAlloc; + bits = pShare->bits; + bits->refcnt++; + } + else + { + if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) + { + client->errorValue = sourceChar; + return BadValue; + } + if (!maskfont) + { + register long n; + register unsigned char *bits; + + n = BitmapBytePad(cm.width)*(long)cm.height; + bits = mskbits = (unsigned char *)xalloc(n); + if (!bits) + return BadAlloc; + while (--n >= 0) + *bits++ = ~0; + } + else + { + if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm)) + { + client->errorValue = maskChar; + return BadValue; + } + if (res = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)) + return res; + } + if (res = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)) + { + xfree(mskbits); + return res; + } + if (sourcefont != maskfont) + { + pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + if (pCurs) + bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec)); + else + bits = (CursorBitsPtr)NULL; + } + else + { + pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + if (pCurs) + bits = (CursorBitsPtr)xalloc(sizeof(CursorBits)); + else + bits = (CursorBitsPtr)NULL; + } + if (!bits) + { + xfree(pCurs); + xfree(mskbits); + xfree(srcbits); + return BadAlloc; + } + bits->source = srcbits; + bits->mask = mskbits; + bits->width = cm.width; + bits->height = cm.height; + bits->xhot = cm.xhot; + bits->yhot = cm.yhot; + if (sourcefont != maskfont) + bits->refcnt = -1; + else + { + bits->refcnt = 1; + pShare = (GlyphSharePtr)xalloc(sizeof(GlyphShare)); + if (!pShare) + { + FreeCursorBits(bits); + return BadAlloc; + } + pShare->font = sourcefont; + sourcefont->refcnt++; + pShare->sourceChar = sourceChar; + pShare->maskChar = maskChar; + pShare->bits = bits; + pShare->next = sharedGlyphs; + sharedGlyphs = pShare; + } + } + pCurs->bits = bits; + pCurs->refcnt = 1; + + pCurs->foreRed = foreRed; + pCurs->foreGreen = foreGreen; + pCurs->foreBlue = foreBlue; + + pCurs->backRed = backRed; + pCurs->backGreen = backGreen; + pCurs->backBlue = backBlue; + + /* + * realize the cursor for every screen + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + if (!( *pscr->RealizeCursor)( pscr, pCurs)) + { + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + ( *pscr->UnrealizeCursor)( pscr, pCurs); + } + FreeCursorBits(pCurs->bits); + xfree(pCurs); + return BadAlloc; + } + } + *ppCurs = pCurs; + return Success; +} + +/*********************************************************** + * CreateRootCursor + * + * look up the name of a font + * open the font + * add the font to the resource table + * make a cursor from the glyphs + * add the cursor to the resource table + *************************************************************/ + +CursorPtr +CreateRootCursor(pfilename, glyph) + char * pfilename; + unsigned int glyph; +{ + CursorPtr curs; + FontPtr cursorfont; + int err; + XID fontID; + + fontID = FakeClientID(0); + err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync, + (unsigned)strlen( pfilename), pfilename); + if (err != Success) + return NullCursor; + + cursorfont = (FontPtr)LookupIDByType(fontID, RT_FONT); + if (!cursorfont) + return NullCursor; + if (AllocGlyphCursor(fontID, glyph, fontID, glyph + 1, + 0, 0, 0, ~0, ~0, ~0, &curs, serverClient) != Success) + return NullCursor; + + if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs)) + return NullCursor; + + return curs; +} diff --git a/dix/devices.c b/dix/devices.c new file mode 100644 index 000000000..3a9d56522 --- /dev/null +++ b/dix/devices.c @@ -0,0 +1,1687 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + + +/* $Xorg: devices.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */ + +#include "X.h" +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "site.h" +#define XKB_IN_SERVER +#ifdef XKB +#include "XKBsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +extern void CopySwap32Write(), SwapTimeCoordWrite(); +extern void ActivatePointerGrab(), DeactivatePointerGrab(); +extern void ActivateKeyboardGrab(), DeactivateKeyboardGrab(); +extern Mask EventMaskForClient(); +extern void EnqueueEvent(); + +DevicePtr +AddInputDevice(deviceProc, autoStart) + DeviceProc deviceProc; + Bool autoStart; +{ + register DeviceIntPtr dev; + + if (inputInfo.numDevices >= MAX_DEVICES) + return (DevicePtr)NULL; + dev = (DeviceIntPtr) xalloc(sizeof(DeviceIntRec)); + if (!dev) + return (DevicePtr)NULL; + dev->name = (char *)NULL; + dev->type = 0; + dev->id = inputInfo.numDevices; + inputInfo.numDevices++; + dev->public.on = FALSE; + dev->public.processInputProc = (ProcessInputProc)NoopDDA; + dev->public.realInputProc = (ProcessInputProc)NoopDDA; + dev->public.enqueueInputProc = EnqueueEvent; + dev->deviceProc = deviceProc; + dev->startup = autoStart; + dev->sync.frozen = FALSE; + dev->sync.other = NullGrab; + dev->sync.state = NOT_GRABBED; + dev->sync.event = (xEvent *) NULL; + dev->sync.evcount = 0; + dev->grab = NullGrab; + dev->grabTime = currentTime; + dev->fromPassiveGrab = FALSE; + dev->key = (KeyClassPtr)NULL; + dev->valuator = (ValuatorClassPtr)NULL; + dev->button = (ButtonClassPtr)NULL; + dev->focus = (FocusClassPtr)NULL; + dev->proximity = (ProximityClassPtr)NULL; + dev->kbdfeed = (KbdFeedbackPtr)NULL; + dev->ptrfeed = (PtrFeedbackPtr)NULL; + dev->intfeed = (IntegerFeedbackPtr)NULL; + dev->stringfeed = (StringFeedbackPtr)NULL; + dev->bell = (BellFeedbackPtr)NULL; + dev->leds = (LedFeedbackPtr)NULL; + dev->next = inputInfo.off_devices; +#ifdef XKB + dev->xkb_interest= NULL; +#endif + inputInfo.off_devices = dev; + return &dev->public; +} + +Bool +EnableDevice(dev) + register DeviceIntPtr dev; +{ + register DeviceIntPtr *prev; + + for (prev = &inputInfo.off_devices; + *prev && (*prev != dev); + prev = &(*prev)->next) + ; + if ((*prev != dev) || !dev->inited || + ((*dev->deviceProc)(dev, DEVICE_ON) != Success)) + return FALSE; + *prev = dev->next; + dev->next = inputInfo.devices; + inputInfo.devices = dev; + return TRUE; +} + +Bool +DisableDevice(dev) + register DeviceIntPtr dev; +{ + register DeviceIntPtr *prev; + + for (prev = &inputInfo.devices; + *prev && (*prev != dev); + prev = &(*prev)->next) + ; + if (*prev != dev) + return FALSE; + (void)(*dev->deviceProc)(dev, DEVICE_OFF); + *prev = dev->next; + dev->next = inputInfo.off_devices; + inputInfo.off_devices = dev; + return TRUE; +} + +int +InitAndStartDevices() +{ + register DeviceIntPtr dev, next; + + for (dev = inputInfo.off_devices; dev; dev = dev->next) + dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success); + for (dev = inputInfo.off_devices; dev; dev = next) + { + next = dev->next; + if (dev->inited && dev->startup) + (void)EnableDevice(dev); + } + for (dev = inputInfo.devices; + dev && (dev != inputInfo.keyboard); + dev = dev->next) + ; + if (!dev || (dev != inputInfo.keyboard)) + return BadImplementation; + for (dev = inputInfo.devices; + dev && (dev != inputInfo.pointer); + dev = dev->next) + ; + if (!dev || (dev != inputInfo.pointer)) + return BadImplementation; + return Success; +} + +static void +CloseDevice(dev) + register DeviceIntPtr dev; +{ + KbdFeedbackPtr k, knext; + PtrFeedbackPtr p, pnext; + IntegerFeedbackPtr i, inext; + StringFeedbackPtr s, snext; + BellFeedbackPtr b, bnext; + LedFeedbackPtr l, lnext; + + if (dev->inited) + (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); + xfree(dev->name); + if (dev->key) + { +#ifdef XKB + if (dev->key->xkbInfo) + XkbFreeInfo(dev->key->xkbInfo); +#endif + xfree(dev->key->curKeySyms.map); + xfree(dev->key->modifierKeyMap); + xfree(dev->key); + } + xfree(dev->valuator); +#ifdef XKB + if ((dev->button)&&(dev->button->xkb_acts)) + xfree(dev->button->xkb_acts); +#endif + xfree(dev->button); + if (dev->focus) + { + xfree(dev->focus->trace); + xfree(dev->focus); + } + xfree(dev->proximity); + for (k=dev->kbdfeed; k; k=knext) + { + knext = k->next; +#ifdef XKB + if (k->xkb_sli) + XkbFreeSrvLedInfo(k->xkb_sli); +#endif + xfree(k); + } + for (p=dev->ptrfeed; p; p=pnext) + { + pnext = p->next; + xfree(p); + } + for (i=dev->intfeed; i; i=inext) + { + inext = i->next; + xfree(i); + } + for (s=dev->stringfeed; s; s=snext) + { + snext = s->next; + xfree(s->ctrl.symbols_supported); + xfree(s->ctrl.symbols_displayed); + xfree(s); + } + for (b=dev->bell; b; b=bnext) + { + bnext = b->next; + xfree(b); + } + for (l=dev->leds; l; l=lnext) + { + lnext = l->next; +#ifdef XKB + if (l->xkb_sli) + XkbFreeSrvLedInfo(l->xkb_sli); +#endif + xfree(l); + } +#ifdef XKB + while (dev->xkb_interest) { + XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); + } +#endif + xfree(dev->sync.event); + xfree(dev); +} + +void +CloseDownDevices() +{ + register DeviceIntPtr dev, next; + + for (dev = inputInfo.devices; dev; dev = next) + { + next = dev->next; + CloseDevice(dev); + } + for (dev = inputInfo.off_devices; dev; dev = next) + { + next = dev->next; + CloseDevice(dev); + } +} + +void +RemoveDevice(dev) + register DeviceIntPtr dev; +{ + register DeviceIntPtr prev,tmp,next; + + prev= NULL; + for (tmp= inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { + next = tmp->next; + if (tmp==dev) { + CloseDevice(tmp); + if (prev==NULL) + inputInfo.devices = next; + else + prev->next = next; + inputInfo.numDevices--; + return; + } + } + + prev= NULL; + for (tmp= inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) { + next = tmp->next; + if (tmp==dev) { + CloseDevice(tmp); + if (prev==NULL) + inputInfo.off_devices = next; + else + prev->next = next; + inputInfo.numDevices--; + return; + } + } + ErrorF("Internal Error! Attempt to remove a non-existent device\n"); + return; +} + +int +NumMotionEvents() +{ + return inputInfo.pointer->valuator->numMotionEvents; +} + +void +RegisterPointerDevice(device) + DevicePtr device; +{ + DeviceIntPtr dev = (DeviceIntPtr)device; + inputInfo.pointer = dev; +#ifdef XKB + if (noXkbExtension) { + device->processInputProc = CoreProcessPointerEvent; + device->realInputProc = CoreProcessPointerEvent; + } else { + device->processInputProc = ProcessPointerEvent; + device->realInputProc = ProcessPointerEvent; + } +#else + device->processInputProc = ProcessPointerEvent; + device->realInputProc = ProcessPointerEvent; +#endif + dev->ActivateGrab = ActivatePointerGrab; + dev->DeactivateGrab = DeactivatePointerGrab; + if (!dev->name) + { + char *p = "pointer"; + dev->name = (char *)xalloc(strlen(p) + 1); + strcpy(dev->name, p); + } +} + +void +RegisterKeyboardDevice(device) + DevicePtr device; +{ + DeviceIntPtr dev = (DeviceIntPtr)device; + inputInfo.keyboard = dev; +#ifdef XKB + if (noXkbExtension) { + device->processInputProc = CoreProcessKeyboardEvent; + device->realInputProc = CoreProcessKeyboardEvent; + } else { + device->processInputProc = ProcessKeyboardEvent; + device->realInputProc = ProcessKeyboardEvent; + } +#else + device->processInputProc = ProcessKeyboardEvent; + device->realInputProc = ProcessKeyboardEvent; +#endif + dev->ActivateGrab = ActivateKeyboardGrab; + dev->DeactivateGrab = DeactivateKeyboardGrab; + if (!dev->name) + { + char *k = "keyboard"; + dev->name = (char *)xalloc(strlen(k) + 1); + strcpy(dev->name, k); + } +} + +DevicePtr +LookupKeyboardDevice() +{ + return &inputInfo.keyboard->public; +} + +DevicePtr +LookupPointerDevice() +{ + return &inputInfo.pointer->public; +} + +DevicePtr +LookupDevice(id) + int id; +{ + DeviceIntPtr dev; + + for (dev=inputInfo.devices; dev; dev=dev->next) { + if (dev->id == (CARD8)id) + return (DevicePtr)dev; + } + for (dev=inputInfo.off_devices; dev; dev=dev->next) { + if (dev->id == (CARD8)id) + return (DevicePtr)dev; + } + return NULL; +} + +void +QueryMinMaxKeyCodes(minCode, maxCode) + KeyCode *minCode, *maxCode; +{ + if (inputInfo.keyboard) { + *minCode = inputInfo.keyboard->key->curKeySyms.minKeyCode; + *maxCode = inputInfo.keyboard->key->curKeySyms.maxKeyCode; + } +} + +Bool +SetKeySymsMap(dst, src) + register KeySymsPtr dst, src; +{ + int i, j; + int rowDif = src->minKeyCode - dst->minKeyCode; + /* if keysym map size changes, grow map first */ + + if (src->mapWidth < dst->mapWidth) + { + for (i = src->minKeyCode; i <= src->maxKeyCode; i++) + { +#define SI(r, c) (((r-src->minKeyCode)*src->mapWidth) + (c)) +#define DI(r, c) (((r - dst->minKeyCode)*dst->mapWidth) + (c)) + for (j = 0; j < src->mapWidth; j++) + dst->map[DI(i, j)] = src->map[SI(i, j)]; + for (j = src->mapWidth; j < dst->mapWidth; j++) + dst->map[DI(i, j)] = NoSymbol; +#undef SI +#undef DI + } + return TRUE; + } + else if (src->mapWidth > dst->mapWidth) + { + KeySym *map; + int bytes = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + map = (KeySym *)xalloc(bytes); + if (!map) + return FALSE; + bzero((char *)map, bytes); + if (dst->map) + { + for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) + memmove((char *)&map[i*src->mapWidth], + (char *)&dst->map[i*dst->mapWidth], + dst->mapWidth * sizeof(KeySym)); + xfree(dst->map); + } + dst->mapWidth = src->mapWidth; + dst->map = map; + } + memmove((char *)&dst->map[rowDif * dst->mapWidth], + (char *)src->map, + (int)(src->maxKeyCode - src->minKeyCode + 1) * + dst->mapWidth * sizeof(KeySym)); + return TRUE; +} + +static Bool +InitModMap(keyc) + register KeyClassPtr keyc; +{ + int i, j; + CARD8 keysPerModifier[8]; + CARD8 mask; + + keyc->maxKeysPerModifier = 0; + for (i = 0; i < 8; i++) + keysPerModifier[i] = 0; + for (i = 8; i < MAP_LENGTH; i++) + { + for (j = 0, mask = 1; j < 8; j++, mask <<= 1) + { + if (mask & keyc->modifierMap[i]) + { + if (++keysPerModifier[j] > keyc->maxKeysPerModifier) + keyc->maxKeysPerModifier = keysPerModifier[j]; + } + } + } + keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier); + if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier) + return (FALSE); + bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier); + for (i = 0; i < 8; i++) + keysPerModifier[i] = 0; + for (i = 8; i < MAP_LENGTH; i++) + { + for (j = 0, mask = 1; j < 8; j++, mask <<= 1) + { + if (mask & keyc->modifierMap[i]) + { + keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) + + keysPerModifier[j]] = i; + keysPerModifier[j]++; + } + } + } + return TRUE; +} + +Bool +InitKeyClassDeviceStruct(dev, pKeySyms, pModifiers) + DeviceIntPtr dev; + KeySymsPtr pKeySyms; + CARD8 pModifiers[]; +{ + int i; + register KeyClassPtr keyc; + + keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec)); + if (!keyc) + return FALSE; + keyc->curKeySyms.map = (KeySym *)NULL; + keyc->curKeySyms.mapWidth = 0; + keyc->curKeySyms.minKeyCode = pKeySyms->minKeyCode; + keyc->curKeySyms.maxKeyCode = pKeySyms->maxKeyCode; + keyc->modifierKeyMap = (KeyCode *)NULL; + keyc->state = 0; + keyc->prev_state = 0; + if (pModifiers) + memmove((char *)keyc->modifierMap, (char *)pModifiers, MAP_LENGTH); + else + bzero((char *)keyc->modifierMap, MAP_LENGTH); + bzero((char *)keyc->down, DOWN_LENGTH); + for (i = 0; i < 8; i++) + keyc->modifierKeyCount[i] = 0; + if (!SetKeySymsMap(&keyc->curKeySyms, pKeySyms) || !InitModMap(keyc)) + { + xfree(keyc->curKeySyms.map); + xfree(keyc->modifierKeyMap); + xfree(keyc); + return FALSE; + } + dev->key = keyc; +#ifdef XKB + dev->key->xkbInfo= NULL; + if (!noXkbExtension) XkbInitDevice(dev); +#endif + return TRUE; +} + +Bool +InitButtonClassDeviceStruct(dev, numButtons, map) + register DeviceIntPtr dev; + int numButtons; + CARD8 *map; +{ + register ButtonClassPtr butc; + int i; + + butc = (ButtonClassPtr)xalloc(sizeof(ButtonClassRec)); + if (!butc) + return FALSE; + butc->numButtons = numButtons; + for (i = 1; i <= numButtons; i++) + butc->map[i] = map[i]; + butc->buttonsDown = 0; + butc->state = 0; + butc->motionMask = 0; + bzero((char *)butc->down, DOWN_LENGTH); +#ifdef XKB + butc->xkb_acts= NULL; +#endif + dev->button = butc; + return TRUE; +} + +Bool +InitValuatorClassDeviceStruct(dev, numAxes, motionProc, numMotionEvents, mode) + DeviceIntPtr dev; + ValuatorMotionProcPtr motionProc; + int numAxes; + int numMotionEvents; + int mode; +{ + int i; + register ValuatorClassPtr valc; + + valc = (ValuatorClassPtr)xalloc(sizeof(ValuatorClassRec) + + numAxes * sizeof(AxisInfo) + + numAxes * sizeof(unsigned int)); + if (!valc) + return FALSE; + valc->GetMotionProc = motionProc; + valc->numMotionEvents = numMotionEvents; + valc->motionHintWindow = NullWindow; + valc->numAxes = numAxes; + valc->mode = mode; + valc->axes = (AxisInfoPtr)(valc + 1); + valc->axisVal = (int *)(valc->axes + numAxes); + for (i=0; iaxisVal[i]=0; + dev->valuator = valc; + return TRUE; +} + +Bool +InitFocusClassDeviceStruct(dev) + DeviceIntPtr dev; +{ + register FocusClassPtr focc; + + focc = (FocusClassPtr)xalloc(sizeof(FocusClassRec)); + if (!focc) + return FALSE; + focc->win = PointerRootWin; + focc->revert = None; + focc->time = currentTime; + focc->trace = (WindowPtr *)NULL; + focc->traceSize = 0; + focc->traceGood = 0; + dev->focus = focc; + return TRUE; +} + +Bool +InitKbdFeedbackClassDeviceStruct(dev, bellProc, controlProc) + DeviceIntPtr dev; + BellProcPtr bellProc; + KbdCtrlProcPtr controlProc; +{ + register KbdFeedbackPtr feedc; + + feedc = (KbdFeedbackPtr)xalloc(sizeof(KbdFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->BellProc = bellProc; + feedc->CtrlProc = controlProc; +#ifdef XKB + defaultKeyboardControl.autoRepeat = TRUE; +#endif + feedc->ctrl = defaultKeyboardControl; + feedc->ctrl.id = 0; + if (feedc->next = dev->kbdfeed) + feedc->ctrl.id = dev->kbdfeed->ctrl.id + 1; + dev->kbdfeed = feedc; +#ifdef XKB + feedc->xkb_sli= NULL; + if (!noXkbExtension) + XkbFinishDeviceInit(dev); +#endif + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + return TRUE; +} + +Bool +InitPtrFeedbackClassDeviceStruct(dev, controlProc) + DeviceIntPtr dev; + PtrCtrlProcPtr controlProc; +{ + register PtrFeedbackPtr feedc; + + feedc = (PtrFeedbackPtr)xalloc(sizeof(PtrFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; +#ifdef sgi + feedc->ctrl.num = 1; + feedc->ctrl.den = 1; + feedc->ctrl.threshold = 1; +#else + feedc->ctrl = defaultPointerControl; +#endif + feedc->ctrl.id = 0; + if ( (feedc->next = dev->ptrfeed) ) + feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1; + dev->ptrfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + + +LedCtrl defaultLedControl = { + DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; + +BellCtrl defaultBellControl = { + DEFAULT_BELL, + DEFAULT_BELL_PITCH, + DEFAULT_BELL_DURATION, + 0}; + +IntegerCtrl defaultIntegerControl = { + DEFAULT_INT_RESOLUTION, + DEFAULT_INT_MIN_VALUE, + DEFAULT_INT_MAX_VALUE, + DEFAULT_INT_DISPLAYED, + 0}; + +Bool +InitStringFeedbackClassDeviceStruct (dev, controlProc, max_symbols, + num_symbols_supported, symbols) + DeviceIntPtr dev; + StringCtrlProcPtr controlProc; + int max_symbols; + int num_symbols_supported; + KeySym *symbols; +{ + int i; + register StringFeedbackPtr feedc; + + feedc = (StringFeedbackPtr)xalloc(sizeof(StringFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl.num_symbols_supported = num_symbols_supported; + feedc->ctrl.num_symbols_displayed = 0; + feedc->ctrl.max_symbols = max_symbols; + feedc->ctrl.symbols_supported = (KeySym *) + xalloc (sizeof (KeySym) * num_symbols_supported); + feedc->ctrl.symbols_displayed = (KeySym *) + xalloc (sizeof (KeySym) * max_symbols); + if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) + { + if (feedc->ctrl.symbols_supported) + xfree(feedc->ctrl.symbols_supported); + if (feedc->ctrl.symbols_displayed) + xfree(feedc->ctrl.symbols_displayed); + xfree(feedc); + return FALSE; + } + for (i=0; ictrl.symbols_supported+i) = *symbols++; + for (i=0; ictrl.symbols_displayed+i) = (KeySym) NULL; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->stringfeed) ) + feedc->ctrl.id = dev->stringfeed->ctrl.id + 1; + dev->stringfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitBellFeedbackClassDeviceStruct (dev, bellProc, controlProc) + DeviceIntPtr dev; + BellProcPtr bellProc; + BellCtrlProcPtr controlProc; +{ + register BellFeedbackPtr feedc; + + feedc = (BellFeedbackPtr)xalloc(sizeof(BellFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->BellProc = bellProc; + feedc->ctrl = defaultBellControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->bell) ) + feedc->ctrl.id = dev->bell->ctrl.id + 1; + dev->bell = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitLedFeedbackClassDeviceStruct (dev, controlProc) + DeviceIntPtr dev; + LedCtrlProcPtr controlProc; +{ + register LedFeedbackPtr feedc; + + feedc = (LedFeedbackPtr)xalloc(sizeof(LedFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultLedControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->leds) ) + feedc->ctrl.id = dev->leds->ctrl.id + 1; +#ifdef XKB + feedc->xkb_sli= NULL; +#endif + dev->leds = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitIntegerFeedbackClassDeviceStruct (dev, controlProc) + DeviceIntPtr dev; + IntegerCtrlProcPtr controlProc; +{ + register IntegerFeedbackPtr feedc; + + feedc = (IntegerFeedbackPtr)xalloc(sizeof(IntegerFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultIntegerControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->intfeed) ) + feedc->ctrl.id = dev->intfeed->ctrl.id + 1; + dev->intfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitPointerDeviceStruct(device, map, numButtons, motionProc, controlProc, + numMotionEvents) + DevicePtr device; + CARD8 *map; + int numButtons; + PtrCtrlProcPtr controlProc; + ValuatorMotionProcPtr motionProc; + int numMotionEvents; +{ + DeviceIntPtr dev = (DeviceIntPtr)device; + + return(InitButtonClassDeviceStruct(dev, numButtons, map) && + InitValuatorClassDeviceStruct(dev, 2, motionProc, + numMotionEvents, 0) && + InitPtrFeedbackClassDeviceStruct(dev, controlProc)); +} + +Bool +InitKeyboardDeviceStruct(device, pKeySyms, pModifiers, bellProc, controlProc) + DevicePtr device; + KeySymsPtr pKeySyms; + CARD8 pModifiers[]; + BellProcPtr bellProc; + KbdCtrlProcPtr controlProc; +{ + DeviceIntPtr dev = (DeviceIntPtr)device; + + return(InitKeyClassDeviceStruct(dev, pKeySyms, pModifiers) && + InitFocusClassDeviceStruct(dev) && + InitKbdFeedbackClassDeviceStruct(dev, bellProc, controlProc)); +} + +void +SendMappingNotify(request, firstKeyCode, count, client) + unsigned int request, count; + unsigned int firstKeyCode; + ClientPtr client; +{ + int i; + xEvent event; + + event.u.u.type = MappingNotify; + event.u.mappingNotify.request = request; + if (request == MappingKeyboard) + { + event.u.mappingNotify.firstKeyCode = firstKeyCode; + event.u.mappingNotify.count = count; + } +#ifdef XKB + if (!noXkbExtension && + ((request == MappingKeyboard) || (request == MappingModifier))) { + XkbApplyMappingChange(inputInfo.keyboard,request,firstKeyCode,count, + client); + } +#endif + + /* 0 is the server client */ + for (i=1; iclientState == ClientStateRunning) + { +#ifdef XKB + if (!noXkbExtension && + (request == MappingKeyboard) && + (clients[i]->xkbClientFlags != 0) && + (clients[i]->mapNotifyMask&XkbKeySymsMask)) + continue; +#endif + event.u.u.sequenceNumber = clients[i]->sequence; + WriteEventsToClient(clients[i], 1, &event); + } + } +} + +/* + * n-squared algorithm. n < 255 and don't want to copy the whole thing and + * sort it to do the checking. How often is it called? Just being lazy? + */ +Bool +BadDeviceMap(buff, length, low, high, errval) + register BYTE *buff; + int length; + unsigned low, high; + XID *errval; +{ + register int i, j; + + for (i = 0; i < length; i++) + if (buff[i]) /* only check non-zero elements */ + { + if ((low > buff[i]) || (high < buff[i])) + { + *errval = buff[i]; + return TRUE; + } + for (j = i + 1; j < length; j++) + if (buff[i] == buff[j]) + { + *errval = buff[i]; + return TRUE; + } + } + return FALSE; +} + +Bool +AllModifierKeysAreUp(dev, map1, per1, map2, per2) + register DeviceIntPtr dev; + register CARD8 *map1, *map2; + int per1, per2; +{ + register int i, j, k; + register CARD8 *down = dev->key->down; + + for (i = 8; --i >= 0; map2 += per2) + { + for (j = per1; --j >= 0; map1++) + { + if (*map1 && BitIsOn(down, *map1)) + { + for (k = per2; (--k >= 0) && (*map1 != map2[k]);) + ; + if (k < 0) + return FALSE; + } + } + } + return TRUE; +} + +int +ProcSetModifierMapping(client) + ClientPtr client; +{ + xSetModifierMappingReply rep; + REQUEST(xSetModifierMappingReq); + KeyCode *inputMap; + int inputMapLen; + register int i; + DeviceIntPtr keybd = inputInfo.keyboard; + register KeyClassPtr keyc = keybd->key; + + REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); + + if (client->req_len != ((stuff->numKeyPerModifier<<1) + + (sizeof (xSetModifierMappingReq)>>2))) + return BadLength; + + inputMapLen = 8*stuff->numKeyPerModifier; + inputMap = (KeyCode *)&stuff[1]; + + /* + * Now enforce the restriction that "all of the non-zero keycodes must be + * in the range specified by min-keycode and max-keycode in the + * connection setup (else a Value error)" + */ + i = inputMapLen; + while (i--) + { + if (inputMap[i] + && (inputMap[i] < keyc->curKeySyms.minKeyCode + || inputMap[i] > keyc->curKeySyms.maxKeyCode)) + { + client->errorValue = inputMap[i]; + return BadValue; + } + } + +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, keybd, TRUE)) + return BadAccess; +#endif + +#ifdef LBX + LbxFlushModifierMapTag(); +#endif + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.success = MappingSuccess; + + /* + * Now enforce the restriction that none of the old or new + * modifier keys may be down while we change the mapping, and + * that the DDX layer likes the choice. + */ + if (!AllModifierKeysAreUp(keybd, keyc->modifierKeyMap, + (int)keyc->maxKeysPerModifier, + inputMap, (int)stuff->numKeyPerModifier) + || + !AllModifierKeysAreUp(keybd, inputMap, (int)stuff->numKeyPerModifier, + keyc->modifierKeyMap, + (int)keyc->maxKeysPerModifier)) + { + rep.success = MappingBusy; + } + else + { + for (i = 0; i < inputMapLen; i++) + { + if (inputMap[i] && !LegalModifier(inputMap[i], (DevicePtr)keybd)) + { + rep.success = MappingFailed; + break; + } + } + } + + if (rep.success == MappingSuccess) + { + KeyCode *map; + /* + * Now build the keyboard's modifier bitmap from the + * list of keycodes. + */ + map = (KeyCode *)xalloc(inputMapLen); + if (!map && inputMapLen) + return BadAlloc; + if (keyc->modifierKeyMap) + xfree(keyc->modifierKeyMap); + keyc->modifierKeyMap = map; + memmove((char *)map, (char *)inputMap, inputMapLen); + + keyc->maxKeysPerModifier = stuff->numKeyPerModifier; + for (i = 0; i < MAP_LENGTH; i++) + keyc->modifierMap[i] = 0; + for (i = 0; i < inputMapLen; i++) + { + if (inputMap[i]) + keyc->modifierMap[inputMap[i]] |= + (1<<(((unsigned int)i)/keyc->maxKeysPerModifier)); + } + } + + if (rep.success == MappingSuccess) + SendMappingNotify(MappingModifier, 0, 0, client); + + WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); + + return(client->noClientException); +} + +int +ProcGetModifierMapping(client) + ClientPtr client; +{ + xGetModifierMappingReply rep; + REQUEST(xReq); + register KeyClassPtr keyc = inputInfo.keyboard->key; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.numKeyPerModifier = keyc->maxKeysPerModifier; + rep.sequenceNumber = client->sequence; + /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ + rep.length = keyc->maxKeysPerModifier << 1; + + WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); + + /* Use the (modified by DDX) map that SetModifierMapping passed in */ + (void)WriteToClient(client, (int)(keyc->maxKeysPerModifier << 3), + (char *)keyc->modifierKeyMap); + return client->noClientException; +} + +int +ProcChangeKeyboardMapping(client) + ClientPtr client; +{ + REQUEST(xChangeKeyboardMappingReq); + unsigned len; + KeySymsRec keysyms; + register KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); + + len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); + if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) + return BadLength; + if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || + (stuff->firstKeyCode > curKeySyms->maxKeyCode)) + { + client->errorValue = stuff->firstKeyCode; + return BadValue; + } + if ( ((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) > + curKeySyms->maxKeyCode) || + (stuff->keySymsPerKeyCode == 0)) + { + client->errorValue = stuff->keySymsPerKeyCode; + return BadValue; + } +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, + TRUE)) + return BadAccess; +#endif + keysyms.minKeyCode = stuff->firstKeyCode; + keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; + keysyms.mapWidth = stuff->keySymsPerKeyCode; + keysyms.map = (KeySym *)&stuff[1]; + if (!SetKeySymsMap(curKeySyms, &keysyms)) + return BadAlloc; +#ifdef LBX + LbxFlushKeyboardMapTag(); +#endif + SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes, + client); + return client->noClientException; + +} + +int +ProcSetPointerMapping(client) + ClientPtr client; +{ + REQUEST(xSetPointerMappingReq); + BYTE *map; + xSetPointerMappingReply rep; + register unsigned int i; + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); + if (client->req_len != (sizeof(xSetPointerMappingReq)+stuff->nElts+3) >> 2) + return BadLength; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.success = MappingSuccess; + map = (BYTE *)&stuff[1]; + if (stuff->nElts != mouse->button->numButtons) + { + client->errorValue = stuff->nElts; + return BadValue; + } + if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue)) + return BadValue; + for (i=0; i < stuff->nElts; i++) + if ((mouse->button->map[i + 1] != map[i]) && + BitIsOn(mouse->button->down, i + 1)) + { + rep.success = MappingBusy; + WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); + return Success; + } + for (i = 0; i < stuff->nElts; i++) + mouse->button->map[i + 1] = map[i]; + SendMappingNotify(MappingPointer, 0, 0, client); + WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); + return Success; +} + +int +ProcGetKeyboardMapping(client) + ClientPtr client; +{ + xGetKeyboardMappingReply rep; + REQUEST(xGetKeyboardMappingReq); + KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + + REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); + + if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || + (stuff->firstKeyCode > curKeySyms->maxKeyCode)) + { + client->errorValue = stuff->firstKeyCode; + return BadValue; + } + if (stuff->firstKeyCode + stuff->count > + (unsigned)(curKeySyms->maxKeyCode + 1)) + { + client->errorValue = stuff->count; + return BadValue; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.keySymsPerKeyCode = curKeySyms->mapWidth; + /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ + rep.length = (curKeySyms->mapWidth * stuff->count); + WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep); + client->pSwapReplyFunc = CopySwap32Write; + WriteSwappedDataToClient( + client, + curKeySyms->mapWidth * stuff->count * sizeof(KeySym), + &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) * + curKeySyms->mapWidth]); + + return client->noClientException; +} + +int +ProcGetPointerMapping(client) + ClientPtr client; +{ + xGetPointerMappingReply rep; + REQUEST(xReq); + ButtonClassPtr butc = inputInfo.pointer->button; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nElts = butc->numButtons; + rep.length = ((unsigned)rep.nElts + (4-1))/4; + WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); + (void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); + return Success; +} + +void +NoteLedState(keybd, led, on) + DeviceIntPtr keybd; + int led; + Bool on; +{ + KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl; + if (on) + ctrl->leds |= ((Leds)1 << (led - 1)); + else + ctrl->leds &= ~((Leds)1 << (led - 1)); +} + +int +Ones(mask) /* HACKMEM 169 */ + unsigned long mask; +{ + register unsigned long y; + + y = (mask >> 1) &033333333333; + y = mask - y - ((y >>1) & 033333333333); + return (((y + (y >> 3)) & 030707070707) % 077); +} + +int +ProcChangeKeyboardControl (client) + ClientPtr client; +{ +#define DO_ALL (-1) + KeybdCtrl ctrl; + DeviceIntPtr keybd = inputInfo.keyboard; + XID *vlist; + int t; + int led = DO_ALL; + int key = DO_ALL; + BITS32 vmask, index; + int mask, i; + REQUEST(xChangeKeyboardControlReq); + + REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); + vmask = stuff->mask; + if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask)) + return BadLength; +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, keybd, TRUE)) + return BadAccess; +#endif + vlist = (XID *)&stuff[1]; /* first word of values */ + ctrl = keybd->kbdfeed->ctrl; + while (vmask) + { + index = (BITS32) lowbit (vmask); + vmask &= ~index; + switch (index) + { + case KBKeyClickPercent: + t = (INT8)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.click; + else if (t < 0 || t > 100) + { + client->errorValue = t; + return BadValue; + } + ctrl.click = t; + break; + case KBBellPercent: + t = (INT8)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.bell; + else if (t < 0 || t > 100) + { + client->errorValue = t; + return BadValue; + } + ctrl.bell = t; + break; + case KBBellPitch: + t = (INT16)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.bell_pitch; + else if (t < 0) + { + client->errorValue = t; + return BadValue; + } + ctrl.bell_pitch = t; + break; + case KBBellDuration: + t = (INT16)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.bell_duration; + else if (t < 0) + { + client->errorValue = t; + return BadValue; + } + ctrl.bell_duration = t; + break; + case KBLed: + led = (CARD8)*vlist; + vlist++; + if (led < 1 || led > 32) + { + client->errorValue = led; + return BadValue; + } + if (!(stuff->mask & KBLedMode)) + return BadMatch; + break; + case KBLedMode: + t = (CARD8)*vlist; + vlist++; + if (t == LedModeOff) + { + if (led == DO_ALL) + ctrl.leds = 0x0; + else + ctrl.leds &= ~(((Leds)(1)) << (led - 1)); + } + else if (t == LedModeOn) + { + if (led == DO_ALL) + ctrl.leds = ~0L; + else + ctrl.leds |= (((Leds)(1)) << (led - 1)); + } + else + { + client->errorValue = t; + return BadValue; + } +#ifdef XKB + if (!noXkbExtension) { + XkbEventCauseRec cause; + XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client); + keybd->kbdfeed->ctrl.leds = ctrl.leds; + XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))), + ctrl.leds, &cause); + } +#endif + break; + case KBKey: + key = (KeyCode)*vlist; + vlist++; + if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode || + (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) + { + client->errorValue = key; + return BadValue; + } + if (!(stuff->mask & KBAutoRepeatMode)) + return BadMatch; + break; + case KBAutoRepeatMode: + i = (key >> 3); + mask = (1 << (key & 7)); + t = (CARD8)*vlist; + vlist++; +#ifdef XKB + if (!noXkbExtension && key != DO_ALL) + XkbDisableComputedAutoRepeats(keybd,key); +#endif + if (t == AutoRepeatModeOff) + { + if (key == DO_ALL) + ctrl.autoRepeat = FALSE; + else + ctrl.autoRepeats[i] &= ~mask; + } + else if (t == AutoRepeatModeOn) + { + if (key == DO_ALL) + ctrl.autoRepeat = TRUE; + else + ctrl.autoRepeats[i] |= mask; + } + else if (t == AutoRepeatModeDefault) + { + if (key == DO_ALL) + ctrl.autoRepeat = defaultKeyboardControl.autoRepeat; + else + ctrl.autoRepeats[i] = + (ctrl.autoRepeats[i] & ~mask) | + (defaultKeyboardControl.autoRepeats[i] & mask); + } + else + { + client->errorValue = t; + return BadValue; + } + break; + default: + client->errorValue = stuff->mask; + return BadValue; + } + } + keybd->kbdfeed->ctrl = ctrl; +#ifdef XKB + /* The XKB RepeatKeys control and core protocol global autorepeat */ + /* value are linked */ + if (!noXkbExtension) { + XkbSetRepeatKeys(keybd,key,keybd->kbdfeed->ctrl.autoRepeat); + } + else +#endif + (*keybd->kbdfeed->CtrlProc)(keybd, &keybd->kbdfeed->ctrl); + return Success; +#undef DO_ALL +} + +int +ProcGetKeyboardControl (client) + ClientPtr client; +{ + int i; + register KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl; + xGetKeyboardControlReply rep; + REQUEST(xReq); + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 5; + rep.sequenceNumber = client->sequence; + rep.globalAutoRepeat = ctrl->autoRepeat; + rep.keyClickPercent = ctrl->click; + rep.bellPercent = ctrl->bell; + rep.bellPitch = ctrl->bell_pitch; + rep.bellDuration = ctrl->bell_duration; + rep.ledMask = ctrl->leds; + for (i = 0; i < 32; i++) + rep.map[i] = ctrl->autoRepeats[i]; + WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); + return Success; +} + +int +ProcBell(client) + ClientPtr client; +{ + register DeviceIntPtr keybd = inputInfo.keyboard; + int base = keybd->kbdfeed->ctrl.bell; + int newpercent; + REQUEST(xBellReq); + REQUEST_SIZE_MATCH(xBellReq); + if (stuff->percent < -100 || stuff->percent > 100) + { + client->errorValue = stuff->percent; + return BadValue; + } + newpercent = (base * stuff->percent) / 100; + if (stuff->percent < 0) + newpercent = base + newpercent; + else + newpercent = base - newpercent + stuff->percent; +#ifdef XKB + if (!noXkbExtension) + XkbHandleBell(FALSE,FALSE, keybd, newpercent, &keybd->kbdfeed->ctrl, 0, + None, NULL, client); + else +#endif + (*keybd->kbdfeed->BellProc)(newpercent, keybd, + (pointer) &keybd->kbdfeed->ctrl, 0); + return Success; +} + +int +ProcChangePointerControl(client) + ClientPtr client; +{ + DeviceIntPtr mouse = inputInfo.pointer; + PtrCtrl ctrl; /* might get BadValue part way through */ + REQUEST(xChangePointerControlReq); + + REQUEST_SIZE_MATCH(xChangePointerControlReq); + ctrl = mouse->ptrfeed->ctrl; + if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) + { + client->errorValue = stuff->doAccel; + return(BadValue); + } + if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) + { + client->errorValue = stuff->doThresh; + return(BadValue); + } + if (stuff->doAccel) + { + if (stuff->accelNum == -1) + ctrl.num = defaultPointerControl.num; + else if (stuff->accelNum < 0) + { + client->errorValue = stuff->accelNum; + return BadValue; + } + else ctrl.num = stuff->accelNum; + if (stuff->accelDenum == -1) + ctrl.den = defaultPointerControl.den; + else if (stuff->accelDenum <= 0) + { + client->errorValue = stuff->accelDenum; + return BadValue; + } + else ctrl.den = stuff->accelDenum; + } + if (stuff->doThresh) + { + if (stuff->threshold == -1) + ctrl.threshold = defaultPointerControl.threshold; + else if (stuff->threshold < 0) + { + client->errorValue = stuff->threshold; + return BadValue; + } + else ctrl.threshold = stuff->threshold; + } + mouse->ptrfeed->ctrl = ctrl; + (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl); + return Success; +} + +int +ProcGetPointerControl(client) + ClientPtr client; +{ + register PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl; + REQUEST(xReq); + xGetPointerControlReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.threshold = ctrl->threshold; + rep.accelNumerator = ctrl->num; + rep.accelDenominator = ctrl->den; + WriteReplyToClient(client, sizeof(xGenericReply), &rep); + return Success; +} + +void +MaybeStopHint(dev, client) + register DeviceIntPtr dev; + ClientPtr client; +{ + GrabPtr grab = dev->grab; + + if ((grab && SameClient(grab, client) && + ((grab->eventMask & PointerMotionHintMask) || + (grab->ownerEvents && + (EventMaskForClient(dev->valuator->motionHintWindow, client) & + PointerMotionHintMask)))) || + (!grab && + (EventMaskForClient(dev->valuator->motionHintWindow, client) & + PointerMotionHintMask))) + dev->valuator->motionHintWindow = NullWindow; +} + +int +ProcGetMotionEvents(client) + ClientPtr client; +{ + WindowPtr pWin; + xTimecoord * coords = (xTimecoord *) NULL; + xGetMotionEventsReply rep; + int i, count, xmin, xmax, ymin, ymax; + unsigned long nEvents; + DeviceIntPtr mouse = inputInfo.pointer; + TimeStamp start, stop; + REQUEST(xGetMotionEventsReq); + + REQUEST_SIZE_MATCH(xGetMotionEventsReq); + pWin = SecurityLookupWindow(stuff->window, client, TRUE); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + nEvents = 0; + start = ClientTimeToServerTime(stuff->start); + stop = ClientTimeToServerTime(stuff->stop); + if ((CompareTimeStamps(start, stop) != LATER) && + (CompareTimeStamps(start, currentTime) != LATER) && + mouse->valuator->numMotionEvents) + { + if (CompareTimeStamps(stop, currentTime) == LATER) + stop = currentTime; + coords = (xTimecoord *)ALLOCATE_LOCAL(mouse->valuator->numMotionEvents + * sizeof(xTimecoord)); + if (!coords) + return BadAlloc; + count = (*mouse->valuator->GetMotionProc) (mouse, coords, + start.milliseconds, + stop.milliseconds, + pWin->drawable.pScreen); + xmin = pWin->drawable.x - wBorderWidth (pWin); + xmax = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + ymin = pWin->drawable.y - wBorderWidth (pWin); + ymax = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + for (i = 0; i < count; i++) + if ((xmin <= coords[i].x) && (coords[i].x < xmax) && + (ymin <= coords[i].y) && (coords[i].y < ymax)) + { + coords[nEvents].time = coords[i].time; + coords[nEvents].x = coords[i].x - pWin->drawable.x; + coords[nEvents].y = coords[i].y - pWin->drawable.y; + nEvents++; + } + } + rep.length = nEvents * (sizeof(xTimecoord) >> 2); + rep.nEvents = nEvents; + WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); + if (nEvents) + { + client->pSwapReplyFunc = SwapTimeCoordWrite; + WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord), + (char *)coords); + } + if (coords) + DEALLOCATE_LOCAL(coords); + return Success; +} + +int +ProcQueryKeymap(client) + ClientPtr client; +{ + REQUEST(xReq); + xQueryKeymapReply rep; + int i; + CARD8 *down = inputInfo.keyboard->key->down; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 2; +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + bzero((char *)&rep.map[0], 32); + } + else +#endif + for (i = 0; i<32; i++) + rep.map[i] = down[i]; + WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); + return Success; +} + diff --git a/dix/dispatch.c b/dix/dispatch.c new file mode 100644 index 000000000..68cd8e549 --- /dev/null +++ b/dix/dispatch.c @@ -0,0 +1,3966 @@ +/* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + +#include "windowstr.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif +#ifdef XAPPGROUP +#include "extensions/Xagsrv.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1 << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern WindowPtr *WindowTable; +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; +extern void ReleaseActiveGrabs(); +extern void NotImplemented(); +extern void SwapConnClientPrefix( +#if NeedFunctionPrototypes + xConnClientPrefix * +#endif +); + +Selection *CurrentSelections; +int NumCurrentSelections; + +extern CARD32 defaultScreenSaverTime; +extern CARD32 defaultScreenSaverInterval; +extern int defaultScreenSaverBlanking; +extern int defaultScreenSaverAllowExposures; +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +#ifdef XKB +extern Bool noXkbExtension; +#endif + +extern void Swap32Write(), SLHostsExtend(), SQColorsExtend(), WriteSConnectionInfo(); +extern void WriteSConnSetupPrefix(); + +static void KillAllClients( +#if NeedFunctionPrototypes + void +#endif +); + +static void DeleteClientFromAnySelections( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +#ifdef LBX +extern unsigned long StandardRequestLength(); +#endif + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; +char dispatchException = 0; +char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(c0, c1) + HWEventQueuePtr c0, c1; +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; +} + +void +FlushClientCaches(id) + XID id; +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; ilastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch() +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + nready = WaitForSomething(clientReady); + + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + /* now, finally, deal with client requests */ + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (MAX_BIG_REQUEST_SIZE << 2)) + result = BadLength; + else + result = (* client->requestVector[MAJOROP])(client); + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } + } + FlushAllOutput(); + + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +/*ARGSUSED*/ +int +ProcBadRequest(client) + ClientPtr client; +{ + return (BadRequest); +} + +int +ProcCreateWindow(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(client, rep) + register ClientPtr client; + xGetGeometryReply *rep; +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(client) + register ClientPtr client; +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(client) + register ClientPtr client; +{ + + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + numChildren++; + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + childIDs[curChild++] = pChild->drawable.id; + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(client) + register ClientPtr client; +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(client) + register ClientPtr client; +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(client) + register ClientPtr client; +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(client) + register ClientPtr client; +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) +#ifdef XCSECURITY + && (!client->CheckAccess || + (* client->CheckAccess)(client, CurrentSelections[i].window, + RT_WINDOW, SecurityReadAccess, + CurrentSelections[i].pWin)) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(client) + register ClientPtr client; +{ + REQUEST(xReq); + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +UngrabServer(client) + ClientPtr client; +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(client) + register ClientPtr client; +{ + REQUEST(xReq); + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(client) + register ClientPtr client; +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(client) + register ClientPtr client; +{ + int err; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(client) + register ClientPtr client; +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if ( pFont != (FontPtr)NULL) /* id was valid */ + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(client) + register ClientPtr client; +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(client) + register ClientPtr client; +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(client) + register ClientPtr client; +{ + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(client) + register ClientPtr client; +{ + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/*ARGSUSED*/ +int +dixDestroyPixmap(value, pid) + pointer value; /* must conform to DeleteType */ + XID pid; +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(client) + register ClientPtr client; +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(client) + register ClientPtr client; +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(client) + register ClientPtr client; +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(client) + register ClientPtr client; +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(client) + register ClientPtr client; +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(client) + register ClientPtr client; +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(client) + register ClientPtr client; +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(client) + register ClientPtr client; +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(client) + register ClientPtr client; +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyLine(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolySegment(client) + register ClientPtr client; +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyRectangle (client) + register ClientPtr client; +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +int +ProcFillPoly(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyFillRectangle(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + if (things) + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyFillArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(client) + register ClientPtr client; +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = BitmapBytePadProto(stuff->width + stuff->leftPad); +#endif + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = BitmapBytePadProto(stuff->width + stuff->leftPad); + lengthProto *= stuff->depth; +#endif + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = PixmapBytePadProto(stuff->width, stuff->depth); +#endif + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* handle 64 bit case where protocol may pad to 32 and we want 64 */ + if ( length != lengthProto ) { + register int i; + char * stuffptr, /* pointer into protocol data */ + * tmpptr; /* new location to copy to */ + + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->height))) + return (BadAlloc); + + bzero(tmpImage,length*stuff->height); + + if ( stuff->format == XYPixmap ) { + int lineBytes = BitmapBytePad(stuff->width + stuff->leftPad); + int lineBytesProto = + BitmapBytePadProto(stuff->width + stuff->leftPad); + int depth = stuff->depth; + + stuffptr = (char *)&stuff[1]; + tmpptr = tmpImage; + for ( i = 0; i < stuff->height*stuff->depth; + stuffptr += lineBytesProto,tmpptr += lineBytes, i++) + memmove(tmpptr,stuffptr,lineBytesProto); + } + else { + for ( i = 0,stuffptr = (char *)&stuff[1],tmpptr=tmpImage; + i < stuff->height; + stuffptr += lengthProto,tmpptr += length, i++) + memmove(tmpptr,stuffptr,lengthProto); + } + } + + /* handle 64-bit case where stuff is not 64-bit aligned */ + else if ((unsigned long)&stuff[1] & (sizeof(long)-1)) { + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->height))) + return (BadAlloc); + memmove(tmpImage,(char *)&stuff[1],length*stuff->height); + } + else + tmpImage = (char *)&stuff[1]; +#else + tmpImage = (char *)&stuff[1]; + lengthProto = length; +#endif /* INTERNAL_VS_EXTERNAL_PADDING */ + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* free up our temporary space if used */ + if (tmpImage != (char *)&stuff[1]) + DEALLOCATE_LOCAL(tmpImage); +#endif /* INTERNAL_VS_EXTERNAL_PADDING */ + + return (client->noClientException); +} + + +int +DoGetImage(client, format, drawable, x, y, width, height, planemask, im_return) + register ClientPtr client; + Drawable drawable; + int format; + int x, y, width, height; + Mask planemask; + xGetImageReply **im_return; +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + long widthBytesLineProto, lengthProto; +#endif + Mask plane; + char *pBuf; + xGetImageReply xgi; + RegionPtr pVisibleRegion = NULL; + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLineProto = PixmapBytePadProto(width, pDraw->depth); + lengthProto = widthBytesLineProto * height; +#endif + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLineProto = BitmapBytePadProto(width); + lengthProto = widthBytesLineProto * height * + Ones(planemask & (plane | (plane - 1))); +#endif + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + xgi.length = lengthProto; +#else + xgi.length = length; +#endif + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XCSECURITY + if (client->trustLevel != XSecurityClientTrusted && + pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* for 64-bit server, convert image to pad to 32 bits */ + if ( widthBytesLine != widthBytesLineProto ) { + register char * bufPtr, * protoPtr; + register int i; + + for (i = 1, + bufPtr = pBuf + widthBytesLine, + protoPtr = pBuf + widthBytesLineProto; + i < nlines; + bufPtr += widthBytesLine, + protoPtr += widthBytesLineProto, + i++) + memmove(protoPtr, bufPtr, widthBytesLineProto); + } +#endif + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) +/* Don't split me, gcc pukes when you do */ +#ifdef INTERNAL_VS_EXTERNAL_PADDING + (void)WriteToClient(client, + (int)(nlines * widthBytesLineProto), + pBuf); +#else + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); +#endif + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* for 64-bit server, convert image to pad to 32 bits */ + if ( widthBytesLine != widthBytesLineProto ) { + register char * bufPtr, * protoPtr; + register int i; + + for (i = 1, + bufPtr = pBuf + widthBytesLine, + protoPtr = pBuf + widthBytesLineProto; + i < nlines; + bufPtr += widthBytesLine, + protoPtr += widthBytesLineProto, + i++) + memmove(protoPtr, bufPtr, widthBytesLineProto); + } +#endif + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + pBuf += nlines * widthBytesLineProto; +#else + pBuf += nlines * widthBytesLine; +#endif + } else +/* Don't split me, gcc pukes when you do */ +#ifdef INTERNAL_VS_EXTERNAL_PADDING + (void)WriteToClient(client, + (int)(nlines * widthBytesLineProto), + pBuf); +#else + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); +#endif + linesDone += nlines; + } + } + } + } +#ifdef XCSECURITY + if (pVisibleRegion) + REGION_DESTROY(pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(client) + register ClientPtr client; +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(client) + register ClientPtr client; +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(client) + register ClientPtr client; +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadValue); +} + +int +ProcFreeColormap(client) + register ClientPtr client; +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(client) + register ClientPtr client; +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(client) + register ClientPtr client; +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor(client) + register ClientPtr client; +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pmap, (xReq *) stuff)) + return Success; +#endif + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocNamedColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorCells request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorPlanes request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +int +ProcCreateGlyphCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor(client) + register ClientPtr client; +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (client) + register ClientPtr client; +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (client) + register ClientPtr client; +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + if (blankingOption == DefaultBlanking) + ScreenSaverBlanking = defaultScreenSaverBlanking; + else + ScreenSaverBlanking = blankingOption; + if (exposureOption == DefaultExposures) + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + else + ScreenSaverAllowExposures = exposureOption; + + if (stuff->timeout >= 0) + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + else + ScreenSaverTime = defaultScreenSaverTime; + if (stuff->interval >= 0) + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + else + ScreenSaverInterval = defaultScreenSaverInterval; + return (client->noClientException); +} + +int +ProcGetScreenSaver(client) + register ClientPtr client; +{ + REQUEST(xReq); + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(client) + register ClientPtr client; +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(client) + register ClientPtr client; +{ +extern int GetHosts(); + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + REQUEST(xListHostsReq); + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XCSECURITY + /* untrusted clients can't list hosts */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to list hosts\n", client->index); + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(client) + register ClientPtr client; +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(client) + register ClientPtr client; +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(client) + register ClientPtr client; +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + REQUEST (xReq); + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(client) + register ClientPtr client; +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(client) + register ClientPtr client; +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + return client->noClientException; +} + +int ProcNoOperation(client) + register ClientPtr client; +{ + REQUEST(xReq); + + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors() +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = NotImplemented; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +Bool terminateAtReset = FALSE; + +void +CloseDownClient(client) + register ClientPtr client; +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); +#ifdef LBX + ProcessQTagZombies(); +#endif + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + { + if (terminateAtReset) + dispatchException |= DE_TERMINATE; + else + dispatchException |= DE_RESET; + } + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; icloseDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; icloseDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +void InitClient(client, i, ospriv) + ClientPtr client; + int i; + pointer ospriv; +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (pointer *)NULL; + client->noClientException = Success; +#ifdef DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef LBX + client->readRequest = StandardReadRequestFromClient; +#endif +#ifdef XCSECURITY + client->trustLevel = XSecurityClientTrusted; + client->CheckAccess = NULL; + client->authId = 0; +#endif +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +int +InitClientPrivates(client) + ClientPtr client; +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr +NextAvailableClient(ospriv) + pointer ospriv; +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(client) + register ClientPtr client; +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +#ifdef LBX +void +IncrementClientCount() +{ + nClients++; +} +#endif + +int +SendConnSetup(client, reason) + register ClientPtr client; + char *reason; +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + char pad[3]; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); + for (i=0; icurrentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(client) + register ClientPtr client; +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +void +SendErrorToClient(client, majorCode, minorCode, resId, errorCode) + ClientPtr client; + unsigned int majorCode; + unsigned int minorCode; + XID resId; + int errorCode; +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(pWin) + WindowPtr pWin; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(client) + ClientPtr client; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(client) + ClientPtr client; +{ + client->noClientException = -1; +} diff --git a/dix/dixfonts.c b/dix/dixfonts.c new file mode 100644 index 000000000..83ef68b96 --- /dev/null +++ b/dix/dixfonts.c @@ -0,0 +1,2128 @@ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +************************************************************************/ + +/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */ + +#define NEED_REPLIES +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +#ifdef DEBUG +#include +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +static Mask FontFormat = +#if IMAGE_BYTE_ORDER == LSBFirst + BitmapFormatByteOrderLSB | +#else + BitmapFormatByteOrderMSB | +#endif + +#if BITMAP_BIT_ORDER == LSBFirst + BitmapFormatBitOrderLSB | +#else + BitmapFormatBitOrderMSB | +#endif + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +static FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + case BadFontPath: + return BadName; + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(defaultfontname) + char *defaultfontname; +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +/* ARGSUSED */ +void +FontWakeup(data, count, LastSelectMask) + pointer data; + int count; + pointer LastSelectMask; +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +UseFPE(fpe) + FontPathElementPtr fpe; +{ + fpe->refcount++; +} + +static void +FreeFPE (fpe) + FontPathElementPtr fpe; +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +doOpenFont(client, c) + ClientPtr client; + OFclosurePtr c; +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, doOpenFont, (pointer) c); + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + if (!(*pScr->RealizeFont) (pScr, pfont)) + { + CloseFont (pfont, (Font) 0); + err = AllocError; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + ClientWakeup(c->client); + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/* + * Decrement font's ref count, and free storage if ref count equals zero + */ +/*ARGSUSED*/ +int +CloseFont(value, fid) + pointer value; /* must conform to DeleteType */ + XID fid; +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef LBX + LbxFreeFontTag(pfont); +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + + /* + * \ Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. \ + */ + +void +QueryFont(pFont, pReply, nProtoCCIStructs) + FontPtr pFont; + xQueryFontReply *pReply; /* caller must allocate this storage */ + int nProtoCCIStructs; +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit, + &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +doListFontsAndAliases(client, c) + ClientPtr client; + LFclosurePtr c; +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, doListFontsAndAliases, (pointer) c); + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &resolved, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + return TRUE; +} + +int +ListFonts(client, pattern, length, max_names) + ClientPtr client; + unsigned char *pattern; + unsigned int length; + unsigned int max_names; +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(client, c) + ClientPtr client; + LFWIclosurePtr c; +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, doListFontsWithInfo, c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, doListFontsWithInfo, c); + c->slept = TRUE; + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + c->savedName = (char *) pFontInfo; + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(client, length, pattern, max_names) + ClientPtr client; + int length; + unsigned char *pattern; + int max_names; +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(client, c) + ClientPtr client; + register PTclosurePtr c; +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state; + FontPathElementPtr fpe; + GC *origGC; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = c->pGC->ops->PolyText8; + else + c->polyText = c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, doPolyText, (pointer) c); + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(client, pDraw, pGC, pElt, endReq, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + unsigned char *pElt; + unsigned char *endReq; + int xorg; + int yorg; + int reqType; + XID did; +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(client, c) + ClientPtr client; + register ITclosurePtr c; +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, doImageText, (pointer) c); + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(client, pDraw, pGC, nChars, data, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + int nChars; + unsigned char *data; + int xorg; + int yorg; + int reqType; + XID did; +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +DetermineFPEType(pathname) + char *pathname; +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +FreeFontPath(list, n, force) + FontPathElementPtr *list; + Bool force; + int n; +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +find_existing_fpe(list, num, name, len) + FontPathElementPtr *list; + int num; + unsigned char *name; + int len; +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +SetFontPathElements(npaths, paths, bad) + int npaths; + unsigned char *paths; + int *bad; +{ + int i, + err; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe, + *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) { + len = (unsigned int) (*cp++); + + if (len) { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + fplist[valid_paths++] = fpe; + cp += len; + continue; + } + /* if error or can't do it, act like it's a new one */ + } + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + cp += len; + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) { + xfree(fpe->name); + xfree(fpe); + err = BadValue; + goto bail; + } + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) { + xfree(fpe->name); + xfree(fpe); + err = BadValue; + goto bail; + } + fplist[valid_paths++] = fpe; + } else { + err = BadValue; + goto bail; + } + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--i >= 0) + FreeFPE(fplist[i]); + xfree(fplist); + return err; +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(client, npaths, paths, error) + ClientPtr client; + int npaths; + unsigned char *paths; + int *error; +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadName; + } else { + err = SetFontPathElements(npaths, paths, error); + } + return err; +} + +int +SetDefaultFontPath(path) + char *path; +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ + len = strlen(path) + 1; + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; + pp = (unsigned char *) path; + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(count, length) + int *count; + int *length; +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +int +LoadGlyphs(client, pfont, nchars, item_size, data) + ClientPtr client; + FontPtr pfont; + unsigned nchars; + int item_size; + unsigned char *data; +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(client) + ClientPtr client; +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else { + FontFileRegisterFpeFunctions(); + fs_register_fpe_functions(); + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (num) + int *num; +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(name_func, init_func, free_func, reset_func, + open_func, close_func, list_func, start_lfwi_func, next_lfwi_func, + wakeup_func, client_died, load_glyphs, + start_list_alias_func, next_list_alias_func, + set_path_func) + Bool (*name_func) (); + int (*init_func) (); + int (*free_func) (); + int (*reset_func) (); + int (*open_func) (); + int (*close_func) (); + int (*list_func) (); + int (*start_lfwi_func) (); + int (*next_lfwi_func) (); + int (*wakeup_func) (); + int (*client_died) (); + int (*load_glyphs) (); + int (*start_list_alias_func) (); + int (*next_list_alias_func) (); + void (*set_path_func) (); +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(id) + XID id; +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(pfont, id) + FontPtr pfont; + Font id; +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(id) + Font id; +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(client) + ClientPtr client; +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(fpe, block_handler) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(fpe, block_handler, all) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; + Bool all; +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +dump_char_ascii(cip) + CharInfoPtr cip; +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif diff --git a/dix/dixutils.c b/dix/dixutils.c new file mode 100644 index 000000000..3b16c6a13 --- /dev/null +++ b/dix/dixutils.c @@ -0,0 +1,969 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* + +(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved. + +Permission to use, copy, modify, distribute, and sublicense this software and its +documentation for any purpose and without fee is hereby granted, provided that +the above copyright notices appear in all copies and that both those copyright +notices and this permission notice appear in supporting documentation and that +the name of Adobe Systems Incorporated not be used in advertising or publicity +pertaining to distribution of the software without specific, written prior +permission. No trademark license to use the Adobe trademarks is hereby +granted. If the Adobe trademark "Display PostScript"(tm) is used to describe +this software, its functionality or for any other purpose, such use shall be +limited to a statement that this software works in conjunction with the Display +PostScript system. Proper trademark attribution to reflect Adobe's ownership +of the trademark shall be given whenever any such reference to the Display +PostScript system is made. + +ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY +PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE +DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- +INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU +OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT +LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER +SUPPORT FOR THE SOFTWARE. + +Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems +Incorporated which may be registered in certain jurisdictions. + +Author: Adobe Systems Incorporated + +*/ + +/* $Xorg: dixutils.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#define XK_LATIN1 +#include "keysymdef.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +/* + * CompareTimeStamps returns -1, 0, or +1 depending on if the first + * argument is less than, equal to or greater than the second argument. + */ + +int +CompareTimeStamps(a, b) + TimeStamp a, b; +{ + if (a.months < b.months) + return EARLIER; + if (a.months > b.months) + return LATER; + if (a.milliseconds < b.milliseconds) + return EARLIER; + if (a.milliseconds > b.milliseconds) + return LATER; + return SAMETIME; +} + +/* + * convert client times to server TimeStamps + */ + +#define HALFMONTH ((unsigned long) 1<<31) +TimeStamp +ClientTimeToServerTime(c) + CARD32 c; +{ + TimeStamp ts; + if (c == CurrentTime) + return currentTime; + ts.months = currentTime.months; + ts.milliseconds = c; + if (c > currentTime.milliseconds) + { + if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH) + ts.months -= 1; + } + else if (c < currentTime.milliseconds) + { + if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH) + ts.months += 1; + } + return ts; +} + +/* + * ISO Latin-1 case conversion routine + * + * this routine always null-terminates the result, so + * beware of too-small buffers + */ + +void +CopyISOLatin1Lowered(dest, source, length) + register unsigned char *dest, *source; + int length; +{ + register int i; + + for (i = 0; i < length; i++, source++, dest++) + { + if ((*source >= XK_A) && (*source <= XK_Z)) + *dest = *source + (XK_a - XK_A); + else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis)) + *dest = *source + (XK_agrave - XK_Agrave); + else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn)) + *dest = *source + (XK_oslash - XK_Ooblique); + else + *dest = *source; + } + *dest = '\0'; +} + +#ifdef XCSECURITY + +/* SecurityLookupWindow and SecurityLookupDrawable: + * Look up the window/drawable taking into account the client doing + * the lookup and the type of access desired. Return the window/drawable + * if it exists and the client is allowed access, else return NULL. + * Most Proc* functions should be calling these instead of + * LookupWindow and LookupDrawable, which do no access checks. + */ + +WindowPtr +SecurityLookupWindow(rid, client, access_mode) + XID rid; + ClientPtr client; + Mask access_mode; +{ + WindowPtr pWin; + + client->errorValue = rid; + if(rid == INVALID) + return NULL; + if (client->trustLevel != XSecurityClientTrusted) + return (WindowPtr)SecurityLookupIDByType(client, rid, RT_WINDOW, access_mode); + if (client->lastDrawableID == rid) + { + if (client->lastDrawable->type == DRAWABLE_WINDOW) + return ((WindowPtr) client->lastDrawable); + return (WindowPtr) NULL; + } + pWin = (WindowPtr)SecurityLookupIDByType(client, rid, RT_WINDOW, access_mode); + if (pWin && pWin->drawable.type == DRAWABLE_WINDOW) { + client->lastDrawable = (DrawablePtr) pWin; + client->lastDrawableID = rid; + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + return pWin; +} + + +pointer +SecurityLookupDrawable(rid, client, access_mode) + XID rid; + ClientPtr client; + Mask access_mode; +{ + register DrawablePtr pDraw; + + if(rid == INVALID) + return (pointer) NULL; + if (client->trustLevel != XSecurityClientTrusted) + return (DrawablePtr)SecurityLookupIDByClass(client, rid, RC_DRAWABLE, + access_mode); + if (client->lastDrawableID == rid) + return ((pointer) client->lastDrawable); + pDraw = (DrawablePtr)SecurityLookupIDByClass(client, rid, RC_DRAWABLE, + access_mode); + if (pDraw && (pDraw->type != UNDRAWABLE_WINDOW)) + return (pointer)pDraw; + return (pointer)NULL; +} + +/* We can't replace the LookupWindow and LookupDrawable functions with + * macros because of compatibility with loadable servers. + */ + +WindowPtr +LookupWindow(rid, client) + XID rid; + ClientPtr client; +{ + return SecurityLookupWindow(rid, client, SecurityUnknownAccess); +} + +pointer +LookupDrawable(rid, client) + XID rid; + ClientPtr client; +{ + return SecurityLookupDrawable(rid, client, SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +WindowPtr +LookupWindow(rid, client) + XID rid; + ClientPtr client; +{ + WindowPtr pWin; + + client->errorValue = rid; + if(rid == INVALID) + return NULL; + if (client->lastDrawableID == rid) + { + if (client->lastDrawable->type == DRAWABLE_WINDOW) + return ((WindowPtr) client->lastDrawable); + return (WindowPtr) NULL; + } + pWin = (WindowPtr)LookupIDByType(rid, RT_WINDOW); + if (pWin && pWin->drawable.type == DRAWABLE_WINDOW) { + client->lastDrawable = (DrawablePtr) pWin; + client->lastDrawableID = rid; + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + return pWin; +} + + +pointer +LookupDrawable(rid, client) + XID rid; + ClientPtr client; +{ + register DrawablePtr pDraw; + + if(rid == INVALID) + return (pointer) NULL; + if (client->lastDrawableID == rid) + return ((pointer) client->lastDrawable); + pDraw = (DrawablePtr)LookupIDByClass(rid, RC_DRAWABLE); + if (pDraw && (pDraw->type != UNDRAWABLE_WINDOW)) + return (pointer)pDraw; + return (pointer)NULL; +} + +#endif /* XCSECURITY */ + +ClientPtr +LookupClient(rid, client) + XID rid; + ClientPtr client; +{ + pointer pRes = (pointer)SecurityLookupIDByClass(client, rid, RC_ANY, + SecurityReadAccess); + int clientIndex = CLIENT_ID(rid); + + if (clientIndex && pRes && clients[clientIndex] && !(rid & SERVER_BIT)) + { + return clients[clientIndex]; + } + return (ClientPtr)NULL; +} + + +int +AlterSaveSetForClient(client, pWin, mode) + ClientPtr client; + WindowPtr pWin; + unsigned mode; +{ + int numnow; + pointer *pTmp; + int j; + + numnow = client->numSaved; + j = 0; + if (numnow) + { + pTmp = client->saveSet; + while ((j < numnow) && (pTmp[j] != (pointer)pWin)) + j++; + } + if (mode == SetModeInsert) + { + if (j < numnow) /* duplicate */ + return(Success); + numnow++; + pTmp = (pointer *)xrealloc(client->saveSet, sizeof(pointer) * numnow); + if (!pTmp) + return(BadAlloc); + client->saveSet = pTmp; + client->numSaved = numnow; + client->saveSet[numnow - 1] = (pointer)pWin; + return(Success); + } + else if ((mode == SetModeDelete) && (j < numnow)) + { + while (j < numnow-1) + { + pTmp[j] = pTmp[j+1]; + j++; + } + numnow--; + if (numnow) + { + pTmp = (pointer *)xrealloc(client->saveSet, + sizeof(pointer) * numnow); + if (pTmp) + client->saveSet = pTmp; + } + else + { + xfree(client->saveSet); + client->saveSet = (pointer *)NULL; + } + client->numSaved = numnow; + return(Success); + } + return(Success); +} + +void +DeleteWindowFromAnySaveSet(pWin) + WindowPtr pWin; +{ + register int i; + register ClientPtr client; + + for (i = 0; i< currentMaxClients; i++) + { + client = clients[i]; + if (client && client->numSaved) + (void)AlterSaveSetForClient(client, pWin, SetModeDelete); + } +} + +/* No-op Don't Do Anything : sometimes we need to be able to call a procedure + * that doesn't do anything. For example, on screen with only static + * colormaps, if someone calls install colormap, it's easier to have a dummy + * procedure to call than to check if there's a procedure + */ +void +NoopDDA( +#if NeedVarargsPrototypes + void* f, ... +#endif +) +{ +} + +typedef struct _BlockHandler { + BlockHandlerProcPtr BlockHandler; + WakeupHandlerProcPtr WakeupHandler; + pointer blockData; + Bool deleted; +} BlockHandlerRec, *BlockHandlerPtr; + +static BlockHandlerPtr handlers; +static int numHandlers; +static int sizeHandlers; +static Bool inHandler; +static Bool handlerDeleted; + +/* called from the OS layer */ +void +BlockHandler(pTimeout, pReadmask) +pointer pTimeout; /* DIX doesn't want to know how OS represents time */ +pointer pReadmask; /* nor how it represents the set of descriptors */ +{ + register int i, j; + + ++inHandler; + for (i = 0; i < screenInfo.numScreens; i++) + (* screenInfo.screens[i]->BlockHandler)(i, + screenInfo.screens[i]->blockData, + pTimeout, pReadmask); + for (i = 0; i < numHandlers; i++) + (*handlers[i].BlockHandler) (handlers[i].blockData, + pTimeout, pReadmask); + if (handlerDeleted) + { + for (i = 0; i < numHandlers;) + if (handlers[i].deleted) + { + for (j = i; j < numHandlers - 1; j++) + handlers[j] = handlers[j+1]; + numHandlers--; + } + else + i++; + handlerDeleted = FALSE; + } + --inHandler; +} + +void +WakeupHandler(result, pReadmask) +int result; /* 32 bits of undefined result from the wait */ +pointer pReadmask; /* the resulting descriptor mask */ +{ + register int i, j; + + ++inHandler; + for (i = numHandlers - 1; i >= 0; i--) + (*handlers[i].WakeupHandler) (handlers[i].blockData, + result, pReadmask); + for (i = 0; i < screenInfo.numScreens; i++) + (* screenInfo.screens[i]->WakeupHandler)(i, + screenInfo.screens[i]->wakeupData, + result, pReadmask); + if (handlerDeleted) + { + for (i = 0; i < numHandlers;) + if (handlers[i].deleted) + { + for (j = i; j < numHandlers - 1; j++) + handlers[j] = handlers[j+1]; + numHandlers--; + } + else + i++; + handlerDeleted = FALSE; + } + --inHandler; +} + +/* Reentrant with BlockHandler and WakeupHandler, except wakeup won't + * get called until next time + */ + +Bool +RegisterBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData) + BlockHandlerProcPtr blockHandler; + WakeupHandlerProcPtr wakeupHandler; + pointer blockData; +{ + BlockHandlerPtr new; + + if (numHandlers >= sizeHandlers) + { + new = (BlockHandlerPtr) xrealloc (handlers, (numHandlers + 1) * + sizeof (BlockHandlerRec)); + if (!new) + return FALSE; + handlers = new; + sizeHandlers = numHandlers + 1; + } + handlers[numHandlers].BlockHandler = blockHandler; + handlers[numHandlers].WakeupHandler = wakeupHandler; + handlers[numHandlers].blockData = blockData; + handlers[numHandlers].deleted = FALSE; + numHandlers = numHandlers + 1; + return TRUE; +} + +void +RemoveBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData) + BlockHandlerProcPtr blockHandler; + WakeupHandlerProcPtr wakeupHandler; + pointer blockData; +{ + int i; + + for (i = 0; i < numHandlers; i++) + if (handlers[i].BlockHandler == blockHandler && + handlers[i].WakeupHandler == wakeupHandler && + handlers[i].blockData == blockData) + { + if (inHandler) + { + handlerDeleted = TRUE; + handlers[i].deleted = TRUE; + } + else + { + for (; i < numHandlers - 1; i++) + handlers[i] = handlers[i+1]; + numHandlers--; + } + break; + } +} + +void +InitBlockAndWakeupHandlers () +{ + xfree (handlers); + handlers = (BlockHandlerPtr) 0; + numHandlers = 0; + sizeHandlers = 0; +} + +/* + * A general work queue. Perform some task before the server + * sleeps for input. + */ + +WorkQueuePtr workQueue; +static WorkQueuePtr *workQueueLast = &workQueue; + +void +ProcessWorkQueue() +{ + WorkQueuePtr q, *p; + + p = &workQueue; + /* + * Scan the work queue once, calling each function. Those + * which return TRUE are removed from the queue, otherwise + * they will be called again. This must be reentrant with + * QueueWorkProc. + */ + while (q = *p) + { + if ((*q->function) (q->client, q->closure)) + { + /* remove q from the list */ + *p = q->next; /* don't fetch until after func called */ + xfree (q); + } + else + { + p = &q->next; /* don't fetch until after func called */ + } + } + workQueueLast = p; +} + +void +ProcessWorkQueueZombies() +{ + WorkQueuePtr q, *p; + + p = &workQueue; + while (q = *p) + { + if (q->client && q->client->clientGone) + { + (void) (*q->function) (q->client, q->closure); + /* remove q from the list */ + *p = q->next; /* don't fetch until after func called */ + xfree (q); + } + else + { + p = &q->next; /* don't fetch until after func called */ + } + } + workQueueLast = p; +} + +Bool +QueueWorkProc (function, client, closure) + Bool (*function)(); + ClientPtr client; + pointer closure; +{ + WorkQueuePtr q; + + q = (WorkQueuePtr) xalloc (sizeof *q); + if (!q) + return FALSE; + q->function = function; + q->client = client; + q->closure = closure; + q->next = NULL; + *workQueueLast = q; + workQueueLast = &q->next; + return TRUE; +} + +/* + * Manage a queue of sleeping clients, awakening them + * when requested, by using the OS functions IgnoreClient + * and AttendClient. Note that this *ignores* the troubles + * with request data interleaving itself with events, but + * we'll leave that until a later time. + */ + +typedef struct _SleepQueue { + struct _SleepQueue *next; + ClientPtr client; + Bool (*function)(); + pointer closure; +} SleepQueueRec, *SleepQueuePtr; + +static SleepQueuePtr sleepQueue = NULL; + +Bool +ClientSleep (client, function, closure) + ClientPtr client; + Bool (*function)(); + pointer closure; +{ + SleepQueuePtr q; + + q = (SleepQueuePtr) xalloc (sizeof *q); + if (!q) + return FALSE; + + IgnoreClient (client); + q->next = sleepQueue; + q->client = client; + q->function = function; + q->closure = closure; + sleepQueue = q; + return TRUE; +} + +Bool +ClientSignal (client) + ClientPtr client; +{ + SleepQueuePtr q; + + for (q = sleepQueue; q; q = q->next) + if (q->client == client) + { + return QueueWorkProc (q->function, q->client, q->closure); + } + return FALSE; +} + +void +ClientWakeup (client) + ClientPtr client; +{ + SleepQueuePtr q, *prev; + + prev = &sleepQueue; + while ( (q = *prev) ) + { + if (q->client == client) + { + *prev = q->next; + xfree (q); + if (client->clientGone) + CloseDownClient(client); + else + AttendClient (client); + break; + } + prev = &q->next; + } +} + +Bool +ClientIsAsleep (client) + ClientPtr client; +{ + SleepQueuePtr q; + + for (q = sleepQueue; q; q = q->next) + if (q->client == client) + return TRUE; + return FALSE; +} + +/* + * Generic Callback Manager + */ + +/* ===== Private Procedures ===== */ + +static int numCallbackListsToCleanup = 0; +static CallbackListPtr **listsToCleanup = NULL; + +static Bool +_AddCallback(pcbl, callback, data) + CallbackListPtr *pcbl; + CallbackProcPtr callback; + pointer data; +{ + CallbackPtr cbr; + + cbr = (CallbackPtr) xalloc(sizeof(CallbackRec)); + if (!cbr) + return FALSE; + cbr->proc = callback; + cbr->data = data; + cbr->next = (*pcbl)->list; + cbr->deleted = FALSE; + (*pcbl)->list = cbr; + return TRUE; +} + +static Bool +_DeleteCallback(pcbl, callback, data) + CallbackListPtr *pcbl; + CallbackProcPtr callback; + pointer data; +{ + CallbackListPtr cbl = *pcbl; + CallbackPtr cbr, pcbr; + int i; + + for (pcbr = NULL, cbr = cbl->list; + cbr != NULL; + pcbr = cbr, cbr = cbr->next) + { + if ((cbr->proc == callback) && (cbr->data == data)) + break; + } + if (cbr != NULL) + { + if (cbl->inCallback) + { + ++(cbl->numDeleted); + cbr->deleted = TRUE; + } + else + { + if (pcbr == NULL) + cbl->list = cbr->next; + else + pcbr->next = cbr->next; + xfree(cbr); + } + return TRUE; + } + return FALSE; +} + +static void +_CallCallbacks(pcbl, call_data) + CallbackListPtr *pcbl; + pointer call_data; +{ + CallbackListPtr cbl = *pcbl; + CallbackPtr cbr, pcbr; + + ++(cbl->inCallback); + for (cbr = cbl->list; cbr != NULL; cbr = cbr->next) + { + (*(cbr->proc)) (pcbl, cbr->data, call_data); + } + --(cbl->inCallback); + + if (cbl->inCallback) return; + + /* Was the entire list marked for deletion? */ + + if (cbl->deleted) + { + DeleteCallbackList(pcbl); + return; + } + + /* Were some individual callbacks on the list marked for deletion? + * If so, do the deletions. + */ + + if (cbl->numDeleted) + { + for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; ) + { + if (cbr->deleted) + { + if (pcbr) + { + cbr = cbr->next; + xfree(pcbr->next); + pcbr->next = cbr; + } else + { + cbr = cbr->next; + xfree(cbl->list); + cbl->list = cbr; + } + cbl->numDeleted--; + } + else /* this one wasn't deleted */ + { + pcbr = cbr; + cbr = cbr->next; + } + } + } +} + +static void +_DeleteCallbackList(pcbl) + CallbackListPtr *pcbl; +{ + CallbackListPtr cbl = *pcbl; + CallbackPtr cbr, nextcbr; + int i; + + if (cbl->inCallback) + { + cbl->deleted = TRUE; + return; + } + + for (i = 0; i < numCallbackListsToCleanup; i++) + { + if (listsToCleanup[i] = pcbl) + { + listsToCleanup[i] = NULL; + break; + } + } + + for (cbr = cbl->list; cbr != NULL; cbr = nextcbr) + { + nextcbr = cbr->next; + xfree(cbr); + } + xfree(cbl); + *pcbl = NULL; +} + +static CallbackFuncsRec default_cbfuncs = +{ + _AddCallback, + _DeleteCallback, + _CallCallbacks, + _DeleteCallbackList +}; + +/* ===== Public Procedures ===== */ + +Bool +CreateCallbackList(pcbl, cbfuncs) + CallbackListPtr *pcbl; + CallbackFuncsPtr cbfuncs; +{ + CallbackListPtr cbl; + int i; + + if (!pcbl) return FALSE; + cbl = (CallbackListPtr) xalloc(sizeof(CallbackListRec)); + if (!cbl) return FALSE; + cbl->funcs = cbfuncs ? *cbfuncs : default_cbfuncs; + cbl->inCallback = 0; + cbl->deleted = FALSE; + cbl->numDeleted = 0; + cbl->list = NULL; + *pcbl = cbl; + + for (i = 0; i < numCallbackListsToCleanup; i++) + { + if (!listsToCleanup[i]) + { + listsToCleanup[i] = pcbl; + return TRUE; + } + } + + listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup, + sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1)); + listsToCleanup[numCallbackListsToCleanup] = pcbl; + numCallbackListsToCleanup++; + return TRUE; +} + +Bool +AddCallback(pcbl, callback, data) + CallbackListPtr *pcbl; + CallbackProcPtr callback; + pointer data; +{ + if (!pcbl) return FALSE; + if (!*pcbl) + { /* list hasn't been created yet; go create it */ + if (!CreateCallbackList(pcbl, (CallbackFuncsPtr)NULL)) + return FALSE; + } + return ((*(*pcbl)->funcs.AddCallback) (pcbl, callback, data)); +} + +Bool +DeleteCallback(pcbl, callback, data) + CallbackListPtr *pcbl; + CallbackProcPtr callback; + pointer data; +{ + if (!pcbl || !*pcbl) return FALSE; + return ((*(*pcbl)->funcs.DeleteCallback) (pcbl, callback, data)); +} + +void +CallCallbacks(pcbl, call_data) + CallbackListPtr *pcbl; + pointer call_data; +{ + if (!pcbl || !*pcbl) return; + (*(*pcbl)->funcs.CallCallbacks) (pcbl, call_data); +} + +void +DeleteCallbackList(pcbl) + CallbackListPtr *pcbl; +{ + if (!pcbl || !*pcbl) return; + (*(*pcbl)->funcs.DeleteCallbackList) (pcbl); +} + +void +InitCallbackManager() +{ + int i; + + for (i = 0; i < numCallbackListsToCleanup; i++) + { + DeleteCallbackList(listsToCleanup[i]); + } + if (listsToCleanup) xfree(listsToCleanup); + + numCallbackListsToCleanup = 0; + listsToCleanup = NULL; +} diff --git a/dix/events.c b/dix/events.c new file mode 100644 index 000000000..afadfe6a3 --- /dev/null +++ b/dix/events.c @@ -0,0 +1,3717 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + + +/* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" + +#ifdef XKB +#include "XKBsrv.h" +#endif + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +extern WindowPtr *WindowTable; + +extern void (* EventSwapVector[128]) (); + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the ButtonMotionMasks are equal + * to the corresponding ButtonMasks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +CallbackListPtr EventCallback; +CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +typedef struct { + int x, y; + ScreenPtr pScreen; +} HotSpot; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#ifdef SHAPE + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +} sprite; /* info about the cursor sprite */ + +static void DoEnterLeaveEvents( +#if NeedFunctionPrototypes + WindowPtr /*fromWin*/, + WindowPtr /*toWin*/, + int /*mode*/ +#endif +); + +static WindowPtr XYToWindow( +#if NeedFunctionPrototypes + int /*x*/, + int /*y*/ +#endif +); + +void DeliverFocusedEvent(); +int DeliverDeviceEvents(); +void DoFocusEvents(); +Mask EventMaskForClient(); +Bool CheckDeviceGrabs(); +void EnqueueEvent(); + +extern GrabPtr CreateGrab(); /* Defined in grabs.c */ +extern Bool GrabMatchesSecond(); +extern Bool DeletePassiveGrabFromList(); +extern int AddPassiveGrabToList(); + +extern Bool permitOldBugs; +extern Bool Must_have_memory; +extern int lastEvent; +#ifdef XINPUT +extern int DeviceMotionNotify, DeviceButtonPress, DeviceKeyPress; +#endif + +static Mask lastEventMask; + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x3c /* key and button events */ +}; + +Mask +GetNextEventMask() +{ + lastEventMask <<= 1; + return lastEventMask; +} + +void +SetMaskForEvent(mask, event) + Mask mask; + int event; +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +void +SetCriticalEvent(event) + int event; +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +SyntheticMotion(x, y) + int x, y; +{ + xEvent xE; + + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +ConfineToShape(shape, px, py) + RegionPtr shape; + int *px, *py; +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +CheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen) + CursorPtr cursor; + Bool generateEvents; + Bool confineToScreen; + ScreenPtr pScreen; +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +CheckVirtualMotion(qe, pWin) + register QdEventPtr qe; + register WindowPtr pWin; +{ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +void +ConfineCursorToWindow(pWin, generateEvents, confineToScreen) + WindowPtr pWin; + Bool generateEvents; + Bool confineToScreen; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +ChangeToCursor(cursor) + CursorPtr cursor; +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, PointerConfinedToScreen(), + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + sprite.current = cursor; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(a, b) + register WindowPtr a, b; +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +PostNewCursor() +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +void +GetSpritePosition(px, py) + int *px, *py; +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +MonthChangedOrBadTime(xE) + register xEvent *xE; +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - xE->u.keyButtonPointer.time) > TIMESLOP) + currentTime.months++; + else + xE->u.keyButtonPointer.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(xE) + register xEvent *xE; +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xE, device, count) + xEvent *xE; + DeviceIntPtr device; + int count; +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + xE->u.keyButtonPointer.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { + sprite.hotPhys.x = xE->u.keyButtonPointer.rootX; + sprite.hotPhys.y = xE->u.keyButtonPointer.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = xE->u.keyButtonPointer.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +PlayReleasedEvents() +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +FreezeThaw(dev, frozen) + register DeviceIntPtr dev; + Bool frozen; +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + w = XYToWindow( + xE->u.keyButtonPointer.rootX, xE->u.keyButtonPointer.rootY); + for (i = 0; i < spriteTraceGood; i++) + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + goto playmore; + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +void +CheckGrabForSyncs(thisDev, thisMode, otherMode) + register DeviceIntPtr thisDev; + Bool thisMode, otherMode; +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(mouse, grab, time, autoGrab) + register GrabPtr grab; + register DeviceIntPtr mouse; + TimeStamp time; + Bool autoGrab; +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse, + (Bool)grab->pointerMode, (Bool)grab->keyboardMode); +} + +void +DeactivatePointerGrab(mouse) + register DeviceIntPtr mouse; +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); +} + +void +ActivateKeyboardGrab(keybd, grab, time, passive) + register DeviceIntPtr keybd; + GrabPtr grab; + TimeStamp time; + Bool passive; +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, + (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(keybd) + register DeviceIntPtr keybd; +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(client, time, thisDev, newState) + ClientPtr client; + TimeStamp time; + register DeviceIntPtr thisDev; + int newState; +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(client) + register ClientPtr client; +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + return Success; +} + +void +ReleaseActiveGrabs(client) + ClientPtr client; +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +int +TryClientEvents (client, pEvents, count, mask, filter, grab) + ClientPtr client; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask mask, filter; +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint (pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + SetCriticalOutputPending(); + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx) + register WindowPtr pWin; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask filter; + int mskidx; +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) && + deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, pEvents, grab, client, + deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +int +MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient) + register WindowPtr pWin; + xEvent *pEvents; + int count; + Mask filter; + ClientPtr dontClient; +{ + register OtherClients *other; + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +FixUpEventFromWindow(xE, pWin, child, calcChild) + xEvent *xE; + WindowPtr pWin; + Window child; + Bool calcChild; +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + xE->u.keyButtonPointer.root = ROOT->drawable.id; + xE->u.keyButtonPointer.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + xE->u.keyButtonPointer.sameScreen = xTrue; + xE->u.keyButtonPointer.child = child; + xE->u.keyButtonPointer.eventX = + xE->u.keyButtonPointer.rootX - pWin->drawable.x; + xE->u.keyButtonPointer.eventY = + xE->u.keyButtonPointer.rootY - pWin->drawable.y; + } + else + { + xE->u.keyButtonPointer.sameScreen = xFalse; + xE->u.keyButtonPointer.child = None; + xE->u.keyButtonPointer.eventX = 0; + xE->u.keyButtonPointer.eventY = 0; + } +} + +int +DeliverDeviceEvents(pWin, xE, grab, stopAt, dev, count) + register WindowPtr pWin, stopAt; + register xEvent *xE; + GrabPtr grab; + DeviceIntPtr dev; + int count; +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +int +DeliverEvents(pWin, xE, count, otherParent) + register WindowPtr pWin, otherParent; + register xEvent *xE; + int count; +{ + Mask filter; + int deliveries; + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + +static WindowPtr +XYToWindow(x, y) + int x, y; +{ + register WindowPtr pWin; +#ifdef SHAPE + BoxRec box; +#endif + + spriteTraceGood = 1; /* root window still there */ + pWin = ROOT->firstChild; + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +CheckMotion(xE) + xEvent *xE; +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } + sprite.hot.x = xE->u.keyButtonPointer.rootX; + sprite.hot.y = xE->u.keyButtonPointer.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != xE->u.keyButtonPointer.rootX) || + (sprite.hotPhys.y != xE->u.keyButtonPointer.rootY)) + (*sprite.hotPhys.pScreen->SetCursorPosition)( + sprite.hotPhys.pScreen, + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + xE->u.keyButtonPointer.rootX = sprite.hot.x; + xE->u.keyButtonPointer.rootY = sprite.hot.y; + } + + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +void +DefineInitialRootWindow(win) + register WindowPtr win; +{ + register ScreenPtr pScreen = win->drawable.pScreen; + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; + sprite.win = win; + sprite.current = wCursor (win); + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +/*ARGSUSED*/ +void +WindowHasNewCursor(pWin) + WindowPtr pWin; +{ + PostNewCursor(); +} + +void +NewCurrentScreen(newScreen, x, y) + ScreenPtr newScreen; + int x,y; +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +int +ProcWarpPointer(client) + ClientPtr client; +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + if (stuff->srcWid != None) + { + int winX, winY; + WindowPtr source = SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!source) + return BadWindow; + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } + else + newScreen = sprite.hotPhys.pScreen; + x += stuff->dstX; + y += stuff->dstY; + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +CheckPassiveGrabsOnWindow(pWin, device, xE, count) + WindowPtr pWin; + register DeviceIntPtr device; + register xEvent *xE; + int count; +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if (device == grab->modifierDevice && + (xE->u.u.type == KeyPress +#ifdef XINPUT + || xE->u.u.type == DeviceKeyPress +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + REGION_NOTEMPTY( grab->confineTo->drawable.pScreen, + &grab->confineTo->borderSize)))) + { +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + xE->u.keyButtonPointer.state &= 0x1f00; + xE->u.keyButtonPointer.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/* +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(device, xE, checkFirst, count) + register DeviceIntPtr device; + register xEvent *xE; + int checkFirst; + int count; +{ + register int i; + register WindowPtr pWin; + register FocusClassPtr focus = device->focus; + + if ((xE->u.u.type == ButtonPress +#ifdef XINPUT + || xE->u.u.type == DeviceButtonPress +#endif + ) && device->button->buttonsDown != 1) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(keybd, xE, window, count) + xEvent *xE; + DeviceIntPtr keybd; + WindowPtr window; + int count; +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(xE, thisDev, deactivateGrab, count) + register xEvent *xE; + register DeviceIntPtr thisDev; + Bool deactivateGrab; + int count; +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (xE, keybd, count) +#else +ProcessKeyboardEvent (xE, keybd, count) +#endif + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + xE->u.keyButtonPointer.state = (keyc->state | + inputInfo.pointer->button->state); + xE->u.keyButtonPointer.rootX = sprite.hot.x; + xE->u.keyButtonPointer.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); +} + +void +#ifdef XKB +CoreProcessPointerEvent (xE, mouse, count) +#else +ProcessPointerEvent (xE, mouse, count) +#endif + register xEvent *xE; + register DeviceIntPtr mouse; + int count; +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + xE->u.keyButtonPointer.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + xE->u.keyButtonPointer.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + xE->u.keyButtonPointer.rootX = sprite.hot.x; + xE->u.keyButtonPointer.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; + xE->u.u.detail = butc->map[key]; + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (!--butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; + xE->u.u.detail = butc->map[key]; + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +int +OtherClientGone(value, id) + pointer value; /* must conform to DeleteType */ + XID id; +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(pWin, client, mask) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#if SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#if SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +/*ARGSUSED*/ +int +EventSuppressForWindow(pWin, client, mask, checkOptional) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; + Bool *checkOptional; +{ + register int i, free; + + if ((mask & ~PropagateMask) && !permitOldBugs) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +CommonAncestor(a, b) + register WindowPtr a, b; +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +EnterLeaveEvent(type, mode, detail, pWin, child) + int type, mode, detail; + register WindowPtr pWin; + Window child; +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XCSECURITY + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +EnterNotifies(ancestor, child, mode, detail) + WindowPtr ancestor, child; + int mode, detail; +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +LeaveNotifies(child, ancestor, mode, detail) + WindowPtr child, ancestor; + int detail, mode; +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +DoEnterLeaveEvents(fromWin, toWin, mode) + WindowPtr fromWin, toWin; + int mode; +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +FocusEvent(dev, type, mode, detail, pWin) + DeviceIntPtr dev; + int type, mode, detail; + register WindowPtr pWin; +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XCSECURITY + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +FocusInEvents(dev, ancestor, child, skipChild, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr ancestor, child, skipChild; + int mode, detail; + Bool doAncestor; +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +FocusOutEvents(dev, child, ancestor, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr child, ancestor; + int mode; + int detail; + Bool doAncestor; +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(dev, fromWin, toWin, mode) + DeviceIntPtr dev; + WindowPtr fromWin, toWin; + int mode; +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ + for (i=0; iparent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ + for (i=0; iparent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +SetInputFocus(client, dev, focusID, revertTo, ctime, followOK) + ClientPtr client; + DeviceIntPtr dev; + Window focusID; + CARD8 revertTo; + Time ctime; + Bool followOK; +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(client) + ClientPtr client; +{ + xGetInputFocusReply rep; + REQUEST(xReq); + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(client) + ClientPtr client; +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && + REGION_NOTEMPTY( confineTo->drawable.pScreen, + &confineTo->borderSize)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(client, dev, this_mode, other_mode, grabWindow, ownerEvents, ctime, + mask, status) + register ClientPtr client; + register DeviceIntPtr dev; + unsigned this_mode; + unsigned other_mode; + Window grabWindow; + unsigned ownerEvents; + Time ctime; + Mask mask; + CARD8 *status; +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(client) + ClientPtr client; +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(client) + ClientPtr client; +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +int +ProcSendEvent(client) + ClientPtr client; +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32 && + !permitOldBugs) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(client) + ClientPtr client; +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(client) + ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcGrabButton(client) + ClientPtr client; +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + permitOldBugs ? (Mask)(stuff->eventMask | + ButtonPressMask | ButtonReleaseMask) : + (Mask)stuff->eventMask, + (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, + (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers, + ButtonPress, stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(client) + ClientPtr client; +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(pWin, freeResources) + WindowPtr pWin; + Bool freeResources; +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/* Call this whenever some window at or below pWin has changed geometry */ + +/*ARGSUSED*/ +void +CheckCursorConfinement(pWin) + WindowPtr pWin; +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + + if (grab && (confineTo = grab->confineTo)) + { + if (!REGION_NOTEMPTY( confineTo->drawable.pScreen, + &confineTo->borderSize)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(pWin, client) + WindowPtr pWin; + ClientPtr client; +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(client) + ClientPtr client; +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && + (pscr == sprite.hotPhys.pScreen)); + } + return (Success); +} + +void +WriteEventsToClient(pClient, count, events) + ClientPtr pClient; + int count; + xEvent *events; +{ + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} diff --git a/dix/extension.c b/dix/extension.c new file mode 100644 index 000000000..00c6b158d --- /dev/null +++ b/dix/extension.c @@ -0,0 +1,470 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +ExtensionEntry *AddExtension(name, NumEvents, NumErrors, MainProc, + SwappedMainProc, CloseDownProc, MinorOpcodeProc) + char *name; + int NumEvents; + int NumErrors; + int (* MainProc)(); + int (* SwappedMainProc)(); + void (* CloseDownProc)(); + unsigned short (* MinorOpcodeProc)(); +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry)); + if (!ext) + return((ExtensionEntry *) NULL); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + +#ifdef LBX + (void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase); +#endif + return(ext); +} + +Bool AddExtensionAlias(alias, ext) + char *alias; + ExtensionEntry *ext; +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; +#ifdef LBX + return LbxAddExtensionAlias(ext->index, alias); +#else + return TRUE; +#endif +} + +static int +FindExtension(extname, len) + char *extname; + int len; +{ + int i, j; + + for (i=0; iname) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +void +DeclareExtensionSecurity(extname, secure) + char *extname; + Bool secure; +{ +#ifdef XCSECURITY + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + { + int majorop = extensions[i]->base; + extensions[i]->secure = secure; + if (secure) + { + UntrustedProcVector[majorop] = ProcVector[majorop]; + SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop]; + } + else + { + UntrustedProcVector[majorop] = ProcBadRequest; + SwappedUntrustedProcVector[majorop] = ProcBadRequest; + } + } +#endif +#ifdef LBX + LbxDeclareExtensionSecurity(extname, secure); +#endif +} + +unsigned short +StandardMinorOpcode(client) + ClientPtr client; +{ + return ((xReq *)client->requestBuffer)->data; +} + +unsigned short +MinorOpcodeOfRequest(client) + ClientPtr client; +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + +#ifdef LBX + LbxCloseDownExtensions(); +#endif + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; inum) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(client) + ClientPtr client; +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(client) + ClientPtr client; +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST(xReq); + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(name, pGC) + char *name; + GCPtr pGC; +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(name, pGC, proc) + char *name; + GC *pGC; + ExtensionLookupProc proc; +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(name, pScreen, proc) + char *name; + ScreenPtr pScreen; + ExtensionLookupProc proc; +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} diff --git a/dix/ffs.c b/dix/ffs.c new file mode 100644 index 000000000..8d0954689 --- /dev/null +++ b/dix/ffs.c @@ -0,0 +1,37 @@ +/* $Xorg: ffs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +int +ffs(int i) +{ + int j; + for (j = 1; (i & 1) == 0; j++) + i >>= 1; + return j; +} diff --git a/dix/gc.c b/dix/gc.c new file mode 100644 index 000000000..e8ce161e8 --- /dev/null +++ b/dix/gc.c @@ -0,0 +1,1330 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: gc.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "misc.h" +#include "resource.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "region.h" + +#include "dix.h" +#include + +extern XID clientErrorValue; + +static Bool CreateDefaultTile( +#if NeedFunctionPrototypes + GCPtr /*pGC*/ +#endif +); + +unsigned char DefaultDash[2] = {4, 4}; + +void +ValidateGC(pDraw, pGC) + DrawablePtr pDraw; + GC *pGC; +{ + (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); + pGC->stateChanges = 0; + pGC->serialNumber = pDraw->serialNumber; +} + + +/* dixChangeGC(client, pGC, mask, pC32, pUnion) + * + * This function was created as part of the Security extension + * implementation. The client performing the gc change must be passed so + * that access checks can be performed on any tiles, stipples, or fonts + * that are specified. ddxen can call this too; they should normally + * pass NullClient for the client since any access checking should have + * already been done at a higher level. + * + * Since we had to create a new function anyway, we decided to change the + * way the list of gc values is passed to eliminate the compiler warnings + * caused by the DoChangeGC interface. You can pass the values via pC32 + * or pUnion, but not both; one of them must be NULL. If you don't need + * to pass any pointers, you can use either one: + * + * /* example calling dixChangeGC using pC32 parameter + * CARD32 v[2]; + * v[0] = foreground; + * v[1] = background; + * dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL); + * + * /* example calling dixChangeGC using pUnion parameter; + * /* same effect as above + * ChangeGCVal v[2]; + * v[0].val = foreground; + * v[1].val = background; + * dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v); + * + * However, if you need to pass a pointer to a pixmap or font, you MUST + * use the pUnion parameter. + * + * /* example calling dixChangeGC passing pointers in the value list + * ChangeGCVal v[2]; + * v[0].val = FillTiled; + * v[1].ptr = pPixmap; /* pointer to a pixmap + * dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v); + * + * Note: we could have gotten by with just the pUnion parameter, but on + * 64 bit machines that would have forced us to copy the value list that + * comes in the ChangeGC request. + * + * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this + * is far too many changes to consider at this time, so we've only + * changed the ones that caused compiler warnings. New code should use + * dixChangeGC. + * + * dpw + */ + +#define NEXTVAL(_type, _var) { \ + if (pC32) _var = (_type)*pC32++; \ + else { \ + _var = (_type)(pUnion->val); pUnion++; \ + } \ + } + +#define NEXT_PTR(_type, _var) { \ + assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; } + +int +dixChangeGC(client, pGC, mask, pC32, pUnion) + ClientPtr client; + register GC *pGC; + register BITS32 mask; + CARD32 *pC32; + ChangeGCValPtr pUnion; +{ + register BITS32 index; + register int error = 0; + PixmapPtr pPixmap; + BITS32 maskQ; + + assert( (pC32 && !pUnion) || (!pC32 && pUnion) ); + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + + maskQ = mask; /* save these for when we walk the GCque */ + while (mask && !error) + { + index = (BITS32) lowbit (mask); + mask &= ~index; + pGC->stateChanges |= index; + switch (index) + { + case GCFunction: + { + CARD8 newalu; + NEXTVAL(CARD8, newalu); + if (newalu <= GXset) + pGC->alu = newalu; + else + { + clientErrorValue = newalu; + error = BadValue; + } + break; + } + case GCPlaneMask: + NEXTVAL(unsigned long, pGC->planemask); + break; + case GCForeground: + NEXTVAL(unsigned long, pGC->fgPixel); + /* + * this is for CreateGC + */ + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + { + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = pGC->fgPixel; + } + break; + case GCBackground: + NEXTVAL(unsigned long, pGC->bgPixel); + break; + case GCLineWidth: /* ??? line width is a CARD16 */ + NEXTVAL(CARD16, pGC->lineWidth); + break; + case GCLineStyle: + { + unsigned int newlinestyle; + NEXTVAL(unsigned int, newlinestyle); + if (newlinestyle <= LineDoubleDash) + pGC->lineStyle = newlinestyle; + else + { + clientErrorValue = newlinestyle; + error = BadValue; + } + break; + } + case GCCapStyle: + { + unsigned int newcapstyle; + NEXTVAL(unsigned int, newcapstyle); + if (newcapstyle <= CapProjecting) + pGC->capStyle = newcapstyle; + else + { + clientErrorValue = newcapstyle; + error = BadValue; + } + break; + } + case GCJoinStyle: + { + unsigned int newjoinstyle; + NEXTVAL(unsigned int, newjoinstyle); + if (newjoinstyle <= JoinBevel) + pGC->joinStyle = newjoinstyle; + else + { + clientErrorValue = newjoinstyle; + error = BadValue; + } + break; + } + case GCFillStyle: + { + unsigned int newfillstyle; + NEXTVAL(unsigned int, newfillstyle); + if (newfillstyle <= FillOpaqueStippled) + pGC->fillStyle = newfillstyle; + else + { + clientErrorValue = newfillstyle; + error = BadValue; + } + break; + } + case GCFillRule: + { + unsigned int newfillrule; + NEXTVAL(unsigned int, newfillrule); + if (newfillrule <= WindingRule) + pGC->fillRule = newfillrule; + else + { + clientErrorValue = newfillrule; + error = BadValue; + } + break; + } + case GCTile: + { + XID newpix = 0; + if (pUnion) + { + NEXT_PTR(PixmapPtr, pPixmap); + } + else + { + NEXTVAL(XID, newpix); + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + newpix, RT_PIXMAP, SecurityReadAccess); + } + if (pPixmap) + { + if ((pPixmap->drawable.depth != pGC->depth) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pPixmap; + } + } + else + { + clientErrorValue = newpix; + error = BadPixmap; + } + break; + } + case GCStipple: + { + XID newstipple = 0; + if (pUnion) + { + NEXT_PTR(PixmapPtr, pPixmap); + } + else + { + NEXTVAL(XID, newstipple) + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + newstipple, RT_PIXMAP, SecurityReadAccess); + } + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + pGC->stipple = pPixmap; + } + } + else + { + clientErrorValue = newstipple; + error = BadPixmap; + } + break; + } + case GCTileStipXOrigin: + NEXTVAL(INT16, pGC->patOrg.x); + break; + case GCTileStipYOrigin: + NEXTVAL(INT16, pGC->patOrg.y); + break; + case GCFont: + { + FontPtr pFont; + XID newfont = 0; + if (pUnion) + { + NEXT_PTR(FontPtr, pFont); + } + else + { + NEXTVAL(XID, newfont) + pFont = (FontPtr)SecurityLookupIDByType(client, newfont, + RT_FONT, SecurityReadAccess); + } + if (pFont) + { + pFont->refcnt++; + if (pGC->font) + CloseFont(pGC->font, (Font)0); + pGC->font = pFont; + } + else + { + clientErrorValue = newfont; + error = BadFont; + } + break; + } + case GCSubwindowMode: + { + unsigned int newclipmode; + NEXTVAL(unsigned int, newclipmode); + if (newclipmode <= IncludeInferiors) + pGC->subWindowMode = newclipmode; + else + { + clientErrorValue = newclipmode; + error = BadValue; + } + break; + } + case GCGraphicsExposures: + { + unsigned int newge; + NEXTVAL(unsigned int, newge); + if (newge <= xTrue) + pGC->graphicsExposures = newge; + else + { + clientErrorValue = newge; + error = BadValue; + } + break; + } + case GCClipXOrigin: + NEXTVAL(INT16, pGC->clipOrg.x); + break; + case GCClipYOrigin: + NEXTVAL(INT16, pGC->clipOrg.y); + break; + case GCClipMask: + { + Pixmap pid; + int clipType; + + if (pUnion) + { + NEXT_PTR(PixmapPtr, pPixmap); + } + else + { + NEXTVAL(Pixmap, pid) + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, RT_PIXMAP, SecurityReadAccess); + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + else if (!pUnion && (pid != None)) + { + clientErrorValue = pid; + error = BadPixmap; + } + if(error == Success) + { + (*pGC->funcs->ChangeClip)(pGC, clipType, + (pointer)pPixmap, 0); + } + break; + } + case GCDashOffset: + NEXTVAL(INT16, pGC->dashOffset); + break; + case GCDashList: + { + CARD8 newdash; + NEXTVAL(CARD8, newdash); + if (newdash == 4) + { + if (pGC->dash != DefaultDash) + { + xfree(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + } + } + else if (newdash != 0) + { + unsigned char *dash; + + dash = (unsigned char *)xalloc(2 * sizeof(unsigned char)); + if (dash) + { + if (pGC->dash != DefaultDash) + xfree(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = dash; + dash[0] = newdash; + dash[1] = newdash; + } + else + error = BadAlloc; + } + else + { + clientErrorValue = newdash; + error = BadValue; + } + break; + } + case GCArcMode: + { + unsigned int newarcmode; + NEXTVAL(unsigned int, newarcmode); + if (newarcmode <= ArcPieSlice) + pGC->arcMode = newarcmode; + else + { + clientErrorValue = newarcmode; + error = BadValue; + } + break; + } + default: + clientErrorValue = maskQ; + error = BadValue; + break; + } + } /* end while mask && !error */ + + if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) + { + if (!CreateDefaultTile (pGC)) + { + pGC->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pGC->funcs->ChangeGC)(pGC, maskQ); + return error; +} + +#undef NEXTVAL +#undef NEXT_PTR + +/* Publically defined entry to ChangeGC. Just calls dixChangeGC and tells + * it that all of the entries are constants or IDs */ +int +ChangeGC(pGC, mask, pval) + register GC *pGC; + register BITS32 mask; + XID *pval; +{ + return (dixChangeGC(NullClient, pGC, mask, pval, NULL)); +} + +/* DoChangeGC(pGC, mask, pval, fPointer) + mask is a set of bits indicating which values to change. + pval contains an appropriate value for each mask. + fPointer is true if the values for tiles, stipples, fonts or clipmasks + are pointers instead of IDs. Note: if you are passing pointers you + MUST declare the array of values as type pointer! Other data types + may not be large enough to hold pointers on some machines. Yes, + this means you have to cast to (XID *) when you pass the array to + DoChangeGC. Similarly, if you are not passing pointers (fPointer = 0) you + MUST declare the array as type XID (not unsigned long!), or again the wrong + size data type may be used. To avoid this cruftiness, use dixChangeGC + above. + + if there is an error, the value is marked as changed + anyway, which is probably wrong, but infrequent. + +NOTE: + all values sent over the protocol for ChangeGC requests are +32 bits long +*/ +int +DoChangeGC(pGC, mask, pval, fPointer) + register GC *pGC; + register BITS32 mask; + XID *pval; + int fPointer; +{ + if (fPointer) + /* XXX might be a problem on 64 bit big-endian servers */ + dixChangeGC(NullClient, pGC, mask, NULL, (ChangeGCValPtr)pval); + else + dixChangeGC(NullClient, pGC, mask, pval, NULL); +} + + +/* CreateGC(pDrawable, mask, pval, pStatus) + creates a default GC for the given drawable, using mask to fill + in any non-default values. + Returns a pointer to the new GC on success, NULL otherwise. + returns status of non-default fields in pStatus +BUG: + should check for failure to create default tile + +*/ + +static GCPtr +AllocateGC(pScreen) + ScreenPtr pScreen; +{ + GCPtr pGC; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pGC = (GCPtr)xalloc(pScreen->totalGCSize); + if (pGC) + { + ppriv = (DevUnion *)(pGC + 1); + pGC->devPrivates = ppriv; + sizes = pScreen->GCPrivateSizes; + ptr = (char *)(ppriv + pScreen->GCPrivateLen); + for (i = pScreen->GCPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pGC; +} + +GCPtr +CreateGC(pDrawable, mask, pval, pStatus) + DrawablePtr pDrawable; + BITS32 mask; + XID *pval; + int *pStatus; +{ + register GCPtr pGC; + extern FontPtr defaultFont; + + pGC = AllocateGC(pDrawable->pScreen); + if (!pGC) + { + *pStatus = BadAlloc; + return (GCPtr)NULL; + } + + pGC->pScreen = pDrawable->pScreen; + pGC->depth = pDrawable->depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = GC_CHANGE_SERIAL_BIT; + pGC->funcs = 0; + + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + if (mask & GCForeground) + { + /* + * magic special case -- ChangeGC checks for this condition + * and snags the Foreground value to create a pseudo default-tile + */ + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = NullPixmap; + } + else + { + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + } + + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->clientClip = (pointer)NULL; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->dashOffset = 0; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + /* use the default font and stipple */ + pGC->font = defaultFont; + defaultFont->refcnt++; + pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; + pGC->stipple->refcnt++; + + pGC->stateChanges = (1 << GCLastBit+1) - 1; + if (!(*pGC->pScreen->CreateGC)(pGC)) + *pStatus = BadAlloc; + else if (mask) + *pStatus = ChangeGC(pGC, mask, pval); + else + *pStatus = Success; + if (*pStatus != Success) + { + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + pGC->tileIsPixel = TRUE; /* undo special case */ + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + + return (pGC); +} + +static Bool +CreateDefaultTile (pGC) + GCPtr pGC; +{ + XID tmpval[3]; + PixmapPtr pTile; + GCPtr pgcScratch; + xRectangle rect; + CARD16 w, h; + + w = 1; + h = 1; + (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); + pTile = (PixmapPtr) + (*pGC->pScreen->CreatePixmap)(pGC->pScreen, + w, h, pGC->depth); + pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); + if (!pTile || !pgcScratch) + { + if (pTile) + (*pTile->drawable.pScreen->DestroyPixmap)(pTile); + if (pgcScratch) + FreeScratchGC(pgcScratch); + return FALSE; + } + tmpval[0] = GXcopy; + tmpval[1] = pGC->tile.pixel; + tmpval[2] = FillSolid; + (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, + tmpval); + ValidateGC((DrawablePtr)pTile, pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); + /* Always remember to free the scratch graphics context after use. */ + FreeScratchGC(pgcScratch); + + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pTile; + return TRUE; +} + +int +CopyGC(pgcSrc, pgcDst, mask) + register GC *pgcSrc; + register GC *pgcDst; + register BITS32 mask; +{ + register BITS32 index; + BITS32 maskQ; + int error = 0; + + if (pgcSrc == pgcDst) + return Success; + pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pgcDst->stateChanges |= mask; + maskQ = mask; + while (mask) + { + index = (BITS32) lowbit (mask); + mask &= ~index; + switch (index) + { + case GCFunction: + pgcDst->alu = pgcSrc->alu; + break; + case GCPlaneMask: + pgcDst->planemask = pgcSrc->planemask; + break; + case GCForeground: + pgcDst->fgPixel = pgcSrc->fgPixel; + break; + case GCBackground: + pgcDst->bgPixel = pgcSrc->bgPixel; + break; + case GCLineWidth: + pgcDst->lineWidth = pgcSrc->lineWidth; + break; + case GCLineStyle: + pgcDst->lineStyle = pgcSrc->lineStyle; + break; + case GCCapStyle: + pgcDst->capStyle = pgcSrc->capStyle; + break; + case GCJoinStyle: + pgcDst->joinStyle = pgcSrc->joinStyle; + break; + case GCFillStyle: + pgcDst->fillStyle = pgcSrc->fillStyle; + break; + case GCFillRule: + pgcDst->fillRule = pgcSrc->fillRule; + break; + case GCTile: + { + if (EqualPixUnion(pgcDst->tileIsPixel, + pgcDst->tile, + pgcSrc->tileIsPixel, + pgcSrc->tile)) + { + break; + } + if (!pgcDst->tileIsPixel) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); + pgcDst->tileIsPixel = pgcSrc->tileIsPixel; + pgcDst->tile = pgcSrc->tile; + if (!pgcDst->tileIsPixel) + pgcDst->tile.pixmap->refcnt++; + break; + } + case GCStipple: + { + if (pgcDst->stipple == pgcSrc->stipple) + break; + if (pgcDst->stipple) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); + pgcDst->stipple = pgcSrc->stipple; + if (pgcDst->stipple) + pgcDst->stipple->refcnt ++; + break; + } + case GCTileStipXOrigin: + pgcDst->patOrg.x = pgcSrc->patOrg.x; + break; + case GCTileStipYOrigin: + pgcDst->patOrg.y = pgcSrc->patOrg.y; + break; + case GCFont: + if (pgcDst->font == pgcSrc->font) + break; + if (pgcDst->font) + CloseFont(pgcDst->font, (Font)0); + if ((pgcDst->font = pgcSrc->font) != NullFont) + (pgcDst->font)->refcnt++; + break; + case GCSubwindowMode: + pgcDst->subWindowMode = pgcSrc->subWindowMode; + break; + case GCGraphicsExposures: + pgcDst->graphicsExposures = pgcSrc->graphicsExposures; + break; + case GCClipXOrigin: + pgcDst->clipOrg.x = pgcSrc->clipOrg.x; + break; + case GCClipYOrigin: + pgcDst->clipOrg.y = pgcSrc->clipOrg.y; + break; + case GCClipMask: + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + break; + case GCDashOffset: + pgcDst->dashOffset = pgcSrc->dashOffset; + break; + case GCDashList: + if (pgcSrc->dash == DefaultDash) + { + if (pgcDst->dash != DefaultDash) + { + xfree(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = pgcSrc->dash; + } + } + else + { + unsigned char *dash; + unsigned int i; + + dash = (unsigned char *)xalloc(pgcSrc->numInDashList * + sizeof(unsigned char)); + if (dash) + { + if (pgcDst->dash != DefaultDash) + xfree(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = dash; + for (i=0; inumInDashList; i++) + dash[i] = pgcSrc->dash[i]; + } + else + error = BadAlloc; + } + break; + case GCArcMode: + pgcDst->arcMode = pgcSrc->arcMode; + break; + default: + clientErrorValue = maskQ; + error = BadValue; + break; + } + } + if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) + { + if (!CreateDefaultTile (pgcDst)) + { + pgcDst->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); + return error; +} + +/***************** + * FreeGC + * does the diX part of freeing the characteristics in the GC + ***************/ + +/*ARGSUSED*/ +int +FreeGC(value, gid) + pointer value; /* must conform to DeleteType */ + XID gid; +{ + GCPtr pGC = (GCPtr)value; + + CloseFont(pGC->font, (Font)0); + (* pGC->funcs->DestroyClip)(pGC); + + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + + (*pGC->funcs->DestroyGC) (pGC); + if (pGC->dash != DefaultDash) + xfree(pGC->dash); + xfree(pGC); + return(Success); +} + +void +SetGCMask(pGC, selectMask, newDataMask) + GCPtr pGC; + Mask selectMask; + Mask newDataMask; +{ + pGC->stateChanges = (~selectMask & pGC->stateChanges) | + (selectMask & newDataMask); + if (selectMask & newDataMask) + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; +} + + + +/* CreateScratchGC(pScreen, depth) + like CreateGC, but doesn't do the default tile or stipple, +since we can't create them without already having a GC. any code +using the tile or stipple has to set them explicitly anyway, +since the state of the scratch gc is unknown. This is OK +because ChangeGC() has to be able to deal with NULL tiles and +stipples anyway (in case the CreateGC() call has provided a +value for them -- we can't set the default tile until the +client-supplied attributes are installed, since the fgPixel +is what fills the default tile. (maybe this comment should +go with CreateGC() or ChangeGC().) +*/ + +GCPtr +CreateScratchGC(pScreen, depth) + ScreenPtr pScreen; + unsigned depth; +{ + register GCPtr pGC; + extern FontPtr defaultFont; + + pGC = AllocateGC(pScreen); + if (!pGC) + return (GCPtr)NULL; + + pGC->pScreen = pScreen; + pGC->depth = depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = 0; + + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + pGC->font = defaultFont; + if ( pGC->font) /* necessary, because open of default font could fail */ + pGC->font->refcnt++; + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->dashOffset = 0; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + pGC->stateChanges = (1 << GCLastBit+1) - 1; + if (!(*pScreen->CreateGC)(pGC)) + { + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + return pGC; +} + +void +FreeGCperDepth(screenNum) + int screenNum; +{ + register int i; + register ScreenPtr pScreen; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + ppGC = pScreen->GCperDepth; + + for (i = 0; i <= pScreen->numDepths; i++) + (void)FreeGC(ppGC[i], (XID)0); + pScreen->rgf = ~0L; +} + + +Bool +CreateGCperDepth(screenNum) + int screenNum; +{ + register int i; + register ScreenPtr pScreen; + DepthPtr pDepth; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + pScreen->rgf = 0; + ppGC = pScreen->GCperDepth; + /* do depth 1 separately because it's not included in list */ + if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) + return FALSE; + ppGC[0]->graphicsExposures = FALSE; + + pDepth = pScreen->allowedDepths; + for (i=0; inumDepths; i++, pDepth++) + { + if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) + { + for (; i >= 0; i--) + (void)FreeGC(ppGC[i], (XID)0); + return FALSE; + } + ppGC[i+1]->graphicsExposures = FALSE; + } + return TRUE; +} + +Bool +CreateDefaultStipple(screenNum) + int screenNum; +{ + register ScreenPtr pScreen; + XID tmpval[3]; + xRectangle rect; + CARD16 w, h; + GCPtr pgcScratch; + + pScreen = screenInfo.screens[screenNum]; + + w = 16; + h = 16; + (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); + if (!(pScreen->PixmapPerDepth[0] = + (*pScreen->CreatePixmap)(pScreen, w, h, 1))) + return FALSE; + /* fill stipple with 1 */ + tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid; + pgcScratch = GetScratchGC(1, pScreen); + if (!pgcScratch) + { + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); + return FALSE; + } + (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); + ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], + pgcScratch, 1, &rect); + FreeScratchGC(pgcScratch); + return TRUE; +} + +void +FreeDefaultStipple(screenNum) + int screenNum; +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); +} + +int +SetDashes(pGC, offset, ndash, pdash) +register GCPtr pGC; +unsigned offset; +register unsigned ndash; +register unsigned char *pdash; +{ + register long i; + register unsigned char *p, *indash; + BITS32 maskQ = 0; + + i = ndash; + p = pdash; + while (i--) + { + if (!*p++) + { + /* dash segment must be > 0 */ + clientErrorValue = 0; + return BadValue; + } + } + + if (ndash & 1) + p = (unsigned char *)xalloc(2 * ndash * sizeof(unsigned char)); + else + p = (unsigned char *)xalloc(ndash * sizeof(unsigned char)); + if (!p) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + if (offset != pGC->dashOffset) + { + pGC->dashOffset = offset; + pGC->stateChanges |= GCDashOffset; + maskQ |= GCDashOffset; + } + + if (pGC->dash != DefaultDash) + xfree(pGC->dash); + pGC->numInDashList = ndash; + pGC->dash = p; + if (ndash & 1) + { + pGC->numInDashList += ndash; + indash = pdash; + i = ndash; + while (i--) + *p++ = *indash++; + } + while(ndash--) + *p++ = *pdash++; + pGC->stateChanges |= GCDashList; + maskQ |= GCDashList; + + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, maskQ); + return Success; +} + +int +VerifyRectOrder(nrects, prects, ordering) + int nrects; + xRectangle *prects; + int ordering; +{ + register xRectangle *prectP, *prectN; + register int i; + + switch(ordering) + { + case Unsorted: + return CT_UNSORTED; + case YSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if(prectN->y < prectP->y) + return -1; + } + return CT_YSORTED; + case YXSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y < prectP->y) || + ( (prectN->y == prectP->y) && + (prectN->x < prectP->x) ) ) + return -1; + } + return CT_YXSORTED; + case YXBanded: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y != prectP->y && + prectN->y < prectP->y + (int) prectP->height) || + ((prectN->y == prectP->y) && + (prectN->height != prectP->height || + prectN->x < prectP->x + (int) prectP->width))) + return -1; + } + return CT_YXBANDED; + } + return -1; +} + +int +SetClipRects(pGC, xOrigin, yOrigin, nrects, prects, ordering) + GCPtr pGC; + int xOrigin, yOrigin; + int nrects; + xRectangle *prects; + int ordering; +{ + int newct, size; + xRectangle *prectsNew; + + newct = VerifyRectOrder(nrects, prects, ordering); + if (newct < 0) + return(BadMatch); + size = nrects * sizeof(xRectangle); + prectsNew = (xRectangle *) xalloc(size); + if (!prectsNew && size) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + pGC->clipOrg.x = xOrigin; + pGC->stateChanges |= GCClipXOrigin; + + pGC->clipOrg.y = yOrigin; + pGC->stateChanges |= GCClipYOrigin; + + if (size) + memmove((char *)prectsNew, (char *)prects, size); + (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); + return Success; +} + + +/* + sets reasonable defaults + if we can get a pre-allocated one, use it and mark it as used. + if we can't, create one out of whole cloth (The Velveteen GC -- if + you use it often enough it will become real.) +*/ +GCPtr +GetScratchGC(depth, pScreen) + register unsigned depth; + register ScreenPtr pScreen; +{ + register int i; + register GCPtr pGC; + + for (i=0; i<=pScreen->numDepths; i++) + if ( pScreen->GCperDepth[i]->depth == depth && + !(pScreen->rgf & (1L << (i+1))) + ) + { + pScreen->rgf |= (1L << (i+1)); + pGC = (pScreen->GCperDepth[i]); + + pGC->alu = GXcopy; + pGC->planemask = ~0; + pGC->serialNumber = 0; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcChord; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = FALSE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + if (pGC->clientClipType != CT_NONE) + (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); + pGC->stateChanges = (1 << GCLastBit+1) - 1; + return pGC; + } + /* if we make it this far, need to roll our own */ + pGC = CreateScratchGC(pScreen, depth); + if (pGC) + pGC->graphicsExposures = FALSE; + return pGC; +} + +/* + if the gc to free is in the table of pre-existing ones, +mark it as available. + if not, free it for real +*/ +void +FreeScratchGC(pGC) + register GCPtr pGC; +{ + register ScreenPtr pScreen = pGC->pScreen; + register int i; + + for (i=0; i<=pScreen->numDepths; i++) + { + if ( pScreen->GCperDepth[i] == pGC) + { + pScreen->rgf &= ~(1L << (i+1)); + return; + } + } + (void)FreeGC(pGC, (GContext)0); +} diff --git a/dix/globals.c b/dix/globals.c new file mode 100644 index 000000000..fe45f64cd --- /dev/null +++ b/dix/globals.c @@ -0,0 +1,139 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + +/* $Xorg: globals.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "misc.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "input.h" +#include "dixfont.h" +#include "site.h" +#include "dixstruct.h" +#include "os.h" + +ScreenInfo screenInfo; +KeybdCtrl defaultKeyboardControl = { + DEFAULT_KEYBOARD_CLICK, + DEFAULT_BELL, + DEFAULT_BELL_PITCH, + DEFAULT_BELL_DURATION, + DEFAULT_AUTOREPEAT, + DEFAULT_AUTOREPEATS, + DEFAULT_LEDS, + 0}; + +PtrCtrl defaultPointerControl = { + DEFAULT_PTR_NUMERATOR, + DEFAULT_PTR_DENOMINATOR, + DEFAULT_PTR_THRESHOLD, + 0}; + +ClientPtr *clients; +ClientPtr serverClient; +int currentMaxClients; /* current size of clients array */ + +WindowPtr *WindowTable; + +unsigned long globalSerialNumber = 0; +unsigned long serverGeneration = 0; + +/* these next four are initialized in main.c */ +CARD32 ScreenSaverTime; +CARD32 ScreenSaverInterval; +int ScreenSaverBlanking; +int ScreenSaverAllowExposures; + +#define DEFAULT_STANDBY_TIME DEFAULT_SCREEN_SAVER_TIME * 2 +#define DEFAULT_SUSPEND_TIME DEFAULT_SCREEN_SAVER_TIME * 3 +#define DEFAULT_OFF_TIME DEFAULT_SCREEN_SAVER_TIME * 4 +#ifdef DPMSExtension +CARD32 DPMSStandbyTime = DEFAULT_STANDBY_TIME; +CARD32 DPMSSuspendTime = DEFAULT_SUSPEND_TIME; +CARD32 DPMSOffTime = DEFAULT_OFF_TIME; +CARD16 DPMSPowerLevel = 0; +BOOL DPMSEnabled = FALSE; +BOOL DPMSEnabledSwitch = FALSE; /* these denote the DPMS command line */ +BOOL DPMSDisabledSwitch = FALSE; /* switch states */ +BOOL DPMSCapableFlag = FALSE; +#endif + +CARD32 defaultScreenSaverTime = DEFAULT_SCREEN_SAVER_TIME; +CARD32 defaultScreenSaverInterval = DEFAULT_SCREEN_SAVER_INTERVAL; +int defaultScreenSaverBlanking = DEFAULT_SCREEN_SAVER_BLANKING; +int defaultScreenSaverAllowExposures = DEFAULT_SCREEN_SAVER_EXPOSURES; +#ifndef NOLOGOHACK +int logoScreenSaver = DEFAULT_LOGO_SCREEN_SAVER; +#endif + +char *defaultFontPath = COMPILEDDEFAULTFONTPATH; +char *defaultTextFont = COMPILEDDEFAULTFONT; +char *defaultCursorFont = COMPILEDCURSORFONT; +char *rgbPath = RGB_DB; +char *defaultDisplayClass = COMPILEDDISPLAYCLASS; +FontPtr defaultFont; /* not declared in dix.h to avoid including font.h in + every compilation of dix code */ +CursorPtr rootCursor; +ClientPtr requestingClient; /* XXX this should be obsolete now, remove? */ + +TimeStamp currentTime; +TimeStamp lastDeviceEventTime; + +Bool permitOldBugs = FALSE; /* turn off some error checking, to permit certain + * old broken clients (like R2/R3 xterms) to work + */ + +int defaultColorVisualClass = -1; +int monitorResolution = 0; + +char *display; + +CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND; +int argcGlobal; +char **argvGlobal; diff --git a/dix/glyphcurs.c b/dix/glyphcurs.c new file mode 100644 index 000000000..630e98fa3 --- /dev/null +++ b/dix/glyphcurs.c @@ -0,0 +1,197 @@ +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +************************************************************************/ + +/* $Xorg: glyphcurs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "misc.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(pfont, ch, cm, ppbits) + FontPtr pfont; + unsigned int ch; + register CursorMetricPtr cm; + unsigned char **ppbits; +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = (PixmapPtr)(*pScreen->CreatePixmap)(pScreen, cm->width, + cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + (*pScreen->DestroyPixmap)(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + /* fill the pixmap with 0 */ + gcval[0].val = GXcopy; + gcval[1].val = 0; + gcval[2].ptr = (pointer)pfont; + dixChangeGC(NullClient, pGC, GCFunction | GCForeground | GCFont, + NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyFillRect)((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + dixChangeGC(NullClient, pGC, GCForeground, NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyText16)((DrawablePtr)ppix, pGC, cm->xhot, cm->yhot, + 1, (unsigned short *)char2b); + (*pScreen->GetImage)((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + (*pScreen->DestroyPixmap)(ppix); + return Success; +} + + +Bool +CursorMetricsFromGlyph( pfont, ch, cm) + register FontPtr pfont; + unsigned ch; + register CursorMetricPtr cm; +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} diff --git a/dix/grabs.c b/dix/grabs.c new file mode 100644 index 000000000..80422f53f --- /dev/null +++ b/dix/grabs.c @@ -0,0 +1,441 @@ +/* $Xorg: grabs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +*/ + +#include "X.h" +#include "misc.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "windowstr.h" +#include "inputstr.h" +#include "cursorstr.h" + +extern InputInfo inputInfo; + +#define BITMASK(i) (((Mask)1) << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +GrabPtr +CreateGrab(client, device, window, eventMask, ownerEvents, keyboardMode, + pointerMode, modDevice, modifiers, type, keybut, confineTo, cursor) + int client; + DeviceIntPtr device; + WindowPtr window; + Mask eventMask; + Bool ownerEvents, keyboardMode, pointerMode; + DeviceIntPtr modDevice; + unsigned short modifiers; + int type; + KeyCode keybut; /* key or button */ + WindowPtr confineTo; + CursorPtr cursor; +{ + GrabPtr grab; + + grab = (GrabPtr)xalloc(sizeof(GrabRec)); + if (!grab) + return (GrabPtr)NULL; + grab->resource = FakeClientID(client); + grab->device = device; + grab->coreGrab = ((device == inputInfo.keyboard) || + (device == inputInfo.pointer)); + grab->window = window; + grab->eventMask = eventMask; + grab->ownerEvents = ownerEvents; + grab->keyboardMode = keyboardMode; + grab->pointerMode = pointerMode; + grab->modifiersDetail.exact = modifiers; + grab->modifiersDetail.pMask = NULL; + grab->modifierDevice = modDevice; + grab->coreMods = ((modDevice == inputInfo.keyboard) || + (modDevice == inputInfo.pointer)); + grab->type = type; + grab->detail.exact = keybut; + grab->detail.pMask = NULL; + grab->confineTo = confineTo; + grab->cursor = cursor; + if (cursor) + cursor->refcnt++; + return grab; + +} + +static void +FreeGrab(pGrab) + GrabPtr pGrab; +{ + if (pGrab->modifiersDetail.pMask != NULL) + xfree(pGrab->modifiersDetail.pMask); + + if (pGrab->detail.pMask != NULL) + xfree(pGrab->detail.pMask); + + if (pGrab->cursor) + FreeCursor(pGrab->cursor, (Cursor)0); + + xfree(pGrab); +} + +/*ARGSUSED*/ +int +DeletePassiveGrab(value, id) + pointer value; + XID id; +{ + register GrabPtr g, prev; + GrabPtr pGrab = (GrabPtr)value; + + /* it is OK if the grab isn't found */ + prev = 0; + for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next) + { + if (pGrab == g) + { + if (prev) + prev->next = g->next; + else + if (!(pGrab->window->optional->passiveGrabs = g->next)) + CheckWindowOptionalNeed (pGrab->window); + break; + } + prev = g; + } + FreeGrab(pGrab); + return Success; +} + +static Mask * +DeleteDetailFromMask(pDetailMask, detail) + Mask *pDetailMask; + unsigned short detail; +{ + register Mask *mask; + register int i; + + mask = (Mask *)xalloc(sizeof(Mask) * MasksPerDetailMask); + if (mask) + { + if (pDetailMask) + for (i = 0; i < MasksPerDetailMask; i++) + mask[i]= pDetailMask[i]; + else + for (i = 0; i < MasksPerDetailMask; i++) + mask[i]= ~0L; + BITCLEAR(mask, detail); + } + return mask; +} + +static Bool +IsInGrabMask(firstDetail, secondDetail, exception) + DetailRec firstDetail, secondDetail; + unsigned short exception; +{ + if (firstDetail.exact == exception) + { + if (firstDetail.pMask == NULL) + return TRUE; + + /* (at present) never called with two non-null pMasks */ + if (secondDetail.exact == exception) + return FALSE; + + if (GETBIT(firstDetail.pMask, secondDetail.exact)) + return TRUE; + } + + return FALSE; +} + +static Bool +IdenticalExactDetails(firstExact, secondExact, exception) + unsigned short firstExact, secondExact, exception; +{ + if ((firstExact == exception) || (secondExact == exception)) + return FALSE; + + if (firstExact == secondExact) + return TRUE; + + return FALSE; +} + +static Bool +DetailSupersedesSecond(firstDetail, secondDetail, exception) + DetailRec firstDetail, secondDetail; + unsigned short exception; +{ + if (IsInGrabMask(firstDetail, secondDetail, exception)) + return TRUE; + + if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact, + exception)) + return TRUE; + + return FALSE; +} + +static Bool +GrabSupersedesSecond(pFirstGrab, pSecondGrab) + GrabPtr pFirstGrab, pSecondGrab; +{ + if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail, + pSecondGrab->modifiersDetail, + (unsigned short)AnyModifier)) + return FALSE; + + if (DetailSupersedesSecond(pFirstGrab->detail, + pSecondGrab->detail, (unsigned short)AnyKey)) + return TRUE; + + return FALSE; +} + +Bool +GrabMatchesSecond(pFirstGrab, pSecondGrab) + GrabPtr pFirstGrab, pSecondGrab; +{ + if ((pFirstGrab->device != pSecondGrab->device) || + (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) || + (pFirstGrab->type != pSecondGrab->type)) + return FALSE; + + if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) || + GrabSupersedesSecond(pSecondGrab, pFirstGrab)) + return TRUE; + + if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail, + (unsigned short)AnyKey) + && + DetailSupersedesSecond(pFirstGrab->modifiersDetail, + pSecondGrab->modifiersDetail, + (unsigned short)AnyModifier)) + return TRUE; + + if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail, + (unsigned short)AnyKey) + && + DetailSupersedesSecond(pSecondGrab->modifiersDetail, + pFirstGrab->modifiersDetail, + (unsigned short)AnyModifier)) + return TRUE; + + return FALSE; +} + +int +AddPassiveGrabToList(pGrab) + GrabPtr pGrab; +{ + GrabPtr grab; + + for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next) + { + if (GrabMatchesSecond(pGrab, grab)) + { + if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource)) + { + FreeGrab(pGrab); + return BadAccess; + } + } + } + + if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window)) + { + FreeGrab(pGrab); + return BadAlloc; + } + pGrab->next = pGrab->window->optional->passiveGrabs; + pGrab->window->optional->passiveGrabs = pGrab; + if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab)) + return Success; + return BadAlloc; +} + +/* the following is kinda complicated, because we need to be able to back out + * if any allocation fails + */ + +Bool +DeletePassiveGrabFromList(pMinuendGrab) + GrabPtr pMinuendGrab; +{ + register GrabPtr grab; + GrabPtr *deletes, *adds; + Mask ***updates, **details; + int i, ndels, nadds, nups; + Bool ok; + +#define UPDATE(mask,exact) \ + if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \ + ok = FALSE; \ + else \ + updates[nups++] = &(mask) + + i = 0; + for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next) + i++; + if (!i) + return TRUE; + deletes = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr)); + adds = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr)); + updates = (Mask ***)ALLOCATE_LOCAL(i * sizeof(Mask **)); + details = (Mask **)ALLOCATE_LOCAL(i * sizeof(Mask *)); + if (!deletes || !adds || !updates || !details) + { + if (details) DEALLOCATE_LOCAL(details); + if (updates) DEALLOCATE_LOCAL(updates); + if (adds) DEALLOCATE_LOCAL(adds); + if (deletes) DEALLOCATE_LOCAL(deletes); + return FALSE; + } + ndels = nadds = nups = 0; + ok = TRUE; + for (grab = wPassiveGrabs(pMinuendGrab->window); + grab && ok; + grab = grab->next) + { + if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) || + !GrabMatchesSecond(grab, pMinuendGrab)) + continue; + if (GrabSupersedesSecond(pMinuendGrab, grab)) + { + deletes[ndels++] = grab; + } + else if ((grab->detail.exact == AnyKey) + && (grab->modifiersDetail.exact != AnyModifier)) + { + UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); + } + else if ((grab->modifiersDetail.exact == AnyModifier) + && (grab->detail.exact != AnyKey)) + { + UPDATE(grab->modifiersDetail.pMask, + pMinuendGrab->modifiersDetail.exact); + } + else if ((pMinuendGrab->detail.exact != AnyKey) + && (pMinuendGrab->modifiersDetail.exact != AnyModifier)) + { + GrabPtr pNewGrab; + + UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); + + pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device, + grab->window, (Mask)grab->eventMask, + (Bool)grab->ownerEvents, + (Bool)grab->keyboardMode, + (Bool)grab->pointerMode, + grab->modifierDevice, + AnyModifier, (int)grab->type, + pMinuendGrab->detail.exact, + grab->confineTo, grab->cursor); + if (!pNewGrab) + ok = FALSE; + else if (!(pNewGrab->modifiersDetail.pMask = + DeleteDetailFromMask(grab->modifiersDetail.pMask, + pMinuendGrab->modifiersDetail.exact)) + || + (!pNewGrab->window->optional && + !MakeWindowOptional(pNewGrab->window))) + { + FreeGrab(pNewGrab); + ok = FALSE; + } + else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB, + (pointer)pNewGrab)) + ok = FALSE; + else + adds[nadds++] = pNewGrab; + } + else if (pMinuendGrab->detail.exact == AnyKey) + { + UPDATE(grab->modifiersDetail.pMask, + pMinuendGrab->modifiersDetail.exact); + } + else + { + UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); + } + } + + if (!ok) + { + for (i = 0; i < nadds; i++) + FreeResource(adds[i]->resource, RT_NONE); + for (i = 0; i < nups; i++) + xfree(details[i]); + } + else + { + for (i = 0; i < ndels; i++) + FreeResource(deletes[i]->resource, RT_NONE); + for (i = 0; i < nadds; i++) + { + grab = adds[i]; + grab->next = grab->window->optional->passiveGrabs; + grab->window->optional->passiveGrabs = grab; + } + for (i = 0; i < nups; i++) + { + xfree(*updates[i]); + *updates[i] = details[i]; + } + } + DEALLOCATE_LOCAL(details); + DEALLOCATE_LOCAL(updates); + DEALLOCATE_LOCAL(adds); + DEALLOCATE_LOCAL(deletes); + return ok; + +#undef UPDATE +} diff --git a/dix/initatoms.c b/dix/initatoms.c new file mode 100644 index 000000000..f1734a734 --- /dev/null +++ b/dix/initatoms.c @@ -0,0 +1,79 @@ +/* THIS IS A GENERATED FILE + * + * Do not change! Changing this file implies a protocol change! + */ + +#include "X.h" +#include "Xatom.h" +extern Atom MakeAtom(); +MakePredeclaredAtoms() +{ + if (MakeAtom("PRIMARY", 7, 1) != XA_PRIMARY) AtomError(); + if (MakeAtom("SECONDARY", 9, 1) != XA_SECONDARY) AtomError(); + if (MakeAtom("ARC", 3, 1) != XA_ARC) AtomError(); + if (MakeAtom("ATOM", 4, 1) != XA_ATOM) AtomError(); + if (MakeAtom("BITMAP", 6, 1) != XA_BITMAP) AtomError(); + if (MakeAtom("CARDINAL", 8, 1) != XA_CARDINAL) AtomError(); + if (MakeAtom("COLORMAP", 8, 1) != XA_COLORMAP) AtomError(); + if (MakeAtom("CURSOR", 6, 1) != XA_CURSOR) AtomError(); + if (MakeAtom("CUT_BUFFER0", 11, 1) != XA_CUT_BUFFER0) AtomError(); + if (MakeAtom("CUT_BUFFER1", 11, 1) != XA_CUT_BUFFER1) AtomError(); + if (MakeAtom("CUT_BUFFER2", 11, 1) != XA_CUT_BUFFER2) AtomError(); + if (MakeAtom("CUT_BUFFER3", 11, 1) != XA_CUT_BUFFER3) AtomError(); + if (MakeAtom("CUT_BUFFER4", 11, 1) != XA_CUT_BUFFER4) AtomError(); + if (MakeAtom("CUT_BUFFER5", 11, 1) != XA_CUT_BUFFER5) AtomError(); + if (MakeAtom("CUT_BUFFER6", 11, 1) != XA_CUT_BUFFER6) AtomError(); + if (MakeAtom("CUT_BUFFER7", 11, 1) != XA_CUT_BUFFER7) AtomError(); + if (MakeAtom("DRAWABLE", 8, 1) != XA_DRAWABLE) AtomError(); + if (MakeAtom("FONT", 4, 1) != XA_FONT) AtomError(); + if (MakeAtom("INTEGER", 7, 1) != XA_INTEGER) AtomError(); + if (MakeAtom("PIXMAP", 6, 1) != XA_PIXMAP) AtomError(); + if (MakeAtom("POINT", 5, 1) != XA_POINT) AtomError(); + if (MakeAtom("RECTANGLE", 9, 1) != XA_RECTANGLE) AtomError(); + if (MakeAtom("RESOURCE_MANAGER", 16, 1) != XA_RESOURCE_MANAGER) AtomError(); + if (MakeAtom("RGB_COLOR_MAP", 13, 1) != XA_RGB_COLOR_MAP) AtomError(); + if (MakeAtom("RGB_BEST_MAP", 12, 1) != XA_RGB_BEST_MAP) AtomError(); + if (MakeAtom("RGB_BLUE_MAP", 12, 1) != XA_RGB_BLUE_MAP) AtomError(); + if (MakeAtom("RGB_DEFAULT_MAP", 15, 1) != XA_RGB_DEFAULT_MAP) AtomError(); + if (MakeAtom("RGB_GRAY_MAP", 12, 1) != XA_RGB_GRAY_MAP) AtomError(); + if (MakeAtom("RGB_GREEN_MAP", 13, 1) != XA_RGB_GREEN_MAP) AtomError(); + if (MakeAtom("RGB_RED_MAP", 11, 1) != XA_RGB_RED_MAP) AtomError(); + if (MakeAtom("STRING", 6, 1) != XA_STRING) AtomError(); + if (MakeAtom("VISUALID", 8, 1) != XA_VISUALID) AtomError(); + if (MakeAtom("WINDOW", 6, 1) != XA_WINDOW) AtomError(); + if (MakeAtom("WM_COMMAND", 10, 1) != XA_WM_COMMAND) AtomError(); + if (MakeAtom("WM_HINTS", 8, 1) != XA_WM_HINTS) AtomError(); + if (MakeAtom("WM_CLIENT_MACHINE", 17, 1) != XA_WM_CLIENT_MACHINE) AtomError(); + if (MakeAtom("WM_ICON_NAME", 12, 1) != XA_WM_ICON_NAME) AtomError(); + if (MakeAtom("WM_ICON_SIZE", 12, 1) != XA_WM_ICON_SIZE) AtomError(); + if (MakeAtom("WM_NAME", 7, 1) != XA_WM_NAME) AtomError(); + if (MakeAtom("WM_NORMAL_HINTS", 15, 1) != XA_WM_NORMAL_HINTS) AtomError(); + if (MakeAtom("WM_SIZE_HINTS", 13, 1) != XA_WM_SIZE_HINTS) AtomError(); + if (MakeAtom("WM_ZOOM_HINTS", 13, 1) != XA_WM_ZOOM_HINTS) AtomError(); + if (MakeAtom("MIN_SPACE", 9, 1) != XA_MIN_SPACE) AtomError(); + if (MakeAtom("NORM_SPACE", 10, 1) != XA_NORM_SPACE) AtomError(); + if (MakeAtom("MAX_SPACE", 9, 1) != XA_MAX_SPACE) AtomError(); + if (MakeAtom("END_SPACE", 9, 1) != XA_END_SPACE) AtomError(); + if (MakeAtom("SUPERSCRIPT_X", 13, 1) != XA_SUPERSCRIPT_X) AtomError(); + if (MakeAtom("SUPERSCRIPT_Y", 13, 1) != XA_SUPERSCRIPT_Y) AtomError(); + if (MakeAtom("SUBSCRIPT_X", 11, 1) != XA_SUBSCRIPT_X) AtomError(); + if (MakeAtom("SUBSCRIPT_Y", 11, 1) != XA_SUBSCRIPT_Y) AtomError(); + if (MakeAtom("UNDERLINE_POSITION", 18, 1) != XA_UNDERLINE_POSITION) AtomError(); + if (MakeAtom("UNDERLINE_THICKNESS", 19, 1) != XA_UNDERLINE_THICKNESS) AtomError(); + if (MakeAtom("STRIKEOUT_ASCENT", 16, 1) != XA_STRIKEOUT_ASCENT) AtomError(); + if (MakeAtom("STRIKEOUT_DESCENT", 17, 1) != XA_STRIKEOUT_DESCENT) AtomError(); + if (MakeAtom("ITALIC_ANGLE", 12, 1) != XA_ITALIC_ANGLE) AtomError(); + if (MakeAtom("X_HEIGHT", 8, 1) != XA_X_HEIGHT) AtomError(); + if (MakeAtom("QUAD_WIDTH", 10, 1) != XA_QUAD_WIDTH) AtomError(); + if (MakeAtom("WEIGHT", 6, 1) != XA_WEIGHT) AtomError(); + if (MakeAtom("POINT_SIZE", 10, 1) != XA_POINT_SIZE) AtomError(); + if (MakeAtom("RESOLUTION", 10, 1) != XA_RESOLUTION) AtomError(); + if (MakeAtom("COPYRIGHT", 9, 1) != XA_COPYRIGHT) AtomError(); + if (MakeAtom("NOTICE", 6, 1) != XA_NOTICE) AtomError(); + if (MakeAtom("FONT_NAME", 9, 1) != XA_FONT_NAME) AtomError(); + if (MakeAtom("FAMILY_NAME", 11, 1) != XA_FAMILY_NAME) AtomError(); + if (MakeAtom("FULL_NAME", 9, 1) != XA_FULL_NAME) AtomError(); + if (MakeAtom("CAP_HEIGHT", 10, 1) != XA_CAP_HEIGHT) AtomError(); + if (MakeAtom("WM_CLASS", 8, 1) != XA_WM_CLASS) AtomError(); + if (MakeAtom("WM_TRANSIENT_FOR", 16, 1) != XA_WM_TRANSIENT_FOR) AtomError(); +} diff --git a/dix/main.c b/dix/main.c new file mode 100644 index 000000000..5b50ea94f --- /dev/null +++ b/dix/main.c @@ -0,0 +1,678 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: main.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "Xos.h" /* for unistd.h */ +#include "Xproto.h" +#include "scrnintstr.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "extension.h" +#include "colormap.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "font.h" +#include "opaque.h" +#include "servermd.h" +#include "site.h" +#include "dixfont.h" + +extern CARD32 defaultScreenSaverTime; +extern CARD32 defaultScreenSaverInterval; +extern int defaultScreenSaverBlanking; +extern int defaultScreenSaverAllowExposures; + +#ifdef DPMSExtension +#include "dpms.h" +extern BOOL DPMSCapableFlag; +extern BOOL DPMSEnabled; +#endif + +void ddxGiveUp(); + +extern int InitClientPrivates( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void Dispatch( +#if NeedFunctionPrototypes + void +#endif +); + +extern char *display; +char *ConnectionInfo; +xConnSetupPrefix connSetupPrefix; + +extern WindowPtr *WindowTable; +extern FontPtr defaultFont; +extern int screenPrivateCount; + +extern void InitProcVectors(); +extern void InitEvents(); +extern void DefineInitialRootWindow(); +extern Bool CreateGCperDepthArray(); + +static Bool CreateConnectionBlock( +#if NeedFunctionPrototypes + void +#endif +); + +static void FreeScreen( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/ +#endif +); + +PaddingInfo PixmapWidthPaddingInfo[33]; + +#ifdef INTERNAL_VS_EXTERNAL_PADDING +/* add padding info for 32-bit interface. PutImage and GetImage will + * work on 32-bit padding while the rest of the server will work + * on 64-bit padding (Alpha). + */ +PaddingInfo PixmapWidthPaddingInfoProto[33]; +#endif + +int connBlockScreenStart; + +static int restart = 0; + +void +NotImplemented() +{ + FatalError("Not implemented"); +} + +/* + * This array encodes the answer to the question "what is the log base 2 + * of the number of pixels that fit in a scanline pad unit?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int answer[6][4] = { + /* pad pad pad pad*/ + /* 8 16 32 64 */ + + { 3, 4, 5 , 6 }, /* 1 bit per pixel */ + { 1, 2, 3 , 4 }, /* 4 bits per pixel */ + { 0, 1, 2 , 3 }, /* 8 bits per pixel */ + { ~0, 0, 1 , 2 }, /* 16 bits per pixel */ + { ~0, ~0, 0 , 1 }, /* 24 bits per pixel */ + { ~0, ~0, 0 , 1 } /* 32 bits per pixel */ +}; + +/* + * This array gives the answer to the question "what is the first index for + * the answer array above given the number of bits per pixel?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int indexForBitsPerPixel[ 33 ] = { + ~0, 0, ~0, ~0, /* 1 bit per pixel */ + 1, ~0, ~0, ~0, /* 4 bits per pixel */ + 2, ~0, ~0, ~0, /* 8 bits per pixel */ + ~0,~0, ~0, ~0, + 3, ~0, ~0, ~0, /* 16 bits per pixel */ + ~0,~0, ~0, ~0, + 4, ~0, ~0, ~0, /* 24 bits per pixel */ + ~0,~0, ~0, ~0, + 5 /* 32 bits per pixel */ +}; + +/* + * This array gives the answer to the question "what is the second index for + * the answer array above given the number of bits per scanline pad unit?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int indexForScanlinePad[ 65 ] = { + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 3 /* 64 bits per scanline pad unit */ +}; + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int i, j, k; + HWEventQueueType alwaysCheckForInput[2]; + + /* Notice if we're restart. Probably this is because we jumped through + * uninitialized pointer */ + if (restart) + FatalError("server restarted. Jumped through uninitialized pointer?\n"); + else + restart = 1; + +#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS + ExpandCommandLine(&argc, &argv); +#endif + +#ifdef _SC_OPEN_MAX + /* if sysconf(_SC_OPEN_MAX) is supported, at runtime MaxClients will be + * reassigned instead of using MAXSOCKS */ + if (MaxClients == 0) + MaxClients = MIN(MAXCLIENTS, sysconf(_SC_OPEN_MAX)); +#endif + + /* These are needed by some routines which are called from interrupt + * handlers, thus have no direct calling path back to main and thus + * can't be passed argc, argv as parameters */ + argcGlobal = argc; + argvGlobal = argv; + display = "0"; + ProcessCommandLine(argc, argv); + + alwaysCheckForInput[0] = 0; + alwaysCheckForInput[1] = 1; + while(1) + { + serverGeneration++; + ScreenSaverTime = defaultScreenSaverTime; + ScreenSaverInterval = defaultScreenSaverInterval; + ScreenSaverBlanking = defaultScreenSaverBlanking; + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + InitBlockAndWakeupHandlers(); + /* Perform any operating system dependent initializations you'd like */ + OsInit(); + if(serverGeneration == 1) + { + CreateWellKnownSockets(); + InitProcVectors(); + clients = (ClientPtr *)xalloc(MAXCLIENTS * sizeof(ClientPtr)); + if (!clients) + FatalError("couldn't create client array"); + for (i=1; iCreateScreenResources && + !(*pScreen->CreateScreenResources)(pScreen)) + FatalError("failed to create screen resources"); + if (!CreateGCperDepth(i)) + FatalError("failed to create scratch GCs"); + if (!CreateDefaultStipple(i)) + FatalError("failed to create default stipple"); + if (!CreateRootWindow(pScreen)) + FatalError("failed to create root window"); + } + InitInput(argc, argv); + if (InitAndStartDevices() != Success) + FatalError("failed to initialize core devices"); + + InitFonts(); + if (SetDefaultFontPath(defaultFontPath) != Success) + ErrorF("failed to set default font path '%s'", defaultFontPath); + if (!SetDefaultFont(defaultTextFont)) + FatalError("could not open default font '%s'", defaultTextFont); + if (!(rootCursor = CreateRootCursor(defaultCursorFont, 0))) + FatalError("could not open default cursor font '%s'", + defaultCursorFont); +#ifdef DPMSExtension + /* check all screens, looking for DPMS Capabilities */ + DPMSCapableFlag = DPMSSupported(); + if (!DPMSCapableFlag) + DPMSEnabled = FALSE; +#endif + for (i = 0; i < screenInfo.numScreens; i++) + InitRootWindow(WindowTable[i]); + DefineInitialRootWindow(WindowTable[0]); + + if (!CreateConnectionBlock()) + FatalError("could not create connection block info"); + + Dispatch(); + + /* Now free up whatever must be freed */ + if (screenIsSaved == SCREEN_SAVER_ON) + SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset); + CloseDownExtensions(); + FreeAllResources(); + CloseDownDevices(); + for (i = screenInfo.numScreens - 1; i >= 0; i--) + { + FreeScratchPixmapsForScreen(i); + FreeGCperDepth(i); + FreeDefaultStipple(i); + (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]); + FreeScreen(screenInfo.screens[i]); + screenInfo.numScreens = i; + } + xfree(WindowTable); + FreeFonts (); + xfree(serverClient->devPrivates); + + if (dispatchException & DE_TERMINATE) + { + ddxGiveUp(); + break; + } + + xfree(ConnectionInfo); + } + return(0); +} + +static int padlength[4] = {0, 3, 2, 1}; + +static Bool +CreateConnectionBlock() +{ + xConnSetup setup; + xWindowRoot root; + xDepth depth; + xVisualType visual; + xPixmapFormat format; + unsigned long vid; + int i, j, k, + lenofblock, + sizesofar = 0; + char *pBuf; + + + /* Leave off the ridBase and ridMask, these must be sent with + connection */ + + setup.release = VENDOR_RELEASE; + /* + * per-server image and bitmap parameters are defined in Xmd.h + */ + setup.imageByteOrder = screenInfo.imageByteOrder; + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if ( screenInfo.bitmapScanlineUnit > 32 ) + setup.bitmapScanlineUnit = 32; + else +#endif + setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if ( screenInfo.bitmapScanlinePad > 32 ) + setup.bitmapScanlinePad = 32; + else +#endif + setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad; + + setup.bitmapBitOrder = screenInfo.bitmapBitOrder; + setup.motionBufferSize = NumMotionEvents(); + setup.numRoots = screenInfo.numScreens; + setup.nbytesVendor = strlen(VENDOR_STRING); + setup.numFormats = screenInfo.numPixmapFormats; + setup.maxRequestSize = MAX_REQUEST_SIZE; + QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode); + + lenofblock = sizeof(xConnSetup) + + ((setup.nbytesVendor + 3) & ~3) + + (setup.numFormats * sizeof(xPixmapFormat)) + + (setup.numRoots * sizeof(xWindowRoot)); + ConnectionInfo = (char *) xalloc(lenofblock); + if (!ConnectionInfo) + return FALSE; + + memmove(ConnectionInfo, (char *)&setup, sizeof(xConnSetup)); + sizesofar = sizeof(xConnSetup); + pBuf = ConnectionInfo + sizeof(xConnSetup); + + memmove(pBuf, VENDOR_STRING, (int)setup.nbytesVendor); + sizesofar += setup.nbytesVendor; + pBuf += setup.nbytesVendor; + i = padlength[setup.nbytesVendor & 3]; + sizesofar += i; + while (--i >= 0) + *pBuf++ = 0; + + for (i=0; i 32 ) + format.scanLinePad = 32; + else +#endif + format.scanLinePad = screenInfo.formats[i].scanlinePad; + memmove(pBuf, (char *)&format, sizeof(xPixmapFormat)); + pBuf += sizeof(xPixmapFormat); + sizesofar += sizeof(xPixmapFormat); + } + + connBlockScreenStart = sizesofar; + for (i=0; idrawable.id; + root.defaultColormap = pScreen->defColormap; + root.whitePixel = pScreen->whitePixel; + root.blackPixel = pScreen->blackPixel; + root.currentInputMask = 0; /* filled in when sent */ + root.pixWidth = pScreen->width; + root.pixHeight = pScreen->height; + root.mmWidth = pScreen->mmWidth; + root.mmHeight = pScreen->mmHeight; + root.minInstalledMaps = pScreen->minInstalledCmaps; + root.maxInstalledMaps = pScreen->maxInstalledCmaps; + root.rootVisualID = pScreen->rootVisual; + root.backingStore = pScreen->backingStoreSupport; + root.saveUnders = pScreen->saveUnderSupport != NotUseful; + root.rootDepth = pScreen->rootDepth; + root.nDepths = pScreen->numDepths; + memmove(pBuf, (char *)&root, sizeof(xWindowRoot)); + sizesofar += sizeof(xWindowRoot); + pBuf += sizeof(xWindowRoot); + + pDepth = pScreen->allowedDepths; + for(j = 0; j < pScreen->numDepths; j++, pDepth++) + { + lenofblock += sizeof(xDepth) + + (pDepth->numVids * sizeof(xVisualType)); + pBuf = (char *)xrealloc(ConnectionInfo, lenofblock); + if (!pBuf) + { + xfree(ConnectionInfo); + return FALSE; + } + ConnectionInfo = pBuf; + pBuf += sizesofar; + depth.depth = pDepth->depth; + depth.nVisuals = pDepth->numVids; + memmove(pBuf, (char *)&depth, sizeof(xDepth)); + pBuf += sizeof(xDepth); + sizesofar += sizeof(xDepth); + for(k = 0; k < pDepth->numVids; k++) + { + vid = pDepth->vids[k]; + for (pVisual = pScreen->visuals; + pVisual->vid != vid; + pVisual++) + ; + visual.visualID = vid; + visual.class = pVisual->class; + visual.bitsPerRGB = pVisual->bitsPerRGBValue; + visual.colormapEntries = pVisual->ColormapEntries; + visual.redMask = pVisual->redMask; + visual.greenMask = pVisual->greenMask; + visual.blueMask = pVisual->blueMask; + memmove(pBuf, (char *)&visual, sizeof(xVisualType)); + pBuf += sizeof(xVisualType); + sizesofar += sizeof(xVisualType); + } + } + } + connSetupPrefix.success = xTrue; + connSetupPrefix.length = lenofblock/4; + connSetupPrefix.majorVersion = X_PROTOCOL; + connSetupPrefix.minorVersion = X_PROTOCOL_REVISION; + return TRUE; +} + +/* + grow the array of screenRecs if necessary. + call the device-supplied initialization procedure +with its screen number, a pointer to its ScreenRec, argc, and argv. + return the number of successfully installed screens. + +*/ + +int +AddScreen(pfnInit, argc, argv) + Bool (* pfnInit)(); + int argc; + char **argv; +{ + + int i; + int scanlinepad, format, depth, bitsPerPixel, j, k; + ScreenPtr pScreen; +#ifdef DEBUG + void (**jNI) (); +#endif /* DEBUG */ + + i = screenInfo.numScreens; + if (i == MAXSCREENS) + return -1; + + pScreen = (ScreenPtr) xalloc(sizeof(ScreenRec)); + if (!pScreen) + return -1; + + pScreen->devPrivates = (DevUnion *)xalloc(screenPrivateCount * + sizeof(DevUnion)); + if (!pScreen->devPrivates && screenPrivateCount) + { + xfree(pScreen); + return -1; + } + pScreen->myNum = i; + pScreen->WindowPrivateLen = 0; + pScreen->WindowPrivateSizes = (unsigned *)NULL; + pScreen->totalWindowSize = sizeof(WindowRec); + pScreen->GCPrivateLen = 0; + pScreen->GCPrivateSizes = (unsigned *)NULL; + pScreen->totalGCSize = sizeof(GC); +#ifdef PIXPRIV + pScreen->PixmapPrivateLen = 0; + pScreen->PixmapPrivateSizes = (unsigned *)NULL; + pScreen->totalPixmapSize = sizeof(PixmapRec); +#endif + pScreen->ClipNotify = (void (*)())NULL; /* for R4 ddx compatibility */ + pScreen->CreateScreenResources = (Bool (*)())NULL; + +#ifdef DEBUG + for (jNI = &pScreen->QueryBestSize; + jNI < (void (**) ()) &pScreen->SendGraphicsExpose; + jNI++) + *jNI = NotImplemented; +#endif /* DEBUG */ + + /* + * This loop gets run once for every Screen that gets added, + * but thats ok. If the ddx layer initializes the formats + * one at a time calling AddScreen() after each, then each + * iteration will make it a little more accurate. Worst case + * we do this loop N * numPixmapFormats where N is # of screens. + * Anyway, this must be called after InitOutput and before the + * screen init routine is called. + */ + for (format=0; formatrgf = ~0L; /* there are no scratch GCs yet*/ + WindowTable[i] = NullWindow; + screenInfo.screens[i] = pScreen; + screenInfo.numScreens++; + if (!(*pfnInit)(i, pScreen, argc, argv)) + { + FreeScreen(pScreen); + screenInfo.numScreens--; + return -1; + } + return i; +} + +static void +FreeScreen(pScreen) + ScreenPtr pScreen; +{ + xfree(pScreen->WindowPrivateSizes); + xfree(pScreen->GCPrivateSizes); +#ifdef PIXPRIV + xfree(pScreen->PixmapPrivateSizes); +#endif + xfree(pScreen->devPrivates); + xfree(pScreen); +} diff --git a/dix/pixmap.c b/dix/pixmap.c new file mode 100644 index 000000000..b65559f6e --- /dev/null +++ b/dix/pixmap.c @@ -0,0 +1,147 @@ +/* $Xorg: pixmap.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#include "scrnintstr.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "site.h" + + +/* + * Scratch pixmap management and device independent pixmap allocation + * function. + */ + + +/* callable by ddx */ +PixmapPtr +GetScratchPixmapHeader(pScreen, width, height, depth, bitsPerPixel, devKind, + pPixData) + ScreenPtr pScreen; + int width; + int height; + int depth; + int bitsPerPixel; + int devKind; + pointer pPixData; +{ + PixmapPtr pPixmap = pScreen->pScratchPixmap; + + if (pPixmap) + pScreen->pScratchPixmap = NULL; + else + /* width and height of 0 means don't allocate any pixmap data */ + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth); + + if (pPixmap) + if ((*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + bitsPerPixel, devKind, pPixData)) + return pPixmap; + return NullPixmap; +} + + +/* callable by ddx */ +void +FreeScratchPixmapHeader(pPixmap) + PixmapPtr pPixmap; +{ + if (pPixmap) + { + ScreenPtr pScreen = pPixmap->drawable.pScreen; + + pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */ + if (pScreen->pScratchPixmap) + (*pScreen->DestroyPixmap)(pPixmap); + else + pScreen->pScratchPixmap = pPixmap; + } +} + + +Bool +CreateScratchPixmapsForScreen(scrnum) + int scrnum; +{ + /* let it be created on first use */ + screenInfo.screens[scrnum]->pScratchPixmap = NULL; + return TRUE; +} + + +void +FreeScratchPixmapsForScreen(scrnum) + int scrnum; +{ + FreeScratchPixmapHeader(screenInfo.screens[scrnum]->pScratchPixmap); +} + + +/* callable by ddx */ +PixmapPtr +AllocatePixmap(pScreen, pixDataSize) + ScreenPtr pScreen; + int pixDataSize; +{ + PixmapPtr pPixmap; +#ifdef PIXPRIV + char *ptr; + DevUnion *ppriv; + unsigned *sizes; + unsigned size; + int i; + + pPixmap = (PixmapPtr)xalloc(pScreen->totalPixmapSize + pixDataSize); + if (!pPixmap) + return NullPixmap; + ppriv = (DevUnion *)(pPixmap + 1); + pPixmap->devPrivates = ppriv; + sizes = pScreen->PixmapPrivateSizes; + ptr = (char *)(ppriv + pScreen->PixmapPrivateLen); + for (i = pScreen->PixmapPrivateLen; --i >= 0; ppriv++, sizes++) + { + if (size = *sizes) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } +#else + pPixmap = (PixmapPtr)xalloc(sizeof(PixmapRec) + pixDataSize); +#endif + return pPixmap; +} diff --git a/dix/privates.c b/dix/privates.c new file mode 100644 index 000000000..a252dbce9 --- /dev/null +++ b/dix/privates.c @@ -0,0 +1,351 @@ +/* $Xorg: privates.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#include "scrnintstr.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "servermd.h" +#include "site.h" + +/* + * See the Wrappers and devPrivates section in "Definition of the + * Porting Layer for the X v11 Sample Server" (doc/Server/ddx.tbl.ms) + * for information on how to use devPrivates. + */ + +/* + * client private machinery + */ + +static int clientPrivateCount; +int clientPrivateLen; +unsigned *clientPrivateSizes; +unsigned totalClientSize; + +void +ResetClientPrivates() +{ + clientPrivateCount = 0; + clientPrivateLen = 0; + xfree(clientPrivateSizes); + clientPrivateSizes = (unsigned *)NULL; + totalClientSize = sizeof(ClientRec); + +} + +int +AllocateClientPrivateIndex() +{ + return clientPrivateCount++; +} + +Bool +AllocateClientPrivate(index, amount) + int index; + unsigned amount; +{ + unsigned oldamount; + + if (index >= clientPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(clientPrivateSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (clientPrivateLen <= index) + { + nsizes[clientPrivateLen++] = 0; + totalClientSize += sizeof(DevUnion); + } + clientPrivateSizes = nsizes; + } + oldamount = clientPrivateSizes[index]; + if (amount > oldamount) + { + clientPrivateSizes[index] = amount; + totalClientSize += (amount - oldamount); + } + return TRUE; +} + +/* + * screen private machinery + */ + +int screenPrivateCount; + +void +ResetScreenPrivates() +{ + screenPrivateCount = 0; +} + +/* this can be called after some screens have been created, + * so we have to worry about resizing existing devPrivates + */ +int +AllocateScreenPrivateIndex() +{ + int index; + int i; + ScreenPtr pScreen; + DevUnion *nprivs; + + index = screenPrivateCount++; + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + nprivs = (DevUnion *)xrealloc(pScreen->devPrivates, + screenPrivateCount * sizeof(DevUnion)); + if (!nprivs) + { + screenPrivateCount--; + return -1; + } + pScreen->devPrivates = nprivs; + } + return index; +} + + +/* + * window private machinery + */ + +static int windowPrivateCount; + +void +ResetWindowPrivates() +{ + windowPrivateCount = 0; +} + +int +AllocateWindowPrivateIndex() +{ + return windowPrivateCount++; +} + +Bool +AllocateWindowPrivate(pScreen, index, amount) + register ScreenPtr pScreen; + int index; + unsigned amount; +{ + unsigned oldamount; + + if (index >= pScreen->WindowPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(pScreen->WindowPrivateSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (pScreen->WindowPrivateLen <= index) + { + nsizes[pScreen->WindowPrivateLen++] = 0; + pScreen->totalWindowSize += sizeof(DevUnion); + } + pScreen->WindowPrivateSizes = nsizes; + } + oldamount = pScreen->WindowPrivateSizes[index]; + if (amount > oldamount) + { + pScreen->WindowPrivateSizes[index] = amount; + pScreen->totalWindowSize += (amount - oldamount); + } + return TRUE; +} + + +/* + * gc private machinery + */ + +static int gcPrivateCount; + +void +ResetGCPrivates() +{ + gcPrivateCount = 0; +} + +int +AllocateGCPrivateIndex() +{ + return gcPrivateCount++; +} + +Bool +AllocateGCPrivate(pScreen, index, amount) + register ScreenPtr pScreen; + int index; + unsigned amount; +{ + unsigned oldamount; + + if (index >= pScreen->GCPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(pScreen->GCPrivateSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (pScreen->GCPrivateLen <= index) + { + nsizes[pScreen->GCPrivateLen++] = 0; + pScreen->totalGCSize += sizeof(DevUnion); + } + pScreen->GCPrivateSizes = nsizes; + } + oldamount = pScreen->GCPrivateSizes[index]; + if (amount > oldamount) + { + pScreen->GCPrivateSizes[index] = amount; + pScreen->totalGCSize += (amount - oldamount); + } + return TRUE; +} + + +/* + * pixmap private machinery + */ +#ifdef PIXPRIV +static int pixmapPrivateCount; + +void +ResetPixmapPrivates() +{ + pixmapPrivateCount = 0; +} + +int +AllocatePixmapPrivateIndex() +{ + return pixmapPrivateCount++; +} + +Bool +AllocatePixmapPrivate(pScreen, index, amount) + register ScreenPtr pScreen; + int index; + unsigned amount; +{ + unsigned oldamount; + + if (index >= pScreen->PixmapPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(pScreen->PixmapPrivateSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (pScreen->PixmapPrivateLen <= index) + { + nsizes[pScreen->PixmapPrivateLen++] = 0; + pScreen->totalPixmapSize += sizeof(DevUnion); + } + pScreen->PixmapPrivateSizes = nsizes; + } + oldamount = pScreen->PixmapPrivateSizes[index]; + if (amount > oldamount) + { + pScreen->PixmapPrivateSizes[index] = amount; + pScreen->totalPixmapSize += (amount - oldamount); + } + return TRUE; +} +#endif + + +/* + * colormap private machinery + */ + +int colormapPrivateCount; + +void +ResetColormapPrivates() +{ + colormapPrivateCount = 0; +} + + +int +AllocateColormapPrivateIndex (initPrivFunc) + +InitCmapPrivFunc initPrivFunc; + +{ + int index; + int i; + ColormapPtr pColormap; + DevUnion *privs; + + index = colormapPrivateCount++; + + for (i = 0; i < screenInfo.numScreens; i++) + { + /* + * AllocateColormapPrivateIndex may be called after the + * default colormap has been created on each screen! + * + * We must resize the devPrivates array for the default + * colormap on each screen, making room for this new private. + * We also call the initialization function 'initPrivFunc' on + * the new private allocated for each default colormap. + */ + + ScreenPtr pScreen = screenInfo.screens[i]; + + pColormap = (ColormapPtr) LookupIDByType ( + pScreen->defColormap, RT_COLORMAP); + + privs = (DevUnion *) xrealloc (pColormap->devPrivates, + colormapPrivateCount * sizeof(DevUnion)); + + pColormap->devPrivates = privs; + + if (!privs || !(*initPrivFunc)(pColormap)) + { + colormapPrivateCount--; + return -1; + } + } + + return index; +} diff --git a/dix/property.c b/dix/property.c new file mode 100644 index 000000000..1b92dfa35 --- /dev/null +++ b/dix/property.c @@ -0,0 +1,724 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: property.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xproto.h" +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +extern void CopySwap16Write(), CopySwap32Write(), Swap32Write(); + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(client) + ClientPtr client; +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XCSECURITY + char action = SecurityCheckPropertyAccess(client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XCSECURITY + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XCSECURITY + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(client) + ClientPtr client; +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + +#ifdef LBX + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL); +#else + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); +#endif + if (err != Success) + return err; + else + return client->noClientException; +} + +int +ChangeWindowProperty(pWin, property, type, format, mode, len, value, sendevent) + WindowPtr pWin; + Atom property, type; + int format, mode; + unsigned long len; + pointer value; + Bool sendevent; +{ +#ifdef LBX + return LbxChangeWindowProperty(NULL, pWin, property, type, + format, mode, len, TRUE, value, + sendevent, NULL); +#else + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +#endif +} + +int +DeleteProperty(pWin, propName) + WindowPtr pWin; + Atom propName; +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply(client, propertyType, format, reply) + ClientPtr client; + ATOM propertyType; + int format; + xGetPropertyReply *reply; +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(client) + ClientPtr client; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XCSECURITY + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } +#ifdef LBX + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } +#endif + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = CopySwap32Write; break; + case 16: client->pSwapReplyFunc = CopySwap16Write; break; + default: client->pSwapReplyFunc = (void (*) ())WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +int +ProcListProperties(client) + ClientPtr client; +{ + Atom *pAtoms, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(client) + register ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XCSECURITY + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} diff --git a/dix/resource.c b/dix/resource.c new file mode 100644 index 000000000..76f9ef191 --- /dev/null +++ b/dix/resource.c @@ -0,0 +1,855 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + +/* $Xorg: resource.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ + +#include "X.h" +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include + +extern WindowPtr *WindowTable; + +static void RebuildTable( +#if NeedFunctionPrototypes + int /*client*/ +#endif +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +static RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +static RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +RESTYPE +CreateNewResourceType(deleteFunc) + DeleteType deleteFunc; +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(client) + ClientPtr client; +{ + register int i, j; + + if (client == serverClient) + { + extern int DeleteWindow(), dixDestroyPixmap(), FreeGC(); + extern int CloseFont(), FreeCursor(); + extern int FreeColormap(), FreeClientPixels(); + extern int OtherClientGone(), DeletePassiveGrab(); + + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +AvailableID(client, id, maxid, goodid) + register int client; + register XID id, maxid, goodid; +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +void +GetXIDRange(client, server, minp, maxp) + int client; + Bool server; + XID *minp, *maxp; +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/* GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +unsigned int +GetXIDList(pClient, count, pids) + ClientPtr pClient; + unsigned int count; + XID *pids; +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +XID +FakeClientID(client) + register int client; +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +Bool +AddResource(id, type, value) + XID id; + RESTYPE type; + pointer value; +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%x, %x, %x), client=%d \n", + id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(client) + int client; +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +void +FreeResource(id, skipDeleteFuncType) + XID id; + RESTYPE skipDeleteFuncType; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + FatalError("Freeing resource id=%X which isn't there", id); +} + + +void +FreeResourceByType(id, type, skipFree) + XID id; + RESTYPE type; + Bool skipFree; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +Bool +ChangeResourceValue (id, rtype, value) + XID id; + RESTYPE rtype; + pointer value; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +void +FindClientResourcesByType(client, type, func, cdata) + ClientPtr client; + RESTYPE type; + FindResType func; + pointer cdata; +{ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +void +FreeClientNeverRetainResources(client) + ClientPtr client; +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(client) + ClientPtr client; +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +Bool +LegalNewID(id, client) + XID id; + register ClientPtr client; +{ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +#ifdef XCSECURITY + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +pointer +SecurityLookupIDByType(client, id, rtype, mode) + ClientPtr client; + XID id; + RESTYPE rtype; + Mask mode; +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert( (rtype & TypeMask) <= lastResourceType); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, rtype, mode, retval); + return retval; +} + + +pointer +SecurityLookupIDByClass(client, id, classes, mode) + ClientPtr client; + XID id; + RESTYPE classes; + Mask mode; +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert (classes >= lastResourceClass); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, res->type, mode, retval); + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +/* + * LookupIDByType returns the object with the given id and type, else NULL. + */ +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + return res->value; + } + return (pointer)NULL; +} + +/* + * LookupIDByClass returns the object with the given id and any one of the + * given classes, else NULL. + */ +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + return res->value; + } + return (pointer)NULL; +} + +#endif /* XCSECURITY */ diff --git a/dix/swaprep.c b/dix/swaprep.c new file mode 100644 index 000000000..ffce75ac4 --- /dev/null +++ b/dix/swaprep.c @@ -0,0 +1,1443 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + +/* $Xorg: swaprep.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "fontstruct.h" +#include "scrnintstr.h" + +void SwapVisual(), SwapConnSetup(), SwapWinRoot(); + +/* Thanks to Jack Palevich for testing and subsequently rewriting all this */ +void +Swap32Write(pClient, size, pbuf) + ClientPtr pClient; + int size; /* in bytes */ + register CARD32 *pbuf; +{ + register int i; + register char n; + + size >>= 2; + for(i = 0; i < size; i++) + /* brackets are mandatory here, because "swapl" macro expands + to several statements */ + { + swapl(&pbuf[i], n); + } + (void)WriteToClient(pClient, size << 2, (char *) pbuf); +} + +void +CopySwap32Write(pClient, size, pbuf) + ClientPtr pClient; + int size; /* in bytes */ + CARD32 *pbuf; +{ + int bufsize = size; + CARD32 *pbufT; + register CARD32 *from, *to, *fromLast, *toLast; + CARD32 tmpbuf[1]; + + /* Allocate as big a buffer as we can... */ + while (!(pbufT = (CARD32 *) ALLOCATE_LOCAL(bufsize))) + { + bufsize >>= 1; + if (bufsize == 4) + { + pbufT = tmpbuf; + break; + } + } + + /* convert lengths from # of bytes to # of longs */ + size >>= 2; + bufsize >>= 2; + + from = pbuf; + fromLast = from + size; + while (from < fromLast) { + int nbytes; + to = pbufT; + toLast = to + min (bufsize, fromLast - from); + nbytes = (toLast - to) << 2; + while (to < toLast) { + /* can't write "cpswapl(*from++, *to++)" because cpswapl is a macro + that evaulates its args more than once */ + cpswapl(*from, *to); + from++; + to++; + } + (void)WriteToClient (pClient, nbytes, (char *) pbufT); + } + + if (pbufT != tmpbuf) + DEALLOCATE_LOCAL ((char *) pbufT); +} + +void +CopySwap16Write(pClient, size, pbuf) + ClientPtr pClient; + int size; /* in bytes */ + short *pbuf; +{ + int bufsize = size; + short *pbufT; + register short *from, *to, *fromLast, *toLast; + short tmpbuf[2]; + + /* Allocate as big a buffer as we can... */ + while (!(pbufT = (short *) ALLOCATE_LOCAL(bufsize))) + { + bufsize >>= 1; + if (bufsize == 4) + { + pbufT = tmpbuf; + break; + } + } + + /* convert lengths from # of bytes to # of shorts */ + size >>= 1; + bufsize >>= 1; + + from = pbuf; + fromLast = from + size; + while (from < fromLast) { + int nbytes; + to = pbufT; + toLast = to + min (bufsize, fromLast - from); + nbytes = (toLast - to) << 1; + while (to < toLast) { + /* can't write "cpswaps(*from++, *to++)" because cpswaps is a macro + that evaulates its args more than once */ + cpswaps(*from, *to); + from++; + to++; + } + (void)WriteToClient (pClient, nbytes, (char *) pbufT); + } + + if (pbufT != tmpbuf) + DEALLOCATE_LOCAL ((char *) pbufT); +} + + +/* Extra-small reply */ +void +SGenericReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGenericReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +/* Extra-large reply */ +void +SGetWindowAttributesReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetWindowAttributesReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->visualID, n); + swaps(&pRep->class, n); + swapl(&pRep->backingBitPlanes, n); + swapl(&pRep->backingPixel, n); + swapl(&pRep->colormap, n); + swapl(&pRep->allEventMasks, n); + swapl(&pRep->yourEventMask, n); + swaps(&pRep->doNotPropagateMask, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetGeometryReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetGeometryReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->root, n); + swaps(&pRep->x, n); + swaps(&pRep->y, n); + swaps(&pRep->width, n); + swaps(&pRep->height, n); + swaps(&pRep->borderWidth, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryTreeReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xQueryTreeReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->root, n); + swapl(&pRep->parent, n); + swaps(&pRep->nChildren, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SInternAtomReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xInternAtomReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->atom, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetAtomNameReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetAtomNameReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nameLength, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + +void +SGetPropertyReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetPropertyReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->propertyType, n); + swapl(&pRep->bytesAfter, n); + swapl(&pRep->nItems, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListPropertiesReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xListPropertiesReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nProperties, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetSelectionOwnerReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetSelectionOwnerReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->owner, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + +void +SQueryPointerReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xQueryPointerReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->root, n); + swapl(&pRep->child, n); + swaps(&pRep->rootX, n); + swaps(&pRep->rootY, n); + swaps(&pRep->winX, n); + swaps(&pRep->winY, n); + swaps(&pRep->mask, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SwapTimecoord(pCoord) + xTimecoord *pCoord; +{ + register char n; + + swapl(&pCoord->time, n); + swaps(&pCoord->x, n); + swaps(&pCoord->y, n); +} + +void +SwapTimeCoordWrite(pClient, size, pRep) + ClientPtr pClient; + int size; + xTimecoord *pRep; +{ + int i, n; + xTimecoord *pRepT; + + n = size / sizeof(xTimecoord); + pRepT = pRep; + for(i = 0; i < n; i++) + { + SwapTimecoord(pRepT); + pRepT++; + } + (void)WriteToClient(pClient, size, (char *) pRep); + +} +void +SGetMotionEventsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetMotionEventsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->nEvents, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +STranslateCoordsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xTranslateCoordsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->child, n); + swaps(&pRep->dstX, n); + swaps(&pRep->dstY, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetInputFocusReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetInputFocusReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->focus, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +/* extra long reply */ +void +SQueryKeymapReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xQueryKeymapReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +#ifndef LBX +static +#endif +void +SwapCharInfo(pInfo) + xCharInfo *pInfo; +{ + register char n; + + swaps(&pInfo->leftSideBearing, n); + swaps(&pInfo->rightSideBearing, n); + swaps(&pInfo->characterWidth, n); + swaps(&pInfo->ascent, n); + swaps(&pInfo->descent, n); + swaps(&pInfo->attributes, n); +} + +static void +SwapFontInfo(pr) + xQueryFontReply *pr; +{ + register char n; + + swaps(&pr->minCharOrByte2, n); + swaps(&pr->maxCharOrByte2, n); + swaps(&pr->defaultChar, n); + swaps(&pr->nFontProps, n); + swaps(&pr->fontAscent, n); + swaps(&pr->fontDescent, n); + SwapCharInfo( &pr->minBounds); + SwapCharInfo( &pr->maxBounds); + swapl(&pr->nCharInfos, n); +} + +#ifndef LBX +static +#endif +void +SwapFont( pr, hasGlyphs) + xQueryFontReply * pr; + Bool hasGlyphs; +{ + unsigned i; + xCharInfo * pxci; + unsigned nchars, nprops; + char *pby; + register char n; + + swaps(&pr->sequenceNumber, n); + swapl(&pr->length, n); + nchars = pr->nCharInfos; + nprops = pr->nFontProps; + SwapFontInfo(pr); + pby = (char *) &pr[1]; + /* Font properties are an atom and either an int32 or a CARD32, so + * they are always 2 4 byte values */ + for(i = 0; i < nprops; i++) + { + swapl(pby, n); + pby += 4; + swapl(pby, n); + pby += 4; + } + if (hasGlyphs) + { + pxci = (xCharInfo *)pby; + for(i = 0; i< nchars; i++, pxci++) + SwapCharInfo(pxci); + } +} + +void +SQueryFontReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xQueryFontReply *pRep; +{ + SwapFont(pRep, TRUE); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryTextExtentsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xQueryTextExtentsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->fontAscent, n); + swaps(&pRep->fontDescent, n); + swaps(&pRep->overallAscent, n); + swaps(&pRep->overallDescent, n); + swapl(&pRep->overallWidth, n); + swapl(&pRep->overallLeft, n); + swapl(&pRep->overallRight, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListFontsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xListFontsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nFonts, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListFontsWithInfoReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xListFontsWithInfoReply *pRep; +{ + SwapFont((xQueryFontReply *)pRep, FALSE); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetFontPathReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetFontPathReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nPaths, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetImageReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetImageReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->visual, n); + (void)WriteToClient(pClient, size, (char *) pRep); + /* Fortunately, image doesn't need swapping */ +} + +void +SListInstalledColormapsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xListInstalledColormapsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nColormaps, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocColorReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xAllocColorReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->red, n); + swaps(&pRep->green, n); + swaps(&pRep->blue, n); + swapl(&pRep->pixel, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocNamedColorReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xAllocNamedColorReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->pixel, n); + swaps(&pRep->exactRed, n); + swaps(&pRep->exactGreen, n); + swaps(&pRep->exactBlue, n); + swaps(&pRep->screenRed, n); + swaps(&pRep->screenGreen, n); + swaps(&pRep->screenBlue, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocColorCellsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xAllocColorCellsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nPixels, n); + swaps(&pRep->nMasks, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + +void +SAllocColorPlanesReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xAllocColorPlanesReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nPixels, n); + swapl(&pRep->redMask, n); + swapl(&pRep->greenMask, n); + swapl(&pRep->blueMask, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SwapRGB(prgb) + xrgb *prgb; +{ + register char n; + + swaps(&prgb->red, n); + swaps(&prgb->green, n); + swaps(&prgb->blue, n); +} + +void +SQColorsExtend(pClient, size, prgb) + ClientPtr pClient; + int size; + xrgb *prgb; +{ + int i, n; + xrgb *prgbT; + + n = size / sizeof(xrgb); + prgbT = prgb; + for(i = 0; i < n; i++) + { + SwapRGB(prgbT); + prgbT++; + } + (void)WriteToClient(pClient, size, (char *) prgb); +} + +void +SQueryColorsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xQueryColorsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nColors, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SLookupColorReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xLookupColorReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->exactRed, n); + swaps(&pRep->exactGreen, n); + swaps(&pRep->exactBlue, n); + swaps(&pRep->screenRed, n); + swaps(&pRep->screenGreen, n); + swaps(&pRep->screenBlue, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryBestSizeReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xQueryBestSizeReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->width, n); + swaps(&pRep->height, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListExtensionsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xListExtensionsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetKeyboardMappingReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetKeyboardMappingReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetPointerMappingReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetPointerMappingReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetModifierMappingReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetModifierMappingReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetKeyboardControlReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetKeyboardControlReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->ledMask, n); + swaps(&pRep->bellPitch, n); + swaps(&pRep->bellDuration, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetPointerControlReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetPointerControlReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->accelNumerator, n); + swaps(&pRep->accelDenominator, n); + swaps(&pRep->threshold, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetScreenSaverReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xGetScreenSaverReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->timeout, n); + swaps(&pRep->interval, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SLHostsExtend(pClient, size, buf) + ClientPtr pClient; + int size; + char *buf; +{ + char *bufT = buf; + char *endbuf = buf + size; + while (bufT < endbuf) { + xHostEntry *host = (xHostEntry *) bufT; + int len = host->length; + register char n; + swaps (&host->length, n); + bufT += sizeof (xHostEntry) + (((len + 3) >> 2) << 2); + } + (void)WriteToClient (pClient, size, buf); +} + +void +SListHostsReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xListHostsReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nHosts, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + + +void +SErrorEvent(from, to) + xError *from, *to; +{ + to->type = X_Error; + to->errorCode = from->errorCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->resourceID, to->resourceID); + cpswaps(from->minorCode, to->minorCode); + to->majorCode = from->majorCode; +} + +void +SKeyButtonPtrEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.keyButtonPointer.time, + to->u.keyButtonPointer.time); + cpswapl(from->u.keyButtonPointer.root, + to->u.keyButtonPointer.root); + cpswapl(from->u.keyButtonPointer.event, + to->u.keyButtonPointer.event); + cpswapl(from->u.keyButtonPointer.child, + to->u.keyButtonPointer.child); + cpswaps(from->u.keyButtonPointer.rootX, + to->u.keyButtonPointer.rootX); + cpswaps(from->u.keyButtonPointer.rootY, + to->u.keyButtonPointer.rootY); + cpswaps(from->u.keyButtonPointer.eventX, + to->u.keyButtonPointer.eventX); + cpswaps(from->u.keyButtonPointer.eventY, + to->u.keyButtonPointer.eventY); + cpswaps(from->u.keyButtonPointer.state, + to->u.keyButtonPointer.state); + to->u.keyButtonPointer.sameScreen = + from->u.keyButtonPointer.sameScreen; +} + +void +SEnterLeaveEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.enterLeave.time, to->u.enterLeave.time); + cpswapl(from->u.enterLeave.root, to->u.enterLeave.root); + cpswapl(from->u.enterLeave.event, to->u.enterLeave.event); + cpswapl(from->u.enterLeave.child, to->u.enterLeave.child); + cpswaps(from->u.enterLeave.rootX, to->u.enterLeave.rootX); + cpswaps(from->u.enterLeave.rootY, to->u.enterLeave.rootY); + cpswaps(from->u.enterLeave.eventX, to->u.enterLeave.eventX); + cpswaps(from->u.enterLeave.eventY, to->u.enterLeave.eventY); + cpswaps(from->u.enterLeave.state, to->u.enterLeave.state); + to->u.enterLeave.mode = from->u.enterLeave.mode; + to->u.enterLeave.flags = from->u.enterLeave.flags; +} + +void +SFocusEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.focus.window, to->u.focus.window); + to->u.focus.mode = from->u.focus.mode; +} + +void +SExposeEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.expose.window, to->u.expose.window); + cpswaps(from->u.expose.x, to->u.expose.x); + cpswaps(from->u.expose.y, to->u.expose.y); + cpswaps(from->u.expose.width, to->u.expose.width); + cpswaps(from->u.expose.height, to->u.expose.height); + cpswaps(from->u.expose.count, to->u.expose.count); +} + +void +SGraphicsExposureEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.graphicsExposure.drawable, + to->u.graphicsExposure.drawable); + cpswaps(from->u.graphicsExposure.x, + to->u.graphicsExposure.x); + cpswaps(from->u.graphicsExposure.y, + to->u.graphicsExposure.y); + cpswaps(from->u.graphicsExposure.width, + to->u.graphicsExposure.width); + cpswaps(from->u.graphicsExposure.height, + to->u.graphicsExposure.height); + cpswaps(from->u.graphicsExposure.minorEvent, + to->u.graphicsExposure.minorEvent); + cpswaps(from->u.graphicsExposure.count, + to->u.graphicsExposure.count); + to->u.graphicsExposure.majorEvent = + from->u.graphicsExposure.majorEvent; +} + +void +SNoExposureEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.noExposure.drawable, to->u.noExposure.drawable); + cpswaps(from->u.noExposure.minorEvent, to->u.noExposure.minorEvent); + to->u.noExposure.majorEvent = from->u.noExposure.majorEvent; +} + +void +SVisibilityEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.visibility.window, to->u.visibility.window); + to->u.visibility.state = from->u.visibility.state; +} + +void +SCreateNotifyEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.createNotify.window, to->u.createNotify.window); + cpswapl(from->u.createNotify.parent, to->u.createNotify.parent); + cpswaps(from->u.createNotify.x, to->u.createNotify.x); + cpswaps(from->u.createNotify.y, to->u.createNotify.y); + cpswaps(from->u.createNotify.width, to->u.createNotify.width); + cpswaps(from->u.createNotify.height, to->u.createNotify.height); + cpswaps(from->u.createNotify.borderWidth, + to->u.createNotify.borderWidth); + to->u.createNotify.override = from->u.createNotify.override; +} + +void +SDestroyNotifyEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.destroyNotify.event, to->u.destroyNotify.event); + cpswapl(from->u.destroyNotify.window, to->u.destroyNotify.window); +} + +void +SUnmapNotifyEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.unmapNotify.event, to->u.unmapNotify.event); + cpswapl(from->u.unmapNotify.window, to->u.unmapNotify.window); + to->u.unmapNotify.fromConfigure = from->u.unmapNotify.fromConfigure; +} + +void +SMapNotifyEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.mapNotify.event, to->u.mapNotify.event); + cpswapl(from->u.mapNotify.window, to->u.mapNotify.window); + to->u.mapNotify.override = from->u.mapNotify.override; +} + +void +SMapRequestEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.mapRequest.parent, to->u.mapRequest.parent); + cpswapl(from->u.mapRequest.window, to->u.mapRequest.window); +} + +void +SReparentEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.reparent.event, to->u.reparent.event); + cpswapl(from->u.reparent.window, to->u.reparent.window); + cpswapl(from->u.reparent.parent, to->u.reparent.parent); + cpswaps(from->u.reparent.x, to->u.reparent.x); + cpswaps(from->u.reparent.y, to->u.reparent.y); + to->u.reparent.override = from->u.reparent.override; +} + +void +SConfigureNotifyEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.configureNotify.event, + to->u.configureNotify.event); + cpswapl(from->u.configureNotify.window, + to->u.configureNotify.window); + cpswapl(from->u.configureNotify.aboveSibling, + to->u.configureNotify.aboveSibling); + cpswaps(from->u.configureNotify.x, to->u.configureNotify.x); + cpswaps(from->u.configureNotify.y, to->u.configureNotify.y); + cpswaps(from->u.configureNotify.width, to->u.configureNotify.width); + cpswaps(from->u.configureNotify.height, + to->u.configureNotify.height); + cpswaps(from->u.configureNotify.borderWidth, + to->u.configureNotify.borderWidth); + to->u.configureNotify.override = from->u.configureNotify.override; +} + +void +SConfigureRequestEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; /* actually stack-mode */ + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.configureRequest.parent, + to->u.configureRequest.parent); + cpswapl(from->u.configureRequest.window, + to->u.configureRequest.window); + cpswapl(from->u.configureRequest.sibling, + to->u.configureRequest.sibling); + cpswaps(from->u.configureRequest.x, to->u.configureRequest.x); + cpswaps(from->u.configureRequest.y, to->u.configureRequest.y); + cpswaps(from->u.configureRequest.width, + to->u.configureRequest.width); + cpswaps(from->u.configureRequest.height, + to->u.configureRequest.height); + cpswaps(from->u.configureRequest.borderWidth, + to->u.configureRequest.borderWidth); + cpswaps(from->u.configureRequest.valueMask, + to->u.configureRequest.valueMask); +} + + +void +SGravityEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.gravity.event, to->u.gravity.event); + cpswapl(from->u.gravity.window, to->u.gravity.window); + cpswaps(from->u.gravity.x, to->u.gravity.x); + cpswaps(from->u.gravity.y, to->u.gravity.y); +} + +void +SResizeRequestEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.resizeRequest.window, to->u.resizeRequest.window); + cpswaps(from->u.resizeRequest.width, to->u.resizeRequest.width); + cpswaps(from->u.resizeRequest.height, to->u.resizeRequest.height); +} + +void +SCirculateEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.circulate.event, to->u.circulate.event); + cpswapl(from->u.circulate.window, to->u.circulate.window); + cpswapl(from->u.circulate.parent, to->u.circulate.parent); + to->u.circulate.place = from->u.circulate.place; +} + +void +SPropertyEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.property.window, to->u.property.window); + cpswapl(from->u.property.atom, to->u.property.atom); + cpswapl(from->u.property.time, to->u.property.time); + to->u.property.state = from->u.property.state; +} + +void +SSelectionClearEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.selectionClear.time, to->u.selectionClear.time); + cpswapl(from->u.selectionClear.window, to->u.selectionClear.window); + cpswapl(from->u.selectionClear.atom, to->u.selectionClear.atom); +} + +void +SSelectionRequestEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.selectionRequest.time, to->u.selectionRequest.time); + cpswapl(from->u.selectionRequest.owner, + to->u.selectionRequest.owner); + cpswapl(from->u.selectionRequest.requestor, + to->u.selectionRequest.requestor); + cpswapl(from->u.selectionRequest.selection, + to->u.selectionRequest.selection); + cpswapl(from->u.selectionRequest.target, + to->u.selectionRequest.target); + cpswapl(from->u.selectionRequest.property, + to->u.selectionRequest.property); +} + +void +SSelectionNotifyEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.selectionNotify.time, to->u.selectionNotify.time); + cpswapl(from->u.selectionNotify.requestor, + to->u.selectionNotify.requestor); + cpswapl(from->u.selectionNotify.selection, + to->u.selectionNotify.selection); + cpswapl(from->u.selectionNotify.target, + to->u.selectionNotify.target); + cpswapl(from->u.selectionNotify.property, + to->u.selectionNotify.property); +} + +void +SColormapEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.colormap.window, to->u.colormap.window); + cpswapl(from->u.colormap.colormap, to->u.colormap.colormap); + to->u.colormap.new = from->u.colormap.new; + to->u.colormap.state = from->u.colormap.state; +} + +void +SMappingEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + to->u.mappingNotify.request = from->u.mappingNotify.request; + to->u.mappingNotify.firstKeyCode = + from->u.mappingNotify.firstKeyCode; + to->u.mappingNotify.count = from->u.mappingNotify.count; +} + +void +SClientMessageEvent(from, to) + xEvent *from, *to; +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; /* actually format */ + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.clientMessage.window, to->u.clientMessage.window); + cpswapl(from->u.clientMessage.u.l.type, + to->u.clientMessage.u.l.type); + switch (from->u.u.detail) { + case 8: + memmove(to->u.clientMessage.u.b.bytes, + from->u.clientMessage.u.b.bytes,20); + break; + case 16: + cpswaps(from->u.clientMessage.u.s.shorts0, + to->u.clientMessage.u.s.shorts0); + cpswaps(from->u.clientMessage.u.s.shorts1, + to->u.clientMessage.u.s.shorts1); + cpswaps(from->u.clientMessage.u.s.shorts2, + to->u.clientMessage.u.s.shorts2); + cpswaps(from->u.clientMessage.u.s.shorts3, + to->u.clientMessage.u.s.shorts3); + cpswaps(from->u.clientMessage.u.s.shorts4, + to->u.clientMessage.u.s.shorts4); + cpswaps(from->u.clientMessage.u.s.shorts5, + to->u.clientMessage.u.s.shorts5); + cpswaps(from->u.clientMessage.u.s.shorts6, + to->u.clientMessage.u.s.shorts6); + cpswaps(from->u.clientMessage.u.s.shorts7, + to->u.clientMessage.u.s.shorts7); + cpswaps(from->u.clientMessage.u.s.shorts8, + to->u.clientMessage.u.s.shorts8); + cpswaps(from->u.clientMessage.u.s.shorts9, + to->u.clientMessage.u.s.shorts9); + break; + case 32: + cpswapl(from->u.clientMessage.u.l.longs0, + to->u.clientMessage.u.l.longs0); + cpswapl(from->u.clientMessage.u.l.longs1, + to->u.clientMessage.u.l.longs1); + cpswapl(from->u.clientMessage.u.l.longs2, + to->u.clientMessage.u.l.longs2); + cpswapl(from->u.clientMessage.u.l.longs3, + to->u.clientMessage.u.l.longs3); + cpswapl(from->u.clientMessage.u.l.longs4, + to->u.clientMessage.u.l.longs4); + break; + } +} + +void +SKeymapNotifyEvent(from, to) + xEvent *from, *to; +{ + /* Keymap notify events are special; they have no + sequence number field, and contain entirely 8-bit data */ + *to = *from; +} + +void +SwapConnSetupInfo(pInfo, pInfoTBase) + char *pInfo; + char *pInfoTBase; +{ + int i, j, k; + ScreenPtr pScreen; + DepthPtr pDepth; + char *pInfoT; + xConnSetup *pConnSetup = (xConnSetup *)pInfo; + + pInfoT = pInfoTBase; + SwapConnSetup(pConnSetup, (xConnSetup *)pInfoT); + pInfo += sizeof(xConnSetup); + pInfoT += sizeof(xConnSetup); + + /* Copy the vendor string */ + i = (pConnSetup->nbytesVendor + 3) & ~3; + memmove(pInfoT, pInfo, i); + pInfo += i; + pInfoT += i; + + /* The Pixmap formats don't need to be swapped, just copied. */ + i = sizeof(xPixmapFormat) * screenInfo.numPixmapFormats; + memmove(pInfoT, pInfo, i); + pInfo += i; + pInfoT += i; + + for(i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + SwapWinRoot((xWindowRoot *)pInfo, (xWindowRoot *)pInfoT); + pInfo += sizeof(xWindowRoot); + pInfoT += sizeof(xWindowRoot); + pDepth = pScreen->allowedDepths; + for(j = 0; j < pScreen->numDepths; j++, pDepth++) + { + ((xDepth *)pInfoT)->depth = ((xDepth *)pInfo)->depth; + cpswaps(((xDepth *)pInfo)->nVisuals, ((xDepth *)pInfoT)->nVisuals); + pInfo += sizeof(xDepth); + pInfoT += sizeof(xDepth); + for(k = 0; k < pDepth->numVids; k++) + { + SwapVisual((xVisualType *)pInfo, (xVisualType *)pInfoT); + pInfo += sizeof(xVisualType); + pInfoT += sizeof(xVisualType); + } + } + } +} + + +void +WriteSConnectionInfo(pClient, size, pInfo) + ClientPtr pClient; + unsigned long size; + char *pInfo; +{ + char *pInfoTBase; + + pInfoTBase = (char *) ALLOCATE_LOCAL(size); + if (!pInfoTBase) + { + pClient->noClientException = -1; + return; + } + SwapConnSetupInfo(pInfo, pInfoTBase); + (void)WriteToClient(pClient, (int)size, (char *) pInfoTBase); + DEALLOCATE_LOCAL(pInfoTBase); +} + +void +SwapConnSetup(pConnSetup, pConnSetupT) + xConnSetup *pConnSetup, *pConnSetupT; +{ + cpswapl(pConnSetup->release, pConnSetupT->release); + cpswapl(pConnSetup->ridBase, pConnSetupT->ridBase); + cpswapl(pConnSetup->ridMask, pConnSetupT->ridMask); + cpswapl(pConnSetup->motionBufferSize, pConnSetupT->motionBufferSize); + cpswaps(pConnSetup->nbytesVendor, pConnSetupT->nbytesVendor); + cpswaps(pConnSetup->maxRequestSize, pConnSetupT->maxRequestSize); + pConnSetupT->minKeyCode = pConnSetup->minKeyCode; + pConnSetupT->maxKeyCode = pConnSetup->maxKeyCode; + pConnSetupT->numRoots = pConnSetup->numRoots; + pConnSetupT->numFormats = pConnSetup->numFormats; + pConnSetupT->imageByteOrder = pConnSetup->imageByteOrder; + pConnSetupT->bitmapBitOrder = pConnSetup->bitmapBitOrder; + pConnSetupT->bitmapScanlineUnit = pConnSetup->bitmapScanlineUnit; + pConnSetupT->bitmapScanlinePad = pConnSetup->bitmapScanlinePad; +} + +void +SwapWinRoot(pRoot, pRootT) + xWindowRoot *pRoot, *pRootT; +{ + cpswapl(pRoot->windowId, pRootT->windowId); + cpswapl(pRoot->defaultColormap, pRootT->defaultColormap); + cpswapl(pRoot->whitePixel, pRootT->whitePixel); + cpswapl(pRoot->blackPixel, pRootT->blackPixel); + cpswapl(pRoot->currentInputMask, pRootT->currentInputMask); + cpswaps(pRoot->pixWidth, pRootT->pixWidth); + cpswaps(pRoot->pixHeight, pRootT->pixHeight); + cpswaps(pRoot->mmWidth, pRootT->mmWidth); + cpswaps(pRoot->mmHeight, pRootT->mmHeight); + cpswaps(pRoot->minInstalledMaps, pRootT->minInstalledMaps); + cpswaps(pRoot->maxInstalledMaps, pRootT->maxInstalledMaps); + cpswapl(pRoot->rootVisualID, pRootT->rootVisualID); + pRootT->backingStore = pRoot->backingStore; + pRootT->saveUnders = pRoot->saveUnders; + pRootT->rootDepth = pRoot->rootDepth; + pRootT->nDepths = pRoot->nDepths; +} + +void +SwapVisual(pVis, pVisT) + xVisualType *pVis, *pVisT; +{ + cpswapl(pVis->visualID, pVisT->visualID); + pVisT->class = pVis->class; + pVisT->bitsPerRGB = pVis->bitsPerRGB; + cpswaps(pVis->colormapEntries, pVisT->colormapEntries); + cpswapl(pVis->redMask, pVisT->redMask); + cpswapl(pVis->greenMask, pVisT->greenMask); + cpswapl(pVis->blueMask, pVisT->blueMask); +} + +void +SwapConnSetupPrefix(pcspFrom, pcspTo) + xConnSetupPrefix *pcspFrom; + xConnSetupPrefix *pcspTo; +{ + pcspTo->success = pcspFrom->success; + pcspTo->lengthReason = pcspFrom->lengthReason; + cpswaps(pcspFrom->majorVersion, pcspTo->majorVersion); + cpswaps(pcspFrom->minorVersion, pcspTo->minorVersion); + cpswaps(pcspFrom->length, pcspTo->length); +} + +void +WriteSConnSetupPrefix(pClient, pcsp) + ClientPtr pClient; + xConnSetupPrefix *pcsp; +{ + xConnSetupPrefix cspT; + + SwapConnSetupPrefix(pcsp, &cspT); + (void)WriteToClient(pClient, sizeof(cspT), (char *) &cspT); +} diff --git a/dix/swapreq.c b/dix/swapreq.c new file mode 100644 index 000000000..d0b1a2525 --- /dev/null +++ b/dix/swapreq.c @@ -0,0 +1,1173 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + +/* $Xorg: swapreq.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "Xprotostr.h" +#include "misc.h" +#include "dixstruct.h" + +extern int (* ProcVector[256]) (); +extern void (* EventSwapVector[128]) (); /* for SendEvent */ + +/* Thanks to Jack Palevich for testing and subsequently rewriting all this */ + +/* Byte swap a list of longs */ + +void +SwapLongs (list, count) + register CARD32 *list; + register unsigned long count; +{ + register char n; + + while (count >= 8) { + swapl(list+0, n); + swapl(list+1, n); + swapl(list+2, n); + swapl(list+3, n); + swapl(list+4, n); + swapl(list+5, n); + swapl(list+6, n); + swapl(list+7, n); + list += 8; + count -= 8; + } + if (count != 0) { + do { + swapl(list, n); + list++; + } while (--count != 0); + } +} + +/* Byte swap a list of shorts */ + +void +SwapShorts (list, count) + register short *list; + register unsigned long count; +{ + register char n; + + while (count >= 16) { + swaps(list+0, n); + swaps(list+1, n); + swaps(list+2, n); + swaps(list+3, n); + swaps(list+4, n); + swaps(list+5, n); + swaps(list+6, n); + swaps(list+7, n); + swaps(list+8, n); + swaps(list+9, n); + swaps(list+10, n); + swaps(list+11, n); + swaps(list+12, n); + swaps(list+13, n); + swaps(list+14, n); + swaps(list+15, n); + list += 16; + count -= 16; + } + if (count != 0) { + do { + swaps(list, n); + list++; + } while (--count != 0); + } +} + +/* The following is used for all requests that have + no fields to be swapped (except "length") */ +int +SProcSimpleReq(client) + register ClientPtr client; +{ + register char n; + + REQUEST(xReq); + swaps(&stuff->length, n); + return(*ProcVector[stuff->reqType])(client); +} + +/* The following is used for all requests that have + only a single 32-bit field to be swapped, coming + right after the "length" field */ +int +SProcResourceReq(client) + register ClientPtr client; +{ + register char n; + + REQUEST(xResourceReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xResourceReq); /* not EXACT */ + swapl(&stuff->id, n); + return(*ProcVector[stuff->reqType])(client); +} + +int +SProcCreateWindow(client) + register ClientPtr client; +{ + register char n; + + REQUEST(xCreateWindowReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + swapl(&stuff->wid, n); + swapl(&stuff->parent, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swaps(&stuff->borderWidth, n); + swaps(&stuff->class, n); + swapl(&stuff->visual, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_CreateWindow])(client)); +} + +int +SProcChangeWindowAttributes(client) + register ClientPtr client; +{ + register char n; + + REQUEST(xChangeWindowAttributesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + swapl(&stuff->window, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return((* ProcVector[X_ChangeWindowAttributes])(client)); +} + +int +SProcReparentWindow(client) + register ClientPtr client; +{ + register char n; + REQUEST(xReparentWindowReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xReparentWindowReq); + swapl(&stuff->window, n); + swapl(&stuff->parent, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[X_ReparentWindow])(client)); +} + +int +SProcConfigureWindow(client) + register ClientPtr client; +{ + register char n; + REQUEST(xConfigureWindowReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + swapl(&stuff->window, n); + swaps(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_ConfigureWindow])(client)); + +} + + +int +SProcInternAtom(client) + register ClientPtr client; +{ + register char n; + REQUEST(xInternAtomReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xInternAtomReq); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_InternAtom])(client)); +} + +int +SProcChangeProperty(client) + register ClientPtr client; +{ + register char n; + REQUEST(xChangePropertyReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch ( stuff->format ) { + case 8 : + break; + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + } + return((* ProcVector[X_ChangeProperty])(client)); +} + +int +SProcDeleteProperty(client) + register ClientPtr client; +{ + register char n; + REQUEST(xDeletePropertyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDeletePropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + return((* ProcVector[X_DeleteProperty])(client)); + +} + +int +SProcGetProperty(client) + register ClientPtr client; +{ + register char n; + REQUEST(xGetPropertyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetPropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + return((* ProcVector[X_GetProperty])(client)); +} + +int +SProcSetSelectionOwner(client) + register ClientPtr client; +{ + register char n; + REQUEST(xSetSelectionOwnerReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + swapl(&stuff->window, n); + swapl(&stuff->selection, n); + swapl(&stuff->time, n); + return((* ProcVector[X_SetSelectionOwner])(client)); +} + +int +SProcConvertSelection(client) + register ClientPtr client; +{ + register char n; + REQUEST(xConvertSelectionReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xConvertSelectionReq); + swapl(&stuff->requestor, n); + swapl(&stuff->selection, n); + swapl(&stuff->target, n); + swapl(&stuff->property, n); + swapl(&stuff->time, n); + return((* ProcVector[X_ConvertSelection])(client)); +} + +int +SProcSendEvent(client) + register ClientPtr client; +{ + register char n; + xEvent eventT; + void (*proc)(), NotImplemented(); + REQUEST(xSendEventReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSendEventReq); + swapl(&stuff->destination, n); + swapl(&stuff->eventMask, n); + + /* Swap event */ + proc = EventSwapVector[stuff->event.u.u.type & 0177]; + if (!proc || (int (*)()) proc == (int (*)()) NotImplemented) /* no swapping proc; invalid event type? */ + return (BadValue); + (*proc)(&stuff->event, &eventT); + stuff->event = eventT; + + return((* ProcVector[X_SendEvent])(client)); +} + +int +SProcGrabPointer(client) + register ClientPtr client; +{ + register char n; + REQUEST(xGrabPointerReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabPointerReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->eventMask, n); + swapl(&stuff->confineTo, n); + swapl(&stuff->cursor, n); + swapl(&stuff->time, n); + return((* ProcVector[X_GrabPointer])(client)); +} + +int +SProcGrabButton(client) + register ClientPtr client; +{ + register char n; + REQUEST(xGrabButtonReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabButtonReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->eventMask, n); + swapl(&stuff->confineTo, n); + swapl(&stuff->cursor, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_GrabButton])(client)); +} + +int +SProcUngrabButton(client) + register ClientPtr client; +{ + register char n; + REQUEST(xUngrabButtonReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xUngrabButtonReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_UngrabButton])(client)); +} + +int +SProcChangeActivePointerGrab(client) + register ClientPtr client; +{ + register char n; + REQUEST(xChangeActivePointerGrabReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + swapl(&stuff->cursor, n); + swapl(&stuff->time, n); + swaps(&stuff->eventMask, n); + return((* ProcVector[X_ChangeActivePointerGrab])(client)); +} + +int +SProcGrabKeyboard(client) + register ClientPtr client; +{ + register char n; + REQUEST(xGrabKeyboardReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabKeyboardReq); + swapl(&stuff->grabWindow, n); + swapl(&stuff->time, n); + return((* ProcVector[X_GrabKeyboard])(client)); +} + +int +SProcGrabKey(client) + register ClientPtr client; +{ + register char n; + REQUEST(xGrabKeyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabKeyReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_GrabKey])(client)); +} + +int +SProcUngrabKey(client) + register ClientPtr client; +{ + register char n; + REQUEST(xUngrabKeyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xUngrabKeyReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_UngrabKey])(client)); +} + +int +SProcGetMotionEvents(client) + register ClientPtr client; +{ + register char n; + REQUEST(xGetMotionEventsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetMotionEventsReq); + swapl(&stuff->window, n); + swapl(&stuff->start, n); + swapl(&stuff->stop, n); + return((* ProcVector[X_GetMotionEvents])(client)); +} + +int +SProcTranslateCoords(client) + register ClientPtr client; +{ + register char n; + REQUEST(xTranslateCoordsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + swapl(&stuff->srcWid, n); + swapl(&stuff->dstWid, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + return((* ProcVector[X_TranslateCoords])(client)); +} + +int +SProcWarpPointer(client) + register ClientPtr client; +{ + register char n; + REQUEST(xWarpPointerReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xWarpPointerReq); + swapl(&stuff->srcWid, n); + swapl(&stuff->dstWid, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + return((* ProcVector[X_WarpPointer])(client)); +} + +int +SProcSetInputFocus(client) + register ClientPtr client; +{ + register char n; + REQUEST(xSetInputFocusReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetInputFocusReq); + swapl(&stuff->focus, n); + swapl(&stuff->time, n); + return((* ProcVector[X_SetInputFocus])(client)); +} + +int +SProcOpenFont(client) + register ClientPtr client; +{ + register char n; + REQUEST(xOpenFontReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xOpenFontReq); + swapl(&stuff->fid, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_OpenFont])(client)); +} + +int +SProcListFonts(client) + register ClientPtr client; +{ + register char n; + REQUEST(xListFontsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xListFontsReq); + swaps(&stuff->maxNames, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_ListFonts])(client)); +} + +int +SProcListFontsWithInfo(client) + register ClientPtr client; +{ + register char n; + REQUEST(xListFontsWithInfoReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xListFontsWithInfoReq); + swaps(&stuff->maxNames, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_ListFontsWithInfo])(client)); +} + +int +SProcSetFontPath(client) + register ClientPtr client; +{ + register char n; + REQUEST(xSetFontPathReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + swaps(&stuff->nFonts, n); + return((* ProcVector[X_SetFontPath])(client)); +} + +int +SProcCreatePixmap(client) + register ClientPtr client; +{ + register char n; + REQUEST(xCreatePixmapReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreatePixmapReq); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_CreatePixmap])(client)); +} + +int +SProcCreateGC(client) + register ClientPtr client; +{ + register char n; + REQUEST(xCreateGCReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + swapl(&stuff->gc, n); + swapl(&stuff->drawable, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_CreateGC])(client)); +} + +int +SProcChangeGC(client) + register ClientPtr client; +{ + register char n; + REQUEST(xChangeGCReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + swapl(&stuff->gc, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_ChangeGC])(client)); +} + +int +SProcCopyGC(client) + register ClientPtr client; +{ + register char n; + REQUEST(xCopyGCReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyGCReq); + swapl(&stuff->srcGC, n); + swapl(&stuff->dstGC, n); + swapl(&stuff->mask, n); + return((* ProcVector[X_CopyGC])(client)); +} + +int +SProcSetDashes(client) + register ClientPtr client; +{ + register char n; + REQUEST(xSetDashesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSetDashesReq); + swapl(&stuff->gc, n); + swaps(&stuff->dashOffset, n); + swaps(&stuff->nDashes, n); + return((* ProcVector[X_SetDashes])(client)); + +} + +int +SProcSetClipRectangles(client) + register ClientPtr client; +{ + register char n; + REQUEST(xSetClipRectanglesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + swapl(&stuff->gc, n); + swaps(&stuff->xOrigin, n); + swaps(&stuff->yOrigin, n); + SwapRestS(stuff); + return((* ProcVector[X_SetClipRectangles])(client)); +} + +int +SProcClearToBackground(client) + register ClientPtr client; +{ + register char n; + REQUEST(xClearAreaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xClearAreaReq); + swapl(&stuff->window, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_ClearArea])(client)); +} + +int +SProcCopyArea(client) + register ClientPtr client; +{ + register char n; + REQUEST(xCopyAreaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyAreaReq); + swapl(&stuff->srcDrawable, n); + swapl(&stuff->dstDrawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_CopyArea])(client)); +} + +int +SProcCopyPlane(client) + register ClientPtr client; +{ + register char n; + REQUEST(xCopyPlaneReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyPlaneReq); + swapl(&stuff->srcDrawable, n); + swapl(&stuff->dstDrawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->bitPlane, n); + return((* ProcVector[X_CopyPlane])(client)); +} + +/* The following routine is used for all Poly drawing requests + (except FillPoly, which uses a different request format) */ +int +SProcPoly(client) + register ClientPtr client; +{ + register char n; + + REQUEST(xPolyPointReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + SwapRestS(stuff); + return((* ProcVector[stuff->reqType])(client)); +} + +/* cannot use SProcPoly for this one, because xFillPolyReq + is longer than xPolyPointReq, and we don't want to swap + the difference as shorts! */ +int +SProcFillPoly(client) + register ClientPtr client; +{ + register char n; + + REQUEST(xFillPolyReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + SwapRestS(stuff); + return((* ProcVector[X_FillPoly])(client)); +} + +int +SProcPutImage(client) + register ClientPtr client; +{ + register char n; + REQUEST(xPutImageReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + /* Image should already be swapped */ + return((* ProcVector[X_PutImage])(client)); + +} + +int +SProcGetImage(client) + register ClientPtr client; +{ + register char n; + REQUEST(xGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + return((* ProcVector[X_GetImage])(client)); +} + +/* ProcPolyText used for both PolyText8 and PolyText16 */ + +int +SProcPolyText(client) + register ClientPtr client; +{ + register char n; + REQUEST(xPolyTextReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[stuff->reqType])(client)); +} + +/* ProcImageText used for both ImageText8 and ImageText16 */ + +int +SProcImageText(client) + register ClientPtr client; +{ + register char n; + REQUEST(xImageTextReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xImageTextReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[stuff->reqType])(client)); +} + +int +SProcCreateColormap(client) + register ClientPtr client; +{ + register char n; + REQUEST(xCreateColormapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreateColormapReq); + swapl(&stuff->mid, n); + swapl(&stuff->window, n); + swapl(&stuff->visual, n); + return((* ProcVector[X_CreateColormap])(client)); +} + + +int +SProcCopyColormapAndFree(client) + register ClientPtr client; +{ + register char n; + REQUEST(xCopyColormapAndFreeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + swapl(&stuff->mid, n); + swapl(&stuff->srcCmap, n); + return((* ProcVector[X_CopyColormapAndFree])(client)); + +} + +int +SProcAllocColor (client) + register ClientPtr client; +{ + register char n; + REQUEST(xAllocColorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xAllocColorReq); + swapl(&stuff->cmap, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + return((* ProcVector[X_AllocColor])(client)); +} + +int +SProcAllocNamedColor (client) + register ClientPtr client; +{ + register char n; + + REQUEST(xAllocNamedColorReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xAllocNamedColorReq); + swapl(&stuff->cmap, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_AllocNamedColor])(client)); +} + +int +SProcAllocColorCells (client) + register ClientPtr client; +{ + register char n; + REQUEST(xAllocColorCellsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->planes, n); + return((* ProcVector[X_AllocColorCells])(client)); +} + +int +SProcAllocColorPlanes(client) + register ClientPtr client; +{ + register char n; + REQUEST(xAllocColorPlanesReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + return((* ProcVector[X_AllocColorPlanes])(client)); +} + +int +SProcFreeColors (client) + register ClientPtr client; +{ + register char n; + REQUEST(xFreeColorsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + swapl(&stuff->cmap, n); + swapl(&stuff->planeMask, n); + SwapRestL(stuff); + return((* ProcVector[X_FreeColors])(client)); + +} + +void +SwapColorItem(pItem) + xColorItem *pItem; +{ + register char n; + + swapl(&pItem->pixel, n); + swaps(&pItem->red, n); + swaps(&pItem->green, n); + swaps(&pItem->blue, n); +} + +int +SProcStoreColors (client) + register ClientPtr client; +{ + register char n; + long count; + xColorItem *pItem; + + REQUEST(xStoreColorsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + swapl(&stuff->cmap, n); + pItem = (xColorItem *) &stuff[1]; + for(count = LengthRestB(stuff)/sizeof(xColorItem); --count >= 0; ) + SwapColorItem(pItem++); + return((* ProcVector[X_StoreColors])(client)); +} + +int +SProcStoreNamedColor (client) + register ClientPtr client; +{ + register char n; + REQUEST(xStoreNamedColorReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xStoreNamedColorReq); + swapl(&stuff->cmap, n); + swapl(&stuff->pixel, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_StoreNamedColor])(client)); +} + +int +SProcQueryColors(client) + register ClientPtr client; +{ + register char n; + REQUEST(xQueryColorsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + swapl(&stuff->cmap, n); + SwapRestL(stuff); + return((* ProcVector[X_QueryColors])(client)); +} + +int +SProcLookupColor(client) + register ClientPtr client; +{ + register char n; + REQUEST(xLookupColorReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xLookupColorReq); + swapl(&stuff->cmap, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_LookupColor])(client)); +} + +int +SProcCreateCursor( client) + register ClientPtr client; +{ + register char n; + REQUEST(xCreateCursorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreateCursorReq); + swapl(&stuff->cid, n); + swapl(&stuff->source, n); + swapl(&stuff->mask, n); + swaps(&stuff->foreRed, n); + swaps(&stuff->foreGreen, n); + swaps(&stuff->foreBlue, n); + swaps(&stuff->backRed, n); + swaps(&stuff->backGreen, n); + swaps(&stuff->backBlue, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[X_CreateCursor])(client)); +} + +int +SProcCreateGlyphCursor( client) + register ClientPtr client; +{ + register char n; + REQUEST(xCreateGlyphCursorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + swapl(&stuff->cid, n); + swapl(&stuff->source, n); + swapl(&stuff->mask, n); + swaps(&stuff->sourceChar, n); + swaps(&stuff->maskChar, n); + swaps(&stuff->foreRed, n); + swaps(&stuff->foreGreen, n); + swaps(&stuff->foreBlue, n); + swaps(&stuff->backRed, n); + swaps(&stuff->backGreen, n); + swaps(&stuff->backBlue, n); + return((* ProcVector[X_CreateGlyphCursor])(client)); +} + + +int +SProcRecolorCursor(client) + register ClientPtr client; +{ + register char n; + REQUEST(xRecolorCursorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecolorCursorReq); + swapl(&stuff->cursor, n); + swaps(&stuff->foreRed, n); + swaps(&stuff->foreGreen, n); + swaps(&stuff->foreBlue, n); + swaps(&stuff->backRed, n); + swaps(&stuff->backGreen, n); + swaps(&stuff->backBlue, n); + return((* ProcVector[X_RecolorCursor])(client)); +} + +int +SProcQueryBestSize (client) + register ClientPtr client; +{ + register char n; + REQUEST(xQueryBestSizeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_QueryBestSize])(client)); + +} + +int +SProcQueryExtension (client) + register ClientPtr client; +{ + register char n; + REQUEST(xQueryExtensionReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xQueryExtensionReq); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_QueryExtension])(client)); +} + +int +SProcChangeKeyboardMapping (client) + register ClientPtr client; +{ + register char n; + REQUEST(xChangeKeyboardMappingReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); + SwapRestL(stuff); + return((* ProcVector[X_ChangeKeyboardMapping])(client)); +} + + +int +SProcChangeKeyboardControl (client) + register ClientPtr client; +{ + register char n; + REQUEST(xChangeKeyboardControlReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_ChangeKeyboardControl])(client)); +} + +int +SProcChangePointerControl (client) + register ClientPtr client; +{ + register char n; + REQUEST(xChangePointerControlReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xChangePointerControlReq); + swaps(&stuff->accelNum, n); + swaps(&stuff->accelDenum, n); + swaps(&stuff->threshold, n); + return((* ProcVector[X_ChangePointerControl])(client)); +} + + +int +SProcSetScreenSaver (client) + register ClientPtr client; +{ + register char n; + REQUEST(xSetScreenSaverReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + swaps(&stuff->timeout, n); + swaps(&stuff->interval, n); + return((* ProcVector[X_SetScreenSaver])(client)); +} + +int +SProcChangeHosts(client) + register ClientPtr client; +{ + register char n; + + REQUEST(xChangeHostsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeHostsReq); + swaps(&stuff->hostLength, n); + return((* ProcVector[X_ChangeHosts])(client)); + +} + +int SProcRotateProperties(client) + register ClientPtr client; +{ + register char n; + REQUEST(xRotatePropertiesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRotatePropertiesReq); + swapl(&stuff->window, n); + swaps(&stuff->nAtoms, n); + swaps(&stuff->nPositions, n); + SwapRestL(stuff); + return ((* ProcVector[X_RotateProperties])(client)); +} + +/*ARGSUSED*/ +int +SProcNoOperation(client) + ClientPtr client; +{ + register char n; + REQUEST(xReq); + swaps(&stuff->length, n); + return ((* ProcVector[X_NoOperation])(client)); +} + +void +SwapConnClientPrefix(pCCP) + xConnClientPrefix *pCCP; +{ + register char n; + + swaps(&pCCP->majorVersion, n); + swaps(&pCCP->minorVersion, n); + swaps(&pCCP->nbytesAuthProto, n); + swaps(&pCCP->nbytesAuthString, n); +} diff --git a/dix/tables.c b/dix/tables.c new file mode 100644 index 000000000..7c84bdc96 --- /dev/null +++ b/dix/tables.c @@ -0,0 +1,615 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: tables.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ + +extern int ProcInitialConnection(), ProcEstablishConnection(); + +extern int ProcBadRequest(), ProcCreateWindow(), + ProcChangeWindowAttributes(), ProcGetWindowAttributes(), + ProcDestroyWindow(), ProcDestroySubwindows(), ProcChangeSaveSet(), + ProcReparentWindow(), ProcMapWindow(), ProcMapSubwindows(), + ProcUnmapWindow(), ProcUnmapSubwindows(), ProcConfigureWindow(), + ProcCirculateWindow(), ProcGetGeometry(), ProcQueryTree(), + ProcInternAtom(), ProcGetAtomName(), ProcChangeProperty(), + ProcDeleteProperty(), ProcGetProperty(), ProcListProperties(), + ProcSetSelectionOwner(), ProcGetSelectionOwner(), ProcConvertSelection(), + ProcSendEvent(), ProcGrabPointer(), ProcUngrabPointer(), + ProcGrabButton(), ProcUngrabButton(), ProcChangeActivePointerGrab(), + ProcGrabKeyboard(), ProcUngrabKeyboard(), ProcGrabKey(), + ProcUngrabKey(), ProcAllowEvents(), ProcGrabServer(), + ProcUngrabServer(), ProcQueryPointer(), ProcGetMotionEvents(), + ProcTranslateCoords(), ProcWarpPointer(), ProcSetInputFocus(), + ProcGetInputFocus(), ProcQueryKeymap(), ProcOpenFont(), + ProcCloseFont(), ProcQueryFont(), ProcQueryTextExtents(), + ProcListFonts(), ProcListFontsWithInfo(), ProcSetFontPath(), + ProcGetFontPath(), ProcCreatePixmap(), ProcFreePixmap(), + ProcCreateGC(), ProcChangeGC(), ProcCopyGC(), + ProcSetDashes(), ProcSetClipRectangles(), ProcFreeGC(), + ProcClearToBackground(), ProcCopyArea(), ProcCopyPlane(), + ProcPolyPoint(), ProcPolyLine(), ProcPolySegment(), + ProcPolyRectangle(), ProcPolyArc(), ProcFillPoly(), + ProcPolyFillRectangle(), ProcPolyFillArc(), ProcPutImage(), + ProcGetImage(), ProcPolyText(), + ProcImageText8(), ProcImageText16(), ProcCreateColormap(), + ProcFreeColormap(), ProcCopyColormapAndFree(), ProcInstallColormap(), + ProcUninstallColormap(), ProcListInstalledColormaps(), ProcAllocColor(), + ProcAllocNamedColor(), ProcAllocColorCells(), ProcAllocColorPlanes(), + ProcFreeColors(), ProcStoreColors(), ProcStoreNamedColor(), + ProcQueryColors(), ProcLookupColor(), ProcCreateCursor(), + ProcCreateGlyphCursor(), ProcFreeCursor(), ProcRecolorCursor(), + ProcQueryBestSize(), ProcQueryExtension(), ProcListExtensions(), + ProcChangeKeyboardMapping(), ProcSetPointerMapping(), + ProcGetKeyboardMapping(), ProcGetPointerMapping(), + ProcChangeKeyboardControl(), + ProcGetKeyboardControl(), ProcBell(), ProcChangePointerControl(), + ProcGetPointerControl(), ProcSetScreenSaver(), ProcGetScreenSaver(), + ProcChangeHosts(), ProcListHosts(), ProcChangeAccessControl(), + ProcChangeCloseDownMode(), ProcKillClient(), + ProcRotateProperties(), ProcForceScreenSaver(), + ProcSetModifierMapping(), ProcGetModifierMapping(), + ProcNoOperation(); + +extern int SProcSProcBadRequest(), SProcCreateWindow(), + SProcChangeWindowAttributes(), + SProcReparentWindow(), SProcConfigureWindow(), + SProcInternAtom(), SProcChangeProperty(), + SProcDeleteProperty(), SProcGetProperty(), + SProcSetSelectionOwner(), + SProcConvertSelection(), + SProcSendEvent(), SProcGrabPointer(), + SProcGrabButton(), SProcUngrabButton(), SProcChangeActivePointerGrab(), + SProcGrabKeyboard(), SProcGrabKey(), + SProcUngrabKey(), SProcGetMotionEvents(), + SProcTranslateCoords(), SProcWarpPointer(), SProcSetInputFocus(), + SProcOpenFont(), + SProcListFonts(), SProcListFontsWithInfo(), SProcSetFontPath(), + SProcCreatePixmap(), + SProcCreateGC(), SProcChangeGC(), SProcCopyGC(), + SProcSetDashes(), SProcSetClipRectangles(), + SProcClearToBackground(), SProcCopyArea(), SProcCopyPlane(), + SProcPoly(), SProcFillPoly(), SProcPutImage(), + SProcGetImage(), SProcPolyText(), + SProcImageText(), SProcCreateColormap(), + SProcCopyColormapAndFree(), SProcAllocColor(), + SProcAllocNamedColor(), SProcAllocColorCells(), SProcAllocColorPlanes(), + SProcFreeColors(), SProcStoreColors(), SProcStoreNamedColor(), + SProcQueryColors(), SProcLookupColor(), SProcCreateCursor(), + SProcCreateGlyphCursor(), SProcRecolorCursor(), + SProcQueryBestSize(), SProcQueryExtension(), + SProcChangeKeyboardMapping(), SProcChangeKeyboardControl(), + SProcChangePointerControl(), + SProcSetScreenSaver(), + SProcChangeHosts(), + SProcRotateProperties(), + SProcNoOperation(), SProcResourceReq(), SProcSimpleReq(); + +extern void + SErrorEvent(), NotImplemented(), SKeyButtonPtrEvent(), SEnterLeaveEvent(), + SFocusEvent(), SKeymapNotifyEvent(), SExposeEvent(), + SGraphicsExposureEvent(), SNoExposureEvent(), SVisibilityEvent(), + SCreateNotifyEvent(), SDestroyNotifyEvent(), SUnmapNotifyEvent(), + SMapNotifyEvent(), SMapRequestEvent(), SReparentEvent(), + SConfigureNotifyEvent(), SConfigureRequestEvent(), SGravityEvent(), + SResizeRequestEvent(), SCirculateEvent(), + SPropertyEvent(), SSelectionClearEvent(), SSelectionRequestEvent(), + SSelectionNotifyEvent(), SColormapEvent(), SClientMessageEvent(), SMappingEvent(); + +extern void + SGetWindowAttributesReply(), SGetGeometryReply(), SQueryTreeReply(), + SInternAtomReply(), SGetAtomNameReply(), SGetPropertyReply(), + SListPropertiesReply(), + SGetSelectionOwnerReply(), + SQueryPointerReply(), SGetMotionEventsReply(), STranslateCoordsReply(), + SGetInputFocusReply(), SQueryKeymapReply(), SQueryFontReply(), + SQueryTextExtentsReply(), SListFontsReply(), SListFontsWithInfoReply(), + SGetFontPathReply(), SGetImageReply(), SListInstalledColormapsReply(), + SAllocColorReply(), SAllocNamedColorReply(), SAllocColorCellsReply(), + SAllocColorPlanesReply(), SQueryColorsReply(), SLookupColorReply(), + SQueryBestSizeReply(), SListExtensionsReply(), + SGetKeyboardMappingReply(), SGetKeyboardControlReply(), + SGetPointerControlReply(), SGetScreenSaverReply(), + SListHostsReply(), SGetPointerMappingReply(), + SGetModifierMappingReply(), SGenericReply(); + +#ifdef K5AUTH +extern int + k5_stage1(), k5_stage2(), k5_stage3(), k5_bad(); +#endif + +int (* InitialVector[3]) () = +{ + 0, + ProcInitialConnection, + ProcEstablishConnection +}; + +int (* ProcVector[256]) () = +{ + ProcBadRequest, + ProcCreateWindow, + ProcChangeWindowAttributes, + ProcGetWindowAttributes, + ProcDestroyWindow, + ProcDestroySubwindows, /* 5 */ + ProcChangeSaveSet, + ProcReparentWindow, + ProcMapWindow, + ProcMapSubwindows, + ProcUnmapWindow, /* 10 */ + ProcUnmapSubwindows, + ProcConfigureWindow, + ProcCirculateWindow, + ProcGetGeometry, + ProcQueryTree, /* 15 */ + ProcInternAtom, + ProcGetAtomName, + ProcChangeProperty, + ProcDeleteProperty, + ProcGetProperty, /* 20 */ + ProcListProperties, + ProcSetSelectionOwner, + ProcGetSelectionOwner, + ProcConvertSelection, + ProcSendEvent, /* 25 */ + ProcGrabPointer, + ProcUngrabPointer, + ProcGrabButton, + ProcUngrabButton, + ProcChangeActivePointerGrab, /* 30 */ + ProcGrabKeyboard, + ProcUngrabKeyboard, + ProcGrabKey, + ProcUngrabKey, + ProcAllowEvents, /* 35 */ + ProcGrabServer, + ProcUngrabServer, + ProcQueryPointer, + ProcGetMotionEvents, + ProcTranslateCoords, /* 40 */ + ProcWarpPointer, + ProcSetInputFocus, + ProcGetInputFocus, + ProcQueryKeymap, + ProcOpenFont, /* 45 */ + ProcCloseFont, + ProcQueryFont, + ProcQueryTextExtents, + ProcListFonts, + ProcListFontsWithInfo, /* 50 */ + ProcSetFontPath, + ProcGetFontPath, + ProcCreatePixmap, + ProcFreePixmap, + ProcCreateGC, /* 55 */ + ProcChangeGC, + ProcCopyGC, + ProcSetDashes, + ProcSetClipRectangles, + ProcFreeGC, /* 60 */ + ProcClearToBackground, + ProcCopyArea, + ProcCopyPlane, + ProcPolyPoint, + ProcPolyLine, /* 65 */ + ProcPolySegment, + ProcPolyRectangle, + ProcPolyArc, + ProcFillPoly, + ProcPolyFillRectangle, /* 70 */ + ProcPolyFillArc, + ProcPutImage, + ProcGetImage, + ProcPolyText, + ProcPolyText, /* 75 */ + ProcImageText8, + ProcImageText16, + ProcCreateColormap, + ProcFreeColormap, + ProcCopyColormapAndFree, /* 80 */ + ProcInstallColormap, + ProcUninstallColormap, + ProcListInstalledColormaps, + ProcAllocColor, + ProcAllocNamedColor, /* 85 */ + ProcAllocColorCells, + ProcAllocColorPlanes, + ProcFreeColors, + ProcStoreColors, + ProcStoreNamedColor, /* 90 */ + ProcQueryColors, + ProcLookupColor, + ProcCreateCursor, + ProcCreateGlyphCursor, + ProcFreeCursor, /* 95 */ + ProcRecolorCursor, + ProcQueryBestSize, + ProcQueryExtension, + ProcListExtensions, + ProcChangeKeyboardMapping, /* 100 */ + ProcGetKeyboardMapping, + ProcChangeKeyboardControl, + ProcGetKeyboardControl, + ProcBell, + ProcChangePointerControl, /* 105 */ + ProcGetPointerControl, + ProcSetScreenSaver, + ProcGetScreenSaver, + ProcChangeHosts, + ProcListHosts, /* 110 */ + ProcChangeAccessControl, + ProcChangeCloseDownMode, + ProcKillClient, + ProcRotateProperties, + ProcForceScreenSaver, /* 115 */ + ProcSetPointerMapping, + ProcGetPointerMapping, + ProcSetModifierMapping, + ProcGetModifierMapping, + 0, /* 120 */ + 0, + 0, + 0, + 0, + 0, /* 125 */ + 0, + ProcNoOperation +}; + +int (* SwappedProcVector[256]) () = +{ + ProcBadRequest, + SProcCreateWindow, + SProcChangeWindowAttributes, + SProcResourceReq, /* GetWindowAttributes */ + SProcResourceReq, /* DestroyWindow */ + SProcResourceReq, /* 5 DestroySubwindows */ + SProcResourceReq, /* SProcChangeSaveSet, */ + SProcReparentWindow, + SProcResourceReq, /* MapWindow */ + SProcResourceReq, /* MapSubwindows */ + SProcResourceReq, /* 10 UnmapWindow */ + SProcResourceReq, /* UnmapSubwindows */ + SProcConfigureWindow, + SProcResourceReq, /* SProcCirculateWindow, */ + SProcResourceReq, /* GetGeometry */ + SProcResourceReq, /* 15 QueryTree */ + SProcInternAtom, + SProcResourceReq, /* SProcGetAtomName, */ + SProcChangeProperty, + SProcDeleteProperty, + SProcGetProperty, /* 20 */ + SProcResourceReq, /* SProcListProperties, */ + SProcSetSelectionOwner, + SProcResourceReq, /* SProcGetSelectionOwner, */ + SProcConvertSelection, + SProcSendEvent, /* 25 */ + SProcGrabPointer, + SProcResourceReq, /* SProcUngrabPointer, */ + SProcGrabButton, + SProcUngrabButton, + SProcChangeActivePointerGrab, /* 30 */ + SProcGrabKeyboard, + SProcResourceReq, /* SProcUngrabKeyboard, */ + SProcGrabKey, + SProcUngrabKey, + SProcResourceReq, /* 35 SProcAllowEvents, */ + SProcSimpleReq, /* SProcGrabServer, */ + SProcSimpleReq, /* SProcUngrabServer, */ + SProcResourceReq, /* SProcQueryPointer, */ + SProcGetMotionEvents, + SProcTranslateCoords, /*40 */ + SProcWarpPointer, + SProcSetInputFocus, + SProcSimpleReq, /* SProcGetInputFocus, */ + SProcSimpleReq, /* QueryKeymap, */ + SProcOpenFont, /* 45 */ + SProcResourceReq, /* SProcCloseFont, */ + SProcResourceReq, /* SProcQueryFont, */ + SProcResourceReq, /* SProcQueryTextExtents, */ + SProcListFonts, + SProcListFontsWithInfo, /* 50 */ + SProcSetFontPath, + SProcSimpleReq, /* GetFontPath, */ + SProcCreatePixmap, + SProcResourceReq, /* SProcFreePixmap, */ + SProcCreateGC, /* 55 */ + SProcChangeGC, + SProcCopyGC, + SProcSetDashes, + SProcSetClipRectangles, + SProcResourceReq, /* 60 SProcFreeGC, */ + SProcClearToBackground, + SProcCopyArea, + SProcCopyPlane, + SProcPoly, /* PolyPoint, */ + SProcPoly, /* 65 PolyLine */ + SProcPoly, /* PolySegment, */ + SProcPoly, /* PolyRectangle, */ + SProcPoly, /* PolyArc, */ + SProcFillPoly, + SProcPoly, /* 70 PolyFillRectangle */ + SProcPoly, /* PolyFillArc, */ + SProcPutImage, + SProcGetImage, + SProcPolyText, + SProcPolyText, /* 75 */ + SProcImageText, + SProcImageText, + SProcCreateColormap, + SProcResourceReq, /* SProcFreeColormap, */ + SProcCopyColormapAndFree, /* 80 */ + SProcResourceReq, /* SProcInstallColormap, */ + SProcResourceReq, /* SProcUninstallColormap, */ + SProcResourceReq, /* SProcListInstalledColormaps, */ + SProcAllocColor, + SProcAllocNamedColor, /* 85 */ + SProcAllocColorCells, + SProcAllocColorPlanes, + SProcFreeColors, + SProcStoreColors, + SProcStoreNamedColor, /* 90 */ + SProcQueryColors, + SProcLookupColor, + SProcCreateCursor, + SProcCreateGlyphCursor, + SProcResourceReq, /* 95 SProcFreeCursor, */ + SProcRecolorCursor, + SProcQueryBestSize, + SProcQueryExtension, + SProcSimpleReq, /* ListExtensions, */ + SProcChangeKeyboardMapping, /* 100 */ + SProcSimpleReq, /* GetKeyboardMapping, */ + SProcChangeKeyboardControl, + SProcSimpleReq, /* GetKeyboardControl, */ + SProcSimpleReq, /* Bell, */ + SProcChangePointerControl, /* 105 */ + SProcSimpleReq, /* GetPointerControl, */ + SProcSetScreenSaver, + SProcSimpleReq, /* GetScreenSaver, */ + SProcChangeHosts, + SProcSimpleReq, /* 110 ListHosts, */ + SProcSimpleReq, /* SProcChangeAccessControl, */ + SProcSimpleReq, /* SProcChangeCloseDownMode, */ + SProcResourceReq, /* SProcKillClient, */ + SProcRotateProperties, + SProcSimpleReq, /* 115 ForceScreenSaver */ + SProcSimpleReq, /* SetPointerMapping, */ + SProcSimpleReq, /* GetPointerMapping, */ + SProcSimpleReq, /* SetModifierMapping, */ + SProcSimpleReq, /* GetModifierMapping, */ + 0, /* 120 */ + 0, + 0, + 0, + 0, + 0, /* 125 */ + 0, + SProcNoOperation +}; + +void (* EventSwapVector[128]) () = +{ + SErrorEvent, + NotImplemented, + SKeyButtonPtrEvent, + SKeyButtonPtrEvent, + SKeyButtonPtrEvent, + SKeyButtonPtrEvent, /* 5 */ + SKeyButtonPtrEvent, + SEnterLeaveEvent, + SEnterLeaveEvent, + SFocusEvent, + SFocusEvent, /* 10 */ + SKeymapNotifyEvent, + SExposeEvent, + SGraphicsExposureEvent, + SNoExposureEvent, + SVisibilityEvent, /* 15 */ + SCreateNotifyEvent, + SDestroyNotifyEvent, + SUnmapNotifyEvent, + SMapNotifyEvent, + SMapRequestEvent, /* 20 */ + SReparentEvent, + SConfigureNotifyEvent, + SConfigureRequestEvent, + SGravityEvent, + SResizeRequestEvent, /* 25 */ + SCirculateEvent, + SCirculateEvent, + SPropertyEvent, + SSelectionClearEvent, + SSelectionRequestEvent, /* 30 */ + SSelectionNotifyEvent, + SColormapEvent, + SClientMessageEvent, + SMappingEvent, +}; + + +void (* ReplySwapVector[256]) () = +{ + NotImplemented, + NotImplemented, + NotImplemented, + SGetWindowAttributesReply, + NotImplemented, + NotImplemented, /* 5 */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 10 */ + NotImplemented, + NotImplemented, + NotImplemented, + SGetGeometryReply, + SQueryTreeReply, /* 15 */ + SInternAtomReply, + SGetAtomNameReply, + NotImplemented, + NotImplemented, + SGetPropertyReply, /* 20 */ + SListPropertiesReply, + NotImplemented, + SGetSelectionOwnerReply, + NotImplemented, + NotImplemented, /* 25 */ + SGenericReply, /* SGrabPointerReply, */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 30 */ + SGenericReply, /* SGrabKeyboardReply, */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 35 */ + NotImplemented, + NotImplemented, + SQueryPointerReply, + SGetMotionEventsReply, + STranslateCoordsReply, /* 40 */ + NotImplemented, + NotImplemented, + SGetInputFocusReply, + SQueryKeymapReply, + NotImplemented, /* 45 */ + NotImplemented, + SQueryFontReply, + SQueryTextExtentsReply, + SListFontsReply, + SListFontsWithInfoReply, /* 50 */ + NotImplemented, + SGetFontPathReply, + NotImplemented, + NotImplemented, + NotImplemented, /* 55 */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 60 */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 65 */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 70 */ + NotImplemented, + NotImplemented, + SGetImageReply, + NotImplemented, + NotImplemented, /* 75 */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 80 */ + NotImplemented, + NotImplemented, + SListInstalledColormapsReply, + SAllocColorReply, + SAllocNamedColorReply, /* 85 */ + SAllocColorCellsReply, + SAllocColorPlanesReply, + NotImplemented, + NotImplemented, + NotImplemented, /* 90 */ + SQueryColorsReply, + SLookupColorReply, + NotImplemented, + NotImplemented, + NotImplemented, /* 95 */ + NotImplemented, + SQueryBestSizeReply, + SGenericReply, /* SQueryExtensionReply, */ + SListExtensionsReply, + NotImplemented, /* 100 */ + SGetKeyboardMappingReply, + NotImplemented, + SGetKeyboardControlReply, + NotImplemented, + NotImplemented, /* 105 */ + SGetPointerControlReply, + NotImplemented, + SGetScreenSaverReply, + NotImplemented, + SListHostsReply, /* 110 */ + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, /* 115 */ + SGenericReply, /* SetPointerMapping */ + SGetPointerMappingReply, + SGenericReply, /* SetModifierMapping */ + SGetModifierMappingReply, /* 119 */ + NotImplemented, /* 120 */ + NotImplemented, /* 121 */ + NotImplemented, /* 122 */ + NotImplemented, /* 123 */ + NotImplemented, /* 124 */ + NotImplemented, /* 125 */ + NotImplemented, /* 126 */ + NotImplemented, /* NoOperation */ + NotImplemented +}; + +#ifdef K5AUTH +int (*k5_Vector[256])() = +{ + k5_bad, + k5_stage1, + k5_bad, + k5_stage3 +}; +#endif diff --git a/dix/window.c b/dix/window.c new file mode 100644 index 000000000..b24c48376 --- /dev/null +++ b/dix/window.c @@ -0,0 +1,3698 @@ +/* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +*/ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#ifdef XAPPGROUP +#include "extensions/Xagsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +extern Bool permitOldBugs; + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11}; +static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88}; + +int screenIsSaved = SCREEN_SAVER_OFF; + +ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +extern WindowPtr *WindowTable; + +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +extern int rand(); + +static Bool TileScreenSaver( +#if NeedFunctionPrototypes + int /*i*/, + int /*kind*/ +#endif +); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +int numSaveUndersViewable = 0; +int deltaSaveUndersViewable = 0; + +#ifdef DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(p1, indent) + WindowPtr p1; + int indent; +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; idrawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; iclipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +int +TraverseTree(pWin, func, data) + register WindowPtr pWin; + VisitWindowProcPtr func; + pointer data; +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +int +WalkTree(pScreen, func, data) + ScreenPtr pScreen; + VisitWindowProcPtr func; + pointer data; +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +SetWindowToDefaults(pWin) + register WindowPtr pWin; +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +} + +static void +MakeRootTile(pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + GCPtr pGC; + unsigned char back[128]; + int len = BitmapBytePad(sizeof(long)); + register unsigned char *from, *to; + register int i, j; + + pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, len, 4, + pScreen->rootDepth); + + pWin->backgroundState = BackgroundPixmap; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pWin->background.pixmap || !pGC) + FatalError("cound not create root tile"); + + { + CARD32 attributes[2]; + + attributes[0] = pScreen->whitePixel; + attributes[1] = pScreen->blackPixel; + + (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); + } + + ValidateGC((DrawablePtr)pWin->background.pixmap, pGC); + + from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb; + to = back; + + for (i = 4; i > 0; i--, from++) + for (j = len; j > 0; j--) + *to++ = *from; + + (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, + 0, 0, len, 4, 0, XYBitmap, (char *)back); + + FreeScratchGC(pGC); + +} + +WindowPtr +AllocateWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + pScreen->backingStoreSupport = NotUseful; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +void +InitRootWindow(pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + MakeRootTile(pWin); + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + + MapWindow(pWin, serverClient); +} + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(pWin, Rgn, x, y, w, h) + register WindowPtr pWin; + RegionPtr Rgn; + register int x, y; + int w, h; +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +WindowPtr +RealChildHead(pWin) + register WindowPtr pWin; +{ + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +WindowPtr +CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist, + depth, client, visual, error) + Window wid; + register WindowPtr pParent; + int x,y; + unsigned int w, h, bw; + unsigned int class; + register Mask vmask; + XID *vlist; + int depth; + ClientPtr client; + VisualID visual; + int *error; +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (client->trustLevel != XSecurityClientTrusted) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_INIT(pScreen, &pWin->clipList, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderClip, NullBox, 1); + REGION_INIT(pScreen, &pWin->winSize, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderSize, NullBox, 1); + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + + return pWin; +} + +static void +FreeWindowResources(pWin) + register WindowPtr pWin; +{ + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +CrushTree(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild, pSib, pParent; + Bool (* UnrealizeWindow)(); + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +/*ARGSUSED*/ +int +DeleteWindow(value, wid) + pointer value; + XID wid; + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + xfree(pWin); + return Success; +} + +/*ARGSUSED*/ +void +DestroySubwindows(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +int +ChangeWindowAttributes(pWin, vmask, vlist, client) + register WindowPtr pWin; + Mask vmask; + XID *vlist; + ClientPtr client; +{ + register Mask index; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index = (Mask) lowbit (tmask); + tmask &= ~index; + switch (index) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows */ + if (client->trustLevel == XSecurityClientTrusted) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XCSECURITY + } + else + { /* didn't change the background to None, so don't tell ddx */ + index = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != ~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == ~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if (win_owner->appgroup && !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_INIT(pScreen, &exposed, NullBox, 0); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(pWin, client, wa) + register WindowPtr pWin; + ClientPtr client; + xGetWindowAttributesReply *wa; +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +WindowPtr +MoveWindowInStack(pWin, pNextSib) + register WindowPtr pWin, pNextSib; +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + } + + return( pFirstChange ); +} + +RegionPtr +CreateUnclippedWinSize (pWin) + register WindowPtr pWin; +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +void +SetWinSize (pWin) + register WindowPtr pWin; +{ + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +void +SetBorderSize (pWin) + register WindowPtr pWin; +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +void +GravityTranslate (x, y, oldx, oldy, dw, dh, gravity, destx, desty) + register int x, y; /* new window position */ + int oldx, oldy; /* old window position */ + int dw, dh; + unsigned gravity; + register int *destx, *desty; /* position relative to gravity */ +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +void +ResizeChildrenWinSize(pWin, dx, dy, dw, dh) + register WindowPtr pWin; + int dx, dy, dw, dh; +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + (*pScreen->PositionWindow)(pChild, + pChild->drawable.x, pChild->drawable.y); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +IsSiblingAboveMe(pMe, pSib) + register WindowPtr pMe, pSib; +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +WindowExtents(pWin, pBox) + register WindowPtr pWin; + register BoxPtr pBox; +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +MakeBoundingRegion (pWin, pBox) + register WindowPtr pWin; + BoxPtr pBox; +{ + RegionPtr pRgn; + register ScreenPtr pScreen = pWin->drawable.pScreen; + + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +ShapeOverlap (pWin, pWinBox, pSib, pSibBox) + WindowPtr pWin, pSib; + BoxPtr pWinBox, pSibBox; +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +AnyWindowOverlapsMe(pWin, pHead, box) + WindowPtr pWin, pHead; + register BoxPtr box; +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +IOverlapAnyWindow(pWin, box) + WindowPtr pWin; + register BoxPtr box; +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode) + register WindowPtr pWin, pSib; + short x, y; + unsigned short w, h; + int smode; +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +ReflectStackChange(pWin, pSib, kind) + register WindowPtr pWin, pSib; + VTKind kind; +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + WindowPtr pParent; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!(pParent = pWin->parent)) + return ; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(pWin, mask, vlist, client) + register WindowPtr pWin; + register Mask mask; + XID *vlist; + ClientPtr client; +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid; + Mask index, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index = (Mask)lowbit (tmask); + tmask &= ~index; + switch (index) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { + if (pWin->nextSib != pSib) + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(pParent, direction, client) + WindowPtr pParent; + int direction; + ClientPtr client; +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +CompareWIDs(pWin, value) + WindowPtr pWin; + pointer value; /* must conform to VisitWindowProcPtr */ +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(pWin, pParent, x, y, client) + register WindowPtr pWin, pParent; + int x,y; + ClientPtr client; +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +RealizeTree(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + Bool (* Realize)(); + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +int +MapWindow(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (pWin->mapped) + return(Success); + +#ifdef XCSECURITY + /* don't let an untrusted client map a child-of-trusted-window, InputOnly + * window; too easy to steal device input + */ + if ( (client->trustLevel != XSecurityClientTrusted) && + (pWin->drawable.class == InputOnly) && + (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) ) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_INIT(pScreen, &temp, NullBox, 0); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(pParent, client) + register WindowPtr pParent; + ClientPtr client; +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +UnrealizeTree(pWin, fromConfigure) + WindowPtr pWin; + Bool fromConfigure; +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +int +UnmapWindow(pWin, fromConfigure) + register WindowPtr pWin; + Bool fromConfigure; +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(pWin) + register WindowPtr pWin; +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; jnumSaved; j++) + { + pWin = (WindowPtr)client->saveSet[j]; + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (pointer *)NULL; +} + +Bool +VisibleBoundingBoxFromPoint(pWin, x, y, box) + register WindowPtr pWin; + int x, y; /* in root */ + BoxPtr box; /* "return" value */ +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +Bool +PointInWindowIsVisible(pWin, x, y) + register WindowPtr pWin; + int x, y; /* in root */ +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box)) + return(TRUE); + return(FALSE); +} + + +RegionPtr +NotClippedByChildren(pWin) + register WindowPtr pWin; +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + + +void +SendVisibilityNotify(pWin) + WindowPtr pWin; +{ + xEvent event; + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = pWin->visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +extern int logoScreenSaver; +static void DrawLogo( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); +#endif + +void +SaveScreens(on, mode) + int on; + int mode; +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; +} + +static Bool +TileScreenSaver(i, kind) + int i; + int kind; +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; jwidth + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +WindowPtr +FindWindowWithOptional (w) + register WindowPtr w; +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +void +CheckWindowOptionalNeed (w) + register WindowPtr w; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +Bool +MakeWindowOptional (pWin) + register WindowPtr pWin; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (pWin) + register WindowPtr pWin; +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + if (pWin->cursorIsNone == FALSE) + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = TRUE; + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +DrawLogo(pWin) + WindowPtr pWin; +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif diff --git a/dix/xpstubs.c b/dix/xpstubs.c new file mode 100644 index 000000000..2702b453d --- /dev/null +++ b/dix/xpstubs.c @@ -0,0 +1,54 @@ +/* +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. +*/ + +/* $Xorg: xpstubs.c,v 1.5 2001/03/08 17:52:08 pookie Exp $ */ + +#include "misc.h" +#include "font.h" + +Bool +XpClientIsBitmapClient(client) + ClientPtr client; +{ + return TRUE; +} + +Bool +XpClientIsPrintClient(client, fpe) + ClientPtr client; + FontPathElementPtr fpe; +{ + return FALSE; +} + +int +XprintOptions(argc, argv, i) + int argc; + char **argv; + int i; +{ + return i; +} diff --git a/doc/Xserver.man.pre b/doc/Xserver.man.pre new file mode 100644 index 000000000..75cc34c4c --- /dev/null +++ b/doc/Xserver.man.pre @@ -0,0 +1,679 @@ +.\" $Xorg: Xserver.man,v 1.4 2001/02/09 02:04:07 xorgcvs Exp $ +.\" Copyright 1984 - 1991, 1993, 1994, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.TH XSERVER 1 "Release 6.4" "X Version 11" +.SH NAME +Xserver \- X Window System display server +.SH SYNOPSIS +.B X +[option ...] +.SH DESCRIPTION +.I X +is the generic name for the X Window System display server. It is +frequently a link or a copy of the appropriate server binary for +driving the most frequently used server on a given machine. +.SH "STARTING THE SERVER" +The X server is usually started from the X Display Manager program \fIxdm(1)\fP. +This utility is run from the system boot files and takes care of keeping +the server running, prompting for usernames and passwords, and starting up +the user sessions. +.PP +Installations that run more than one window system may need to use the +\fIxinit(1)\fP utility instead of \fIxdm\fP. However, \fIxinit\fP is +to be considered a tool for building startup scripts and is not +intended for use by end users. Site administrators are \fBstrongly\fP +urged to use \fIxdm\fP, or build other interfaces for novice users. +.PP +The X server may also be started directly by the user, though this +method is usually reserved for testing and is not recommended for +normal operation. On some platforms, the user must have special +permission to start the X server, often because access to certain +devices (e.g. /dev/mouse) is restricted. +.PP +When the X server starts up, it typically takes over the display. If +you are running on a workstation whose console is the display, you may +not be able to log into the console while the server is running. +.SH OPTIONS +All of the X servers accept the following command line options: +.TP 8 +.B :\fIdisplaynumber\fP +the X server runs as the given \fIdisplaynumber\fP, which by default is 0. +If multiple X servers are to run simultaneously on a host, each must have +a unique display number. See the DISPLAY +NAMES section of the \fIX(1)\fP manual page to learn how to specify +which display number clients should try to use. +.TP 8 +.B \-a \fInumber\fP +sets pointer acceleration (i.e. the ratio of how much is reported to how much +the user actually moved the pointer). +.TP 8 +.B \-ac +disables host-based access control mechanisms. Enables access by any host, +and permits any host to modify the access control list. +Use with extreme caution. +This option exists primarily for running test suites remotely. +.TP 8 +.B \-audit \fIlevel\fP +Sets the audit trail level. The default level is 1, meaning only connection +rejections are reported. Level 2 additionally reports all successful +connections and disconnects. Level 4 enables messages from the +SECURITY extension, if present, including generation and revocation of +authorizations and violations of the security policy. +Level 0 turns off the audit trail. +Audit lines are sent as standard error output. +.TP 8 +.B \-auth \fIauthorization-file\fP +Specifies a file which contains a collection of authorization records used +to authenticate access. See also the \fIxdm\fP and \fIXsecurity\fP manual +pages. +.TP 8 +.B bc +disables certain kinds of error checking, for bug compatibility with +previous releases (e.g., to work around bugs in R2 and R3 xterms and toolkits). +Deprecated. +.TP 8 +.B \-bs +disables backing store support on all screens. +.TP 8 +.B \-c +turns off key-click. +.TP 8 +.B c \fIvolume\fP +sets key-click volume (allowable range: 0-100). +.TP 8 +.B \-cc \fIclass\fP +sets the visual class for the root window of color screens. +The class numbers are as specified in the X protocol. +Not obeyed by all servers. +.TP 8 +.B \-co \fIfilename\fP +sets name of RGB color database. The default is /lib/X11/rgb, +where refers to the root of the X11 install tree. +.TP 8 +.B \-config \fIfilename\fP +reads more options from the given file. Options in the file may be separated +by newlines if desired. If a '#' character appears on a line, all characters +between it and the next newline are ignored, providing a simple commenting +facility. The \fB\-config\fP option itself may appear in the file. +.TP 8 +.B \-core +causes the server to generate a core dump on fatal errors. +.TP 8 +.B \-dpi \fIresolution\fP +sets the resolution of the screen, in dots per inch. +To be used when the server cannot determine the screen size from the hardware. +.TP 8 +.B \-deferglyphs \fIwhichfonts\fP +specifies the types of fonts for which the server should attempt to use +deferred glyph loading. \fIwhichfonts\fP can be all (all fonts), +none (no fonts), or 16 (16 bit fonts only). +.TP 8 +.B \-f \fIvolume\fP +sets feep (bell) volume (allowable range: 0-100). +.TP 8 +.B \-fc \fIcursorFont\fP +sets default cursor font. +.TP 8 +.B \-fn \fIfont\fP +sets the default font. +.TP 8 +.B \-fp \fIfontPath\fP +sets the search path for fonts. This path is a comma separated list +of directories which the X server searches for font databases. +.TP 8 +.B \-help +prints a usage message. +.TP 8 +.B \-I +causes all remaining command line arguments to be ignored. +.TP 8 +.B \-kb +disables the XKEYBOARD extension if present. +.TP 8 +.B \-p \fIminutes\fP +sets screen-saver pattern cycle time in minutes. +.TP 8 +.B \-pn +permits the server to continue running if it fails to establish all of +its well-known sockets (connection points for clients), but +establishes at least one. +.TP 8 +.B \-r +turns off auto-repeat. +.TP 8 +.B r +turns on auto-repeat. +.TP 8 +.B \-s \fIminutes\fP +sets screen-saver timeout time in minutes. +.TP 8 +.B \-su +disables save under support on all screens. +.TP 8 +.B \-t \fInumber\fP +sets pointer acceleration threshold in pixels (i.e. after how many pixels +pointer acceleration should take effect). +.TP 8 +.B \-terminate +causes the server to terminate at server reset, instead of continuing to run. +.TP 8 +.B \-to \fIseconds\fP +sets default connection timeout in seconds. +.TP 8 +.B \-tst +disables all testing extensions (e.g., XTEST, XTrap, XTestExtension1, RECORD). +.TP 8 +.B tty\fIxx\fP +ignored, for servers started the ancient way (from init). +.TP 8 +.B v +sets video-off screen-saver preference. +.TP 8 +.B \-v +sets video-on screen-saver preference. +.TP 8 +.B \-wm +forces the default backing-store of all windows to be WhenMapped. This +is a backdoor way of getting backing-store to apply to all windows. +Although all mapped windows will have backing store, the backing store +attribute value reported by the server for a window will be the last +value established by a client. If it has never been set by a client, +the server will report the default value, NotUseful. This behavior is +required by the X protocol, which allows the server to exceed the +client's backing store expectations but does not provide a way to tell +the client that it is doing so. +.TP 8 +.B \-x \fIextension\fP +loads the specified extension at init. +This is a no-op for most implementations. +.TP 8 +.B [+-]xinerama +enable(+) or disable(-) XINERAMA extension. Default is disabled. +.SH SERVER DEPENDENT OPTIONS +Some X servers accept the following options: +.TP 8 +.B \-ld \fIkilobytes\fP +sets the data space limit of the server to the specified number of kilobytes. +A value of zero makes the data size as large as possible. The default value +of \-1 leaves the data space limit unchanged. +.TP 8 +.B \-lf \fIfiles\fP +sets the number-of-open-files limit of the server to the specified number. +A value of zero makes the limit as large as possible. The default value +of \-1 leaves the limit unchanged. +.TP 8 +.B \-ls \fIkilobytes\fP +sets the stack space limit of the server to the specified number of kilobytes. +A value of zero makes the stack size as large as possible. The default value +of \-1 leaves the stack space limit unchanged. +.TP 8 +.B \-logo +turns on the X Window System logo display in the screen-saver. +There is currently no way to change this from a client. +.TP 8 +.B nologo +turns off the X Window System logo display in the screen-saver. +There is currently no way to change this from a client. +.SH XDMCP OPTIONS +X servers that support XDMCP have the following options. +See the \fIX Display Manager Control Protocol\fP specification for more +information. +.TP 8 +.B \-query \fIhost-name\fP +Enable XDMCP and send Query packets to the specified host. +.TP 8 +.B \-broadcast +Enable XDMCP and broadcast BroadcastQuery packets to the network. The +first responding display manager will be chosen for the session. +.TP 8 +.B \-indirect \fIhost-name\fP +Enable XDMCP and send IndirectQuery packets to the specified host. +.TP 8 +.B \-port \fIport-num\fP +Use an alternate port number for XDMCP packets. Must be specified before +any \-query, \-broadcast or \-indirect options. +.TP 8 +.B \-class \fIdisplay-class\fP +XDMCP has an additional display qualifier used in resource lookup for +display-specific options. This option sets that value, by default it +is "MIT-Unspecified" (not a very useful value). +.TP 8 +.B \-cookie \fIxdm-auth-bits\fP +When testing XDM-AUTHENTICATION-1, a private key is shared between the +server and the manager. This option sets the value of that private +data (not that it is very private, being on the command line!). +.TP 8 +.B \-displayID \fIdisplay-id\fP +Yet another XDMCP specific value, this one allows the display manager to +identify each display so that it can locate the shared key. +.SH XKEYBOARD OPTIONS +X servers that support the XKEYBOARD extension accept the following options: +.TP 8 +.B \-xkbdir \fIdirectory\fP +base directory for keyboard layout files +.TP 8 +.B \-xkbmap \fIfilename\fP +keyboard description to load on startup +.TP 8 +.B [+-]accessx +enable(+) or disable(-) AccessX key sequences +.TP 8 +.B \-ar1 \fImilliseconds\fP +sets the length of time in milliseconds that a key must be depressed before +autorepeat starts +.TP 8 +.B \-ar2 \fImilliseconds\fP +sets the length of time in milliseconds that should elapse between +autorepeat-generated keystrokes +.PP +Many servers also have device-specific command line options. See the +manual pages for the individual servers for more details. +.SH SECURITY EXTENSION OPTIONS +X servers that support the SECURITY extension accept the following option: +.TP 8 +.B \-sp \fIfilename\fP +causes +the server to attempt to read and interpret filename as a security policy +file with the format described below. The file is read at +server startup and reread at each server reset. +.PP +The syntax of the security policy file is as follows. +Notation: "*" means zero or more occurrences of the preceding element, +and "+" means one or more occurrences. To interpret , ignore +the text after the /; it is used to distinguish between instances of + in the next section. +.PP +.nf + ::= * + + ::= '\en' + + ::= | | | + + ::= # * '\en' + + ::= '\en' + + ::= sitepolicy '\en' + + ::= property '\en' + + ::= + + ::= any | root | + + ::= | + + ::= = + + ::= [ | | ]* + + ::= r | w | d + + ::= a | i | e + + ::= | | + + ::= " * " + + ::= ' * ' + + ::= + + + ::= [ ' ' | '\et' ]* + +Character sets: + + ::= any character except '\en' + ::= any character except " + ::= any character except ' + ::= any character except those in +.fi +.PP +The semantics associated with the above syntax are as follows. +.PP +, the first line in the file, specifies the file format +version. If the server does not recognize the version , it +ignores the rest of the file. The version string for the file format +described here is "version-1" . +.PP +Once past the , lines that do not match the above syntax +are ignored. +.PP + lines are ignored. +.PP + lines are currently ignored. They are intended to +specify the site policies used by the XC-QUERY-SECURITY-1 +authorization method. +.PP + lines specify how the server should react to untrusted +client requests that affect the X Window property named . +The rest of this section describes the interpretation of an +. +.PP +For an to apply to a given instance of , + must be on a window that is in the set of windows +specified by . If is any, the rule applies to + on any window. If is root, the rule applies to + only on root windows. +.PP +If is , the following apply. If is a , the rule applies when the window also +has that , regardless of its value. If is a , must also have +the value specified by . In this case, the property must +have type STRING and format 8, and should contain one or more +null-terminated strings. If any of the strings match , the +rule applies. +.PP +The definition of string matching is simple case-sensitive string +comparison with one elaboration: the occurence of the character '*' in + is a wildcard meaning "any string." A can +contain multiple wildcards anywhere in the string. For example, "x*" +matches strings that begin with x, "*x" matches strings that end with +x, "*x*" matches strings containing x, and "x*y*" matches strings that +start with x and subsequently contain y. +.PP +There may be multiple lines for a given . +The rules are tested in the order that they appear in the file. The +first rule that applies is used. +.PP + specify operations that untrusted clients may attempt, and +the actions that the server should take in response to those operations. +.PP + can be r (read), w (write), or d (delete). The following +table shows how X Protocol property requests map to these operations +in The Open Group server implementation. +.PP +.nf +GetProperty r, or r and d if delete = True +ChangeProperty w +RotateProperties r and w +DeleteProperty d +ListProperties none, untrusted clients can always list all properties +.fi +.PP + can be a (allow), i (ignore), or e (error). Allow means +execute the request as if it had been issued by a trusted client. +Ignore means treat the request as a no-op. In the case of +GetProperty, ignore means return an empty property value if the +property exists, regardless of its actual value. Error means do not +execute the request and return a BadAtom error with the atom set to +the property name. Error is the default action for all properties, +including those not listed in the security policy file. +.PP +An applies to all s that follow it, until the next + is encountered. Thus, irwad means ignore read and write, +allow delete. +.PP +GetProperty and RotateProperties may do multiple operations (r and d, +or r and w). If different actions apply to the operations, the most +severe action is applied to the whole request; there is no partial +request execution. The severity ordering is: allow < ignore < error. +Thus, if the for a property are ired (ignore read, error +delete), and an untrusted client attempts GetProperty on that property +with delete = True, an error is returned, but the property value is +not. Similarly, if any of the properties in a RotateProperties do not +allow both read and write, an error is returned without changing any +property values. +.PP +Here is an example security policy file. +.PP +.ta 3i 4i +.nf +version-1 + +# Allow reading of application resources, but not writing. +property RESOURCE_MANAGER root ar iw +property SCREEN_RESOURCES root ar iw + +# Ignore attempts to use cut buffers. Giving errors causes apps to crash, +# and allowing access may give away too much information. +property CUT_BUFFER0 root irw +property CUT_BUFFER1 root irw +property CUT_BUFFER2 root irw +property CUT_BUFFER3 root irw +property CUT_BUFFER4 root irw +property CUT_BUFFER5 root irw +property CUT_BUFFER6 root irw +property CUT_BUFFER7 root irw + +# If you are using Motif, you probably want these. +property _MOTIF_DEFAULT_BINDINGS root ar iw +property _MOTIF_DRAG_WINDOW root ar iw +property _MOTIF_DRAG_TARGETS any ar iw +property _MOTIF_DRAG_ATOMS any ar iw +property _MOTIF_DRAG_ATOM_PAIRS any ar iw + +# The next two rules let xwininfo -tree work when untrusted. +property WM_NAME any ar + +# Allow read of WM_CLASS, but only for windows with WM_NAME. +# This might be more restrictive than necessary, but demonstrates +# the facility, and is also an attempt to +# say "top level windows only." +property WM_CLASS WM_NAME ar + +# These next three let xlsclients work untrusted. Think carefully +# before including these; giving away the client machine name and command +# may be exposing too much. +property WM_STATE WM_NAME ar +property WM_CLIENT_MACHINE WM_NAME ar +property WM_COMMAND WM_NAME ar + +# To let untrusted clients use the standard colormaps created by +# xstdcmap, include these lines. +property RGB_DEFAULT_MAP root ar +property RGB_BEST_MAP root ar +property RGB_RED_MAP root ar +property RGB_GREEN_MAP root ar +property RGB_BLUE_MAP root ar +property RGB_GRAY_MAP root ar + +# To let untrusted clients use the color management database created +# by xcmsdb, include these lines. +property XDCCC_LINEAR_RGB_CORRECTION root ar +property XDCCC_LINEAR_RGB_MATRICES root ar +property XDCCC_GRAY_SCREENWHITEPOINT root ar +property XDCCC_GRAY_CORRECTION root ar + +# To let untrusted clients use the overlay visuals that many vendors +# support, include this line. +property SERVER_OVERLAY_VISUALS root ar + +# Dumb examples to show other capabilities. + +# oddball property names and explicit specification of error conditions +property "property with spaces" 'property with "' aw er ed + +# Allow deletion of Woo-Hoo if window also has property OhBoy with value +# ending in "son". Reads and writes will cause an error. +property Woo-Hoo OhBoy = "*son" ad + +.fi +.SH "NETWORK CONNECTIONS" +The X server supports client connections via a platform-dependent subset of +the following transport types: TCP\/IP, Unix Domain sockets, DECnet, +and several varieties of SVR4 local connections. See the DISPLAY +NAMES section of the \fIX(1)\fP manual page to learn how to specify +which transport type clients should try to use. +.SH GRANTING ACCESS +The X server implements a platform-dependent subset of the following +authorization protocols: MIT-MAGIC-COOKIE-1, XDM-AUTHORIZATION-1, +SUN-DES-1, and MIT-KERBEROS-5. See the \fIXsecurity(1)\fP manual page +for information on the operation of these protocols. +.PP +Authorization data required by the above protocols is passed to the +server in a private file named with the \fB\-auth\fP command line +option. Each time the server is about to accept the first connection +after a reset (or when the server is starting), it reads this file. +If this file contains any authorization records, the local host is not +automatically allowed access to the server, and only clients which +send one of the authorization records contained in the file in the +connection setup information will be allowed access. See the +\fIXau\fP manual page for a description of the binary format of this +file. See \fIxauth(1)\fP for maintenance of this file, and distribution +of its contents to remote hosts. +.PP +The X server also uses a host-based access control list for deciding +whether or not to accept connections from clients on a particular machine. +If no other authorization mechanism is being used, +this list initially consists of the host on which the server is running as +well as any machines listed in the file \fI/etc/X\fBn\fI.hosts\fR, where +\fBn\fP is the display number of the server. Each line of the file should +contain either an Internet hostname (e.g. expo.lcs.mit.edu) or a DECnet +hostname in double colon format (e.g. hydra::). There should be no leading +or trailing spaces on any lines. For example: +.sp +.in +8 +.nf +joesworkstation +corporate.company.com +star:: +bigcpu:: +.fi +.in -8 +.PP +Users can add or remove hosts from this list and enable or disable access +control using the \fIxhost\fP command from the same machine as the server. +.PP +If the X FireWall Proxy (\fIxfwp\fP) is being used without a sitepolicy, +host-based authorization must be turned on for clients to be able to +connect to the X server via the \fIxfwp\fP. If \fIxfwp\fP is run without +a configuration file and thus no sitepolicy is defined, if \fIxfwp\fP +is using an X server where xhost + has been run to turn off host-based +authorization checks, when a client tries to connect to this X server +via \fIxfwp\fP, the X server will deny the connection. See \fIxfwp(1)\fP +for more information about this proxy. +.PP +The X protocol intrinsically does not have any notion of window operation +permissions or place any restrictions on what a client can do; if a program can +connect to a display, it has full run of the screen. +X servers that support the SECURITY extension fare better because clients +can be designated untrusted via the authorization they use to connect; see +the \fIxauth(1)\fP manual page for details. Restrictions are imposed +on untrusted clients that curtail the mischief they can do. See the SECURITY +extension specification for a complete list of these restrictions. +.PP +Sites that have better +authentication and authorization systems might wish to make +use of the hooks in the libraries and the server to provide additional +security models. +.SH SIGNALS +The X server attaches special meaning to the following signals: +.TP 8 +.I SIGHUP +This signal causes the server to close all existing connections, free all +resources, and restore all defaults. It is sent by the display manager +whenever the main user's main application (usually an \fIxterm\fP or window +manager) exits to force the server to clean up and prepare for the next +user. +.TP 8 +.I SIGTERM +This signal causes the server to exit cleanly. +.TP 8 +.I SIGUSR1 +This signal is used quite differently from either of the above. When the +server starts, it checks to see if it has inherited SIGUSR1 as SIG_IGN +instead of the usual SIG_DFL. In this case, the server sends a SIGUSR1 to +its parent process after it has set up the various connection schemes. +\fIXdm\fP uses this feature to recognize when connecting to the server +is possible. +.SH FONTS +The X server +can obtain fonts from directories and/or from font servers. +The list of directories and font servers +the X server uses when trying to open a font is controlled +by the \fIfont path\fP. +.LP +The default font path is +"/lib/X11/fonts/misc/, +/lib/X11/fonts/Speedo/, +/lib/X11/fonts/Type1/, +/lib/X11/fonts/75dpi/, +/lib/X11/fonts/100dpi/" . +where refers to the root of the X11 install tree. +.LP +The font path can be set with the \fB\-fp\fP option or by \fIxset(1)\fP +after the server has started. +.SH FILES +.TP 30 +/etc/X\fBn\fP.hosts +Initial access control list for display number \fBn\fP +.TP 30 +/lib/X11/fonts/misc, /lib/X11/fonts/75dpi, /lib/X11/fonts/100dpi +Bitmap font directories +.TP 30 +/lib/X11/fonts/Speedo, /lib/X11/fonts/Type1 +Outline font directories +.TP 30 +/lib/X11/fonts/PEX +PEX font directories +.TP 30 +/lib/X11/rgb.txt +Color database +.TP 30 +/tmp/.X11-unix/X\fBn\fP +Unix domain socket for display number \fBn\fP +.TP 30 +/tmp/rcX\fBn\fP +Kerberos 5 replay cache for display number \fBn\fP +.TP 30 +/usr/adm/X\fBn\fPmsgs +Error log file for display number \fBn\fP if run from \fIinit(8)\fP +.TP 30 +/lib/X11/xdm/xdm-errors +Default error log file if the server is run from \fIxdm(1)\fP +.LP +Note: refers to the root of the X11 install tree. +.SH "SEE ALSO" +General information: X(1) +.PP +Protocols: +.I "X Window System Protocol," +.I "The X Font Service Protocol," +.I "X Display Manager Control Protocol" +.PP +Fonts: bdftopcf(1), mkfontdir(1), xfs(1), xlsfonts(1), xfontsel(1), xfd(1), +.I "X Logical Font Description Conventions" +.PP +Security: Xsecurity(1), xauth(1), Xau(1), xdm(1), xhost(1), xfwp(1) +.I "Security Extension Specification" +.PP +Starting the server: xdm(1), xinit(1) +.PP +Controlling the server once started: xset(1), xsetroot(1), xhost(1) +.PP +Server-specific man pages: +Xdec(1), XmacII(1), Xsun(1), Xnest(1), Xvfb(1), +XF86_Accel(1), XF86_Mono(1), XF86_SVGA(1), XF86_VGA16(1), XFree86(1) +.PP +Server internal documentation: +.I "Definition of the Porting Layer for the X v11 Sample Server" +.SH AUTHORS +The sample server was originally written by Susan Angebranndt, Raymond +Drewry, Philip Karlton, and Todd Newman, from Digital Equipment +Corporation, with support from a large cast. It has since been +extensively rewritten by Keith Packard and Bob Scheifler, from MIT. +Dave Wiggins took over post-R5 and made substantial improvements. diff --git a/hw/vfb/InitInput.c b/hw/vfb/InitInput.c new file mode 100644 index 000000000..255c56f8e --- /dev/null +++ b/hw/vfb/InitInput.c @@ -0,0 +1,357 @@ +/* $Xorg: InitInput.c,v 1.4 2001/02/09 02:04:44 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X11/X.h" +#define NEED_EVENTS +#include "X11/Xproto.h" +#include "scrnintstr.h" +#include "inputstr.h" +#include "X11/Xos.h" +#include "mibstore.h" +#include "mipointer.h" +#include "lk201kbd.h" +#include "keysym.h" + +Bool +LegalModifier(key, pDev) + unsigned int key; + DevicePtr pDev; +{ + return TRUE; +} + +void +ProcessInputEvents() +{ + mieqProcessInputEvents(); + miPointerUpdate(); +} + +#define VFB_MIN_KEY 8 +#define VFB_MAX_KEY 255 +KeySym map[MAP_LENGTH * LK201_GLYPHS_PER_KEY]; + +/* The only reason for using the LK201 mappings here was that they were + * easy to lift. + */ +static Bool +GetLK201Mappings(pKeySyms, pModMap) + KeySymsPtr pKeySyms; + CARD8 *pModMap; +{ +#define INDEX(in) ((in - VFB_MIN_KEY) * LK201_GLYPHS_PER_KEY) + int i; + + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + pModMap[ KEY_LOCK ] = LockMask; + pModMap[ KEY_SHIFT ] = ShiftMask; + pModMap[ KEY_CTRL ] = ControlMask; + pModMap[ KEY_COMPOSE ] = Mod1Mask; + + pKeySyms->minKeyCode = VFB_MIN_KEY; + pKeySyms->maxKeyCode = VFB_MAX_KEY; + pKeySyms->mapWidth = LK201_GLYPHS_PER_KEY; + pKeySyms->map = map; + + for (i = 0; i < (MAP_LENGTH * LK201_GLYPHS_PER_KEY); i++) + map[i] = NoSymbol; /* make sure it is restored */ + + map[INDEX(KEY_F1)] = XK_F1; + map[INDEX(KEY_F2)] = XK_F2; + map[INDEX(KEY_F3)] = XK_F3; + map[INDEX(KEY_F4)] = XK_F4; + map[INDEX(KEY_F5)] = XK_F5; + map[INDEX(KEY_F6)] = XK_F6; + map[INDEX(KEY_F7)] = XK_F7; + map[INDEX(KEY_F8)] = XK_F8; + map[INDEX(KEY_F9)] = XK_F9; + map[INDEX(KEY_F10)] = XK_F10; + map[INDEX(KEY_F11)] = XK_F11; + map[INDEX(KEY_F12)] = XK_F12; + map[INDEX(KEY_F13)] = XK_F13; + map[INDEX(KEY_F14)] = XK_F14; + + map[INDEX(KEY_HELP)] = XK_Help; + map[INDEX(KEY_MENU)] = XK_Menu; + + map[INDEX(KEY_F17)] = XK_F17; + map[INDEX(KEY_F18)] = XK_F18; + map[INDEX(KEY_F19)] = XK_F19; + map[INDEX(KEY_F20)] = XK_F20; + + map[INDEX(KEY_FIND)] = XK_Find; + map[INDEX(KEY_INSERT_HERE)] = XK_Insert; + map[INDEX(KEY_REMOVE)] = XK_Delete; + map[INDEX(KEY_SELECT)] = XK_Select; + map[INDEX(KEY_PREV_SCREEN)] = XK_Prior; + map[INDEX(KEY_NEXT_SCREEN)] = XK_Next; + + map[INDEX(KEY_KP_0)] = XK_KP_0; + map[INDEX(KEY_KP_PERIOD)] = XK_KP_Decimal; + map[INDEX(KEY_KP_ENTER)] = XK_KP_Enter; + map[INDEX(KEY_KP_1)] = XK_KP_1; + map[INDEX(KEY_KP_2)] = XK_KP_2; + map[INDEX(KEY_KP_3)] = XK_KP_3; + map[INDEX(KEY_KP_4)] = XK_KP_4; + map[INDEX(KEY_KP_5)] = XK_KP_5; + map[INDEX(KEY_KP_6)] = XK_KP_6; + map[INDEX(KEY_KP_COMMA)] = XK_KP_Separator; + map[INDEX(KEY_KP_7)] = XK_KP_7; + map[INDEX(KEY_KP_8)] = XK_KP_8; + map[INDEX(KEY_KP_9)] = XK_KP_9; + map[INDEX(KEY_KP_HYPHEN)] = XK_KP_Subtract; + map[INDEX(KEY_KP_PF1)] = XK_KP_F1; + map[INDEX(KEY_KP_PF2)] = XK_KP_F2; + map[INDEX(KEY_KP_PF3)] = XK_KP_F3; + map[INDEX(KEY_KP_PF4)] = XK_KP_F4; + + map[INDEX(KEY_LEFT)] = XK_Left; + map[INDEX(KEY_RIGHT)] = XK_Right; + map[INDEX(KEY_DOWN)] = XK_Down; + map[INDEX(KEY_UP)] = XK_Up; + + map[INDEX(KEY_SHIFT)] = XK_Shift_L; + map[INDEX(KEY_CTRL)] = XK_Control_L; + map[INDEX(KEY_LOCK)] = XK_Caps_Lock; + map[INDEX(KEY_COMPOSE)] = XK_Multi_key; + map[INDEX(KEY_COMPOSE)+1] = XK_Meta_L; + map[INDEX(KEY_DELETE)] = XK_Delete; + map[INDEX(KEY_RETURN)] = XK_Return; + map[INDEX(KEY_TAB)] = XK_Tab; + + map[INDEX(KEY_TILDE)] = XK_quoteleft; + map[INDEX(KEY_TILDE)+1] = XK_asciitilde; + + map[INDEX(KEY_TR_1)] = XK_1; + map[INDEX(KEY_TR_1)+1] = XK_exclam; + map[INDEX(KEY_Q)] = XK_Q; + map[INDEX(KEY_A)] = XK_A; + map[INDEX(KEY_Z)] = XK_Z; + + map[INDEX(KEY_TR_2)] = XK_2; + map[INDEX(KEY_TR_2)+1] = XK_at; + + map[INDEX(KEY_W)] = XK_W; + map[INDEX(KEY_S)] = XK_S; + map[INDEX(KEY_X)] = XK_X; + + map[INDEX(KEY_LANGLE_RANGLE)] = XK_less; + map[INDEX(KEY_LANGLE_RANGLE)+1] = XK_greater; + + map[INDEX(KEY_TR_3)] = XK_3; + map[INDEX(KEY_TR_3)+1] = XK_numbersign; + + map[INDEX(KEY_E)] = XK_E; + map[INDEX(KEY_D)] = XK_D; + map[INDEX(KEY_C)] = XK_C; + + map[INDEX(KEY_TR_4)] = XK_4; + map[INDEX(KEY_TR_4)+1] = XK_dollar; + + map[INDEX(KEY_R)] = XK_R; + map[INDEX(KEY_F)] = XK_F; + map[INDEX(KEY_V)] = XK_V; + map[INDEX(KEY_SPACE)] = XK_space; + + map[INDEX(KEY_TR_5)] = XK_5; + map[INDEX(KEY_TR_5)+1] = XK_percent; + + map[INDEX(KEY_T)] = XK_T; + map[INDEX(KEY_G)] = XK_G; + map[INDEX(KEY_B)] = XK_B; + + map[INDEX(KEY_TR_6)] = XK_6; + map[INDEX(KEY_TR_6)+1] = XK_asciicircum; + + map[INDEX(KEY_Y)] = XK_Y; + map[INDEX(KEY_H)] = XK_H; + map[INDEX(KEY_N)] = XK_N; + + map[INDEX(KEY_TR_7)] = XK_7; + map[INDEX(KEY_TR_7)+1] = XK_ampersand; + + map[INDEX(KEY_U)] = XK_U; + map[INDEX(KEY_J)] = XK_J; + map[INDEX(KEY_M)] = XK_M; + + map[INDEX(KEY_TR_8)] = XK_8; + map[INDEX(KEY_TR_8)+1] = XK_asterisk; + + map[INDEX(KEY_I)] = XK_I; + map[INDEX(KEY_K)] = XK_K; + + map[INDEX(KEY_COMMA)] = XK_comma; + map[INDEX(KEY_COMMA)+1] = XK_less; + + map[INDEX(KEY_TR_9)] = XK_9; + map[INDEX(KEY_TR_9)+1] = XK_parenleft; + + map[INDEX(KEY_O)] = XK_O; + map[INDEX(KEY_L)] = XK_L; + + map[INDEX(KEY_PERIOD)] = XK_period; + map[INDEX(KEY_PERIOD)+1] = XK_greater; + + map[INDEX(KEY_TR_0)] = XK_0; + map[INDEX(KEY_TR_0)+1] = XK_parenright; + + map[INDEX(KEY_P)] = XK_P; + + map[INDEX(KEY_SEMICOLON)] = XK_semicolon; + map[INDEX(KEY_SEMICOLON)+1] = XK_colon; + + map[INDEX(KEY_QMARK)] = XK_slash; + map[INDEX(KEY_QMARK)+1] = XK_question; + + map[INDEX(KEY_PLUS)] = XK_equal; + map[INDEX(KEY_PLUS)+1] = XK_plus; + + map[INDEX(KEY_RBRACE)] = XK_bracketright; + map[INDEX(KEY_RBRACE)+1] = XK_braceright; + + map[INDEX(KEY_VBAR)] = XK_backslash; + map[INDEX(KEY_VBAR)+1] = XK_bar; + + map[INDEX(KEY_UBAR)] = XK_minus; + map[INDEX(KEY_UBAR)+1] = XK_underscore; + + map[INDEX(KEY_LBRACE)] = XK_bracketleft; + map[INDEX(KEY_LBRACE)+1] = XK_braceleft; + + map[INDEX(KEY_QUOTE)] = XK_quoteright; + map[INDEX(KEY_QUOTE)+1] = XK_quotedbl; + + map[INDEX(KEY_F11)] = XK_Escape; + + return TRUE; +#undef INDEX +} + +static int +vfbKeybdProc(pDevice, onoff) + DeviceIntPtr pDevice; + int onoff; +{ + KeySymsRec keySyms; + CARD8 modMap[MAP_LENGTH]; + int i; + DevicePtr pDev = (DevicePtr)pDevice; + + switch (onoff) + { + case DEVICE_INIT: + GetLK201Mappings(&keySyms, modMap); + InitKeyboardDeviceStruct(pDev, &keySyms, modMap, + (BellProcPtr)NoopDDA, (KbdCtrlProcPtr)NoopDDA); + break; + case DEVICE_ON: + pDev->on = TRUE; + break; + case DEVICE_OFF: + pDev->on = FALSE; + break; + case DEVICE_CLOSE: + break; + } + return Success; +} + +static int +vfbMouseProc(pDevice, onoff) + DeviceIntPtr pDevice; + int onoff; +{ + BYTE map[4]; + DevicePtr pDev = (DevicePtr)pDevice; + + switch (onoff) + { + case DEVICE_INIT: + map[1] = 1; + map[2] = 2; + map[3] = 3; + InitPointerDeviceStruct(pDev, map, 3, miPointerGetMotionEvents, + (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize()); + break; + + case DEVICE_ON: + pDev->on = TRUE; + break; + + case DEVICE_OFF: + pDev->on = FALSE; + break; + + case DEVICE_CLOSE: + break; + } + return Success; +} + +void +InitInput(argc, argv) + int argc; + char *argv[]; +{ + DevicePtr p, k; + p = AddInputDevice(vfbMouseProc, TRUE); + k = AddInputDevice(vfbKeybdProc, TRUE); + RegisterPointerDevice(p); + RegisterKeyboardDevice(k); + miRegisterPointerDevice(screenInfo.screens[0], p); + (void)mieqInit (k, p); +} + +#ifdef XTESTEXT1 +void +XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey) + int dev_type; + int keycode; + int keystate; + int mousex; + int mousey; +{ +} + +void +XTestGetPointerPos(fmousex, fmousey) + short *fmousex, *fmousey; +{ +} + +void +XTestJumpPointer(jx, jy, dev_type) + int jx; + int jy; + int dev_type; +{ +} +#endif + diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c new file mode 100644 index 000000000..c2334e745 --- /dev/null +++ b/hw/vfb/InitOutput.c @@ -0,0 +1,981 @@ +/* $Xorg: InitOutput.c,v 1.4 2001/02/09 02:04:45 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef WIN32 +#include +#endif +#include +#include "X11/X.h" +#define NEED_EVENTS +#include "X11/Xproto.h" +#include "X11/Xos.h" +#include "scrnintstr.h" +#include "servermd.h" +#define PSZ 8 +#include "cfb.h" +#include "mibstore.h" +#include "colormapst.h" +#include "gcstruct.h" +#include "input.h" +#include "mipointer.h" +#include +#ifdef HAS_MMAP +#include +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif +#endif /* HAS_MMAP */ +#include +#include +#ifndef WIN32 +#include +#endif +#include +#ifdef HAS_SHM +#include +#include +#endif /* HAS_SHM */ +#include "dix.h" +#include "miline.h" + +extern char *display; + +#define VFB_DEFAULT_WIDTH 1280 +#define VFB_DEFAULT_HEIGHT 1024 +#define VFB_DEFAULT_DEPTH 8 +#define VFB_DEFAULT_WHITEPIXEL 0 +#define VFB_DEFAULT_BLACKPIXEL 1 +#define VFB_DEFAULT_LINEBIAS 0 +#define XWD_WINDOW_NAME_LEN 60 + +typedef struct +{ + int scrnum; + int width; + int paddedWidth; + int height; + int depth; + int bitsPerPixel; + int sizeInBytes; + int ncolors; + char *pfbMemory; + XWDColor *pXWDCmap; + XWDFileHeader *pXWDHeader; + Pixel blackPixel; + Pixel whitePixel; + unsigned int lineBias; + +#ifdef HAS_MMAP + int mmap_fd; + char mmap_file[MAXPATHLEN]; +#endif + +#ifdef HAS_SHM + int shmid; +#endif +} vfbScreenInfo, *vfbScreenInfoPtr; + +static int vfbNumScreens; +static vfbScreenInfo vfbScreens[MAXSCREENS]; +static Bool vfbPixmapDepths[33]; +static char *pfbdir = NULL; +typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType; +static fbMemType fbmemtype = NORMAL_MEMORY_FB; +static char needswap = 0; +static int lastScreen = -1; + +#define swapcopy16(_dst, _src) \ + if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \ + else _dst = _src; + +#define swapcopy32(_dst, _src) \ + if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \ + else _dst = _src; + + +static void +vfbInitializePixmapDepths() +{ + int i; + vfbPixmapDepths[1] = TRUE; /* always need bitmaps */ + for (i = 2; i <= 32; i++) + vfbPixmapDepths[i] = FALSE; +} + +static void +vfbInitializeDefaultScreens() +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].scrnum = i; + vfbScreens[i].width = VFB_DEFAULT_WIDTH; + vfbScreens[i].height = VFB_DEFAULT_HEIGHT; + vfbScreens[i].depth = VFB_DEFAULT_DEPTH; + vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL; + vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL; + vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS; + vfbScreens[i].pfbMemory = NULL; + } + vfbNumScreens = 1; +} + +static int +vfbBitsPerPixel(depth) + int depth; +{ + if (depth == 1) return 1; + else if (depth <= 8) return 8; + else if (depth <= 16) return 16; + else return 32; +} + +void +ddxGiveUp() +{ + int i; + + /* clean up the framebuffers */ + + switch (fbmemtype) + { +#ifdef HAS_MMAP + case MMAPPED_FILE_FB: + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == unlink(vfbScreens[i].mmap_file)) + { + perror("unlink"); + ErrorF("unlink %s failed, errno %d", + vfbScreens[i].mmap_file, errno); + } + } + break; +#endif /* HAS_MMAP */ + +#ifdef HAS_SHM + case SHARED_MEMORY_FB: + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader)) + { + perror("shmdt"); + ErrorF("shmdt failed, errno %d", errno); + } + } + break; +#endif /* HAS_SHM */ + + case NORMAL_MEMORY_FB: + for (i = 0; i < vfbNumScreens; i++) + { + Xfree(vfbScreens[i].pXWDHeader); + } + break; + } +} + +void +AbortDDX() +{ + ddxGiveUp(); +} + +void +OsVendorInit() +{ +} + +void +ddxUseMsg() +{ + ErrorF("-screen scrn WxHxD set screen's width, height, depth\n"); + ErrorF("-pixdepths list-of-int support given pixmap depths\n"); + ErrorF("-linebias n adjust thin line pixelization\n"); + ErrorF("-blackpixel n pixel value for black\n"); + ErrorF("-whitepixel n pixel value for white\n"); + +#ifdef HAS_MMAP + ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n"); +#endif + +#ifdef HAS_SHM + ErrorF("-shmem put framebuffers in shared memory\n"); +#endif +} + +int +ddxProcessArgument (argc, argv, i) + int argc; + char *argv[]; + int i; +{ + static Bool firstTime = TRUE; + + if (firstTime) + { + vfbInitializeDefaultScreens(); + vfbInitializePixmapDepths(); + firstTime = FALSE; + } + + if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */ + { + int screenNum; + if (i + 2 >= argc) UseMsg(); + screenNum = atoi(argv[i+1]); + if (screenNum < 0 || screenNum >= MAXSCREENS) + { + ErrorF("Invalid screen number %d\n", screenNum); + UseMsg(); + } + if (3 != sscanf(argv[i+2], "%dx%dx%d", + &vfbScreens[screenNum].width, + &vfbScreens[screenNum].height, + &vfbScreens[screenNum].depth)) + { + ErrorF("Invalid screen configuration %s\n", argv[i+2]); + UseMsg(); + } + + if (screenNum >= vfbNumScreens) + vfbNumScreens = screenNum + 1; + lastScreen = screenNum; + return 3; + } + + if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */ + { + int depth, ret = 1; + + if (++i >= argc) UseMsg(); + while ((i < argc) && (depth = atoi(argv[i++])) != 0) + { + if (depth < 0 || depth > 32) + { + ErrorF("Invalid pixmap depth %d\n", depth); + UseMsg(); + } + vfbPixmapDepths[depth] = TRUE; + ret++; + } + return ret; + } + + if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */ + { + Pixel pix; + if (++i >= argc) UseMsg(); + pix = atoi(argv[i]); + if (-1 == lastScreen) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].blackPixel = pix; + } + } + else + { + vfbScreens[lastScreen].blackPixel = pix; + } + return 2; + } + + if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */ + { + Pixel pix; + if (++i >= argc) UseMsg(); + pix = atoi(argv[i]); + if (-1 == lastScreen) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].whitePixel = pix; + } + } + else + { + vfbScreens[lastScreen].whitePixel = pix; + } + return 2; + } + + if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */ + { + unsigned int linebias; + if (++i >= argc) UseMsg(); + linebias = atoi(argv[i]); + if (-1 == lastScreen) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].lineBias = linebias; + } + } + else + { + vfbScreens[lastScreen].lineBias = linebias; + } + return 2; + } + +#ifdef HAS_MMAP + if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */ + { + if (++i >= argc) UseMsg(); + pfbdir = argv[i]; + fbmemtype = MMAPPED_FILE_FB; + return 2; + } +#endif /* HAS_MMAP */ + +#ifdef HAS_SHM + if (strcmp (argv[i], "-shmem") == 0) /* -shmem */ + { + fbmemtype = SHARED_MEMORY_FB; + return 1; + } +#endif + + return 0; +} + +#ifdef DDXTIME /* from ServerOSDefines */ +CARD32 +GetTimeInMillis() +{ + struct timeval tp; + + X_GETTIMEOFDAY(&tp); + return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} +#endif + + +static Bool +vfbMultiDepthCreateGC(pGC) + GCPtr pGC; +{ + switch (vfbBitsPerPixel(pGC->depth)) + { + case 1: return mfbCreateGC (pGC); + case 8: return cfbCreateGC (pGC); + case 16: return cfb16CreateGC (pGC); + case 32: return cfb32CreateGC (pGC); + default: return FALSE; + } +} + +static void +vfbMultiDepthGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart) + DrawablePtr pDrawable; /* drawable from which to get bits */ + int wMax; /* largest value of all *pwidths */ + register DDXPointPtr ppt; /* points to start copying from */ + int *pwidth; /* list of number of bits to copy */ + int nspans; /* number of scanlines to copy */ + char *pdstStart; /* where to put the bits */ +{ + switch (pDrawable->bitsPerPixel) { + case 1: + mfbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + break; + case 8: + cfbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + break; + case 16: + cfb16GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + break; + case 32: + cfb32GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + break; + } + return; +} + +static void +vfbMultiDepthGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine) + DrawablePtr pDrawable; + int sx, sy, w, h; + unsigned int format; + unsigned long planeMask; + char *pdstLine; +{ + switch (pDrawable->bitsPerPixel) + { + case 1: + mfbGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + break; + case 8: + cfbGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + break; + case 16: + cfb16GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + break; + case 32: + cfb32GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + break; + } +} + +static ColormapPtr InstalledMaps[MAXSCREENS]; + +static int +vfbListInstalledColormaps(pScreen, pmaps) + ScreenPtr pScreen; + Colormap *pmaps; +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + *pmaps = InstalledMaps[pScreen->myNum]->mid; + return (1); +} + + +static void +vfbInstallColormap(pmap) + ColormapPtr pmap; +{ + int index = pmap->pScreen->myNum; + ColormapPtr oldpmap = InstalledMaps[index]; + + if (pmap != oldpmap) + { + int entries; + XWDFileHeader *pXWDHeader; + XWDColor *pXWDCmap; + VisualPtr pVisual; + Pixel * ppix; + xrgb * prgb; + xColorItem *defs; + int i; + + if(oldpmap != (ColormapPtr)None) + WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); + /* Install pmap */ + InstalledMaps[index] = pmap; + WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); + + entries = pmap->pVisual->ColormapEntries; + pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader; + pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; + pVisual = pmap->pVisual; + + swapcopy32(pXWDHeader->visual_class, pVisual->class); + swapcopy32(pXWDHeader->red_mask, pVisual->redMask); + swapcopy32(pXWDHeader->green_mask, pVisual->greenMask); + swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask); + swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue); + swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries); + + ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel)); + prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb)); + defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem)); + + for (i = 0; i < entries; i++) ppix[i] = i; + /* XXX truecolor */ + QueryColors(pmap, entries, ppix, prgb); + + for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */ + defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */ + defs[i].red = prgb[i].red; + defs[i].green = prgb[i].green; + defs[i].blue = prgb[i].blue; + defs[i].flags = DoRed|DoGreen|DoBlue; + } + (*pmap->pScreen->StoreColors)(pmap, entries, defs); + + DEALLOCATE_LOCAL(ppix); + DEALLOCATE_LOCAL(prgb); + DEALLOCATE_LOCAL(defs); + } +} + +static void +vfbUninstallColormap(pmap) + ColormapPtr pmap; +{ + ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum]; + + if(pmap == curpmap) + { + if (pmap->mid != pmap->pScreen->defColormap) + { + curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, + RT_COLORMAP); + (*pmap->pScreen->InstallColormap)(curpmap); + } + } +} + +static void +vfbStoreColors(pmap, ndef, pdefs) + ColormapPtr pmap; + int ndef; + xColorItem *pdefs; +{ + XWDColor *pXWDCmap; + int i; + + if (pmap != InstalledMaps[pmap->pScreen->myNum]) return; + + pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; + + if ((pmap->pVisual->class | DynamicClass) == DirectColor) + return; + + for (i = 0; i < ndef; i++) + { + if (pdefs[i].flags & DoRed) + swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red); + if (pdefs[i].flags & DoGreen) + swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green); + if (pdefs[i].flags & DoBlue) + swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue); + } +} + +static Bool +vfbSaveScreen(pScreen, on) + ScreenPtr pScreen; + int on; +{ + return TRUE; +} + +#ifdef HAS_MMAP + +/* this flushes any changes to the screens out to the mmapped file */ +static void +vfbBlockHandler(blockData, pTimeout, pReadmask) + pointer blockData; + OSTimePtr pTimeout; + pointer pReadmask; +{ + int i; + + for (i = 0; i < vfbNumScreens; i++) + { +#ifdef MS_ASYNC + if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, + (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC)) +#else + /* silly NetBSD and who else? */ + if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, + (size_t)vfbScreens[i].sizeInBytes)) +#endif + { + perror("msync"); + ErrorF("msync failed, errno %d", errno); + } + } +} + + +static void +vfbWakeupHandler(blockData, result, pReadmask) + pointer blockData; + int result; + pointer pReadmask; +{ +} + + +static void +vfbAllocateMmappedFramebuffer(pvfb) + vfbScreenInfoPtr pvfb; +{ +#define DUMMY_BUFFER_SIZE 65536 + char dummyBuffer[DUMMY_BUFFER_SIZE]; + int currentFileSize, writeThisTime; + + sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum); + if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666))) + { + perror("open"); + ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno); + return; + } + + /* Extend the file to be the proper size */ + + bzero(dummyBuffer, DUMMY_BUFFER_SIZE); + for (currentFileSize = 0; + currentFileSize < pvfb->sizeInBytes; + currentFileSize += writeThisTime) + { + writeThisTime = min(DUMMY_BUFFER_SIZE, + pvfb->sizeInBytes - currentFileSize); + if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime)) + { + perror("write"); + ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno); + return; + } + } + + /* try to mmap the file */ + + pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes, + PROT_READ|PROT_WRITE, + MAP_FILE|MAP_SHARED, + pvfb->mmap_fd, 0); + if (-1 == (int)pvfb->pXWDHeader) + { + perror("mmap"); + ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno); + pvfb->pXWDHeader = NULL; + return; + } + + if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler, + NULL)) + { + pvfb->pXWDHeader = NULL; + } +} +#endif /* HAS_MMAP */ + + +#ifdef HAS_SHM +static void +vfbAllocateSharedMemoryFramebuffer(pvfb) + vfbScreenInfoPtr pvfb; +{ + /* create the shared memory segment */ + + pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777); + if (pvfb->shmid < 0) + { + perror("shmget"); + ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno); + return; + } + + /* try to attach it */ + + pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0); + if (-1 == (int)pvfb->pXWDHeader) + { + perror("shmat"); + ErrorF("shmat failed, errno %d", errno); + pvfb->pXWDHeader = NULL; + return; + } + + ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid); +} +#endif /* HAS_SHM */ + +static char * +vfbAllocateFramebufferMemory(pvfb) + vfbScreenInfoPtr pvfb; +{ + if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */ + + if (pvfb->bitsPerPixel == 1) + pvfb->sizeInBytes = (pvfb->paddedWidth * pvfb->height); + else + pvfb->sizeInBytes = pvfb->paddedWidth * pvfb->height * + (pvfb->bitsPerPixel/8); + + /* Calculate how many entries in colormap. This is rather bogus, because + * the visuals haven't even been set up yet, but we need to know because we + * have to allocate space in the file for the colormap. The number 10 + * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c. + */ + + if (pvfb->depth <= 10) + { /* single index colormaps */ + pvfb->ncolors = 1 << pvfb->depth; + } + else + { /* decomposed colormaps */ + int nplanes_per_color_component = pvfb->depth / 3; + if (pvfb->depth % 3) nplanes_per_color_component++; + pvfb->ncolors = 1 << nplanes_per_color_component; + } + + /* add extra bytes for XWDFileHeader, window name, and colormap */ + + pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN + + pvfb->ncolors * SIZEOF(XWDColor); + + pvfb->pXWDHeader = NULL; + switch (fbmemtype) + { +#ifdef HAS_MMAP + case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break; +#endif + +#ifdef HAS_SHM + case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break; +#endif + + case NORMAL_MEMORY_FB: + pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes); + break; + } + + if (pvfb->pXWDHeader) + { + pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader + + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN); + pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors); + return pvfb->pfbMemory; + } + else + return NULL; +} + + +static void +vfbWriteXWDFileHeader(pScreen) + ScreenPtr pScreen; +{ + vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; + XWDFileHeader *pXWDHeader = pvfb->pXWDHeader; + char hostname[XWD_WINDOW_NAME_LEN]; + VisualPtr pVisual; + unsigned long swaptest = 1; + int i; + + needswap = *(char *) &swaptest; + + pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader; + pXWDHeader->file_version = XWD_FILE_VERSION; + + pXWDHeader->pixmap_format = ZPixmap; + pXWDHeader->pixmap_depth = pvfb->depth; + pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height; + pXWDHeader->xoffset = 0; + pXWDHeader->byte_order = IMAGE_BYTE_ORDER; + pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER; +#ifndef INTERNAL_VS_EXTERNAL_PADDING + pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width; + pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT; + pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD; +#else + pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth; + pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO; + pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO; +#endif + pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel; + pXWDHeader->bytes_per_line = pvfb->paddedWidth; + pXWDHeader->ncolors = pvfb->ncolors; + + /* visual related fields are written when colormap is installed */ + + pXWDHeader->window_x = pXWDHeader->window_y = 0; + pXWDHeader->window_bdrwidth = 0; + + /* write xwd "window" name: Xvfb hostname:server.screen */ + + if (-1 == gethostname(hostname, sizeof(hostname))) + hostname[0] = 0; + else + hostname[XWD_WINDOW_NAME_LEN-1] = 0; + sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display, + pScreen->myNum); + + /* write colormap pixel slot values */ + + for (i = 0; i < pvfb->ncolors; i++) + { + pvfb->pXWDCmap[i].pixel = i; + } + + /* byte swap to most significant byte first */ + + if (needswap) + { + SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4); + for (i = 0; i < pvfb->ncolors; i++) + { + register char n; + swapl(&pvfb->pXWDCmap[i].pixel, n); + } + } +} + + +static Bool +vfbCursorOffScreen (ppScreen, x, y) + ScreenPtr *ppScreen; + int *x, *y; +{ + return FALSE; +} + +static void +vfbCrossScreen (pScreen, entering) + ScreenPtr pScreen; + Bool entering; +{ +} + +static miPointerScreenFuncRec vfbPointerCursorFuncs = +{ + vfbCursorOffScreen, + vfbCrossScreen, + miPointerWarpCursor +}; + +static Bool +vfbScreenInit(index, pScreen, argc, argv) + int index; + ScreenPtr pScreen; + int argc; + char ** argv; +{ + vfbScreenInfoPtr pvfb = &vfbScreens[index]; + int dpix = 100, dpiy = 100; + int ret; + char *pbits; + + pvfb->paddedWidth = PixmapBytePad(pvfb->width, pvfb->depth); + pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth); + pbits = vfbAllocateFramebufferMemory(pvfb); + if (!pbits) return FALSE; + + switch (pvfb->bitsPerPixel) + { + case 1: + ret = mfbScreenInit(pScreen, pbits, pvfb->width, pvfb->height, + dpix, dpiy, pvfb->paddedWidth * 8); + break; + case 8: + ret = cfbScreenInit(pScreen, pbits, pvfb->width, pvfb->height, + dpix, dpiy, pvfb->paddedWidth); + break; + case 16: + ret = cfb16ScreenInit(pScreen, pbits, pvfb->width, pvfb->height, + dpix, dpiy, pvfb->paddedWidth); + break; + case 32: + ret = cfb32ScreenInit(pScreen, pbits, pvfb->width, pvfb->height, + dpix, dpiy, pvfb->paddedWidth); + break; + default: + return FALSE; + } + + if (!ret) return FALSE; + + pScreen->CreateGC = vfbMultiDepthCreateGC; + pScreen->GetImage = vfbMultiDepthGetImage; + pScreen->GetSpans = vfbMultiDepthGetSpans; + + pScreen->InstallColormap = vfbInstallColormap; + pScreen->UninstallColormap = vfbUninstallColormap; + pScreen->ListInstalledColormaps = vfbListInstalledColormaps; + + pScreen->SaveScreen = vfbSaveScreen; + pScreen->StoreColors = vfbStoreColors; + + miDCInitialize(pScreen, &vfbPointerCursorFuncs); + + vfbWriteXWDFileHeader(pScreen); + + pScreen->blackPixel = pvfb->blackPixel; + pScreen->whitePixel = pvfb->whitePixel; + + if (pvfb->bitsPerPixel == 1) + { + ret = mfbCreateDefColormap(pScreen); + } + else + { + ret = cfbCreateDefColormap(pScreen); + } + + miSetZeroLineBias(pScreen, pvfb->lineBias); + + return ret; + +} /* end vfbScreenInit */ + + +void +InitOutput(screenInfo, argc, argv) + ScreenInfo *screenInfo; + int argc; + char **argv; +{ + int i; + int NumFormats = 0; + FILE *pf = stderr; + + /* initialize pixmap formats */ + + /* must have a pixmap depth to match every screen depth */ + for (i = 0; i < vfbNumScreens; i++) + { + vfbPixmapDepths[vfbScreens[i].depth] = TRUE; + } + + for (i = 1; i <= 32; i++) + { + if (vfbPixmapDepths[i]) + { + if (NumFormats >= MAXFORMATS) + FatalError ("MAXFORMATS is too small for this server\n"); + screenInfo->formats[NumFormats].depth = i; + screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i); + screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD; + NumFormats++; + } + } + + screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + screenInfo->numPixmapFormats = NumFormats; + + /* initialize screens */ + + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == AddScreen(vfbScreenInit, argc, argv)) + { + FatalError("Couldn't add screen %d", i); + } + } + +} /* end InitOutput */ + +/* this is just to get the server to link on AIX */ +#ifdef AIXV3 +int SelectWaitTime = 10000; /* usec */ +#endif + diff --git a/hw/vfb/Xvfb.man.pre b/hw/vfb/Xvfb.man.pre new file mode 100644 index 000000000..3d8d86156 --- /dev/null +++ b/hw/vfb/Xvfb.man.pre @@ -0,0 +1,128 @@ +.\" $Xorg: Xvfb.man,v 1.4 2001/02/09 02:04:45 xorgcvs Exp $ +.\" Copyright 1993, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.TH XVFB 1 "Release 6.4" "X Version 11" +.SH NAME +Xvfb \- virtual framebuffer X server for X Version 11 +.SH SYNOPSIS +.B Xvfb +[ option ] ... +.SH DESCRIPTION +.I Xvfb +is an X server that can run on machines with no display hardware +and no physical input devices. It emulates a dumb framebuffer using +virtual memory. +.PP +The primary use of this server was intended to be server testing. The +mfb or cfb code for any depth can be exercised with this server +without the need for real hardware that supports the desired depths. +The X community has found many other novel uses for \fIXvfb\fP, +including testing clients against unusual depths and screen +configurations, doing batch processing with \fIXvfb\fP as a background +rendering engine, load testing, as an aid to porting the X server to a +new platform, and providing an unobtrusive way to run applications +that don't really need an X server but insist on having one anyway. +.SH BUILDING +To build \fIXvfb\fP, put the following in your host.def and remake. +.PP +#define BuildServer YES /* if you aren't already building other servers */ +.br +#define XVirtualFramebufferServer YES + +.SH OPTIONS +.PP +In addition to the normal server options described in the \fIXserver(1)\fP +manual page, \fIXvfb\fP accepts the following command line switches: +.TP 4 +.B "\-screen \fIscreennum\fP \fIWxHxD\fP" +This option creates screen \fIscreennum\fP and sets its width, height, +and depth to W, H, and D respectively. By default, only screen 0 exists +and has the dimensions 1280x1024x8. +.TP 4 +.B "\-pixdepths \fIlist-of-depths\fP" +This option specifies a list of pixmap depths that the server should +support in addition to the depths implied by the supported screens. +\fIlist-of-depths\fP is a space-separated list of integers that can +have values from 1 to 32. +.TP 4 +.B "\-fbdir \fIframebuffer-directory\fP" +This option specifies the directory in which the memory mapped files +containing the framebuffer memory should be created. +See FILES. +This option only exists on machines that have the mmap and msync system +calls. +.TP 4 +.B "\-shmem" +This option specifies that the framebuffer should be put in shared memory. +The shared memory ID for each screen will be printed by the server. +The shared memory is in xwd format. +This option only exists on machines that support the System V shared memory +interface. +.PP +If neither \fB\-shmem\fP nor \fB\-fbdir\fP is specified, +the framebuffer memory will be allocated with malloc(). +.TP 4 +.B "\-linebias \fIn\fP" +This option specifies how to adjust the pixelization of thin lines. +The value \fIn\fP is a bitmask of octants in which to prefer an axial +step when the Bresenham error term is exactly zero. See the file +Xserver/mi/miline.h for more information. This option is probably only useful +to server developers to experiment with the range of line pixelization +possible with the cfb and mfb code. +.TP 4 +.B "\-blackpixel \fIpixel-value\fP, \-whitepixel \fIpixel-value\fP" +These options specify the black and white pixel values the server should use. +.SH FILES +The following files are created if the \-fbdir option is given. +.TP 4 +\fIframebuffer-directory\fP/Xvfb_screen +Memory mapped file containing screen n's framebuffer memory, one file +per screen. The file is in xwd format. Thus, taking a full-screen +snapshot can be done with a file copy command, and the resulting +snapshot will even contain the cursor image. +.SH EXAMPLES +.TP 8 +Xvfb :1 -screen 0 1600x1200x32 +The server will listen for connections as server number 1, and screen 0 +will be depth 32 1600x1200. +.TP 8 +Xvfb :1 -screen 1 1600x1200x16 +The server will listen for connections as server number 1, will have the +default screen configuration (one screen, 1280x1024x8), and screen 1 +will be depth 16 1600x1200. +.TP 8 +Xvfb -pixdepths 3 27 -fbdir /usr/tmp +The server will listen for connections as server number 0, will have the +default screen configuration (one screen, 1280x1024x8), +will also support pixmap +depths of 3 and 27, +and will use memory mapped files in /usr/tmp for the framebuffer. +.TP 8 +xwud -in /usr/tmp/Xvfb_screen0 +Displays screen 0 of the server started by the preceding example. +.SH "SEE ALSO" +.PP +X(1), Xserver(1), xwd(1), xwud(1), XWDFile.h +.SH AUTHORS +David P. Wiggins, The Open Group, Inc. diff --git a/hw/vfb/lk201kbd.h b/hw/vfb/lk201kbd.h new file mode 100644 index 000000000..9b4090ed0 --- /dev/null +++ b/hw/vfb/lk201kbd.h @@ -0,0 +1,159 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: lk201kbd.h,v 1.4 2001/02/09 02:04:45 xorgcvs Exp $ */ + +#define MIN_LK201_KEY 86 +#define MAX_LK201_KEY 251 +#define LK201_GLYPHS_PER_KEY 2 + +#define KEY_F1 86 +#define KEY_F2 87 +#define KEY_F3 88 +#define KEY_F4 89 +#define KEY_F5 90 +#define KEY_F6 100 +#define KEY_F7 101 +#define KEY_F8 102 +#define KEY_F9 103 +#define KEY_F10 104 +#define KEY_F11 113 +#define KEY_F12 114 +#define KEY_F13 115 +#define KEY_F14 116 +#define KEY_HELP 124 +#define KEY_MENU 125 +#define KEY_F17 128 +#define KEY_F18 129 +#define KEY_F19 130 +#define KEY_F20 131 +#define KEY_FIND 138 +#define KEY_INSERT_HERE 139 +#define KEY_REMOVE 140 +#define KEY_SELECT 141 +#define KEY_PREV_SCREEN 142 +#define KEY_NEXT_SCREEN 143 +#define KEY_KP_0 146 /* key pad */ +#define KEY_KP_PERIOD 148 /* key pad */ +#define KEY_KP_ENTER 149 /* key pad */ +#define KEY_KP_1 150 /* key pad */ +#define KEY_KP_2 151 /* key pad */ +#define KEY_KP_3 152 /* key pad */ +#define KEY_KP_4 153 /* key pad */ +#define KEY_KP_5 154 /* key pad */ +#define KEY_KP_6 155 /* key pad */ +#define KEY_KP_COMMA 156 /* key pad */ +#define KEY_KP_7 157 /* key pad */ +#define KEY_KP_8 158 /* key pad */ +#define KEY_KP_9 159 /* key pad */ +#define KEY_KP_HYPHEN 160 +#define KEY_KP_PF1 161 +#define KEY_KP_PF2 162 +#define KEY_KP_PF3 163 +#define KEY_KP_PF4 164 +#define KEY_LEFT 167 +#define KEY_RIGHT 168 +#define KEY_DOWN 169 +#define KEY_UP 170 +#define KEY_SHIFT 174 +#define KEY_CTRL 175 +#define KEY_LOCK 176 +#define KEY_COMPOSE 177 +#define KEY_APPLE 177 +#define KEY_META 177 +#define KEY_DELETE 188 +#define KEY_RETURN 189 +#define KEY_TAB 190 +#define KEY_TILDE 191 +#define KEY_TR_1 192 /* Top Row */ +#define KEY_Q 193 +#define KEY_A 194 +#define KEY_Z 195 +#define KEY_TR_2 197 +#define KEY_W 198 +#define KEY_S 199 +#define KEY_X 200 +#define KEY_LANGLE_RANGLE 201 /* xxx */ +#define KEY_TR_3 203 +#define KEY_E 204 +#define KEY_D 205 +#define KEY_C 206 +#define KEY_TR_4 208 +#define KEY_R 209 +#define KEY_F 210 +#define KEY_V 211 +#define KEY_SPACE 212 +#define KEY_TR_5 214 +#define KEY_T 215 +#define KEY_G 216 +#define KEY_B 217 +#define KEY_TR_6 219 +#define KEY_Y 220 +#define KEY_H 221 +#define KEY_N 222 +#define KEY_TR_7 224 +#define KEY_U 225 +#define KEY_J 226 +#define KEY_M 227 +#define KEY_TR_8 229 +#define KEY_I 230 +#define KEY_K 231 +#define KEY_COMMA 232 /* xxx */ +#define KEY_TR_9 234 +#define KEY_O 235 +#define KEY_L 236 +#define KEY_PERIOD 237 /* xxx */ +#define KEY_TR_0 239 +#define KEY_P 240 +#define KEY_SEMICOLON 242 /* xxx */ +#define KEY_QMARK 243 +#define KEY_PLUS 245 /* xxx */ +#define KEY_RBRACE 246 +#define KEY_VBAR 247 /* xxx */ +#define KEY_UBAR 249 /* xxx */ +#define KEY_LBRACE 250 +#define KEY_QUOTE 251 diff --git a/hw/xfree86/common/atKeynames.h b/hw/xfree86/common/atKeynames.h new file mode 100644 index 000000000..24ae59a30 --- /dev/null +++ b/hw/xfree86/common/atKeynames.h @@ -0,0 +1,335 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/atKeynames.h,v 3.9 1996/12/23 06:43:13 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: atKeynames.h,v 1.3 2000/08/17 19:50:28 cpqbld Exp $ */ + +#ifndef _ATKEYNAMES_H +#define _ATKEYNAMES_H + +#define XK_TECHNICAL +#define XK_KATAKANA +#include "keysym.h" + +#define GLYPHS_PER_KEY 4 +#define NUM_KEYCODES 150 +#define NUM_STD_KEYCODES 127 +#define MIN_KEYCODE 8 +#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) +#define MAX_STD_KEYCODE (NUM_STD_KEYCODES + MIN_KEYCODE - 1) + +#define AltMask Mod1Mask +#define NumLockMask Mod2Mask +#define AltLangMask Mod3Mask +#define KanaMask Mod4Mask +#define ScrollLockMask Mod5Mask + +#define KeyPressed(k) (keyc->down[k >> 3] & (1 << (k & 7))) +#define ModifierDown(k) ((keyc->state & (k)) == (k)) + +#define XF86XK_ModeLock 0x1008FF01 /* Mode Switch Lock */ + +/* + * NOTE: The AT/MF keyboards can generate (via the 8042) two (MF: three) + * sets of scancodes. Set3 can only be generated by a MF keyboard. + * Set2 sends a makecode for keypress, and the same code prefixed by a + * F0 for keyrelease. This is a little bit ugly to handle. Thus we use + * here for X386 the PC/XT compatible Set1. This set uses 8bit scancodes. + * Bit 7 ist set if the key is released. The code E0 switches to a + * different meaning to add the new MF cursorkeys, while not breaking old + * applications. E1 is another special prefix. Since I assume that there + * will be further versions of PC/XT scancode compatible keyboards, we + * may be in trouble one day. + * + * IDEA: 1) Use Set2 on AT84 keyboards and translate it to MF Set3. + * 2) Use the keyboards native set and translate it to common keysyms. + */ + +/* + * definition of the AT84/MF101/MF102 Keyboard: + * ============================================================ + * Defined Key Cap Glyphs Pressed value + * Key Name Main Also (hex) (dec) + * ---------------- ---------- ------- ------ ------ + */ + +#ifndef PC98 + +#define KEY_Escape /* Escape 0x01 */ 1 +#define KEY_1 /* 1 ! 0x02 */ 2 +#define KEY_2 /* 2 @ 0x03 */ 3 +#define KEY_3 /* 3 # 0x04 */ 4 +#define KEY_4 /* 4 $ 0x05 */ 5 +#define KEY_5 /* 5 % 0x06 */ 6 +#define KEY_6 /* 6 ^ 0x07 */ 7 +#define KEY_7 /* 7 & 0x08 */ 8 +#define KEY_8 /* 8 * 0x09 */ 9 +#define KEY_9 /* 9 ( 0x0a */ 10 +#define KEY_0 /* 0 ) 0x0b */ 11 +#define KEY_Minus /* - (Minus) _ (Under) 0x0c */ 12 +#define KEY_Equal /* = (Equal) + 0x0d */ 13 +#define KEY_BackSpace /* Back Space 0x0e */ 14 +#define KEY_Tab /* Tab 0x0f */ 15 +#define KEY_Q /* Q 0x10 */ 16 +#define KEY_W /* W 0x11 */ 17 +#define KEY_E /* E 0x12 */ 18 +#define KEY_R /* R 0x13 */ 19 +#define KEY_T /* T 0x14 */ 20 +#define KEY_Y /* Y 0x15 */ 21 +#define KEY_U /* U 0x16 */ 22 +#define KEY_I /* I 0x17 */ 23 +#define KEY_O /* O 0x18 */ 24 +#define KEY_P /* P 0x19 */ 25 +#define KEY_LBrace /* [ { 0x1a */ 26 +#define KEY_RBrace /* ] } 0x1b */ 27 +#define KEY_Enter /* Enter 0x1c */ 28 +#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29 +#define KEY_A /* A 0x1e */ 30 +#define KEY_S /* S 0x1f */ 31 +#define KEY_D /* D 0x20 */ 32 +#define KEY_F /* F 0x21 */ 33 +#define KEY_G /* G 0x22 */ 34 +#define KEY_H /* H 0x23 */ 35 +#define KEY_J /* J 0x24 */ 36 +#define KEY_K /* K 0x25 */ 37 +#define KEY_L /* L 0x26 */ 38 +#define KEY_SemiColon /* ;(SemiColon) :(Colon) 0x27 */ 39 +#define KEY_Quote /* ' (Apostr) " (Quote) 0x28 */ 40 +#define KEY_Tilde /* ` (Accent) ~ (Tilde) 0x29 */ 41 +#define KEY_ShiftL /* Shift(left) 0x2a */ 42 +#define KEY_BSlash /* \(BckSlash) |(VertBar)0x2b */ 43 +#define KEY_Z /* Z 0x2c */ 44 +#define KEY_X /* X 0x2d */ 45 +#define KEY_C /* C 0x2e */ 46 +#define KEY_V /* V 0x2f */ 47 +#define KEY_B /* B 0x30 */ 48 +#define KEY_N /* N 0x31 */ 49 +#define KEY_M /* M 0x32 */ 50 +#define KEY_Comma /* , (Comma) < (Less) 0x33 */ 51 +#define KEY_Period /* . (Period) >(Greater)0x34 */ 52 +#define KEY_Slash /* / (Slash) ? 0x35 */ 53 +#define KEY_ShiftR /* Shift(right) 0x36 */ 54 +#define KEY_KP_Multiply /* * 0x37 */ 55 +#define KEY_Alt /* Alt(left) 0x38 */ 56 +#define KEY_Space /* (SpaceBar) 0x39 */ 57 +#define KEY_CapsLock /* CapsLock 0x3a */ 58 +#define KEY_F1 /* F1 0x3b */ 59 +#define KEY_F2 /* F2 0x3c */ 60 +#define KEY_F3 /* F3 0x3d */ 61 +#define KEY_F4 /* F4 0x3e */ 62 +#define KEY_F5 /* F5 0x3f */ 63 +#define KEY_F6 /* F6 0x40 */ 64 +#define KEY_F7 /* F7 0x41 */ 65 +#define KEY_F8 /* F8 0x42 */ 66 +#define KEY_F9 /* F9 0x43 */ 67 +#define KEY_F10 /* F10 0x44 */ 68 +#define KEY_NumLock /* NumLock 0x45 */ 69 +#define KEY_ScrollLock /* ScrollLock 0x46 */ 70 +#define KEY_KP_7 /* 7 Home 0x47 */ 71 +#define KEY_KP_8 /* 8 Up 0x48 */ 72 +#define KEY_KP_9 /* 9 PgUp 0x49 */ 73 +#define KEY_KP_Minus /* - (Minus) 0x4a */ 74 +#define KEY_KP_4 /* 4 Left 0x4b */ 75 +#define KEY_KP_5 /* 5 0x4c */ 76 +#define KEY_KP_6 /* 6 Right 0x4d */ 77 +#define KEY_KP_Plus /* + (Plus) 0x4e */ 78 +#define KEY_KP_1 /* 1 End 0x4f */ 79 +#define KEY_KP_2 /* 2 Down 0x50 */ 80 +#define KEY_KP_3 /* 3 PgDown 0x51 */ 81 +#define KEY_KP_0 /* 0 Insert 0x52 */ 82 +#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83 +#define KEY_SysReqest /* SysReqest 0x54 */ 84 + /* NOTUSED 0x55 */ +#define KEY_Less /* < (Less) >(Greater) 0x56 */ 86 +#define KEY_F11 /* F11 0x57 */ 87 +#define KEY_F12 /* F12 0x58 */ 88 + +#define KEY_Prefix0 /* special 0x60 */ 96 +#define KEY_Prefix1 /* specail 0x61 */ 97 + +/* + * The 'scancodes' below are generated by the server, because the MF101/102 + * keyboard sends them as sequence of other scancodes + */ +#define KEY_Home /* Home 0x59 */ 89 +#define KEY_Up /* Up 0x5a */ 90 +#define KEY_PgUp /* PgUp 0x5b */ 91 +#define KEY_Left /* Left 0x5c */ 92 +#define KEY_Begin /* Begin 0x5d */ 93 +#define KEY_Right /* Right 0x5e */ 94 +#define KEY_End /* End 0x5f */ 95 +#define KEY_Down /* Down 0x60 */ 96 +#define KEY_PgDown /* PgDown 0x61 */ 97 +#define KEY_Insert /* Insert 0x62 */ 98 +#define KEY_Delete /* Delete 0x63 */ 99 +#define KEY_KP_Enter /* Enter 0x64 */ 100 +#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101 +#define KEY_Pause /* Pause 0x66 */ 102 +#define KEY_Print /* Print 0x67 */ 103 +#define KEY_KP_Divide /* Didive 0x68 */ 104 +#define KEY_AltLang /* AtlLang(right) 0x69 */ 105 +#define KEY_Break /* Break 0x6a */ 106 +#define KEY_LMeta /* Left Meta 0x6b */ 107 +#define KEY_RMeta /* Right Meta 0x6c */ 108 +#define KEY_Menu /* Menu 0x6d */ 109 +#define KEY_F13 /* F13 0x6e */ 110 +#define KEY_F14 /* F14 0x6f */ 111 +#define KEY_F15 /* F15 0x70 */ 112 +#define KEY_F16 /* F16 0x71 */ 113 +#define KEY_F17 /* F17 0x72 */ 114 +#define KEY_KP_DEC /* KP_DEC 0x73 */ 115 +#define KEY_SN_KP_7 /* ServerNumLock 7 0x80 */ 128 +#define KEY_SN_KP_8 /* ServerNumLock 8 0x81 */ 129 +#define KEY_SN_KP_9 /* ServerNumLock 9 0x82 */ 130 +#define KEY_SN_KP_4 /* ServerNumLock 4 0x83 */ 131 +#define KEY_SN_KP_5 /* ServerNumLock 5 0x84 */ 132 +#define KEY_SN_KP_6 /* ServerNumLock 6 0x85 */ 133 +#define KEY_SN_KP_1 /* ServerNumLock 1 0x86 */ 134 +#define KEY_SN_KP_2 /* ServerNumLock 2 0x87 */ 135 +#define KEY_SN_KP_3 /* ServerNumLock 4 0x88 */ 136 +#define KEY_SN_KP_0 /* ServerNumLock 0 0x89 */ 137 +#define KEY_SN_KP_Dec /* ServerNumLock Decimal 0x8a */ 138 +#define KEY_SN_KP_Home /* ServerNumLock Home 0x8b */ 139 +#define KEY_SN_KP_Up /* ServerNumLock Up 0x8c */ 140 +#define KEY_SN_KP_Prior /* ServerNumLock Prior 0x8d */ 141 +#define KEY_SN_KP_Left /* ServerNumLock Left 0x8e */ 142 +#define KEY_SN_KP_Begin /* ServerNumLock Begin 0x8f */ 143 +#define KEY_SN_KP_Right /* ServerNumLock Right 0x90 */ 144 +#define KEY_SN_KP_End /* ServerNumLock End 0x91 */ 145 +#define KEY_SN_KP_Down /* ServerNumLock Down 0x92 */ 146 +#define KEY_SN_KP_Next /* ServerNumLock Next 0x93 */ 147 +#define KEY_SN_KP_Ins /* ServerNumLock Ins 0x94 */ 148 +#define KEY_SN_KP_Del /* ServerNumLock Del 0x95 */ 149 + +#else + +#define KEY_Escape /* Escape 0x01 */ 0 +#define KEY_1 /* 1 ! 0x02 */ 1 +#define KEY_2 /* 2 " 0x03 */ 2 +#define KEY_3 /* 3 # 0x04 */ 3 +#define KEY_4 /* 4 $ 0x05 */ 4 +#define KEY_5 /* 5 % 0x06 */ 5 +#define KEY_6 /* 6 & 0x07 */ 6 +#define KEY_7 /* 7 ' 0x08 */ 7 +#define KEY_8 /* 8 ( 0x09 */ 8 +#define KEY_9 /* 9 ) 0x0a */ 9 +#define KEY_0 /* 0 0x0b */ 10 +#define KEY_Minus /* - (Minus) = (Equal) 0x0c */ 11 +#define KEY_Hat /* ^ (Hat) ` 0x0d */ 12 +#define KEY_BSlash /* \(BckSlash) |(VertBar)0x2b */ 13 +#define KEY_BackSpace /* Back Space 0x0e */ 14 +#define KEY_Tab /* Tab 0x0f */ 15 +#define KEY_Q /* Q 0x10 */ 16 +#define KEY_W /* W 0x11 */ 17 +#define KEY_E /* E 0x12 */ 18 +#define KEY_R /* R 0x13 */ 19 +#define KEY_T /* T 0x14 */ 20 +#define KEY_Y /* Y 0x15 */ 21 +#define KEY_U /* U 0x16 */ 22 +#define KEY_I /* I 0x17 */ 23 +#define KEY_O /* O 0x18 */ 24 +#define KEY_P /* P 0x19 */ 25 +#define KEY_At /* @ ~ 0x1a */ 26 +#define KEY_LBrace /* [ { 0x1b */ 27 +#define KEY_Enter /* Enter 0x1c */ 28 +#define KEY_A /* A 0x1d */ 29 +#define KEY_S /* S 0x1e */ 30 +#define KEY_D /* D 0x1f */ 31 +#define KEY_F /* F 0x20 */ 32 +#define KEY_G /* G 0x21 */ 33 +#define KEY_H /* H 0x22 */ 34 +#define KEY_J /* J 0x23 */ 35 +#define KEY_K /* K 0x24 */ 36 +#define KEY_L /* L 0x25 */ 37 +#define KEY_SemiColon /* ;(SemiColon) +(Plus) 0x26 */ 38 +#define KEY_Colon /* :(Colon) *(Quote) 0x27 */ 39 +#define KEY_RBrace /* ] } 0x28 */ 40 +#define KEY_Z /* Z 0x29 */ 41 +#define KEY_X /* X 0x2a */ 42 +#define KEY_C /* C 0x2b */ 43 +#define KEY_V /* V 0x2c */ 44 +#define KEY_B /* B 0x2d */ 45 +#define KEY_N /* N 0x2e */ 46 +#define KEY_M /* M 0x2f */ 47 +#define KEY_Comma /* , (Comma) < (Less) 0x30 */ 48 +#define KEY_Period /* . (Period) >(Greater)0x31 */ 49 +#define KEY_Slash /* / (Slash) ? 0x32 */ 50 +#define KEY_Under /* _ 0x33 */ 51 +#define KEY_Space /* (SpaceBar) 0x34 */ 52 +#define KEY_Xfer /* (XFER) 0x35 */ 53 +#define KEY_PgUp /* PgUp 0x36 */ 54 +#define KEY_Pgdown /* (Roll Down) 0x37 */ 55 +#define KEY_Insert /* Insert 0x38 */ 56 +#define KEY_Delete /* Delete 0x39 */ 57 +#define KEY_Up /* Up 0x3a */ 58 +#define KEY_Left /* Left 0x3b */ 59 +#define KEY_Right /* Right 0x3c */ 60 +#define KEY_Down /* Down 0x3d */ 61 +#define KEY_Home /* Home 0x3e */ 62 +#define KEY_Help /* Help 0x3f */ 63 +#define KEY_KP_Subtract /* - (Minus) 0x40 */ 64 +#define KEY_KP_Minus /* - */ 64 +#define KEY_KP_Divide /* / (Slash) 0x41 */ 65 +#define KEY_KP_7 /* 7 0x42 */ 66 +#define KEY_KP_8 /* 8 0x43 */ 67 +#define KEY_KP_9 /* 9 0x44 */ 68 +#define KEY_KP_Multiply /* * 0x45 */ 69 +#define KEY_KP_4 /* 4 0x46 */ 70 +#define KEY_KP_5 /* 5 0x47 */ 71 +#define KEY_KP_6 /* 6 0x48 */ 72 +#define KEY_KP_Add /* + (Plus) 0x49 */ 73 +#define KEY_KP_Plus /* + */ 73 +#define KEY_KP_1 /* 1 0x4a */ 74 +#define KEY_KP_2 /* 2 0x4b */ 75 +#define KEY_KP_3 /* 3 0x4c */ 76 +#define KEY_KP_Equal /* = 0x4d */ 77 +#define KEY_KP_0 /* 0 0x4e */ 78 +#define KEY_KP_Separator /* , 0x4f */ 79 +#define KEY_KP_Decimal /* . (Decimal) 0x50 */ 80 +#define KEY_Nfer /* (NFER) 0x51 */ 81 +#define KEY_F11 /* F11 0x52 */ 82 +#define KEY_F12 /* F12 0x53 */ 83 +#define KEY_F13 /* F13 0x54 */ 84 +#define KEY_F14 /* F14 0x55 */ 85 +#define KEY_F15 /* F15 0x56 */ 86 +#define KEY_Break /* (Stop) 0x60 */ 96 +#define KEY_Copy /* (Copy) 0x61 */ 97 +#define KEY_Begin /* Begin ?? */ 97 +#define KEY_F1 /* F1 0x62 */ 98 +#define KEY_F2 /* F2 0x63 */ 99 +#define KEY_F3 /* F3 0x64 */ 100 +#define KEY_F4 /* F4 0x65 */ 101 +#define KEY_F5 /* F5 0x66 */ 102 +#define KEY_F6 /* F6 0x67 */ 103 +#define KEY_F7 /* F7 0x68 */ 104 +#define KEY_F8 /* F8 0x69 */ 105 +#define KEY_F9 /* F9 0x6a */ 106 +#define KEY_F10 /* F10 0x6b */ 107 +#define KEY_ShiftL /* Shift(left) 0x70 */ 112 +#define KEY_CapsLock /* CapsLock 0x71 */ 113 +#define KEY_KanaLock /* Kana 0x72 */ 114 +#define KEY_Alt /* Alt(left) 0x73 */ 115 +#define KEY_LCtrl /* Ctrl(left) 0x74 */ 116 + +#endif /* PC98 */ + +#endif /* _ATKEYNAMES_H */ diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h new file mode 100644 index 000000000..f85ecd132 --- /dev/null +++ b/hw/xfree86/common/compiler.h @@ -0,0 +1,1460 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/compiler.h,v 3.24.2.2 1998/02/07 00:44:37 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: compiler.h,v 1.3 2000/08/17 19:50:28 cpqbld Exp $ */ + +#ifndef _COMPILER_H +#define _COMPILER_H + +#ifndef __STDC__ +# ifdef signed +# undef signed +# endif +# ifdef volatile +# undef volatile +# endif +# ifdef const +# undef const +# endif +# define signed /**/ +# ifdef __GNUC__ +# define volatile __volatile__ +# define const __const__ +# ifdef PC98 +# undef NO_INLINE +# endif +# else +# define const /**/ +# ifdef PC98 +# define __inline__ /**/ +# endif +# endif /* __GNUC__ */ +#endif /* !__STDC__ */ + +#if defined(IODEBUG) && defined(__GNUC__) +#define outb RealOutb +#define outw RealOutw +#define outl RealOutl +#define inb RealInb +#define inw RealInw +#define inl RealInl +#endif + +#ifdef NO_INLINE + +extern void outb(); +extern void outw(); +extern void outl(); +extern unsigned int inb(); +extern unsigned int inw(); +extern unsigned int inl(); +#if NeedFunctionPrototypes +extern unsigned char rdinx(unsigned short int, unsigned char); +extern void wrinx(unsigned short int, unsigned char, unsigned char); +extern void modinx(unsigned short int, unsigned char, unsigned char, unsigned char); +extern int testrg(unsigned short int, unsigned char); +extern int testinx2(unsigned short int, unsigned char, unsigned char); +extern int testinx(unsigned short int, unsigned char); +#else /* NeedFunctionProtoypes */ +extern unsigned char rdinx(); +extern void wrinx(); +extern void modinx(); +extern int testrg(); +extern int testinx2(); +extern int testinx(); +#endif /* NeedFunctionProtoypes */ + +#else /* NO_INLINE */ + +#ifdef __GNUC__ + +#if defined(linux) && defined(__alpha__) +/* for Linux on Alpha, we use the LIBC _inx/_outx routines */ +/* note that the appropriate setup via "ioperm" needs to be done */ +/* *before* any inx/outx is done. */ + +static __inline__ void +outb(port, val) + unsigned short port; + char val; +{ + extern void _outb(char val, unsigned short port); + _outb(val, port); +} + +static __inline__ void +outw(port, val) + unsigned short port; + short val; +{ + extern void _outw(short val, unsigned short port); + _outw(val, port); +} + +static __inline__ void +outl(port, val) + unsigned short port; + int val; +{ + extern void _outl(int val, unsigned short port); + _outl(val, port); +} + +static __inline__ unsigned int +inb(port) + unsigned short port; +{ + extern unsigned int _inb(unsigned short port); + return _inb(port); +} + +static __inline__ unsigned int +inw(port) + unsigned short port; +{ + extern unsigned int _inw(unsigned short port); + return _inw(port); +} + +static __inline__ unsigned int +inl(port) + unsigned short port; +{ + extern unsigned int _inl(unsigned short port); + return _inl(port); +} + + +/* + * inline functions to do unaligned accesses + * from linux/include/asm-alpha/unaligned.h + */ + +static __inline__ unsigned long ldq_u(unsigned long * r11) +{ + unsigned long r1,r2; + __asm__("ldq_u %0,%3\n\t" + "ldq_u %1,%4\n\t" + "extql %0,%2,%0\n\t" + "extqh %1,%2,%1\n\t" + "bis %1,%0,%0" + :"=&r" (r1), "=&r" (r2) + :"r" (r11), + "m" (*r11), + "m" (*(unsigned long *)(7+(char *) r11))); + return r1; +} + +static __inline__ unsigned long ldl_u(unsigned int * r11) +{ + unsigned long r1,r2; + __asm__("ldq_u %0,%3\n\t" + "ldq_u %1,%4\n\t" + "extll %0,%2,%0\n\t" + "extlh %1,%2,%1\n\t" + "bis %1,%0,%0" + :"=&r" (r1), "=&r" (r2) + :"r" (r11), + "m" (*r11), + "m" (*(unsigned long *)(3+(char *) r11))); + return r1; +} + +static __inline__ unsigned long ldw_u(unsigned short * r11) +{ + unsigned long r1,r2; + __asm__("ldq_u %0,%3\n\t" + "ldq_u %1,%4\n\t" + "extwl %0,%2,%0\n\t" + "extwh %1,%2,%1\n\t" + "bis %1,%0,%0" + :"=&r" (r1), "=&r" (r2) + :"r" (r11), + "m" (*r11), + "m" (*(unsigned long *)(1+(char *) r11))); + return r1; +} + +static __inline__ void stq_u(unsigned long r5, unsigned long * r11) +{ + unsigned long r1,r2,r3,r4; + + __asm__("ldq_u %3,%1\n\t" + "ldq_u %2,%0\n\t" + "insqh %6,%7,%5\n\t" + "insql %6,%7,%4\n\t" + "mskqh %3,%7,%3\n\t" + "mskql %2,%7,%2\n\t" + "bis %3,%5,%3\n\t" + "bis %2,%4,%2\n\t" + "stq_u %3,%1\n\t" + "stq_u %2,%0" + :"=m" (*r11), + "=m" (*(unsigned long *)(7+(char *) r11)), + "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) + :"r" (r5), "r" (r11)); +} + +static __inline__ void stl_u(unsigned long r5, unsigned int * r11) +{ + unsigned long r1,r2,r3,r4; + + __asm__("ldq_u %3,%1\n\t" + "ldq_u %2,%0\n\t" + "inslh %6,%7,%5\n\t" + "insll %6,%7,%4\n\t" + "msklh %3,%7,%3\n\t" + "mskll %2,%7,%2\n\t" + "bis %3,%5,%3\n\t" + "bis %2,%4,%2\n\t" + "stq_u %3,%1\n\t" + "stq_u %2,%0" + :"=m" (*r11), + "=m" (*(unsigned long *)(3+(char *) r11)), + "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) + :"r" (r5), "r" (r11)); +} + +static __inline__ void stw_u(unsigned long r5, unsigned short * r11) +{ + unsigned long r1,r2,r3,r4; + + __asm__("ldq_u %3,%1\n\t" + "ldq_u %2,%0\n\t" + "inswh %6,%7,%5\n\t" + "inswl %6,%7,%4\n\t" + "mskwh %3,%7,%3\n\t" + "mskwl %2,%7,%2\n\t" + "bis %3,%5,%3\n\t" + "bis %2,%4,%2\n\t" + "stq_u %3,%1\n\t" + "stq_u %2,%0" + :"=m" (*r11), + "=m" (*(unsigned long *)(1+(char *) r11)), + "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) + :"r" (r5), "r" (r11)); +} + +#define mem_barrier() __asm__ __volatile__("mb" : : : "memory") +#ifdef __ELF__ +#define write_mem_barrier() __asm__ __volatile__("wmb" : : : "memory") +#else /* ECOFF gas 2.6 doesn't know "wmb" :-( */ +#define write_mem_barrier() mem_barrier() +#endif + +#else /* defined(linux) && defined(__alpha__) */ +#if defined(__mips__) + +unsigned int IOPortBase; /* Memory mapped I/O port area */ + +static __inline__ void +outb(port, val) + short port; + char val; +{ + *(volatile unsigned char*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ void +outw(port, val) + short port; + short val; +{ + *(volatile unsigned short*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ void +outl(port, val) + short port; + int val; +{ + *(volatile unsigned long*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ unsigned int +inb(port) + short port; +{ + return(*(volatile unsigned char*)(((unsigned short)(port))+IOPortBase)); +} + +static __inline__ unsigned int +inw(port) + short port; +{ + return(*(volatile unsigned short*)(((unsigned short)(port))+IOPortBase)); +} + +static __inline__ unsigned int +inl(port) + short port; +{ + return(*(volatile unsigned long*)(((unsigned short)(port))+IOPortBase)); +} + + +static __inline__ unsigned long ldq_u(unsigned long * r11) +{ + unsigned long r1; + __asm__("lwr %0,%2\n\t" + "lwl %0,%3\n\t" + :"=&r" (r1) + :"r" (r11), + "m" (*r11), + "m" (*(unsigned long *)(3+(char *) r11))); + return r1; +} + +static __inline__ unsigned long ldl_u(unsigned int * r11) +{ + unsigned long r1; + __asm__("lwr %0,%2\n\t" + "lwl %0,%3\n\t" + :"=&r" (r1) + :"r" (r11), + "m" (*r11), + "m" (*(unsigned long *)(3+(char *) r11))); + return r1; +} + +static __inline__ unsigned long ldw_u(unsigned short * r11) +{ + unsigned long r1; + __asm__("lwr %0,%2\n\t" + "lwl %0,%3\n\t" + :"=&r" (r1) + :"r" (r11), + "m" (*r11), + "m" (*(unsigned long *)(1+(char *) r11))); + return r1; +} + +#define stq_u(v,p) stl_u(v,p) +#define stl_u(v,p) ((unsigned char *)(p)) = (v); \ + ((unsigned char *)(p)+1) = ((v) >> 8); \ + ((unsigned char *)(p)+2) = ((v) >> 16); \ + ((unsigned char *)(p)+3) = ((v) >> 24) + +#define stw_u(v,p) ((unsigned char *)(p)) = (v); \ + ((unsigned char *)(p)+1) = ((v) >> 8) + +#define mem_barrier() /* NOP */ + +#else /* defined(mips) */ + +#define ldq_u(p) (*((unsigned long *)(p))) +#define ldl_u(p) (*((unsigned int *)(p))) +#define ldw_u(p) (*((unsigned short *)(p))) +#define stq_u(v,p) ((unsigned long *)(p)) = (v) +#define stl_u(v,p) ((unsigned int *)(p)) = (v) +#define stw_u(v,p) ((unsigned short *)(p)) = (v) +#define mem_barrier() /* NOP */ +#define write_mem_barrier() /* NOP */ + +#if !defined(FAKEIT) && !defined(__mc68000__) +#ifdef GCCUSESGAS + +/* + * If gcc uses gas rather than the native assembler, the syntax of these + * inlines has to be different. DHD + */ +#ifndef PC98 + +static __inline__ void +#if NeedFunctionPrototypes +outb( +unsigned short int port, +unsigned char val) +#else +outb(port, val) +unsigned short int port; +unsigned char val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("outb %0,%1" : :"a" (val), "d" (port)); +} + + +static __inline__ void +#if NeedFunctionPrototypes +outw( +unsigned short int port, +unsigned short int val) +#else +outw(port, val) +unsigned short int port; +unsigned short int val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("outw %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ void +#if NeedFunctionPrototypes +outl( +unsigned short int port, +unsigned int val) +#else +outl(port, val) +unsigned short int port; +unsigned int val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inb( +unsigned short int port) +#else +inb(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned char ret; + __asm__ __volatile__("inb %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inw( +unsigned short int port) +#else +inw(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned short int ret; + __asm__ __volatile__("inw %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inl( +unsigned short int port) +#else +inl(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned int ret; + __asm__ __volatile__("inl %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +#else /* PC98 */ + +static __inline__ void +#if NeedFunctionPrototypes +_outb( +unsigned short int port, +unsigned char val) +#else +_outb(port, val) +unsigned short int port; +unsigned char val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("outb %0,%1" ::"a" (val), "d" (port)); +} + +static __inline__ void +#if NeedFunctionPrototypes +_outw( +unsigned short int port, +unsigned short int val) +#else +_outw(port, val) +unsigned short int port; +unsigned short int val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("outw %0,%1" ::"a" (val), "d" (port)); +} + +static __inline__ void +#if NeedFunctionPrototypes +_outl( +unsigned short int port, +unsigned int val) +#else +_outl(port, val) +unsigned short int port; +unsigned int val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port)); +} + + +static __inline__ unsigned int +#if NeedFunctionPrototypes +_inb( +unsigned short int port) +#else +_inb(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned char ret; + __asm__ __volatile__("inb %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +_inw( +unsigned short int port) +#else +_inw(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned short ret; + __asm__ __volatile__("inw %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +_inl( +unsigned short int port) +#else +_inl(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned int ret; + __asm__ __volatile__("inl %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + + +#if defined(PC98_PW) || defined(PC98_XKB) || defined(PC98_NEC) || defined(PC98_PWLB) || defined(PC98_GA968) +#define PW_PORT 0x600 +extern short chipID; +#if NeedFunctionPrototypes +extern void *mmioBase; +#else +extern unsigned char *mmioBase; +#endif +extern unsigned short _port_tbl[]; +#define port_convert(x) _port_tbl[(unsigned short)x] +#endif + +#if defined(PC98_WAB) || defined(PC98_GANB_WAP) +static __inline__ unsigned short +port_convert(unsigned short port) +{ + port <<= 8; + port &= 0x7f00; /* Mask 0111 1111 0000 0000 */ + port |= 0xE0; + return port; +} +#endif /* PC98_WAB || PC98_GANB_WAP */ + +#if defined(PC98_WABEP) +static __inline__ unsigned short +port_convert(unsigned short port) +{ + port &= 0x7f; /* Mask 0000 0000 0111 1111 */ + port |= 0x0f00; + return port; +} +#endif /* PC98_WABEP */ + +#ifdef PC98_WSNA +static __inline__ unsigned short +port_convert(unsigned short port) +{ + port <<= 8; + port &= 0x7f00; /* Mask 0111 1111 0000 0000 */ + port |= 0xE2; + return port; +} +#endif /* PC98_WSNA */ + +#ifdef PC98_NKVNEC +#ifdef PC98_NEC_CIRRUS2 +static __inline__ unsigned short +port_convert(unsigned short port) +{ + port = (port & 0xf) + ((port & 0xf0) << 4) + 0x0050; + return port; +} +#else +static __inline__ unsigned short +port_convert(unsigned short port) +{ + port = (port & 0xf) + ((port & 0xf0) << 4) + 0x00a0; + return port; +} +#endif /* PC98_NEC_CIRRUS2 */ +#endif /* PC98_NKVNEC */ + +#if defined(PC98_TGUI) || defined(PC98_MGA) +#if NeedFunctionPrototypes +extern void *mmioBase; +#else +extern unsigned char *mmioBase; +#endif +#endif + +static __inline__ void +#if NeedFunctionPrototypes +outb( +unsigned short port, +unsigned char val) +#else +outb(port, val) +unsigned short port; +unsigned char val; +#endif /* NeedFunctionPrototypes */ +{ +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + *(volatile unsigned char *)((char *)mmioBase+(port)) = (unsigned char)(val); +#else + __asm__ __volatile__("outb %0,%1" : :"a" (val), "d" (port)); +#endif +} + +static __inline__ void +#if NeedFunctionPrototypes +outw( +unsigned short port, +unsigned short val) +#else +outw(port, val) +unsigned short port; +unsigned short val; +#endif /* NeedFunctionPrototypes */ +{ +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + *(volatile unsigned short *)((char *)mmioBase+(port)) = (unsigned short)(val); +#else + __asm__ __volatile__("outw %0,%1" : :"a" (val), "d" (port)); +#endif +} + +static __inline__ void +#if NeedFunctionPrototypes +outl( +unsigned short port, +unsigned int val) +#else +outl(port, val) +unsigned short port; +unsigned int val; +#endif /* NeedFunctionPrototypes */ +{ +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + *(volatile unsigned int *)((char *)mmioBase+(port)) = (unsigned int)(val); +#else + __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port)); +#endif +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inb( +unsigned short port) +#else +inb(port) +unsigned short port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned char ret; + +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + ret =*(volatile unsigned char *)((char *)mmioBase+(port)); +#else + __asm__ __volatile__("inb %1,%0" : + "=a" (ret) : + "d" (port)); +#endif + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inw( +unsigned short port) +#else +inw(port) +unsigned short port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned short ret; + +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + ret =*(volatile unsigned short *)((char *)mmioBase+(port)); +#else + __asm__ __volatile__("inw %1,%0" : + "=a" (ret) : + "d" (port)); +#endif + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inl( +unsigned short port) +#else +inl(port) +unsigned short port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned int ret; + +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + ret =*(volatile unsigned int *)((char *)mmioBase+(port)); +#else + __asm__ __volatile__("inl %1,%0" : + "=a" (ret) : + "d" (port)); +#endif + return ret; +} + +#endif /* PC98 */ + +#else /* GCCUSESGAS */ + +static __inline__ void +#if NeedFunctionPrototypes +outb( +unsigned short int port, +unsigned char val) +#else +outb(port, val) +unsigned short int port; +unsigned char val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("out%B0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +#if NeedFunctionPrototypes +outw( +unsigned short int port, +unsigned short int val) +#else +outw(port, val) +unsigned short int port; +unsigned short int val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("out%W0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +#if NeedFunctionPrototypes +outl( +unsigned short int port, +unsigned int val) +#else +outl(port, val) +unsigned short int port; +unsigned int val; +#endif /* NeedFunctionPrototypes */ +{ + __asm__ __volatile__("out%L0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inb( +unsigned short int port) +#else +inb(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned char ret; + __asm__ __volatile__("in%B0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inw( +unsigned short int port) +#else +inw(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned short int ret; + __asm__ __volatile__("in%W0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inl( +unsigned short int port) +#else +inl(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + unsigned int ret; + __asm__ __volatile__("in%L0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +#endif /* GCCUSESGAS */ + +#else /* !defined(FAKEIT) && !defined(__mc68000__) */ + +static __inline__ void +#if NeedFunctionPrototypes +outb( +unsigned short int port, +unsigned char val) +#else +outb(port, val) +unsigned short int port; +unsigned char val; +#endif /* NeedFunctionPrototypes */ +{ +} + +static __inline__ void +#if NeedFunctionPrototypes +outw( +unsigned short int port, +unsigned short int val) +#else +outw(port, val) +unsigned short int port; +unsigned short int val; +#endif /* NeedFunctionPrototypes */ +{ +} + +static __inline__ void +#if NeedFunctionPrototypes +outl( +unsigned short int port, +unsigned int val) +#else +outl(port, val) +unsigned short int port; +unsigned int val; +#endif /* NeedFunctionPrototypes */ +{ +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inb( +unsigned short int port) +#else +inb(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + return 0; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inw( +unsigned short int port) +#else +inw(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + return 0; +} + +static __inline__ unsigned int +#if NeedFunctionPrototypes +inl( +unsigned short int port) +#else +inl(port) +unsigned short int port; +#endif /* NeedFunctionPrototypes */ +{ + return 0; +} + +#endif /* FAKEIT */ + +#endif /* defined(mips) */ +#endif /* defined(AlphaArchitecture) && defined(LinuxArchitecture) */ + +#else /* __GNUC__ */ +#if !defined(AMOEBA) && !defined(MINIX) +# if defined(__STDC__) && (__STDC__ == 1) +# ifndef asm +# define asm __asm +# endif +# endif +# ifdef SVR4 +# include +# ifndef __HIGHC__ +# ifndef __USLC__ +# define __USLC__ +# endif +# endif +# endif +# ifndef PC98 +# ifndef SCO325 +# include +# else +# include "scoasm.h" +# endif +# else +#if defined(PC98_PW) || defined(PC98_XKB) || defined(PC98_NEC) || defined(PC98_PWLB) || defined(PC98_GA968) +#define PW_PORT 0x600 +extern short chipID; +#if NeedFunctionPrototypes +extern void *mmioBase; +#else +extern unsigned char *mmioBase; +#endif +extern unsigned short _port_tbl[]; +#define port_convert(x) _port_tbl[(unsigned short)x] +#endif + +#if defined(PC98_TGUI) || defined(PC98_MGA) +#if NeedFunctionPrototypes +extern void *mmioBase; +#else +extern unsigned char *mmioBase; +#endif +#endif + +asm void _outl(port,val) +{ +%reg port,val; + movl port, %edx + movl val, %eax + outl (%dx) +%reg port; mem val; + movl port, %edx + movl val, %eax + outl (%dx) +%mem port; reg val; + movw port, %dx + movl val, %eax + outl (%dx) +%mem port,val; + movw port, %dx + movl val, %eax + outl (%dx) +} + +asm void _outw(port,val) +{ +%reg port,val; + movl port, %edx + movl val, %eax + data16 + outl (%dx) +%reg port; mem val; + movl port, %edx + movw val, %ax + data16 + outl (%dx) +%mem port; reg val; + movw port, %dx + movl val, %eax + data16 + outl (%dx) +%mem port,val; + movw port, %dx + movw val, %ax + data16 + outl (%dx) +} + +asm void _outb(port,val) +{ +%reg port,val; + movl port, %edx + movl val, %eax + outb (%dx) +%reg port; mem val; + movl port, %edx + movb val, %al + outb (%dx) +%mem port; reg val; + movw port, %dx + movl val, %eax + outb (%dx) +%mem port,val; + movw port, %dx + movb val, %al + outb (%dx) +} + +asm int _inl(port) +{ +%reg port; + movl port, %edx + inl (%dx) +%mem port; + movw port, %dx + inl (%dx) +} + +asm int _inw(port) +{ +%reg port; + subl %eax, %eax + movl port, %edx + data16 + inl (%dx) +%mem port; + subl %eax, %eax + movw port, %dx + data16 + inl (%dx) +} + +asm int _inb(port) +{ +%reg port; + subl %eax, %eax + movl port, %edx + inb (%dx) +%mem port; + subl %eax, %eax + movw port, %dx + inb (%dx) +} + +#if defined(PC98_WAB) || defined(PC98_GANB_WAP) +static unsigned short +port_convert(unsigned short port) +{ + port <<= 8; + port &= 0x7f00; /* Mask 0111 1111 0000 0000 */ + port |= 0xE0; + return port; +} +#endif /* PC98_WAB || PC98_GANB_WAP */ + +#if defined(PC98_WABEP) +static unsigned short +port_convert(unsigned short port) +{ + port &= 0x7f; /* Mask 0000 0000 0111 1111 */ + port |= 0x0f00; + return port; +} +#endif /* PC98_WABEP */ + +#ifdef PC98_WSNA +static unsigned short +port_convert(unsigned short port) +{ + port <<= 8; + port &= 0x7f00; /* Mask 0111 1111 0000 0000 */ + port |= 0xE2; + return port; +} +#endif /* PC98_WSNA */ + +#ifdef PC98_NKVNEC +#ifdef PC98_NEC_CIRRUS2 +static unsigned short +port_convert(unsigned short port) +{ + port = (port & 0xf) + ((port & 0xf0) << 4) + 0x0050; + return port; +} +#else +static unsigned short +port_convert(unsigned short port) +{ + port = (port & 0xf) + ((port & 0xf0) << 4) + 0x00a0; + return port; +} +#endif /* PC98_NEC_CIRRUS2 */ +#endif /* PC98_NKVNEC */ + +static void outl(port,val) +{ +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + *(volatile unsigned int *)((char *)mmioBase+(port)) = (unsigned int)(val); +#else + _outl(port,val); +#endif +} + +static void outw(port,val) +{ +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + *(volatile unsigned short *)((char *)mmioBase+(port)) = (unsigned short)(val); +#else + _outw(port,val); +#endif +} + +static void outb(port,val) +{ +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + *(volatile unsigned char *)((char *)mmioBase+(port)) = (unsigned char)(val); +#else + _outb(port,val); +#endif +} + +static int inl(port) +{ + unsigned int ret; + +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + ret =*(volatile unsigned int *)((char *)mmioBase+(port)); +#else + ret = _inl(port); +#endif + return ret; +} + +static int inw(port) +{ + unsigned short ret; + +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + ret =*(volatile unsigned short *)((char *)mmioBase+(port)); +#else + ret = _inw(port); +#endif + return ret; +} + +static int inb(port) +{ + unsigned char ret; + +#if defined(PC98_GANB_WAP) || defined(PC98_NKVNEC) || defined(PC98_WAB) || \ + defined(PC98_WABEP) || defined(PC98_WSNA) || defined(PC98_PW) || \ + defined(PC98_XKB) || defined(PC98_NEC) + unsigned short tmp; + tmp=port_convert(port); + port=tmp; +#endif + +#if defined(PC98_NEC)||defined(PC98_PWLB)||defined(PC98_TGUI)||defined(PC98_MGA) + ret =*(volatile unsigned char *)((char *)mmioBase+(port)); +#else + ret = _inb(port); +#endif + return ret; +} + + +# endif /* PC98 */ +# if !defined(__HIGHC__) && !defined(SCO325) +# pragma asm partial_optimization outl +# pragma asm partial_optimization outw +# pragma asm partial_optimization outb +# pragma asm partial_optimization inl +# pragma asm partial_optimization inw +# pragma asm partial_optimization inb +# endif +#endif +#define ldq_u(p) (*((unsigned long *)(p))) +#define ldl_u(p) (*((unsigned int *)(p))) +#define ldw_u(p) (*((unsigned short *)(p))) +#define stq_u(v,p) ((unsigned long *)(p)) = (v) +#define stl_u(v,p) ((unsigned int *)(p)) = (v) +#define stw_u(v,p) ((unsigned short *)(p)) = (v) +#define mem_barrier() /* NOP */ +#define write_mem_barrier() /* NOP */ +#endif /* __GNUC__ */ + +#if defined(IODEBUG) && defined(__GNUC__) +#undef inb +#undef inw +#undef inl +#undef outb +#undef outw +#undef outl +#define inb(a) __extension__ ({unsigned char __c=RealInb(a); ErrorF("inb(0x%03x) = 0x%02x\t@ line %4d, file %s\n", a, __c, __LINE__, __FILE__);__c;}) +#define inw(a) __extension__ ({unsigned short __c=RealInw(a); ErrorF("inw(0x%03x) = 0x%04x\t@ line %4d, file %s\n", a, __c, __LINE__, __FILE__);__c;}) +#define inl(a) __extension__ ({unsigned long __c=RealInl(a); ErrorF("inl(0x%03x) = 0x%08x\t@ line %4d, file %s\n", a, __c, __LINE__, __FILE__);__c;}) + +#define outb(a,b) (ErrorF("outb(0x%03x, 0x%02x)\t@ line %4d, file %s\n", a, b, __LINE__, __FILE__),RealOutb(a,b)) +#define outw(a,b) (ErrorF("outw(0x%03x, 0x%04x)\t@ line %4d, file %s\n", a, b, __LINE__, __FILE__),RealOutw(a,b)) +#define outl(a,b) (ErrorF("outl(0x%03x, 0x%08x)\t@ line %4d, file %s\n", a, b, __LINE__, __FILE__),RealOutl(a,b)) +#endif + +/* + * This header sometimes gets included where is isn't needed, and on some + * OSs this causes problems because the following functions generate + * references to inb() and outb() which can't be resolved. Defining + * NO_COMPILER_H_EXTRAS avoids this problem. + */ + +#ifndef NO_COMPILER_H_EXTRAS +/* + *----------------------------------------------------------------------- + * Port manipulation convenience functions + *----------------------------------------------------------------------- + */ + +#ifndef __GNUC__ +#define __inline__ /**/ +#endif + +/* + * rdinx - read the indexed byte port 'port', index 'ind', and return its value + */ +static __inline__ unsigned char +#ifdef __STDC__ +rdinx(unsigned short int port, unsigned char ind) +#else +rdinx(port, ind) +unsigned short int port; +unsigned char ind; +#endif +{ + if (port == 0x3C0) /* reset attribute flip-flop */ + (void) inb(0x3DA); + outb(port, ind); + return(inb(port+1)); +} + +/* + * wrinx - write 'val' to port 'port', index 'ind' + */ +static __inline__ void +#ifdef __STDC__ +wrinx(unsigned short int port, unsigned char ind, unsigned char val) +#else +wrinx(port, ind, val) +unsigned short int port; +unsigned char ind, val; +#endif +{ + outb(port, ind); + outb(port+1, val); +} + +/* + * modinx - in register 'port', index 'ind', set the bits in 'mask' as in 'new'; + * the other bits are unchanged. + */ +static __inline__ void +#ifdef __STDC__ +modinx(unsigned short int port, unsigned char ind, + unsigned char mask, unsigned char new) +#else +modinx(port, ind, mask, new) +unsigned short int port; +unsigned char ind, mask, new; +#endif +{ + unsigned char tmp; + + tmp = (rdinx(port, ind) & ~mask) | (new & mask); + wrinx(port, ind, tmp); +} + +/* + * tstrg - returns true iff the bits in 'mask' of register 'port' are + * readable & writable. + */ + +static __inline__ int +#ifdef __STDC__ +testrg(unsigned short int port, unsigned char mask) +#else +tstrg(port, mask) +unsigned short int port; +unsigned char mask; +#endif +{ + unsigned char old, new1, new2; + + old = inb(port); + outb(port, old & ~mask); + new1 = inb(port) & mask; + outb(port, old | mask); + new2 = inb(port) & mask; + outb(port, old); + return((new1 == 0) && (new2 == mask)); +} + +/* + * testinx2 - returns true iff the bits in 'mask' of register 'port', index + * 'ind' are readable & writable. + */ +static __inline__ int +#ifdef __STDC__ +testinx2(unsigned short int port, unsigned char ind, unsigned char mask) +#else +testinx2(port, ind, mask) +unsigned short int port; +unsigned char ind, mask; +#endif +{ + unsigned char old, new1, new2; + + old = rdinx(port, ind); + wrinx(port, ind, old & ~mask); + new1 = rdinx(port, ind) & mask; + wrinx(port, ind, old | mask); + new2 = rdinx(port, ind) & mask; + wrinx(port, ind, old); + return((new1 == 0) && (new2 == mask)); +} + +/* + * testinx - returns true iff all bits of register 'port', index 'ind' are + * readable & writable. + */ +static __inline__ int +#ifdef __STDC__ +testinx(unsigned short int port, unsigned char ind) +#else +testinx(port, ind, mask) +unsigned short int port; +unsigned char ind; +#endif +{ + return(testinx2(port, ind, 0xFF)); +} +#endif /* NO_COMPILER_H_EXTRAS */ + +#endif /* NO_INLINE */ +#endif /* _COMPILER_H */ diff --git a/hw/xfree86/common/scoasm.h b/hw/xfree86/common/scoasm.h new file mode 100644 index 000000000..12fe46693 --- /dev/null +++ b/hw/xfree86/common/scoasm.h @@ -0,0 +1,112 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/scoasm.h,v 3.0 1996/10/03 08:34:06 dawes Exp $ */ + +/* + * scoasm.h - used to define inline versions of certain functions which + * do NOT appear in sys/inline.h. + */ +#ifdef SCO325 +#ifndef _SCOASM_HDR_INC +#define _SCOASM_HDR_INC + +asm void outl(port,val) +{ +%reg port,val; + movl port, %edx + movl val, %eax + outl (%dx) +%reg port; mem val; + movl port, %edx + movl val, %eax + outl (%dx) +%mem port; reg val; + movw port, %dx + movl val, %eax + outl (%dx) +%mem port,val; + movw port, %dx + movl val, %eax + outl (%dx) +} + +asm void outw(port,val) +{ +%reg port,val; + movl port, %edx + movl val, %eax + data16 + outl (%dx) +%reg port; mem val; + movl port, %edx + movw val, %ax + data16 + outl (%dx) +%mem port; reg val; + movw port, %dx + movl val, %eax + data16 + outl (%dx) +%mem port,val; + movw port, %dx + movw val, %ax + data16 + outl (%dx) +} + +asm void outb(port,val) +{ +%reg port,val; + movl port, %edx + movl val, %eax + outb (%dx) +%reg port; mem val; + movl port, %edx + movb val, %al + outb (%dx) +%mem port; reg val; + movw port, %dx + movl val, %eax + outb (%dx) +%mem port,val; + movw port, %dx + movb val, %al + outb (%dx) +} + +asm int inl(port) +{ +%reg port; + movl port, %edx + inl (%dx) +%mem port; + movw port, %dx + inl (%dx) +} + +asm int inw(port) +{ +%reg port; + subl %eax, %eax + movl port, %edx + data16 + inl (%dx) +%mem port; + subl %eax, %eax + movw port, %dx + data16 + inl (%dx) +} + +asm int inb(port) +{ +%reg port; + subl %eax, %eax + movl port, %edx + inb (%dx) +%mem port; + subl %eax, %eax + movw port, %dx + inb (%dx) +} + +#endif /* _SCOASM_HDR_INC */ +#endif /* SCO325 */ diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h new file mode 100644 index 000000000..ba00913d8 --- /dev/null +++ b/hw/xfree86/common/xf86.h @@ -0,0 +1,743 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86.h,v 3.47.2.8 1998/02/24 19:05:53 hohndel Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86.h,v 1.3 2000/08/17 19:50:28 cpqbld Exp $ */ + +#ifndef _XF86_H +#define _XF86_H + +#include "misc.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86_Option.h" + +/* + * structure common for all modes + */ +typedef struct _DispM { + struct _DispM *prev,*next; + char *name; /* identifier of this mode */ + /* These are the values that the user sees/provides */ + int Clock; /* pixel clock */ + int HDisplay; /* horizontal timing */ + int HSyncStart; + int HSyncEnd; + int HTotal; + int HSkew; + int VDisplay; /* vertical timing */ + int VSyncStart; + int VSyncEnd; + int VTotal; + int Flags; + /* These are the values the hardware uses */ + int SynthClock; /* Actual clock freq to be programmed */ + int CrtcHDisplay; + int CrtcHSyncStart; + int CrtcHSyncEnd; + int CrtcHTotal; + int CrtcHSkew; + int CrtcVDisplay; + int CrtcVSyncStart; + int CrtcVSyncEnd; + int CrtcVTotal; + Bool CrtcHAdjusted; + Bool CrtcVAdjusted; + int PrivSize; + INT32 *Private; +} DisplayModeRec, *DisplayModePtr; + +#define V_PHSYNC 0x0001 +#define V_NHSYNC 0x0002 +#define V_PVSYNC 0x0004 +#define V_NVSYNC 0x0008 +#define V_INTERLACE 0x0010 +#define V_DBLSCAN 0x0020 +#define V_CSYNC 0x0040 +#define V_PCSYNC 0x0080 +#define V_NCSYNC 0x0100 +#define V_HSKEW 0x0200 /* hskew provided */ +#define V_PIXMUX 0x1000 +#define V_DBLCLK 0x2000 +#define V_CLKDIV2 0x4000 + +/* The monitor description */ + +#define MAX_HSYNC 8 +#define MAX_VREFRESH 8 + +typedef struct { float hi, lo; } range; + +typedef struct { + char *id; + char *vendor; + char *model; + float EMPTY; + int n_hsync; + range hsync[MAX_HSYNC]; + int n_vrefresh; + range vrefresh[MAX_VREFRESH]; + DisplayModePtr Modes, Last; /* Start and end of monitor's mode list */ +} MonRec, *MonPtr; + +#define MAXCLOCKS 128 +#define MAXDACSPEEDS 4 /* for <= 8, 16, 24, 32bpp */ + +/* Set default max allowed clock to 90MHz */ +#define DEFAULT_MAX_CLOCK 90000 + +/* + * the graphic device + */ +typedef struct { + Bool configured; + int tmpIndex; + int scrnIndex; + Bool (* Probe)( +#if NeedNestedPrototypes + void +#endif +); + Bool (* Init)( +#if NeedNestedPrototypes + int scr_index, + ScreenPtr pScreen, + int argc, + char **argv +#endif +); + int (* ValidMode)( +#if NeedNestedPrototypes + DisplayModePtr target, + Bool verbose, + int flag +#endif +); + void (* EnterLeaveVT)( +#if NeedNestedPrototypes + int, + int +#endif +); + void (* EnterLeaveMonitor)( +#if NeedNestedPrototypes + int +#endif +); + void (* EnterLeaveCursor)( +#if NeedNestedPrototypes + int +#endif +); + void (* AdjustFrame)( +#if NeedNestedPrototypes + int x, + int y +#endif +); + Bool (* SwitchMode)( +#if NeedNestedPrototypes + DisplayModePtr modes +#endif +); + void (* DPMSSet)( +#if NeedNestedPrototypes + int level +#endif +); + void (* PrintIdent)( +#if NeedNestedPrototypes + void +#endif +); + int depth; + xrgb weight; + int bitsPerPixel; + int defaultVisual; + int virtualX,virtualY; + int displayWidth; + int frameX0, frameY0, frameX1, frameY1; + OFlagSet options; + OFlagSet clockOptions; + OFlagSet xconfigFlag; + char *chipset; + char *ramdac; + int dacSpeeds[MAXDACSPEEDS]; + int dacSpeedBpp; + int clocks; + int clock[MAXCLOCKS]; + int maxClock; + int videoRam; + int BIOSbase; /* Base address of video BIOS */ + unsigned long MemBase; /* Frame buffer base address */ + int width, height; /* real display dimensions */ + unsigned long speedup; /* Use SpeedUp code */ + DisplayModePtr modes; + MonPtr monitor; + char *clockprog; + int textclock; + Bool bankedMono; /* display supports banking for mono server */ + char *name; + xrgb blackColour; + xrgb whiteColour; + int *validTokens; + char *patchLevel; + unsigned int IObase; /* AGX - video card I/O reg base */ + unsigned int DACbase; /* AGX - dac I/O reg base */ + unsigned long COPbase; /* AGX - coprocessor memory base */ + unsigned int POSbase; /* AGX - I/O address of POS regs */ + int instance; /* AGX - XGA video card instance number */ + int s3Madjust; + int s3Nadjust; + int s3MClk; + int chipID; + int chipRev; + unsigned long VGAbase; /* AGX - 64K aperture memory address */ + int s3RefClk; + int s3BlankDelay; + int textClockFreq; + char *DCConfig; + char *DCOptions; + int MemClk; /* General flag used for memory clocking */ + int LCDClk; +#ifdef XFreeXDGA + int directMode; + void (*setBank)( +#if NeedNestedPrototypes + int +#endif + ); + unsigned long physBase; + int physSize; +#endif +#ifdef XF86SETUP + void *device; /* This should be GDevPtr, but it causes + problems with include file order */ +#endif +} ScrnInfoRec, *ScrnInfoPtr; + +typedef struct { + int token; /* id of the token */ + char *name; /* pointer to the LOWERCASED name */ +} SymTabRec, *SymTabPtr; + +#define VGA_DRIVER 1 +#define V256_DRIVER 2 +#define WGA_DRIVER 3 +#define XGA_DRIVER 4 + +#define ENTER 1 +#define LEAVE 0 + +/* These are possible return values for xf86CheckMode() and ValidMode() */ +#define MODE_OK 0 +#define MODE_HSYNC 1 /* hsync out of range */ +#define MODE_VSYNC 2 /* vsync out of range */ +#define MODE_BAD 255 /* unspecified reason */ + +/* These are the possible flags for ValidMode */ +#define MODE_USED 1 /* this mode is really being used in the */ + /* modes line of the Display Subsection */ +#define MODE_SUGGESTED 2 /* this mode is included in the available*/ + /* modes in the Monitor Section */ +#define MODE_VID 3 /* this is called from the VidMode extension */ + +/* Indicates the level of DPMS support */ +typedef enum { + DPMSSupportUnknown, + DPMSNotSupported, + DPMSFullSupport +} DPMSSupportStatus; + +/* flags for xf86LookupMode */ +#define LOOKUP_DEFAULT 0 /* Use default mode lookup method */ +#define LOOKUP_BEST_REFRESH 1 /* Pick modes with best refresh */ +#define LOOKUP_NO_INTERLACED 2 /* Ignore interlaced modes */ +#define LOOKUP_FORCE_DEFAULT 4 /* Force default lookup method */ + +#define INTERLACE_REFRESH_WEIGHT 1.5 + +/* SpeedUp options */ + +#define SPEEDUP_FILLBOX 1 +#define SPEEDUP_FILLRECT 2 +#define SPEEDUP_BITBLT 4 +#define SPEEDUP_LINE 8 +#define SPEEDUP_TEGBLT8 0x10 +#define SPEEDUP_RECTSTIP 0x20 + +/* + * This is the routines where SpeedUp is quicker than fXF86. The problem is + * that the SpeedUp fillbox is better for drawing vertical and horizontal + * line segments, and the fXF86 version is significantly better for + * more general lines + */ +#define SPEEDUP_BEST (SPEEDUP_FILLRECT | SPEEDUP_BITBLT | \ + SPEEDUP_LINE | SPEEDUP_TEGBLT8 | \ + SPEEDUP_RECTSTIP) +/* +#define SPEEDUP_BEST (SPEEDUP_FILLBOX | SPEEDUP_FILLRECT | \ + SPEEDUP_BITBLT | SPEEDUP_LINE | \ + SPEEDUP_TEGBLT8 | SPEEDUP_RECTSTIP) +*/ + +/* + * SpeedUp routines which are not dependent on the screen virtual resolution + */ +#ifndef SPEEDUP_ANYWIDTH +#define SPEEDUP_ANYWIDTH (SPEEDUP_FILLRECT | SPEEDUP_BITBLT | \ + SPEEDUP_LINE | SPEEDUP_FILLBOX) +#endif + +/* + * SpeedUp routines which are not dependent on ET4000 + */ +#ifndef SPEEDUP_ANYCHIPSET +#define SPEEDUP_ANYCHIPSET (SPEEDUP_TEGBLT8 | SPEEDUP_RECTSTIP) +#endif + +/* All SpeedUps */ +#define SPEEDUP_ALL (SPEEDUP_FILLBOX | SPEEDUP_FILLRECT | \ + SPEEDUP_BITBLT | SPEEDUP_LINE | \ + SPEEDUP_TEGBLT8 | SPEEDUP_RECTSTIP) + +/* SpeedUp flags used if SpeedUp is not in XF86Config */ +#define SPEEDUP_DEFAULT SPEEDUP_ALL + +extern Bool xf86VTSema; + +/* Mouse device private record */ + +#define MSE_MAPTOX (-1) +#define MSE_MAPTOY (-2) +#define MSE_MAXBUTTONS 12 +#define MSE_DFLTBUTTONS 3 + +typedef struct _MouseDevRec { + DeviceProc mseProc; /* procedure for initializing */ + void (* mseEvents)( +#if NeedNestedPrototypes + struct _MouseDevRec * +#endif + ); /* proc for processing events */ + DeviceIntPtr device; + int mseFd; + char *mseDevice; + int mseType; + int mseModel; + int baudRate; + int oldBaudRate; + int sampleRate; + int lastButtons; + int threshold, num, den; /* acceleration */ + int buttons; /* # of buttons */ + int emulateState; /* automata state for 2 button mode */ + Bool emulate3Buttons; + int emulate3Timeout; /* Timeout for 3 button emulation */ + Bool chordMiddle; + int mouseFlags; /* Flags to Clear after opening mouse dev */ + int truebuttons; /* Arg to maintain before emulate3buttons timer callback */ + + int resolution; + int negativeZ; + int positiveZ; +#ifndef MOUSE_PROTOCOL_IN_KERNEL + unsigned char protoPara[7]; +#endif + +#ifndef CSRG_BASED + /* xque part */ + int xquePending; /* was xqueFd, but nothing uses that */ + int xqueSema; +#endif +#ifdef XINPUT + struct _LocalDeviceRec *local; +#endif +} MouseDevRec, *MouseDevPtr; + +#ifdef XINPUT +#define MOUSE_DEV(dev) (MouseDevPtr) PRIVATE(dev) +#else +#define MOUSE_DEV(dev) (MouseDevPtr) (dev)->public.devicePrivate +#endif + +/* Global data */ +/* xf86Init.c */ +extern double xf86rGamma, xf86gGamma, xf86bGamma; + +#ifdef XF86VIDMODE +extern Bool xf86VidModeEnabled; +extern Bool xf86VidModeAllowNonLocal; +#endif +#ifdef XF86MISC +extern Bool xf86MiscModInDevEnabled; +extern Bool xf86MiscModInDevAllowNonLocal; +#endif + +/* PCI probe flags */ + + +typedef enum { + PCIProbe1 = 0, + PCIProbe2, + PCIForceConfig1, + PCIForceConfig2 +} PciProbeType; + +extern PciProbeType xf86PCIFlags; + +/* Function Prototypes */ +#ifndef _NO_XF86_PROTOTYPES + +/* xf86Init.c */ +void InitOutput( +#if NeedFunctionPrototypes + ScreenInfo *pScreenInfo, + int argc, + char **argv +#endif +); + +void InitInput( +#if NeedFunctionPrototypes + int argc, + char **argv +#endif +); + +void ddxGiveUp( +#if NeedFunctionPrototypes + void +#endif +); + +void AbortDDX( +#if NeedFunctionPrototypes + void +#endif +); + +int ddxProcessArgument( +#if NeedFunctionPrototypes + int argc, + char *argv[], + int i +#endif +); + +void ddxUseMsg( +#if NeedFunctionPrototypes + void +#endif +); + +/* xf86Config.c */ +unsigned int StrToUL( +#if NeedFunctionPrototypes + char *str +#endif +); + +#ifndef CONFIG_RETURN_TYPE +#ifdef XF86SETUP +#define CONFIG_RETURN_TYPE int +#else +#define CONFIG_RETURN_TYPE void +#endif +#endif + +CONFIG_RETURN_TYPE xf86Config( +#if NeedFunctionPrototypes + int vtopen +#endif +); + +CONFIG_RETURN_TYPE configPointerSection( +#if NeedFunctionPrototypes + MouseDevPtr /*mouse_dev*/, + int /*end_tag*/, + char** /*devicename*/ +#endif +); + +Bool xf86LookupMode( +#if NeedFunctionPrototypes + DisplayModePtr target, + ScrnInfoPtr driver, + int flags +#endif +); + +void xf86VerifyOptions( +#if NeedFunctionPrototypes + OFlagSet *allowedOptions, + ScrnInfoPtr driver +#endif +); + +int xf86CheckMode( +#if NeedFunctionPrototypes + ScrnInfoPtr scrp, + DisplayModePtr dispmp, + MonPtr monp, + int verbose +#endif +); + +int xf86GetNearestClock( +#if NeedFunctionPrototypes + ScrnInfoPtr Screen, + int Frequency +#endif +); + +/* xf86Cursor.c */ +void xf86InitViewport( +#if NeedFunctionPrototypes + ScrnInfoPtr pScr +#endif +); + +void xf86SetViewport( +#if NeedFunctionPrototypes + ScreenPtr pScreen, + int x, + int y +#endif +); + +void xf86LockZoom( +#if NeedFunctionPrototypes + ScreenPtr pScreen, + int lock +#endif +); + +void xf86ZoomViewport( +#if NeedFunctionPrototypes + ScreenPtr pScreen, + int zoom +#endif +); + +/* xf86Dl.c */ +void* +xf86LoadModule( +#if NeedFunctionPrototypes + const char * file, + const char * path +#endif +); + +/* xf86Events.c */ +int TimeSinceLastInputEvent( +#if NeedFunctionPrototypes + void +#endif +); + +void SetTimeSinceLastInputEvent( +#if NeedFunctionPrototypes + void +#endif +); + +void ProcessInputEvents( +#if NeedFunctionPrototypes + void +#endif +); + +void xf86PostKbdEvent( +#if NeedFunctionPrototypes + unsigned key +#endif +); + +void xf86PostMseEvent( +#if NeedFunctionPrototypes + DeviceIntPtr device, + int buttons, + int dx, + int dy +#endif +); + +void xf86Block( +#if NeedFunctionPrototypes + pointer blockData, + OSTimePtr pTimeout, + pointer pReadmask +#endif +); + +void xf86Wakeup( +#if NeedFunctionPrototypes + pointer blockData, + int err, + pointer pReadmask +#endif +); + +void xf86SigHandler( +#if NeedFunctionPrototypes + int signo +#endif +); + +/* xf86Io.c */ +void xf86KbdBell( +#if NeedFunctionPrototypes + int percent, + DeviceIntPtr pKeyboard, + pointer ctrl, + int unused +#endif +); + +void xf86KbdLeds( +#if NeedFunctionPrototypes + void +#endif +); + +void xf86KbdCtrl( +#if NeedFunctionPrototypes + DevicePtr pKeyboard, + KeybdCtrl *ctrl +#endif +); + +void xf86InitKBD( +#if NeedFunctionPrototypes + Bool init +#endif +); + +int xf86KbdProc( +#if NeedFunctionPrototypes + DeviceIntPtr pKeyboard, + int what +#endif +); + +void xf86MseCtrl( +#if NeedFunctionPrototypes + DevicePtr pPointer, + PtrCtrl *ctrl +#endif +); + +int GetMotionEvents( +#if NeedFunctionPrototypes + DeviceIntPtr, + xTimecoord *, + unsigned long, + unsigned long, + ScreenPtr +#endif +); + +int xf86MseProc( +#if NeedFunctionPrototypes + DeviceIntPtr pPointer, + int what +#endif +); + +void xf86MseEvents( +#if NeedFunctionPrototypes + MouseDevPtr mouse +#endif +); + +CARD32 GetTimeInMillis( +#if NeedFunctionPrototypes + void +#endif +); + +void OsVendorInit( +#if NeedFunctionPrototypes + void +#endif +); + +/* xf86_Mouse.c */ +Bool xf86MouseSupported( +#if NeedFunctionPrototypes + int mousetype +#endif +); + +void xf86SetupMouse( +#if NeedFunctionPrototypes + MouseDevPtr mouse +#endif +); + +void xf86MouseProtocol( +#if NeedFunctionPrototypes + DeviceIntPtr device, + unsigned char *rBuf, + int nBytes +#endif +); + +#ifdef XINPUT +void xf86MouseCtrl( +#if NeedFunctionPrototypes + DeviceIntPtr device, + PtrCtrl *ctrl +#endif +); +#endif + +/* xf86_PnPMouse.c */ +int xf86GetPnPMouseProtocol( +#if NeedFunctionPrototypes + MouseDevPtr mouse +#endif +); + +/* xf86Kbd.c */ +Bool LegalModifier( +#if NeedFunctionPrototypes + unsigned int key, + DevicePtr pDev +#endif +); + +void xf86KbdGetMapping( +#if NeedFunctionPrototypes + KeySymsPtr pKeySyms, + CARD8 *pModMap +#endif +); +#endif /* _NO_XF86_PROTOTYPES */ + +/* End of Prototypes */ + +#endif /* _XF86_H */ + + diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c new file mode 100644 index 000000000..e523dd0fc --- /dev/null +++ b/hw/xfree86/common/xf86Config.c @@ -0,0 +1,3934 @@ +/* + * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Config.c,v 3.113.2.17 1998/02/24 19:05:54 hohndel Exp $ + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + */ +/* $Xorg: xf86Config.c,v 1.3 2000/08/17 19:50:28 cpqbld Exp $ */ + +#ifndef X_NOT_STDC_ENV +#include +#else +extern double atof(); +extern char *getenv(); +#endif + +#define NEED_EVENTS 1 +#include "X.h" +#include "Xproto.h" +#include "Xmd.h" +#include "input.h" +#include "servermd.h" +#include "scrnintstr.h" + +#ifdef DPMSExtension +#include "opaque.h" +extern CARD32 DPMSStandbyTime; +extern CARD32 DPMSSuspendTime; +extern CARD32 DPMSOffTime; +#endif + +#define NO_COMPILER_H_EXTRAS +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +#define INIT_CONFIG +#include "xf86_Config.h" + +#ifdef XKB +#include "inputstr.h" +#include "XKBsrv.h" +#endif + +#ifdef XF86SETUP +#include "xfsconf.h" +#endif + +#ifdef XINPUT +#include "xf86Xinput.h" + +#ifndef XF86SETUP +extern DeviceAssocRec mouse_assoc; +#endif +#endif + +#ifdef NEED_RETURN_VALUE +#define HANDLE_RETURN(xx) if (xx == RET_ERROR) return RET_ERROR +#else +#define HANDLE_RETURN(xx) xx +#endif + +#define CONFIG_BUF_LEN 1024 + +static FILE * configFile = NULL; +static int configStart = 0; /* start of the current token */ +static int configPos = 0; /* current readers position */ +static int configLineNo = 0; /* linenumber */ +static char *configBuf,*configRBuf; /* buffer for lines */ +static char *configPath; /* path to config file */ +static char *fontPath = NULL; /* font path */ +static char *modulePath = NULL; /* module path */ +static int pushToken = LOCK_TOKEN; +static LexRec val; /* global return value */ +static char DCerr; +static int scr_index = 0; + +#ifdef XF86SETUP +#define STATIC_OR_NOT +#else +#define STATIC_OR_NOT static +#endif +STATIC_OR_NOT int n_monitors = 0; +STATIC_OR_NOT MonPtr monitor_list = NULL; +STATIC_OR_NOT int n_devices = 0; +STATIC_OR_NOT GDevPtr device_list = NULL; + +static int screenno = -100; /* some little number ... */ + +extern char *defaultFontPath; +extern char *rgbPath; + +extern Bool xf86fpFlag, xf86coFlag, xf86sFlag; +extern Bool xf86ScreensOpen; + +extern int defaultColorVisualClass; +extern CARD32 defaultScreenSaverTime, ScreenSaverTime; + +char *xf86VisualNames[] = { + "StaticGray", + "GrayScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor" +}; + +static CONFIG_RETURN_TYPE configFilesSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configServerFlagsSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configKeyboardSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configDeviceSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configScreenSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configDisplaySubsection( +#if NeedFunctionPrototypes + DispPtr disp +#endif +); +static CONFIG_RETURN_TYPE configMonitorSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configDynamicModuleSection( +#if NeedFunctionPrototypes + void +#endif +); +static char *xf86DCSaveLine( +#if NeedFunctionPrototypes +char *, +int +#endif +); +static char *xf86DCOption( +#if NeedFunctionPrototypes +char *, +LexRec +#endif +); +static char * xf86DCConcatOption( +#if NeedFunctionPrototypes +char *, +char * +#endif +); +#ifndef XF86SETUP +static +#endif +CONFIG_RETURN_TYPE findConfigFile( +#if NeedFunctionPrototypes + char *filename, + FILE **fp +#endif +); +static int getScreenIndex( +#if NeedFunctionPrototypes + int token +#endif +); +static int getStringToken( +#if NeedFunctionPrototypes + SymTabRec tab[] +#endif +); +static CONFIG_RETURN_TYPE readVerboseMode( +#if NeedFunctionPrototypes + MonPtr monp +#endif +); +static Bool validateGraphicsToken( +#if NeedFunctionPrototypes + int *validTokens, + int token +#endif +); +extern char * xf86GetPathElem( +#if NeedFunctionPrototypes + char **pnt +#endif +); +static DisplayModePtr xf86PruneModes( +#if NeedFunctionPrototypes + MonPtr monp, + DisplayModePtr allmodes, + ScrnInfoPtr scrp, + Bool card +#endif +); +static char * xf86ValidateFontPath( +#if NeedFunctionPrototypes + char * /* path */ +#endif +); +#ifdef XINPUT +extern CONFIG_RETURN_TYPE xf86ConfigExtendedInputSection( +#if NeedFunctionPrototypes + LexPtr pval +#endif +); +#endif + +#ifdef XKB +extern char *XkbInitialMap; +#endif + +#define DIR_FILE "/fonts.dir" + +/* + * xf86GetPathElem -- + * Extract a single element from the font path string starting at + * pnt. The font path element will be returned, and pnt will be + * updated to point to the start of the next element, or set to + * NULL if there are no more. + */ +char * +xf86GetPathElem(pnt) + char **pnt; +{ + char *p1; + + p1 = *pnt; + *pnt = index(*pnt, ','); + if (*pnt != NULL) { + **pnt = '\0'; + *pnt += 1; + } + return(p1); +} + +/* + * StrToUL -- + * + * A portable, but restricted, version of strtoul(). It only understands + * hex, octal, and decimal. But it's good enough for our needs. + */ +unsigned int StrToUL(str) +char *str; +{ + int base = 10; + char *p = str; + unsigned int tot = 0; + + if (*p == '0') { + p++; + if (*p == 'x') { + p++; + base = 16; + } + else + base = 8; + } + while (*p) { + if ((*p >= '0') && (*p <= ((base == 8)?'7':'9'))) { + tot = tot * base + (*p - '0'); + } + else if ((base == 16) && (*p >= 'a') && (*p <= 'f')) { + tot = tot * base + 10 + (*p - 'a'); + } + else if ((base == 16) && (*p >= 'A') && (*p <= 'F')) { + tot = tot * base + 10 + (*p - 'A'); + } + else { + return(tot); + } + p++; + } + return(tot); +} + +/* + * xf86ValidateFontPath -- + * Validates the user-specified font path. Each element that + * begins with a '/' is checked to make sure the directory exists. + * If the directory exists, the existence of a file named 'fonts.dir' + * is checked. If either check fails, an error is printed and the + * element is removed from the font path. + */ +#define CHECK_TYPE(mode, type) ((S_IFMT & (mode)) == (type)) +static char * +xf86ValidateFontPath(path) + char *path; +{ + char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem; + struct stat stat_buf; + int flag; + int dirlen; + + tmp_path = (char *)Xcalloc(strlen(path)+1); + out_pnt = tmp_path; + path_elem = NULL; + next = path; + while (next != NULL) { + path_elem = xf86GetPathElem(&next); +#ifndef __EMX__ + if (*path_elem == '/') { + dir_elem = (char *)Xcalloc(strlen(path_elem) + 1); + if ((p1 = strchr(path_elem, ':')) != 0) +#else + /* OS/2 must prepend X11ROOT */ + if (*path_elem == '/') { + path_elem = (char*)__XOS2RedirRoot(path_elem); + dir_elem = (char*)xcalloc(1, strlen(path_elem) + 1); + if (p1 = strchr(path_elem+2, ':')) +#endif + dirlen = p1 - path_elem; + else + dirlen = strlen(path_elem); + strncpy(dir_elem, path_elem, dirlen); + dir_elem[dirlen] = '\0'; + flag = stat(dir_elem, &stat_buf); + if (flag == 0) + if (!CHECK_TYPE(stat_buf.st_mode, S_IFDIR)) + flag = -1; + if (flag != 0) { + ErrorF("Warning: The directory \"%s\" does not exist.\n", dir_elem); + ErrorF(" Entry deleted from font path.\n"); + continue; + } + else { + p1 = (char *)xalloc(strlen(dir_elem)+strlen(DIR_FILE)+1); + strcpy(p1, dir_elem); + strcat(p1, DIR_FILE); + flag = stat(p1, &stat_buf); + if (flag == 0) + if (!CHECK_TYPE(stat_buf.st_mode, S_IFREG)) + flag = -1; +#ifndef __EMX__ + xfree(p1); +#endif + if (flag != 0) { + ErrorF("Warning: 'fonts.dir' not found (or not valid) in \"%s\".\n", + dir_elem); + ErrorF(" Entry deleted from font path.\n"); + ErrorF(" (Run 'mkfontdir' on \"%s\").\n", dir_elem); + continue; + } + } + xfree(dir_elem); + } + + /* + * Either an OK directory, or a font server name. So add it to + * the path. + */ + if (out_pnt != tmp_path) + *out_pnt++ = ','; + strcat(out_pnt, path_elem); + out_pnt += strlen(path_elem); + } + return(tmp_path); +} + +/* + * xf86GetToken -- + * Read next Token form the config file. Handle the global variable + * pushToken. + */ +int +xf86GetToken(tab) + SymTabRec tab[]; +{ + int c, i; + + /* + * First check whether pushToken has a different value than LOCK_TOKEN. + * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the other + * case the next token must be read from the input. + */ + if (pushToken == EOF) return(EOF); + else if (pushToken == LOCK_TOKEN) + { + + c = configBuf[configPos]; + + /* + * Get start of next Token. EOF is handled, whitespaces & comments are + * skipped. + */ + do { + if (!c) { + if (fgets(configBuf,CONFIG_BUF_LEN-1,configFile) == NULL) + { + return( pushToken = EOF ); + } + configLineNo++; + configStart = configPos = 0; + } +#ifndef __EMX__ + while (((c=configBuf[configPos++])==' ') || ( c=='\t') || ( c=='\n')); +#else + while (((c=configBuf[configPos++])==' ') || ( c=='\t') || ( c=='\n') + || (c=='\r')); +#endif + if (c == '#') c = '\0'; + } while (!c); + + /* GJA -- handle '-' and ',' + * Be careful: "-hsync" is a keyword. + */ + if ( (c == ',') && !isalpha(configBuf[configPos]) ) { + configStart = configPos; return COMMA; + } else if ( (c == '-') && !isalpha(configBuf[configPos]) ) { + configStart = configPos; return DASH; + } + + configStart = configPos; + /* + * Numbers are returned immediately ... + */ + if (isdigit(c)) + { + int base; + + if (c == '0') + if ((configBuf[configPos] == 'x') || + (configBuf[configPos] == 'X')) + base = 16; + else + base = 8; + else + base = 10; + + configRBuf[0] = c; i = 1; + while (isdigit(c = configBuf[configPos++]) || + (c == '.') || (c == 'x') || + ((base == 16) && (((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F'))))) + configRBuf[i++] = c; + configPos--; /* GJA -- one too far */ + configRBuf[i] = '\0'; + val.num = StrToUL(configRBuf); + val.realnum = atof(configRBuf); + return(NUMBER); + } + + /* + * All Strings START with a \" ... + */ + else if (c == '\"') + { + i = -1; + do { + configRBuf[++i] = (c = configBuf[configPos++]); +#ifndef __EMX__ + } while ((c != '\"') && (c != '\n') && (c != '\0')); +#else + } while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0')); +#endif + configRBuf[i] = '\0'; + val.str = (char *)xalloc(strlen(configRBuf) + 1); + strcpy(val.str, configRBuf); /* private copy ! */ + return(STRING); + } + + /* + * ... and now we MUST have a valid token. The search is + * handled later along with the pushed tokens. + */ + else + { + configRBuf[0] = c; + i = 0; + do { + configRBuf[++i] = (c = configBuf[configPos++]);; +#ifndef __EMX__ + } while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\0')); +#else + } while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') ); +#endif + configRBuf[i] = '\0'; i=0; + } + + } + else + { + + /* + * Here we deal with pushed tokens. Reinitialize pushToken again. If + * the pushed token was NUMBER || STRING return them again ... + */ + int temp = pushToken; + pushToken = LOCK_TOKEN; + + if (temp == COMMA || temp == DASH) return(temp); + if (temp == NUMBER || temp == STRING) return(temp); + } + + /* + * Joop, at last we have to lookup the token ... + */ + if (tab) + { + i = 0; + while (tab[i].token != -1) + if (StrCaseCmp(configRBuf,tab[i].name) == 0) + return(tab[i].token); + else + i++; + } + + return(ERROR_TOKEN); /* Error catcher */ +} + +/* + * xf86GetToken -- + * Lookup a string if it is actually a token in disguise. + */ +static int +getStringToken(tab) + SymTabRec tab[]; +{ + int i; + + for ( i = 0 ; tab[i].token != -1 ; i++ ) { + if ( ! StrCaseCmp(tab[i].name,val.str) ) return tab[i].token; + } + return(ERROR_TOKEN); +} + +/* + * getScreenIndex -- + * Given the screen token, returns the index in xf86Screens, or -1 if + * the screen type is not applicable to this server. + */ +static int +getScreenIndex(token) + int token; +{ + int i; + + for (i = 0; xf86ScreenNames[i] >= 0 && xf86ScreenNames[i] != token; i++) + ; + if (xf86ScreenNames[i] < 0) + return(-1); + else + return(i); +} + +/* + * validateGraphicsToken -- + * If token is a graphics token, check it is in the list of validTokens + * XXXX This needs modifying to work as it did with the old format + */ +static Bool +validateGraphicsToken(validTokens, token) + int *validTokens; + int token; +{ + int i; + + for (i = 0; ScreenTab[i].token >= 0 && ScreenTab[i].token != token; i++) + ; + if (ScreenTab[i].token < 0) + return(FALSE); /* Not a graphics token */ + + for (i = 0; validTokens[i] >= 0 && validTokens[i] != token; i++) + ; + return(validTokens[i] >= 0); +} + +/* + * xf86TokenToString -- + * returns the string corresponding to token + */ +char * +xf86TokenToString(table, token) + SymTabPtr table; + int token; +{ + int i; + + for (i = 0; table[i].token >= 0 && table[i].token != token; i++) + ; + if (table[i].token < 0) + return("unknown"); + else + return(table[i].name); +} + +/* + * xf86StringToToken -- + * returns the string corresponding to token + */ +int +xf86StringToToken(table, string) + SymTabPtr table; + char *string; +{ + int i; + + for (i = 0; table[i].token >= 0 && StrCaseCmp(string, table[i].name); i++) + ; + return(table[i].token); +} + +/* + * xf86ConfigError -- + * Print a READABLE ErrorMessage!!! All information that is + * interesting is printed. Even a pointer to the erroneous place is + * printed. Maybe our e-mail will be less :-) + */ +#ifdef XF86SETUP +int +XF86SetupXF86ConfigError(msg) +#else +void +xf86ConfigError(msg) +#endif + char *msg; +{ + int i,j; + + ErrorF( "\nConfig Error: %s:%d\n\n%s", configPath, configLineNo, configBuf); + for (i = 1, j = 1; i < configStart; i++, j++) + if (configBuf[i-1] != '\t') + ErrorF(" "); + else + do + ErrorF(" "); + while (((j++)%8) != 0); + for (i = configStart; i <= configPos; i++) ErrorF("^"); + ErrorF("\n%s\n", msg); +#ifdef NEED_RETURN_VALUE + return RET_ERROR; +#else + exit(-1); /* simple exit ... */ +#endif +} + +#ifndef XF86SETUP +void +xf86DeleteMode(infoptr, dispmp) +ScrnInfoPtr infoptr; +DisplayModePtr dispmp; +{ + if(infoptr->modes == dispmp) + infoptr->modes = dispmp->next; + + if(dispmp->next == dispmp) + FatalError("No valid modes found.\n"); + + ErrorF("%s %s: Removing mode \"%s\" from list of valid modes.\n", + XCONFIG_PROBED, infoptr->name, dispmp->name); + dispmp->prev->next = dispmp->next; + dispmp->next->prev = dispmp->prev; + + xfree(dispmp->name); + xfree(dispmp); +} +#endif + +/* + * findConfigFile -- + * Locate the XF86Config file. Abort if not found. + */ +#ifndef XF86SETUP +static +#endif +CONFIG_RETURN_TYPE +findConfigFile(filename, fp) + char *filename; + FILE **fp; +{ +#define configFile (*fp) +#define MAXPTRIES 6 + char *home = NULL; + char *xconfig = NULL; + char *xwinhome = NULL; + char *configPaths[MAXPTRIES]; + int pcount = 0, idx; + + /* + * First open if necessary the config file. + * If the -xf86config flag was used, use the name supplied there (root only). + * If $XF86CONFIG is a pathname, use it as the name of the config file (root) + * If $XF86CONFIG is set but doesn't contain a '/', append it to 'XF86Config' + * and search the standard places (root only). + * If $XF86CONFIG is not set, just search the standard places. + */ + while (!configFile) { + + /* + * configPaths[0] is used as a buffer for -xf86config + * and $XF86CONFIG if it contains a path + * configPaths[1...MAXPTRIES-1] is used to store the paths of each of + * the other attempts + */ + for (pcount = idx = 0; idx < MAXPTRIES; idx++) + configPaths[idx] = NULL; + + /* + * First check if the -xf86config option was used. + */ + configPaths[pcount] = (char *)xalloc(PATH_MAX); +#ifndef __EMX__ + if (getuid() == 0 && xf86ConfigFile[0]) +#else + if (xf86ConfigFile[0]) +#endif + { + strcpy(configPaths[pcount], xf86ConfigFile); + if ((configFile = fopen(configPaths[pcount], "r")) != 0) + break; + else + FatalError( + "Cannot read file \"%s\" specified by the -xf86config flag\n", + configPaths[pcount]); + } + /* + * Check if XF86CONFIG is set. + */ +#ifndef __EMX__ + if (getuid() == 0 + && (xconfig = getenv("XF86CONFIG")) != 0 + && index(xconfig, '/')) +#else + /* no root available, and filenames start with drive letter */ + if ((xconfig = getenv("XF86CONFIG")) != 0 + && isalpha(xconfig[0]) + && xconfig[1]==':') +#endif + { + strcpy(configPaths[pcount], xconfig); + if ((configFile = fopen(configPaths[pcount], "r")) != 0) + break; + else + FatalError( + "Cannot read file \"%s\" specified by XF86CONFIG variable\n", + configPaths[pcount]); + } + +#ifndef __EMX__ + /* + * ~/XF86Config ... + */ + if (getuid() == 0 && (home = getenv("HOME"))) { + configPaths[++pcount] = (char *)xalloc(PATH_MAX); + strcpy(configPaths[pcount],home); + strcat(configPaths[pcount],"/XF86Config"); + if (xconfig) strcat(configPaths[pcount],xconfig); + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; + } + + /* + * /etc/XF86Config + */ + configPaths[++pcount] = (char *)xalloc(PATH_MAX); + strcpy(configPaths[pcount], "/etc/XF86Config"); + if (xconfig) strcat(configPaths[pcount],xconfig); + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; + + /* + * $(LIBDIR)/XF86Config. + */ + + configPaths[++pcount] = (char *)xalloc(PATH_MAX); + if (getuid() == 0 && (xwinhome = getenv("XWINHOME")) != NULL) + sprintf(configPaths[pcount], "%s/lib/X11/XF86Config", xwinhome); + else + strcpy(configPaths[pcount], SERVER_CONFIG_FILE); + if (getuid() == 0 && xconfig) strcat(configPaths[pcount],xconfig); + strcat(configPaths[pcount], "."); +#ifdef AMOEBA + { + extern char *XServerHostName; + + strcat(configPaths[pcount], XServerHostName); + } +#else + gethostname(configPaths[pcount]+strlen(configPaths[pcount]), + MAXHOSTNAMELEN); +#endif + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; +#endif /* !__EMX__ */ + + /* + * $(LIBDIR)/XF86Config + */ + configPaths[++pcount] = (char *)xalloc(PATH_MAX); +#ifndef __EMX__ + if (getuid() == 0 && xwinhome) + sprintf(configPaths[pcount], "%s/lib/X11/XF86Config", xwinhome); + else + strcpy(configPaths[pcount], SERVER_CONFIG_FILE); + if (getuid() == 0 && xconfig) strcat(configPaths[pcount],xconfig); +#else + /* we explicitly forbid numerous config files everywhere for OS/2; + * users should consider them lucky to have one in a standard place + * and another one with the -xf86config option + */ + xwinhome = getenv("X11ROOT"); /* get drive letter */ + if (!xwinhome) FatalError("X11ROOT environment variable not set\n"); + strcpy(configPaths[pcount], __XOS2RedirRoot("/XFree86/lib/X11/XConfig")); +#endif + + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; + + ErrorF("\nCould not find config file!\n"); + ErrorF("- Tried:\n"); + for (idx = 1; idx <= pcount; idx++) + if (configPaths[idx] != NULL) + ErrorF(" %s\n", configPaths[idx]); + FatalError("No config file found!\n%s", getuid() == 0 ? "" : + "Note, the X server no longer looks for XF86Config in $HOME"); + } + strcpy(filename, configPaths[pcount]); + if (xf86Verbose) { + ErrorF("XF86Config: %s\n", filename); + ErrorF("%s stands for supplied, %s stands for probed/default values\n", + XCONFIG_GIVEN, XCONFIG_PROBED); + } + for (idx = 0; idx <= pcount; idx++) + if (configPaths[idx] != NULL) + xfree(configPaths[idx]); +#undef configFile +#undef MAXPTRIES +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static DisplayModePtr pNew, pLast; +static Bool graphFound = FALSE; + +/* + * xf86GetNearestClock -- + * Find closest clock to given frequency (in kHz). This assumes the + * number of clocks is greater than zero. + */ +int +xf86GetNearestClock(Screen, Frequency) + ScrnInfoPtr Screen; + int Frequency; +{ + int NearestClock = 0; + int MinimumGap = abs(Frequency - Screen->clock[0]); + int i; + for (i = 1; i < Screen->clocks; i++) + { + int Gap = abs(Frequency - Screen->clock[i]); + if (Gap < MinimumGap) + { + MinimumGap = Gap; + NearestClock = i; + } + } + return NearestClock; +} + +/* + * xf86Config -- + * Fill some internal structure with userdefined setups. Many internal + * Structs are initialized. The drivers are selected and initialized. + * if (! vtopen), XF86Config is read, but devices are not probed. + * if (vtopen), devices are probed (and modes resolved). + * The vtopen argument was added so that XF86Config information could be + * made available before the VT is opened. + */ +CONFIG_RETURN_TYPE +xf86Config (vtopen) + int vtopen; +{ + int token; + int i, j; +#if defined(SYSV) || defined(linux) + int xcpipe[2]; +#endif +#ifdef XINPUT + LocalDevicePtr local; +#endif + + if (!vtopen) + { + + OFLG_ZERO(&GenericXF86ConfigFlag); + configBuf = (char*)xalloc(CONFIG_BUF_LEN); + configRBuf = (char*)xalloc(CONFIG_BUF_LEN); + configPath = (char*)xalloc(PATH_MAX); + + configBuf[0] = '\0'; /* sanity ... */ + + /* + * Read the XF86Config file with the real uid to avoid security problems + * + * For SYSV we fork, and send the data back to the parent through a pipe + */ +#if defined(SYSV) || defined(linux) + if (getuid() != 0) { + if (pipe(xcpipe)) + FatalError("Pipe failed (%s)\n", strerror(errno)); + switch (fork()) { + case -1: + FatalError("Fork failed (%s)\n", strerror(errno)); + break; + case 0: /* child */ + close(xcpipe[0]); + setuid(getuid()); + HANDLE_RETURN(findConfigFile(configPath, &configFile)); + { + unsigned char pbuf[CONFIG_BUF_LEN]; + int nbytes; + + /* Pass the filename back as the first line */ + strcat(configPath, "\n"); + if (write(xcpipe[1], configPath, strlen(configPath)) < 0) + FatalError("Child error writing to pipe (%s)\n", strerror(errno)); + while ((nbytes = fread(pbuf, 1, CONFIG_BUF_LEN, configFile)) > 0) + if (write(xcpipe[1], pbuf, nbytes) < 0) + FatalError("Child error writing to pipe (%s)\n", strerror(errno)); + } + close(xcpipe[1]); + fclose(configFile); + exit(0); + break; + default: /* parent */ + close(xcpipe[1]); + configFile = (FILE *)fdopen(xcpipe[0], "r"); + if (fgets(configPath, PATH_MAX, configFile) == NULL) + FatalError("Error reading config file\n"); + configPath[strlen(configPath) - 1] = '\0'; + } + } + else { + HANDLE_RETURN(findConfigFile(configPath, &configFile)); + } +#else /* ! (SYSV || linux) */ + { +#ifndef __EMX__ /* in OS/2 we don't care about uids */ + int real_uid = getuid(); + + if (real_uid) { +#ifdef MINIX + setuid(getuid()); +#else +#if !defined(SVR4) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) + setruid(0); +#endif + seteuid(real_uid); +#endif /* MINIX */ + } +#endif /* __EMX__ */ + + HANDLE_RETURN(findConfigFile(configPath, &configFile)); +#if defined(MINIX) || defined(__EMX__) + /* no need to restore the uid to root */ +#else + if (real_uid) { + seteuid(0); +#if !defined(SVR4) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) + setruid(real_uid); +#endif + } +#endif /* MINIX */ + } +#endif /* SYSV || linux */ + xf86Info.sharedMonitor = FALSE; + xf86Info.kbdProc = NULL; + xf86Info.notrapSignals = FALSE; + xf86Info.caughtSignal = FALSE; + + /* Allocate mouse device */ +#if defined(XINPUT) && !defined(XF86SETUP) + local = mouse_assoc.device_allocate(); + xf86Info.mouseLocal = (pointer) local; + xf86Info.mouseDev = (MouseDevPtr) local->private; + xf86Info.mouseDev->mseProc = NULL; +#else + xf86Info.mouseDev = (MouseDevPtr) Xcalloc(sizeof(MouseDevRec)); +#endif + + while ((token = xf86GetToken(TopLevelTab)) != EOF) { + switch(token) { + case SECTION: + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("section name string expected"); + if ( StrCaseCmp(val.str, "files") == 0 ) { + HANDLE_RETURN(configFilesSection()); + } else if ( StrCaseCmp(val.str, "serverflags") == 0 ) { + HANDLE_RETURN(configServerFlagsSection()); + } else if ( StrCaseCmp(val.str, "keyboard") == 0 ) { + HANDLE_RETURN(configKeyboardSection()); + } else if ( StrCaseCmp(val.str, "pointer") == 0 ) { + HANDLE_RETURN(configPointerSection(xf86Info.mouseDev, ENDSECTION, NULL)); + } else if ( StrCaseCmp(val.str, "device") == 0 ) { + HANDLE_RETURN(configDeviceSection()); + } else if ( StrCaseCmp(val.str, "monitor") == 0 ) { + HANDLE_RETURN(configMonitorSection()); + } else if ( StrCaseCmp(val.str, "screen") == 0 ) { + HANDLE_RETURN(configScreenSection()); +#ifdef XINPUT + } else if ( StrCaseCmp(val.str, "xinput") == 0 ) { + HANDLE_RETURN(xf86ConfigExtendedInputSection(&val)); +#endif + } else if ( StrCaseCmp(val.str, "module") == 0 ) { + HANDLE_RETURN(configDynamicModuleSection()); + } else { + xf86ConfigError("not a recognized section name"); + } + break; + } + } + + fclose(configFile); + xfree(configBuf); + xfree(configRBuf); + xfree(configPath); + + /* These aren't needed after the XF86Config file has been read */ +#ifndef XF86SETUP + if (monitor_list) + xfree(monitor_list); + if (device_list) + xfree(device_list); +#endif + if (modulePath) + xfree(modulePath); + +#if defined(SYSV) || defined(linux) + if (getuid() != 0) { + /* Wait for the child */ + wait(NULL); + } +#endif + + /* Try XF86Config FontPath first */ + if (!xf86fpFlag) + if (fontPath) { + char *f = xf86ValidateFontPath(fontPath); + if (*f) + defaultFontPath = f; + else + ErrorF( + "Warning: FontPath is completely invalid. Using compiled-in default.\n" + ); + xfree(fontPath); + fontPath = (char *)NULL; + } + else + ErrorF("Warning: No FontPath specified, using compiled-in default.\n"); + else /* Use fontpath specified with '-fp' */ + { + OFLG_CLR (XCONFIG_FONTPATH, &GenericXF86ConfigFlag); + if (fontPath) + { + xfree(fontPath); + fontPath = (char *)NULL; + } + } + if (!fontPath) { + /* xf86ValidateFontPath will write into it's arg, but defaultFontPath + could be static, so we make a copy. */ + char *f = (char *)xalloc(strlen(defaultFontPath) + 1); + f[0] = '\0'; + strcpy (f, defaultFontPath); + defaultFontPath = xf86ValidateFontPath(f); + xfree(f); + } + else + xfree(fontPath); + + /* If defaultFontPath is still empty, exit here */ + + if (! *defaultFontPath) + FatalError("No valid FontPath could be found\n"); + if (xf86Verbose) + ErrorF("%s FontPath set to \"%s\"\n", + OFLG_ISSET(XCONFIG_FONTPATH, &GenericXF86ConfigFlag) ? XCONFIG_GIVEN : + XCONFIG_PROBED, defaultFontPath); + + if (!xf86Info.kbdProc) + FatalError("You must specify a keyboard in XF86Config"); + if (!xf86Info.mouseDev->mseProc) + FatalError("You must specify a mouse in XF86Config"); + + if (!graphFound) + { + Bool needcomma = FALSE; + + ErrorF("\nYou must provide a \"Screen\" section in XF86Config for at\n"); + ErrorF("least one of the following graphics drivers: "); + for (i = 0; i < xf86MaxScreens; i++) + { + if (xf86Screens[i]) + { + ErrorF("%s%s", needcomma ? ", " : "", + xf86TokenToString(DriverTab, xf86ScreenNames[i])); + needcomma = TRUE; + } + } + ErrorF("\n"); + FatalError("No configured graphics devices"); + } + } +#ifndef XF86SETUP + else /* if (vtopen) */ + { + /* + * Probe all configured screens for letting them resolve their modes + */ + xf86ScreensOpen = TRUE; + for ( i=0; i < xf86MaxScreens; i++ ) + if (xf86Screens[i] && xf86Screens[i]->configured && + (xf86Screens[i]->configured = (xf86Screens[i]->Probe)())){ + /* if driver doesn't report error do it here */ + if(xf86DCGetToken(xf86Screens[i]->DCConfig,NULL,DeviceTab) != EOF){ + xf86DCConfigError("Unknown device section keyword"); + FatalError("\n"); + } + if(xf86Screens[i]->DCOptions){ + xf86DCGetOption(xf86Screens[i]->DCOptions,NULL); + FatalError("\n"); + } + xf86InitViewport(xf86Screens[i]); + } + + /* + * Now sort the drivers to match the order of the ScreenNumbers + * requested by the user. (sorry, slow bubble-sort here) + * Note, that after this sorting the first driver that is not configured + * can be used as last-mark for all configured ones. + */ + for ( j = 0; j < xf86MaxScreens-1; j++) + for ( i=0; i < xf86MaxScreens-j-1; i++ ) + if (!xf86Screens[i] || !xf86Screens[i]->configured || + (xf86Screens[i+1] && xf86Screens[i+1]->configured && + (xf86Screens[i+1]->tmpIndex < xf86Screens[i]->tmpIndex))) + { + ScrnInfoPtr temp = xf86Screens[i+1]; + xf86Screens[i+1] = xf86Screens[i]; + xf86Screens[i] = temp; + } + + } +#endif /* XF86SETUP */ + +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static char* prependRoot(char *pathname) +{ +#ifndef __EMX__ + return pathname; +#else + /* XXXX caveat: multiple path components in line */ + return (char*)__XOS2RedirRoot(pathname); +#endif +} + +static CONFIG_RETURN_TYPE +configFilesSection() +{ + int token; + int i, j; + int k, l; + char *str; + + while ((token = xf86GetToken(FilesTab)) != ENDSECTION) { + switch (token) { + case FONTPATH: + OFLG_SET(XCONFIG_FONTPATH,&GenericXF86ConfigFlag); + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Font path component expected"); + j = FALSE; + str = prependRoot(val.str); + if (fontPath == NULL) + { + fontPath = (char *)xalloc(1); + fontPath[0] = '\0'; + i = strlen(str) + 1; + } + else + { + i = strlen(fontPath) + strlen(str) + 1; + if (fontPath[strlen(fontPath)-1] != ',') + { + i++; + j = TRUE; + } + } + fontPath = (char *)xrealloc(fontPath, i); + if (j) + strcat(fontPath, ","); + + strcat(fontPath, str); + xfree(val.str); + break; + + case RGBPATH: + OFLG_SET(XCONFIG_RGBPATH, &GenericXF86ConfigFlag); + if (xf86GetToken(NULL) != STRING) xf86ConfigError("RGB path expected"); + if (!xf86coFlag) + rgbPath = val.str; + break; + + case MODULEPATH: + OFLG_SET(XCONFIG_MODULEPATH, &GenericXF86ConfigFlag); + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Module path expected"); + l = FALSE; + str = prependRoot(val.str); + if (modulePath == NULL) { + modulePath = (char *)xalloc(1); + modulePath[0] = '\0'; + k = strlen(str) + 1; + } + else + { + k = strlen(modulePath) + strlen(str) + 1; + if (modulePath[strlen(modulePath)-1] != ',') + { + k++; + l = TRUE; + } + } + modulePath = (char *)xrealloc(modulePath, k); + if (l) + strcat(modulePath, ","); + + strcat(modulePath, str); + xfree(val.str); + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + default: + xf86ConfigError("File section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configServerFlagsSection() +{ + int token; + + xf86Info.dontZap = FALSE; + xf86Info.dontZoom = FALSE; + + while ((token = xf86GetToken(ServerFlagsTab)) != ENDSECTION) { + switch (token) { + case NOTRAPSIGNALS: + xf86Info.notrapSignals=TRUE; + break; + case DONTZAP: + xf86Info.dontZap = TRUE; + break; + case DONTZOOM: + xf86Info.dontZoom = TRUE; + break; +#ifdef XF86VIDMODE + case DISABLEVIDMODE: + xf86VidModeEnabled = FALSE; + break; + case ALLOWNONLOCAL: + xf86VidModeAllowNonLocal = TRUE; + break; +#endif +#ifdef XF86MISC + case DISABLEMODINDEV: + xf86MiscModInDevEnabled = FALSE; + break; + case MODINDEVALLOWNONLOCAL: + xf86MiscModInDevAllowNonLocal = TRUE; + break; +#endif + case ALLOWMOUSEOPENFAIL: + xf86AllowMouseOpenFail = TRUE; + break; + case PCIPROBE1: + xf86PCIFlags = PCIProbe1; + break; + case PCIPROBE2: + xf86PCIFlags = PCIProbe2; + break; + case PCIFORCECONFIG1: + xf86PCIFlags = PCIForceConfig1; + break; + case PCIFORCECONFIG2: + xf86PCIFlags = PCIForceConfig2; + break; + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + default: + xf86ConfigError("Server flags section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configKeyboardSection() +{ + int token, ntoken; + + /* Initialize defaults */ + xf86Info.serverNumLock = FALSE; + xf86Info.xleds = 0L; + xf86Info.kbdDelay = 500; + xf86Info.kbdRate = 30; + xf86Info.kbdProc = (DeviceProc)0; + xf86Info.vtinit = NULL; + xf86Info.vtSysreq = VT_SYSREQ_DEFAULT; + xf86Info.specialKeyMap = (int *)xalloc((RIGHTCTL - LEFTALT + 1) * + sizeof(int)); + xf86Info.specialKeyMap[LEFTALT - LEFTALT] = KM_META; + xf86Info.specialKeyMap[RIGHTALT - LEFTALT] = KM_META; + xf86Info.specialKeyMap[SCROLLLOCK - LEFTALT] = KM_COMPOSE; + xf86Info.specialKeyMap[RIGHTCTL - LEFTALT] = KM_CONTROL; +#if defined(SVR4) && defined(i386) && !defined(PC98) + xf86Info.panix106 = FALSE; +#endif +#ifdef XKB + xf86Info.xkbkeymap = NULL; + xf86Info.xkbtypes = "default"; +#ifndef PC98 + xf86Info.xkbcompat = "default"; + xf86Info.xkbkeycodes = "xfree86"; + xf86Info.xkbsymbols = "us(pc101)"; + xf86Info.xkbgeometry = "pc"; +#else + xf86Info.xkbcompat = "pc98"; + xf86Info.xkbkeycodes = "xfree98"; + xf86Info.xkbsymbols = "nec/jp(pc98)"; + xf86Info.xkbgeometry = "nec(pc98)"; +#endif + xf86Info.xkbcomponents_specified = False; + xf86Info.xkbrules = "xfree86"; + xf86Info.xkbmodel = NULL; + xf86Info.xkblayout = NULL; + xf86Info.xkbvariant = NULL; + xf86Info.xkboptions = NULL; +#endif + + while ((token = xf86GetToken(KeyboardTab)) != ENDSECTION) { + switch (token) { + case KPROTOCOL: + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Keyboard protocol name expected"); + if ( StrCaseCmp(val.str,"standard") == 0 ) { + xf86Info.kbdProc = xf86KbdProc; +#ifdef AMOEBA + xf86Info.kbdEvents = NULL; +#else + xf86Info.kbdEvents = xf86KbdEvents; +#endif + } else if ( StrCaseCmp(val.str,"xqueue") == 0 ) { +#ifdef XQUEUE + xf86Info.kbdProc = xf86XqueKbdProc; + xf86Info.kbdEvents = xf86XqueEvents; + xf86Info.mouseDev->xqueSema = 0; + if (xf86Verbose) + ErrorF("%s Xqueue selected for keyboard input\n", + XCONFIG_GIVEN); +#endif + } else { + xf86ConfigError("Not a valid keyboard protocol name"); + } + break; + case AUTOREPEAT: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Autorepeat delay expected"); + xf86Info.kbdDelay = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Autorepeat rate expected"); + xf86Info.kbdRate = val.num; + break; + case SERVERNUM: + xf86Info.serverNumLock = TRUE; + break; + + case XLEDS: + while ((token= xf86GetToken(NULL)) == NUMBER) + xf86Info.xleds |= 1L << (val.num-1); + pushToken = token; + break; + case LEFTALT: + case RIGHTALT: + case SCROLLLOCK: + case RIGHTCTL: + ntoken = xf86GetToken(KeyMapTab); + if ((ntoken == EOF) || (ntoken == STRING) || (ntoken == NUMBER)) + xf86ConfigError("KeyMap type token expected"); + else { + switch(ntoken) { + case KM_META: + case KM_COMPOSE: + case KM_MODESHIFT: + case KM_MODELOCK: + case KM_SCROLLLOCK: + case KM_CONTROL: + xf86Info.specialKeyMap[token - LEFTALT] = ntoken; + break; + default: + xf86ConfigError("Illegal KeyMap type"); + break; + } + } + break; + case VTINIT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("VTInit string expected"); + xf86Info.vtinit = val.str; + if (xf86Verbose) + ErrorF("%s VTInit: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case VTSYSREQ: +#ifdef USE_VT_SYSREQ + xf86Info.vtSysreq = TRUE; + if (xf86Verbose && !VT_SYSREQ_DEFAULT) + ErrorF("%s VTSysReq enabled\n", XCONFIG_GIVEN); +#else + xf86ConfigError("VTSysReq not supported on this OS"); +#endif + break; + +#ifdef XKB + case XKBDISABLE: + noXkbExtension = TRUE; + if (xf86Verbose) + ErrorF("%s XKB: disabled\n", XCONFIG_GIVEN); + break; + + case XKBKEYMAP: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBKeymap string expected"); + xf86Info.xkbkeymap = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: keymap: \"%s\" (overrides other XKB settings)\n", + XCONFIG_GIVEN, val.str); + break; + + case XKBCOMPAT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBCompat string expected"); + xf86Info.xkbcompat = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: compat: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBTYPES: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBTypes string expected"); + xf86Info.xkbtypes = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: types: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBKEYCODES: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBKeycodes string expected"); + xf86Info.xkbkeycodes = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: keycodes: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBGEOMETRY: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBGeometry string expected"); + xf86Info.xkbgeometry = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: geometry: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBSYMBOLS: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBSymbols string expected"); + xf86Info.xkbsymbols = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: symbols: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBRULES: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBRules string expected"); + xf86Info.xkbrules = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: rules: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBMODEL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBModel string expected"); + xf86Info.xkbmodel = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: model: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBLAYOUT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBLayout string expected"); + xf86Info.xkblayout = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: layout: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBVARIANT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBVariant string expected"); + xf86Info.xkbvariant = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: variant: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBOPTIONS: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBOptions string expected"); + xf86Info.xkboptions = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: options: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; +#endif +#if defined(SVR4) && defined(i386) && !defined(PC98) + case PANIX106: + xf86Info.panix106 = TRUE; + if (xf86Verbose) + ErrorF("%s PANIX106: enabled\n", XCONFIG_GIVEN); + break; +#endif + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + + default: + xf86ConfigError("Keyboard section keyword expected"); + break; + } + } + if (xf86Info.kbdProc == (DeviceProc)0) + { + xf86ConfigError("No keyboard device given"); + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +CONFIG_RETURN_TYPE +configPointerSection(MouseDevPtr mouse_dev, + int end_tag, + char **devicename) /* used by extended device */ +{ + int token; + int mtoken; + int i; + char *mouseType = "unknown"; + + /* Set defaults */ + mouse_dev->baudRate = 1200; + mouse_dev->oldBaudRate = -1; + mouse_dev->sampleRate = 0; + mouse_dev->resolution = 0; + mouse_dev->buttons = MSE_DFLTBUTTONS; + mouse_dev->emulate3Buttons = FALSE; + mouse_dev->emulate3Timeout = 50; + mouse_dev->chordMiddle = FALSE; + mouse_dev->mouseFlags = 0; + mouse_dev->mseProc = (DeviceProc)0; + mouse_dev->mseDevice = NULL; + mouse_dev->mseType = -1; + mouse_dev->mseModel = 0; + mouse_dev->negativeZ = 0; + mouse_dev->positiveZ = 0; + + while ((token = xf86GetToken(PointerTab)) != end_tag) { + switch (token) { + + case PROTOCOL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Mouse name expected"); +#if defined(USE_OSMOUSE) || defined(OSMOUSE_ONLY) + if ( StrCaseCmp(val.str,"osmouse") == 0 ) { + if (xf86Verbose) + ErrorF("%s OsMouse selected for mouse input\n", XCONFIG_GIVEN); + /* + * allow an option to be passed to the OsMouse routines + */ + if ((i = xf86GetToken(NULL)) != ERROR_TOKEN) + xf86OsMouseOption(i, (pointer) &val); + else + pushToken = i; + mouse_dev->mseProc = xf86OsMouseProc; + mouse_dev->mseEvents = (void(*)(MouseDevPtr))xf86OsMouseEvents; + break; + } +#endif +#ifdef XQUEUE + if ( StrCaseCmp(val.str,"xqueue") == 0 ) { + mouse_dev->mseProc = xf86XqueMseProc; + mouse_dev->mseEvents = (void(*)(MouseDevPtr))xf86XqueEvents; + mouse_dev->xqueSema = 0; + if (xf86Verbose) + ErrorF("%s Xqueue selected for mouse input\n", + XCONFIG_GIVEN); + break; + } +#endif + +#ifndef OSMOUSE_ONLY +#if defined(MACH) || defined(AMOEBA) + mouseType = (char *) xalloc (strlen (val.str) + 1); + strcpy (mouseType, val.str); +#else + mouseType = (char *)strdup(val.str); /* GJA -- should we free this? */ +#endif + mtoken = getStringToken(MouseTab); /* Which mouse? */ +#ifdef AMOEBA + mouse_dev->mseProc = xf86MseProc; + mouse_dev->mseEvents = NULL; +#else + mouse_dev->mseProc = xf86MseProc; + mouse_dev->mseEvents = xf86MseEvents; +#endif + mouse_dev->mseType = mtoken - MICROSOFT; + if (!xf86MouseSupported(mouse_dev->mseType)) + { + xf86ConfigError("Mouse type not supported by this OS"); + } +#else /* OSMOUSE_ONLY */ + xf86ConfigError("Mouse type not supported by this OS"); +#endif /* OSMOUSE_ONLY */ + +#ifdef MACH386 + /* Don't need to specify the device for MACH -- should always be this */ + mouse_dev->mseDevice = "/dev/mouse"; +#endif + break; +#ifndef OSMOUSE_ONLY + case PDEVICE: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Mouse device expected"); + mouse_dev->mseDevice = val.str; + break; + case BAUDRATE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Baudrate expected"); + if (mouse_dev->mseType + MICROSOFT == LOGIMAN) + { + /* + * XXXX This should be extended to other mouse types -- most + * support only 1200. Should also disallow baudrate for bus mice + */ + /* Moan if illegal baud rate! [CHRIS-211092] */ + if ((val.num != 1200) && (val.num != 9600)) + xf86ConfigError("Only 1200 or 9600 Baud are supported by MouseMan"); + } + else if (val.num%1200 != 0 || val.num < 1200 || val.num > 9600) + xf86ConfigError("Baud rate must be one of 1200, 2400, 4800, or 9600"); + mouse_dev->baudRate = val.num; + break; + + case SAMPLERATE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Sample rate expected"); +#if 0 + if (mouse_dev->mseType + MICROSOFT == LOGIMAN) + { + /* XXXX Most mice don't allow this */ + /* Moan about illegal sample rate! [CHRIS-211092] */ + xf86ConfigError("Selection of sample rate is not supported by MouseMan"); + } +#endif + mouse_dev->sampleRate = val.num; + break; + + case PRESOLUTION: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Resolution expected"); + if (val.num <= 0) + xf86ConfigError("Resolution must be a positive value"); + mouse_dev->resolution = val.num; + break; +#endif /* OSMOUSE_ONLY */ + case EMULATE3: + if (mouse_dev->chordMiddle) + xf86ConfigError("Can't use Emulate3Buttons with ChordMiddle"); + mouse_dev->emulate3Buttons = TRUE; + break; + + case EM3TIMEOUT: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("3 button emulation timeout expected"); + mouse_dev->emulate3Timeout = val.num; + break; + +#ifndef OSMOUSE_ONLY + case CHORDMIDDLE: + if (mouse_dev->mseType + MICROSOFT == MICROSOFT || + mouse_dev->mseType + MICROSOFT == LOGIMAN) + { + if (mouse_dev->emulate3Buttons) + xf86ConfigError("Can't use ChordMiddle with Emulate3Buttons"); + mouse_dev->chordMiddle = TRUE; + } + else + xf86ConfigError("ChordMiddle is only supported for Microsoft and MouseMan"); + break; + + case CLEARDTR: +#ifdef CLEARDTR_SUPPORT + if (mouse_dev->mseType + MICROSOFT == MOUSESYS) + mouse_dev->mouseFlags |= MF_CLEAR_DTR; + else + xf86ConfigError("ClearDTR only supported for MouseSystems mouse"); +#else + xf86ConfigError("ClearDTR not supported on this OS"); +#endif + break; + case CLEARRTS: +#ifdef CLEARDTR_SUPPORT + if (mouse_dev->mseType + MICROSOFT == MOUSESYS) + mouse_dev->mouseFlags |= MF_CLEAR_RTS; + else + xf86ConfigError("ClearRTS only supported for MouseSystems mouse"); +#else + xf86ConfigError("ClearRTS not supported on this OS"); +#endif + break; +#endif /* OSMOUSE_ONLY */ + + case DEVICE_NAME: + if (!devicename) /* not called for an extended device */ + xf86ConfigError("Pointer section keyword expected"); + + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Option string expected"); + *devicename = strdup(val.str); + break; + +#ifndef XF86SETUP +#ifdef XINPUT + case ALWAYSCORE: + xf86AlwaysCore(mouse_dev->local, TRUE); + break; +#endif +#endif + + case ZAXISMAPPING: + switch (xf86GetToken(ZMapTab)) { + case NUMBER: + if (val.num <= 0 || val.num > MSE_MAXBUTTONS) + xf86ConfigError("Button number (1..12) expected"); + mouse_dev->negativeZ = 1 << (val.num - 1); + if (xf86GetToken(NULL) != NUMBER || + val.num <= 0 || val.num > MSE_MAXBUTTONS) + xf86ConfigError("Button number (1..12) expected"); + mouse_dev->positiveZ = 1 << (val.num - 1); + break; + case XAXIS: + mouse_dev->negativeZ = mouse_dev->positiveZ = MSE_MAPTOX; + break; + case YAXIS: + mouse_dev->negativeZ = mouse_dev->positiveZ = MSE_MAPTOY; + break; + default: + xf86ConfigError("Button number (1..12), X or Y expected"); + } + break; + + case PBUTTONS: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Number of buttons (1..12) expected"); + if (val.num <= 0 || val.num > MSE_MAXBUTTONS) + xf86ConfigError("Number of buttons must be a positive value (1..12)"); + mouse_dev->buttons = val.num; + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + + default: + xf86ConfigError("Pointer section keyword expected"); + break; + } + + } + /* Print log and make sanity checks */ + + if (mouse_dev->mseProc == (DeviceProc)0) + { + xf86ConfigError("No mouse protocol given"); + } + + /* + * if mseProc is set and mseType isn't, then using Xqueue or OSmouse. + * Otherwise, a mouse device is required. + */ + if (mouse_dev->mseType >= 0 && !mouse_dev->mseDevice) + { + xf86ConfigError("No mouse device given"); + } + + switch (mouse_dev->negativeZ) { + case 0: /* none */ + case MSE_MAPTOX: + case MSE_MAPTOY: + break; + default: /* buttons */ + for (i = 0; mouse_dev->negativeZ != (1 << i); ++i) + ; + if (i + 1 > mouse_dev->buttons) + mouse_dev->buttons = i + 1; + for (i = 0; mouse_dev->positiveZ != (1 << i); ++i) + ; + if (i + 1 > mouse_dev->buttons) + mouse_dev->buttons = i + 1; + break; + } + + if (xf86Verbose && mouse_dev->mseType >= 0) + { + Bool formatFlag = FALSE; + ErrorF("%s Mouse: type: %s, device: %s", + XCONFIG_GIVEN, mouseType, mouse_dev->mseDevice); + if (mouse_dev->mseType != P_BM + && mouse_dev->mseType != P_PS2 + && mouse_dev->mseType != P_IMPS2 + && mouse_dev->mseType != P_THINKINGPS2 + && mouse_dev->mseType != P_MMANPLUSPS2 + && mouse_dev->mseType != P_GLIDEPOINTPS2 + && mouse_dev->mseType != P_NETPS2 + && mouse_dev->mseType != P_NETSCROLLPS2 + && mouse_dev->mseType != P_SYSMOUSE) + { + formatFlag = TRUE; + ErrorF(", baudrate: %d", mouse_dev->baudRate); + } + if (mouse_dev->sampleRate) + { + ErrorF(formatFlag ? "\n%s Mouse: samplerate: %d" : "%ssamplerate: %d", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->sampleRate); + formatFlag = !formatFlag; + } + if (mouse_dev->resolution) + { + ErrorF(formatFlag ? "\n%s Mouse: resolution: %d" : "%sresolution: %d", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->resolution); + formatFlag = !formatFlag; + } + ErrorF(formatFlag ? "\n%s Mouse: buttons: %d" : "%sbuttons: %d", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->buttons); + formatFlag = !formatFlag; + if (mouse_dev->emulate3Buttons) + { + ErrorF(formatFlag ? "\n%s Mouse: 3 button emulation (timeout: %dms)" : + "%s3 button emulation (timeout: %dms)", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->emulate3Timeout); + formatFlag = !formatFlag; + } + if (mouse_dev->chordMiddle) + ErrorF(formatFlag ? "\n%s Mouse: Chorded middle button" : + "%sChorded middle button", + formatFlag ? XCONFIG_GIVEN : ", "); + ErrorF("\n"); + + switch (mouse_dev->negativeZ) { + case 0: /* none */ + break; + case MSE_MAPTOX: + ErrorF("%s Mouse: zaxismapping: X\n", XCONFIG_GIVEN); + break; + case MSE_MAPTOY: + ErrorF("%s Mouse: zaxismapping: Y\n", XCONFIG_GIVEN); + break; + default: /* buttons */ + for (i = 0; mouse_dev->negativeZ != (1 << i); ++i) + ; + ErrorF("%s Mouse: zaxismapping: (-)%d", XCONFIG_GIVEN, i + 1); + for (i = 0; mouse_dev->positiveZ != (1 << i); ++i) + ; + ErrorF(" (+)%d\n", i + 1); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configDeviceSection() +{ + int token; + int i; + GDevPtr devp; + + /* Allocate one more device */ + if ( device_list == NULL ) { + device_list = (GDevPtr) xalloc(sizeof(GDevRec)); + } else { + device_list = (GDevPtr) xrealloc(device_list, + (n_devices+1) * sizeof(GDevRec)); + } + devp = &(device_list[n_devices]); /* Point to the last device */ + n_devices++; + + /* Pre-init the newly created device */ + devp->identifier = NULL; + devp->board = NULL; + devp->vendor = NULL; + devp->chipset = NULL; + devp->ramdac = NULL; + for (i=0; idacSpeeds[i] = 0; + OFLG_ZERO(&(devp->options)); + OFLG_ZERO(&(devp->xconfigFlag)); + devp->videoRam = 0; + devp->speedup = SPEEDUP_DEFAULT; + OFLG_ZERO(&(devp->clockOptions)); + devp->clocks = 0; + devp->clockprog = NULL; + devp->textClockValue = -1; + /* GJA -- We initialize the following fields to known values. + * If later on we find they contain different values, + * they might be interesting to print. + */ + devp->IObase = 0; + devp->DACbase = 0; + devp->COPbase = 0; + devp->POSbase = 0; + devp->instance = 0; + devp->BIOSbase = 0; + devp->VGAbase = 0; + devp->MemBase = 0; + devp->s3Madjust = 0; + devp->s3Nadjust = 0; + devp->s3MClk = 0; + devp->chipID = 0; + devp->chipRev = 0; + devp->s3RefClk = 0; + devp->s3BlankDelay = -1; + devp->DCConfig = NULL; + devp->DCOptions = NULL; + devp->MemClk = 0; + devp->LCDClk = 0; + + while ((token = xf86GetToken(DeviceTab)) != ENDSECTION) { + devp->DCConfig = xf86DCSaveLine(devp->DCConfig, token); + switch (token) { + + case IDENTIFIER: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("identifier name expected"); + devp->identifier = val.str; + break; + + case VENDOR: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("vendor name expected"); + devp->vendor = val.str; + break; + + case BOARD: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("board name expected"); + devp->board = val.str; + break; + + case CHIPSET: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Chipset string expected"); + devp->chipset = val.str; + OFLG_SET(XCONFIG_CHIPSET,&(devp->xconfigFlag)); + break; + + case RAMDAC: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("RAMDAC string expected"); + devp->ramdac = val.str; + OFLG_SET(XCONFIG_RAMDAC,&(devp->xconfigFlag)); + break; + + case DACSPEED: + for (i=0; idacSpeeds[i] = 0; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("DAC speed(s) expected"); + else { + devp->dacSpeeds[0] = (int)(val.realnum * 1000.0 + 0.5); + for(i=1; idacSpeeds[i] = (int)(val.realnum * 1000.0 + 0.5); + else { + pushToken = token; + break; + } + } + } + OFLG_SET(XCONFIG_DACSPEED,&(devp->xconfigFlag)); + break; + + case CLOCKCHIP: + /* Only allow one Clock string */ + if (OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(devp->clockOptions))) + { + xf86ConfigError("Only one Clock chip may be specified."); + break; + } + if (devp->clocks == 0) + { + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); + i = 0; + while (xf86_ClockOptionTab[i].token != -1) + { + if (StrCaseCmp(val.str, xf86_ClockOptionTab[i].name) == 0) + { + OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &(devp->clockOptions)); + OFLG_SET(xf86_ClockOptionTab[i].token, + &(devp->clockOptions)); + break; + } + i++; + } + if (xf86_ClockOptionTab[i].token == -1) { + xf86ConfigError("Unknown clock chip"); + break; + } + } + else + { + xf86ConfigError("Clocks previously specified by value"); + } + break; + + case CLOCKS: + OFLG_SET(XCONFIG_CLOCKS,&(devp->xconfigFlag)); + if ((token = xf86GetToken(NULL)) == STRING) + { + xf86ConfigError("Use ClockChip to specify a programmable clock"); + break; + } + if (OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(devp->clockOptions))) + { + xf86ConfigError("Clock previously specified as programmable"); + break; + } + for (i = devp->clocks; token == NUMBER && i < MAXCLOCKS; i++) { + devp->clock[i] = (int)(val.realnum * 1000.0 + 0.5); + token = xf86GetToken(NULL); + } + + devp->clocks = i; + pushToken = token; + break; + + case OPTION: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); + i = 0; + while (xf86_OptionTab[i].token != -1) + { + if (StrCaseCmp(val.str, xf86_OptionTab[i].name) == 0) + { + OFLG_SET(xf86_OptionTab[i].token, &(devp->options)); + break; + } + i++; + } + if (xf86_OptionTab[i].token == -1) + /*xf86ConfigError("Unknown option string");*/ + devp->DCOptions = xf86DCOption(devp->DCOptions,val); + break; + + case VIDEORAM: + OFLG_SET(XCONFIG_VIDEORAM,&(devp->xconfigFlag)); + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Video RAM size expected"); + devp->videoRam = val.num; + break; + + case SPEEDUP: + OFLG_SET(XCONFIG_SPEEDUP,&(devp->xconfigFlag)); + if ((token = xf86GetToken(NULL)) == STRING) + if (!strcmp(val.str,"all")) + devp->speedup = SPEEDUP_ALL; + else + if (!strcmp(val.str,"best")) + devp->speedup = SPEEDUP_BEST; + else + if (!strcmp(val.str,"none")) + devp->speedup = 0; + else + xf86ConfigError("Unrecognised SpeedUp option"); + else + { + pushToken = token; + if ((token = xf86GetToken(NULL)) == NUMBER) + devp->speedup = val.num; + else + { + pushToken = token; + devp->speedup = SPEEDUP_ALL; + } + } + break; + + case NOSPEEDUP: + OFLG_SET(XCONFIG_SPEEDUP,&(devp->xconfigFlag)); + devp->speedup = 0; + break; + + case CLOCKPROG: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("ClockProg string expected"); + if (val.str[0] != '/') + FatalError("Full pathname must be given for ClockProg \"%s\"\n", + val.str); + if (access(val.str, X_OK) < 0) + { + if (access(val.str, F_OK) < 0) + FatalError("ClockProg \"%s\" does not exist\n", val.str); + else + FatalError("ClockProg \"%s\" is not executable\n", val.str); + } + { + struct stat stat_buf; + stat(val.str, &stat_buf); + if (!CHECK_TYPE(stat_buf.st_mode, S_IFREG)) + FatalError("ClockProg \"%s\" is not a regular file\n", val.str); + } + devp->clockprog = val.str; + if (xf86GetToken(NULL) == NUMBER) + { + devp->textClockValue = (int)(val.realnum * 1000.0 + 0.5); + } + else + { + pushToken = token; + } + break; + + case BIOSBASE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("BIOS base address expected"); + devp->BIOSbase = val.num; + OFLG_SET(XCONFIG_BIOSBASE, &(devp->xconfigFlag)); + break; + + case MEMBASE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Memory base address expected"); + devp->MemBase = val.num; + OFLG_SET(XCONFIG_MEMBASE, &(devp->xconfigFlag)); + break; + + case IOBASE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Direct access register I/O base address expected"); + devp->IObase = val.num; + OFLG_SET(XCONFIG_IOBASE, &(devp->xconfigFlag)); + break; + + case DACBASE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("DAC base I/O address expected"); + devp->DACbase = val.num; + OFLG_SET(XCONFIG_DACBASE, &(devp->xconfigFlag)); + break; + + case COPBASE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Coprocessor base memory address expected"); + devp->COPbase = val.num; + OFLG_SET(XCONFIG_COPBASE, &(devp->xconfigFlag)); + break; + + case POSBASE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("POS base address expected"); + devp->POSbase = val.num; + OFLG_SET(XCONFIG_POSBASE, &(devp->xconfigFlag)); + break; + + case INSTANCE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Video adapter instance number expected"); + devp->instance = val.num; + OFLG_SET(XCONFIG_INSTANCE, &(devp->xconfigFlag)); + break; + + case S3MNADJUST: + if ((token = xf86GetToken(NULL)) == DASH) { /* negative number */ + token = xf86GetToken(NULL); + val.num = -val.num; + } + if (token != NUMBER || val.num<-31 || val.num>31) + xf86ConfigError("M adjust (max. 31) expected"); + devp->s3Madjust = val.num; + + if ((token = xf86GetToken(NULL)) == DASH) { /* negative number */ + token = xf86GetToken(NULL); + val.num = -val.num; + } + if (token == NUMBER) { + if (val.num<-255 || val.num>255) + xf86ConfigError("N adjust (max. 255) expected"); + else + devp->s3Nadjust = val.num; + } + else pushToken = token; + break; + + case S3MCLK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("MCLK value in MHz expected"); + devp->s3MClk = (int)(val.realnum * 1000.0 + 0.5); + break; + + case MEMCLOCK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Memory Clock value in MHz expected"); + devp->MemClk = (int)(val.realnum * 1000.0 + 0.5); + OFLG_SET(XCONFIG_MEMCLOCK,&(devp->xconfigFlag)); + break; + + case LCDCLOCK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("LCD Clock value in MHz expected"); + devp->LCDClk = (int)(val.realnum * 1000.0 + 0.5); + OFLG_SET(XCONFIG_LCDCLOCK,&(devp->xconfigFlag)); + break; + + case CHIPID: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("ChipID expected"); + devp->chipID = val.num; + break; + + case CHIPREV: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("ChipRev expected"); + devp->chipRev = val.num; + break; + + case VGABASEADDR: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("VGA aperature base address expected"); + devp->VGAbase = val.num; + OFLG_SET(XCONFIG_VGABASE, &(devp->xconfigFlag)); + break; + + case S3REFCLK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("RefCLK value in MHz expected"); + devp->s3RefClk = (int)(val.realnum * 1000.0 + 0.5); + break; + + case S3BLANKDELAY: + if (xf86GetToken(NULL) != NUMBER || val.num>7) + xf86ConfigError("number(s) 0..7 expected"); + devp->s3BlankDelay = val.num; + if ((token=xf86GetToken(NULL)) == NUMBER) { + if (val.num>7) xf86ConfigError("number2 0..7 expected"); + devp->s3BlankDelay |= val.num<<4; + } + else pushToken = token; + break; + + case TEXTCLOCKFRQ: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Text clock expected"); + devp->textClockValue = (int)(val.realnum * 1000.0 + 0.5); + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + default: + if(DCerr) + xf86ConfigError("Device section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configMonitorSection() +{ + int token; + int i; + MonPtr monp; + float multiplier; + + /* Allocate one more monitor */ + if ( monitor_list == NULL ) { + monitor_list = (MonPtr) xalloc(sizeof(MonRec)); + } else { + monitor_list = (MonPtr) xrealloc(monitor_list, + (n_monitors+1) * sizeof(MonRec)); + } + monp = &(monitor_list[n_monitors]); /* Point to the new monitor */ + monp->Modes = 0; + monp->Last = 0; + monp->n_hsync = 0; + monp->n_vrefresh = 0; + n_monitors++; + + while ((token = xf86GetToken(MonitorTab)) != ENDSECTION) { + switch (token) { + case IDENTIFIER: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("identifier name expected"); + monp->id = val.str; + break; + case VENDOR: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("vendor name expected"); + monp->vendor = val.str; + break; + case MODEL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("model name expected"); + monp->model = val.str; + break; + case MODE: + readVerboseMode(monp); + break; + case MODELINE: + token = xf86GetToken(NULL); + pNew = (DisplayModePtr)xalloc(sizeof(DisplayModeRec)); + + if (monp->Last) + monp->Last->next = pNew; + else + monp->Modes = pNew; + + if (token == STRING) + { + pNew->name = val.str; + if ((token = xf86GetToken(NULL)) != NUMBER) + FatalError("Dotclock expected"); + } + else if (monp->Last) + { +#if defined(MACH) || defined(AMOEBA) + pNew->name = (char *) xalloc (strlen (monp->Last->name) + 1); + strcpy (pNew->name, monp->Last->name); +#else + pNew->name = (char *)strdup(monp->Last->name); +#endif + } + else + xf86ConfigError("Mode name expected"); + + pNew->next = NULL; + pNew->prev = NULL; + pNew->Flags = 0; + pNew->Clock = (int)(val.realnum * 1000.0 + 0.5); + pNew->CrtcHAdjusted = FALSE; + pNew->CrtcVAdjusted = FALSE; + pNew->CrtcHSkew = pNew->HSkew = 0; + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHDisplay = pNew->HDisplay = val.num; + else xf86ConfigError("Horizontal display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncStart = pNew->HSyncStart = val.num; + else xf86ConfigError("Horizontal sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncEnd = pNew->HSyncEnd = val.num; + else xf86ConfigError("Horizontal sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHTotal = pNew->HTotal = val.num; + else xf86ConfigError("Horizontal total expected"); + + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVDisplay = pNew->VDisplay = val.num; + else xf86ConfigError("Vertical display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncStart = pNew->VSyncStart = val.num; + else xf86ConfigError("Vertical sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncEnd = pNew->VSyncEnd = val.num; + else xf86ConfigError("Vertical sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVTotal = pNew->VTotal = val.num; + else xf86ConfigError("Vertical total expected"); + + token = xf86GetToken(TimingTab); + while ( (token == TT_INTERLACE) || (token == TT_PHSYNC) || + (token == TT_NHSYNC) || (token == TT_PVSYNC) || + (token == TT_NVSYNC) || (token == TT_CSYNC) || + (token == TT_PCSYNC) || (token == TT_NCSYNC) || + (token == TT_DBLSCAN) || (token == TT_HSKEW) ) + { + switch(token) { + + case TT_INTERLACE: pNew->Flags |= V_INTERLACE; break; + case TT_PHSYNC: pNew->Flags |= V_PHSYNC; break; + case TT_NHSYNC: pNew->Flags |= V_NHSYNC; break; + case TT_PVSYNC: pNew->Flags |= V_PVSYNC; break; + case TT_NVSYNC: pNew->Flags |= V_NVSYNC; break; + case TT_CSYNC: pNew->Flags |= V_CSYNC; break; + case TT_PCSYNC: pNew->Flags |= V_PCSYNC; break; + case TT_NCSYNC: pNew->Flags |= V_NCSYNC; break; + case TT_DBLSCAN: pNew->Flags |= V_DBLSCAN; break; + case TT_HSKEW: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Horizontal skew expected"); + pNew->CrtcHSkew = pNew->HSkew = val.num; + pNew->Flags |= V_HSKEW; + break; + default: + xf86ConfigError("bug found in config reader"); break; + } + token = xf86GetToken(TimingTab); + } + pushToken = token; + monp->Last = pNew; /* GJA */ + break; + case BANDWIDTH: + /* This should be completely removed at some point */ + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Bandwidth number expected"); +#if 0 + monp->bandwidth = val.realnum; + /* Handle optional scaler */ + token = xf86GetToken(UnitTab); + switch ( token ) { + case HRZ: multiplier = 1.0e-6; break; + case KHZ: multiplier = 1.0e-3; break; + case MHZ: multiplier = 1.0; break; + default: multiplier = 1.0; pushToken = token; + } + monp->bandwidth *= multiplier; +#endif + break; + case HORIZSYNC: + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Horizontal sync value expected"); + monp->hsync[monp->n_hsync].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for horizontal sync value expected"); + monp->hsync[monp->n_hsync].hi = val.realnum; + } else { + pushToken = token; + monp->hsync[monp->n_hsync].hi = monp->hsync[monp->n_hsync].lo; + } + monp->n_hsync++; + while ( (token = xf86GetToken(NULL)) == COMMA ) { + if ( monp->n_hsync == MAX_HSYNC ) + xf86ConfigError("Sorry. Too many horizontal sync intervals."); + + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Horizontal sync value expected"); + monp->hsync[monp->n_hsync].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for horizontal sync value expected"); + monp->hsync[monp->n_hsync].hi = val.realnum; + } else { + pushToken = token; + monp->hsync[monp->n_hsync].hi = monp->hsync[monp->n_hsync].lo; + } + monp->n_hsync++; + } + pushToken = token; + /* Handle optional scaler */ + token = xf86GetToken(UnitTab); + switch ( token ) { + case HRZ: multiplier = 1.0e-3; break; + case KHZ: multiplier = 1.0; break; + case MHZ: multiplier = 1.0e3; break; + default: multiplier = 1.0; pushToken = token; + } + for ( i = 0 ; i < monp->n_hsync ; i++ ) { + monp->hsync[i].hi *= multiplier; + monp->hsync[i].lo *= multiplier; + } + break; + case VERTREFRESH: + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].hi = val.realnum; + } else { + monp->vrefresh[monp->n_vrefresh].hi = + monp->vrefresh[monp->n_vrefresh].lo; + pushToken = token; + } + monp->n_vrefresh++; + while ( (token = xf86GetToken(NULL)) == COMMA ) { + if ( monp->n_vrefresh == MAX_HSYNC ) + xf86ConfigError("Sorry. Too many vertical refresh intervals."); + + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].hi = val.realnum; + } else { + monp->vrefresh[monp->n_vrefresh].hi = + monp->vrefresh[monp->n_vrefresh].lo; + pushToken = token; + } + monp->n_vrefresh++; + } + pushToken = token; + /* Handle optional scaler */ + token = xf86GetToken(UnitTab); + switch ( token ) { + case HRZ: multiplier = 1.0; break; + case KHZ: multiplier = 1.0e3; break; + case MHZ: multiplier = 1.0e6; break; + default: multiplier = 1.0; pushToken = token; + } + for ( i = 0 ; i < monp->n_vrefresh ; i++ ) { + monp->vrefresh[i].hi *= multiplier; + monp->vrefresh[i].lo *= multiplier; + } + break; + case GAMMA: { + char *msg = "gamma correction value(s) expected\n either one value or three r/g/b values with 0.1 <= gamma <= 10"; + if ((token = xf86GetToken(NULL)) != NUMBER || val.realnum<0.1 || val.realnum>10) + xf86ConfigError(msg); + else { + xf86rGamma = xf86gGamma = xf86bGamma = 1.0 / val.realnum; + if ((token = xf86GetToken(NULL)) == NUMBER) { + if (val.realnum<0.1 || val.realnum>10) xf86ConfigError(msg); + else { + xf86gGamma = 1.0 / val.realnum; + if ((token = xf86GetToken(NULL)) != NUMBER || val.realnum<0.1 || val.realnum>10) + xf86ConfigError(msg); + else { + xf86bGamma = 1.0 / val.realnum; + } + } + } + else pushToken = token; + } + break; + } + case EOF: + FatalError("Unexpected EOF. Missing EndSection?"); + break; /* :-) */ + + default: + xf86ConfigError("Monitor section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configDynamicModuleSection() +{ + int token; + + while ((token = xf86GetToken(ModuleTab)) != ENDSECTION) { + switch (token) { + case LOAD: + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Dynamic module expected"); + else { +#ifdef DYNAMIC_MODULE + if (!modulePath) { + static Bool firstTime = TRUE; + + modulePath = (char*)Xcalloc(strlen(DEFAULT_MODULE_PATH)+1); + strcpy(modulePath, DEFAULT_MODULE_PATH); + + if (xf86Verbose && firstTime) { + ErrorF("%s no ModulePath specified using default: %s\n", + XCONFIG_PROBED, DEFAULT_MODULE_PATH); + firstTime = FALSE; + } + } + xf86LoadModule(val.str, modulePath); +#else + ErrorF("Dynamic modules not supported. \"%s\" not loaded\n", + val.str); +#endif + } + break; + + case EOF: + FatalError("Unexpected EOF. Missing EndSection?"); + break; /* :-) */ + + default: + xf86ConfigError("Module section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +readVerboseMode(monp) +MonPtr monp; +{ + int token, token2; + int had_dotclock = 0, had_htimings = 0, had_vtimings = 0; + + pNew = (DisplayModePtr)xalloc(sizeof(DisplayModeRec)); + pNew->next = NULL; + pNew->prev = NULL; + pNew->Flags = 0; + pNew->HDisplay = pNew->VDisplay = 0; /* Uninitialized */ + pNew->CrtcHAdjusted = pNew->CrtcVAdjusted = FALSE; + pNew->CrtcHSkew = pNew->HSkew = 0; + + if (monp->Last) + monp->Last->next = pNew; + else + monp->Modes = pNew; + monp->Last = pNew; + + if ( xf86GetToken(NULL) != STRING ) { + FatalError("Mode name expected"); + } + pNew->name = val.str; + while ((token = xf86GetToken(ModeTab)) != ENDMODE) { + switch (token) { + case DOTCLOCK: + if ((token = xf86GetToken(NULL)) != NUMBER) { + FatalError("Dotclock expected"); + } + pNew->Clock = (int)(val.realnum * 1000.0 + 0.5); + had_dotclock = 1; + break; + case HTIMINGS: + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHDisplay = pNew->HDisplay = val.num; + else xf86ConfigError("Horizontal display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncStart = pNew->HSyncStart = val.num; + else xf86ConfigError("Horizontal sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncEnd = pNew->HSyncEnd = val.num; + else xf86ConfigError("Horizontal sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHTotal = pNew->HTotal = val.num; + else xf86ConfigError("Horizontal total expected"); + had_htimings = 1; + break; + case VTIMINGS: + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVDisplay = pNew->VDisplay = val.num; + else xf86ConfigError("Vertical display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncStart = pNew->VSyncStart = val.num; + else xf86ConfigError("Vertical sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncEnd = pNew->VSyncEnd = val.num; + else xf86ConfigError("Vertical sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVTotal = pNew->VTotal = val.num; + else xf86ConfigError("Vertical total expected"); + had_vtimings = 1; + break; + case FLAGS: + token = xf86GetToken(NULL); + if (token != STRING) + xf86ConfigError("Flag string expected. Note: flags must be in \"\""); + while ( token == STRING ) { + token2 = getStringToken(TimingTab); + switch(token2) { + case TT_INTERLACE: pNew->Flags |= V_INTERLACE; break; + case TT_PHSYNC: pNew->Flags |= V_PHSYNC; break; + case TT_NHSYNC: pNew->Flags |= V_NHSYNC; break; + case TT_PVSYNC: pNew->Flags |= V_PVSYNC; break; + case TT_NVSYNC: pNew->Flags |= V_NVSYNC; break; + case TT_CSYNC: pNew->Flags |= V_CSYNC; break; + case TT_PCSYNC: pNew->Flags |= V_PCSYNC; break; + case TT_NCSYNC: pNew->Flags |= V_NCSYNC; break; + case TT_DBLSCAN: pNew->Flags |= V_DBLSCAN; break; + default: + xf86ConfigError("Unknown flag string"); break; + } + token = xf86GetToken(NULL); + } + pushToken = token; + break; + case HSKEW: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Horizontal skew expected"); + pNew->Flags |= V_HSKEW; + pNew->CrtcHSkew = pNew->HSkew = val.num; + break; + } + } + if ( !had_dotclock ) xf86ConfigError("the dotclock is missing"); + if ( !had_htimings ) xf86ConfigError("the horizontal timings are missing"); + if ( !had_vtimings ) xf86ConfigError("the vertical timings are missing"); +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static Bool dummy; + +#ifdef XF86SETUP +int xf86setup_scrn_ndisps[8]; +DispPtr xf86setup_scrn_displays[8]; +#endif + +static CONFIG_RETURN_TYPE +configScreenSection() +{ + int i, j; + int driverno; + int had_monitor = 0, had_device = 0; + int dispIndex = 0; + int numDisps = 0; + DispPtr dispList = NULL; + DispPtr dispp; + + int token; + ScrnInfoPtr screen = NULL; + int textClockValue = -1; + + token = xf86GetToken(ScreenTab); + if ( token != DRIVER ) + xf86ConfigError("The screen section must begin with the 'driver' line"); + + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Driver name expected"); + driverno = getStringToken(DriverTab); + switch ( driverno ) { + case SVGA: + case VGA2: + case MONO: + case VGA16: + case ACCEL: + case FBDEV: + break; + default: + xf86ConfigError("Not a recognized driver name"); + } + scr_index = getScreenIndex(driverno); + + dummy = scr_index < 0 || !xf86Screens[scr_index]; + if (dummy) + screen = (ScrnInfoPtr)xalloc(sizeof(ScrnInfoRec)); + else + { + screen = xf86Screens[scr_index]; + screen->configured = TRUE; + screen->tmpIndex = screenno++; + screen->scrnIndex = scr_index; /* scrnIndex must not be changed */ + screen->frameX0 = -1; + screen->frameY0 = -1; + screen->virtualX = -1; + screen->virtualY = -1; + screen->defaultVisual = -1; + screen->modes = NULL; + screen->width = 240; + screen->height = 180; + screen->bankedMono = FALSE; + screen->textclock = -1; + screen->blackColour.red = 0; + screen->blackColour.green = 0; + screen->blackColour.blue = 0; + screen->whiteColour.red = 0x3F; + screen->whiteColour.green = 0x3F; + screen->whiteColour.blue = 0x3F; + } + screen->clocks = 0; + + while ((token = xf86GetToken(ScreenTab)) != ENDSECTION) { + switch (token) { + + case DEFBPP: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Default color depth expected"); + screen->depth = val.num; + break; + + case SCREENNO: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Screen number expected"); + screen->tmpIndex = val.num; + break; + + case SUBSECTION: + if ((xf86GetToken(NULL) != STRING) || (StrCaseCmp(val.str, "display") != 0)) { + xf86ConfigError("You must say \"Display\" here"); + } + if (dispList == NULL) { + dispList = (DispPtr)xalloc(sizeof(DispRec)); + } else { + dispList = (DispPtr)xrealloc(dispList, + (numDisps + 1) * sizeof(DispRec)); + } + dispp = dispList + numDisps; + numDisps++; + dispp->depth = -1; + dispp->weight.red = dispp->weight.green = dispp->weight.blue = 0; + dispp->frameX0 = -1; + dispp->frameY0 = -1; + dispp->virtualX = -1; + dispp->virtualY = -1; + dispp->modes = NULL; + dispp->whiteColour.red = dispp->whiteColour.green = + dispp->whiteColour.blue = 0x3F; + dispp->blackColour.red = dispp->blackColour.green = + dispp->blackColour.blue = 0; + dispp->defaultVisual = -1; + OFLG_ZERO(&(dispp->options)); + OFLG_ZERO(&(dispp->xconfigFlag)); + dispp->DCOptions = NULL; + + configDisplaySubsection(dispp); + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + + case MDEVICE: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Device name expected"); + for ( i = 0 ; i < n_devices ; i++ ) { + if ( strcmp(device_list[i].identifier,val.str) == 0 ) { + /* Copy back */ + if (!dummy && xf86Verbose) { + ErrorF("%s %s: Graphics device ID: \"%s\"\n", + XCONFIG_GIVEN, screen->name, device_list[i].identifier); + } + screen->clocks = device_list[i].clocks; + for ( j = 0 ; j < MAXCLOCKS ; j++ ) { + screen->clock[j] = device_list[i].clock[j]; + } + screen->chipset = device_list[i].chipset; + screen->ramdac = device_list[i].ramdac; + for (j=0; jdacSpeeds[j] = device_list[i].dacSpeeds[j]; + screen->dacSpeedBpp = 0; + screen->options = device_list[i].options; + screen->clockOptions = device_list[i].clockOptions; + screen->xconfigFlag = device_list[i].xconfigFlag; + screen->videoRam = device_list[i].videoRam; + screen->speedup = device_list[i].speedup; + screen->clockprog = device_list[i].clockprog; + textClockValue = device_list[i].textClockValue; + if (OFLG_ISSET(XCONFIG_BIOSBASE, &screen->xconfigFlag)) + screen->BIOSbase = device_list[i].BIOSbase; + if (OFLG_ISSET(XCONFIG_MEMBASE, &screen->xconfigFlag)) + screen->MemBase = device_list[i].MemBase; + if (OFLG_ISSET(XCONFIG_IOBASE, &screen->xconfigFlag)) + screen->IObase = device_list[i].IObase; + if (OFLG_ISSET(XCONFIG_DACBASE, &screen->xconfigFlag)) + screen->DACbase = device_list[i].DACbase; + if (OFLG_ISSET(XCONFIG_COPBASE, &screen->xconfigFlag)) + screen->COPbase = device_list[i].COPbase; + if (OFLG_ISSET(XCONFIG_POSBASE, &screen->xconfigFlag)) + screen->POSbase = device_list[i].POSbase; + if (OFLG_ISSET(XCONFIG_INSTANCE, &screen->xconfigFlag)) + screen->instance = device_list[i].instance; + screen->s3Madjust = device_list[i].s3Madjust; + screen->s3Nadjust = device_list[i].s3Nadjust; + screen->s3MClk = device_list[i].s3MClk; + screen->MemClk = device_list[i].MemClk; + screen->LCDClk = device_list[i].LCDClk; + screen->chipID = device_list[i].chipID; + screen->chipRev = device_list[i].chipRev; + screen->s3RefClk = device_list[i].s3RefClk; + screen->s3BlankDelay = device_list[i].s3BlankDelay; + screen->textClockFreq = device_list[i].textClockValue; + if (OFLG_ISSET(XCONFIG_VGABASE, &screen->xconfigFlag)) + screen->VGAbase = device_list[i].VGAbase; + screen->DCConfig = device_list[i].DCConfig; + screen->DCOptions = device_list[i].DCOptions; +#ifdef XF86SETUP + screen->device = (void *) &device_list[i]; +#endif + break; + } + } + if ( i == n_devices ) { /* Exhausted the device list */ + xf86ConfigError("Not a declared device"); + } + had_device = 1; + break; + + case MONITOR: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Monitor name expected"); + for ( i = 0 ; i < n_monitors ; i++ ) { + if ( strcmp(monitor_list[i].id,val.str) == 0 ) { + if (!dummy && xf86Verbose) { + ErrorF("%s %s: Monitor ID: \"%s\"\n", + XCONFIG_GIVEN, screen->name, monitor_list[i].id); + } + if (!dummy) { + monitor_list[i].Modes = xf86PruneModes(&monitor_list[i], + monitor_list[i].Modes, + screen, FALSE); + screen->monitor = (MonPtr)xalloc(sizeof(MonRec)); + memcpy(screen->monitor, &monitor_list[i], sizeof(MonRec)); + } + break; + } + } + if ( i == n_monitors ) { /* Exhausted the monitor list */ + xf86ConfigError("Not a declared monitor"); + } + had_monitor = 1; + break; + + case BLANKTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver blank time expected"); + if (!dummy && !xf86sFlag) + defaultScreenSaverTime = ScreenSaverTime = val.num * MILLI_PER_MIN; + break; + + case STANDBYTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver standby time expected"); +#ifdef DPMSExtension + if (!dummy) + DPMSStandbyTime = val.num * MILLI_PER_MIN; +#endif + break; + + case SUSPENDTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver suspend time expected"); +#ifdef DPMSExtension + if (!dummy) + DPMSSuspendTime = val.num * MILLI_PER_MIN; +#endif + break; + + case OFFTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver off time expected"); +#ifdef DPMSExtension + if (!dummy) + DPMSOffTime = val.num * MILLI_PER_MIN; +#endif + break; + + default: + if (!dummy && !validateGraphicsToken(screen->validTokens, token)) + { + xf86ConfigError("Screen section keyword expected"); + } + break; + } + } + + if (!dummy) { + if (dispList == NULL) { + FatalError( + "A \"Display\" subsection is required in each \"Screen\" section\n"); + } else { + /* Work out which if any Display subsection to use based on depth */ + if (xf86bpp < 0) { + /* + * no -bpp option given, so take depth if only one Display subsection + * Don't do this for VGA2 and VGA16 where it makes no sense, and only + * causes problems + */ + if (numDisps == 1) { +#ifndef XF86SETUP + if (dispList[0].depth > 0 + && !(driverno >= VGA2 && driverno <= VGA16)) { + xf86bpp = dispList[0].depth; + } +#endif + dispIndex = 0; + } else { + xf86bpp = screen->depth; + /* Look for a section which matches the driver's default depth */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if (dispList[dispIndex].depth == screen->depth) + break; + } + if (dispIndex == numDisps) { + /* No match. This time, allow 15/16 and 24/32 to match */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if ((screen->depth == 15 && dispList[dispIndex].depth == 16) || + (screen->depth == 16 && dispList[dispIndex].depth == 15) || + (screen->depth == 24 && dispList[dispIndex].depth == 32) || + (screen->depth == 32 && dispList[dispIndex].depth == 24)) + break; + } + } + if (dispIndex == numDisps) { + /* Still no match, so exit */ + FatalError("No \"Display\" subsection for default depth %d\n", + screen->depth); + } + } + } else { + /* xf86bpp is set */ + if (numDisps == 1 && dispList[0].depth < 0) { + /* one Display subsection, no depth set, so use it */ + /* XXXX Maybe should only do this when xf86bpp == default depth?? */ + dispIndex = 0; + } else { + /* find Display subsection matching xf86bpp */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if (dispList[dispIndex].depth == xf86bpp) + break; + } + if (dispIndex == numDisps) { +#if 0 + /* No match. This time, allow 15/16 and 24/32 to match */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if ((xf86bpp == 15 && dispList[dispIndex].depth == 16) || + (xf86bpp == 16 && dispList[dispIndex].depth == 15) || + (xf86bpp == 24 && dispList[dispIndex].depth == 32) || + (xf86bpp == 32 && dispList[dispIndex].depth == 24)) + break; +#else + /* No match. This time, allow 15/16 to match */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if ((xf86bpp == 15 && dispList[dispIndex].depth == 16) || + (xf86bpp == 16 && dispList[dispIndex].depth == 15)) + break; +#endif + } + } + if (dispIndex == numDisps) { + if (!(driverno >= VGA2 && driverno <= VGA16)) { + /* Still no match, so exit */ + FatalError("No \"Display\" subsection for -bpp depth %d\n", + xf86bpp); + } + else + dispIndex = 0; + } + } + } + /* Now copy the info across to the screen rec */ + dispp = dispList + dispIndex; + if (xf86bpp > 0) screen->depth = xf86bpp; + else if (dispp->depth > 0) screen->depth = dispp->depth; + if (xf86weight.red || xf86weight.green || xf86weight.blue) + screen->weight = xf86weight; + else if (dispp->weight.red > 0) { + screen->weight = dispp->weight; + xf86weight = dispp->weight; + } + screen->frameX0 = dispp->frameX0; + screen->frameY0 = dispp->frameY0; + screen->virtualX = dispp->virtualX; + screen->virtualY = dispp->virtualY; + screen->modes = dispp->modes; + screen->whiteColour = dispp->whiteColour; + screen->blackColour = dispp->blackColour; + screen->defaultVisual = dispp->defaultVisual; + /* Add any new options that might be set */ + for (i = 0; i < MAX_OFLAGS; i++) { + if (OFLG_ISSET(i, &(dispp->options))) + OFLG_SET(i, &(screen->options)); + if (OFLG_ISSET(i, &(dispp->xconfigFlag))) + OFLG_SET(i, &(screen->xconfigFlag)); + } + screen->DCOptions = xf86DCConcatOption(screen->DCOptions,dispp->DCOptions); +#ifdef XF86SETUP + xf86setup_scrn_ndisps[driverno-SVGA] = numDisps; + xf86setup_scrn_displays[driverno-SVGA] = dispList; +#else + /* Don't need them any more */ + xfree(dispList); +#endif + } + + /* Maybe these should be FatalError() instead? */ + if ( !had_monitor ) { + xf86ConfigError("A screen must specify a monitor"); + } + if ( !had_device ) { + xf86ConfigError("A screen must specify a device"); + } + } + + /* Check for information that must be specified in XF86Config */ + if (scr_index >= 0 && xf86Screens[scr_index]) + { + ScrnInfoPtr driver = xf86Screens[scr_index]; + + graphFound = TRUE; + + if (driver->clockprog && !driver->clocks) + { + if (!OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(screen->clockOptions))){ + ErrorF("%s: No clock line specified: assuming programmable clocks\n"); + OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &(screen->clockOptions));} + driver->textclock = textClockValue; + } + + /* Find the Index of the Text Clock for the ClockProg */ + if (driver->clockprog && textClockValue > 0 + && !OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(screen->clockOptions))) + { + driver->textclock = xf86GetNearestClock(driver, textClockValue); + if (abs(textClockValue - driver->clock[driver->textclock]) > + CLOCK_TOLERANCE) + FatalError( + "There is no defined dot-clock matching the text clock\n"); + if (xf86Verbose) + ErrorF("%s %s: text clock = %7.3f, clock used = %7.3f\n", + XCONFIG_GIVEN, + driver->name, textClockValue / 1000.0, + driver->clock[driver->textclock] / 1000.0); + } + if (xf86Verbose && driver->defaultVisual > 0) { + char *visualname; + switch (driver->defaultVisual) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + case TrueColor: + case DirectColor: + visualname = xf86VisualNames[driver->defaultVisual]; + break; + default: + xf86ConfigError("unknown visual type"); + } + ErrorF("%s %s: Default visual: %s\n", XCONFIG_GIVEN, driver->name, + visualname); + } + if (defaultColorVisualClass < 0) + defaultColorVisualClass = driver->defaultVisual; + + /* GJA --Moved these from the device code. Had to reorganize it + * a bit. + */ + if (xf86Verbose) { + if (OFLG_ISSET(XCONFIG_IOBASE, &driver->xconfigFlag)) + ErrorF("%s %s: Direct Access Register I/O Base Address: %x\n", + XCONFIG_GIVEN, driver->name, driver->IObase); + + if (OFLG_ISSET(XCONFIG_DACBASE, &driver->xconfigFlag)) + ErrorF("%s %s: DAC Base I/O Address: %x\n", + XCONFIG_GIVEN, driver->name, driver->DACbase); + + if (OFLG_ISSET(XCONFIG_COPBASE, &driver->xconfigFlag)) + ErrorF("%s %s: Coprocessor Base Memory Address: %x\n", + XCONFIG_GIVEN, driver->name, driver->COPbase); + + if (OFLG_ISSET(XCONFIG_POSBASE, &driver->xconfigFlag)) + ErrorF("%s %s: POS Base Address: %x\n", XCONFIG_GIVEN, driver->name, + driver->POSbase); + + if (OFLG_ISSET(XCONFIG_BIOSBASE, &driver->xconfigFlag)) + ErrorF("%s %s: BIOS Base Address: %x\n", XCONFIG_GIVEN, driver->name, + driver->BIOSbase); + + if (OFLG_ISSET(XCONFIG_MEMBASE, &driver->xconfigFlag)) + ErrorF("%s %s: Memory Base Address: %x\n", XCONFIG_GIVEN, + driver->name, driver->MemBase); + + if (OFLG_ISSET(XCONFIG_VGABASE, &driver->xconfigFlag)) + ErrorF("%s %s: VGA Aperture Base Address: %x\n", XCONFIG_GIVEN, + driver->name, driver->VGAbase); + + /* Print clock program */ + if ( driver->clockprog ) { + ErrorF("%s %s: ClockProg: \"%s\"", XCONFIG_GIVEN, driver->name, + driver->clockprog); + if ( textClockValue ) + ErrorF(", Text Clock: %7.3f\n", textClockValue / 1000.0); + ErrorF("\n"); + } + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configDisplaySubsection(disp) +DispPtr disp; +{ + int token; + int i; + + while ((token = xf86GetToken(DisplayTab)) != ENDSUBSECTION) { + switch (token) { + case DEPTH: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display depth expected"); + disp->depth = val.num; + break; + + case WEIGHT: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display weight expected"); + if (val.num > 9) { + disp->weight.red = (val.num / 100) % 10; + disp->weight.green = (val.num / 10) % 10; + disp->weight.blue = val.num % 10; + } else { + disp->weight.red = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display weight expected"); + disp->weight.green = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display weight expected"); + disp->weight.blue = val.num; + } + break; + + case VIEWPORT: + OFLG_SET(XCONFIG_VIEWPORT,&(disp->xconfigFlag)); + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Viewport X expected"); + disp->frameX0 = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Viewport Y expected"); + disp->frameY0 = val.num; + break; + + case VIRTUAL: + OFLG_SET(XCONFIG_VIRTUAL,&(disp->xconfigFlag)); + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Virtual X expected"); + disp->virtualX = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Virtual Y expected"); + disp->virtualY = val.num; + break; + + case MODES: + for (pLast=NULL; (token = xf86GetToken(NULL)) == STRING; pLast = pNew) + { + pNew = (DisplayModePtr)xalloc(sizeof(DisplayModeRec)); + pNew->name = val.str; + pNew->PrivSize = 0; + pNew->Private = NULL; + + if (pLast) + { + pLast->next = pNew; + pNew->prev = pLast; + } + else + disp->modes = pNew; + } + /* Make sure at least one mode was present */ + if (!pLast) + xf86ConfigError("Mode name expected"); + pNew->next = disp->modes; + disp->modes->prev = pLast; + pushToken = token; + break; + + case BLACK: + case WHITE: + { + unsigned char rgb[3]; + int ii; + + for (ii = 0; ii < 3; ii++) + { + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("RGB value expected"); + rgb[ii] = val.num & 0x3F; + } + if (token == BLACK) + { + disp->blackColour.red = rgb[0]; + disp->blackColour.green = rgb[1]; + disp->blackColour.blue = rgb[2]; + } + else + { + disp->whiteColour.red = rgb[0]; + disp->whiteColour.green = rgb[1]; + disp->whiteColour.blue = rgb[2]; + } + } + break; + + case VISUAL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Visual name expected"); + token = getStringToken(VisualTab); + if (!dummy && disp->defaultVisual >= 0) + xf86ConfigError("Only one default visual may be specified"); + disp->defaultVisual = token - STATICGRAY; + break; + + case OPTION: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); + i = 0; + while (xf86_OptionTab[i].token != -1) + { + if (StrCaseCmp(val.str, xf86_OptionTab[i].name) == 0) + { + OFLG_SET(xf86_OptionTab[i].token, &(disp->options)); + break; + } + i++; + } + if (xf86_OptionTab[i].token == -1) + disp->DCOptions = xf86DCOption(disp->DCOptions,val); + break; + + /* The following should really go in the S3 server */ + case INVERTVCLK: + case BLANKDELAY: + case EARLYSC: + { + DisplayModePtr p = disp->modes; + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Mode name expected"); + if (disp->modes == NULL) + xf86ConfigError("This must be after the Modes line"); + { + Bool found = FALSE; + int opt; + INT32 value; + char *mode_string = (char *)xalloc(strlen(val.str)+1); + strcpy(mode_string,val.str); + + switch (token) { + default: /* pacify compiler (uninitialized opt, value) */ + case INVERTVCLK: + if (xf86GetToken(NULL) != NUMBER || val.num < 0 || val.num > 1) + xf86ConfigError("0 or 1 expected"); + opt = S3_INVERT_VCLK; + value = val.num; + break; + + case BLANKDELAY: + if (xf86GetToken(NULL) != NUMBER || val.num < 0 || val.num > 7) + xf86ConfigError("number(s) 0..7 expected"); + opt = S3_BLANK_DELAY; + value = val.num; + if ((token=xf86GetToken(NULL)) == NUMBER) { + if (val.num < 0 || val.num > 7) + xf86ConfigError("number2 0..7 expected"); + value |= val.num << 4; + } + else pushToken = token; + break; + + case EARLYSC: + if (xf86GetToken(NULL) != NUMBER || val.num < 0 || val.num > 1) + xf86ConfigError("0 or 1 expected"); + opt = S3_EARLY_SC; + value = val.num; + break; + } + + do { + if (strcmp(p->name, mode_string) == 0 + || strcmp("*", mode_string) == 0) { + found = TRUE; + if (!p->PrivSize || !p->Private) { + p->PrivSize = S3_MODEPRIV_SIZE; + p->Private = (INT32 *)Xcalloc(sizeof(INT32) * S3_MODEPRIV_SIZE); + p->Private[0] = 0; + } + p->Private[0] |= (1 << opt); + p->Private[opt] = value; + } + p = p->next; + } while (p != disp->modes); + if (!found) xf86ConfigError("No mode of that name in the Modes line"); + xfree(mode_string); + } + } + break; + + + case EOF: + FatalError("Unexpected EOF (missing EndSubSection)"); + break; /* :-) */ + + default: + xf86ConfigError("Display subsection keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +Bool +xf86LookupMode(target, driver, flags) + DisplayModePtr target; + ScrnInfoPtr driver; + int flags; +{ + DisplayModePtr p; + DisplayModePtr best_mode = NULL; + int i, j, k, Gap; + int Minimum_Gap = CLOCK_TOLERANCE + 1; + Bool found_mode = FALSE; + Bool clock_too_high = FALSE; + static Bool first_time = TRUE; + double refresh, bestRefresh = 0.0; + + if (first_time) + { + ErrorF("%s %s: Maximum allowed dot-clock: %1.3f MHz\n", XCONFIG_PROBED, + driver->name, driver->maxClock / 1000.0); + first_time = FALSE; + /* + * First time through, cull modes which are not valid for the + * card/driver. + */ + driver->monitor->Modes = xf86PruneModes(NULL, driver->monitor->Modes, + driver, TRUE); + } + + if (xf86BestRefresh && !(flags & LOOKUP_FORCE_DEFAULT)) + flags |= LOOKUP_BEST_REFRESH; + + for (p = driver->monitor->Modes; p != NULL; p = p->next) /* scan list */ + { + if (!strcmp(p->name, target->name)) /* names equal ? */ + { + /* First check if the driver objects to the mode */ + if ((driver->ValidMode)(p, xf86Verbose, MODE_USED) != MODE_OK) + { + ErrorF("%s %s: Mode \"%s\" rejected by driver. Deleted.\n", + XCONFIG_PROBED,driver->name, target->name ); + break; + } + + if ((flags & LOOKUP_NO_INTERLACED) && (p->Flags & V_INTERLACE)) + { + continue; + } + + if ((OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(driver->clockOptions))) && + !OFLG_ISSET(OPTION_NO_PROGRAM_CLOCKS, &(driver->options))) + { + if (driver->clocks == 0) + { + /* this we know */ + driver->clock[0] = 25175; /* 25.175Mhz */ + driver->clock[1] = 28322; /* 28.322MHz */ + driver->clocks = 2; + } + + if ((p->Clock / 1000) > (driver->maxClock / 1000)) + clock_too_high = TRUE; + else + { + /* We fill in the the programmable clocks as we go */ + for (i=0; i < driver->clocks; i++) + if (driver->clock[i] == p->Clock) + break; + + if (i >= MAXCLOCKS) + { + ErrorF("%s %s: Too many programmable clocks used (limit %d)!\n", + XCONFIG_PROBED, driver->name, MAXCLOCKS); + return FALSE; + } + + if (i == driver->clocks) + { + driver->clock[i] = p->Clock; + driver->clocks++; + } + + + if (flags & LOOKUP_BEST_REFRESH) + { + refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; + if (p->Flags & V_INTERLACE) + { + refresh *= 2; + refresh /= INTERLACE_REFRESH_WEIGHT; + } + else if (p->Flags & V_DBLSCAN) + { + refresh /= 2; + } + if (refresh > bestRefresh) + { + best_mode = p; + bestRefresh = refresh; + target->Clock = i; + } + } + else + { + target->Clock = i; + best_mode = p; + } + } + } + else + { + /* + * go look if any of the clocks in the list matches the one in + * the mode (j=1), or if a better match exists when the clocks + * in the list are divided by 2 (j=2) + */ + if (OFLG_ISSET(OPTION_CLKDIV2, &(driver->options))) + k=2; + else + k=1; + for (j=1 ; j<=k ; j++) + { + i = xf86GetNearestClock(driver, p->Clock*j); + if (flags & LOOKUP_BEST_REFRESH) + { + if ( ((driver->clock[i]/j) / 1000) > (driver->maxClock / 1000) ) + clock_too_high = TRUE; + else + { + refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; + if (p->Flags & V_INTERLACE) + { + refresh *= 2; + refresh /= INTERLACE_REFRESH_WEIGHT; + } + else if (p->Flags & V_DBLSCAN) + { + refresh /= 2; + } + if (refresh > bestRefresh) + { + target->Clock = i; + if (j==2) p->Flags |= V_CLKDIV2; + best_mode = p; + bestRefresh = refresh; + } + } + } + else + { + Gap = abs( p->Clock - (driver->clock[i]/j) ); + if (Gap < Minimum_Gap) + { + if ( ((driver->clock[i]/j) / 1000) > (driver->maxClock / 1000) ) + clock_too_high = TRUE; + else + { + target->Clock = i; + if (j==2) p->Flags |= V_CLKDIV2; + best_mode = p; + Minimum_Gap = Gap; + } + } + } + } + } + found_mode = TRUE; + } + } + + if (best_mode != NULL) + { + target->HDisplay = best_mode->HDisplay; + target->HSyncStart = best_mode->HSyncStart; + target->HSyncEnd = best_mode->HSyncEnd; + target->HTotal = best_mode->HTotal; + target->HSkew = best_mode->HSkew; + target->VDisplay = best_mode->VDisplay; + target->VSyncStart = best_mode->VSyncStart; + target->VSyncEnd = best_mode->VSyncEnd; + target->VTotal = best_mode->VTotal; + target->Flags = best_mode->Flags; + target->CrtcHDisplay = best_mode->CrtcHDisplay; + target->CrtcHSyncStart = best_mode->CrtcHSyncStart; + target->CrtcHSyncEnd = best_mode->CrtcHSyncEnd; + target->CrtcHTotal = best_mode->CrtcHTotal; + target->CrtcHSkew = best_mode->CrtcHSkew; + target->CrtcVDisplay = best_mode->CrtcVDisplay; + target->CrtcVSyncStart = best_mode->CrtcVSyncStart; + target->CrtcVSyncEnd = best_mode->CrtcVSyncEnd; + target->CrtcVTotal = best_mode->CrtcVTotal; + target->CrtcHAdjusted = best_mode->CrtcHAdjusted; + target->CrtcVAdjusted = best_mode->CrtcVAdjusted; + if (target->Flags & V_DBLSCAN) + { + target->CrtcVDisplay *= 2; + target->CrtcVSyncStart *= 2; + target->CrtcVSyncEnd *= 2; + target->CrtcVTotal *= 2; + target->CrtcVAdjusted = TRUE; + } + +#if 0 + /* I'm not sure if this is the best place for this in the + * new XF86Config organization. - SRA + */ + if (found_mode) + if ((driver->ValidMode)(target, xf86Verbose, MODE_USED) != MODE_OK) + { + ErrorF("%s %s: Unable to support mode \"%s\"\n", + XCONFIG_GIVEN,driver->name, target->name ); + return(FALSE); + } +#endif + + if (xf86Verbose) + { + ErrorF("%s %s: Mode \"%s\": mode clock = %7.3f", + XCONFIG_GIVEN, driver->name, target->name, + best_mode->Clock / 1000.0); + if (!OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(driver->clockOptions)) || + OFLG_ISSET(OPTION_NO_PROGRAM_CLOCKS, &(driver->options))) { + ErrorF(", clock used = %7.3f", driver->clock[target->Clock] / 1000.0); + if (target->Flags & V_CLKDIV2) + ErrorF("/2"); + } + ErrorF("\n"); + } + } + else if (!found_mode) + ErrorF("%s %s: There is no mode definition named \"%s\"\n", + XCONFIG_PROBED, driver->name, target->name); + else if (clock_too_high) + ErrorF("%s %s: Clock for mode \"%s\" %s\n\tLimit is %7.3f MHz\n", + XCONFIG_PROBED, driver->name, target->name, + "is too high for the configured hardware.", + driver->maxClock / 1000.0); + else + ErrorF("%s %s: There is no defined dot-clock matching mode \"%s\"\n", + XCONFIG_PROBED, driver->name, target->name); + + return (best_mode != NULL); +} + +void +xf86VerifyOptions(allowedOptions, driver) + OFlagSet *allowedOptions; + ScrnInfoPtr driver; +{ + int j; + + for (j=0; xf86_OptionTab[j].token >= 0; j++) + if ((OFLG_ISSET(xf86_OptionTab[j].token, &driver->options))) + if (OFLG_ISSET(xf86_OptionTab[j].token, allowedOptions)) + { + if (xf86Verbose) + ErrorF("%s %s: Option \"%s\"\n", XCONFIG_GIVEN, + driver->name, xf86_OptionTab[j].name); + } + else + ErrorF("%s %s: Option flag \"%s\" is not defined for this driver\n", + XCONFIG_GIVEN, driver->name, xf86_OptionTab[j].name); +} + +/* Note: (To keep me [GJA] from getting confused) + * We have two mode-related datastructures: + * 1. A doubly linked mode name list, with ends marked by self-pointers. + * 2. A doubly linked mode structure list. + * We are operating here on the second structure. + * Initially this is just singly linked. + */ +static DisplayModePtr +xf86PruneModes(monp, allmodes, scrp, card) + MonPtr monp; /* Monitor specification */ + DisplayModePtr allmodes; /* List to be pruned */ + ScrnInfoPtr scrp; + Bool card; /* TRUE => do driver validity check */ +{ + DisplayModePtr dispmp; /* To walk the list */ + DisplayModePtr olddispmp; /* The one being freed. */ + DisplayModePtr remainder; /* The first one retained. */ + + dispmp = allmodes; + + /* The first modes to be deleted require that the pointer to the + * mode list is updated. Also, they have no predecessor in the list. + */ + while (dispmp && + (card ? + ((scrp->ValidMode)(dispmp, xf86Verbose, MODE_SUGGESTED) + != MODE_OK) : + (xf86CheckMode(scrp, dispmp, monp, xf86Verbose) != MODE_OK))) { + olddispmp = dispmp; + dispmp = dispmp->next; + xfree(olddispmp->name); + xfree(olddispmp); + } + /* Now we either have a mode that fits, or no mode at all */ + if ( ! dispmp ) { /* No mode at all */ + return NULL; + } + remainder = dispmp; + while ( dispmp->next ) { + if (card ? + ((scrp->ValidMode)(dispmp->next,xf86Verbose,MODE_SUGGESTED) + != MODE_OK) : + (xf86CheckMode(scrp, dispmp->next, monp, xf86Verbose) != + MODE_OK)) { + olddispmp = dispmp->next; + dispmp->next = dispmp->next->next; + xfree(olddispmp->name); + xfree(olddispmp); + } else { + dispmp = dispmp->next; + } + } + return remainder; /* Return pointer to {the first / the list } */ +} + +/* + * Return MODE_OK if the mode pointed to by dispmp agrees with all constraints + * we can make up for the monitor pointed to by monp. + */ +int +xf86CheckMode(scrp, dispmp, monp, verbose) + ScrnInfoPtr scrp; + DisplayModePtr dispmp; + MonPtr monp; + Bool verbose; +{ + int i; + float dotclock, hsyncfreq, vrefreshrate; + char *scrname = scrp->name; + + /* Sanity checks */ + if ((0 >= dispmp->HDisplay) || + (dispmp->HDisplay > dispmp->HSyncStart) || + (dispmp->HSyncStart >= dispmp->HSyncEnd) || + (dispmp->HSyncEnd >= dispmp->HTotal)) + { + ErrorF( + "%s %s: Invalid horizontal timing for mode \"%s\". Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name); + return MODE_HSYNC; + } + + if ((0 >= dispmp->VDisplay) || + (dispmp->VDisplay > dispmp->VSyncStart) || + (dispmp->VSyncStart >= dispmp->VSyncEnd) || + (dispmp->VSyncEnd >= dispmp->VTotal)) + { + ErrorF( + "%s %s: Invalid vertical timing for mode \"%s\". Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name); + return MODE_VSYNC; + } + + /* Deal with the dispmp->Clock being a frequency or index */ + if (dispmp->Clock > MAXCLOCKS) { + dotclock = (float)dispmp->Clock; + } else { + dotclock = (float)scrp->clock[dispmp->Clock]; + } + hsyncfreq = dotclock / (float)(dispmp->HTotal); + for ( i = 0 ; i < monp->n_hsync ; i++ ) + if ( (hsyncfreq > 0.999 * monp->hsync[i].lo) && + (hsyncfreq < 1.001 * monp->hsync[i].hi) ) + break; /* In range. */ + + /* Now see whether we ran out of sync frequencies */ + if ( i == monp->n_hsync ) { + if (verbose) { + ErrorF( + "%s %s: Mode \"%s\" needs hsync freq of %.2f kHz. Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name, hsyncfreq); + } + return MODE_HSYNC; + } + + vrefreshrate = dotclock * 1000.0 / + ((float)(dispmp->HTotal) * (float)(dispmp->VTotal)) ; + if ( dispmp->Flags & V_INTERLACE ) vrefreshrate *= 2.0; + if ( dispmp->Flags & V_DBLSCAN ) vrefreshrate /= 2.0; + for ( i = 0 ; i < monp->n_vrefresh ; i++ ) + if ( (vrefreshrate > 0.999 * monp->vrefresh[i].lo) && + (vrefreshrate < 1.001 * monp->vrefresh[i].hi) ) + break; /* In range. */ + + /* Now see whether we ran out of refresh rates */ + if ( i == monp->n_vrefresh ) { + if (verbose) { + ErrorF( + "%s %s: Mode \"%s\" needs vert refresh rate of %.2f Hz. Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name, vrefreshrate); + } + return MODE_VSYNC; + } + + /* Interlaced modes should have an odd VTotal */ + if (dispmp->Flags & V_INTERLACE) + dispmp->CrtcVTotal = dispmp->VTotal |= 1; + + /* Passed every test. */ + return MODE_OK; +} + +/* + * Save entire line from config file in memory area, if memory area + * does not exist allocate it. Set DCerr according to value of token. + * Return address of memory area. + */ +static char *xf86DCSaveLine(DCPointer,token) + char *DCPointer; + int token; +{ + static int len = 0; /* length of memory area where to store strings */ + static int pos = 0; /* current position */ + char *currpointer; /* pointer to current position in memory area */ + static int currline; /* lineno of line currently interpreted */ + int addlen; /* len to add to pos */ + + if(DCPointer == NULL){ /* initialize */ + DCPointer = (char *)xalloc(4096); /* initial size 4kB */ + len = 4096; + strcpy(DCPointer,configPath); + pos = strlen(DCPointer) + 1; + currline = -1; /* no line yet */ + } + + if(configLineNo != currline) /* new line */ + { + currline = configLineNo; + addlen = strlen(configBuf) + 1 + sizeof(int); /* string + lineno */ + while ( (pos + addlen) >= len ){ /* not enough space? */ + DCPointer = (char *)xrealloc(DCPointer, (len + 4096)); + len += 4096; + } + currpointer = DCPointer + pos; /* find current position */ + memcpy(currpointer, &currline, sizeof(int)); /* Grrr unaligned ints.. */ + strcpy((currpointer + sizeof(int)),configBuf); /* store complete line*/ + pos += addlen; /* goto end */ + currpointer += addlen; + *(currpointer) = EOF; /* mark end */ + } + switch(token){ + case STRING: + case DASH: + case NUMBER: + case COMMA: + break; + case ERROR_TOKEN: /* if unknown token unset DCerr to ignore it */ + DCerr = 0; /* and subsequent STRING, DASH, NUMBER, COMMA */ + break; + default: /* set to complain if a valid token is */ + DCerr = 1; /* followed by an unwanted STRING etc. */ + } + return(DCPointer); +} + +/* + * Store any unknown Option strings (contained in val.str) + * in a memory are pointed to by pointer. If it doesn't + * exist allocate it and return a pointer pointing to it + */ + +static char * +xf86DCOption(DCPointer, val) + char *DCPointer; + LexRec val; +{ + static int len = 0; + static int pos = 0; + int addlen; + char *currpointer; /* current position */ + + if (DCPointer == NULL){ /* First time: initialize */ + DCPointer = (char *)xalloc(4096); /* allocate enough space */ + strcpy(DCPointer,configPath); + pos = strlen(DCPointer) + 1; + len = 4096; /* and total length */ + } + + addlen = sizeof(int) + strlen(val.str) + 1; /* token, lineno */ + while( (pos + addlen) >= len ){ /* reallocate if not enough */ + DCPointer = (char *)xrealloc(DCPointer, (len + 4096)); + len += 4096; + } + currpointer = DCPointer + pos; + *(int *)currpointer=configLineNo; + strcpy(currpointer + sizeof(int),val.str); /* store string */ + pos += addlen; + *(currpointer + addlen) = EOF; /* mark end */ + return(DCPointer); +} + +static char +* xf86DCConcatOption(Pointer1, Pointer2) +char *Pointer1; +char *Pointer2; +{ + int s1 = 0; + int s2 = 0; + int s3; + char *ptmp; + + if(Pointer1) + while(*(Pointer1 + s1) != EOF){s1++;} + else if (Pointer2) + return Pointer2; + else return NULL; + if(Pointer2) + while(*(Pointer2 + s2) != EOF){s2++;} + else if (Pointer1) + return Pointer1; + else return NULL; + s3 = strlen(Pointer2) + 1; + s2 -= s3; + + Pointer1 = (char *)xrealloc(Pointer1,s1+s2+1); + ptmp = Pointer1 + s1; + Pointer2 += s3; + do{ + *ptmp = *Pointer2; + *ptmp++; + *Pointer2++; + } while(s2--); + return Pointer1; +} + diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c new file mode 100644 index 000000000..6c0943b41 --- /dev/null +++ b/hw/xfree86/common/xf86Cursor.c @@ -0,0 +1,326 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Cursor.c,v 3.13 1996/12/23 06:43:22 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86Cursor.c,v 1.3 2000/08/17 19:50:29 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "cursor.h" +#include "mipointer.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#ifdef XFreeXDGA +#include "Xproto.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "servermd.h" + +#define _XF86DGA_SERVER_ +#include "extensions/xf86dgastr.h" +#endif + +#ifdef XINPUT +#include "xf86_Config.h" +#include "XIproto.h" +#include "xf86Xinput.h" +#endif + +/* #include "atKeynames.h" -hv- dont need that include here */ + + +static Bool xf86CursorOffScreen( +#if NeedFunctionPrototypes + ScreenPtr *pScreen, + int *x, + int *y +#endif +); +static void xf86CrossScreen( +#if NeedFunctionPrototypes + ScreenPtr pScreen, + Bool entering +#endif +); +static void xf86WrapCursor( +#if NeedFunctionPrototypes + ScreenPtr pScreen, + int x, + int y +#endif +); + +miPointerScreenFuncRec xf86PointerScreenFuncs = { + xf86CursorOffScreen, + xf86CrossScreen, + xf86WrapCursor, +#ifdef XINPUT + xf86eqEnqueue, +#endif +}; + + + +/* + * xf86InitViewport -- + * Initialize paning & zooming parameters, so that a driver must only + * check what resolutions are possible and whether the virtual area + * is valid if specifyed. + */ + +void +xf86InitViewport(pScr) + ScrnInfoPtr pScr; +{ + /* + * Compute the initial Viewport if necessary + */ + if (pScr->frameX0 < 0) + { + pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2; + pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2; + } + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + + /* + * Now adjust the initial Viewport, so it lies within the virtual area + */ + if (pScr->frameX1 >= pScr->virtualX) + { + pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + } + + if (pScr->frameY1 >= pScr->virtualY) + { + pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + } +} + + +/* + * xf86SetViewport -- + * Scroll the visual part of the screen so the pointer is visible. + */ + +void +xf86SetViewport(pScreen, x, y) + ScreenPtr pScreen; + int x, y; +{ + Bool frameChanged = FALSE; + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + + /* + * check wether (x,y) belongs to the visual part of the screen + * if not, change the base of the displayed frame accoring + */ + if ( pScr->frameX0 > x) { + pScr->frameX0 = x; + pScr->frameX1 = x + pScr->modes->HDisplay - 1; + frameChanged = TRUE ; + } + + if ( pScr->frameX1 < x) { + pScr->frameX1 = x + 1; + pScr->frameX0 = x - pScr->modes->HDisplay + 1; + frameChanged = TRUE ; + } + + if ( pScr->frameY0 > y) { + pScr->frameY0 = y; + pScr->frameY1 = y + pScr->modes->VDisplay - 1; + frameChanged = TRUE; + } + + if ( pScr->frameY1 < y) { + pScr->frameY1 = y; + pScr->frameY0 = y - pScr->modes->VDisplay + 1; + frameChanged = TRUE; + } + + if (frameChanged) (pScr->AdjustFrame)(pScr->frameX0, pScr->frameY0); +} + + +static Bool xf86ZoomLocked = FALSE; + +/* + * xf86LockZoom -- + * Enable/disable ZoomViewport + */ + +void +xf86LockZoom (pScreen, lock) + ScreenPtr pScreen; + Bool lock; +{ + /* + * pScreen is currently ignored, but may be used later to enable locking + * of individual screens. + */ + + xf86ZoomLocked = lock; +} + +/* + * xf86ZoomViewport -- + * Reinitialize the visual part of the screen for another modes-> + */ + +void +xf86ZoomViewport (pScreen, zoom) + ScreenPtr pScreen; + int zoom; +{ + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + + if (xf86ZoomLocked) + return; + +#ifdef XFreeXDGA + /* + * We should really send the mode change request to the DGA client and let + * it decide what to do. For now just bin the request + */ + if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectGraphics) + return; +#endif + + if (pScr->modes != pScr->modes->next) + { + pScr->modes = zoom > 0 ? pScr->modes->next : pScr->modes->prev; + + if ((pScr->SwitchMode)(pScr->modes)) + { + /* + * adjust new frame for the displaysize + */ + pScr->frameX0 = (pScr->frameX1 + pScr->frameX0 -pScr->modes->HDisplay)/2; + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + + if (pScr->frameX0 < 0) + { + pScr->frameX0 = 0; + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + } + else if (pScr->frameX1 >= pScr->virtualX) + { + pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + } + + pScr->frameY0 = (pScr->frameY1 + pScr->frameY0 - pScr->modes->VDisplay)/2; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + + if (pScr->frameY0 < 0) + { + pScr->frameY0 = 0; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + } + else if (pScr->frameY1 >= pScr->virtualY) + { + pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + } + } + else /* switch failed, so go back to old mode */ + pScr->modes = zoom > 0 ? pScr->modes->prev : pScr->modes->next; + } + + (pScr->AdjustFrame)(pScr->frameX0, pScr->frameY0); +} + + + +/* + * xf86CursorOffScreen -- + * Check whether it is necessary to switch to another screen + */ + +/* ARGSUSED */ +static Bool +xf86CursorOffScreen (pScreen, x, y) + ScreenPtr *pScreen; + int *x, *y; +{ + int i; + + if ((screenInfo.numScreens > 1) && ((*x < 0) || ((*pScreen)->width <= *x))) { + i = (*pScreen)->myNum; + if (*x < 0) { + i = (i ? i : screenInfo.numScreens) -1; + *pScreen = screenInfo.screens[i]; + *x += (*pScreen)->width; + } + else { + *x -= (*pScreen)->width; + i = (i+1) % screenInfo.numScreens; + *pScreen = screenInfo.screens[i]; + } + return(TRUE); + } + return(FALSE); +} + + + +/* + * xf86CrossScreen -- + * Switch to another screen + */ + +/* ARGSUSED */ +static void +xf86CrossScreen (pScreen, entering) + ScreenPtr pScreen; + Bool entering; +{ + if (xf86Info.sharedMonitor) + (XF86SCRNINFO(pScreen)->EnterLeaveMonitor)(entering); + (XF86SCRNINFO(pScreen)->EnterLeaveCursor)(entering); +} + + +/* + * xf86WrapCursor -- + * Wrap possible to another screen + */ + +/* ARGSUSED */ +static void +xf86WrapCursor (pScreen, x, y) + ScreenPtr pScreen; + int x,y; +{ + miPointerWarpCursor(pScreen,x,y); + + xf86Info.currentScreen = pScreen; +} diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c new file mode 100644 index 000000000..aa0983111 --- /dev/null +++ b/hw/xfree86/common/xf86Events.c @@ -0,0 +1,1575 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Events.c,v 3.42.2.4 1998/02/07 09:23:28 hohndel Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86Events.c,v 1.3 2000/08/17 19:50:29 cpqbld Exp $ */ + +/* [JCH-96/01/21] Extended std reverse map to four buttons. */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "Xpoll.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "xf86_Config.h" +#include "atKeynames.h" + + +#ifdef XFreeXDGA +#include "XIproto.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "exevents.h" + +#define _XF86DGA_SERVER_ +#include "extensions/xf86dgastr.h" +#endif + +#ifdef XINPUT +#include "XI.h" +#include "XIproto.h" +#include "xf86Xinput.h" +#endif + +#include "mipointer.h" +#include "opaque.h" +#ifdef DPMSExtension +#include "extensions/dpms.h" +#endif + +#ifdef XKB +extern Bool noXkbExtension; +#endif + +#define XE_POINTER 1 +#define XE_KEYBOARD 2 + +#ifdef XTESTEXT1 + +#define XTestSERVER_SIDE +#include "xtestext1.h" +extern short xtest_mousex; +extern short xtest_mousey; +extern int on_steal_input; +extern Bool XTestStealKeyData(); +extern void XTestStealMotionData(); + +#ifdef XINPUT +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + if (!on_steal_input || \ + XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \ + xtest_mousex, xtest_mousey)) \ + xf86eqEnqueue((ev)) +#else +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + if (!on_steal_input || \ + XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \ + xtest_mousex, xtest_mousey)) \ + mieqEnqueue((ev)) +#endif + +#define MOVEPOINTER(dx, dy, time) \ + if (on_steal_input) \ + XTestStealMotionData(dx, dy, XE_POINTER, xtest_mousex, xtest_mousey); \ + miPointerDeltaCursor (dx, dy, time) + +#else /* ! XTESTEXT1 */ + +#ifdef XINPUT +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + xf86eqEnqueue((ev)) +#else +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + mieqEnqueue((ev)) +#endif +#define MOVEPOINTER(dx, dy, time) \ + miPointerDeltaCursor (dx, dy, time) + +#endif + +Bool xf86VTSema = TRUE; + +#ifdef XINPUT +extern InputInfo inputInfo; +#endif /* XINPUT */ + +/* + * The first of many hack's to get VT switching to work under + * Solaris 2.1 for x86. The basic problem is that Solaris is supposed + * to be SVR4. It is for the most part, except where the video interface + * is concerned. These hacks work around those problems. + * See the comments for Linux, and SCO. + * + * This is a toggleling variable: + * FALSE = No VT switching keys have been pressed last time around + * TRUE = Possible VT switch Pending + * (DWH - 12/2/93) + * + * This has been generalised to work with Linux and *BSD+syscons (DHD) + */ + +#ifdef USE_VT_SYSREQ +static Bool VTSysreqToggle = FALSE; +#endif /* !USE_VT_SYSREQ */ +static Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for *BSD */ + +extern fd_set EnabledDevices; + +#if defined(CODRV_SUPPORT) +extern unsigned char xf86CodrvMap[]; +#endif + +#if defined(XQUEUE) && !defined(XQUEUE_ASYNC) +extern void xf86XqueRequest( +#if NeedFunctionPrototypes + void +#endif + ); +#endif + +#ifdef DPMSExtension +extern BOOL DPMSEnabled; +extern void DPMSSet(CARD16); +#endif + +static void xf86VTSwitch( +#if NeedFunctionPrototypes + void +#endif + ); +#ifdef XFreeXDGA +static void XF86DirectVideoMoveMouse( +#if NeedFunctionPrototypes + int x, + int y, + CARD32 mtime +#endif + ); +static void XF86DirectVideoKeyEvent( +#if NeedFunctionPrototypes + xEvent *xE, + int keycode, + int etype +#endif + ); +#endif +static CARD32 buttonTimer( +#if NeedFunctionPrototypes + OsTimerPtr timer, + CARD32 now, + pointer arg +#endif + ); + +/* + * Lets create a simple finite-state machine: + * + * state[?][0]: action1 + * state[?][1]: action2 + * state[?][2]: next state + * + * action > 0: ButtonPress + * action = 0: nothing + * action < 0: ButtonRelease + * + * Why this stuff ??? Normally you cannot press both mousebuttons together, so + * the mouse reports both pressed at the same time ... + */ + +static char stateTab[48][3] = { + +/* nothing pressed */ + { 0, 0, 0 }, + { 0, 0, 8 }, /* 1 right -> delayed right */ + { 0, 0, 0 }, /* 2 nothing */ + { 0, 0, 8 }, /* 3 right -> delayed right */ + { 0, 0, 16 }, /* 4 left -> delayed left */ + { 2, 0, 24 }, /* 5 left & right (middle press) -> middle pressed */ + { 0, 0, 16 }, /* 6 left -> delayed left */ + { 2, 0, 24 }, /* 7 left & right (middle press) -> middle pressed */ + +/* delayed right */ + { 1, -1, 0 }, /* 8 nothing (right event) -> init */ + { 1, 0, 32 }, /* 9 right (right press) -> right pressed */ + { 1, -1, 0 }, /* 10 nothing (right event) -> init */ + { 1, 0, 32 }, /* 11 right (right press) -> right pressed */ + { 1, -1, 16 }, /* 12 left (right event) -> delayed left */ + { 2, 0, 24 }, /* 13 left & right (middle press) -> middle pressed */ + { 1, -1, 16 }, /* 14 left (right event) -> delayed left */ + { 2, 0, 24 }, /* 15 left & right (middle press) -> middle pressed */ + +/* delayed left */ + { 3, -3, 0 }, /* 16 nothing (left event) -> init */ + { 3, -3, 8 }, /* 17 right (left event) -> delayed right */ + { 3, -3, 0 }, /* 18 nothing (left event) -> init */ + { 3, -3, 8 }, /* 19 right (left event) -> delayed right */ + { 3, 0, 40 }, /* 20 left (left press) -> pressed left */ + { 2, 0, 24 }, /* 21 left & right (middle press) -> pressed middle */ + { 3, 0, 40 }, /* 22 left (left press) -> pressed left */ + { 2, 0, 24 }, /* 23 left & right (middle press) -> pressed middle */ + +/* pressed middle */ + { -2, 0, 0 }, /* 24 nothing (middle release) -> init */ + { -2, 0, 0 }, /* 25 right (middle release) -> init */ + { -2, 0, 0 }, /* 26 nothing (middle release) -> init */ + { -2, 0, 0 }, /* 27 right (middle release) -> init */ + { -2, 0, 0 }, /* 28 left (middle release) -> init */ + { 0, 0, 24 }, /* 29 left & right -> pressed middle */ + { -2, 0, 0 }, /* 30 left (middle release) -> init */ + { 0, 0, 24 }, /* 31 left & right -> pressed middle */ + +/* pressed right */ + { -1, 0, 0 }, /* 32 nothing (right release) -> init */ + { 0, 0, 32 }, /* 33 right -> pressed right */ + { -1, 0, 0 }, /* 34 nothing (right release) -> init */ + { 0, 0, 32 }, /* 35 right -> pressed right */ + { -1, 0, 16 }, /* 36 left (right release) -> delayed left */ + { -1, 2, 24 }, /* 37 left & right (r rel, m prs) -> middle pressed */ + { -1, 0, 16 }, /* 38 left (right release) -> delayed left */ + { -1, 2, 24 }, /* 39 left & right (r rel, m prs) -> middle pressed */ + +/* pressed left */ + { -3, 0, 0 }, /* 40 nothing (left release) -> init */ + { -3, 0, 8 }, /* 41 right (left release) -> delayed right */ + { -3, 0, 0 }, /* 42 nothing (left release) -> init */ + { -3, 0, 8 }, /* 43 right (left release) -> delayed right */ + { 0, 0, 40 }, /* 44 left -> left pressed */ + { -3, 2, 24 }, /* 45 left & right (l rel, mprs) -> middle pressed */ + { 0, 0, 40 }, /* 46 left -> left pressed */ + { -3, 2, 24 }, /* 47 left & right (l rel, mprs) -> middle pressed */ +}; + + +/* + * Table to allow quick reversal of natural button mapping to correct mapping + */ + +/* + * [JCH-96/01/21] The ALPS GlidePoint pad extends the MS protocol + * with a fourth button activated by tapping the PAD. + * The 2nd line corresponds to 4th button on; the drv sends + * the buttons in the following map (MSBit described first) : + * 0 | 4th | 1st | 2nd | 3rd + * And we remap them (MSBit described first) : + * 0 | 4th | 3rd | 2nd | 1st + */ +static char reverseMap[32] = { 0, 4, 2, 6, 1, 5, 3, 7, + 8, 12, 10, 14, 9, 13, 11, 15, + 16, 20, 18, 22, 17, 21, 19, 23, + 24, 28, 26, 30, 25, 29, 27, 31}; + + +static char hitachMap[16] = { 0, 2, 1, 3, + 8, 10, 9, 11, + 4, 6, 5, 7, + 12, 14, 13, 15 }; + +#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f]) + + +/* + * TimeSinceLastInputEvent -- + * Function used for screensaver purposes by the os module. Retruns the + * time in milliseconds since there last was any input. + */ + +int +TimeSinceLastInputEvent() +{ + if (xf86Info.lastEventTime == 0) { + xf86Info.lastEventTime = GetTimeInMillis(); + } + return GetTimeInMillis() - xf86Info.lastEventTime; +} + + + +/* + * SetTimeSinceLastInputEvent -- + * Set the lastEventTime to now. + */ + +void +SetTimeSinceLastInputEvent() +{ + xf86Info.lastEventTime = GetTimeInMillis(); +} + + + +/* + * ProcessInputEvents -- + * Retrieve all waiting input events and pass them to DIX in their + * correct chronological order. Only reads from the system pointer + * and keyboard. + */ + +void +ProcessInputEvents () +{ + int x, y; +#ifdef INHERIT_LOCK_STATE + static int generation = 0; +#endif + +#ifdef AMOEBA +#define MAXEVENTS 32 +#define BUTTON_PRESS 0x1000 +#define MAP_BUTTON(ev,but) (((ev) == EV_ButtonPress) ? \ + ((but) | BUTTON_PRESS) : ((but) & ~BUTTON_PRESS)) +#define KEY_RELEASE 0x80 +#define MAP_KEY(ev, key) (((ev) == EV_KeyReleaseEvent) ? \ + ((key) | KEY_RELEASE) : ((key) & ~KEY_RELEASE)) + + register IOPEvent *e, *elast; + IOPEvent events[MAXEVENTS]; + int dx, dy, nevents; +#endif + + /* + * With INHERIT_LOCK_STATE defined, the initial state of CapsLock, NumLock + * and ScrollLock will be set to match that of the VT the server is + * running on. + */ +#ifdef INHERIT_LOCK_STATE + if (generation != serverGeneration) { + xEvent kevent; + DevicePtr pKeyboard = xf86Info.pKeyboard; + extern unsigned int xf86InitialCaps, xf86InitialNum, xf86InitialScroll; + + generation = serverGeneration; + kevent.u.keyButtonPointer.time = GetTimeInMillis(); + kevent.u.keyButtonPointer.rootX = 0; + kevent.u.keyButtonPointer.rootY = 0; + kevent.u.u.type = KeyPress; + + + if (xf86InitialCaps) { + kevent.u.u.detail = xf86InitialCaps; + (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1); + xf86InitialCaps = 0; + } + if (xf86InitialNum) { + kevent.u.u.detail = xf86InitialNum; + (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1); + xf86InitialNum = 0; + } + if (xf86InitialScroll) { + kevent.u.u.detail = xf86InitialScroll; + (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1); + xf86InitialScroll = 0; + } + } +#endif + +#ifdef AMOEBA + /* + * Get all events from the IOP server + */ + while ((nevents = AmoebaGetEvents(events, MAXEVENTS)) > 0) { + for (e = &events[0], elast = &events[nevents]; e < elast; e++) { + xf86Info.lastEventTime = e->time; + switch (e->type) { + case EV_PointerDelta: + if (e->x != 0 || e->y != 0) { + xf86PostMseEvent(&xf86Info.pMouse, 0, e->x, e->y); + } + break; + case EV_ButtonPress: + case EV_ButtonRelease: + xf86PostMseEvent(&xf86Info.pMouse, MAP_BUTTON(e->type, e->keyorbut), 0, 0); + break; + case EV_KeyPressEvent: + case EV_KeyReleaseEvent: + xf86PostKbdEvent(MAP_KEY(e->type, e->keyorbut)); + break; + default: + /* this shouldn't happen */ + ErrorF("stray event %d (%d,%d) %x\n", + e->type, e->x, e->y, e->keyorbut); + break; + } + } + } +#endif + + xf86Info.inputPending = FALSE; + +#ifdef XINPUT + xf86eqProcessInputEvents(); +#else + mieqProcessInputEvents(); +#endif + miPointerUpdate(); + + miPointerPosition(&x, &y); + xf86SetViewport(xf86Info.currentScreen, x, y); +} + + + +/* + * xf86PostKbdEvent -- + * Translate the raw hardware KbdEvent into an XEvent, and tell DIX + * about it. Scancode preprocessing and so on is done ... + * + * OS/2 specific xf86PostKbdEvent(key) has been moved to os-support/os2/os2_kbd.c + * as some things differ, and I did not want to scatter this routine with + * ifdefs further (hv). + */ + +#ifdef ASSUME_CUSTOM_KEYCODES +extern u_char SpecialServerMap[]; +#endif /* ASSUME_CUSTOM_KEYCODES */ + +#if !defined(__EMX__) +void +xf86PostKbdEvent(key) + unsigned key; +{ + int scanCode = (key & 0x7f); + int specialkey; + Bool down = (key & 0x80 ? FALSE : TRUE); + KeyClassRec *keyc = ((DeviceIntPtr)xf86Info.pKeyboard)->key; + Bool updateLeds = FALSE; + Bool UsePrefix = FALSE; + Bool Direction = FALSE; + xEvent kevent; + KeySym *keysym; + int keycode; + static int lockkeys = 0; +#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + static Bool first_time = TRUE; +#endif + +#if defined(CODRV_SUPPORT) + if (xf86Info.consType == CODRV011 || xf86Info.consType == CODRV01X) + scanCode = xf86CodrvMap[scanCode]; +#endif + +#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + if (first_time) + { + first_time = FALSE; + VTSwitchEnabled = (xf86Info.consType == SYSCONS) + || (xf86Info.consType == PCVT); + } +#endif + +#if defined (i386) && defined (SVR4) && !defined (PC98) + /* + * PANIX returns DICOP standards based keycodes in using 106jp + * keyboard. We need to remap some keys. + */ +#define KEY_P_UP 0x5A +#define KEY_P_PGUP 0x5B +#define KEY_P_LEFT 0x5C +#define KEY_P_BKSL 0x73 +#define KEY_P_YEN 0x7D +#define KEY_P_NFER 0x7B +#define KEY_P_XFER 0x79 + + if(xf86Info.panix106 == TRUE){ + switch (scanCode) { + /* case 0x78: scanCode = KEY_P_UP; break; not needed*/ + case 0x56: scanCode = KEY_P_BKSL; break; /* Backslash */ + case 0x5A: scanCode = KEY_P_NFER; break; /* No Kanji Transfer*/ + case 0x5B: scanCode = KEY_P_XFER; break; /* Kanji Tranfer */ + case 0x5C: scanCode = KEY_P_YEN; break; /* Yen curs pgup */ + case 0x6B: scanCode = KEY_P_LEFT; break; /* Cur Left */ + case 0x6F: scanCode = KEY_P_PGUP; break; /* Cur PageUp */ + case 0x72: scanCode = KEY_AltLang; break; /* AltLang(right) */ + case 0x73: scanCode = KEY_RCtrl; break; /* not needed */ + } + } +#endif /* i386 && SVR4 */ + +#ifndef ASSUME_CUSTOM_KEYCODES + /* + * First do some special scancode remapping ... + */ + if (xf86Info.scanPrefix == 0) { + + switch (scanCode) { + +#ifndef PC98 + case KEY_Prefix0: + case KEY_Prefix1: +#if defined(PCCONS_SUPPORT) || defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + if (xf86Info.consType == PCCONS || xf86Info.consType == SYSCONS + || xf86Info.consType == PCVT) { +#endif + xf86Info.scanPrefix = scanCode; /* special prefixes */ + return; +#if defined(PCCONS_SUPPORT) || defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + } + break; +#endif +#endif /* not PC98 */ + } +#ifndef PC98 + if (xf86Info.serverNumLock) { + if ((!xf86Info.numLock && ModifierDown(ShiftMask)) || + (xf86Info.numLock && !ModifierDown(ShiftMask))) { + /* + * Hardwired numlock handling ... (Some applications break if they have + * these keys double defined, like twm) + */ + switch (scanCode) { + case KEY_KP_7: scanCode = KEY_SN_KP_7; break; /* curs 7 */ + case KEY_KP_8: scanCode = KEY_SN_KP_8; break; /* curs 8 */ + case KEY_KP_9: scanCode = KEY_SN_KP_9; break; /* curs 9 */ + case KEY_KP_4: scanCode = KEY_SN_KP_4; break; /* curs 4 */ + case KEY_KP_5: scanCode = KEY_SN_KP_5; break; /* curs 5 */ + case KEY_KP_6: scanCode = KEY_SN_KP_6; break; /* curs 6 */ + case KEY_KP_1: scanCode = KEY_SN_KP_1; break; /* curs 1 */ + case KEY_KP_2: scanCode = KEY_SN_KP_2; break; /* curs 2 */ + case KEY_KP_3: scanCode = KEY_SN_KP_3; break; /* curs 3 */ + case KEY_KP_0: scanCode = KEY_SN_KP_0; break; /* curs 0 */ + case KEY_KP_Decimal: scanCode = KEY_SN_KP_Dec; break; /* curs decimal */ + } + } else { + switch (scanCode) { + case KEY_KP_7: scanCode = KEY_SN_KP_Home; break; /* curs home */ + case KEY_KP_8: scanCode = KEY_SN_KP_Up ; break; /* curs up */ + case KEY_KP_9: scanCode = KEY_SN_KP_Prior; break; /* curs pgup */ + case KEY_KP_4: scanCode = KEY_SN_KP_Left; break; /* curs left */ + case KEY_KP_5: scanCode = KEY_SN_KP_Begin; break; /* curs begin */ + case KEY_KP_6: scanCode = KEY_SN_KP_Right; break; /* curs right */ + case KEY_KP_1: scanCode = KEY_SN_KP_End; break; /* curs end */ + case KEY_KP_2: scanCode = KEY_SN_KP_Down; break; /* curs down */ + case KEY_KP_3: scanCode = KEY_SN_KP_Next; break; /* curs pgdn */ + case KEY_KP_0: scanCode = KEY_SN_KP_Ins; break; /* curs ins */ + case KEY_KP_Decimal: scanCode = KEY_SN_KP_Del; break; /* curs del */ + } + } + } +#endif /* not PC98 */ + } + +#ifndef PC98 + else if ( +#ifdef CSRG_BASED + (xf86Info.consType == PCCONS || xf86Info.consType == SYSCONS + || xf86Info.consType == PCVT) && +#endif + (xf86Info.scanPrefix == KEY_Prefix0)) { + xf86Info.scanPrefix = 0; + + switch (scanCode) { + case KEY_KP_7: scanCode = KEY_Home; break; /* curs home */ + case KEY_KP_8: scanCode = KEY_Up; break; /* curs up */ + case KEY_KP_9: scanCode = KEY_PgUp; break; /* curs pgup */ + case KEY_KP_4: scanCode = KEY_Left; break; /* curs left */ + case KEY_KP_5: scanCode = KEY_Begin; break; /* curs begin */ + case KEY_KP_6: scanCode = KEY_Right; break; /* curs right */ + case KEY_KP_1: scanCode = KEY_End; break; /* curs end */ + case KEY_KP_2: scanCode = KEY_Down; break; /* curs down */ + case KEY_KP_3: scanCode = KEY_PgDown; break; /* curs pgdown */ + case KEY_KP_0: scanCode = KEY_Insert; break; /* curs insert */ + case KEY_KP_Decimal: scanCode = KEY_Delete; break; /* curs delete */ + case KEY_Enter: scanCode = KEY_KP_Enter; break; /* keypad enter */ + case KEY_LCtrl: scanCode = KEY_RCtrl; break; /* right ctrl */ + case KEY_KP_Multiply: scanCode = KEY_Print; break; /* print */ + case KEY_Slash: scanCode = KEY_KP_Divide; break; /* keyp divide */ + case KEY_Alt: scanCode = KEY_AltLang; break; /* right alt */ + case KEY_ScrollLock: scanCode = KEY_Break; break; /* curs break */ + case 0x5b: scanCode = KEY_LMeta; break; + case 0x5c: scanCode = KEY_RMeta; break; + case 0x5d: scanCode = KEY_Menu; break; + case KEY_F3: scanCode = KEY_F13; break; + case KEY_F4: scanCode = KEY_F14; break; + case KEY_F5: scanCode = KEY_F15; break; + case KEY_F6: scanCode = KEY_F16; break; + case KEY_F7: scanCode = KEY_F17; break; + case KEY_KP_Plus: scanCode = KEY_KP_DEC; break; + /* + * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) + */ + default: + return; /* skip illegal */ + } + } + + else if (xf86Info.scanPrefix == KEY_Prefix1) + { + xf86Info.scanPrefix = (scanCode == KEY_LCtrl) ? KEY_LCtrl : 0; + return; + } + + else if (xf86Info.scanPrefix == KEY_LCtrl) + { + xf86Info.scanPrefix = 0; + if (scanCode != KEY_NumLock) return; + scanCode = KEY_Pause; /* pause */ + } +#endif /* not PC98 */ +#endif /* !ASSUME_CUSTOM_KEYCODES */ + + /* + * and now get some special keysequences + */ + +#ifdef ASSUME_CUSTOM_KEYCODES + specialkey = SpecialServerMap[scanCode]; +#else /* ASSUME_CUSTOM_KEYCODES */ + specialkey = scanCode; +#endif /* ASSUME_CUSTOM_KEYCODES */ + + if ((ModifierDown(ControlMask | AltMask)) || + (ModifierDown(ControlMask | AltLangMask))) + { + + switch (specialkey) { + + case KEY_BackSpace: + if (!xf86Info.dontZap) { +#ifdef XFreeXDGA + if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectGraphics) + break; +#endif + GiveUp(0); + } + break; + + /* + * The idea here is to pass the scancode down to a list of + * registered routines. There should be some standard conventions + * for processing certain keys. + */ + case KEY_KP_Minus: /* Keypad - */ + if (!xf86Info.dontZoom) { + if (down) xf86ZoomViewport(xf86Info.currentScreen, -1); + return; + } + break; + + case KEY_KP_Plus: /* Keypad + */ + if (!xf86Info.dontZoom) { + if (down) xf86ZoomViewport(xf86Info.currentScreen, 1); + return; + } + break; + +#if defined(linux) || (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT))) || defined(SCO) + /* + * Under Linux, the raw keycodes are consumed before the kernel + * does any processing on them, so we must emulate the vt switching + * we want ourselves. + */ + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + if (VTSwitchEnabled && !xf86Info.vtSysreq +#if (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT))) + && (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) +#endif + ) + { + if (down) +#ifdef SCO325 + ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F1); +#else + ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F1 + 1); +#endif + return; + } + break; + case KEY_F11: + case KEY_F12: + if (VTSwitchEnabled && !xf86Info.vtSysreq +#if (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT))) + && (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) +#endif + ) + { + if (down) +#ifdef SCO325 + ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F11 + 10); +#else + ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F11 + 11); +#endif + return; + } + break; +#endif /* linux || BSD with VTs */ + + /* just worth mentioning here: any 386bsd keyboard driver + * (pccons.c or co_kbd.c) catches CTRL-ALT-DEL and CTRL-ALT-ESC + * before any application (e.g. XF86) will see it + * OBS: syscons does not, nor does pcvt ! + */ + } + } + + /* + * Start of actual Solaris VT switching code. + * This should pretty much emulate standard SVR4 switching keys. + * + * DWH 12/2/93 + */ + +#ifdef USE_VT_SYSREQ + if (VTSwitchEnabled && xf86Info.vtSysreq) + { + switch (specialkey) + { + /* + * syscons on *BSD doesn't have a VT #0 -- don't think Linux does + * either + */ +#if defined (sun) && defined (i386) && defined (SVR4) + case KEY_H: + if (VTSysreqToggle && down) + { + ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0); + VTSysreqToggle = 0; + return; + } + break; + + /* + * Yah, I know the N, and P keys seem backwards, however that's + * how they work under Solaris + * XXXX N means go to next active VT not necessarily vtno+1 (or vtno-1) + */ + + case KEY_N: + if (VTSysreqToggle && down) + { + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno - 1 ) < 0) + ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); + VTSysreqToggle = FALSE; + return; + } + break; + + case KEY_P: + if (VTSysreqToggle && down) + { + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1 ) < 0) + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0) + ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); + VTSysreqToggle = FALSE; + return; + } + break; +#endif + + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + if (VTSysreqToggle && down) + { + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey-KEY_F1 + 1) < 0) + ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); + VTSysreqToggle = FALSE; + return; + } + break; + + case KEY_F11: + case KEY_F12: + if (VTSysreqToggle && down) + { + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey-KEY_F11 + 11) < 0) + ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); + VTSysreqToggle = FALSE; + return; + } + break; + + /* Ignore these keys -- ie don't let them cancel an alt-sysreq */ + case KEY_Alt: +#ifndef PC98 + case KEY_AltLang: +#endif /* not PC98 */ + break; + +#ifndef PC98 + case KEY_SysReqest: + if (down && (ModifierDown(AltMask) || ModifierDown(AltLangMask))) + VTSysreqToggle = TRUE; + break; +#endif /* not PC98 */ + + default: + if (VTSysreqToggle) + { + /* + * We only land here when Alt-SysReq is followed by a + * non-switching key. + */ + VTSysreqToggle = FALSE; + + } + } + } + +#endif /* USE_VT_SYSREQ */ + +#ifdef SCO + /* + * With the console in raw mode, SCO will not switch consoles, + * you get around this by activating the next console along, if + * this fails then go back to console 0, if there is only one + * then it doesn't matter, switching to yourself is a nop as far + * as the console driver is concerned. + * We could do something similar to linux here but SCO ODT uses + * Ctrl-PrintScrn, so why change? + */ + if (specialkey == KEY_Print && ModifierDown(ControlMask)) { + if (down) + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1) < 0) + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0) + ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); + return; + } +#endif /* SCO */ + + /* + * Now map the scancodes to real X-keycodes ... + */ + keycode = scanCode + MIN_KEYCODE; + keysym = (keyc->curKeySyms.map + + keyc->curKeySyms.mapWidth * + (keycode - keyc->curKeySyms.minKeyCode)); +#ifdef XKB + if (noXkbExtension) { +#endif + /* + * Filter autorepeated caps/num/scroll lock keycodes. + */ +#define CAPSFLAG 0x01 +#define NUMFLAG 0x02 +#define SCROLLFLAG 0x04 +#define MODEFLAG 0x08 + if( down ) { + switch( keysym[0] ) { + case XK_Caps_Lock : + if (lockkeys & CAPSFLAG) + return; + else + lockkeys |= CAPSFLAG; + break; + + case XK_Num_Lock : + if (lockkeys & NUMFLAG) + return; + else + lockkeys |= NUMFLAG; + break; + + case XK_Scroll_Lock : + if (lockkeys & SCROLLFLAG) + return; + else + lockkeys |= SCROLLFLAG; + break; + } + if (keysym[1] == XF86XK_ModeLock) + { + if (lockkeys & MODEFLAG) + return; + else + lockkeys |= MODEFLAG; + } + + } + else { + switch( keysym[0] ) { + case XK_Caps_Lock : + lockkeys &= ~CAPSFLAG; + break; + + case XK_Num_Lock : + lockkeys &= ~NUMFLAG; + break; + + case XK_Scroll_Lock : + lockkeys &= ~SCROLLFLAG; + break; + } + if (keysym[1] == XF86XK_ModeLock) + lockkeys &= ~MODEFLAG; + } + + /* + * LockKey special handling: + * ignore releases, toggle on & off on presses. + * Don't deal with the Caps_Lock keysym directly, but check the lock modifier + */ +#ifndef PC98 + if (keyc->modifierMap[keycode] & LockMask || + keysym[0] == XK_Scroll_Lock || + keysym[1] == XF86XK_ModeLock || + keysym[0] == XK_Num_Lock) + { + Bool flag; + + if (!down) return; + if (KeyPressed(keycode)) { + down = !down; + flag = FALSE; + } + else + flag = TRUE; + + if (keyc->modifierMap[keycode] & LockMask) xf86Info.capsLock = flag; + if (keysym[0] == XK_Num_Lock) xf86Info.numLock = flag; + if (keysym[0] == XK_Scroll_Lock) xf86Info.scrollLock = flag; + if (keysym[1] == XF86XK_ModeLock) xf86Info.modeSwitchLock = flag; + updateLeds = TRUE; + } +#endif /* not PC98 */ + +#ifndef ASSUME_CUSTOM_KEYCODES + /* + * normal, non-keypad keys + */ + if (scanCode < KEY_KP_7 || scanCode > KEY_KP_Decimal) { +#if !defined(CSRG_BASED) && !defined(MACH386) && !defined(MINIX) && !defined(__OSF__) + /* + * magic ALT_L key on AT84 keyboards for multilingual support + */ + if (xf86Info.kbdType == KB_84 && + ModifierDown(AltMask) && + keysym[2] != NoSymbol) + { + UsePrefix = TRUE; + Direction = TRUE; + } +#endif /* !CSRG_BASED && !MACH386 && !MINIX && !__OSF__ */ + } +#endif /* !ASSUME_CUSTOM_KEYCODES */ + if (updateLeds) xf86KbdLeds(); +#ifdef XKB + } +#endif + + /* + * check for an autorepeat-event + */ + if ((down && KeyPressed(keycode)) && + (xf86Info.autoRepeat != AutoRepeatModeOn || keyc->modifierMap[keycode])) + return; + + xf86Info.lastEventTime = kevent.u.keyButtonPointer.time = GetTimeInMillis(); + /* + * And now send these prefixes ... + * NOTE: There cannot be multiple Mode_Switch keys !!!! + */ + if (UsePrefix) + { + ENQUEUE(&kevent, + keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], + (Direction ? KeyPress : KeyRelease), + XE_KEYBOARD); + ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD); + ENQUEUE(&kevent, + keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], + (Direction ? KeyRelease : KeyPress), + XE_KEYBOARD); + } + else + { +#ifdef XFreeXDGA + if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectKeyb) { + XF86DirectVideoKeyEvent(&kevent, keycode, (down ? KeyPress : KeyRelease)); + } else +#endif + { + ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD); + + } + } +} +#endif /* !__EMX__ */ + + +static CARD32 +buttonTimer(timer, now, arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +{ + MouseDevPtr priv = MOUSE_DEV((DeviceIntPtr) arg); + + xf86PostMseEvent(((DeviceIntPtr) arg), priv->truebuttons, 0, 0); + return(0); +} + + +/* + * xf86PostMseEvent -- + * Translate the raw hardware MseEvent into an XEvent(s), and tell DIX + * about it. Perform a 3Button emulation if required. + */ + +void +xf86PostMseEvent(device, buttons, dx, dy) + DeviceIntPtr device; + int buttons, dx, dy; +{ + static OsTimerPtr timer = NULL; + MouseDevPtr private = MOUSE_DEV(device); + int id, change; + int truebuttons; + xEvent mevent[2]; +#ifdef XINPUT + deviceKeyButtonPointer *xev = (deviceKeyButtonPointer *) mevent; + deviceValuator *xv = (deviceValuator *) (xev+1); + int is_pointer; /* the mouse is the pointer ? */ +#endif + +#ifdef AMOEBA + int pressed; + + pressed = ((buttons & BUTTON_PRESS) != 0); + buttons &= ~BUTTON_PRESS; +#endif + +#ifdef XINPUT + is_pointer = xf86IsCorePointer(device); + + if (!is_pointer) { + xev->time = xf86Info.lastEventTime = GetTimeInMillis(); + } + else +#endif + xf86Info.lastEventTime = mevent->u.keyButtonPointer.time = GetTimeInMillis(); + + truebuttons = buttons; + if (private->mseType == P_MMHIT) + buttons = reverseBits(hitachMap, buttons); + else + buttons = reverseBits(reverseMap, buttons); + + if (dx || dy) { + + /* + * accelerate the baby now if sqrt(dx*dx + dy*dy) > threshold ! + * but do some simpler arithmetic here... + */ + if ((abs(dx) + abs(dy)) >= private->threshold) { + dx = (dx * private->num) / private->den; + dy = (dy * private->num)/ private->den; + } + +#ifdef XINPUT + if (is_pointer) { +#endif +#ifdef XFreeXDGA + if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectMouse) { + XF86DirectVideoMoveMouse(dx, dy, mevent->u.keyButtonPointer.time); + } else +#endif + { + MOVEPOINTER(dx, dy, mevent->u.keyButtonPointer.time); + } +#ifdef XINPUT + } + else { + xev->type = DeviceMotionNotify; + xev->deviceid = device->id | MORE_EVENTS; + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->num_valuators = 2; + xv->first_valuator = 0; + xv->device_state = 0; + xv->valuator0 = dx; + xv->valuator1 = dy; + xf86eqEnqueue(mevent); + } +#endif + } + + if (private->emulate3Buttons) + { + + /* + * Hack to operate the middle button even with Emulate3Buttons set. + * Modifying the state table to keep track of the middle button state + * would nearly double its size, so I'll stick with this fix. - TJW + */ + if (private->mseType == P_MMHIT) + change = buttons ^ reverseBits(hitachMap, private->lastButtons); + else + change = buttons ^ reverseBits(reverseMap, private->lastButtons); + if (change & 02) + { +#ifdef XINPUT + if (xf86CheckButton(2, (buttons & 02))) { +#endif + ENQUEUE(mevent, + 2, (buttons & 02) ? ButtonPress : ButtonRelease, + XE_POINTER); +#ifdef XINPUT + } +#endif + } + + /* + * emulate the third button by the other two + */ + if ((id = stateTab[buttons + private->emulateState][0]) != 0) + { +#ifdef XINPUT + if (is_pointer) { + if (xf86CheckButton(abs(id), (id >= 0))) { +#endif + ENQUEUE(mevent, + abs(id), (id < 0 ? ButtonRelease : ButtonPress), + XE_POINTER); +#ifdef XINPUT + } + } + else { + xev->type = (id < 0 ? DeviceButtonRelease : DeviceButtonPress); + xev->deviceid = device->id | MORE_EVENTS; + xev->detail = abs(id); + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->num_valuators = 0; + xv->device_state = 0; + xf86eqEnqueue(mevent); + } +#endif + } + + if ((id = stateTab[buttons + private->emulateState][1]) != 0) + { +#ifdef XINPUT + if (is_pointer) { + if (xf86CheckButton(abs(id), (id >= 0))) { +#endif + ENQUEUE(mevent, + abs(id), (id < 0 ? ButtonRelease : ButtonPress), + XE_POINTER); +#ifdef XINPUT + } + } + else { + xev->type = (id < 0 ? DeviceButtonRelease : DeviceButtonPress); + xev->deviceid = device->id | MORE_EVENTS; + xev->detail = abs(id); + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->num_valuators = 0; + xv->device_state = 0; + xf86eqEnqueue(mevent); + } +#endif + } + + private->emulateState = stateTab[buttons + private->emulateState][2]; + if (stateTab[buttons + private->emulateState][0] || + stateTab[buttons + private->emulateState][1]) + { + private->truebuttons = truebuttons; + timer = TimerSet(timer, 0, private->emulate3Timeout, buttonTimer, + (pointer)device); + } + else + { + if (timer) + { + TimerFree(timer); + timer = NULL; + } + } + } + else + { +#ifdef AMOEBA + if (truebuttons != 0) { +#ifdef XINPUT + if (is_pointer) { + if (xf86CheckButton(truebuttons)) { +#endif + ENQUEUE(mevent, + truebuttons, (pressed ? ButtonPress : ButtonRelease), + XE_POINTER); +#ifdef XINPUT + } + } + else { + xev->type = pressed ? DeviceButtonPress : DeviceButtonRelease; + xev->deviceid = device->id | MORE_EVENTS; + xev->detail = truebuttons; + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->num_valuators = 0; + xv->device_state = 0; + xf86eqEnqueue(mevent); + } +#endif + } +#else + /* + * real three button event + * Note that xf86Info.lastButtons has the hardware button mapping which + * is the reverse of the button mapping reported to the server. + */ + if (private->mseType == P_MMHIT) + change = buttons ^ reverseBits(hitachMap, private->lastButtons); + else + change = buttons ^ reverseBits(reverseMap, private->lastButtons); + while (change) + { + id = ffs(change); + change &= ~(1 << (id-1)); +#ifdef XINPUT + if (is_pointer) { + if (xf86CheckButton(id, (buttons&(1<<(id-1))))) { +#endif + ENQUEUE(mevent, + id, (buttons&(1<<(id-1)))? ButtonPress : ButtonRelease, + XE_POINTER); +#ifdef XINPUT + } + } + else { + xev->type = (buttons&(1<<(id-1)))? DeviceButtonPress : DeviceButtonRelease; + xev->deviceid = device->id | MORE_EVENTS; + xev->detail = id; + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->num_valuators = 0; + xv->device_state = 0; + xf86eqEnqueue(mevent); + } +#endif + } +#endif + } + private->lastButtons = truebuttons; +} + + + +/* + * xf86Block -- + * Os block handler. + */ + +/* ARGSUSED */ +void +xf86Block(blockData, pTimeout, pReadmask) + pointer blockData; + OSTimePtr pTimeout; + pointer pReadmask; +{ +} + + +#ifndef AMOEBA + +/* + * xf86Wakeup -- + * Os wakeup handler. + */ + +/* ARGSUSED */ +void +xf86Wakeup(blockData, err, pReadmask) + pointer blockData; + int err; + pointer pReadmask; +{ + +#ifndef __EMX__ +#ifdef __OSF__ + fd_set kbdDevices; + fd_set mseDevices; +#endif /* __OSF__ */ + fd_set* LastSelectMask = (fd_set*)pReadmask; + fd_set devicesWithInput; + + if ((int)err >= 0) { + XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices); +#ifdef __OSF__ + /* + * Until the two devices are made nonblock on read, we have to do this. + */ + + MASKANDSETBITS(devicesWithInput, pReadmask, EnabledDevices); + + CLEARBITS(kbdDevices); + BITSET(kbdDevices, xf86Info.consoleFd); + MASKANDSETBITS(kbdDevices, kbdDevices, devicesWithInput); + + CLEARBITS(mseDevices); + BITSET(mseDevices, xf86Info.mouseDev->mseFd); + MASKANDSETBITS(mseDevices, mseDevices, devicesWithInput); + + if (ANYSET(kbdDevices) || xf86Info.kbdRate) + (xf86Info.kbdEvents)(ANYSET(kbdDevices)); + if (ANYSET(mseDevices)) + (xf86Info.mouseDev->mseEvents)(1); + +#else + if (XFD_ANYSET(&devicesWithInput)) + { + (xf86Info.kbdEvents)(); + (xf86Info.mouseDev->mseEvents)(xf86Info.mouseDev); + } +#endif /* __OSF__ */ + } +#else /* __EMX__ */ + + (xf86Info.kbdEvents)(); /* Under OS/2, always call */ + (xf86Info.mouseDev->mseEvents)(xf86Info.mouseDev); + +#endif /* __EMX__ */ + +#if defined(XQUEUE) && !defined(XQUEUE_ASYNC) + /* This could be done more cleanly */ + if (xf86Info.mouseDev->xqueSema && xf86Info.mouseDev->xquePending) + xf86XqueRequest(); +#endif + + if (xf86VTSwitchPending()) xf86VTSwitch(); + + if (xf86Info.inputPending) ProcessInputEvents(); +} + +#endif /* AMOEBA */ + + +/* + * xf86SigHandler -- + * Catch unexpected signals and exit cleanly. + */ +void +xf86SigHandler(signo) + int signo; +{ + signal(signo,SIG_IGN); + xf86Info.caughtSignal = TRUE; + FatalError("Caught signal %d. Server aborting\n", signo); +} + +/* + * xf86VTSwitch -- + * Handle requests for switching the vt. + */ +static void +xf86VTSwitch() +{ + int j; + +#ifdef XFreeXDGA + /* + * Not ideal, but until someone adds DGA events to the DGA client we + * should protect the machine + */ + if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectGraphics) { + xf86Info.vtRequestsPending = FALSE; + return; + } +#endif + if (xf86VTSema) { + for (j = 0; j < screenInfo.numScreens; j++) + (XF86SCRNINFO(screenInfo.screens[j])->EnterLeaveVT)(LEAVE, j); + +#ifndef __EMX__ + DisableDevice((DeviceIntPtr)xf86Info.pKeyboard); + DisableDevice((DeviceIntPtr)xf86Info.pMouse); +#endif + + if (!xf86VTSwitchAway()) { + /* + * switch failed + */ + + for (j = 0; j < screenInfo.numScreens; j++) + (XF86SCRNINFO(screenInfo.screens[j])->EnterLeaveVT)(ENTER, j); + SaveScreens(SCREEN_SAVER_FORCER,ScreenSaverReset); +#ifdef DPMSExtension + if (DPMSEnabled) + DPMSSet(DPMSModeOn); +#endif + +#ifndef __EMX__ + EnableDevice((DeviceIntPtr)xf86Info.pKeyboard); + EnableDevice((DeviceIntPtr)xf86Info.pMouse); +#endif + + } else { + xf86VTSema = FALSE; + } + } else { + if (!xf86VTSwitchTo()) return; + + xf86VTSema = TRUE; + for (j = 0; j < screenInfo.numScreens; j++) + (XF86SCRNINFO(screenInfo.screens[j])->EnterLeaveVT)(ENTER, j); + + /* Turn screen saver off when switching back */ + SaveScreens(SCREEN_SAVER_FORCER,ScreenSaverReset); +#ifdef DPMSExtension + if (DPMSEnabled) + DPMSSet(DPMSModeOn); +#endif + +#ifndef __EMX__ + EnableDevice((DeviceIntPtr)xf86Info.pKeyboard); + EnableDevice((DeviceIntPtr)xf86Info.pMouse); +#endif + + } +} + +#ifdef XTESTEXT1 + +void +XTestGetPointerPos(fmousex, fmousey) + short *fmousex; + short *fmousey; +{ + int x,y; + + miPointerPosition(&x, &y); + *fmousex = x; + *fmousey = y; +} + + + +void +XTestJumpPointer(jx, jy, dev_type) + int jx; + int jy; + int dev_type; +{ + miPointerAbsoluteCursor(jx, jy, GetTimeInMillis() ); +} + + + +void +XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey) + int dev_type; + int keycode; + int keystate; + int mousex; + int mousey; +{ + xEvent tevent; + + tevent.u.u.type = (dev_type == XE_POINTER) ? + (keystate == XTestKEY_UP) ? ButtonRelease : ButtonPress : + (keystate == XTestKEY_UP) ? KeyRelease : KeyPress; + tevent.u.u.detail = keycode; + tevent.u.keyButtonPointer.rootX = mousex; + tevent.u.keyButtonPointer.rootY = mousey; + tevent.u.keyButtonPointer.time = xf86Info.lastEventTime = GetTimeInMillis(); +#ifdef XINPUT + xf86eqEnqueue(&tevent); +#else + mieqEnqueue(&tevent); +#endif + xf86Info.inputPending = TRUE; /* virtual event */ +} + +#endif /* XTESTEXT1 */ + + +#ifdef XFreeXDGA +static void +XF86DirectVideoMoveMouse(x, y, mtime) + int x; + int y; + CARD32 mtime; +{ + xEvent xE; + + xE.u.u.type = MotionNotify; + xE.u.keyButtonPointer.time = xf86Info.lastEventTime = mtime; + xf86Info.lastEventTime = mtime; + + + xE.u.keyButtonPointer.eventY = x; + xE.u.keyButtonPointer.eventY = y; + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + + if (((DeviceIntPtr)(xf86Info.pMouse))->grab) + DeliverGrabbedEvent(&xE, (xf86Info.pMouse), FALSE, 1); + else + DeliverDeviceEvents(GetSpriteWindow(), &xE, NullGrab, NullWindow, + (xf86Info.pMouse), 1); +} + +static void +XF86DirectVideoKeyEvent(xE, keycode, etype) +xEvent *xE; +int keycode; +int etype; +{ + DeviceIntPtr keybd = (DeviceIntPtr)xf86Info.pKeyboard; + KeyClassPtr keyc = keybd->key; + BYTE *kptr; + + kptr = &keyc->down[keycode >> 3]; + xE->u.u.type = etype; + xE->u.u.detail = keycode; + + /* clear the keypress state */ + if (etype == KeyPress) { + *kptr &= ~(1 << (keycode & 7)); + } + keybd->public.processInputProc(xE, keybd, 1); +} +#endif diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c new file mode 100644 index 000000000..864933a84 --- /dev/null +++ b/hw/xfree86/common/xf86Init.c @@ -0,0 +1,834 @@ +/* + * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Init.c,v 3.66.2.2 1997/06/29 08:43:36 dawes Exp $ + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + */ +/* $Xorg: xf86Init.c,v 1.3 2000/08/17 19:50:29 cpqbld Exp $ */ + +#ifndef X_NOT_STDC_ENV +#include +#else +extern int atoi(); +#endif + +#define NEED_EVENTS +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "input.h" +#include "servermd.h" +#include "scrnintstr.h" +#include "site.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "xf86Version.h" +#include "mipointer.h" + +#ifdef XINPUT +#include "XI.h" +#include "XIproto.h" +#include "xf86_Config.h" +#include "xf86Xinput.h" +#else +#include "inputstr.h" +#endif + +#include "opaque.h" + +#ifdef XTESTEXT1 +#include "atKeynames.h" +extern int xtest_command_key; +#endif /* XTESTEXT1 */ + +#ifdef __EMX__ +#define seteuid(x) /*nothing*/ +#define setruid(x) /*nothing*/ +#endif + +/* xf86Exiting is set while the screen is shutting down (even on a reset) */ +Bool xf86Exiting = FALSE; +Bool xf86Resetting = FALSE; +Bool xf86ProbeFailed = TRUE; +Bool xf86FlipPixels = FALSE; +#ifdef XF86VIDMODE +Bool xf86VidModeEnabled = TRUE; +Bool xf86VidModeAllowNonLocal = FALSE; +#endif +#ifdef XF86MISC +Bool xf86MiscModInDevEnabled = TRUE; +Bool xf86MiscModInDevAllowNonLocal = FALSE; +#endif +Bool xf86AllowMouseOpenFail = FALSE; +PciProbeType xf86PCIFlags = PCIProbe1; +Bool xf86ScreensOpen = FALSE; +int xf86Verbose = 1; +Bool xf86fpFlag = FALSE; +Bool xf86coFlag = FALSE; +Bool xf86sFlag = FALSE; +Bool xf86ProbeOnly = FALSE; +char xf86ConfigFile[PATH_MAX] = ""; +int xf86bpp = -1; +xrgb xf86weight = { 0, 0, 0 } ; /* RGB weighting at 16 bpp */ +double xf86rGamma=1.0, xf86gGamma=1.0, xf86bGamma=1.0; +unsigned char xf86rGammaMap[256], xf86gGammaMap[256], xf86bGammaMap[256]; +char *xf86ServerName = NULL; +Bool xf86BestRefresh = FALSE; + +int vgaIOBase = 0x3d0; +int vgaCRIndex = 0x3d4; +int vgaCRReg = 0x3d5; + +static void xf86PrintBanner( +#if NeedFunctionPrototypes + void +#endif + ); +static void xf86PrintConfig( +#if NeedFunctionPrototypes + void +#endif + ); +#ifdef DO_CHECK_BETA +void xf86CheckBeta( +#if NeedFunctionPrototypes + int, + char * +#endif + ); +static int extraDays = 0; +static char *expKey = NULL; +#endif + +extern ScrnInfoPtr xf86Screens[]; +extern int xf86MaxScreens; +extern double pow(); +#ifdef USE_XF86_SERVERLOCK +extern void xf86UnlockServer(); +#endif +#ifdef __EMX__ +extern void os2ServerVideoAccess(); +#endif + +xf86InfoRec xf86Info; +int xf86ScreenIndex; + +/* + * InitOutput -- + * Initialize screenInfo for all actually accessible framebuffers. + * That includes vt-manager setup, querying all possible devices and + * collecting the pixmap formats. + */ + +void +InitOutput(pScreenInfo, argc, argv) + ScreenInfo *pScreenInfo; + int argc; + char **argv; +{ + int i, j, scr_index; + static int numFormats = 0; + static PixmapFormatRec formats[MAXFORMATS]; + static unsigned long generation = 0; + int any_screens = 0; + +#ifdef __EMX__ + os2ServerVideoAccess(); /* See if we have access to the screen before doing anything */ +#endif + + if (serverGeneration == 1) { + + if ((xf86ServerName = strrchr(argv[0], '/')) != 0) + xf86ServerName++; + else + xf86ServerName = argv[0]; + +#ifdef DO_CHECK_BETA + xf86CheckBeta(extraDays, expKey); +#endif + + xf86PrintBanner(); + + xf86PrintConfig(); + + xf86OpenConsole(); + +#if !defined(AMOEBA) && !defined(MINIX) + /* + * If VTInit was set, run that program with consoleFd as stdin and stdout + */ + + if (xf86Info.vtinit) { + switch(fork()) { + case -1: + FatalError("Fork failed for VTInit (%s)\n", strerror(errno)); + break; + case 0: /* child */ + setuid(getuid()); + /* set stdin, stdout to the consoleFd */ + for (i = 0; i < 2; i++) { + if (xf86Info.consoleFd != i) { + close(i); + dup(xf86Info.consoleFd); + } + } + execl("/bin/sh", "sh", "-c", xf86Info.vtinit, NULL); + ErrorF("Warning: exec of /bin/sh failed for VTInit (%s)\n", + strerror(errno)); + exit(255); + break; + default: /* parent */ + wait(NULL); + } + } +#endif /* !AMOEBA && !MINIX */ + + /* Do this after XF86Config is read (it's normally in OsInit()) */ + OsInitColors(); + + for (i=0; i<256; i++) { + xf86rGammaMap[i] = (int)(pow(i/255.0,xf86rGamma)*255.0+0.5); + xf86gGammaMap[i] = (int)(pow(i/255.0,xf86gGamma)*255.0+0.5); + xf86bGammaMap[i] = (int)(pow(i/255.0,xf86bGamma)*255.0+0.5); + } + + xf86Config(TRUE); /* Probe displays, and resolve modes */ + +#ifdef XKB + xf86InitXkb(); +#endif + + /* + * collect all possible formats + */ + formats[0].depth = 1; + formats[0].bitsPerPixel = 1; + formats[0].scanlinePad = BITMAP_SCANLINE_PAD; + numFormats++; + + for ( i=0; + i < xf86MaxScreens && xf86Screens[i] && xf86Screens[i]->configured; + i++ ) + { + /* + * At least one probe function succeeded. + */ + any_screens = 1; + + /* + * add new pixmap format + */ + for ( j=0; j < numFormats; j++ ) { + + if (formats[j].depth == xf86Screens[i]->depth && + formats[j].bitsPerPixel == xf86Screens[i]->bitsPerPixel) + break; /* found */ + } + + if (j == numFormats) { /* not already there */ + formats[j].depth = xf86Screens[i]->depth; + formats[j].bitsPerPixel = xf86Screens[i]->bitsPerPixel; + formats[j].scanlinePad = BITMAP_SCANLINE_PAD; + numFormats++; + if ( numFormats > MAXFORMATS ) + FatalError( "Too many pixmap formats! Exiting\n" ); + } + } + if (!any_screens) + if (xf86ProbeFailed) + ErrorF("\n *** None of the configured devices were detected.***\n\n"); + else + ErrorF( + "\n *** A configured device found, but display modes could not be resolved.***\n\n"); + if (xf86ProbeOnly) + { + xf86VTSema = FALSE; + AbortDDX(); + fflush(stderr); + exit(0); + } + } + else { + /* + * serverGeneration != 1; some OSs have to do things here, too. + */ + xf86OpenConsole(); + } + + /* + * Install signal handler for unexpected signals + */ + if (!xf86Info.notrapSignals) + { + xf86Info.caughtSignal=FALSE; + signal(SIGSEGV,xf86SigHandler); + signal(SIGILL,xf86SigHandler); +#ifdef SIGEMT + signal(SIGEMT,xf86SigHandler); +#endif + signal(SIGFPE,xf86SigHandler); +#ifdef SIGBUS + signal(SIGBUS,xf86SigHandler); +#endif +#ifdef SIGSYS + signal(SIGSYS,xf86SigHandler); +#endif +#ifdef SIGXCPU + signal(SIGXCPU,xf86SigHandler); +#endif +#ifdef SIGXFSZ + signal(SIGXFSZ,xf86SigHandler); +#endif + } + + + /* + * Use the previous collected parts to setup pScreenInfo + */ + pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + pScreenInfo->numPixmapFormats = numFormats; + for ( i=0; i < numFormats; i++ ) pScreenInfo->formats[i] = formats[i]; + + if (generation != serverGeneration) + { + xf86ScreenIndex = AllocateScreenPrivateIndex(); + generation = serverGeneration; + } + + + for ( i=0; + i < xf86MaxScreens && xf86Screens[i] && xf86Screens[i]->configured; + i++ ) + { + /* + * On a server-reset, we have explicitely to remap all stuff ... + * (At startuptime this is implicitely done by probing the device + */ + if (serverGeneration != 1) + { + xf86Resetting = TRUE; + xf86Exiting = FALSE; +#ifdef HAS_USL_VTS + if (!xf86VTSema) + ioctl(xf86Info.consoleFd,VT_RELDISP,VT_ACKACQ); +#endif + xf86VTSema = TRUE; + (xf86Screens[i]->EnterLeaveVT)(ENTER, i); + xf86Resetting = FALSE; + } +#ifdef SCO + else { + /* + * Under SCO we must ack that we got the console at startup, + * I think this is the safest way to assure it + */ + static int once = 1; + if (once) { + once = 0; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) + ErrorF("VT_ACKACQ failed"); + } + } +#endif /* SCO */ + scr_index = AddScreen(xf86Screens[i]->Init, argc, argv); + if (scr_index > -1) + { + screenInfo.screens[scr_index]->devPrivates[xf86ScreenIndex].ptr + = (pointer)xf86Screens[i]; + } + + /* + * Here we have to let the driver getting access of the VT. Note that + * this doesn't mean that the graphics board may access automatically + * the monitor. If the monitor is shared this is done in xf86CrossScreen! + */ + if (!xf86Info.sharedMonitor) (xf86Screens[i]->EnterLeaveMonitor)(ENTER); + } + +#ifndef AMOEBA + RegisterBlockAndWakeupHandlers(xf86Block, xf86Wakeup, (void *)0); +#endif +} + + +/* + * InitInput -- + * Initialize all supported input devices...what else is there + * besides pointer and keyboard? Two DeviceRec's are allocated and + * registered as the system pointer and keyboard devices. + */ + +void +InitInput(argc, argv) + int argc; + char **argv; +{ + xf86Info.vtRequestsPending = FALSE; + xf86Info.inputPending = FALSE; +#ifdef XTESTEXT1 + xtest_command_key = KEY_Begin + MIN_KEYCODE; +#endif /* XTESTEXT1 */ + + xf86Info.pKeyboard = AddInputDevice(xf86Info.kbdProc, TRUE); + xf86Info.pMouse = AddInputDevice(xf86Info.mouseDev->mseProc, TRUE); + RegisterKeyboardDevice((DevicePtr)xf86Info.pKeyboard); + RegisterPointerDevice((DevicePtr)xf86Info.pMouse); + +#ifdef XINPUT + (xf86Info.pMouse)->public.devicePrivate = xf86Info.mouseLocal; +#if 0 /* Is this needed?? */ + ((LocalDevicePtr) xf86Info.mouseLocal)->dev = xf86Info.pMouse; +#endif +#else + (xf86Info.pMouse)->public.devicePrivate = (pointer) xf86Info.mouseDev; +#endif + +#ifdef XINPUT + InitExtInput(); +#endif + + miRegisterPointerDevice(screenInfo.screens[0], (DevicePtr) xf86Info.pMouse); +#ifdef XINPUT + xf86XinputFinalizeInit(xf86Info.pMouse); + xf86eqInit ((DevicePtr)xf86Info.pKeyboard, (DevicePtr)xf86Info.pMouse); +#else + mieqInit (xf86Info.pKeyboard, xf86Info.pMouse); +#endif +} + +/* + * OsVendorInit -- + * OS/Vendor-specific initialisations. Called from OsInit(), which + * is called by dix before establishing the well known sockets. + */ + +extern Bool OsDelayInitColors; + +void +OsVendorInit() +{ +#ifdef SIGCHLD + signal(SIGCHLD, SIG_DFL); /* Need to wait for child processes */ +#endif +#ifdef USE_XF86_SERVERLOCK + extern void xf86LockServer(); + static Bool been_here = FALSE; + + if (!been_here) { + xf86LockServer(); + been_here = TRUE; + } +#endif + OsDelayInitColors = TRUE; +} + +#ifdef DPMSExtension +extern CARD16 DPMSPowerLevel; + +/* + * DPMSSet -- + * Device dependent DPMS mode setting hook. This is called whenever + * the DPMS mode is to be changed. + */ +void +DPMSSet(CARD16 level) +{ + int i; + + /* For each screen, set the power saver level */ + for (i = 0; i < screenInfo.numScreens; i++) { + (XF86SCRNINFO(screenInfo.screens[i])->DPMSSet)(level); + } + + DPMSPowerLevel = level; +} + +#if 0 +/* + * DPMSGet -- + * Device dependent DPMS mode getting hook. This returns the current + * DPMS mode, or -1 if DPMS is not supported. + * + * This should hook in to the appropriate driver-level function, which + * will be added to the ScrnInfoRec. + * + * NOTES: + * 1. the calling interface should be changed to specify which + * screen to check. + * 2. It isn't clear that this function is ever used. + */ +CARD16 +DPMSGet(CARD16 *level) +{ + int i; + + /* For each screen, set the power saver level */ + for (i = 0; i < screenInfo.numScreens; i++) { + ; + } +} +#endif + +/* + * DPMSSupported -- + * Return TRUE if any screen supports DPMS. + */ +Bool +DPMSSupported(void) +{ + int i; + + /* For each screen, check if DPMS is supported */ + for (i = 0; i < screenInfo.numScreens; i++) { + if (XF86SCRNINFO(screenInfo.screens[i])->DPMSSet != (void (*)())NoopDDA) + return TRUE; + } + return FALSE; +} +#endif /* DPMSExtension */ + +/* + * ddxGiveUp -- + * Device dependent cleanup. Called by by dix before normal server death. + * For SYSV386 we must switch the terminal back to normal mode. No error- + * checking here, since there should be restored as much as possible. + */ + +void +ddxGiveUp() +{ +#ifdef USE_XF86_SERVERLOCK + xf86UnlockServer(); +#endif + + xf86CloseConsole(); + + /* If an unexpected signal was caught, dump a core for debugging */ + if (xf86Info.caughtSignal) + abort(); +} + + + +/* + * AbortDDX -- + * DDX - specific abort routine. Called by AbortServer(). The attempt is + * made to restore all original setting of the displays. Also all devices + * are closed. + */ + +void +AbortDDX() +{ + int i; + +#if 0 + if (xf86Exiting) + return; +#endif + + xf86Exiting = TRUE; + + /* + * try to deinitialize all input devices + */ + if (xf86Info.pMouse) (xf86Info.mouseDev->mseProc)(xf86Info.pMouse, DEVICE_CLOSE); + if (xf86Info.pKeyboard) (xf86Info.kbdProc)(xf86Info.pKeyboard, DEVICE_CLOSE); + + /* + * try to restore the original video state + */ +#ifdef HAS_USL_VTS + /* Need the sleep when starting X from within another X session */ + sleep(1); +#endif + if (xf86VTSema && xf86ScreensOpen) + for ( i=0; + i < xf86MaxScreens && xf86Screens[i] && xf86Screens[i]->configured; + i++ ) + (xf86Screens[i]->EnterLeaveVT)(LEAVE, i); + + /* + * This is needed for a abnormal server exit, since the normal exit stuff + * MUST also be performed (i.e. the vt must be left in a defined state) + */ + ddxGiveUp(); +} + +void +OsVendorFatalError() +{ + ErrorF("\nWhen reporting a problem related to a server crash, please send\n" + "the full server output, not just the last messages\n\n"); +} + +/* + * ddxProcessArgument -- + * Process device-dependent command line args. Returns 0 if argument is + * not device dependent, otherwise Count of number of elements of argv + * that are part of a device dependent commandline option. + */ + +/* ARGSUSED */ +int +ddxProcessArgument (argc, argv, i) + int argc; + char *argv[]; + int i; +{ + if (getuid() == 0 && !strcmp(argv[i], "-xf86config")) + { + if (!argv[i+1]) + return 0; + if (strlen(argv[i+1]) >= PATH_MAX) + FatalError("XF86Config path name too long\n"); + strcpy(xf86ConfigFile, argv[i+1]); + return 2; + } + if (!strcmp(argv[i],"-probeonly")) + { + xf86ProbeOnly = TRUE; + return 1; + } + if (!strcmp(argv[i],"-flipPixels")) + { + xf86FlipPixels = TRUE; + return 1; + } +#ifdef XF86VIDMODE + if (!strcmp(argv[i],"-disableVidMode")) + { + xf86VidModeEnabled = FALSE; + return 1; + } + if (!strcmp(argv[i],"-allowNonLocalXvidtune")) + { + xf86VidModeAllowNonLocal = TRUE; + return 1; + } +#endif +#ifdef XF86MISC + if (!strcmp(argv[i],"-disableModInDev")) + { + xf86MiscModInDevEnabled = FALSE; + return 1; + } + if (!strcmp(argv[i],"-allowNonLocalModInDev")) + { + xf86MiscModInDevAllowNonLocal = TRUE; + return 1; + } + if (!strcmp(argv[i],"-allowMouseOpenFail")) + { + xf86AllowMouseOpenFail = TRUE; + return 1; + } +#endif + if (!strcmp(argv[i],"-bestRefresh")) + { + xf86BestRefresh = TRUE; + return 1; + } +#ifdef DO_CHECK_BETA + if (!strcmp(argv[i],"-extendExpiry")) + { + extraDays = atoi(argv[i + 1]); + expKey = argv[i + 2]; + return 3; + } +#endif + if (!strcmp(argv[i],"-verbose")) + { + if (!xf86Verbose++) + xf86Verbose = 2; + return 1; + } + if (!strcmp(argv[i],"-quiet")) + { + xf86Verbose = 0; + return 1; + } + if (!strcmp(argv[i],"-showconfig") || !strcmp(argv[i],"-version")) + { + xf86PrintBanner(); + xf86PrintConfig(); + exit(0); + } + /* Notice the -fp flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-fp")) + { + xf86fpFlag = TRUE; + return 0; + } + /* Notice the -co flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-co")) + { + xf86coFlag = TRUE; + return 0; + } + /* Notice the -s flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-s")) + { + xf86sFlag = TRUE; + return 0; + } +#ifndef XF86MONOVGA + if (!strcmp(argv[i], "-bpp")) + { + int bpp; + if (++i >= argc) + return 0; + if (sscanf(argv[i], "%d", &bpp) == 1) + { + xf86bpp = bpp; + return 2; + } + else + { + ErrorF("Invalid bpp\n"); + return 0; + } + } + if (!strcmp(argv[i], "-weight")) + { + int red, green, blue; + if (++i >= argc) + return 0; + if (sscanf(argv[i], "%1d%1d%1d", &red, &green, &blue) == 3) + { + xf86weight.red = red; + xf86weight.green = green; + xf86weight.blue = blue; + return 2; + } + else + { + ErrorF("Invalid weighting\n"); + return 0; + } + } + if (!strcmp(argv[i], "-gamma") || !strcmp(argv[i], "-rgamma") || + !strcmp(argv[i], "-ggamma") || !strcmp(argv[i], "-bgamma")) + { + double gamma; + if (++i >= argc) + return 0; + if (sscanf(argv[i], "%lf", &gamma) == 1) { + if (gamma < 0.1 || gamma > 10) { + ErrorF("gamma out of range, only 0.1 < gamma_value < 10 is valid\n"); + return 0; + } + if (!strcmp(argv[i-1], "-gamma")) + xf86rGamma = xf86gGamma = xf86bGamma = 1.0 / gamma; + else if (!strcmp(argv[i-1], "-rgamma")) xf86rGamma = 1.0 / gamma; + else if (!strcmp(argv[i-1], "-ggamma")) xf86gGamma = 1.0 / gamma; + else if (!strcmp(argv[i-1], "-bgamma")) xf86bGamma = 1.0 / gamma; + return 2; + } + } +#endif /* XF86MONOVGA */ + return xf86ProcessArgument(argc, argv, i); +} + + +/* + * ddxUseMsg -- + * Print out correct use of device dependent commandline options. + * Maybe the user now knows what really to do ... + */ + +void +ddxUseMsg() +{ + ErrorF("\n"); + ErrorF("\n"); + ErrorF("Device Dependent Usage\n"); + if (getuid() == 0) + ErrorF("-xf86config file specify a configuration file\n"); + ErrorF("-probeonly probe for devices, then exit\n"); + ErrorF("-verbose verbose startup messages\n"); + ErrorF("-quiet minimal startup messages\n"); +#ifndef XF86MONOVGA + ErrorF("-bpp n set number of bits per pixel. Default: 8\n"); + ErrorF("-gamma f set gamma value (0.1 < f < 10.0) Default: 1.0\n"); + ErrorF("-rgamma f set gamma value for red phase\n"); + ErrorF("-ggamma f set gamma value for green phase\n"); + ErrorF("-bgamma f set gamma value for blue phase\n"); + ErrorF("-weight nnn set RGB weighting at 16 bpp. Default: 565\n"); +#endif /* XF86MONOVGA */ + ErrorF("-flipPixels swap default black/white Pixel values\n"); +#ifdef XF86VIDMODE + ErrorF("-disableVidMode disable mode adjustments with xvidtune\n"); + ErrorF("-allowNonLocalXvidtune allow xvidtune to be run as a non-local client\n"); +#endif +#ifdef XF86MISC + ErrorF("-disableModInDev disable dynamic modification of input device settings\n"); + ErrorF("-allowNonLocalModInDev allow changes to keyboard and mouse settings\n"); + ErrorF(" from non-local clients\n"); + ErrorF("-allowMouseOpenFail start server even if the mouse can't be initialized\n"); +#endif + ErrorF("-bestRefresh Chose modes with the best refresh rate\n"); + ErrorF( + "-showconfig show which drivers are included in the server\n"); + xf86UseMsg(); + ErrorF("\n"); +} + + +#ifndef OSNAME +#define OSNAME "unknown" +#endif +#ifndef OSVENDOR +#define OSVENDOR "" +#endif + +static void +xf86PrintBanner() +{ + ErrorF("\nXFree86 Version%s/ X Window System\n",XF86_VERSION); + ErrorF("(protocol Version %d, revision %d, vendor release %d)\n", + X_PROTOCOL, X_PROTOCOL_REVISION, VENDOR_RELEASE ); + ErrorF("Release Date: %s\n", XF86_DATE); + ErrorF("\tIf the server is older than 6-12 months, or if your card is " + "newer\n" + "\tthan the above date, look for a newer version before " + "reporting\n" + "\tproblems. (see http://www.XFree86.Org/FAQ)\n"); + ErrorF("Operating System: %s %s\n", OSNAME, OSVENDOR); +} + +static void +xf86PrintConfig() +{ + int i; + + ErrorF("Configured drivers:\n"); + for (i = 0; i < xf86MaxScreens; i++) + if (xf86Screens[i]) + (xf86Screens[i]->PrintIdent)(); +} + diff --git a/hw/xfree86/common/xf86Io.c b/hw/xfree86/common/xf86Io.c new file mode 100644 index 000000000..6fddb5e89 --- /dev/null +++ b/hw/xfree86/common/xf86Io.c @@ -0,0 +1,542 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Io.c,v 3.28.2.5 1998/02/24 19:05:55 hohndel Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86Io.c,v 1.3 2000/08/17 19:50:29 cpqbld Exp $ */ +/* Patch for PS/2 Intellimouse - Tim Goodwin 1997-11-06. */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "xf86_Config.h" + +#ifdef XINPUT +#include "xf86Xinput.h" +#endif + +#ifdef XKB +#include +#include +#include +#endif + +extern KeybdCtrl defaultKeyboardControl; + +unsigned int xf86InitialCaps = 0; +unsigned int xf86InitialNum = 0; +unsigned int xf86InitialScroll = 0; + +#include "atKeynames.h" + +extern int miPointerGetMotionEvents(DeviceIntPtr pPtr, xTimecoord *coords, + unsigned long start, unsigned long stop, + ScreenPtr pScreen); + +/* + * xf86KbdBell -- + * Ring the terminal/keyboard bell for an amount of time proportional to + * "loudness". + */ + +void +xf86KbdBell(percent, pKeyboard, ctrl, unused) + int percent; /* Percentage of full volume */ + DeviceIntPtr pKeyboard; /* Keyboard to ring */ + pointer ctrl; + int unused; +{ + xf86SoundKbdBell(percent, xf86Info.bell_pitch, xf86Info.bell_duration); +} + +#ifdef AMOEBA +#define LED_CAP IOP_LED_CAP +#define LED_NUM IOP_LED_NUM +#define LED_SCR IOP_LED_SCROLL +#endif + +#ifdef MINIX +#define LED_CAP KBD_LEDS_CAPS +#define LED_NUM KBD_LEDS_NUM +#define LED_SCR KBD_LEDS_SCROLL +#endif + +void +xf86KbdLeds () +{ + int leds = 0; +#ifdef XKB + if (!noXkbExtension) { + XkbEventCauseRec cause; + XkbSetCauseUnknown(&cause); + XkbUpdateIndicators((DeviceIntPtr)xf86Info.pKeyboard, + XkbAllIndicatorsMask, False, NULL, &cause); + return; + } +#endif +#ifdef LED_CAP + if (xf86Info.capsLock && !(xf86Info.xleds & XLED1)) + leds |= LED_CAP; + + if (xf86Info.numLock && !(xf86Info.xleds & XLED2)) + leds |= LED_NUM; + + if ((xf86Info.scrollLock || + xf86Info.modeSwitchLock || + xf86Info.composeLock) && + !(xf86Info.xleds & XLED3)) + leds |= LED_SCR; + + if ((xf86Info.leds & xf86Info.xleds) & XLED1) leds |= LED_CAP; + if ((xf86Info.leds & xf86Info.xleds) & XLED2) leds |= LED_NUM; + if ((xf86Info.leds & xf86Info.xleds) & XLED3) leds |= LED_SCR; + + xf86SetKbdLeds(leds); +#endif /* LED_CAP */ +} + +/* + * xf86KbdCtrl -- + * Alter some of the keyboard control parameters. All special protocol + * values are handled by dix (ProgChangeKeyboardControl) + */ + +void +xf86KbdCtrl (pKeyboard, ctrl) + DevicePtr pKeyboard; /* Keyboard to alter */ + KeybdCtrl *ctrl; +{ + xf86Info.bell_pitch = ctrl->bell_pitch; + xf86Info.bell_duration = ctrl->bell_duration; + xf86Info.autoRepeat = ctrl->autoRepeat; + xf86Info.leds = (ctrl->leds & ~(XCAPS | XNUM | XSCR)); + + xf86Info.composeLock = (ctrl->leds & XCOMP) ? TRUE : FALSE; + + xf86KbdLeds(); +} + +/* + * xf86InitKBD -- + * Reinitialize the keyboard. Only set Lockkeys accrding to ours leds. + * Depress all other keys. + */ + +void +xf86InitKBD(init) +Bool init; +{ + char leds = 0, rad; + unsigned int i; + xEvent kevent; + DeviceIntPtr pKeyboard = xf86Info.pKeyboard; + KeyClassRec *keyc = xf86Info.pKeyboard->key; + KeySym *map = keyc->curKeySyms.map; + +#ifndef MACH386 + kevent.u.keyButtonPointer.time = GetTimeInMillis(); + kevent.u.keyButtonPointer.rootX = 0; + kevent.u.keyButtonPointer.rootY = 0; + + /* + * Hmm... here is the biggest hack of every time ! + * It may be possible that a switch-vt procedure has finished BEFORE + * you released all keys neccessary to do this. That peculiar behavior + * can fool the X-server pretty much, cause it assumes that some keys + * were not released. TWM may stuck alsmost completly.... + * OK, what we are doing here is after returning from the vt-switch + * exeplicitely unrelease all keyboard keys before the input-devices + * are reenabled. + */ + for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map; + i < keyc->curKeySyms.maxKeyCode; + i++, map += keyc->curKeySyms.mapWidth) + if (KeyPressed(i)) + { + switch (*map) { + /* Don't release the lock keys */ + case XK_Caps_Lock: + case XK_Shift_Lock: + case XK_Num_Lock: + case XK_Scroll_Lock: + case XK_Kana_Lock: + break; + default: + kevent.u.u.detail = i; + kevent.u.u.type = KeyRelease; + (* pKeyboard->public.processInputProc)(&kevent, pKeyboard, 1); + } + } +#endif /* MACH386 */ + + xf86Info.scanPrefix = 0; + + if (init) + { + /* + * we must deal here with the fact, that on some cases the numlock or + * capslock key are enabled BEFORE the server is started up. So look + * here at the state on the according LEDS to determine whether a + * lock-key is already set. + */ + + xf86Info.capsLock = FALSE; + xf86Info.numLock = FALSE; + xf86Info.scrollLock = FALSE; + xf86Info.modeSwitchLock = FALSE; + xf86Info.composeLock = FALSE; + +#ifdef LED_CAP +#ifdef INHERIT_LOCK_STATE + leds = xf86Info.leds; + + for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map; + i < keyc->curKeySyms.maxKeyCode; + i++, map += keyc->curKeySyms.mapWidth) + + switch(*map) { + + case XK_Caps_Lock: + case XK_Shift_Lock: + if (leds & LED_CAP) + { + xf86InitialCaps = i; + xf86Info.capsLock = TRUE; + } + break; + + case XK_Num_Lock: + if (leds & LED_NUM) + { + xf86InitialNum = i; + xf86Info.numLock = TRUE; + } + break; + + case XK_Scroll_Lock: + case XK_Kana_Lock: + if (leds & LED_SCR) + { + xf86InitialScroll = i; + xf86Info.scrollLock = TRUE; + } + break; + } +#endif /* INHERIT_LOCK_STATE */ + xf86SetKbdLeds(leds); +#endif /* LED_CAP */ + + if (xf86Info.kbdDelay <= 375) rad = 0x00; + else if (xf86Info.kbdDelay <= 625) rad = 0x20; + else if (xf86Info.kbdDelay <= 875) rad = 0x40; + else rad = 0x60; + + if (xf86Info.kbdRate <= 2) rad |= 0x1F; + else if (xf86Info.kbdRate >= 30) rad |= 0x00; + else rad |= ((58 / xf86Info.kbdRate) - 2); + + xf86SetKbdRepeat(rad); + } +} + +/* + * xf86KbdProc -- + * Handle the initialization, etc. of a keyboard. + */ + +int +xf86KbdProc (pKeyboard, what) + DeviceIntPtr pKeyboard; /* Keyboard to manipulate */ + int what; /* What to do to it */ +{ + KeySymsRec keySyms; + CARD8 modMap[MAP_LENGTH]; + int kbdFd; + + switch (what) { + + case DEVICE_INIT: + /* + * First open and find the current state of the keyboard. + */ + + xf86KbdInit(); + + xf86KbdGetMapping(&keySyms, modMap); + + +#ifndef XKB + defaultKeyboardControl.leds = xf86GetKbdLeds(); +#else + defaultKeyboardControl.leds = 0; +#endif + + /* + * Perform final initialization of the system private keyboard + * structure and fill in various slots in the device record + * itself which couldn't be filled in before. + */ + + pKeyboard->public.on = FALSE; + +#ifdef XKB + if (noXkbExtension) { +#endif + InitKeyboardDeviceStruct((DevicePtr)xf86Info.pKeyboard, + &keySyms, + modMap, + xf86KbdBell, + (KbdCtrlProcPtr)xf86KbdCtrl); +#ifdef XKB + } else { + XkbComponentNamesRec names; + if (XkbInitialMap) { + if ((xf86Info.xkbkeymap = strchr(XkbInitialMap, '/')) != NULL) + xf86Info.xkbkeymap++; + else + xf86Info.xkbkeymap = XkbInitialMap; + } + if (xf86Info.xkbkeymap) { + names.keymap = xf86Info.xkbkeymap; + names.keycodes = NULL; + names.types = NULL; + names.compat = NULL; + names.symbols = NULL; + names.geometry = NULL; + } else { + names.keymap = NULL; + names.keycodes = xf86Info.xkbkeycodes; + names.types = xf86Info.xkbtypes; + names.compat = xf86Info.xkbcompat; + names.symbols = xf86Info.xkbsymbols; + names.geometry = xf86Info.xkbgeometry; + } + if ((xf86Info.xkbkeymap || xf86Info.xkbcomponents_specified) + && (xf86Info.xkbmodel == NULL || xf86Info.xkblayout == NULL)) { + xf86Info.xkbrules = NULL; + } + XkbSetRulesDflts(xf86Info.xkbrules, xf86Info.xkbmodel, + xf86Info.xkblayout, xf86Info.xkbvariant, + xf86Info.xkboptions); + XkbInitKeyboardDeviceStruct(pKeyboard, + &names, + &keySyms, + modMap, + xf86KbdBell, + (KbdCtrlProcPtr)xf86KbdCtrl); + } +#endif + + xf86InitKBD(TRUE); + break; + + case DEVICE_ON: + /* + * Set the keyboard into "direct" mode and turn on + * event translation. + */ + + kbdFd = xf86KbdOn(); + /* + * Discard any pending input after a VT switch to prevent the server + * passing on parts of the VT switch sequence. + */ + sleep(1); + if (kbdFd != -1) { + char buf[16]; + read(kbdFd, buf, 16); + } + +#ifndef __EMX__ /* Under EMX, keyboard cannot be select()'ed */ + if (kbdFd != -1) + AddEnabledDevice(kbdFd); +#endif /* __EMX__ */ + + pKeyboard->public.on = TRUE; + xf86InitKBD(FALSE); + break; + + case DEVICE_CLOSE: + case DEVICE_OFF: + /* + * Restore original keyboard directness and translation. + */ + + kbdFd = xf86KbdOff(); + + if (kbdFd != -1) + RemoveEnabledDevice(kbdFd); + + pKeyboard->public.on = FALSE; + break; + + } + return (Success); +} + +/* + * xf86MseCtrl -- + * Alter the control parameters for the mouse. Note that all special + * protocol values are handled by dix. + */ + +void +xf86MseCtrl(pPointer, ctrl) + DevicePtr pPointer; + PtrCtrl *ctrl; +{ + MouseDevPtr mouse = MOUSE_DEV((DeviceIntPtr) pPointer); + + mouse->num = ctrl->num; + mouse->den = ctrl->den; + mouse->threshold = ctrl->threshold; +} + +/* + * xf86MseProc -- + * Handle the initialization, etc. of a mouse + */ + +int +xf86MseProc(pPointer, what) + DeviceIntPtr pPointer; + int what; +{ + MouseDevPtr mouse = MOUSE_DEV(pPointer); + + mouse->device = pPointer; + + return xf86MseProcAux(pPointer, what, mouse, NULL, + (PtrCtrlProcPtr)xf86MseCtrl); +} + +int +xf86MseProcAux(pPointer, what, mouse, fd, ctrl) + DeviceIntPtr pPointer; + int what; + MouseDevPtr mouse; + int *fd; + PtrCtrlProcPtr ctrl; +{ + unsigned char map[MSE_MAXBUTTONS + 1]; + int nbuttons; + int mousefd; + + switch (what) + { + case DEVICE_INIT: + pPointer->public.on = FALSE; + + /* + * [KAZU-241097] We don't know exactly how many buttons the + * device has... + */ + for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons) + map[nbuttons + 1] = nbuttons + 1; + + InitPointerDeviceStruct((DevicePtr)pPointer, + map, + min(mouse->buttons, MSE_MAXBUTTONS), + miPointerGetMotionEvents, + ctrl, + miPointerGetMotionBufferSize()); + + xf86MouseInit(mouse); + + break; + + case DEVICE_ON: + + mousefd = xf86MouseOn(mouse); + + if (fd) + *fd = mousefd; + + if (mousefd != -1) { + if (mousefd == -2) { + if (fd) + *fd = -1; + } else { + if (mouse->mseType == P_PS2) + write(mousefd, "\364", 1); + + AddEnabledDevice(mousefd); + } + mouse->lastButtons = 0; + mouse->emulateState = 0; + pPointer->public.on = TRUE; + } else { + return !Success; + } + + break; + + case DEVICE_OFF: + case DEVICE_CLOSE: + + mousefd = xf86MouseOff(mouse, what == DEVICE_CLOSE); + + if (mousefd != -1) + RemoveEnabledDevice(mousefd); + + pPointer->public.on = FALSE; + usleep(300000); + break; + } + return Success; +} + +/* + * xf86MseEvents -- + * Read the new events from the device, and pass them to the eventhandler. + * This should is not used if there is only an OS_MOUSE driver. + */ +#ifndef OSMOUSE_ONLY +void +xf86MseEvents(mouse) + MouseDevPtr mouse; +{ + xf86MouseEvents(mouse); +} +#endif + +#if !defined(AMOEBA) && !(defined (sun) && defined(i386) && defined (SVR4)) && !defined(MINIX) && !defined(__mips__) +/* + * These are getting tossed in here until I can think of where + * they really belong + */ +CARD32 +GetTimeInMillis() +{ + struct timeval tp; + + gettimeofday(&tp, 0); + return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} +#endif /* !AMOEBA && !(sun || SVR4) && !MINIX */ + diff --git a/hw/xfree86/common/xf86Kbd.c b/hw/xfree86/common/xf86Kbd.c new file mode 100644 index 000000000..f263937a2 --- /dev/null +++ b/hw/xfree86/common/xf86Kbd.c @@ -0,0 +1,407 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Kbd.c,v 3.14 1997/01/05 11:58:08 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86Kbd.c,v 1.3 2000/08/17 19:50:30 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "atKeynames.h" +#include "xf86_Config.h" + +#include "xf86Keymap.h" + +#define KD_GET_ENTRY(i,n) \ + eascii_to_x[((keymap.key[i].spcl << (n+1)) & 0x100) + keymap.key[i].map[n]] + +/* + * NOTE: Not all possible remappable symbols are remapped. There are two main + * reasons: + * a) The mapping between scancode and SYSV/386 - symboltable + * is inconsistent between different versions and has some + * BIG mistakes. + * b) In X-Windows there is a difference between numpad-keys + * and normal keys. SYSV/386 uses for both kinds of keys + * the same symbol. + * + * Thus only the alpha keypad and the function keys are translated. + * Also CapsLock, NumLock, ScrollLock, Shift, Control & Alt. + */ + +static unsigned char remap[128] = { + 0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00 - 0x07 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08 - 0x0f */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10 - 0x17 */ + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18 - 0x1f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 - 0x27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28 - 0x2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0, /* 0x30 - 0x37 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38 - 0x3f */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0, /* 0x40 - 0x47 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48 - 0x4f */ + 0, 0, 0, 0, 0, 0, 0x56, 0x57, /* 0x50 - 0x57 */ + 0x58, 0, 0, 0, 0, 0, 0, 0, /* 0x58 - 0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68 - 0x6f */ + 0, 0, 0x69, 0x65, 0, 0, 0, 0, /* 0x70 - 0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78 - 0x7f */ +}; + +static KeySym eascii_to_x[512] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, XK_Return, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_Delete, + XK_Ccedilla, XK_udiaeresis, XK_eacute, XK_acircumflex, + XK_adiaeresis, XK_agrave, XK_aring, XK_ccedilla, + XK_ecircumflex, XK_ediaeresis, XK_egrave, XK_idiaeresis, + XK_icircumflex, XK_igrave, XK_Adiaeresis, XK_Aring, + XK_Eacute, XK_ae, XK_AE, XK_ocircumflex, + XK_odiaeresis, XK_ograve, XK_ucircumflex, XK_ugrave, + XK_ydiaeresis, XK_Odiaeresis, XK_Udiaeresis, XK_cent, + XK_sterling, XK_yen, XK_paragraph, XK_section, + XK_aacute, XK_iacute, XK_oacute, XK_uacute, + XK_ntilde, XK_Ntilde, XK_ordfeminine, XK_masculine, + XK_questiondown,XK_hyphen, XK_notsign, XK_onehalf, + XK_onequarter, XK_exclamdown, XK_guillemotleft,XK_guillemotright, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_Greek_alpha, XK_ssharp, XK_Greek_GAMMA, XK_Greek_pi, + XK_Greek_SIGMA, XK_Greek_sigma, XK_mu, XK_Greek_tau, + XK_Greek_PHI, XK_Greek_THETA, XK_Greek_OMEGA, XK_Greek_delta, + XK_infinity, XK_Ooblique, XK_Greek_epsilon, XK_intersection, + XK_identical, XK_plusminus, XK_greaterthanequal, XK_lessthanequal, + XK_topintegral, XK_botintegral, XK_division, XK_similarequal, + XK_degree, NoSymbol, NoSymbol, XK_radical, + XK_Greek_eta, XK_twosuperior, XK_periodcentered, NoSymbol, + + /* + * special marked entries (256 + x) + */ + + NoSymbol, NoSymbol, XK_Shift_L, XK_Shift_R, + XK_Caps_Lock, XK_Num_Lock, XK_Scroll_Lock, XK_Alt_L, + NoSymbol, XK_Control_L, XK_Alt_L, XK_Alt_R, + XK_Control_L, XK_Control_R, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_F1, + XK_F2, XK_F3, XK_F4, XK_F5, + XK_F6, XK_F7, XK_F8, XK_F9, + XK_F10, XK_F11, XK_F12, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + }; + + +/* + * LegalModifier -- + * determine whether a key is a legal modifier key, i.e send a + * press/release sequence. + */ + +/*ARGSUSED*/ +Bool +LegalModifier(key, pDev) + unsigned int key; + DevicePtr pDev; +{ + return (TRUE); +} + + + +/* + * xf86KbdGetMapping -- + * Get the national keyboard mapping. The keyboard type is set, a new map + * and the modifiermap is computed. + */ + +void +xf86KbdGetMapping (pKeySyms, pModMap) + KeySymsPtr pKeySyms; + CARD8 *pModMap; +{ + KeySym *k; +#if !defined(Lynx) && !defined(AMOEBA) && !defined(MINIX) && !defined(__OSF__) && !defined(__EMX__) && !defined(__mips__) + keymap_t keymap; +#endif /* !Lynx && !AMOEBA && !MINIX && !__OSF__ && !__EMX__ */ + char type; + int i, j; + KeySym *pMap; + +#if !defined(Lynx) && !defined(AMOEBA) && !defined(MINIX) && !defined(__OSF__) && !defined(__EMX__) && !defined(__mips__) + xf86Info.kbdType = + ioctl(xf86Info.consoleFd, KDGKBTYPE, &type) != -1 ? type : KB_101; + if (xf86Info.kbdType == KB_84) + pMap = map84; + else + pMap = map; +#else + xf86Info.kbdType = 0; + pMap = map; +#endif + +#if !defined(Lynx) && !defined(AMOEBA) && !defined(MINIX) && !defined(__OSF__) && !defined(__EMX__) && !defined(__mips__) + /* + * use the keymap, which can be gotten from our oringinal vt??. + * ( ttymap(1) !!!! ) + */ + if (ioctl(xf86Info.consoleFd, GIO_KEYMAP, &keymap) != -1) { + for (i = 0; i < keymap.n_keys && i < NUM_KEYCODES; i++) + + if (remap[i]) { + + k = pMap + (remap[i] << 2); + + k[0] = KD_GET_ENTRY(i,0); /* non-shifed */ + k[1] = KD_GET_ENTRY(i,1); /* shifted */ + k[2] = KD_GET_ENTRY(i,4); /* alt */ + k[3] = KD_GET_ENTRY(i,5); /* alt - shifted */ + + if (k[3] == k[2]) k[3] = NoSymbol; + if (k[2] == k[1]) k[2] = NoSymbol; + if (k[1] == k[0]) k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; + } + } +#endif /* !Lynx && !AMOEBA && !MINIX && !__OSF__ && !__EMX__ */ + + /* + * Apply the special key mapping specified in XF86Config + */ + for (k = pMap, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) { + switch (k[0]) { + case XK_Alt_L: + j = K_INDEX_LEFTALT; + break; + case XK_Alt_R: + j = K_INDEX_RIGHTALT; + break; + case XK_Scroll_Lock: + j = K_INDEX_SCROLLLOCK; + break; + case XK_Control_R: + j = K_INDEX_RIGHTCTL; + break; + default: + j = -1; + } + if (j >= 0) + switch (xf86Info.specialKeyMap[j]) { + case KM_META: + if (k[0] == XK_Alt_R) + k[1] = XK_Meta_R; + else { + k[0] = XK_Alt_L; + k[1] = XK_Meta_L; + } + break; + case KM_COMPOSE: + k[0] = XK_Multi_key; + break; + case KM_MODESHIFT: + k[0] = XK_Mode_switch; + k[1] = NoSymbol; + break; + case KM_MODELOCK: + k[0] = XK_Mode_switch; + k[1] = XF86XK_ModeLock; + break; + case KM_SCROLLLOCK: + k[0] = XK_Scroll_Lock; + break; + case KM_CONTROL: + k[0] = XK_Control_R; + break; + } + } + + /* + * compute the modifier map + */ + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + + for (k = pMap, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) + + switch(*k) { + + case XK_Shift_L: + case XK_Shift_R: + pModMap[i] = ShiftMask; + break; + + case XK_Control_L: + case XK_Control_R: + pModMap[i] = ControlMask; + break; + + case XK_Caps_Lock: + pModMap[i] = LockMask; + break; + + case XK_Alt_L: + case XK_Alt_R: + pModMap[i] = AltMask; + break; + + case XK_Num_Lock: + if (!xf86Info.serverNumLock) pModMap[i] = NumLockMask; + break; + + case XK_Scroll_Lock: + pModMap[i] = ScrollLockMask; + break; + + /* kana support */ + case XK_Kana_Lock: + case XK_Kana_Shift: + pModMap[i] = KanaMask; + break; + + /* alternate toggle for multinational support */ + case XK_Mode_switch: + pModMap[i] = AltLangMask; + break; + + } + +#if !defined(Lynx) && !defined(AMOEBA) && !defined(MINIX) && !defined(__OSF__) && !defined(__EMX__) && !defined(__mips__) + xf86Info.kbdType = + ioctl(xf86Info.consoleFd, KDGKBTYPE, &type) != -1 ? type : KB_101; +#else +/* OS/2 sets the keyboard type during xf86OpenKbd */ +#ifndef __EMX__ + xf86Info.kbdType = 0; +#endif +#endif + + + pKeySyms->map = pMap; + pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->minKeyCode = MIN_KEYCODE; + if (xf86Info.serverNumLock) + pKeySyms->maxKeyCode = MAX_KEYCODE; + else + pKeySyms->maxKeyCode = MAX_STD_KEYCODE; +} diff --git a/hw/xfree86/common/xf86KbdBSD.c b/hw/xfree86/common/xf86KbdBSD.c new file mode 100644 index 000000000..bf880dd68 --- /dev/null +++ b/hw/xfree86/common/xf86KbdBSD.c @@ -0,0 +1,687 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86KbdBSD.c,v 3.10 1996/12/23 06:43:30 dawes Exp $ */ +/* + * Derived from xf86Kbd.c by S_ren Schmidt (sos@login.dkuug.dk) + * which is Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * and from xf86KbdCODrv.c by Holger Veit + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + */ +/* $Xorg: xf86KbdBSD.c,v 1.3 2000/08/17 19:50:30 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "atKeynames.h" +#include "xf86_Config.h" +#include "coKeynames.h" +#include "xf86Keymap.h" + +#define KD_GET_ENTRY(i,n) \ + eascii_to_x[((keymap.key[i].spcl << (n+1)) & 0x100) + keymap.key[i].map[n]] + +#ifndef __bsdi__ +static KeySym coGetKeysym(); +#endif + +#ifndef PC98 +static unsigned char remap[128] = { + 0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00 - 0x07 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08 - 0x0f */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10 - 0x17 */ + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18 - 0x1f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 - 0x27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28 - 0x2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0, /* 0x30 - 0x37 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38 - 0x3f */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0, /* 0x40 - 0x47 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48 - 0x4f */ + 0, 0, 0, 0, 0, 0, 0x56, 0x57, /* 0x50 - 0x57 */ + 0x58, 0, 0, 0, 0, 0, 0, 0, /* 0x58 - 0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68 - 0x6f */ + 0, 0, 0x69, 0x65, 0, 0, 0, 0, /* 0x70 - 0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78 - 0x7f */ +}; +#else /* PC98 */ +static unsigned char remap[128] = { + 0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00 - 0x07 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08 - 0x0f */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10 - 0x17 */ + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18 - 0x1f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 - 0x27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28 - 0x2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0, 0, 0, /* 0x30 - 0x37 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x38 - 0x3f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x47 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48 - 0x4f */ + 0, 0, 0x52, 0x53, 0x54, 0x55, 0x56, 0, /* 0x50 - 0x57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x58 - 0x5f */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 - 0x67 */ + 0x68, 0x69, 0x6a, 0x6b, 0, 0, 0, 0, /* 0x68 - 0x6f */ + 0x70, 0x71, 0x72, 0x73, 0x74, 0, 0, 0, /* 0x70 - 0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78 - 0x7f */ +}; +#endif /* PC98 */ + + +/* This table assumes the ibm code page 437 coding for characters + * > 0x80. They are returned in this form by PCVT */ +static KeySym eascii_to_x[512] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, XK_Return, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_Delete, + XK_Ccedilla, XK_udiaeresis, XK_eacute, XK_acircumflex, + XK_adiaeresis, XK_agrave, XK_aring, XK_ccedilla, + XK_ecircumflex, XK_ediaeresis, XK_egrave, XK_idiaeresis, + XK_icircumflex, XK_igrave, XK_Adiaeresis, XK_Aring, + XK_Eacute, XK_ae, XK_AE, XK_ocircumflex, + XK_odiaeresis, XK_ograve, XK_ucircumflex, XK_ugrave, + XK_ydiaeresis, XK_Odiaeresis, XK_Udiaeresis, XK_cent, + XK_sterling, XK_yen, XK_paragraph, XK_section, + XK_aacute, XK_iacute, XK_oacute, XK_uacute, + XK_ntilde, XK_Ntilde, XK_ordfeminine, XK_masculine, + XK_questiondown,XK_hyphen, XK_notsign, XK_onehalf, + XK_onequarter, XK_exclamdown, XK_guillemotleft,XK_guillemotright, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_Greek_alpha, XK_ssharp, XK_Greek_GAMMA, XK_Greek_pi, + XK_Greek_SIGMA, XK_Greek_sigma, XK_mu, XK_Greek_tau, + XK_Greek_PHI, XK_Greek_THETA, XK_Greek_OMEGA, XK_Greek_delta, + XK_infinity, XK_Ooblique, XK_Greek_epsilon, XK_intersection, + XK_identical, XK_plusminus, XK_greaterthanequal, XK_lessthanequal, + XK_topintegral, XK_botintegral, XK_division, XK_similarequal, + XK_degree, NoSymbol, NoSymbol, XK_radical, + XK_Greek_eta, XK_twosuperior, XK_periodcentered, NoSymbol, + + /* + * special marked entries (256 + x) + */ + + NoSymbol, NoSymbol, XK_Shift_L, XK_Shift_R, + XK_Caps_Lock, XK_Num_Lock, XK_Scroll_Lock, XK_Alt_L, + NoSymbol, XK_Control_L, XK_Alt_L, XK_Alt_R, + XK_Control_L, XK_Control_R, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_F1, + XK_F2, XK_F3, XK_F4, XK_F5, + XK_F6, XK_F7, XK_F8, XK_F9, + XK_F10, XK_F11, XK_F12, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + }; + +#ifdef __OpenBSD__ +/* don't mark AltR and CtrlR for remapping, since they + * cannot be remapped by pccons */ +static unsigned char pccons_remap[128] = { + 0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00 - 0x07 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08 - 0x0f */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10 - 0x17 */ + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18 - 0x1f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 - 0x27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28 - 0x2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0, /* 0x30 - 0x37 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38 - 0x3f */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0, /* 0x40 - 0x47 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48 - 0x4f */ + 0, 0, 0, 0, 0, 0, 0x56, 0x57, /* 0x50 - 0x57 */ + 0x58, 0, 0, 0, 0, 0, 0, 0, /* 0x58 - 0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68 - 0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78 - 0x7f */ +}; + +/* This table assumes an iso8859_1 encoding for the characters + * > 80, as returned by pccons */ +static KeySym latin1_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, XK_Return, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_Delete, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis + }; +#endif +/* + * LegalModifier -- + * determine whether a key is a legal modifier key, i.e send a + * press/release sequence. + */ + +/*ARGSUSED*/ +Bool +LegalModifier(key, pDev) + unsigned int key; + DevicePtr pDev; +{ + return (TRUE); +} + +/* + * xf86KbdGetMapping -- + * Get the national keyboard mapping. The keyboard type is set, a new map + * and the modifiermap is computed. + */ + +void +xf86KbdGetMapping (pKeySyms, pModMap) + KeySymsPtr pKeySyms; + CARD8 *pModMap; +{ + KeySym *k; + char type; + int i, j; + +#ifndef __bsdi__ + switch (xf86Info.consType) { + +#ifdef PCCONS_SUPPORT + case PCCONS: +#if defined(__OpenBSD__) + /* + * on OpenBSD, the pccons keymap is programmable, too + */ + { + pccons_keymap_t keymap[KB_NUM_KEYS]; + if (ioctl(xf86Info.consoleFd, CONSOLE_GET_KEYMAP, &keymap) != -1) { + for (i = 0; i < KB_NUM_KEYS; i++) + if (pccons_remap[i]) { + k = map + (pccons_remap[i] << 2); + switch (keymap[i].type) { + case KB_ASCII: + /* For ASCII keys, there is only one char in the keymap */ + k[0] = latin1_to_x[(unsigned char)keymap[i].unshift[0]]; + k[1] = latin1_to_x[(unsigned char)keymap[i].shift[0]]; + k[2] = latin1_to_x[(unsigned char)keymap[i].altgr[0]]; + k[3] = latin1_to_x[(unsigned char)keymap[i].shift_altgr[0]]; + break; + case KB_SCROLL: + k[0] = XK_Scroll_Lock; + goto special; + case KB_NUM: + k[0] = XK_Num_Lock; + goto special; + case KB_CAPS: + k[0] = XK_Caps_Lock; + goto special; + case KB_SHIFT: + switch (keymap[i].unshift[0]) { + case 1: + /* left shift */ + k[0] = XK_Shift_L; + break; + case 2: + /* right shift */ + k[0] = XK_Shift_R; + break; + default: + k[0] = NoSymbol; + } + goto special; + case KB_CTL: + k[0] = XK_Control_L; + goto special; + case KB_ALT: + k[0] = XK_Alt_L; + goto special; + case KB_FUNC: + switch (keymap[i].unshift[2]) { + case 'M': + k[0] = XK_F1; + break; + case 'N': + k[0] = XK_F2; + break; + case 'O': + k[0] = XK_F3; + break; + case 'P': + k[0] = XK_F4; + break; + case 'Q': + k[0] = XK_F5; + break; + case 'R': + k[0] = XK_F6; + break; + case 'S': + k[0] = XK_F7; + break; + case 'T': + k[0] = XK_F8; + break; + case 'U': + k[0] = XK_F9; + break; + case 'V': + k[0] = XK_F10; + break; + case 'W': + k[0] = XK_F11; + break; + case 'X': + k[0] = XK_F12; + break; + default: + k[0] = NoSymbol; + break; + } + goto special; + default: + k[0] = NoSymbol; + special: + k[1] = k[2] = k[3] = NoSymbol; + } + } + } else { + ErrorF("Can't read pccons keymap\n"); + } + } +#endif /* __OpenBSD__ */ + break; +#endif + +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + { + keymap_t keymap; + + if (ioctl(xf86Info.consoleFd, GIO_KEYMAP, &keymap) != -1) { + for (i = 0; i < keymap.n_keys && i < NUM_KEYCODES; i++) +#ifdef PC98 + if (remap[i] || i == 0) { +#else + if (remap[i]) { +#endif + k = map + (remap[i] << 2); + k[0] = KD_GET_ENTRY(i,0); /* non-shifed */ + k[1] = KD_GET_ENTRY(i,1); /* shifted */ + k[2] = KD_GET_ENTRY(i,4); /* alt */ + k[3] = KD_GET_ENTRY(i,5); /* alt - shifted */ + if (k[3] == k[2]) k[3] = NoSymbol; + if (k[2] == k[1]) k[2] = NoSymbol; + if (k[1] == k[0]) k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) + k[2] = k[3] = NoSymbol; + } + } + } + break; +#endif /* SYSCONS || PCVT */ + +#ifdef CODRV_SUPPORT + case CODRV011: + case CODRV01X: + for (i=1; i<= 128; i++) { + struct kbd_ovlkey cokeymap; + struct oldkbd_ovlkey ocokeymap; + KeySym coGetKeysym(); + + if (xf86Info.consType == CODRV011) { + ocokeymap.keynum = i; + if (ioctl(xf86Info.consoleFd, OLDKBDGCKEY, &ocokeymap) < 0) + break; /* Don't try again if it fails once */ + if ((ocokeymap.type & KBD_OVERLOAD)) { /* changed from default setting */ + k = map + (xf86CodrvMap[i] << 2); + k[0] = coGetKeysym(ocokeymap.type,(CARD8*)&ocokeymap.unshift,k[0]); + k[1] = coGetKeysym(ocokeymap.type,(CARD8*)&ocokeymap.shift,k[1]); + k[2] = coGetKeysym(ocokeymap.type,(CARD8*)&ocokeymap.altgr,k[2]); + k[3] = NoSymbol; + } + } else { + cokeymap.keynum = i; + if (ioctl(xf86Info.consoleFd, KBDGCKEY, &cokeymap) < 0) + break; /* Don't try again if it fails once */ + if ((cokeymap.type & KBD_OVERLOAD)) { /* changed from default setting */ + k = map + (xf86CodrvMap[i] << 2); + k[0] = coGetKeysym(cokeymap.type,(CARD8*)&cokeymap.unshift,k[0]); + k[1] = coGetKeysym(cokeymap.type,(CARD8*)&cokeymap.shift,k[1]); + k[2] = coGetKeysym(cokeymap.type,(CARD8*)&cokeymap.altgr,k[2]); + k[3] = coGetKeysym(cokeymap.type,(CARD8*)&cokeymap.shiftaltgr,k[3]); + } + } + if ((cokeymap.type & KBD_OVERLOAD)) { /* changed from default setting */ + if (k[3] == k[2]) k[3] = NoSymbol; + if (k[2] == k[1]) k[2] = NoSymbol; + if (k[1] == k[0]) k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; + } + } + break; +#endif /* CODRV */ + } +#endif /* !bsdi */ + + /* + * Apply the special key mapping specified in XF86Config + */ + for (k = map, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) { + switch (k[0]) { + case XK_Alt_L: + j = K_INDEX_LEFTALT; + break; + case XK_Alt_R: + j = K_INDEX_RIGHTALT; + break; + case XK_Scroll_Lock: + j = K_INDEX_SCROLLLOCK; + break; + case XK_Control_R: + j = K_INDEX_RIGHTCTL; + break; + default: + j = -1; + } + if (j >= 0) + switch (xf86Info.specialKeyMap[j]) { + case KM_META: + if (k[0] == XK_Alt_R) + k[1] = XK_Meta_R; + else { + k[0] = XK_Alt_L; + k[1] = XK_Meta_L; + } + break; + case KM_COMPOSE: + k[0] = XK_Multi_key; + break; + case KM_MODESHIFT: + k[0] = XK_Mode_switch; + k[1] = NoSymbol; + break; + case KM_MODELOCK: + k[0] = XK_Mode_switch; + k[1] = XF86XK_ModeLock; + break; + case KM_SCROLLLOCK: + k[0] = XK_Scroll_Lock; + break; + case KM_CONTROL: + k[0] = XK_Control_R; + break; + } + } + + /* + * compute the modifier map + */ + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + + for (k = map, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) + + switch(*k) { + + case XK_Shift_L: + case XK_Shift_R: + pModMap[i] = ShiftMask; + break; + + case XK_Control_L: + case XK_Control_R: + pModMap[i] = ControlMask; + break; + + case XK_Caps_Lock: + pModMap[i] = LockMask; + break; + + case XK_Alt_L: + case XK_Alt_R: + pModMap[i] = AltMask; + break; + + case XK_Num_Lock: + if (!xf86Info.serverNumLock) pModMap[i] = NumLockMask; + break; + + case XK_Scroll_Lock: + pModMap[i] = ScrollLockMask; + break; + + /* kana support */ + case XK_Kana_Lock: + case XK_Kana_Shift: + pModMap[i] = KanaMask; + break; + + /* alternate toggle for multinational support */ + case XK_Mode_switch: + pModMap[i] = AltLangMask; + break; + + } + + xf86Info.kbdType = 0; + + pKeySyms->map = map; + pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->minKeyCode = MIN_KEYCODE; + if (xf86Info.serverNumLock) + pKeySyms->maxKeyCode = MAX_KEYCODE; + else + pKeySyms->maxKeyCode = MAX_STD_KEYCODE; + +} + +#ifdef CODRV_SUPPORT +/* Converts a CoDriver ASCII+Special combination into a KeySym + */ +static KeySym +coGetKeysym(typ,str,old) + int typ; + CARD8 *str; + KeySym old; +{ + if (strlen((char *)str) > 1) return old; + switch (typ & KBD_MASK) { + case KBD_NONE: + return NoSymbol; + case KBD_SHIFT: + if (old==XK_Shift_L || old==XK_Shift_R) return old; + else return XK_Shift_L; + case KBD_NUM: + return XK_Num_Lock; + case KBD_CTL: + if (old==XK_Control_L || old==XK_Control_R) return old; + else return XK_Control_L; + case KBD_ALTGR: + return XK_Mode_switch; + case KBD_META: + if (old==XK_Alt_L || old==XK_Alt_R) return old; + else return XK_Alt_L; + case KBD_SHFTLOCK: + case KBD_CAPS: + return XK_Caps_Lock; + case KBD_SCROLL: + return XK_Scroll_Lock; + case KBD_BREAK: + return XK_Break; + default: + case KBD_KP: /* there are few good reasons to overload + * F Keys and KP Keys, so we ignore any attempt + * at all + */ + return old; + case KBD_ASCII: + return *str; + } +} +#endif diff --git a/hw/xfree86/common/xf86KbdLnx.c b/hw/xfree86/common/xf86KbdLnx.c new file mode 100644 index 000000000..094044b30 --- /dev/null +++ b/hw/xfree86/common/xf86KbdLnx.c @@ -0,0 +1,697 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86KbdLnx.c,v 3.12 1996/12/23 06:43:31 dawes Exp $ */ +/* + * Linux version of keymapping setup. The kernel (since 0.99.14) has support + * for fully remapping the keyboard, but there are some differences between + * the Linux map and the SVR4 map (esp. in the extended keycodes). We also + * remove the restriction on what keycodes can be remapped. + * Orest Zborowski. + */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86KbdLnx.c,v 1.3 2000/08/17 19:50:30 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "atKeynames.h" +#include "xf86_Config.h" + +#include "xf86Keymap.h" +#include "DECkeysym.h" + +/* + * LegalModifier -- + * determine whether a key is a legal modifier key, i.e send a + * press/release sequence. + */ + +/*ARGSUSED*/ +Bool +LegalModifier(unsigned int key, DevicePtr pDev) +{ + return (TRUE); +} + +/* + * xf86KbdGetMapping -- + * Get the national keyboard mapping. The keyboard type is set, a new map + * and the modifiermap is computed. + */ + +static void readKernelMapping(KeySymsPtr pKeySyms, CARD8 *pModMap); + +void +xf86KbdGetMapping (KeySymsPtr pKeySyms, CARD8 *pModMap) +{ + KeySym *k; + char type; + int i, j; + + readKernelMapping(pKeySyms, pModMap); + + /* + * Apply the special key mapping specified in XF86Config + */ + for (k = map, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) { + switch (k[0]) { + case XK_Alt_L: + j = K_INDEX_LEFTALT; + break; + case XK_Alt_R: + j = K_INDEX_RIGHTALT; + break; + case XK_Scroll_Lock: + j = K_INDEX_SCROLLLOCK; + break; + case XK_Control_R: + j = K_INDEX_RIGHTCTL; + break; + default: + j = -1; + } + if (j >= 0) + switch (xf86Info.specialKeyMap[j]) { + case KM_META: + if (k[0] == XK_Alt_R) + k[1] = XK_Meta_R; + else { + k[0] = XK_Alt_L; + k[1] = XK_Meta_L; + } + break; + case KM_COMPOSE: + k[0] = XK_Multi_key; + break; + case KM_MODESHIFT: + k[0] = XK_Mode_switch; + k[1] = NoSymbol; + break; + case KM_MODELOCK: + k[0] = XK_Mode_switch; + k[1] = XF86XK_ModeLock; + break; + case KM_SCROLLLOCK: + k[0] = XK_Scroll_Lock; + break; + case KM_CONTROL: + k[0] = XK_Control_R; + break; + } + } + + /* + * compute the modifier map + */ + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + + for (k = map, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) + + switch(*k) { + + case XK_Shift_L: + case XK_Shift_R: + pModMap[i] = ShiftMask; + break; + + case XK_Control_L: + case XK_Control_R: + pModMap[i] = ControlMask; + break; + + case XK_Caps_Lock: + pModMap[i] = LockMask; + break; + + case XK_Alt_L: + case XK_Alt_R: + pModMap[i] = AltMask; + break; + + case XK_Num_Lock: + if (!xf86Info.serverNumLock) pModMap[i] = NumLockMask; + break; + + case XK_Scroll_Lock: + pModMap[i] = ScrollLockMask; + break; + + /* kana support */ + case XK_Kana_Lock: + case XK_Kana_Shift: + pModMap[i] = KanaMask; + break; + + /* alternate toggle for multinational support */ + case XK_Mode_switch: + pModMap[i] = AltLangMask; + break; + + } + + xf86Info.kbdType = + ioctl(xf86Info.consoleFd, KDGKBTYPE, &type) != -1 ? type : KB_101; + + pKeySyms->map = map; + pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->minKeyCode = MIN_KEYCODE; + if (xf86Info.serverNumLock) + pKeySyms->maxKeyCode = MAX_KEYCODE; + else + pKeySyms->maxKeyCode = MAX_STD_KEYCODE; + +} + +#include + +static KeySym linux_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_Delete, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis +}; + +#ifndef ASSUME_CUSTOM_KEYCODES + +/* + * Maps the AT keycodes to Linux keycodes + */ +static unsigned char at2lnx[] = +{ + 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ + 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ + 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ + 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ + 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ + 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ + 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ + 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ + 0x11, /* KEY_W */ 0x12, /* KEY_E */ + 0x13, /* KEY_R */ 0x14, /* KEY_T */ + 0x15, /* KEY_Y */ 0x16, /* KEY_U */ + 0x17, /* KEY_I */ 0x18, /* KEY_O */ + 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ + 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ + 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ + 0x1f, /* KEY_S */ 0x20, /* KEY_D */ + 0x21, /* KEY_F */ 0x22, /* KEY_G */ + 0x23, /* KEY_H */ 0x24, /* KEY_J */ + 0x25, /* KEY_K */ 0x26, /* KEY_L */ + 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ + 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ + 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ + 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ + 0x2f, /* KEY_V */ 0x30, /* KEY_B */ + 0x31, /* KEY_N */ 0x32, /* KEY_M */ + 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ + 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ + 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ + 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ + 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ + 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ + 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ + 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ + 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ + 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ + 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ + 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ + 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ + 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ + 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ + 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ + 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ + 0x00, /* 0x55 */ 0x56, /* KEY_Less */ + 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ + 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ + 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ + 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ + 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ + 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ + 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ + 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ + 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ + 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ + 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ + 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ + 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ + 0x00, /* 0x71 */ 0x00, /* 0x72 */ + 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ + 0x00, /* 0x75 */ 0x00, /* 0x76 */ + 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ + 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ + 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ + 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ + 0x00, /* 0x7f */ + /* the following are for ServerNumLock handling */ + 0x47, /* KEY_SN_KP_7 */ 0x48, /* KEY_SN_KP_8 */ + 0x49, /* KEY_SN_KP_9 */ 0x4b, /* KEY_SN_KP_4 */ + 0x4c, /* KEY_SN_KP_5 */ 0x4d, /* KEY_SN_KP_6 */ + 0x4f, /* KEY_SN_KP_1 */ 0x50, /* KEY_SN_KP_2 */ + 0x51, /* KEY_SN_KP_3 */ 0x52, /* KEY_SN_KP_0 */ + 0x53, /* KEY_SN_KP_Decimal */ 0x66, /* KEY_SN_Home */ + 0x67, /* KEY_SN_Up */ 0x68, /* KEY_SN_Prior */ + 0x69, /* KEY_SN_Left */ 0x5d, /* KEY_SN_Begin */ + 0x6a, /* KEY_SN_Right */ 0x6b, /* KEY_SN_End */ + 0x6c, /* KEY_SN_Down */ 0x6d, /* KEY_SN_Next */ + 0x6e, /* KEY_SN_Ins */ 0x6f /* KEY_SN_Del */ +}; +#define NUM_AT2LNX (sizeof(at2lnx) / sizeof(at2lnx[0])) + +#else /* !ASSUME_CUSTOM_KEYCODES */ + +#define NUM_AT2LNX NR_KEYS + +u_char SpecialServerMap[NR_KEYS]; + +#endif /* !ASSUME_CUSTOM_KEYCODES */ + +static void +readKernelMapping(KeySymsPtr pKeySyms, CARD8 *pModMap) +{ + KeySym *k; + int i; + static unsigned char tbl[GLYPHS_PER_KEY] = + { + 0, /* unshifted */ + 1, /* shifted */ + 0, /* modeswitch unshifted */ + 0 /* modeswitch shifted */ + }; + + /* + * Read the mapping from the kernel. + * Since we're still using the XFree86 scancode->AT keycode mapping + * routines, we need to convert the AT keycodes to Linux keycodes, + * then translate the Linux keysyms into X keysyms. + * + * First, figure out which tables to use for the modeswitch columns + * above, from the XF86Config fields. + */ + if (xf86Info.specialKeyMap[K_INDEX_RIGHTCTL] == KM_MODESHIFT || + xf86Info.specialKeyMap[K_INDEX_RIGHTCTL] == KM_MODELOCK) + tbl[2] = 4; /* control */ + else if (xf86Info.specialKeyMap[K_INDEX_RIGHTALT] == KM_MODESHIFT || + xf86Info.specialKeyMap[K_INDEX_RIGHTALT] == KM_MODELOCK) + tbl[2] = 2; /* AltGr */ + else + tbl[2] = 8; /* alt */ + tbl[3] = tbl[2] | 1; + +#ifndef ASSUME_CUSTOM_KEYCODES + for (i = 0, k = map+GLYPHS_PER_KEY; i < NUM_AT2LNX; ++i) +#else /* !ASSUME_CUSTOM_KEYCODES */ + for (i = 0, k = map; i < NUM_AT2LNX; ++i) +#endif /* !ASSUME_CUSTOM_KEYCODES */ + { + struct kbentry kbe; + int j; + +#ifndef ASSUME_CUSTOM_KEYCODES + kbe.kb_index = at2lnx[i]; +#else /* !ASSUME_CUSTOM_KEYCODES */ + kbe.kb_index = i; +#endif /* !ASSUME_CUSTOM_KEYCODES */ + + for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) + { + unsigned short kval; + + *k = NoSymbol; + + kbe.kb_table = tbl[j]; + if ( +#ifndef ASSUME_CUSTOM_KEYCODES + kbe.kb_index == 0 || +#endif /* !ASSUME_CUSTOM_KEYCODES */ + ioctl(xf86Info.consoleFd, KDGKBENT, &kbe)) + continue; + + kval = KVAL(kbe.kb_value); + switch (KTYP(kbe.kb_value)) + { + case KT_LATIN: + case KT_LETTER: + *k = linux_to_x[kval]; + break; + + case KT_FN: + if (kval <= 19) + *k = XK_F1 + kval; + else switch (kbe.kb_value) + { + case K_FIND: + *k = XK_Home; /* or XK_Find */ + break; + case K_INSERT: + *k = XK_Insert; + break; + case K_REMOVE: + *k = XK_Delete; + break; + case K_SELECT: + *k = XK_End; /* or XK_Select */ + break; + case K_PGUP: + *k = XK_Prior; + break; + case K_PGDN: + *k = XK_Next; + break; + case K_HELP: + *k = XK_Help; + break; + case K_DO: + *k = XK_Execute; + break; + case K_PAUSE: + *k = XK_Pause; + break; + case K_MACRO: + *k = XK_Menu; + break; + default: + break; + } + break; + + case KT_SPEC: + switch (kbe.kb_value) + { + case K_ENTER: + *k = XK_Return; + break; + case K_BREAK: + *k = XK_Break; + break; + case K_CAPS: + *k = XK_Caps_Lock; + break; + case K_NUM: + *k = XK_Num_Lock; + break; + case K_HOLD: + *k = XK_Scroll_Lock; + break; + case K_COMPOSE: + *k = XK_Multi_key; + break; + default: + break; + } + break; + + case KT_PAD: + switch (kbe.kb_value) + { + case K_PPLUS: + *k = XK_KP_Add; + break; + case K_PMINUS: + *k = XK_KP_Subtract; + break; + case K_PSTAR: + *k = XK_KP_Multiply; + break; + case K_PSLASH: + *k = XK_KP_Divide; + break; + case K_PENTER: + *k = XK_KP_Enter; + break; + case K_PCOMMA: + *k = XK_KP_Separator; + break; + case K_PDOT: + *k = XK_KP_Decimal; + break; + case K_PPLUSMINUS: + *k = XK_KP_Subtract; + break; + default: + if (kval <= 9) + *k = XK_KP_0 + kval; + break; + } + break; + + /* + * KT_DEAD keys are for accelerated diacritical creation. + */ + case KT_DEAD: + switch (kbe.kb_value) + { + case K_DGRAVE: + *k = XK_dead_grave; + break; + case K_DACUTE: + *k = XK_dead_acute; + break; + case K_DCIRCM: + *k = XK_dead_circumflex; + break; + case K_DTILDE: + *k = XK_dead_tilde; + break; + case K_DDIERE: + *k = XK_dead_diaeresis; + break; + } + break; + + case KT_CUR: + switch (kbe.kb_value) + { + case K_DOWN: + *k = XK_Down; + break; + case K_LEFT: + *k = XK_Left; + break; + case K_RIGHT: + *k = XK_Right; + break; + case K_UP: + *k = XK_Up; + break; + } + break; + + case KT_SHIFT: + switch (kbe.kb_value) + { + case K_ALTGR: + *k = XK_Alt_R; + break; + case K_ALT: + *k = (kbe.kb_index == 0x64 ? + XK_Alt_R : XK_Alt_L); + break; + case K_CTRL: + *k = (kbe.kb_index == 0x61 ? + XK_Control_R : XK_Control_L); + break; + case K_CTRLL: + *k = XK_Control_L; + break; + case K_CTRLR: + *k = XK_Control_R; + break; + case K_SHIFT: + *k = (kbe.kb_index == 0x36 ? + XK_Shift_R : XK_Shift_L); + break; + case K_SHIFTL: + *k = XK_Shift_L; + break; + case K_SHIFTR: + *k = XK_Shift_R; + break; + default: + break; + } + break; + + /* + * KT_ASCII keys accumulate a 3 digit decimal number that gets + * emitted when the shift state changes. We can't emulate that. + */ + case KT_ASCII: + break; + + case KT_LOCK: + if (kbe.kb_value == K_SHIFTLOCK) + *k = XK_Shift_Lock; + break; + + default: + break; + } + } + + if (k[-1] == k[-2]) k[-1] = NoSymbol; + if (k[-2] == k[-3]) k[-2] = NoSymbol; + if (k[-3] == k[-4]) k[-3] = NoSymbol; + if (k[-4] == k[-2] && k[-3] == k[-1]) k[-2] = k[-1] = NoSymbol; + if (k[-1] == k[-4] && k[-2] == k[-3] && k[-2] == NoSymbol) k[-1] =NoSymbol; + } +#ifdef ASSUME_CUSTOM_KEYCODES + /* + * Find the Mapping for the special server functions + */ + for (i = 0; i < NR_KEYS; ++i) { + struct kbentry kbe; + int special = 0; + + kbe.kb_index = i; + kbe.kb_table = 0; /* Plain map */ + if (!ioctl(xf86Info.consoleFd, KDGKBENT, &kbe)) + switch (kbe.kb_value) { + case K(KT_LATIN,0x7f): /* This catches DEL too... But who cares? */ + special = KEY_BackSpace; + break; + case K_PMINUS: + special = KEY_KP_Minus; + break; + case K_PPLUS: + special = KEY_KP_Plus; + break; + case K_F1: + special = KEY_F1; + break; + case K_F2: + special = KEY_F2; + break; + case K_F3: + special = KEY_F3; + break; + case K_F4: + special = KEY_F4; + break; + case K_F5: + special = KEY_F5; + break; + case K_F6: + special = KEY_F6; + break; + case K_F7: + special = KEY_F7; + break; + case K_F8: + special = KEY_F8; + break; + case K_F9: + special = KEY_F9; + break; + case K_F10: + special = KEY_F10; + break; + case K_F11: + special = KEY_F11; + break; + case K_F12: + special = KEY_F12; + break; + case K_ALT: + special = KEY_Alt; + break; + case K_ALTGR: + special = KEY_AltLang; + break; + case K_CONS: + special = KEY_SysReqest; + break; + } + SpecialServerMap[i] = special; + } +#endif /* ASSUME_CUSTOM_KEYCODES */ +} diff --git a/hw/xfree86/common/xf86KbdMach.c b/hw/xfree86/common/xf86KbdMach.c new file mode 100644 index 000000000..cc23ee8e0 --- /dev/null +++ b/hw/xfree86/common/xf86KbdMach.c @@ -0,0 +1,312 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86KbdMach.c,v 3.7 1996/12/23 06:43:32 dawes Exp $ */ +/* + ***************************************************************************** + * HISTORY + * Log: xf86KbdMach.c,v + * Revision 2.1.2.1 92/06/25 10:32:08 moore + * Incorporate the Elliot Dresselhaus's, Ernest Hua's and local changes + * to run Thomas Roell's I386 color X11R5. Original code only worked + * with SCO Unix. New code works with 2.5 and 3.0 Mach + * [92/06/24 rvb] + * + * EndLog + * + ***************************************************************************** + */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86KbdMach.c,v 1.3 2000/08/17 19:50:30 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "atKeynames.h" +#include "xf86_Config.h" + +#include "xf86Keymap.h" + +static KeySym ascii_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, XK_Return, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_Delete, + XK_Ccedilla, XK_udiaeresis, XK_eacute, XK_acircumflex, + XK_adiaeresis, XK_agrave, XK_aring, XK_ccedilla, + XK_ecircumflex, XK_ediaeresis, XK_egrave, XK_idiaeresis, + XK_icircumflex, XK_igrave, XK_Adiaeresis, XK_Aring, + XK_Eacute, XK_ae, XK_AE, XK_ocircumflex, + XK_odiaeresis, XK_ograve, XK_ucircumflex, XK_ugrave, + XK_ydiaeresis, XK_Odiaeresis, XK_Udiaeresis, XK_cent, + XK_sterling, XK_yen, XK_paragraph, XK_section, + XK_aacute, XK_iacute, XK_oacute, XK_uacute, + XK_ntilde, XK_Ntilde, XK_ordfeminine, XK_masculine, + XK_questiondown,XK_hyphen, XK_notsign, XK_onehalf, + XK_onequarter, XK_exclamdown, XK_guillemotleft,XK_guillemotright, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_Greek_alpha, XK_ssharp, XK_Greek_GAMMA, XK_Greek_pi, + XK_Greek_SIGMA, XK_Greek_sigma, XK_mu, XK_Greek_tau, + XK_Greek_PHI, XK_Greek_THETA, XK_Greek_OMEGA, XK_Greek_delta, + XK_infinity, XK_Ooblique, XK_Greek_epsilon, XK_intersection, + XK_identical, XK_plusminus, XK_greaterthanequal, XK_lessthanequal, + XK_topintegral, XK_botintegral, XK_division, XK_similarequal, + XK_degree, NoSymbol, NoSymbol, XK_radical, + XK_Greek_eta, XK_twosuperior, XK_periodcentered, NoSymbol, + }; + +/* + * LegalModifier -- + * determine whether a key is a legal modifier key, i.e send a + * press/release sequence. + */ + +/*ARGSUSED*/ +Bool +LegalModifier(key, pDev) + unsigned int key; + DevicePtr pDev; +{ + return (TRUE); +} + + + +/* + * xf86KbdGetMapping -- + * Get the national keyboard mapping. The keyboard type is set, a new map + * and the modifiermap is computed. + */ + +void +xf86KbdGetMapping (pKeySyms, pModMap) + KeySymsPtr pKeySyms; + CARD8 *pModMap; +{ + KeySym *k; + struct kbentry kbe; + char type; + int i, j; + + for (i = 0; i < NUMKEYS; i++) + { + static int states[] = { NORM_STATE, SHIFT_STATE, ALT_STATE, SHIFT_ALT }; + int j; + + k = &map[i*4]; + kbe.kb_index = i; + + for (j = 0; j < 4; j++) + { + kbe.kb_state = states[j]; + + if (ioctl (xf86Info.consoleFd, KDGKBENT, &kbe) != -1) + continue; + + if (kbe.kb_value [0] == K_SCAN) + { + int keycode = -1; + switch (kbe.kb_value [1]) + { + case K_CTLSC: keycode = XK_Control_L; break; + case K_LSHSC: keycode = XK_Shift_L; break; + case K_RSHSC: keycode = XK_Shift_R; break; + case K_ALTSC: keycode = XK_Alt_L; break; + case K_CLCKSC: keycode = XK_Caps_Lock; break; + case K_NLCKSC: keycode = XK_Num_Lock; break; + default: break; + } + if (keycode > 0) + k[j] = keycode; + } + else if (kbe.kb_value[1] != NC) + { + /* How to handle multiple characters? + Ignore them for now. */ + } + else + { + k[j] = ascii_to_x[kbe.kb_value[0]]; + } + } + } + + /* + * Apply the special key mapping specified in XF86Config + */ + for (k = map, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) { + switch (k[0]) { + case XK_Alt_L: + j = K_INDEX_LEFTALT; + break; + case XK_Alt_R: + j = K_INDEX_RIGHTALT; + break; + case XK_Scroll_Lock: + j = K_INDEX_SCROLLLOCK; + break; + case XK_Control_R: + j = K_INDEX_RIGHTCTL; + break; + default: + j = -1; + } + if (j >= 0) + switch (xf86Info.specialKeyMap[j]) { + case KM_META: + if (k[0] == XK_Alt_R) + k[1] = XK_Meta_R; + else { + k[0] = XK_Alt_L; + k[1] = XK_Meta_L; + } + break; + case KM_COMPOSE: + k[0] = XK_Multi_key; + break; + case KM_MODESHIFT: + k[0] = XK_Mode_switch; + k[1] = NoSymbol; + break; + case KM_MODELOCK: + k[0] = XK_Mode_switch; + k[1] = XF86XK_ModeLock; + break; + case KM_SCROLLLOCK: + k[0] = XK_Scroll_Lock; + break; + case KM_CONTROL: + k[0] = XK_Control_R; + break; + } + } + + /* + * compute the modifier map + */ + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + + for (k = map, i = MIN_KEYCODE; + i < (NUM_KEYCODES + MIN_KEYCODE); + i++, k += 4) + + switch(*k) { + + case XK_Shift_L: + case XK_Shift_R: + pModMap[i] = ShiftMask; + break; + + case XK_Control_L: + case XK_Control_R: + pModMap[i] = ControlMask; + break; + + case XK_Caps_Lock: + pModMap[i] = LockMask; + break; + + case XK_Alt_L: + case XK_Alt_R: + pModMap[i] = AltMask; + break; + + case XK_Num_Lock: + if (!xf86Info.serverNumLock) pModMap[i] = NumLockMask; + break; + + case XK_Scroll_Lock: + pModMap[i] = ScrollLockMask; + break; + + /* kana support */ + case XK_Kana_Lock: + case XK_Kana_Shift: + pModMap[i] = KanaMask; + break; + + /* alternate toggle for multinational support */ + case XK_Mode_switch: + pModMap[i] = AltLangMask; + break; + + } + + xf86Info.kbdType = + ioctl(xf86Info.kbdFd, KDGKBDTYPE, &type) != -1 ? type : KB_VANILLAKB; + + pKeySyms->map = map; + pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->minKeyCode = MIN_KEYCODE; + if (xf86Info.serverNumLock) + pKeySyms->maxKeyCode = MAX_KEYCODE; + else + pKeySyms->maxKeyCode = MAX_STD_KEYCODE; + +} diff --git a/hw/xfree86/common/xf86Keymap.h b/hw/xfree86/common/xf86Keymap.h new file mode 100644 index 000000000..2b9debff4 --- /dev/null +++ b/hw/xfree86/common/xf86Keymap.h @@ -0,0 +1,449 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h,v 3.9 1996/12/23 06:43:35 dawes Exp $ */ +/* + * + * For Scancodes see notes in atKeynames.h !!!! + * + */ +/* $Xorg: xf86Keymap.h,v 1.3 2000/08/17 19:50:30 cpqbld Exp $ */ + +static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = { +#ifndef PC98 + /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, + /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, + /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, + /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, + /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, + /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, + /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, + /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, + /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, + /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, + /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, + /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, + /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, + /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, + /* 0x0f */ XK_Tab, NoSymbol, NoSymbol, NoSymbol, + /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol, + /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol, + /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol, + /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol, + /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol, + /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol, + /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol, + /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol, + /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol, + /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, + /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, + /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, + /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol, + /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol, + /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol, + /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol, + /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol, + /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol, + /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol, + /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol, + /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, + /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, + /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, + /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, + /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol, + /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol, + /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol, + /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol, + /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol, + /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol, + /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol, + /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, + /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, + /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, + /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, + /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, + /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, + /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, + /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, + /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, + /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, + /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, + /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, + /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, + /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, + /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, + /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, + /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, + /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, + /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, + /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, + /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, + /* 0x4c */ NoSymbol, XK_KP_5, NoSymbol, NoSymbol, + /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, + /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, + /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, + /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, + /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, + /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, + /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, + /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, + /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, + /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, + /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, + + /* 0x59 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, + /* 0x5a */ XK_Up, NoSymbol, NoSymbol, NoSymbol, + /* 0x5b */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, + /* 0x5c */ XK_Left, NoSymbol, NoSymbol, NoSymbol, + /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, + /* 0x5e */ XK_Right, NoSymbol, NoSymbol, NoSymbol, + /* 0x5f */ XK_End, NoSymbol, NoSymbol, NoSymbol, + /* 0x60 */ XK_Down, NoSymbol, NoSymbol, NoSymbol, + /* 0x61 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, + /* 0x62 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, + /* 0x63 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, + /* 0x64 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, + /* 0x65 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x66 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, + /* 0x67 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, + /* 0x68 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, + /* 0x69 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, + /* 0x6a */ XK_Break, NoSymbol, NoSymbol, NoSymbol, + /* 0x6b */ XK_Meta_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x6c */ XK_Meta_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x6d */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, + /* 0x6e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x6f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7d */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, +#else /* PC98 */ + /* 0x00 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, + /* 0x01 */ XK_1, XK_exclam, XK_kana_NU, NoSymbol, + /* 0x02 */ XK_2, XK_quotedbl, XK_kana_FU, NoSymbol, + /* 0x03 */ XK_3, XK_numbersign, XK_kana_A, XK_kana_a, + /* 0x04 */ XK_4, XK_dollar, XK_kana_U, XK_kana_u, + /* 0x05 */ XK_5, XK_percent, XK_kana_E, XK_kana_e, + /* 0x06 */ XK_6, XK_ampersand, XK_kana_O, XK_kana_o, + /* 0x07 */ XK_7, XK_quoteright, XK_kana_YA, XK_kana_ya, + /* 0x08 */ XK_8, XK_parenleft, XK_kana_YU, XK_kana_yu, + /* 0x09 */ XK_9, XK_parenright, XK_kana_YO, XK_kana_yo, + /* 0x0a */ XK_0, NoSymbol, XK_kana_WA, XK_kana_WO, + /* 0x0b */ XK_minus, XK_equal, XK_kana_HO, NoSymbol, + /* 0x0c */ XK_asciicircum, XK_quoteleft, XK_kana_HE, NoSymbol, + /* 0x0d */ XK_backslash, XK_bar, XK_prolongedsound, NoSymbol, + /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, + /* 0x0f */ XK_Tab, NoSymbol, NoSymbol, NoSymbol, + /* 0x10 */ XK_Q, NoSymbol, XK_kana_TA, NoSymbol, + /* 0x11 */ XK_W, NoSymbol, XK_kana_TE, NoSymbol, + /* 0x12 */ XK_E, NoSymbol, XK_kana_I, XK_kana_i, + /* 0x13 */ XK_R, NoSymbol, XK_kana_SU, NoSymbol, + /* 0x14 */ XK_T, NoSymbol, XK_kana_KA, NoSymbol, + /* 0x15 */ XK_Y, NoSymbol, XK_kana_N, NoSymbol, + /* 0x16 */ XK_U, NoSymbol, XK_kana_NA, NoSymbol, + /* 0x17 */ XK_I, NoSymbol, XK_kana_NI, NoSymbol, + /* 0x18 */ XK_O, NoSymbol, XK_kana_RA, NoSymbol, + /* 0x19 */ XK_P, NoSymbol, XK_kana_SE, NoSymbol, + /* 0x1a */ XK_at, XK_asciitilde, XK_voicedsound, NoSymbol, + /* 0x1b */ XK_bracketleft, XK_braceleft, XK_semivoicedsound, XK_kana_openingbracket, + /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, + /* 0x1d */ XK_A, NoSymbol, XK_kana_CHI, NoSymbol, + /* 0x1e */ XK_S, NoSymbol, XK_kana_TO, NoSymbol, + /* 0x1f */ XK_D, NoSymbol, XK_kana_SHI, NoSymbol, + /* 0x20 */ XK_F, NoSymbol, XK_kana_HA, NoSymbol, + /* 0x21 */ XK_G, NoSymbol, XK_kana_KI, NoSymbol, + /* 0x22 */ XK_H, NoSymbol, XK_kana_KU, NoSymbol, + /* 0x23 */ XK_J, NoSymbol, XK_kana_MA, NoSymbol, + /* 0x24 */ XK_K, NoSymbol, XK_kana_NO, NoSymbol, + /* 0x25 */ XK_L, NoSymbol, XK_kana_RI, NoSymbol, + /* 0x26 */ XK_semicolon, XK_plus, XK_kana_RE, NoSymbol, + /* 0x27 */ XK_colon, XK_asterisk, XK_kana_KE, NoSymbol, + /* 0x28 */ XK_bracketright,XK_braceright, XK_kana_MU, XK_kana_closingbracket, + /* 0x29 */ XK_Z, NoSymbol, XK_kana_TSU, NoSymbol, + /* 0x2a */ XK_X, NoSymbol, XK_kana_SA, NoSymbol, + /* 0x2b */ XK_C, NoSymbol, XK_kana_SO, NoSymbol, + /* 0x2c */ XK_V, NoSymbol, XK_kana_HI, NoSymbol, + /* 0x2d */ XK_B, NoSymbol, XK_kana_KO, NoSymbol, + /* 0x2e */ XK_N, NoSymbol, XK_kana_MI, NoSymbol, + /* 0x2f */ XK_M, NoSymbol, XK_kana_MO, NoSymbol, + /* 0x30 */ XK_comma, XK_less, XK_kana_NE, XK_kana_comma, + /* 0x31 */ XK_period, XK_greater, XK_kana_RU, XK_kana_fullstop, + /* 0x32 */ XK_slash, XK_question, XK_kana_ME, XK_kana_middledot, + /* 0x33 */ XK_underscore, XK_underscore, XK_kana_RO, NoSymbol, + /* 0x34 */ XK_space, NoSymbol, NoSymbol, NoSymbol, + /* 0x35 */ XK_Henkan, XK_Kanji, NoSymbol, NoSymbol, + /* 0x36 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, + /* 0x37 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, + /* 0x38 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, + /* 0x39 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, + /* 0x3a */ XK_Up, NoSymbol, NoSymbol, NoSymbol, + /* 0x3b */ XK_Left, NoSymbol, NoSymbol, NoSymbol, + /* 0x3c */ XK_Right, NoSymbol, NoSymbol, NoSymbol, + /* 0x3d */ XK_Down, NoSymbol, NoSymbol, NoSymbol, + /* 0x3e */ XK_Clear, XK_Home, NoSymbol, NoSymbol, + /* 0x3f */ XK_Help, NoSymbol, NoSymbol, NoSymbol, + /* 0x40 */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, + /* 0x41 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, + /* 0x42 */ XK_KP_7, NoSymbol, NoSymbol, NoSymbol, + /* 0x43 */ XK_KP_8, NoSymbol, NoSymbol, NoSymbol, + /* 0x44 */ XK_KP_9, NoSymbol, NoSymbol, NoSymbol, + /* 0x45 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, + /* 0x46 */ XK_KP_4, NoSymbol, NoSymbol, NoSymbol, + /* 0x47 */ XK_KP_5, NoSymbol, NoSymbol, NoSymbol, + /* 0x48 */ XK_KP_6, NoSymbol, NoSymbol, NoSymbol, + /* 0x49 */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, + /* 0x4a */ XK_KP_1, NoSymbol, NoSymbol, NoSymbol, + /* 0x4b */ XK_KP_2, NoSymbol, NoSymbol, NoSymbol, + /* 0x4c */ XK_KP_3, NoSymbol, NoSymbol, NoSymbol, + /* 0x4d */ XK_KP_Equal, NoSymbol, NoSymbol, NoSymbol, + /* 0x4e */ XK_KP_0, NoSymbol, NoSymbol, NoSymbol, + /* 0x4f */ XK_KP_Separator,NoSymbol, NoSymbol, NoSymbol, + /* 0x50 */ XK_KP_Decimal, NoSymbol, NoSymbol, NoSymbol, + /* 0x51 */ XK_Muhenkan, NoSymbol, NoSymbol, NoSymbol, + /* 0x52 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, + /* 0x53 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, + /* 0x54 */ XK_F13, NoSymbol, NoSymbol, NoSymbol, + /* 0x55 */ XK_F14, NoSymbol, NoSymbol, NoSymbol, + /* 0x56 */ XK_F15, NoSymbol, NoSymbol, NoSymbol, + /* 0x57 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x58 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5d */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x60 */ XK_Break, NoSymbol, NoSymbol, NoSymbol, + /* 0x61 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, + /* 0x62 */ XK_F1, NoSymbol, NoSymbol, NoSymbol, + /* 0x63 */ XK_F2, NoSymbol, NoSymbol, NoSymbol, + /* 0x64 */ XK_F3, NoSymbol, NoSymbol, NoSymbol, + /* 0x65 */ XK_F4, NoSymbol, NoSymbol, NoSymbol, + /* 0x66 */ XK_F5, NoSymbol, NoSymbol, NoSymbol, + /* 0x67 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, + /* 0x68 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, + /* 0x69 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, + /* 0x6a */ XK_F9, NoSymbol, NoSymbol, NoSymbol, + /* 0x6b */ XK_F10, NoSymbol, NoSymbol, NoSymbol, + /* 0x6c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x6d */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x6e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x6f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x70 */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x71 */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x72 */ XK_kana_switch, NoSymbol, XK_kana_switch, NoSymbol, + /* 0x73 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, + /* 0x74 */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7d */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, +#endif /* PC98 */ + /* 0x7f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + + /* These are for ServerNumLock handling */ + /* 0x80 */ XK_KP_7, NoSymbol, NoSymbol, NoSymbol, + /* 0x81 */ XK_KP_8, NoSymbol, NoSymbol, NoSymbol, + /* 0x82 */ XK_KP_9, NoSymbol, NoSymbol, NoSymbol, + /* 0x83 */ XK_KP_4, NoSymbol, NoSymbol, NoSymbol, + /* 0x84 */ XK_KP_5, NoSymbol, NoSymbol, NoSymbol, + /* 0x85 */ XK_KP_6, NoSymbol, NoSymbol, NoSymbol, + /* 0x86 */ XK_KP_1, NoSymbol, NoSymbol, NoSymbol, + /* 0x87 */ XK_KP_2, NoSymbol, NoSymbol, NoSymbol, + /* 0x88 */ XK_KP_3, NoSymbol, NoSymbol, NoSymbol, + /* 0x89 */ XK_KP_0, NoSymbol, NoSymbol, NoSymbol, + /* 0x8a */ XK_KP_Decimal, NoSymbol, NoSymbol, NoSymbol, + /* 0x8b */ XK_Home, NoSymbol, NoSymbol, NoSymbol, + /* 0x8c */ XK_Up, NoSymbol, NoSymbol, NoSymbol, + /* 0x8d */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, + /* 0x8e */ XK_Left, NoSymbol, NoSymbol, NoSymbol, + /* 0x8f */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, + /* 0x90 */ XK_Right, NoSymbol, NoSymbol, NoSymbol, + /* 0x91 */ XK_End, NoSymbol, NoSymbol, NoSymbol, + /* 0x92 */ XK_Down, NoSymbol, NoSymbol, NoSymbol, + /* 0x93 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, + /* 0x94 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, + /* 0x95 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, +}; + +static KeySym map84[NUM_KEYCODES * GLYPHS_PER_KEY] = { + /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, + /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, + /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, + /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, + /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, + /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, + /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, + /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, + /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, + /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, + /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, + /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, + /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, + /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, + /* 0x0f */ XK_Tab, NoSymbol, NoSymbol, NoSymbol, + /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol, + /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol, + /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol, + /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol, + /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol, + /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol, + /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol, + /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol, + /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol, + /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, + /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, + /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, + /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol, + /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol, + /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol, + /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol, + /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol, + /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol, + /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol, + /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol, + /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, + /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, + /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, + /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, + /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol, + /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol, + /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol, + /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol, + /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol, + /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol, + /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol, + /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, + /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, + /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, + /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, + /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, + /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, + /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, + /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, + /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, + /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, + /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, + /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, + /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, + /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, + /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, + /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, + /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, + /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, + /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, + /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, + /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, + /* 0x4c */ NoSymbol, XK_KP_5, NoSymbol, NoSymbol, + /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, + /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, + /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, + /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, + /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, + /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, + /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, + /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, + /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, + /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, + /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, + + /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5d */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x60 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x61 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x62 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x63 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x64 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, + /* 0x65 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x66 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, + /* 0x67 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, + /* 0x68 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, + /* 0x69 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, + /* 0x6a */ XK_Break, NoSymbol, NoSymbol, NoSymbol, + /* 0x6b */ XK_Meta_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x6c */ XK_Meta_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x6d */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, + /* 0x6e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x6f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7d */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + + /* These are for ServerNumLock handling */ + /* 0x80 */ XK_KP_7, NoSymbol, NoSymbol, NoSymbol, + /* 0x81 */ XK_KP_8, NoSymbol, NoSymbol, NoSymbol, + /* 0x82 */ XK_KP_9, NoSymbol, NoSymbol, NoSymbol, + /* 0x83 */ XK_KP_4, NoSymbol, NoSymbol, NoSymbol, + /* 0x84 */ XK_KP_5, NoSymbol, NoSymbol, NoSymbol, + /* 0x85 */ XK_KP_6, NoSymbol, NoSymbol, NoSymbol, + /* 0x86 */ XK_KP_1, NoSymbol, NoSymbol, NoSymbol, + /* 0x87 */ XK_KP_2, NoSymbol, NoSymbol, NoSymbol, + /* 0x88 */ XK_KP_3, NoSymbol, NoSymbol, NoSymbol, + /* 0x89 */ XK_KP_0, NoSymbol, NoSymbol, NoSymbol, + /* 0x8a */ XK_KP_Decimal, NoSymbol, NoSymbol, NoSymbol, + /* 0x8b */ XK_Home, NoSymbol, NoSymbol, NoSymbol, + /* 0x8c */ XK_Up, NoSymbol, NoSymbol, NoSymbol, + /* 0x8d */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, + /* 0x8e */ XK_Left, NoSymbol, NoSymbol, NoSymbol, + /* 0x8f */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, + /* 0x90 */ XK_Right, NoSymbol, NoSymbol, NoSymbol, + /* 0x91 */ XK_End, NoSymbol, NoSymbol, NoSymbol, + /* 0x92 */ XK_Down, NoSymbol, NoSymbol, NoSymbol, + /* 0x93 */ XK_Next, NoSymbol, NoSymbol, NoSymbol, + /* 0x94 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, + /* 0x95 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, +}; diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h new file mode 100644 index 000000000..3c73f6e56 --- /dev/null +++ b/hw/xfree86/common/xf86Priv.h @@ -0,0 +1,175 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Priv.h,v 3.24.2.1 1998/02/01 16:04:47 robin Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xf86Priv.h,v 1.3 2000/08/17 19:50:30 cpqbld Exp $ */ + +#ifndef _XF86PRIV_H +#define _XF86PRIV_H + +#ifndef _XF86VIDMODE_SERVER_ +#include "Xproto.h" +#include "xf86_OSproc.h" +#endif + +typedef struct { + + /* keyboard part */ + DeviceIntPtr pKeyboard; + DeviceProc kbdProc; /* procedure for initializing */ + void (* kbdEvents)( /* proc for processing events */ +#if NeedNestedPrototypes && !defined(__OSF__) + void +#endif + ); +#ifndef MINIX + int consoleFd; +#else + int kbdFd; +#endif /* MINIX */ +#if defined(MACH386) || defined(__OSF__) + int kbdFd; +#endif /* MACH386 || __OSF__ */ + int vtno; + int kbdType; /* AT84 / AT101 */ + int kbdRate; + int kbdDelay; + int bell_pitch; + int bell_duration; + Bool autoRepeat; + unsigned long leds; + unsigned long xleds; + char *vtinit; + int *specialKeyMap; + int scanPrefix; /* scancode-state */ + Bool capsLock; + Bool numLock; + Bool scrollLock; + Bool modeSwitchLock; + Bool serverNumLock; + Bool composeLock; + Bool vtSysreq; +#if defined(SVR4) && defined(i386) + Bool panix106; +#endif /* SVR4 && i386 */ + + /* mouse part */ + DeviceIntPtr pMouse; +#ifdef XINPUT + pointer mouseLocal; +#endif + MouseDevPtr mouseDev; + + /* event handler part */ + int lastEventTime; + Bool vtRequestsPending; + Bool inputPending; + Bool dontZap; + Bool dontZoom; + Bool notrapSignals; /* don't exit cleanly - die at fault */ + Bool caughtSignal; + + /* graphics part */ + Bool sharedMonitor; + ScreenPtr currentScreen; +#ifdef CSRG_BASED + int screenFd; /* fd for memory mapped access to vga card */ + int consType; /* Which console driver? */ +#endif +#if defined(AMOEBA) + void *screenPtr; +#endif + +#ifdef XKB +/* + * would like to use an XkbComponentNamesRec here but can't without + * pulling in a bunch of header files. :-( + */ + char *xkbkeymap; + char *xkbkeycodes; + char *xkbtypes; + char *xkbcompat; + char *xkbsymbols; + char *xkbgeometry; + Bool xkbcomponents_specified; + char *xkbrules; + char *xkbmodel; + char *xkblayout; + char *xkbvariant; + char *xkboptions; +#endif + +} xf86InfoRec, *xf86InfoPtr; + +extern xf86InfoRec xf86Info; + +/* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */ +#define XLED1 ((unsigned long) 0x00000001) +#define XLED2 ((unsigned long) 0x00000002) +#define XLED3 ((unsigned long) 0x00000004) +#define XCAPS ((unsigned long) 0x20000000) +#define XNUM ((unsigned long) 0x40000000) +#define XSCR ((unsigned long) 0x80000000) +#define XCOMP ((unsigned long) 0x00008000) + +/* 386BSD console driver types (consType) */ +#ifdef CSRG_BASED +#define PCCONS 0 +#define CODRV011 1 +#define CODRV01X 2 +#define SYSCONS 8 +#define PCVT 16 +#endif + +/* Values of xf86Info.mouseFlags */ +#define MF_CLEAR_DTR 1 +#define MF_CLEAR_RTS 2 + +extern int xf86ScreenIndex; + +#define XF86SCRNINFO(p) ((ScrnInfoPtr)((p)->devPrivates[xf86ScreenIndex].ptr)) + +extern int xf86MaxScreens; +extern ScrnInfoPtr xf86Screens[]; +extern int xf86ScreenNames[]; + +extern char xf86ConfigFile[]; +extern int xf86Verbose; +extern Bool xf86ProbeOnly, xf86ProbeFailed; +extern unsigned short xf86MouseCflags[]; +extern Bool xf86SupportedMouseTypes[]; +extern int xf86NumMouseTypes; +extern int xf86bpp; +extern xrgb xf86weight; +extern Bool xf86AllowMouseOpenFail; +extern Bool xf86BestRefresh; + +extern Bool xf86FlipPixels; +#define XF86FLIP_PIXELS() \ + if (xf86FlipPixels) { \ + pScreen->whitePixel = (pScreen->whitePixel) ? 0 : 1; \ + pScreen->blackPixel = (pScreen->blackPixel) ? 0 : 1; \ + } + +#endif /* _XF86PRIV_H */ + + diff --git a/hw/xfree86/common/xf86Version.h b/hw/xfree86/common/xf86Version.h new file mode 100644 index 000000000..f403c31f5 --- /dev/null +++ b/hw/xfree86/common/xf86Version.h @@ -0,0 +1,23 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/xf86Version.h,v 3.236.2.50 1998/03/02 09:58:21 dawes Exp $ */ + +#define XF86_VERSION " 3.3.2 " + +/* The finer points in versions... */ +#define XF86_VERSION_MAJOR 3 +#define XF86_VERSION_MINOR 3 +#define XF86_VERSION_SUBMINOR 2 +#define XF86_VERSION_BETA 0 /* 0="", 1="A", 2="B", etc... */ +#define XF86_VERSION_ALPHA 0 /* 0="", 1="a", 2="b", etc... */ + +#define XF86_VERSION_NUMERIC(major,minor,subminor,beta,alpha) \ + ((((((((major << 7) | minor) << 7) | subminor) << 5) | beta) << 5) | alpha) +#define XF86_VERSION_CURRENT \ + XF86_VERSION_NUMERIC(XF86_VERSION_MAJOR, \ + XF86_VERSION_MINOR, \ + XF86_VERSION_SUBMINOR, \ + XF86_VERSION_BETA, \ + XF86_VERSION_ALPHA) + +#define XF86_DATE "March 2 1998" + +/* $Xorg: xf86Version.h,v 1.3 2000/08/17 19:48:48 cpqbld Exp $ */ diff --git a/hw/xfree86/common/xf86XKB.c b/hw/xfree86/common/xf86XKB.c new file mode 100644 index 000000000..c5ac740fd --- /dev/null +++ b/hw/xfree86/common/xf86XKB.c @@ -0,0 +1,118 @@ +/* $Xorg: xf86XKB.c,v 1.3 2000/08/17 19:50:31 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86XKB.c,v 3.6 1996/12/28 11:14:43 dawes Exp $ */ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XI.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "xf86_Config.h" + +#include "XKBsrv.h" + +#ifdef AMOEBA +#define LED_CAP IOP_LED_CAP +#define LED_NUM IOP_LED_NUM +#define LED_SCR IOP_LED_SCROLL +#endif + +#ifdef MINIX +#define LED_CAP KBD_LEDS_CAPS +#define LED_NUM KBD_LEDS_NUM +#define LED_SCR KBD_LEDS_SCROLL +#endif + +void +xf86InitXkb() +{ +} + +void +#if NeedFunctionPrototypes +XkbDDXUpdateIndicators(DeviceIntPtr pXDev,CARD32 new) +#else +XkbDDXUpdateIndicators(pXDev,new) + DeviceIntPtr pXDev; + CARD32 new; +#endif +{ + CARD32 old; +#ifdef DEBUG +/* if (xkbDebugFlags)*/ + ErrorF("XkbDDXUpdateIndicators(...,0x%x) -- XFree86 version\n",new); +#endif +#ifdef LED_CAP + old= new; + new= 0; + if (old&XLED1) new|= LED_CAP; + if (old&XLED2) new|= LED_NUM; + if (old&XLED3) new|= LED_SCR; +#endif + xf86SetKbdLeds(new); + return; +} + +void +#if NeedFunctionPrototypes +XkbDDXUpdateDeviceIndicators( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + CARD32 new) +#else +XkbDDXUpdateDeviceIndicators(dev,sli,new) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + CARD32 new; +#endif +{ + if (sli->fb.kf==dev->kbdfeed) + XkbDDXUpdateIndicators(dev,new); + else if (sli->class==KbdFeedbackClass) { + KbdFeedbackPtr kf; + kf= sli->fb.kf; + if (kf && kf->CtrlProc) { + (*kf->CtrlProc)(dev,&kf->ctrl); + } + } + else if (sli->class==LedFeedbackClass) { + LedFeedbackPtr lf; + lf= sli->fb.lf; + if (lf && lf->CtrlProc) { + (*lf->CtrlProc)(dev,&lf->ctrl); + } + } + return; +} diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c new file mode 100644 index 000000000..7659deb3f --- /dev/null +++ b/hw/xfree86/common/xf86Xinput.c @@ -0,0 +1,1264 @@ +/* $Xorg: xf86Xinput.c,v 1.3 2000/08/17 19:50:31 cpqbld Exp $ */ +/* + * Copyright 1995,1996 by Frederic Lepied, France. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Xinput.c,v 3.22.2.7 1998/02/07 10:05:22 hohndel Exp $ */ + +#include "Xmd.h" +#include "XI.h" +#include "XIproto.h" +#include "xf86.h" +#include "Xpoll.h" +#include "xf86Priv.h" +#include "xf86_Config.h" +#include "xf86Xinput.h" +#include "xf86Procs.h" +#include "mipointer.h" + +#ifdef DPMSExtension +#include "extensions/dpms.h" +#endif + +#include "exevents.h" /* AddInputDevice */ + +#include "extnsionst.h" +#include "extinit.h" /* LookupDeviceIntRec */ + +#include "windowstr.h" /* screenIsSaved */ + +#include + +extern InputInfo inputInfo; + +#ifndef DYNAMIC_MODULE +#ifdef JOYSTICK_SUPPORT +extern DeviceAssocRec joystick_assoc; +#endif +#ifdef WACOM_SUPPORT +extern DeviceAssocRec wacom_stylus_assoc; +extern DeviceAssocRec wacom_cursor_assoc; +extern DeviceAssocRec wacom_eraser_assoc; +#endif +#ifdef ELOGRAPHICS_SUPPORT +extern DeviceAssocRec elographics_assoc; +#endif +#ifdef SUMMASKETCH_SUPPORT +extern DeviceAssocRec summasketch_assoc; +#endif +#endif + +extern DeviceAssocRec mouse_assoc; + +static int num_devices; +static LocalDevicePtr *localDevices; +static int max_devices; + +static DeviceAssocPtr *deviceAssoc = NULL; +static int numAssoc = 0; +static int maxAssoc = 0; + +static SymTabRec XinputTab[] = { + { ENDSECTION, "endsection"}, + { SUBSECTION, "subsection" }, + { -1, "" }, +}; + +/*********************************************************************** + * + * xf86AlwaysCoreControl -- + * + * Control proc for the integer feedback that controls the always + * core feature. + * + *********************************************************************** + */ +static void +xf86AlwaysCoreControl(DeviceIntPtr device, + IntegerCtrl *control) +{ +} + +/*********************************************************************** + * + * Core devices functions -- + * + * Test if device is the core device by checking the + * value of always core feedback and the inputInfo struct. + * + *********************************************************************** + */ +int +xf86IsCorePointer(DeviceIntPtr device) +{ + LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; + + return((local->always_core_feedback && + local->always_core_feedback->ctrl.integer_displayed) || + (device == inputInfo.pointer)); +} + +static int +xf86IsAlwaysCore(DeviceIntPtr device) +{ + LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; + + return(local->always_core_feedback && + local->always_core_feedback->ctrl.integer_displayed); +} + +int +xf86IsCoreKeyboard(DeviceIntPtr device) +{ + LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; + + return((local->flags & XI86_ALWAYS_CORE) || + (device == inputInfo.keyboard)); +} + +void +xf86AlwaysCore(LocalDevicePtr local, + Bool always) +{ + if (always) { + local->flags |= XI86_ALWAYS_CORE; + } else { + local->flags &= ~XI86_ALWAYS_CORE; + } +} + +/*********************************************************************** + * + * xf86CheckButton -- + * + * Test if the core pointer button state is coherent with + * the button event to send. + * + *********************************************************************** + */ +Bool +xf86CheckButton(int button, + int down) +{ + /* The device may have up to MSE_MAXBUTTONS (12) buttons. */ + int state = (inputInfo.pointer->button->state & 0x0fff00) >> 8; + int check = (state & (1 << (button - 1))); + + if ((check && down) && (!check && !down)) { + return FALSE; + } + + return TRUE; +} + +/*********************************************************************** + * + * ReadInput -- + * Wakeup handler to catch input and dispatch it to our + * input routines if necessary. + * + *********************************************************************** + */ +static void +ReadInput(pointer block_data, + int select_status, + pointer read_mask) +{ + int i; + LocalDevicePtr local_dev; + fd_set* LastSelectMask = (fd_set*) read_mask; + fd_set devices_with_input; + extern fd_set EnabledDevices; + + if (select_status < 1) + return; + + XFD_ANDSET(&devices_with_input, LastSelectMask, &EnabledDevices); + if (!XFD_ANYSET(&devices_with_input)) + return; + + for (i = 0; i < num_devices; i++) { + local_dev = localDevices[i]; + if (local_dev->read_input && + (local_dev->fd >= 0) && + (FD_ISSET(local_dev->fd, ((fd_set *) read_mask)) != 0)) { + (*local_dev->read_input)(local_dev); + break; + } + } +} + +/*********************************************************************** + * + * configExtendedInputSection -- + * + *********************************************************************** + */ + +void +xf86ConfigExtendedInputSection(LexPtr val) +{ + int i; + int token; + +#ifndef DYNAMIC_MODULE +# ifdef JOYSTICK_SUPPORT + xf86AddDeviceAssoc(&joystick_assoc); +# endif +# ifdef WACOM_SUPPORT + xf86AddDeviceAssoc(&wacom_stylus_assoc); + xf86AddDeviceAssoc(&wacom_cursor_assoc); + xf86AddDeviceAssoc(&wacom_eraser_assoc); +# endif +# ifdef ELOGRAPHICS_SUPPORT + xf86AddDeviceAssoc(&elographics_assoc); +# endif +# ifdef SUMMASKETCH_SUPPORT + xf86AddDeviceAssoc(&summasketch_assoc); +# endif +#endif + + xf86AddDeviceAssoc(&mouse_assoc); + + num_devices = 0; + max_devices = 3; + localDevices = (LocalDevicePtr*) xalloc(sizeof(LocalDevicePtr)*max_devices); + + while ((token = xf86GetToken(XinputTab)) != ENDSECTION) + { + if (token == SUBSECTION) + { + int found = 0; + + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("SubSection name expected"); + + for(i=0; !found && istr, deviceAssoc[i]->config_section_name) == 0) + { + if (num_devices == max_devices) { + max_devices *= 2; + localDevices = (LocalDevicePtr*) xrealloc(localDevices, + sizeof(LocalDevicePtr)*max_devices); + } + localDevices[num_devices] = deviceAssoc[i]->device_allocate(); + + if (localDevices[num_devices] && localDevices[num_devices]->device_config) + { + (*localDevices[num_devices]->device_config)(localDevices, + num_devices, + num_devices+1, + val); + localDevices[num_devices]->flags |= XI86_CONFIGURED; + num_devices++; + } + found = 1; + } + } + if (!found) + xf86ConfigError("Invalid SubSection name"); + } + else + xf86ConfigError("XInput keyword section expected"); + } +} + +/*********************************************************************** + * + * xf86AddDeviceAssoc -- + * + * Add an association to the array deviceAssoc. This is needed to + * allow dynamic loading of devices to register themself. + * + *********************************************************************** + */ +void +xf86AddDeviceAssoc(DeviceAssocPtr assoc) +{ + if (!deviceAssoc) { + maxAssoc = 10; + deviceAssoc = (DeviceAssocPtr*) xalloc(sizeof(DeviceAssocPtr)*maxAssoc); + } else { + if (maxAssoc == numAssoc) { + maxAssoc *= 2; + deviceAssoc = (DeviceAssocPtr*) xrealloc(deviceAssoc, sizeof(DeviceAssocPtr)*maxAssoc); + } + } + deviceAssoc[numAssoc] = assoc; + numAssoc++; +} + +/*********************************************************************** + * + * xf86XinputFinalizeInit -- + * + * Create and initialize an integer feedback to control the always + * core feature. + * + *********************************************************************** + */ +void +xf86XinputFinalizeInit(DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + + if (InitIntegerFeedbackClassDeviceStruct(dev, xf86AlwaysCoreControl) == FALSE) { + ErrorF("Unable to init integer feedback for always core feature\n"); + } else { + local->always_core_feedback = dev->intfeed; + dev->intfeed->ctrl.integer_displayed = (local->flags & XI86_ALWAYS_CORE) ? 1 : 0; + } +} + + +/*********************************************************************** + * + * InitExtInput -- + * + * Initialize any extended devices we might have. It is called from + * ddx InitInput. + * + *********************************************************************** + */ + +void +InitExtInput() +{ + DeviceIntPtr dev; + int i; + + /* Register a Wakeup handler to handle input when generated */ + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr) NoopDDA, ReadInput, + NULL); + + /* Add each device */ + for (i = 0; i < num_devices; i++) { + if (localDevices[i]->flags & XI86_CONFIGURED) { + int open_on_init; + + open_on_init = !(localDevices[i]->flags & XI86_NO_OPEN_ON_INIT) || + (localDevices[i]->flags & XI86_ALWAYS_CORE); + + dev = AddInputDevice(localDevices[i]->device_control, + open_on_init); + if (dev == NULL) + FatalError("Too many input devices"); + + localDevices[i]->atom = MakeAtom(localDevices[i]->name, + strlen(localDevices[i]->name), + TRUE); + dev->public.devicePrivate = (pointer) localDevices[i]; + localDevices[i]->dev = dev; + + xf86XinputFinalizeInit(dev); + + RegisterOtherDevice(dev); + if (serverGeneration == 1) + ErrorF("%s Adding extended device \"%s\" (type: %s)\n", XCONFIG_GIVEN, + localDevices[i]->name, localDevices[i]->type_name); + } + } +} + + +/*********************************************************************** + * + * Caller: ProcXOpenDevice + * + * This is the implementation-dependent routine to open an input device. + * Some implementations open all input devices when the server is first + * initialized, and never close them. Other implementations open only + * the X pointer and keyboard devices during server initialization, + * and only open other input devices when some client makes an + * XOpenDevice request. This entry point is for the latter type of + * implementation. + * + * If the physical device is not already open, do it here. In this case, + * you need to keep track of the fact that one or more clients has the + * device open, and physically close it when the last client that has + * it open does an XCloseDevice. + * + * The default implementation is to do nothing (assume all input devices + * are opened during X server initialization and kept open). + * + *********************************************************************** + */ + +void +OpenInputDevice (dev, client, status) + DeviceIntPtr dev; + ClientPtr client; + int *status; +{ + extern int BadDevice; + + if (!dev->inited) { + *status = BadDevice; + } else { + if (!dev->public.on) { + if (!EnableDevice(dev)) { + *status = BadDevice; + } else { + /* to prevent ProcXOpenDevice to call EnableDevice again */ + dev->startup = FALSE; + } + } + } +} + + +/*********************************************************************** + * + * Caller: ProcXChangeKeyboardDevice + * + * This procedure does the implementation-dependent portion of the work + * needed to change the keyboard device. + * + * The X keyboard device has a FocusRec. If the device that has been + * made into the new X keyboard did not have a FocusRec, + * ProcXChangeKeyboardDevice will allocate one for it. + * + * If you do not want clients to be able to focus the old X keyboard + * device, call DeleteFocusClassDeviceStruct to free the FocusRec. + * + * If you support input devices with keys that you do not want to be + * used as the X keyboard, you need to check for them here and return + * a BadDevice error. + * + * The default implementation is to do nothing (assume you do want + * clients to be able to focus the old X keyboard). The commented-out + * sample code shows what you might do if you don't want the default. + * + *********************************************************************** + */ + +int +ChangeKeyboardDevice (old_dev, new_dev) + DeviceIntPtr old_dev; + DeviceIntPtr new_dev; +{ + /********************************************************************** + * DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c * + **********************************************************************/ + return !Success; +} + + +/*********************************************************************** + * + * Caller: ProcXChangePointerDevice + * + * This procedure does the implementation-dependent portion of the work + * needed to change the pointer device. + * + * The X pointer device does not have a FocusRec. If the device that + * has been made into the new X pointer had a FocusRec, + * ProcXChangePointerDevice will free it. + * + * If you want clients to be able to focus the old pointer device that + * has now become accessible through the input extension, you need to + * add a FocusRec to it here. + * + * The XChangePointerDevice protocol request also allows the client + * to choose which axes of the new pointer device are used to move + * the X cursor in the X- and Y- directions. If the axes are different + * than the default ones, you need to keep track of that here. + * + * If you support input devices with valuators that you do not want to be + * used as the X pointer, you need to check for them here and return a + * BadDevice error. + * + * The default implementation is to do nothing (assume you don't want + * clients to be able to focus the old X pointer). The commented-out + * sample code shows what you might do if you don't want the default. + * + *********************************************************************** + */ + +int +#ifdef NeedFunctionPrototypes +ChangePointerDevice ( + DeviceIntPtr old_dev, + DeviceIntPtr new_dev, + unsigned char x, + unsigned char y) +#else +ChangePointerDevice (old_dev, new_dev, x, y) + DeviceIntPtr old_dev, new_dev; + unsigned char x, y; +#endif /* NeedFunctionPrototypes */ +{ + /************************************************************************ + InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr* + + x_axis = x; * keep track of new x-axis* + y_axis = y; * keep track of new y-axis* + if (x_axis != 0 || y_axis != 1) + axes_changed = TRUE; * remember axes have changed* + else + axes_changed = FALSE; + *************************************************************************/ + /* + * We don't allow axis swap or other exotic features. + */ + if (x == 0 && y == 1) { + LocalDevicePtr old_local = (LocalDevicePtr)old_dev->public.devicePrivate; + LocalDevicePtr new_local = (LocalDevicePtr)new_dev->public.devicePrivate; + + InitFocusClassDeviceStruct(old_dev); + + /* Restore Extended motion history information */ + old_dev->valuator->GetMotionProc = old_local->motion_history_proc; + old_dev->valuator->numMotionEvents = old_local->history_size; + + /* Save Extended motion history information */ + new_local->motion_history_proc = new_dev->valuator->GetMotionProc; + new_local->history_size = new_dev->valuator->numMotionEvents; + + /* Set Core motion history information */ + new_dev->valuator->GetMotionProc = miPointerGetMotionEvents; + new_dev->valuator->numMotionEvents = miPointerGetMotionBufferSize(); + + return Success; + } + else + return !Success; +} + + +/*********************************************************************** + * + * Caller: ProcXCloseDevice + * + * Take care of implementation-dependent details of closing a device. + * Some implementations may actually close the device, others may just + * remove this clients interest in that device. + * + * The default implementation is to do nothing (assume all input devices + * are initialized during X server initialization and kept open). + * + *********************************************************************** + */ + +void +CloseInputDevice (d, client) + DeviceIntPtr d; + ClientPtr client; +{ + ErrorF("ProcXCloseDevice to close or not ?\n"); +} + + +/*********************************************************************** + * + * Caller: ProcXListInputDevices + * + * This is the implementation-dependent routine to initialize an input + * device to the point that information about it can be listed. + * Some implementations open all input devices when the server is first + * initialized, and never close them. Other implementations open only + * the X pointer and keyboard devices during server initialization, + * and only open other input devices when some client makes an + * XOpenDevice request. If some other process has the device open, the + * server may not be able to get information about the device to list it. + * + * This procedure should be used by implementations that do not initialize + * all input devices at server startup. It should do device-dependent + * initialization for any devices not previously initialized, and call + * AddInputDevice for each of those devices so that a DeviceIntRec will be + * created for them. + * + * The default implementation is to do nothing (assume all input devices + * are initialized during X server initialization and kept open). + * The commented-out sample code shows what you might do if you don't want + * the default. + * + *********************************************************************** + */ + +void +AddOtherInputDevices () +{ +} + + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceMode (client, dev, mode) + register ClientPtr client; + DeviceIntPtr dev; + int mode; +{ + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + + if (local->switch_mode) { + return (*local->switch_mode)(client, dev, mode); + } + else + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators) + register ClientPtr client; + DeviceIntPtr dev; + int *valuators; + int first_valuator; + int num_valuators; +{ + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + *********************************************************************** + */ + +int +ChangeDeviceControl (client, dev, control) + register ClientPtr client; + DeviceIntPtr dev; + xDeviceCtl *control; +{ + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + + if (!local->control_proc) { + return (BadMatch); + } + else { + return (*local->control_proc)(local, control); + } +} + +/* + * adapted from mieq.c to support extended events + * + */ +extern InputInfo inputInfo; + +#define QUEUE_SIZE 256 + +typedef struct _Event { + xEvent event; +#ifdef XINPUT + deviceValuator val; +#endif + ScreenPtr pScreen; +} EventRec, *EventPtr; + +typedef struct _EventQueue { + HWEventQueueType head, tail; + CARD32 lastEventTime; /* to avoid time running backwards */ + Bool lastMotion; + EventRec events[QUEUE_SIZE]; /* static allocation for signals */ + DevicePtr pKbd, pPtr; /* device pointer, to get funcs */ + ScreenPtr pEnqueueScreen; /* screen events are being delivered to */ + ScreenPtr pDequeueScreen; /* screen events are being dispatched to */ +} EventQueueRec, *EventQueuePtr; + +static EventQueueRec xf86EventQueue; + +Bool +xf86eqInit (pKbd, pPtr) + DevicePtr pKbd, pPtr; +{ + xf86EventQueue.head = xf86EventQueue.tail = 0; + xf86EventQueue.lastEventTime = GetTimeInMillis (); + xf86EventQueue.pKbd = pKbd; + xf86EventQueue.pPtr = pPtr; + xf86EventQueue.lastMotion = FALSE; + xf86EventQueue.pEnqueueScreen = screenInfo.screens[0]; + xf86EventQueue.pDequeueScreen = xf86EventQueue.pEnqueueScreen; + SetInputCheck (&xf86EventQueue.head, &xf86EventQueue.tail); + return TRUE; +} + +/* + * Must be reentrant with ProcessInputEvents. Assumption: xf86eqEnqueue + * will never be interrupted. If this is called from both signal + * handlers and regular code, make sure the signal is suspended when + * called from regular code. + */ + +void +xf86eqEnqueue (e) + xEvent *e; +{ + int oldtail, newtail; + Bool isMotion; +#ifdef XINPUT + int count; + + switch (e->u.u.type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + count = 1; + break; + default: + if (!((deviceKeyButtonPointer *) e)->deviceid & MORE_EVENTS) + { + count = 1; + } + else + { + count = 2; + } + break; + } +#endif + + oldtail = xf86EventQueue.tail; + isMotion = e->u.u.type == MotionNotify; + if (isMotion && xf86EventQueue.lastMotion && oldtail != xf86EventQueue.head) + { + if (oldtail == 0) + oldtail = QUEUE_SIZE; + oldtail = oldtail - 1; + } + else + { + newtail = oldtail + 1; + if (newtail == QUEUE_SIZE) + newtail = 0; + /* Toss events which come in late */ + if (newtail == xf86EventQueue.head) + return; + xf86EventQueue.tail = newtail; + } + + xf86EventQueue.lastMotion = isMotion; + xf86EventQueue.events[oldtail].event = *e; +#ifdef XINPUT + if (count == 2) + { + xf86EventQueue.events[oldtail].val = *((deviceValuator *) (((deviceKeyButtonPointer *) e)+1)); + } +#endif + /* + * Make sure that event times don't go backwards - this + * is "unnecessary", but very useful + */ + if (e->u.keyButtonPointer.time < xf86EventQueue.lastEventTime && + xf86EventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000) + { + xf86EventQueue.events[oldtail].event.u.keyButtonPointer.time = + xf86EventQueue.lastEventTime; + } + xf86EventQueue.events[oldtail].pScreen = xf86EventQueue.pEnqueueScreen; +} + +/* + * Call this from ProcessInputEvents() + */ +void +xf86eqProcessInputEvents () +{ + EventRec *e; + int x, y; + xEvent xe; +#ifdef XINPUT + DeviceIntPtr dev; + int id, count; + deviceKeyButtonPointer *dev_xe; +#endif + + while (xf86EventQueue.head != xf86EventQueue.tail) + { + if (screenIsSaved == SCREEN_SAVER_ON) + SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset); +#ifdef DPMSExtension + if (DPMSPowerLevel != DPMSModeOn) + DPMSSet(DPMSModeOn); +#endif + + e = &xf86EventQueue.events[xf86EventQueue.head]; + /* + * Assumption - screen switching can only occur on motion events + */ + if (e->pScreen != xf86EventQueue.pDequeueScreen) + { + xf86EventQueue.pDequeueScreen = e->pScreen; + x = e->event.u.keyButtonPointer.rootX; + y = e->event.u.keyButtonPointer.rootY; + if (xf86EventQueue.head == QUEUE_SIZE - 1) + xf86EventQueue.head = 0; + else + ++xf86EventQueue.head; + NewCurrentScreen (xf86EventQueue.pDequeueScreen, x, y); + } + else + { + xe = e->event; + if (xf86EventQueue.head == QUEUE_SIZE - 1) + xf86EventQueue.head = 0; + else + ++xf86EventQueue.head; + switch (xe.u.u.type) + { + case KeyPress: + case KeyRelease: + (*xf86EventQueue.pKbd->processInputProc) + (&xe, (DeviceIntPtr)xf86EventQueue.pKbd, 1); + break; +#ifdef XINPUT + case ButtonPress: + case ButtonRelease: + case MotionNotify: + (*(inputInfo.pointer->public.processInputProc)) + (&xe, (DeviceIntPtr)inputInfo.pointer, 1); + break; + + default: + dev_xe = (deviceKeyButtonPointer *) e; + id = dev_xe->deviceid & DEVICE_BITS; + if (!(dev_xe->deviceid & MORE_EVENTS)) { + count = 1; + } else { + count = 2; + } + dev = LookupDeviceIntRec(id); + if (dev == NULL) + { + ErrorF("LookupDeviceIntRec id=0x%x not found\n", id); +/* FatalError("xf86eqProcessInputEvents : device not found.\n"); + */ + break; + } + if (!dev->public.processInputProc) + { + FatalError("xf86eqProcessInputEvents : device has no input proc.\n"); + break; + } + (*dev->public.processInputProc)(&e->event, dev, count); +#else + default: + (*xf86EventQueue.pPtr->processInputProc) + (&xe, (DeviceIntPtr)xf86EventQueue.pPtr, 1); +#endif + break; + } + } + } +} + +/* + * convenient functions to post events + */ + +void +xf86PostMotionEvent(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int loop; + xEvent xE[2]; + deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE; + deviceValuator *xv = (deviceValuator*) xev+1; + LocalDevicePtr local = (LocalDevicePtr)device->public.devicePrivate; + char *buff; + Time current = GetTimeInMillis(); + + if (HAS_MOTION_HISTORY(local)) { + buff = ((char *)local->motion_history + + (sizeof(INT32) * local->dev->valuator->numAxes + sizeof(Time)) * local->last); + } else + buff = 0; + + va_start(var, num_valuators); + + for(loop=0; loopvaluator0 = va_arg(var, int); + break; + case 1: + xv->valuator1 = va_arg(var, int); + break; + case 2: + xv->valuator2 = va_arg(var, int); + break; + case 3: + xv->valuator3 = va_arg(var, int); + break; + case 4: + xv->valuator4 = va_arg(var, int); + break; + case 5: + xv->valuator5 = va_arg(var, int); + break; + } + if ((loop % 6 == 5) || (loop == num_valuators - 1)) { + if (!xf86IsCorePointer(device)) { + xev->type = DeviceMotionNotify; + xev->detail = 0; + xf86Info.lastEventTime = xev->time = current; + xev->deviceid = device->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = device->id; + + xv->num_valuators = (loop % 6) + 1; + xv->first_valuator = first_valuator + (loop / 6) * 6; + xv->device_state = 0; + + if (HAS_MOTION_HISTORY(local)) { + *(Time*)buff = current; + memcpy(buff+sizeof(Time)+sizeof(INT32)*xv->first_valuator, &xv->valuator0, + sizeof(INT32)*xv->num_valuators); + } + + xf86eqEnqueue(xE); + } else { + xf86Info.lastEventTime = current; + + if (num_valuators >= 2) { + if (is_absolute) { + miPointerAbsoluteCursor(xv->valuator0, xv->valuator1, xf86Info.lastEventTime); + } else { + if (device->ptrfeed) { + /* modeled from xf86Events.c */ + if ((abs(xv->valuator0) + abs(xv->valuator1)) >= device->ptrfeed->ctrl.threshold) { + xv->valuator0 = (xv->valuator0 * device->ptrfeed->ctrl.num) / device->ptrfeed->ctrl.den; + xv->valuator1 = (xv->valuator1 * device->ptrfeed->ctrl.num) / device->ptrfeed->ctrl.den; + } + } + miPointerDeltaCursor(xv->valuator0, xv->valuator1, xf86Info.lastEventTime); + } + } + break; + } + } + va_end(var); + } + if (HAS_MOTION_HISTORY(local)) { + local->last = (local->last + 1) % device->valuator->numMotionEvents; + if (local->last == local->first) + local->first = (local->first + 1) % device->valuator->numMotionEvents; + } +} + +void +xf86PostProximityEvent(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int loop; + xEvent xE[2]; + deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE; + deviceValuator *xv = (deviceValuator*) xev+1; + + va_start(var, num_valuators); + + for(loop=0; loopvaluator0 = va_arg(var, int); + break; + case 1: + xv->valuator1 = va_arg(var, int); + break; + case 2: + xv->valuator2 = va_arg(var, int); + break; + case 3: + xv->valuator3 = va_arg(var, int); + break; + case 4: + xv->valuator4 = va_arg(var, int); + break; + case 5: + xv->valuator5 = va_arg(var, int); + break; + } + if ((loop % 6 == 5) || (loop == num_valuators - 1)) { + xev->type = is_in ? ProximityIn : ProximityOut; + xev->detail = 0; + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + xev->deviceid = device->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = device->id; + + xv->num_valuators = (loop % 6) + 1; + xv->first_valuator = first_valuator + (loop / 6) * 6; + xv->device_state = 0; + + xf86eqEnqueue(xE); + } + } + va_end(var); +} + +void +xf86PostButtonEvent(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int loop; + xEvent xE[2]; + deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE; + deviceValuator *xv = (deviceValuator*) xev+1; + int is_core_pointer = xf86IsCorePointer(device); + + /* Check the core pointer button state not to send an inconsistent + * event. This can happen with the AlwaysCore feature. + */ + if (is_core_pointer && !xf86CheckButton(button, is_down)) { + return; + } + + va_start(var, num_valuators); + + + for(loop=0; loopvaluator0 = va_arg(var, int); + break; + case 1: + xv->valuator1 = va_arg(var, int); + break; + case 2: + xv->valuator2 = va_arg(var, int); + break; + case 3: + xv->valuator3 = va_arg(var, int); + break; + case 4: + xv->valuator4 = va_arg(var, int); + break; + case 5: + xv->valuator5 = va_arg(var, int); + break; + } + if (((loop % 6 == 5) || (loop == num_valuators - 1)) && + !is_core_pointer) { + xev->type = is_down ? DeviceButtonPress : DeviceButtonRelease; + xev->detail = button; + + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + xev->deviceid = device->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->device_state = 0; + /* if the device is in the relative mode we don't have to send valuators */ + xv->num_valuators = is_absolute ? (loop % 6) + 1 : 0; + xv->first_valuator = first_valuator + (loop / 6) * 6; + xf86eqEnqueue(xE); + /* if the device is in the relative mode only one event is needed */ + if (!is_absolute) break; + } + if (is_core_pointer && loop == 1) { + int cx, cy; + + GetSpritePosition(&cx, &cy); + + /* Try to find the index in the core buttons map + * which corresponds to the extended button for + * an AlwaysCore device. + */ + if (xf86IsAlwaysCore(device)) { + int loop; + + button = device->button->map[button]; + + for(loop=1; loop<=inputInfo.pointer->button->numButtons; loop++) { + if (inputInfo.pointer->button->map[loop] == button) { + button = loop; + break; + } + } + } + + xE->u.u.type = is_down ? ButtonPress : ButtonRelease; + xE->u.u.detail = button; + xE->u.keyButtonPointer.rootY = cx; + xE->u.keyButtonPointer.rootX = cy; + xf86Info.lastEventTime = xE->u.keyButtonPointer.time = GetTimeInMillis(); + xf86eqEnqueue(xE); + break; + } + } + va_end(var); +} + +void +xf86PostKeyEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int loop; + xEvent xE[2]; + deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE; + deviceValuator *xv = (deviceValuator*) xev+1; + + va_start(var, num_valuators); + + + for(loop=0; loopvaluator0 = va_arg(var, int); + break; + case 1: + xv->valuator1 = va_arg(var, int); + break; + case 2: + xv->valuator2 = va_arg(var, int); + break; + case 3: + xv->valuator3 = va_arg(var, int); + break; + case 4: + xv->valuator4 = va_arg(var, int); + break; + case 5: + xv->valuator5 = va_arg(var, int); + break; + } + if (((loop % 6 == 5) || (loop == num_valuators - 1))) { + xev->type = is_down ? DeviceKeyPress : DeviceKeyRelease; + xev->detail = key_code; + + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + xev->deviceid = device->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->device_state = 0; + /* if the device is in the relative mode we don't have to send valuators */ + xv->num_valuators = is_absolute ? (loop % 6) + 1 : 0; + xv->first_valuator = first_valuator + (loop / 6) * 6; + + xf86eqEnqueue(xE); + /* if the device is in the relative mode only one event is needed */ + if (!is_absolute) break; + } + } + va_end(var); +} + +/* + * Motion history management. + */ + +void +xf86MotionHistoryAllocate(LocalDevicePtr local) +{ + ValuatorClassPtr valuator = local->dev->valuator; + + if (!HAS_MOTION_HISTORY(local)) + return; + + local->motion_history = xalloc((sizeof(INT32) * valuator->numAxes + sizeof(Time)) + * valuator->numMotionEvents); + local->first = 0; + local->last = 0; +} + +int +xf86GetMotionEvents(DeviceIntPtr dev, + xTimecoord *buff, + unsigned long start, + unsigned long stop, + ScreenPtr pScreen) +{ + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + ValuatorClassPtr valuator = dev->valuator; + int num = 0; + int loop = local->first; + int size; + Time current; + + if (!HAS_MOTION_HISTORY(local)) + return 0; + + size = (sizeof(INT32) * valuator->numAxes + sizeof(Time)); + + while (loop != local->last) { + current = *(Time*)(((char *)local->motion_history)+loop*size); + if (current > stop) + return num; + if (current >= start) { + memcpy(((char *)buff)+size*num, + ((char *)local->motion_history)+loop*size, size); + num++; + } + loop = (loop + 1) % valuator->numMotionEvents; + } + return num; +} + +/* end of xf86Xinput.c */ diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h new file mode 100644 index 000000000..b2bb8832f --- /dev/null +++ b/hw/xfree86/common/xf86Xinput.h @@ -0,0 +1,280 @@ +/* $Xorg: xf86Xinput.h,v 1.3 2000/08/17 19:50:31 cpqbld Exp $ */ +/* + * Copyright 1995,1996 by Frederic Lepied, France. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Xinput.h,v 3.14.2.1 1997/05/12 12:52:29 hohndel Exp $ */ + +#ifndef _xf86Xinput_h +#define _xf86Xinput_h + +#ifndef NEED_EVENTS +#define NEED_EVENTS +#endif +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "XI.h" +#include "XIproto.h" +#include "XIstubs.h" + +#define XI86_NO_OPEN_ON_INIT 1 /* open the device only when needed */ +#define XI86_CONFIGURED 2 /* the device has been configured */ +#define XI86_ALWAYS_CORE 4 /* the device always controls the pointer */ + +#ifdef PRIVATE +#undef PRIVATE +#endif +#define PRIVATE(dev) (((LocalDevicePtr)((dev)->public.devicePrivate))->private) + +#ifdef HAS_MOTION_HISTORY +#undef HAS_MOTION_HISTORY +#endif +#define HAS_MOTION_HISTORY(local) ((local)->dev->valuator && (local)->dev->valuator->numMotionEvents) + +typedef struct _LocalDeviceRec { + char *name; + int flags; + Bool (*device_config)( +#if NeedNestedPrototypes + struct _LocalDeviceRec** /*array*/, + int /*index*/, + int /*max*/, + LexPtr /*val*/ +#endif + ); + Bool (*device_control)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + int /*what*/ +#endif + ); + void (*read_input)( +#if NeedNestedPrototypes + struct _LocalDeviceRec* /*local*/ +#endif + ); + int (*control_proc)( +#if NeedNestedPrototypes + struct _LocalDeviceRec* /*local*/, + xDeviceCtl* /* control */ +#endif + ); + void (*close_proc)( +#if NeedNestedPrototypes + struct _LocalDeviceRec* /*local*/ +#endif + ); + int (*switch_mode)( +#if NeedNestedPrototypes + ClientPtr /*client*/, + DeviceIntPtr /*dev*/, + int /*mode*/ +#endif + ); + int fd; + Atom atom; + DeviceIntPtr dev; + pointer private; + int private_flags; + pointer motion_history; + ValuatorMotionProcPtr motion_history_proc; + unsigned int history_size; /* only for configuration purpose */ + unsigned int first; + unsigned int last; + char *type_name; + IntegerFeedbackPtr always_core_feedback; +} LocalDeviceRec, *LocalDevicePtr; + +typedef struct _DeviceAssocRec +{ + char *config_section_name; + LocalDevicePtr (*device_allocate)( +#if NeedNestedPrototypes + void +#endif +); +} DeviceAssocRec, *DeviceAssocPtr; + +extern int DeviceKeyPress; +extern int DeviceKeyRelease; +extern int DeviceButtonPress; +extern int DeviceButtonRelease; +extern int DeviceMotionNotify; +extern int DeviceValuator; +extern int ProximityIn; +extern int ProximityOut; + +extern int +xf86IsCorePointer( +#if NeedFunctionPrototypes + DeviceIntPtr /*dev*/ +#endif +); + +extern int +xf86IsCoreKeyboard( +#if NeedFunctionPrototypes + DeviceIntPtr /*dev*/ +#endif +); + +extern void +xf86AlwaysCore( +#if NeedFunctionPrototypes + LocalDevicePtr /*local*/, + Bool /*always*/ +#endif +); + +void +xf86configExtendedInputSection( +#ifdef NeedFunctionPrototypes + LexPtr /* val */ +#endif +); + +void +xf86AddDeviceAssoc( +#ifdef NeedFunctionPrototypes + DeviceAssocPtr /* assoc */ +#endif +); + +void +InitExtInput( +#ifdef NeedFunctionPrototypes + void +#endif +); + +Bool +xf86eqInit ( +#ifdef NeedFunctionPrototypes + DevicePtr /* pKbd */, + DevicePtr /* pPtr */ +#endif +); + +void +xf86eqEnqueue ( +#ifdef NeedFunctionPrototypes + struct _xEvent * /*event */ +#endif +); + +void +xf86eqProcessInputEvents ( +#ifdef NeedFunctionPrototypes + void +#endif +); + +void +xf86PostMotionEvent( +#if NeedVarargsPrototypes + DeviceIntPtr /*device*/, + int /*is_absolute*/, + int /*first_valuator*/, + int /*num_valuators*/, + ... +#endif +); + +void +xf86PostProximityEvent( +#if NeedVarargsPrototypes + DeviceIntPtr /*device*/, + int /*is_in*/, + int /*first_valuator*/, + int /*num_valuators*/, + ... +#endif +); + +void +xf86PostButtonEvent( +#if NeedVarargsPrototypes + DeviceIntPtr /*device*/, + int /*is_absolute*/, + int /*button*/, + int /*is_down*/, + int /*first_valuator*/, + int /*num_valuators*/, + ... +#endif +); + +void +xf86PostKeyEvent( +#if NeedVarargsPrototypes + DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ... +#endif +); + +void +xf86AddDeviceAssoc( +#if NeedFunctionPrototypes + DeviceAssocPtr /*assoc*/ +#endif +); + +void +xf86MotionHistoryAllocate( +#if NeedFunctionPrototypes + LocalDevicePtr local +#endif +); + +int +xf86GetMotionEvents( +#if NeedFunctionPrototypes + DeviceIntPtr dev, + xTimecoord *buff, + unsigned long start, + unsigned long stop, + ScreenPtr pScreen +#endif +); + +void +xf86XinputFinalizeInit( +#if NeedFunctionPrototypes + DeviceIntPtr dev +#endif +); + +Bool +xf86CheckButton( +#if NeedFunctionPrototypes + int button, + int down +#endif +); + +#endif /* _xf86Xinput_h */ diff --git a/hw/xfree86/dixmods/extmod/xf86vmode.c b/hw/xfree86/dixmods/extmod/xf86vmode.c new file mode 100644 index 000000000..8abab86a5 --- /dev/null +++ b/hw/xfree86/dixmods/extmod/xf86vmode.c @@ -0,0 +1,1429 @@ +/* $XFree86: xc/programs/Xserver/Xext/xf86vmode.c,v 3.25 1996/10/16 14:37:58 dawes Exp $ */ + +/* + +Copyright 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ +/* $Xorg: xf86vmode.c,v 1.3 2000/08/17 19:47:59 cpqbld Exp $ */ +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XF86VIDMODE_SERVER_ +#include "xf86vmstr.h" +#include "Xfuncproto.h" +#include "../hw/xfree86/common/xf86.h" +#include "../hw/xfree86/common/xf86Priv.h" + +extern int xf86ScreenIndex; +extern Bool xf86VidModeEnabled; +extern Bool xf86VidModeAllowNonLocal; + +static int vidmodeErrorBase; + +static int ProcXF86VidModeDispatch( +#if NeedFunctionPrototypes + ClientPtr /* client */ +#endif +); + +static int SProcXF86VidModeDispatch( +#if NeedFunctionPrototypes + ClientPtr /* client */ +#endif +); + +static void XF86VidModeResetProc( +#if NeedFunctionPrototypes + ExtensionEntry* /* extEntry */ +#endif +); + +extern void Swap32Write(); /* XXX should be in header file */ + +static unsigned char XF86VidModeReqCode = 0; + +/* The XF86VIDMODE_EVENTS code is far from complete */ + +#ifdef XF86VIDMODE_EVENTS +static int XF86VidModeEventBase = 0; + +static void SXF86VidModeNotifyEvent(); +#if NeedFunctionPrototypes + xXF86VidModeNotifyEvent * /* from */, + xXF86VidModeNotifyEvent * /* to */ +#endif +); + +extern WindowPtr *WindowTable; + +static RESTYPE EventType; /* resource type for event masks */ + +typedef struct _XF86VidModeEvent *XF86VidModeEventPtr; + +typedef struct _XF86VidModeEvent { + XF86VidModeEventPtr next; + ClientPtr client; + ScreenPtr screen; + XID resource; + CARD32 mask; +} XF86VidModeEventRec; + +static int XF86VidModeFreeEvents(); + +typedef struct _XF86VidModeScreenPrivate { + XF86VidModeEventPtr events; + Bool hasWindow; +} XF86VidModeScreenPrivateRec, *XF86VidModeScreenPrivatePtr; + +static int ScreenPrivateIndex; + +#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr)(s)->devPrivates[ScreenPrivateIndex].ptr) +#define SetScreenPrivate(s,v) ((s)->devPrivates[ScreenPrivateIndex].ptr = (pointer) v); +#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = GetScreenPrivate(s) + +#define New(t) ((t *) xalloc (sizeof (t))) +#endif + +void +XFree86VidModeExtensionInit() +{ + ExtensionEntry* extEntry; +#ifdef XF86VIDMODE_EVENTS + int i; + ScreenPtr pScreen; + + EventType = CreateNewResourceType(XF86VidModeFreeEvents); + ScreenPrivateIndex = AllocateScreenPrivateIndex (); + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + SetScreenPrivate (pScreen, NULL); + } +#endif + + if ( +#ifdef XF86VIDMODE_EVENTS + EventType && ScreenPrivateIndex != -1 && +#endif + (extEntry = AddExtension(XF86VIDMODENAME, + XF86VidModeNumberEvents, + XF86VidModeNumberErrors, + ProcXF86VidModeDispatch, + SProcXF86VidModeDispatch, + XF86VidModeResetProc, + StandardMinorOpcode))) { + XF86VidModeReqCode = (unsigned char)extEntry->base; + vidmodeErrorBase = extEntry->errorBase; +#ifdef XF86VIDMODE_EVENTS + XF86VidModeEventBase = extEntry->eventBase; + EventSwapVector[XF86VidModeEventBase] = SXF86VidModeNotifyEvent; +#endif + } +} + +/*ARGSUSED*/ +static void +XF86VidModeResetProc (extEntry) + ExtensionEntry* extEntry; +{ +} + +#ifdef XF86VIDMODE_EVENTS +static void +CheckScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (!pPriv) + return; + if (!pPriv->events && !pPriv->hasWindow) { + xfree (pPriv); + SetScreenPrivate (pScreen, NULL); + } +} + +static XF86VidModeScreenPrivatePtr +MakeScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (pPriv) + return pPriv; + pPriv = New (XF86VidModeScreenPrivateRec); + if (!pPriv) + return 0; + pPriv->events = 0; + pPriv->hasWindow = FALSE; + SetScreenPrivate (pScreen, pPriv); + return pPriv; +} + +static unsigned long +getEventMask (pScreen, client) + ScreenPtr pScreen; + ClientPtr client; +{ + SetupScreen(pScreen); + XF86VidModeEventPtr pEv; + + if (!pPriv) + return 0; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + if (pEv->client == client) + return pEv->mask; + return 0; +} + +static Bool +setEventMask (pScreen, client, mask) + ScreenPtr pScreen; + ClientPtr client; + unsigned long mask; +{ + SetupScreen(pScreen); + XF86VidModeEventPtr pEv, *pPrev; + + if (getEventMask (pScreen, client) == mask) + return TRUE; + if (!pPriv) { + pPriv = MakeScreenPrivate (pScreen); + if (!pPriv) + return FALSE; + } + for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) + if (pEv->client == client) + break; + if (mask == 0) { + *pPrev = pEv->next; + xfree (pEv); + CheckScreenPrivate (pScreen); + } else { + if (!pEv) { + pEv = New (ScreenSaverEventRec); + if (!pEv) { + CheckScreenPrivate (pScreen); + return FALSE; + } + *pPrev = pEv; + pEv->next = NULL; + pEv->client = client; + pEv->screen = pScreen; + pEv->resource = FakeClientID (client->index); + } + pEv->mask = mask; + } + return TRUE; +} + +static int +XF86VidModeFreeEvents (value, id) + pointer value; + XID id; +{ + XF86VidModeEventPtr pOld = (XF86VidModeEventPtr)value; + ScreenPtr pScreen = pOld->screen; + SetupScreen (pScreen); + XF86VidModeEventPtr pEv, *pPrev; + + if (!pPriv) + return TRUE; + for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) + if (pEv == pOld) + break; + if (!pEv) + return TRUE; + *pPrev = pEv->next; + xfree (pEv); + CheckScreenPrivate (pScreen); + return TRUE; +} + +static void +SendXF86VidModeNotify (pScreen, state, forced) + ScreenPtr pScreen; + int state; + Bool forced; +{ + XF86VidModeScreenPrivatePtr pPriv; + XF86VidModeEventPtr pEv; + unsigned long mask; + xXF86VidModeNotifyEvent ev; + ClientPtr client; + int kind; + + UpdateCurrentTimeIf (); + mask = XF86VidModeNotifyMask; + pScreen = screenInfo.screens[pScreen->myNum]; + pPriv = GetScreenPrivate(pScreen); + if (!pPriv) + return; + kind = XF86VidModeModeChange; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + { + client = pEv->client; + if (client->clientGone) + continue; + if (!(pEv->mask & mask)) + continue; + ev.type = XF86VidModeNotify + XF86VidModeEventBase; + ev.state = state; + ev.sequenceNumber = client->sequence; + ev.timestamp = currentTime.milliseconds; + ev.root = WindowTable[pScreen->myNum]->drawable.id; + ev.kind = kind; + ev.forced = forced; + WriteEventsToClient (client, 1, (xEvent *) &ev); + } +} + +static void +SXF86VidModeNotifyEvent (from, to) + xXF86VidModeNotifyEvent *from, *to; +{ + to->type = from->type; + to->state = from->state; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->timestamp, to->timestamp); + cpswapl (from->root, to->root); + to->kind = from->kind; + to->forced = from->forced; +} +#endif + +static int +ProcXF86VidModeQueryVersion(client) + register ClientPtr client; +{ + xXF86VidModeQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXF86VidModeQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XF86VIDMODE_MAJOR_VERSION; + rep.minorVersion = XF86VIDMODE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXF86VidModeQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86VidModeGetModeLine(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeGetModeLineReq); + xXF86VidModeGetModeLineReply rep; + register int n; + ScrnInfoPtr vptr; + DisplayModePtr mptr; + int privsize; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + mptr = vptr->modes; + + if (!mptr->Private) + privsize = 0; + else + privsize = mptr->PrivSize; + + REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); + rep.type = X_Reply; + rep.length = (SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xGenericReply) + + privsize * sizeof(INT32)) >> 2; + rep.sequenceNumber = client->sequence; + rep.dotclock = vptr->clock[mptr->Clock]; + rep.hdisplay = mptr->HDisplay; + rep.hsyncstart = mptr->HSyncStart; + rep.hsyncend = mptr->HSyncEnd; + rep.htotal = mptr->HTotal; + rep.vdisplay = mptr->VDisplay; + rep.vsyncstart = mptr->VSyncStart; + rep.vsyncend = mptr->VSyncEnd; + rep.vtotal = mptr->VTotal; + rep.flags = mptr->Flags; + rep.privsize = privsize; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.dotclock, n); + swaps(&rep.hdisplay, n); + swaps(&rep.hsyncstart, n); + swaps(&rep.hsyncend, n); + swaps(&rep.htotal, n); + swaps(&rep.vdisplay, n); + swaps(&rep.vsyncstart, n); + swaps(&rep.vsyncend, n); + swaps(&rep.vtotal, n); + swapl(&rep.flags, n); + swapl(&rep.privsize, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetModeLineReply), (char *)&rep); + if (privsize) { + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, privsize * sizeof(INT32), + mptr->Private); + } + return (client->noClientException); +} + +static int +ProcXF86VidModeGetAllModeLines(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeGetAllModeLinesReq); + xXF86VidModeGetAllModeLinesReply rep; + xXF86VidModeModeInfo mdinf; + register int n; + ScrnInfoPtr vptr; + DisplayModePtr mptr, curmptr; + int privsize, modecount=1; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + curmptr = mptr = vptr->modes; + + while (mptr->next != curmptr) { + ++modecount; + mptr = mptr->next; + } + + REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); + rep.type = X_Reply; + rep.length = (SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xGenericReply) + + modecount * sizeof(xXF86VidModeModeInfo)) >> 2; + rep.sequenceNumber = client->sequence; + rep.modecount = modecount; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.modecount, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetAllModeLinesReply), (char *)&rep); + mptr = curmptr; + do { + if (!mptr->Private) + privsize = 0; + else + privsize = mptr->PrivSize; + + mdinf.dotclock = vptr->clock[mptr->Clock]; + mdinf.hdisplay = mptr->HDisplay; + mdinf.hsyncstart = mptr->HSyncStart; + mdinf.hsyncend = mptr->HSyncEnd; + mdinf.htotal = mptr->HTotal; + mdinf.vdisplay = mptr->VDisplay; + mdinf.vsyncstart = mptr->VSyncStart; + mdinf.vsyncend = mptr->VSyncEnd; + mdinf.vtotal = mptr->VTotal; + mdinf.flags = mptr->Flags; + mdinf.privsize = privsize; + if (client->swapped) { + swapl(&mdinf.dotclock, n); + swaps(&mdinf.hdisplay, n); + swaps(&mdinf.hsyncstart, n); + swaps(&mdinf.hsyncend, n); + swaps(&mdinf.htotal, n); + swaps(&mdinf.vdisplay, n); + swaps(&mdinf.vsyncstart, n); + swaps(&mdinf.vsyncend, n); + swaps(&mdinf.vtotal, n); + swapl(&mdinf.flags, n); + swapl(&mdinf.privsize, n); + } + WriteToClient(client, sizeof(xXF86VidModeModeInfo), (char *)&mdinf); + mptr = mptr->next; + } while (mptr != curmptr); + return (client->noClientException); +} + +#define CLOCKSPD(clk,scrp) ((clk>MAXCLOCKS)? clk: scrp->clock[clk]) +#define MODEMATCH(mptr,stuff,scrp) \ + (CLOCKSPD(mptr->Clock,scrp) == CLOCKSPD(stuff->dotclock,scrp) \ + && mptr->HDisplay == stuff->hdisplay \ + && mptr->HSyncStart== stuff->hsyncstart \ + && mptr->HSyncEnd == stuff->hsyncend \ + && mptr->HTotal == stuff->htotal \ + && mptr->VDisplay == stuff->vdisplay \ + && mptr->VSyncStart== stuff->vsyncstart \ + && mptr->VSyncEnd == stuff->vsyncend \ + && mptr->VTotal == stuff->vtotal \ + && mptr->Flags == stuff->flags ) + +static int +ProcXF86VidModeAddModeLine(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeAddModeLineReq); + ScrnInfoPtr vptr; + DisplayModePtr curmptr, mptr, newmptr; + DisplayModeRec modetmp; + int len; + + if (xf86Verbose) { + ErrorF("AddModeLine - scrn: %d clock: %d\n", + stuff->screen, stuff->dotclock); + ErrorF("AddModeLine - hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, stuff->flags); + ErrorF(" after - scrn: %d clock: %d\n", + stuff->screen, stuff->after_dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->after_hdisplay, stuff->after_hsyncstart, + stuff->after_hsyncend, stuff->after_htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + stuff->after_vdisplay, stuff->after_vsyncstart, + stuff->after_vsyncend, stuff->after_vtotal, stuff->after_flags); + } + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + curmptr = mptr = vptr->modes; + + REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeAddModeLineReq) >> 2); + if (len != stuff->privsize) + return BadLength; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + return BadValue; + + if (stuff->after_hsyncstart < stuff->after_hdisplay || + stuff->after_hsyncend < stuff->after_hsyncstart || + stuff->after_htotal < stuff->after_hsyncend || + stuff->after_vsyncstart < stuff->after_vdisplay || + stuff->after_vsyncend < stuff->after_vsyncstart || + stuff->after_vtotal < stuff->after_vsyncend) + return BadValue; + + if (stuff->after_htotal != 0 || stuff->after_vtotal != 0) { + Bool found = FALSE; + do { + if (MODEMATCH(mptr, stuff, vptr)) { + found = TRUE; + break; + } + } while ((mptr = mptr->next) != curmptr); + if (!found) + return BadValue; + } + + newmptr = (DisplayModePtr) xalloc(sizeof(DisplayModeRec)); + + newmptr->Clock = stuff->dotclock; + newmptr->CrtcHDisplay = newmptr->HDisplay = stuff->hdisplay; + newmptr->CrtcHSyncStart= newmptr->HSyncStart = stuff->hsyncstart; + newmptr->CrtcHSyncEnd = newmptr->HSyncEnd = stuff->hsyncend; + newmptr->CrtcHTotal = newmptr->HTotal = stuff->htotal; + newmptr->CrtcVDisplay = newmptr->VDisplay = stuff->vdisplay; + newmptr->CrtcVSyncStart= newmptr->VSyncStart = stuff->vsyncstart; + newmptr->CrtcVSyncEnd = newmptr->VSyncEnd = stuff->vsyncend; + newmptr->CrtcVTotal = newmptr->VTotal = stuff->vtotal; + newmptr->Flags = stuff->flags; +#if 0 + newmptr->CrtcHSkew = newmptr->HSkew = stuff->hskew; +#endif + newmptr->CrtcHAdjusted = FALSE; + newmptr->CrtcVAdjusted = FALSE; + newmptr->name = ""; + newmptr->Private = NULL; + if (stuff->privsize) { + if (xf86Verbose) + ErrorF("AddModeLine - Request includes privates\n"); + newmptr->Private = + (INT32 *) ALLOCATE_LOCAL(stuff->privsize * sizeof(INT32)); + memcpy(newmptr->Private, &stuff[1], stuff->privsize*sizeof(INT32)); + } + + /* Check that the mode is consistent with the monitor specs */ + switch (xf86CheckMode(vptr, newmptr, vptr->monitor, FALSE)) { + case MODE_HSYNC: + xfree(newmptr->Private); + xfree(newmptr); + return vidmodeErrorBase + XF86VidModeBadHTimings; + case MODE_VSYNC: + xfree(newmptr->Private); + xfree(newmptr); + return vidmodeErrorBase + XF86VidModeBadVTimings; + } + + /* Check that the driver is happy with the mode */ + if (vptr->ValidMode(newmptr, xf86Verbose, MODE_VID) != MODE_OK) { + xfree(newmptr->Private); + xfree(newmptr); + return vidmodeErrorBase + XF86VidModeModeUnsuitable; + } + + if (newmptr->Flags & V_DBLSCAN) + { + newmptr->CrtcVDisplay *= 2; + newmptr->CrtcVSyncStart *= 2; + newmptr->CrtcVSyncEnd *= 2; + newmptr->CrtcVTotal *= 2; + newmptr->CrtcVAdjusted = TRUE; + } + + newmptr->next = mptr->next; + newmptr->prev = mptr; + mptr->next = newmptr; + newmptr->next->prev = newmptr; + +#if 0 /* Do we want this? */ + (vptr->SwitchMode)(newmptr); +#endif + + if (xf86Verbose) + ErrorF("AddModeLine - Succeeded\n"); + return(client->noClientException); +} + +static int +ProcXF86VidModeDeleteModeLine(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeDeleteModeLineReq); + ScrnInfoPtr vptr; + DisplayModePtr curmptr, mptr; + DisplayModeRec modetmp; + int len; + + if (xf86Verbose) { + ErrorF("DeleteModeLine - scrn: %d clock: %d\n", + stuff->screen, stuff->dotclock, stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, stuff->flags); + } + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + curmptr = mptr = vptr->modes; + + REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeDeleteModeLineReq) >> 2); + if (len != stuff->privsize) { + ErrorF("req_len = %d, sizeof(Req) = %d, privsize = %d, len = %d, length = %d\n", + client->req_len, sizeof(xXF86VidModeDeleteModeLineReq)>>2, stuff->privsize, len, stuff->length); + return BadLength; + } + + ErrorF("Checking against clock: %d (%d)\n", + mptr->Clock, CLOCKSPD(mptr->Clock, vptr)); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + mptr->HDisplay, mptr->HSyncStart, + mptr->HSyncEnd, mptr->HTotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + mptr->VDisplay, mptr->VSyncStart, mptr->VSyncEnd, + mptr->VTotal, mptr->Flags); + if (MODEMATCH(mptr, stuff, vptr)) + return BadValue; + + while ((mptr = mptr->next) != curmptr) { + ErrorF("Checking against clock: %d (%d)\n", + mptr->Clock, CLOCKSPD(mptr->Clock, vptr)); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + mptr->HDisplay, mptr->HSyncStart, + mptr->HSyncEnd, mptr->HTotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + mptr->VDisplay, mptr->VSyncStart, mptr->VSyncEnd, + mptr->VTotal, mptr->Flags); + if (MODEMATCH(mptr, stuff, vptr)) { + mptr->prev->next = mptr->next; + mptr->next->prev = mptr->prev; + xfree(mptr->name); + xfree(mptr->Private); + xfree(mptr); + if (xf86Verbose) + ErrorF("DeleteModeLine - Succeeded\n"); + return(client->noClientException); + } + } + return BadValue; +} + +static int +ProcXF86VidModeModModeLine(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeModModeLineReq); + ScrnInfoPtr vptr; + DisplayModePtr mptr; + DisplayModeRec modetmp; + int len; + + if (xf86Verbose) { + ErrorF("ModModeLine - scrn: %d hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->screen, stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, stuff->flags); + } + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + mptr = vptr->modes; + + REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeModModeLineReq) >> 2); + if (len != stuff->privsize) + return BadLength; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + return BadValue; + + memcpy(&modetmp, mptr, sizeof(DisplayModeRec)); + + modetmp.HDisplay = stuff->hdisplay; + modetmp.HSyncStart = stuff->hsyncstart; + modetmp.HSyncEnd = stuff->hsyncend; + modetmp.HTotal = stuff->htotal; + modetmp.VDisplay = stuff->vdisplay; + modetmp.VSyncStart = stuff->vsyncstart; + modetmp.VSyncEnd = stuff->vsyncend; + modetmp.VTotal = stuff->vtotal; + modetmp.Flags = stuff->flags; + if (mptr->PrivSize && stuff->privsize) { + if (mptr->PrivSize != stuff->privsize) + return BadValue; + } + if (mptr->PrivSize && mptr->Private) { + modetmp.Private = + (INT32 *)ALLOCATE_LOCAL(mptr->PrivSize * sizeof(INT32)); + if (stuff->privsize) { + if (xf86Verbose) + ErrorF("ModModeLine - Request includes privates\n"); + memcpy(modetmp.Private, &stuff[1], mptr->PrivSize * sizeof(INT32)); + } else + memcpy(modetmp.Private, mptr->Private, + mptr->PrivSize * sizeof(INT32)); + } + + /* Check that the mode is consistent with the monitor specs */ + switch (xf86CheckMode(vptr, &modetmp, vptr->monitor, FALSE)) { + case MODE_HSYNC: + DEALLOCATE_LOCAL(modetmp.Private); + return vidmodeErrorBase + XF86VidModeBadHTimings; + case MODE_VSYNC: + DEALLOCATE_LOCAL(modetmp.Private); + return vidmodeErrorBase + XF86VidModeBadVTimings; + } + + /* Check that the driver is happy with the mode */ + if (vptr->ValidMode(&modetmp, xf86Verbose, MODE_VID) != MODE_OK) { + DEALLOCATE_LOCAL(modetmp.Private); + return vidmodeErrorBase + XF86VidModeModeUnsuitable; + } + + DEALLOCATE_LOCAL(modetmp.Private); + + mptr->HDisplay = stuff->hdisplay; + mptr->HSyncStart = stuff->hsyncstart; + mptr->HSyncEnd = stuff->hsyncend; + mptr->HTotal = stuff->htotal; + mptr->VDisplay = stuff->vdisplay; + mptr->VSyncStart = stuff->vsyncstart; + mptr->VSyncEnd = stuff->vsyncend; + mptr->VTotal = stuff->vtotal; + mptr->Flags = stuff->flags; + mptr->CrtcHDisplay = stuff->hdisplay; + mptr->CrtcHSyncStart = stuff->hsyncstart; + mptr->CrtcHSyncEnd = stuff->hsyncend; + mptr->CrtcHTotal = stuff->htotal; + mptr->CrtcVDisplay = stuff->vdisplay; + mptr->CrtcVSyncStart = stuff->vsyncstart; + mptr->CrtcVSyncEnd = stuff->vsyncend; + mptr->CrtcVTotal = stuff->vtotal; + mptr->CrtcVAdjusted = FALSE; + mptr->CrtcHAdjusted = FALSE; + if (mptr->Flags & V_DBLSCAN) + { + mptr->CrtcVDisplay *= 2; + mptr->CrtcVSyncStart *= 2; + mptr->CrtcVSyncEnd *= 2; + mptr->CrtcVTotal *= 2; + mptr->CrtcVAdjusted = TRUE; + } + if (mptr->PrivSize && stuff->privsize) { + memcpy(mptr->Private, &stuff[1], mptr->PrivSize * sizeof(INT32)); + } + + (vptr->SwitchMode)(mptr); + (vptr->AdjustFrame)(vptr->frameX0, vptr->frameY0); + + if (xf86Verbose) + ErrorF("ModModeLine - Succeeded\n"); + return(client->noClientException); +} + +static int +ProcXF86VidModeValidateModeLine(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeValidateModeLineReq); + xXF86VidModeValidateModeLineReply rep; + ScrnInfoPtr vptr; + DisplayModePtr mptr; + DisplayModeRec modetmp; + int len, status; + + if (xf86Verbose) { + ErrorF("ValidateModeLine - scrn: %d clock: %d\n", + stuff->screen, stuff->dotclock, stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, stuff->flags); + } + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + mptr = vptr->modes; + + REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeValidateModeLineReq) >> 2); + if (len != stuff->privsize) + return BadLength; + + status = MODE_OK; + modetmp.Private = NULL; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + { + status = MODE_BAD; + goto status_reply; + } + + memcpy(&modetmp, mptr, sizeof(DisplayModeRec)); + + modetmp.HDisplay = stuff->hdisplay; + modetmp.HSyncStart = stuff->hsyncstart; + modetmp.HSyncEnd = stuff->hsyncend; + modetmp.HTotal = stuff->htotal; + modetmp.VDisplay = stuff->vdisplay; + modetmp.VSyncStart = stuff->vsyncstart; + modetmp.VSyncEnd = stuff->vsyncend; + modetmp.VTotal = stuff->vtotal; + modetmp.Flags = stuff->flags; + modetmp.Private = NULL; + if (mptr->PrivSize && stuff->privsize) { + if (mptr->PrivSize != stuff->privsize) { + status = MODE_BAD; + goto status_reply; + } + } + if (mptr->PrivSize && mptr->Private) { + modetmp.Private = + (INT32 *)ALLOCATE_LOCAL(mptr->PrivSize * sizeof(INT32)); + if (stuff->privsize) { + if (xf86Verbose) + ErrorF("ValidateModeLine - Request includes privates\n"); + memcpy(modetmp.Private, &stuff[1], mptr->PrivSize * sizeof(INT32)); + } else + memcpy(modetmp.Private, mptr->Private, + mptr->PrivSize * sizeof(INT32)); + } + + /* Check that the mode is consistent with the monitor specs */ + if ((status = xf86CheckMode(vptr, &modetmp, vptr->monitor, FALSE)) != MODE_OK) + goto status_reply; + + /* Check that the driver is happy with the mode */ + status = vptr->ValidMode(&modetmp, xf86Verbose, MODE_VID); + +status_reply: + if (modetmp.Private) + DEALLOCATE_LOCAL(modetmp.Private); + rep.type = X_Reply; + rep.length = (SIZEOF(xXF86VidModeValidateModeLineReply) + - SIZEOF(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.status = status; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xXF86VidModeValidateModeLineReply), (char *)&rep); + if (xf86Verbose) + ErrorF("ValidateModeLine - Succeeded\n"); + return(client->noClientException); +} + +static int +ProcXF86VidModeSwitchMode(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeSwitchModeReq); + ScreenPtr vptr; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = screenInfo.screens[stuff->screen]; + if (xf86Info.dontZoom) + return vidmodeErrorBase + XF86VidModeZoomLocked; + + REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); + + xf86ZoomViewport(vptr, (short)stuff->zoom); + return (client->noClientException); +} + +static int +ProcXF86VidModeSwitchToMode(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeSwitchToModeReq); + ScrnInfoPtr vptr; + DisplayModePtr curmptr, mptr; + DisplayModeRec modetmp; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (xf86Info.dontZoom) + return vidmodeErrorBase + XF86VidModeZoomLocked; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + curmptr = mptr = vptr->modes; + + REQUEST_SIZE_MATCH(xXF86VidModeSwitchToModeReq); + + if (MODEMATCH(mptr, stuff, vptr)) + return (client->noClientException); + + while ((mptr = mptr->next) != curmptr) { + if (MODEMATCH(mptr, stuff, vptr)) { + if ((vptr->SwitchMode)(mptr)) { + vptr->modes = mptr; + vptr->frameX0 = (vptr->frameX1 +vptr->frameX0 -mptr->HDisplay)/2; + vptr->frameX1 = vptr->frameX0 + mptr->HDisplay -1; + if (vptr->frameX0 < 0) { + vptr->frameX0 = 0; + vptr->frameX1 = mptr->HDisplay -1; + } else if (vptr->frameX1 >= vptr->virtualX) { + vptr->frameX0 = vptr->virtualX - mptr->HDisplay; + vptr->frameX1 = vptr->frameX0 + mptr->HDisplay -1; + } + vptr->frameY0 = (vptr->frameY1 +vptr->frameY0 -mptr->VDisplay)/2; + vptr->frameY1 = vptr->frameY0 + mptr->VDisplay -1; + if (vptr->frameY0 < 0) { + vptr->frameY0 = 0; + vptr->frameY1 = mptr->VDisplay -1; + } else if (vptr->frameY1 >= vptr->virtualY) { + vptr->frameY0 = vptr->virtualY - mptr->VDisplay; + vptr->frameY1 = vptr->frameY0 + mptr->VDisplay -1; + } + } + (vptr->AdjustFrame)(vptr->frameX0, vptr->frameY0); + return(client->noClientException); + } + } + return BadValue; +} + +static int +ProcXF86VidModeLockModeSwitch(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeLockModeSwitchReq); + ScreenPtr vptr; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = screenInfo.screens[stuff->screen]; + if (xf86Info.dontZoom) + return vidmodeErrorBase + XF86VidModeZoomLocked; + + REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); + + xf86LockZoom(vptr, (short)stuff->lock); + return (client->noClientException); +} + +static int +ProcXF86VidModeGetMonitor(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeGetMonitorReq); + xXF86VidModeGetMonitorReply rep; + register int n; + ScrnInfoPtr vptr; + MonPtr mptr; + CARD32 *hsyncdata, *vsyncdata; + int i; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + mptr = vptr->monitor; + + REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); + rep.type = X_Reply; + if (mptr->vendor) + rep.vendorLength = strlen(mptr->vendor); + else + rep.vendorLength = 0; + if (mptr->model) + rep.modelLength = strlen(mptr->model); + else + rep.modelLength = 0; + rep.length = (SIZEOF(xXF86VidModeGetMonitorReply) - SIZEOF(xGenericReply) + + (mptr->n_hsync + mptr->n_vrefresh) * sizeof(CARD32) + + ((rep.vendorLength + 3) & ~3) + + ((rep.modelLength + 3) & ~3)) >> 2; + rep.sequenceNumber = client->sequence; + rep.nhsync = mptr->n_hsync; + rep.nvsync = mptr->n_vrefresh; +#if 0 + rep.bandwidth = (unsigned long)(mptr->bandwidth * 1e6); +#endif + hsyncdata = ALLOCATE_LOCAL(mptr->n_hsync * sizeof(CARD32)); + if (!hsyncdata) { + return BadAlloc; + } + vsyncdata = ALLOCATE_LOCAL(mptr->n_vrefresh * sizeof(CARD32)); + if (!vsyncdata) { + DEALLOCATE_LOCAL(hsyncdata); + return BadAlloc; + } + for (i = 0; i < mptr->n_hsync; i++) { + hsyncdata[i] = (unsigned short)(mptr->hsync[i].lo * 100.0) | + (unsigned short)(mptr->hsync[i].hi * 100.0) << 16; + } + for (i = 0; i < mptr->n_vrefresh; i++) { + vsyncdata[i] = (unsigned short)(mptr->vrefresh[i].lo * 100.0) | + (unsigned short)(mptr->vrefresh[i].hi * 100.0) << 16; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.bandwidth, n); + } + WriteToClient(client, SIZEOF(xXF86VidModeGetMonitorReply), (char *)&rep); + client->pSwapReplyFunc = Swap32Write; + WriteSwappedDataToClient(client, mptr->n_hsync * sizeof(CARD32), + hsyncdata); + WriteSwappedDataToClient(client, mptr->n_vrefresh * sizeof(CARD32), + vsyncdata); + if (rep.vendorLength) + WriteToClient(client, rep.vendorLength, mptr->vendor); + if (rep.modelLength) + WriteToClient(client, rep.modelLength, mptr->model); + DEALLOCATE_LOCAL(hsyncdata); + DEALLOCATE_LOCAL(vsyncdata); + return (client->noClientException); +} + +static int +ProcXF86VidModeGetViewPort(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeGetViewPortReq); + xXF86VidModeGetViewPortReply rep; + register int n; + ScrnInfoPtr vptr; + MonPtr mptr; + CARD32 *hsyncdata, *vsyncdata; + int i; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + mptr = vptr->monitor; + + REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); + rep.type = X_Reply; + return (client->noClientException); +} + +static int +ProcXF86VidModeSetViewPort(client) + register ClientPtr client; +{ + REQUEST(xXF86VidModeSetViewPortReq); + register int n; + ScrnInfoPtr vptr; + MonPtr mptr; + CARD32 *hsyncdata, *vsyncdata; + int i; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + mptr = vptr->monitor; + + REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); + return (client->noClientException); +} + +static int +ProcXF86VidModeDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86VidModeQueryVersion: + return ProcXF86VidModeQueryVersion(client); + case X_XF86VidModeGetModeLine: + return ProcXF86VidModeGetModeLine(client); + case X_XF86VidModeGetAllModeLines: + return ProcXF86VidModeGetAllModeLines(client); + case X_XF86VidModeGetMonitor: + return ProcXF86VidModeGetMonitor(client); + case X_XF86VidModeValidateModeLine: + return ProcXF86VidModeValidateModeLine(client); + case X_XF86VidModeGetViewPort: + return ProcXF86VidModeGetViewPort(client); + default: + if (!xf86VidModeEnabled) + return vidmodeErrorBase + XF86VidModeExtensionDisabled; + if (xf86VidModeAllowNonLocal || LocalClient (client)) { + switch (stuff->data) { + case X_XF86VidModeAddModeLine: + return ProcXF86VidModeAddModeLine(client); + case X_XF86VidModeDeleteModeLine: + return ProcXF86VidModeDeleteModeLine(client); + case X_XF86VidModeModModeLine: + return ProcXF86VidModeModModeLine(client); + case X_XF86VidModeSwitchMode: + return ProcXF86VidModeSwitchMode(client); + case X_XF86VidModeSwitchToMode: + return ProcXF86VidModeSwitchToMode(client); + case X_XF86VidModeLockModeSwitch: + return ProcXF86VidModeLockModeSwitch(client); + case X_XF86VidModeSetViewPort: + return ProcXF86VidModeSetViewPort(client); + default: + return BadRequest; + } + } else + return vidmodeErrorBase + XF86VidModeClientNotLocal; + } +} + +static int +SProcXF86VidModeQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86VidModeQueryVersion(client); +} + +static int +SProcXF86VidModeGetModeLine(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeGetModeLineReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetModeLine(client); +} + +static int +SProcXF86VidModeGetAllModeLines(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeGetAllModeLinesReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetAllModeLines(client); +} + +static int +SProcXF86VidModeAddModeLine(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeAddModeLineReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + return ProcXF86VidModeAddModeLine(client); +} + +static int +SProcXF86VidModeDeleteModeLine(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeDeleteModeLineReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + return ProcXF86VidModeDeleteModeLine(client); +} + +static int +SProcXF86VidModeModModeLine(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeModModeLineReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + return ProcXF86VidModeModModeLine(client); +} + +static int +SProcXF86VidModeValidateModeLine(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeValidateModeLineReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + return ProcXF86VidModeValidateModeLine(client); +} + +static int +SProcXF86VidModeSwitchMode(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeSwitchModeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); + swaps(&stuff->screen, n); + swaps(&stuff->zoom, n); + return ProcXF86VidModeSwitchMode(client); +} + +static int +SProcXF86VidModeSwitchToMode(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeSwitchToModeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSwitchToModeReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeSwitchToMode(client); +} + +static int +SProcXF86VidModeLockModeSwitch(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeLockModeSwitchReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); + swaps(&stuff->screen, n); + swaps(&stuff->lock, n); + return ProcXF86VidModeLockModeSwitch(client); +} + +static int +SProcXF86VidModeGetMonitor(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeGetMonitorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetMonitor(client); +} + +static int +SProcXF86VidModeGetViewPort(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeGetViewPortReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetViewPort(client); +} + +static int +SProcXF86VidModeSetViewPort(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86VidModeSetViewPortReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeSetViewPort(client); +} + +static int +SProcXF86VidModeDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86VidModeQueryVersion: + return SProcXF86VidModeQueryVersion(client); + case X_XF86VidModeGetModeLine: + return SProcXF86VidModeGetModeLine(client); + case X_XF86VidModeGetAllModeLines: + return SProcXF86VidModeGetAllModeLines(client); + case X_XF86VidModeGetMonitor: + return SProcXF86VidModeGetMonitor(client); + case X_XF86VidModeGetViewPort: + return SProcXF86VidModeGetViewPort(client); + case X_XF86VidModeValidateModeLine: + return SProcXF86VidModeValidateModeLine(client); + default: + if (!xf86VidModeEnabled) + return vidmodeErrorBase + XF86VidModeExtensionDisabled; + if (xf86VidModeAllowNonLocal || LocalClient(client)) { + switch (stuff->data) { + case X_XF86VidModeAddModeLine: + return SProcXF86VidModeAddModeLine(client); + case X_XF86VidModeDeleteModeLine: + return SProcXF86VidModeDeleteModeLine(client); + case X_XF86VidModeModModeLine: + return SProcXF86VidModeModModeLine(client); + case X_XF86VidModeSwitchMode: + return SProcXF86VidModeSwitchMode(client); + case X_XF86VidModeSwitchToMode: + return SProcXF86VidModeSwitchToMode(client); + case X_XF86VidModeLockModeSwitch: + return SProcXF86VidModeLockModeSwitch(client); + case X_XF86VidModeSetViewPort: + return SProcXF86VidModeSetViewPort(client); + default: + return BadRequest; + } + } else + return vidmodeErrorBase + XF86VidModeClientNotLocal; + } +} diff --git a/hw/xfree86/os-support/README.OS-lib b/hw/xfree86/os-support/README.OS-lib new file mode 100644 index 000000000..cf3a0cc7e --- /dev/null +++ b/hw/xfree86/os-support/README.OS-lib @@ -0,0 +1,437 @@ + + README for XFree86 OS-support Layer + ----------------------------------- + +Contents +-------- + 1) Overview + 2) Directory Layout + 3) Adding a new OS + 4) OS Support API + +1 - Overview +------------ + This directory contains the OS support layer functions for the XFree86 +servers. In addition, some miscellaneous server support functions (not +OS-dependent) are included here, to take advantage of the fact that this +library comes last in the linking order. + +Most of the functionality required to support a new OS is encapsulated in +this library. It is hoped that all OS-specific details can be encapsulated, +but that is not likely ever to be completely possible. Hence some minor +changes will wind up being made in other parts of the server. The major +design principles for this library are maintainability, readability, and +portability. Sometimes these goals conflict; some somewhat arbitrary choices +have been made in implementation. + +2 - Directory Layout +-------------------- + os-support/ Contains headers and documentation; no code + misc/ Non-OS-specific miscellaneous functions that + fit best into the link architecture this way. + shared/ Contains files with functions used by more than one + OS. These are symlinked into the OS subdirectories + at build time via Imakefile rules. This is alway + preferable to reproducing functions in more than one + OS library. + amoeba/ OS support for the Amoeba operating system. + bsd/ OS support for the 386BSD/NetBSD/FreeBSD operating + systems. + bsdi/ OS support for the BSD/386 operating system. + linux/ OS support for the Linux operating system. + mach/ OS support for the Mach and OSF/1 operating systems. + minix/ OS support for the Minix operating system. + os2/ OS support for OS/2 2.11 and OS/2 Warp + sco/ OS support for the SCO SVR3.x operating system. + solx86/ OS support for the Solaris x86 operating system. + sysv/ OS support for all SVR4.0 and SVR4.2, and for + ISC and AT&T SVR3.2 operating systems. + +3 - Adding A New OS +------------------- + Adding a support for a new operating system entails implementing all of +the functions described in the API below. Many of these functions are no-ops +for many operating systems, and appropriate files with dummy declarations are +available in the 'shared' subdirectory. + +If your OS is sufficiently similar to an existing OS, you can make use of +the existing subdirectory. One of the reasons for implementing this OS +library was the unmaintainability of the spagetti-#ifdef code that existed +before. You should try to avoid cluttering the code with #ifdef's. If +you find that the subdirectory is getting cluttered, split off into a +seperate subdirectory (e.g. as was done for SCO, rather than cluttering +the 'sysv' subdirectory). You can split functions out of an existing +subdirectory into the 'shared' subdirectory, if that is appropriate. Just +remember to update the Imakefile for the old subdirectory. + +You will still likely have to make some small changes to other parts of +the server. You should not put OS-specific #define's or #include's anywhere +else in the server. These should all go in the "xf86_OSlib.h" header file +in this directory. + +4 - OS Support API +----------------- +void xf86OpenConsole(void) +{ + /* + * Open console device, activate VTs, etc, etc. Fill in requisite + * pieces of x386Info. Most of this code comes from x386Init.c + */ +} + +void xf86CloseConsole(void) +{ + /* + * Close console at server exit. + */ +} + +Bool xf86VTSwitchPending(void) +{ + /* + * Returns TRUE iff there is a VT switch operation pending for + * the server. In the USL VT model, this is indicated via a + * signal handler. Should return FALSE always for OSs without + * VTs. + */ +} + +Bool xf86VTSwitchAway(void) +{ + /* + * Handles the OS-specific action for switching away from the active + * VT. Returns FALSE if the switch away fails. Should return + * FALSE always for OSs without VTs (then again, this function + * should never be called in that case). + */ +} + +Bool xf86VTSwitchTo(void) +{ + /* + * Handles the OS-specific action for switching to the active VT. + * Returns FALSE if the switch to fails. Should return TRUE + * always for OSs without VTs (then again, this function should + * never be called in that case). + */ +} + +Bool xf86LinearVidMem(void) +{ + /* + * Returns TRUE if the OS supports mapping linear frame buffers + * (ie memory at addresses above physical memory). + */ +} + +pointer xf86MapVidMem(int ScreenNum, int Region, pointer Base, + unsigned long Size) +{ + /* + * Handle mapping the video memory. Returns (pointer *)0 for + * failure; causes server exit. It is allowable to call FatalError() + * from inside this function and exit directly. + */ +} + +void xf86UnMapVidMem(int ScreenNum, int Region, pointer Base, + unsigned long Size) +{ + /* + * Handle unmapping the video memory. This should undo what + * xf86MapVidMem() does. Base is a pointer obtained from + * a previous call to xf86MapVidMem(). + */ +} + +void xf86MapDisplay(int ScreenNum, int Region) +{ + /* + * For OSs that require the screen be mapped when entering a VT. + * A dummy function will be defined for OSs that don't require + * this (or don't have VTs at all). + */ +} + +void xf86UnMapDisplay(int ScreenNum, int Region) +{ + /* + * For Os that require that the screen be unmapped when leaving a + * VT. A dummy function will be defined for OSs that don't require + * this (or don't have VTs at all). + */ +} + +int xf86ReadBIOS(unsigned long Base, unsigned long Offset, + unsigned char *Buf, int Len) +{ + /* + * Read Len bytes from the BIOS at address Base, offset Offset, + * into buffer Buf. Returns -1 for failure or if the OS does + * not support reading the BIOS. This causes a driver probe + * to fail, but does not cause the server to abort. + */ +} + +void xf86ClearIOPortList(int ScreenNum) +{ + /* + * Clears any list of I/O ports that the OS-layer may be maintaining. + * Note: the value used for ScreenNum must be the scrnIndex field + * of the screenInfoRec, because this is the only index that is + * guaranteed to be valid and never change during the life of the + * server. It is not the same as the index of pScreen in ScreenInfo. + */ +} + +void xf86AddIOPorts(int ScreenNum, int NumPorts, unsigned *Ports) +{ + /* + * Adds NumPorts I/O ports listed in array Ports to a list that + * the OS-layer may be maintaining. Successive calls to this + * function are cumulative. + */ +} + +void xf86EnableIOPorts(int ScreenNum) +{ + /* + * Enables I/O permissions. The OS layer can either use a + * previously created list of I/O ports to be used, or can + * enable all I/O port access. + */ +} + +void xf86DisableIOPorts(int ScreenNum) +{ + /* + * Disables I/O permissions. Does not clear the list of I/O + * ports, if any exists. + */ +} + +void xf86DisableIOPrivs(void) +{ + /* + * Do whatever is necessary to disable I/O permissions after forking + * a child process. + */ +} + +Bool xf86DisableInterrupts(void) +{ + /* + * Disable interrupts if allowed for this OS. Returns FALSE if + * this is not allowed or if the attempt fails for some reason. + */ +} + +void xf86EnableInterrupts(void) +{ + /* + * Reenable interrupts + */ +} + +int xf86ProcessArgument(int argc, char *argv[], int i) +{ + /* + * Process OS-specific command-line arguments. See + * ddxProcessArgument() for more info. + */ +} + +void xf86UseMsg(void) +{ + /* + * Print list of OS-specific command-line arguments. See + * ddxUseMsg() for more info. + */ +} + +void xf86SoundKbdBell(int loudness, int pitch, int duration) +{ + /* + * Sound the keyboard bell. pitch is in Hz, duration in ms, + * loudness is in the range 0-100 (0 -> off). For systems + * where the loudness can't be controlled, scale the duration + * by loudness/50. + */ +} + +void xf86SetKbdLeds(int leds) +{ + /* + * Set the keyboard LEDs to the state indicated in leds + */ +} + +int xf86GetKbdLeds(void) +{ + /* + * Return the state of the keyboard LEDs. If the OS doesn't + * support this, return 0. + */ +} + +void xf86SetKbdRepeat(char rad) +{ + /* + * Set the keyboard repeat rate and delay according the + * the rad value. The lower 5 bits determine the repeat + * rate (lower value -> higher rate). The next 2 bits + * determine the delay. + * This should possibly be changed to take separate rate and + * delay parameters. + */ +} + +void xf86KbdInit(void) +{ + /* + * Save initial keyboard state. This is called at the start of + * each server generation. + */ +} + +int xf86KbdOn(void) +{ + /* + * Set the keyboard up for use with X. This is called whenever + * the server becomes active (ie at the start of each generation and + * whenever its VT becomes active). Return the file descriptor + * for keyboard input. Return -1 if there is no file descriptor + * to add as an input device. If there are errors encountered, + * call FatalError(). A return value of -1 is not considered an + * error condition. + */ +} + +int xf86KbdOff(void) +{ + /* + * Return the keyboard to the state saved by xf86KbdInit(). This is + * called at the end of a server generation, and also when the + * server's VT ceases being active. Returns the keyboard file + * descriptor. Returns -1 if there is no file descriptor to be + * removed as an input device. Errors should be handled the same + * way as in xf86KbdOn(). + */ +} + +void xf86KbdEvents(void) +{ + /* + * Read characters from the keyboard device, and post the events + * by calling x386PostKbdEvent(). Read as much as is available + * without waiting. + */ +} + +void xf86SetMouseSpeed(int old, int new, unsigned cflag) +{ + /* + * Set the speed of the mouse port. old is the previous speed, + * new is the new speed, and cflag is the value of the termio[s] + * c_cflag field. For mice that have programmable speed operation, + * this should send the appropriate commands to the mouse. + */ +} + +void xf86MouseInit(void) +{ + /* + * This is called at the start of each server generation. In most + * cases this is a noop. If the mouse must not be opened/closed + * when VT switching, the open should be done here. + */ +} + +int xf86MousedOn(void) +{ + /* + * Set the mouse up for use with X. This is called whenever + * the server becomes active (ie at the start of each generation and + * whenever its VT becomes active). This function normally opens + * the mouse device, and may call xf86SetupMouse() to initialise + * the mouse parameters. Return the file descriptor for mouse input. + * Return -1 if there is no file descriptor to add as an input + * device. If there are errors encountered, call FatalError(). + * A return value of -1 is not considered an error condition. + */ +} + +int xf86MouseOff(Bool doclose) +{ + /* + * Release the mouse from use with X. This is called at the end + * of a server generation (with doclose==TRUE), and also when the + * server's VT ceases being active (with doclose==FALSE). If the + * mouse should not be opened/closed when VT switching, the close + * should be done here when doclose==TRUE. For other systems, the + * mouse device should be closed regardless of the doclose value. + * Returns the mouse file descriptor. Returns -1 if there is no + * file descriptor to be removed as an input device. Errors + * should be handled the same way as in xf86MouseOn(). + */ +} + +void xf86MouseEvents(void) +{ + /* + * Read characters from the mouse device, and post the events + * by calling x386PostMseEvent(). Read as much as is available + * without waiting. If the OS doesn't handle the mouse protocol + * translation, xf86MouseProtocol() may be called to do the + * translation and event posting. If the OS does handle the protocol + * translation, MOUSE_PROTOCOL_IN_KERNEL should be #define'd in + * xf86_OSlib.h. + */ +} + +int xf86OsMouseProc(DevicePtr pPointer, int what) +{ + /* + * Implements the device-proc for the pointer device when an + * OS-based mouse driver is being used (as opposed to the + * server's internal mouse driver). Implemented as any other + * device-proc in the server. + * + * This function only needs to be implemented if USE_OSMOUSE is + * defined for the OS. + */ +} + +int xf86OsMouseEvents(void) +{ + /* + * When supporting an OS-based mouse driver (as opposed to the + * server's internal mouse driver), read some events from the device + * and post them to the DIX layer through x386PostMseEvent(). + * + * This function only needs to be implemented if USE_OSMOUSE is + * defined for the OS. + */ +} + +void xf86OsMouseOption(int token, pointer lex_ptr) +{ + /* + * Used in parsing an OsMouse keyword from the Xconfig file. + * Passed the token type and a pointer to the token value. + * The function should do whatever is appropriate for the OS's + * mouse driver. + * + * This function only needs to be implemented if USE_OSMOUSE is + * defined for the OS. + */ +} + + +$XFree86: xc/programs/Xserver/hw/xfree86/os-support/README.OS-lib,v 3.2 1996/12/23 06:48:59 dawes Exp $ + + + + + +$Xorg: README.OS-lib,v 1.3 2000/08/17 19:51:19 cpqbld Exp $ diff --git a/hw/xfree86/os-support/assyntax.h b/hw/xfree86/os-support/assyntax.h new file mode 100644 index 000000000..ee2c23fa4 --- /dev/null +++ b/hw/xfree86/os-support/assyntax.h @@ -0,0 +1,725 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/assyntax.h,v 3.7.2.2 1997/05/11 02:56:22 dawes Exp $ */ +#ifndef __ASSYNTAX_H__ +#define __ASSYNTAX_H__ + +/* + * Copyright 1992 Vrije Universiteit, The Netherlands + * + * 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 name of the Vrije Universiteit not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The Vrije Universiteit makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * The Vrije Universiteit DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL The Vrije Universiteit 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. + */ +/* $Xorg: assyntax.h,v 1.3 2000/08/17 19:51:19 cpqbld Exp $ */ + + /* + * assyntax.h + * + * Select the syntax appropriate to the 386 assembler being used + * To add support for more assemblers add more columns to the CHOICE + * macro. Note that register names must also have uppercase names + * to avoid macro recursion. e.g., #define ah %ah recurses! + * + * NB 1. Some of the macros for certain assemblers imply that the code is to + * run in protected mode!! Caveat emptor. + * + * NB 2. 486 specific instructions are not included. This is to discourage + * their accidental use in code that is intended to run on 386 and 486 + * systems. + * + * Supported assemblers: + * + * (a) AT&T SysVr4 as(1): default + * (b) GNU Assembler gas: define USE_GAS or GNU_ASSEMBLER + * (c) Amsterdam Compiler kit: define ACK_ASSEMBLER + * + * The following naming conventions have been used to identify the various + * data types: + * _SR = segment register version + * Integer: + * _Q = quadword = 64 bits + * _L = long = 32 bits + * _W = short = 16 bits + * _B = byte = 8 bits + * Floating-point: + * _X = m80real = 80 bits + * _D = double = 64 bits + * _S = single = 32 bits + * + * Author: Gregory J. Sharp, Sept 1992 + * Vrije Universiteit, Amsterdam, The Netherlands + */ + +#if defined(USE_GAS) && !defined(GNU_ASSEMBLER) +#define GNU_ASSEMBLER +#endif + +#if (defined(__STDC__) && !defined(UNIXCPP)) || (defined (sun) && defined (i386) && defined (SVR4) && defined (__STDC__) && !defined (__GNUC__)) +#define CONCAT(x, y) x ## y +#else +#define CONCAT(x, y) x/**/y +#endif + +#ifdef ACK_ASSEMBLER + +/* Assume we write code for 32-bit protected mode! */ + +/* Redefine register names for GAS & AT&T assemblers */ +#define AL al +#define AH ah +#define AX ax +#define EAX ax +#define BL bl +#define BH bh +#define BX bx +#define EBX bx +#define CL cl +#define CH ch +#define CX cx +#define ECX cx +#define DL dl +#define DH dh +#define DX dx +#define EDX dx +#define BP bp +#define EBP bp +#define SI si +#define ESI si +#define DI di +#define EDI di +#define SP sp +#define ESP sp +#define CS cs +#define SS ss +#define DS ds +#define ES es +#define FS fs +#define GS gs +/* Control Registers */ +#define CR0 cr0 +#define CR1 cr1 +#define CR2 cr2 +#define CR3 cr3 +/* Debug Registers */ +#define DR0 dr0 +#define DR1 dr1 +#define DR2 dr2 +#define DR3 dr3 +#define DR4 dr4 +#define DR5 dr5 +#define DR6 dr6 +#define DR7 dr7 +/* Floating-point Stack */ +#define ST st + +#define AS_BEGIN .sect .text; .sect .rom; .sect .data; .sect .bss; .sect .text + + +#define _WTOG o16 /* word toggle for _W instructions */ +#define _LTOG /* long toggle for _L instructions */ +#define ADDR_TOGGLE a16 +#define OPSZ_TOGGLE o16 +#define USE16 .use16 +#define USE32 .use32 + +#define CHOICE(a,b,c) c + +#else /* AT&T or GAS */ + +/* Redefine register names for GAS & AT&T assemblers */ +#define AL %al +#define AH %ah +#define AX %ax +#define EAX %eax +#define BL %bl +#define BH %bh +#define BX %bx +#define EBX %ebx +#define CL %cl +#define CH %ch +#define CX %cx +#define ECX %ecx +#define DL %dl +#define DH %dh +#define DX %dx +#define EDX %edx +#define BP %bp +#define EBP %ebp +#define SI %si +#define ESI %esi +#define DI %di +#define EDI %edi +#define SP %sp +#define ESP %esp +#define CS %cs +#define SS %ss +#define DS %ds +#define ES %es +#define FS %fs +#define GS %gs +/* Control Registers */ +#define CR0 %cr0 +#define CR1 %cr1 +#define CR2 %cr2 +#define CR3 %cr3 +/* Debug Registers */ +#define DR0 %db0 +#define DR1 %db1 +#define DR2 %db2 +#define DR3 %db3 +#define DR4 %db4 +#define DR5 %db5 +#define DR6 %db6 +#define DR7 %db7 +/* Floating-point Stack */ +#define ST %st + +#define AS_BEGIN +#define USE16 +#define USE32 + +#ifdef GNU_ASSEMBLER + +#define ADDR_TOGGLE aword +#define OPSZ_TOGGLE word + +#define CHOICE(a,b,c) b + +#else +/* + * AT&T ASSEMBLER SYNTAX + * ********************* + */ +#define CHOICE(a,b,c) a + +#define ADDR_TOGGLE addr16 +#define OPSZ_TOGGLE data16 + +#endif /* GNU_ASSEMBLER */ +#endif /* ACK_ASSEMBLER */ + + +#if defined(Lynx) || (defined(SYSV) || defined(SVR4)) && !defined(ACK_ASSEMBLER) || (defined(linux) || defined(__OS2ELF__)) && defined(__ELF__) +#define GLNAME(a) a +#else +#define GLNAME(a) CONCAT(_,a) +#endif + + + /****************************************/ + /* */ + /* Select the various choices */ + /* */ + /****************************************/ + + +/* Redefine assembler directives */ +/*********************************/ +#define GLOBL CHOICE(.globl, .globl, .extern) +#define ALIGNTEXT4 CHOICE(.align 4, .align ARG2(2,0x90), .align 4) +#define ALIGNTEXT2 CHOICE(.align 2, .align ARG2(1,0x90), .align 2) +/* ALIGNTEXT4ifNOP is the same as ALIGNTEXT4, but only if the space is + * guaranteed to be filled with NOPs. Otherwise it does nothing. + */ +#define ALIGNTEXT4ifNOP CHOICE(.align 4, .align ARG2(2,0x90), /*can't do it*/) +#define ALIGNDATA4 CHOICE(.align 4, .align ARG2(2,0x0), .align 4) +#define ALIGNDATA2 CHOICE(.align 2, .align ARG2(1,0x0), .align 2) +#define FILE(s) CHOICE(.file s, .file s, .file s) +#define STRING(s) CHOICE(.string s, .asciz s, .asciz s) +#define D_LONG CHOICE(.long, .long, .data4) +#define D_WORD CHOICE(.value, .short, .data2) +#define D_BYTE CHOICE(.byte, .byte, .data1) +#define SPACE CHOICE(.comm, .space, .space) +#define COMM CHOICE(.comm, .comm, .comm) +#define SEG_DATA CHOICE(.data, .data, .sect .data) +#define SEG_TEXT CHOICE(.text, .text, .sect .text) +#define SEG_BSS CHOICE(.bss, .bss, .sect .bss) + +#ifdef GNU_ASSEMBLER +#define D_SPACE(n) . = . + n +#else +#define D_SPACE(n) .space n +#endif + +/* Addressing Modes */ +/* Immediate Mode */ +#define ADDR(a) CHOICE(CONCAT($,a), CONCAT($,a), a) +#define CONST(a) CHOICE(CONCAT($,a), CONCAT($,a), a) + +/* Indirect Mode */ +#define CONTENT(a) CHOICE(a, a, (a)) /* take contents of variable */ +#define REGIND(a) CHOICE((a), (a), (a)) /* Register a indirect */ +/* Register b indirect plus displacement a */ +#define REGOFF(a, b) CHOICE(a(b), a(b), a(b)) +/* Reg indirect Base + Index + Displacement - this is mainly for 16-bit mode + * which has no scaling + */ +#define REGBID(b,i,d) CHOICE(d(b,i), d(b,i), d(b)(i)) +/* Reg indirect Base + (Index * Scale) + Displacement */ +#define REGBISD(b,i,s,d) CHOICE(d(b,i,s), d(b,i,s), d(b)(i*s)) +/* Displaced Scaled Index: */ +#define REGDIS(d,i,s) CHOICE(d(,i,s), d(,i,s), d(i * s)) +/* Indexed Base: */ +#define REGBI(b,i) CHOICE((b,i), (b,i), (b)(i)) +/* Displaced Base: */ +#define REGDB(d,b) CHOICE(d(b), d(b), d(b)) +/* Variable indirect: */ +#define VARINDIRECT(var) CHOICE(*var, *var, (var)) +/* Use register contents as jump/call target: */ +#define CODEPTR(reg) CHOICE(*reg, *reg, reg) + +/* For expressions requiring bracketing + * eg. (CRT0_PM | CRT_EM) + */ + +#define EXPR(a) CHOICE([a], (a), [a]) +#define ENOT(a) CHOICE(0!a, ~a, ~a) +#define EMUL(a,b) CHOICE(a\*b, a*b, a*b) +#define EDIV(a,b) CHOICE(a\/b, a/b, a/b) + +/* + * We have to beat the problem of commas within arguments to choice. + * eg. choice (add a,b, add b,a) will get argument mismatch. Luckily ANSI + * and other known cpp definitions evaluate arguments before substitution + * so the following works. + */ +#define ARG2(a, b) a,b +#define ARG3(a,b,c) a,b,c + +/* Redefine assembler commands */ +#define AAA CHOICE(aaa, aaa, aaa) +#define AAD CHOICE(aad, aad, aad) +#define AAM CHOICE(aam, aam, aam) +#define AAS CHOICE(aas, aas, aas) +#define ADC_L(a, b) CHOICE(adcl ARG2(a,b), adcl ARG2(a,b), _LTOG adc ARG2(b,a)) +#define ADC_W(a, b) CHOICE(adcw ARG2(a,b), adcw ARG2(a,b), _WTOG adc ARG2(b,a)) +#define ADC_B(a, b) CHOICE(adcb ARG2(a,b), adcb ARG2(a,b), adcb ARG2(b,a)) +#define ADD_L(a, b) CHOICE(addl ARG2(a,b), addl ARG2(a,b), _LTOG add ARG2(b,a)) +#define ADD_W(a, b) CHOICE(addw ARG2(a,b), addw ARG2(a,b), _WTOG add ARG2(b,a)) +#define ADD_B(a, b) CHOICE(addb ARG2(a,b), addb ARG2(a,b), addb ARG2(b,a)) +#define AND_L(a, b) CHOICE(andl ARG2(a,b), andl ARG2(a,b), _LTOG and ARG2(b,a)) +#define AND_W(a, b) CHOICE(andw ARG2(a,b), andw ARG2(a,b), _WTOG and ARG2(b,a)) +#define AND_B(a, b) CHOICE(andb ARG2(a,b), andb ARG2(a,b), andb ARG2(b,a)) +#define ARPL(a,b) CHOICE(arpl ARG2(a,b), arpl ARG2(a,b), arpl ARG2(b,a)) +#define BOUND_L(a, b) CHOICE(boundl ARG2(a,b), boundl ARG2(b,a), _LTOG bound ARG2(b,a)) +#define BOUND_W(a, b) CHOICE(boundw ARG2(a,b), boundw ARG2(b,a), _WTOG bound ARG2(b,a)) +#define BSF_L(a, b) CHOICE(bsfl ARG2(a,b), bsfl ARG2(a,b), _LTOG bsf ARG2(b,a)) +#define BSF_W(a, b) CHOICE(bsfw ARG2(a,b), bsfw ARG2(a,b), _WTOG bsf ARG2(b,a)) +#define BSR_L(a, b) CHOICE(bsrl ARG2(a,b), bsrl ARG2(a,b), _LTOG bsr ARG2(b,a)) +#define BSR_W(a, b) CHOICE(bsrw ARG2(a,b), bsrw ARG2(a,b), _WTOG bsr ARG2(b,a)) +#define BT_L(a, b) CHOICE(btl ARG2(a,b), btl ARG2(a,b), _LTOG bt ARG2(b,a)) +#define BT_W(a, b) CHOICE(btw ARG2(a,b), btw ARG2(a,b), _WTOG bt ARG2(b,a)) +#define BTC_L(a, b) CHOICE(btcl ARG2(a,b), btcl ARG2(a,b), _LTOG btc ARG2(b,a)) +#define BTC_W(a, b) CHOICE(btcw ARG2(a,b), btcw ARG2(a,b), _WTOG btc ARG2(b,a)) +#define BTR_L(a, b) CHOICE(btrl ARG2(a,b), btrl ARG2(a,b), _LTOG btr ARG2(b,a)) +#define BTR_W(a, b) CHOICE(btrw ARG2(a,b), btrw ARG2(a,b), _WTOG btr ARG2(b,a)) +#define BTS_L(a, b) CHOICE(btsl ARG2(a,b), btsl ARG2(a,b), _LTOG bts ARG2(b,a)) +#define BTS_W(a, b) CHOICE(btsw ARG2(a,b), btsw ARG2(a,b), _WTOG bts ARG2(b,a)) +#define CALL(a) CHOICE(call a, call a, call a) +#define CALLF(s,a) CHOICE(lcall ARG2(s,a), lcall ARG2(s,a), callf s:a) +#define CBW CHOICE(cbtw, cbw, cbw) +#define CWDE CHOICE(cwtd, cwde, cwde) +#define CLC CHOICE(clc, clc, clc) +#define CLD CHOICE(cld, cld, cld) +#define CLI CHOICE(cli, cli, cli) +#define CLTS CHOICE(clts, clts, clts) +#define CMC CHOICE(cmc, cmc, cmc) +#define CMP_L(a, b) CHOICE(cmpl ARG2(a,b), cmpl ARG2(a,b), _LTOG cmp ARG2(b,a)) +#define CMP_W(a, b) CHOICE(cmpw ARG2(a,b), cmpw ARG2(a,b), _WTOG cmp ARG2(b,a)) +#define CMP_B(a, b) CHOICE(cmpb ARG2(a,b), cmpb ARG2(a,b), cmpb ARG2(b,a)) +#define CMPS_L CHOICE(cmpsl, cmpsl, _LTOG cmps) +#define CMPS_W CHOICE(cmpsw, cmpsw, _WTOG cmps) +#define CMPS_B CHOICE(cmpsb, cmpsb, cmpsb) +#define CWD CHOICE(cwtl, cwd, cwd) +#define CDQ CHOICE(cltd, cdq, cdq) +#define DAA CHOICE(daa, daa, daa) +#define DAS CHOICE(das, das, das) +#define DEC_L(a) CHOICE(decl a, decl a, _LTOG dec a) +#define DEC_W(a) CHOICE(decw a, decw a, _WTOG dec a) +#define DEC_B(a) CHOICE(decb a, decb a, decb a) +#define DIV_L(a) CHOICE(divl a, divl a, div a) +#define DIV_W(a) CHOICE(divw a, divw a, div a) +#define DIV_B(a) CHOICE(divb a, divb a, divb a) +#define ENTER(a,b) CHOICE(enter ARG2(a,b), enter ARG2(a,b), enter ARG2(b,a)) +#define HLT CHOICE(hlt, hlt, hlt) +#define IDIV_L(a) CHOICE(idivl a, idivl a, _LTOG idiv a) +#define IDIV_W(a) CHOICE(idivw a, idivw a, _WTOG idiv a) +#define IDIV_B(a) CHOICE(idivb a, idivb a, idivb a) +/* More forms than this for imul!! */ +#define IMUL_L(a, b) CHOICE(imull ARG2(a,b), imull ARG2(a,b), _LTOG imul ARG2(b,a)) +#define IMUL_W(a, b) CHOICE(imulw ARG2(a,b), imulw ARG2(a,b), _WTOG imul ARG2(b,a)) +#define IMUL_B(a) CHOICE(imulb a, imulb a, imulb a) +#define IN_L CHOICE(inl (DX), inl ARG2(DX,EAX), _LTOG in DX) +#define IN_W CHOICE(inw (DX), inw ARG2(DX,AX), _WTOG in DX) +#define IN_B CHOICE(inb (DX), inb ARG2(DX,AL), inb DX) +/* Please AS code writer: use the following ONLY, if you refer to ports<256 + * directly, but not in IN1_W(DX), for instance, even if IN1_ looks nicer + */ +#if defined (sun) +#define IN1_L(a) CHOICE(inl (a), inl ARG2(a,EAX), _LTOG in a) +#define IN1_W(a) CHOICE(inw (a), inw ARG2(a,AX), _WTOG in a) +#define IN1_B(a) CHOICE(inb (a), inb ARG2(a,AL), inb a) +#else +#define IN1_L(a) CHOICE(inl a, inl ARG2(a,EAX), _LTOG in a) +#define IN1_W(a) CHOICE(inw a, inw ARG2(a,AX), _WTOG in a) +#define IN1_B(a) CHOICE(inb a, inb ARG2(a,AL), inb a) +#endif +#define INC_L(a) CHOICE(incl a, incl a, _LTOG inc a) +#define INC_W(a) CHOICE(incw a, incw a, _WTOG inc a) +#define INC_B(a) CHOICE(incb a, incb a, incb a) +#define INS_L CHOICE(insl, insl, _LTOG ins) +#define INS_W CHOICE(insw, insw, _WTOG ins) +#define INS_B CHOICE(insb, insb, insb) +#define INT(a) CHOICE(int a, int a, int a) +#define INT3 CHOICE(int CONST(3), int3, int CONST(3)) +#define INTO CHOICE(into, into, into) +#define IRET CHOICE(iret, iret, iret) +#define IRETD CHOICE(iret, iret, iretd) +#define JA(a) CHOICE(ja a, ja a, ja a) +#define JAE(a) CHOICE(jae a, jae a, jae a) +#define JB(a) CHOICE(jb a, jb a, jb a) +#define JBE(a) CHOICE(jbe a, jbe a, jbe a) +#define JC(a) CHOICE(jc a, jc a, jc a) +#define JE(a) CHOICE(je a, je a, je a) +#define JG(a) CHOICE(jg a, jg a, jg a) +#define JGE(a) CHOICE(jge a, jge a, jge a) +#define JL(a) CHOICE(jl a, jl a, jl a) +#define JLE(a) CHOICE(jle a, jle a, jle a) +#define JNA(a) CHOICE(jna a, jna a, jna a) +#define JNAE(a) CHOICE(jnae a, jnae a, jnae a) +#define JNB(a) CHOICE(jnb a, jnb a, jnb a) +#define JNBE(a) CHOICE(jnbe a, jnbe a, jnbe a) +#define JNC(a) CHOICE(jnc a, jnc a, jnc a) +#define JNE(a) CHOICE(jne a, jne a, jne a) +#define JNG(a) CHOICE(jng a, jng a, jng a) +#define JNGE(a) CHOICE(jnge a, jnge a, jnge a) +#define JNL(a) CHOICE(jnl a, jnl a, jnl a) +#define JNLE(a) CHOICE(jnle a, jnle a, jnle a) +#define JNO(a) CHOICE(jno a, jno a, jno a) +#define JNP(a) CHOICE(jnp a, jnp a, jnp a) +#define JNS(a) CHOICE(jns a, jns a, jns a) +#define JNZ(a) CHOICE(jnz a, jnz a, jnz a) +#define JO(a) CHOICE(jo a, jo a, jo a) +#define JP(a) CHOICE(jp a, jp a, jp a) +#define JPE(a) CHOICE(jpe a, jpe a, jpe a) +#define JPO(a) CHOICE(jpo a, jpo a, jpo a) +#define JS(a) CHOICE(js a, js a, js a) +#define JZ(a) CHOICE(jz a, jz a, jz a) +#define JMP(a) CHOICE(jmp a, jmp a, jmp a) +#define JMPF(s,a) CHOICE(ljmp ARG2(s,a), ljmp ARG2(s,a), jmpf s:a) +#define LAHF CHOICE(lahf, lahf, lahf) +#if !defined(_REAL_MODE) && !defined(_V86_MODE) +#define LAR(a, b) CHOICE(lar ARG2(a, b), lar ARG2(a, b), lar ARG2(b, a)) +#endif +#define LEA_L(a, b) CHOICE(leal ARG2(a,b), leal ARG2(a,b), _LTOG lea ARG2(b,a)) +#define LEA_W(a, b) CHOICE(leaw ARG2(a,b), leaw ARG2(a,b), _WTOG lea ARG2(b,a)) +#define LEAVE CHOICE(leave, leave, leave) +#define LGDT(a) CHOICE(lgdt a, lgdt a, lgdt a) +#define LIDT(a) CHOICE(lidt a, lidt a, lidt a) +#define LDS(a, b) CHOICE(ldsl ARG2(a,b), lds ARG2(a,b), lds ARG2(b,a)) +#define LES(a, b) CHOICE(lesl ARG2(a,b), les ARG2(a,b), les ARG2(b,a)) +#define LFS(a, b) CHOICE(lfsl ARG2(a,b), lfs ARG2(a,b), lfs ARG2(b,a)) +#define LGS(a, b) CHOICE(lgsl ARG2(a,b), lgs ARG2(a,b), lgs ARG2(b,a)) +#define LSS(a, b) CHOICE(lssl ARG2(a,b), lss ARG2(a,b), lss ARG2(b,a)) +#define LLDT(a) CHOICE(lldt a, lldt a, lldt a) +#define LMSW(a) CHOICE(lmsw a, lmsw a, lmsw a) +#define LOCK CHOICE(lock, lock, lock) +#define LODS_L CHOICE(lodsl, lodsl, _LTOG lods) +#define LODS_W CHOICE(lodsw, lodsw, _WTOG lods) +#define LODS_B CHOICE(lodsb, lodsb, lodsb) +#define LOOP(a) CHOICE(loop a, loop a, loop a) +#define LOOPE(a) CHOICE(loope a, loope a, loope a) +#define LOOPZ(a) CHOICE(loopz a, loopz a, loopz a) +#define LOOPNE(a) CHOICE(loopne a, loopne a, loopne a) +#define LOOPNZ(a) CHOICE(loopnz a, loopnz a, loopnz a) +#if !defined(_REAL_MODE) && !defined(_V86_MODE) +#define LSL(a, b) CHOICE(lsl ARG2(a,b), lsl ARG2(a,b), lsl ARG2(b,a)) +#endif +#define LTR(a) CHOICE(ltr a, ltr a, ltr a) +#define MOV_SR(a, b) CHOICE(movw ARG2(a,b), mov ARG2(a,b), mov ARG2(b,a)) +#define MOV_L(a, b) CHOICE(movl ARG2(a,b), movl ARG2(a,b), _LTOG mov ARG2(b,a)) +#define MOV_W(a, b) CHOICE(movw ARG2(a,b), movw ARG2(a,b), _WTOG mov ARG2(b,a)) +#define MOV_B(a, b) CHOICE(movb ARG2(a,b), movb ARG2(a,b), movb ARG2(b,a)) +#define MOVS_L CHOICE(movsl, movsl, _LTOG movs) +#define MOVS_W CHOICE(movsw, movsw, _WTOG movs) +#define MOVS_B CHOICE(movsb, movsb, movsb) +#define MOVSX_BL(a, b) CHOICE(movsbl ARG2(a,b), movsbl ARG2(a,b), movsx ARG2(b,a)) +#define MOVSX_BW(a, b) CHOICE(movsbw ARG2(a,b), movsbw ARG2(a,b), movsx ARG2(b,a)) +#define MOVSX_WL(a, b) CHOICE(movswl ARG2(a,b), movswl ARG2(a,b), movsx ARG2(b,a)) +#define MOVZX_BL(a, b) CHOICE(movzbl ARG2(a,b), movzbl ARG2(a,b), movzx ARG2(b,a)) +#define MOVZX_BW(a, b) CHOICE(movzbw ARG2(a,b), movzbw ARG2(a,b), movzx ARG2(b,a)) +#define MOVZX_WL(a, b) CHOICE(movzwl ARG2(a,b), movzwl ARG2(a,b), movzx ARG2(b,a)) +#define MUL_L(a) CHOICE(mull a, mull a, _LTOG mul a) +#define MUL_W(a) CHOICE(mulw a, mulw a, _WTOG mul a) +#define MUL_B(a) CHOICE(mulb a, mulb a, mulb a) +#define NEG_L(a) CHOICE(negl a, negl a, _LTOG neg a) +#define NEG_W(a) CHOICE(negw a, negw a, _WTOG neg a) +#define NEG_B(a) CHOICE(negb a, negb a, negb a) +#define NOP CHOICE(nop, nop, nop) +#define NOT_L(a) CHOICE(notl a, notl a, _LTOG not a) +#define NOT_W(a) CHOICE(notw a, notw a, _WTOG not a) +#define NOT_B(a) CHOICE(notb a, notb a, notb a) +#define OR_L(a,b) CHOICE(orl ARG2(a,b), orl ARG2(a,b), _LTOG or ARG2(b,a)) +#define OR_W(a,b) CHOICE(orw ARG2(a,b), orw ARG2(a,b), _WTOG or ARG2(b,a)) +#define OR_B(a,b) CHOICE(orb ARG2(a,b), orb ARG2(a,b), orb ARG2(b,a)) +#define OUT_L CHOICE(outl (DX), outl ARG2(EAX,DX), _LTOG out DX) +#define OUT_W CHOICE(outw (DX), outw ARG2(AX,DX), _WTOG out DX) +#define OUT_B CHOICE(outb (DX), outb ARG2(AL,DX), outb DX) +/* Please AS code writer: use the following ONLY, if you refer to ports<256 + * directly, but not in OUT1_W(DX), for instance, even if OUT1_ looks nicer + */ +#define OUT1_L(a) CHOICE(outl (a), outl ARG2(EAX,a), _LTOG out a) +#define OUT1_W(a) CHOICE(outw (a), outw ARG2(AX,a), _WTOG out a) +#define OUT1_B(a) CHOICE(outb (a), outb ARG2(AL,a), outb a) +#define OUTS_L CHOICE(outsl, outsl, _LTOG outs) +#define OUTS_W CHOICE(outsw, outsw, _WTOG outs) +#define OUTS_B CHOICE(outsb, outsb, outsb) +#define POP_SR(a) CHOICE(pop a, pop a, pop a) +#define POP_L(a) CHOICE(popl a, popl a, _LTOG pop a) +#define POP_W(a) CHOICE(popw a, popw a, _WTOG pop a) +#define POPA_L CHOICE(popal, popal, _LTOG popa) +#define POPA_W CHOICE(popaw, popaw, _WTOG popa) +#define POPF_L CHOICE(popfl, popfl, _LTOG popf) +#define POPF_W CHOICE(popfw, popfw, _WTOG popf) +#define PUSH_SR(a) CHOICE(push a, push a, push a) +#define PUSH_L(a) CHOICE(pushl a, pushl a, _LTOG push a) +#define PUSH_W(a) CHOICE(pushw a, pushw a, _WTOG push a) +#define PUSH_B(a) CHOICE(push a, pushb a, push a) +#define PUSHA_L CHOICE(pushal, pushal, _LTOG pusha) +#define PUSHA_W CHOICE(pushaw, pushaw, _WTOG pusha) +#define PUSHF_L CHOICE(pushfl, pushfl, _LTOG pushf) +#define PUSHF_W CHOICE(pushfw, pushfw, _WTOG pushf) +#define RCL_L(a, b) CHOICE(rcll ARG2(a,b), rcll ARG2(a,b), _LTOG rcl ARG2(b,a)) +#define RCL_W(a, b) CHOICE(rclw ARG2(a,b), rclw ARG2(a,b), _WTOG rcl ARG2(b,a)) +#define RCL_B(a, b) CHOICE(rclb ARG2(a,b), rclb ARG2(a,b), rclb ARG2(b,a)) +#define RCR_L(a, b) CHOICE(rcrl ARG2(a,b), rcrl ARG2(a,b), _LTOG rcr ARG2(b,a)) +#define RCR_W(a, b) CHOICE(rcrw ARG2(a,b), rcrw ARG2(a,b), _WTOG rcr ARG2(b,a)) +#define RCR_B(a, b) CHOICE(rcrb ARG2(a,b), rcrb ARG2(a,b), rcrb ARG2(b,a)) +#define ROL_L(a, b) CHOICE(roll ARG2(a,b), roll ARG2(a,b), _LTOG rol ARG2(b,a)) +#define ROL_W(a, b) CHOICE(rolw ARG2(a,b), rolw ARG2(a,b), _WTOG rol ARG2(b,a)) +#define ROL_B(a, b) CHOICE(rolb ARG2(a,b), rolb ARG2(a,b), rolb ARG2(b,a)) +#define ROR_L(a, b) CHOICE(rorl ARG2(a,b), rorl ARG2(a,b), _LTOG ror ARG2(b,a)) +#define ROR_W(a, b) CHOICE(rorw ARG2(a,b), rorw ARG2(a,b), _WTOG ror ARG2(b,a)) +#define ROR_B(a, b) CHOICE(rorb ARG2(a,b), rorb ARG2(a,b), rorb ARG2(b,a)) +#define REP CHOICE(rep ;, rep ;, repe) +#define REPE CHOICE(repz ;, repe ;, repe) +#define REPNE CHOICE(repnz ;, repne ;, repne) +#define REPNZ REPNE +#define REPZ REPE +#define RET CHOICE(ret, ret, ret) +#define SAHF CHOICE(sahf, sahf, sahf) +#define SAL_L(a, b) CHOICE(sall ARG2(a,b), sall ARG2(a,b), _LTOG sal ARG2(b,a)) +#define SAL_W(a, b) CHOICE(salw ARG2(a,b), salw ARG2(a,b), _WTOG sal ARG2(b,a)) +#define SAL_B(a, b) CHOICE(salb ARG2(a,b), salb ARG2(a,b), salb ARG2(b,a)) +#define SAR_L(a, b) CHOICE(sarl ARG2(a,b), sarl ARG2(a,b), _LTOG sar ARG2(b,a)) +#define SAR_W(a, b) CHOICE(sarw ARG2(a,b), sarw ARG2(a,b), _WTOG sar ARG2(b,a)) +#define SAR_B(a, b) CHOICE(sarb ARG2(a,b), sarb ARG2(a,b), sarb ARG2(b,a)) +#define SBB_L(a, b) CHOICE(sbbl ARG2(a,b), sbbl ARG2(a,b), _LTOG sbb ARG2(b,a)) +#define SBB_W(a, b) CHOICE(sbbw ARG2(a,b), sbbw ARG2(a,b), _WTOG sbb ARG2(b,a)) +#define SBB_B(a, b) CHOICE(sbbb ARG2(a,b), sbbb ARG2(a,b), sbbb ARG2(b,a)) +#define SCAS_L CHOICE(scasl, scasl, _LTOG scas) +#define SCAS_W CHOICE(scasw, scasw, _WTOG scas) +#define SCAS_B CHOICE(scasb, scasb, scasb) +#define SETA(a) CHOICE(seta a, seta a, seta a) +#define SETAE(a) CHOICE(setae a, setae a, setae a) +#define SETB(a) CHOICE(setb a, setb a, setb a) +#define SETBE(a) CHOICE(setbe a, setbe a, setbe a) +#define SETC(a) CHOICE(setc a, setb a, setb a) +#define SETE(a) CHOICE(sete a, sete a, sete a) +#define SETG(a) CHOICE(setg a, setg a, setg a) +#define SETGE(a) CHOICE(setge a, setge a, setge a) +#define SETL(a) CHOICE(setl a, setl a, setl a) +#define SETLE(a) CHOICE(setle a, setle a, setle a) +#define SETNA(a) CHOICE(setna a, setna a, setna a) +#define SETNAE(a) CHOICE(setnae a, setnae a, setnae a) +#define SETNB(a) CHOICE(setnb a, setnb a, setnb a) +#define SETNBE(a) CHOICE(setnbe a, setnbe a, setnbe a) +#define SETNC(a) CHOICE(setnc a, setnb a, setnb a) +#define SETNE(a) CHOICE(setne a, setne a, setne a) +#define SETNG(a) CHOICE(setng a, setng a, setng a) +#define SETNGE(a) CHOICE(setnge a, setnge a, setnge a) +#define SETNL(a) CHOICE(setnl a, setnl a, setnl a) +#define SETNLE(a) CHOICE(setnle a, setnle a, setnle a) +#define SETNO(a) CHOICE(setno a, setno a, setno a) +#define SETNP(a) CHOICE(setnp a, setnp a, setnp a) +#define SETNS(a) CHOICE(setns a, setns a, setna a) +#define SETNZ(a) CHOICE(setnz a, setnz a, setnz a) +#define SETO(a) CHOICE(seto a, seto a, seto a) +#define SETP(a) CHOICE(setp a, setp a, setp a) +#define SETPE(a) CHOICE(setpe a, setpe a, setpe a) +#define SETPO(a) CHOICE(setpo a, setpo a, setpo a) +#define SETS(a) CHOICE(sets a, sets a, seta a) +#define SETZ(a) CHOICE(setz a, setz a, setz a) +#define SGDT(a) CHOICE(sgdt a, sgdt a, sgdt a) +#define SIDT(a) CHOICE(sidt a, sidt a, sidt a) +#define SHL_L(a, b) CHOICE(shll ARG2(a,b), shll ARG2(a,b), _LTOG shl ARG2(b,a)) +#define SHL_W(a, b) CHOICE(shlw ARG2(a,b), shlw ARG2(a,b), _WTOG shl ARG2(b,a)) +#define SHL_B(a, b) CHOICE(shlb ARG2(a,b), shlb ARG2(a,b), shlb ARG2(b,a)) +#define SHLD_L(a,b,c) CHOICE(shldl ARG3(a,b,c), shldl ARG3(a,b,c), _LTOG shld ARG3(c,b,a)) +#define SHLD2_L(a,b) CHOICE(shldl ARG2(a,b), shldl ARG3(CL,a,b), _LTOG shld ARG3(b,a,CL)) +#define SHLD_W(a,b,c) CHOICE(shldw ARG3(a,b,c), shldw ARG3(a,b,c), _WTOG shld ARG3(c,b,a)) +#define SHLD2_W(a,b) CHOICE(shldw ARG2(a,b), shldw ARG3(CL,a,b), _WTOG shld ARG3(b,a,CL)) +#define SHR_L(a, b) CHOICE(shrl ARG2(a,b), shrl ARG2(a,b), _LTOG shr ARG2(b,a)) +#define SHR_W(a, b) CHOICE(shrw ARG2(a,b), shrw ARG2(a,b), _WTOG shr ARG2(b,a)) +#define SHR_B(a, b) CHOICE(shrb ARG2(a,b), shrb ARG2(a,b), shrb ARG2(b,a)) +#define SHRD_L(a,b,c) CHOICE(shrdl ARG3(a,b,c), shrdl ARG3(a,b,c), _LTOG shrd ARG3(c,b,a)) +#define SHRD2_L(a,b) CHOICE(shrdl ARG2(a,b), shrdl ARG3(CL,a,b), _LTOG shrd ARG3(b,a,CL)) +#define SHRD_W(a,b,c) CHOICE(shrdw ARG3(a,b,c), shrdw ARG3(a,b,c), _WTOG shrd ARG3(c,b,a)) +#define SHRD2_W(a,b) CHOICE(shrdw ARG2(a,b), shrdw ARG3(CL,a,b), _WTOG shrd ARG3(b,a,CL)) +#define SLDT(a) CHOICE(sldt a, sldt a, sldt a) +#define SMSW(a) CHOICE(smsw a, smsw a, smsw a) +#define STC CHOICE(stc, stc, stc) +#define STD CHOICE(std, std, std) +#define STI CHOICE(sti, sti, sti) +#define STOS_L CHOICE(stosl, stosl, _LTOG stos) +#define STOS_W CHOICE(stosw, stosw, _WTOG stos) +#define STOS_B CHOICE(stosb, stosb, stosb) +#define STR(a) CHOICE(str a, str a, str a) +#define SUB_L(a, b) CHOICE(subl ARG2(a,b), subl ARG2(a,b), _LTOG sub ARG2(b,a)) +#define SUB_W(a, b) CHOICE(subw ARG2(a,b), subw ARG2(a,b), _WTOG sub ARG2(b,a)) +#define SUB_B(a, b) CHOICE(subb ARG2(a,b), subb ARG2(a,b), subb ARG2(b,a)) +#define TEST_L(a, b) CHOICE(testl ARG2(a,b), testl ARG2(a,b), _LTOG test ARG2(b,a)) +#define TEST_W(a, b) CHOICE(testw ARG2(a,b), testw ARG2(a,b), _WTOG test ARG2(b,a)) +#define TEST_B(a, b) CHOICE(testb ARG2(a,b), testb ARG2(a,b), testb ARG2(b,a)) +#define VERR(a) CHOICE(verr a, verr a, verr a) +#define VERW(a) CHOICE(verw a, verw a, verw a) +#define WAIT CHOICE(wait, wait, wait) +#define XCHG_L(a, b) CHOICE(xchgl ARG2(a,b), xchgl ARG2(a,b), _LTOG xchg ARG2(b,a)) +#define XCHG_W(a, b) CHOICE(xchgw ARG2(a,b), xchgw ARG2(a,b), _WTOG xchg ARG2(b,a)) +#define XCHG_B(a, b) CHOICE(xchgb ARG2(a,b), xchgb ARG2(a,b), xchgb ARG2(b,a)) +#define XLAT CHOICE(xlat, xlat, xlat) +#define XOR_L(a, b) CHOICE(xorl ARG2(a,b), xorl ARG2(a,b), _LTOG xor ARG2(b,a)) +#define XOR_W(a, b) CHOICE(xorw ARG2(a,b), xorw ARG2(a,b), _WTOG xor ARG2(b,a)) +#define XOR_B(a, b) CHOICE(xorb ARG2(a,b), xorb ARG2(a,b), xorb ARG2(b,a)) + + +/* Floating Point Instructions */ +#define F2XM1 CHOICE(f2xm1, f2xm1, f2xm1) +#define FABS CHOICE(fabs, fabs, fabs) +#define FADD_D(a) CHOICE(faddl a, faddl a, faddd a) +#define FADD_S(a) CHOICE(fadds a, fadds a, fadds a) +#define FADD2(a, b) CHOICE(fadd ARG2(a,b), fadd ARG2(a,b), fadd ARG2(b,a)) +#define FADDP(a, b) CHOICE(faddp ARG2(a,b), faddp ARG2(a,b), faddp ARG2(b,a)) +#define FIADD_L(a) CHOICE(fiaddl a, fiaddl a, fiaddl a) +#define FIADD_W(a) CHOICE(fiadd a, fiadds a, fiadds a) +#define FBLD(a) CHOICE(fbld a, fbld a, fbld a) +#define FBSTP(a) CHOICE(fbstp a, fbstp a, fbstp a) +#define FCHS CHOICE(fchs, fchs, fchs) +#define FCLEX CHOICE(fclex, wait; fnclex, wait; fclex) +#define FNCLEX CHOICE(fnclex, fnclex, fclex) +#define FCOM(a) CHOICE(fcom a, fcom a, fcom a) +#define FCOM_D(a) CHOICE(fcoml a, fcoml a, fcomd a) +#define FCOM_S(a) CHOICE(fcoms a, fcoms a, fcoms a) +#define FCOMP(a) CHOICE(fcomp a, fcomp a, fcomp a) +#define FCOMP_D(a) CHOICE(fcompl a, fcompl a, fcompd a) +#define FCOMP_S(a) CHOICE(fcomps a, fcomps a, fcomps a) +#define FCOMPP CHOICE(fcompp, fcompp, fcompp) +#define FCOS CHOICE(fcos, fcos, fcos) +#define FDECSTP CHOICE(fdecstp, fdecstp, fdecstp) +#define FDIV_D(a) CHOICE(fdivl a, fdivl a, fdivd a) +#define FDIV_S(a) CHOICE(fdivs a, fdivs a, fdivs a) +#define FDIV2(a, b) CHOICE(fdiv ARG2(a,b), fdiv ARG2(a,b), fdiv ARG2(b,a)) +#define FDIVP(a, b) CHOICE(fdivp ARG2(a,b), fdivp ARG2(a,b), fdivp ARG2(b,a)) +#define FIDIV_L(a) CHOICE(fidivl a, fidivl a, fidivl a) +#define FIDIV_W(a) CHOICE(fidiv a, fidivs a, fidivs a) +#define FDIVR_D(a) CHOICE(fdivrl a, fdivrl a, fdivrd a) +#define FDIVR_S(a) CHOICE(fdivrs a, fdivrs a, fdivrs a) +#define FDIVR2(a, b) CHOICE(fdivr ARG2(a,b), fdivr ARG2(a,b), fdivr ARG2(b,a)) +#define FDIVRP(a, b) CHOICE(fdivrp ARG2(a,b), fdivrp ARG2(a,b), fdivrp ARG2(b,a)) +#define FIDIVR_L(a) CHOICE(fidivrl a, fidivrl a, fidivrl a) +#define FIDIVR_W(a) CHOICE(fidivr a, fidivrs a, fidivrs a) +#define FFREE(a) CHOICE(ffree a, ffree a, ffree a) +#define FICOM_L(a) CHOICE(ficoml a, ficoml a, ficoml a) +#define FICOM_W(a) CHOICE(ficom a, ficoms a, ficoms a) +#define FICOMP_L(a) CHOICE(ficompl a, ficompl a, ficompl a) +#define FICOMP_W(a) CHOICE(ficomp a, ficomps a, ficomps a) +#define FILD_Q(a) CHOICE(fildll a, fildq a, fildq a) +#define FILD_L(a) CHOICE(fildl a, fildl a, fildl a) +#define FILD_W(a) CHOICE(fild a, filds a, filds a) +#define FINCSTP CHOICE(fincstp, fincstp, fincstp) +#define FINIT CHOICE(finit, wait; fninit, wait; finit) +#define FNINIT CHOICE(fninit, fninit, finit) +#define FIST_L(a) CHOICE(fistl a, fistl a, fistl a) +#define FIST_W(a) CHOICE(fist a, fists a, fists a) +#define FISTP_Q(a) CHOICE(fistpll a, fistpq a, fistpq a) +#define FISTP_L(a) CHOICE(fistpl a, fistpl a, fistpl a) +#define FISTP_W(a) CHOICE(fistp a, fistps a, fistps a) +#define FLD_X(a) CHOICE(fldt a, fldt a, fldx a) /* 80 bit data type! */ +#define FLD_D(a) CHOICE(fldl a, fldl a, fldd a) +#define FLD_S(a) CHOICE(flds a, flds a, flds a) +#define FLD1 CHOICE(fld1, fld1, fld1) +#define FLDL2T CHOICE(fldl2t, fldl2t, fldl2t) +#define FLDL2E CHOICE(fldl2e, fldl2e, fldl2e) +#define FLDPI CHOICE(fldpi, fldpi, fldpi) +#define FLDLG2 CHOICE(fldlg2, fldlg2, fldlg2) +#define FLDLN2 CHOICE(fldln2, fldln2, fldln2) +#define FLDZ CHOICE(fldz, fldz, fldz) +#define FLDCW(a) CHOICE(fldcw a, fldcw a, fldcw a) +#define FLDENV(a) CHOICE(fldenv a, fldenv a, fldenv a) +#define FMUL_S(a) CHOICE(fmuls a, fmuls a, fmuls a) +#define FMUL_D(a) CHOICE(fmull a, fmull a, fmuld a) +#define FMUL2(a, b) CHOICE(fmul ARG2(a,b), fmul ARG2(a,b), fmul ARG2(b,a)) +#define FMULP(a, b) CHOICE(fmulp ARG2(a,b), fmulp ARG2(a,b), fmulp ARG2(b,a)) +#define FIMUL_L(a) CHOICE(fimull a, fimull a, fimull a) +#define FIMUL_W(a) CHOICE(fimul a, fimuls a, fimuls a) +#define FNOP CHOICE(fnop, fnop, fnop) +#define FPATAN CHOICE(fpatan, fpatan, fpatan) +#define FPREM CHOICE(fprem, fprem, fprem) +#define FPREM1 CHOICE(fprem1, fprem1, fprem1) +#define FPTAN CHOICE(fptan, fptan, fptan) +#define FRNDINT CHOICE(frndint, frndint, frndint) +#define FRSTOR(a) CHOICE(frstor a, frstor a, frstor a) +#define FSAVE(a) CHOICE(fsave a, wait; fnsave a, wait; fsave a) +#define FNSAVE(a) CHOICE(fnsave a, fnsave a, fsave a) +#define FSCALE CHOICE(fscale, fscale, fscale) +#define FSIN CHOICE(fsin, fsin, fsin) +#define FSINCOS CHOICE(fsincos, fsincos, fsincos) +#define FSQRT CHOICE(fsqrt, fsqrt, fsqrt) +#define FST_D(a) CHOICE(fstl a, fstl a, fstd a) +#define FST_S(a) CHOICE(fsts a, fsts a, fsts a) +#define FSTP_X(a) CHOICE(fstpt a, fstpt a, fstpx a) +#define FSTP_D(a) CHOICE(fstpl a, fstpl a, fstpd a) +#define FSTP_S(a) CHOICE(fstps a, fstps a, fstps a) +#define FSTCW(a) CHOICE(fstcw a, wait; fnstcw a, wait; fstcw a) +#define FNSTCW(a) CHOICE(fnstcw a, fnstcw a, fstcw a) +#define FSTENV(a) CHOICE(fstenv a, wait; fnstenv a, fstenv a) +#define FNSTENV(a) CHOICE(fnstenv a, fnstenv a, fstenv a) +#define FSTSW(a) CHOICE(fstsw a, wait; fnstsw a, wait; fstsw a) +#define FNSTSW(a) CHOICE(fnstsw a, fnstsw a, fstsw a) +#define FSUB_S(a) CHOICE(fsubs a, fsubs a, fsubs a) +#define FSUB_D(a) CHOICE(fsubl a, fsubl a, fsubd a) +#define FSUB2(a, b) CHOICE(fsub ARG2(a,b), fsub ARG2(a,b), fsub ARG2(b,a)) +#define FSUBP(a, b) CHOICE(fsubp ARG2(a,b), fsubp ARG2(a,b), fsubp ARG2(b,a)) +#define FISUB_L(a) CHOICE(fisubl a, fisubl a, fisubl a) +#define FISUB_W(a) CHOICE(fisub a, fisubs a, fisubs a) +#define FSUBR_S(a) CHOICE(fsubrs a, fsubrs a, fsubrs a) +#define FSUBR_D(a) CHOICE(fsubrl a, fsubrl a, fsubrd a) +#define FSUBR2(a, b) CHOICE(fsubr ARG2(a,b), fsubr ARG2(a,b), fsubr ARG2(b,a)) +#define FSUBRP(a, b) CHOICE(fsubrp ARG2(a,b), fsubrp ARG2(a,b), fsubrp ARG2(b,a)) +#define FISUBR_L(a) CHOICE(fisubrl a, fisubrl a, fisubrl a) +#define FISUBR_W(a) CHOICE(fisubr a, fisubrs a, fisubrs a) +#define FTST CHOICE(ftst, ftst, ftst) +#define FUCOM(a) CHOICE(fucom a, fucom a, fucom a) +#define FUCOMP(a) CHOICE(fucomp a, fucomp a, fucomp a) +#define FUCOMPP CHOICE(fucompp, fucompp, fucompp) +#define FWAIT CHOICE(wait, wait, wait) +#define FXAM CHOICE(fxam, fxam, fxam) +#define FXCH(a) CHOICE(fxch a, fxch a, fxch a) +#define FXTRACT CHOICE(fxtract, fxtract, fxtract) +#define FYL2X CHOICE(fyl2x, fyl2x, fyl2x) +#define FYL2XP1 CHOICE(fyl2xp1, fyl2xp1, fyl2xp1) + +#endif /* __ASSYNTAX_H__ */ diff --git a/hw/xfree86/os-support/bsd/bsd_VTsw.c b/hw/xfree86/os-support/bsd/bsd_VTsw.c new file mode 100644 index 000000000..13e78ad34 --- /dev/null +++ b/hw/xfree86/os-support/bsd/bsd_VTsw.c @@ -0,0 +1,92 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/bsd_VTsw.c,v 3.5 1996/12/23 06:49:35 dawes Exp $ */ +/* + * Derived from VTsw_usl.c which is + * Copyright 1993 by David Wexelblat + * by S_ren Schmidt (sos@login.dkuug.dk) + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Wexelblat not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. David Wexelblat makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL DAVID WEXELBLAT 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. + * + */ +/* $Xorg: bsd_VTsw.c,v 1.3 2000/08/17 19:51:21 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +/* + * Handle the VT-switching interface for OSs that use USL-style ioctl()s + * (the bsd, sysv, sco, and linux subdirs). + */ + +/* + * This function is the signal handler for the VT-switching signal. It + * is only referenced inside the OS-support layer. + */ +void xf86VTRequest(sig) +int sig; +{ +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) { + xf86Info.vtRequestsPending = TRUE; + } +#endif + return; +} + +Bool xf86VTSwitchPending() +{ +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) { + return(xf86Info.vtRequestsPending ? TRUE : FALSE); + } +#endif + return FALSE; +} + +Bool xf86VTSwitchAway() +{ +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) { + xf86Info.vtRequestsPending = FALSE; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0) + return(FALSE); + else + return(TRUE); + } +#endif + return FALSE; +} + +Bool xf86VTSwitchTo() +{ +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) { + xf86Info.vtRequestsPending = FALSE; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) + return(FALSE); + else + return(TRUE); + } +#endif + return(TRUE); +} diff --git a/hw/xfree86/os-support/bsd/bsd_init.c b/hw/xfree86/os-support/bsd/bsd_init.c new file mode 100644 index 000000000..961fd0eac --- /dev/null +++ b/hw/xfree86/os-support/bsd/bsd_init.c @@ -0,0 +1,780 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/bsd_init.c,v 3.8.2.1 1998/02/06 22:36:49 hohndel Exp $ */ +/* + * Copyright 1992 by Rich Murphey + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Rich Murphey and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Rich Murphey and + * David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT 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. + * + */ +/* $Xorg: bsd_init.c,v 1.3 2000/08/17 19:51:21 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +extern void xf86VTRequest( +#if NeedFunctionPrototypes + int +#endif +); + +static Bool KeepTty = FALSE; +static int devConsoleFd = -1; +static int VTnum = -1; +static int initialVT = -1; + +#ifdef PCCONS_SUPPORT +/* Stock 0.1 386bsd pccons console driver interface */ +#ifndef __OpenBSD__ +# define PCCONS_CONSOLE_DEV1 "/dev/ttyv0" +#else +# define PCCONS_CONSOLE_DEV1 "/dev/ttyC0" +#endif +#define PCCONS_CONSOLE_DEV2 "/dev/vga" +#define PCCONS_CONSOLE_MODE O_RDWR|O_NDELAY +#endif + +#ifdef CODRV_SUPPORT +/* Holger Veit's codrv console driver */ +#define CODRV_CONSOLE_DEV "/dev/kbd" +#define CODRV_CONSOLE_MODE O_RDONLY|O_NDELAY +#endif + +#ifdef SYSCONS_SUPPORT +/* The FreeBSD 1.1 version syscons driver uses /dev/ttyv0 */ +#define SYSCONS_CONSOLE_DEV1 "/dev/ttyv0" +#define SYSCONS_CONSOLE_DEV2 "/dev/vga" +#define SYSCONS_CONSOLE_MODE O_RDWR|O_NDELAY +#endif + +#ifdef PCVT_SUPPORT +/* Hellmuth Michaelis' pcvt driver */ +#ifndef __OpenBSD__ +# define PCVT_CONSOLE_DEV "/dev/ttyv0" +#else +# define PCVT_CONSOLE_DEV "/dev/ttyC0" +#endif +#define PCVT_CONSOLE_MODE O_RDWR|O_NDELAY +#endif + +#define CHECK_DRIVER_MSG \ + "Check your kernel's console driver configuration and /dev entries" + +static char *supported_drivers[] = { +#ifdef PCCONS_SUPPORT + "pccons (with X support)", +#endif +#ifdef CODRV_SUPPORT + "codrv", +#endif +#ifdef SYSCONS_SUPPORT + "syscons", +#endif +#ifdef PCVT_SUPPORT + "pcvt", +#endif +}; + + +/* + * Functions to probe for the existance of a supported console driver. + * Any function returns either a valid file descriptor (driver probed + * succesfully), -1 (driver not found), or uses FatalError() if the + * driver was found but proved to not support the required mode to run + * an X server. + */ + +typedef int (*xf86ConsOpen_t)( +#if NeedFunctionPrototypes + void +#endif +); + +#ifdef PCCONS_SUPPORT +static int xf86OpenPccons( +#if NeedFunctionPrototypes + void +#endif +); +#endif /* PCCONS_SUPPORT */ + +#ifdef CODRV_SUPPORT +static int xf86OpenCodrv( +#if NeedFunctionPrototypes + void +#endif +); +#endif /* CODRV_SUPPORT */ + +#ifdef SYSCONS_SUPPORT +static int xf86OpenSyscons( +#if NeedFunctionPrototypes + void +#endif +); +#endif /* SYSCONS_SUPPORT */ + +#ifdef PCVT_SUPPORT +static int xf86OpenPcvt( +#if NeedFunctionPrototypes + void +#endif +); +#endif /* PCVT_SUPPORT */ + +/* + * The sequence of the driver probes is important; start with the + * driver that is best distinguishable, and end with the most generic + * driver. (Otherwise, pcvt would also probe as syscons, and either + * pcvt or syscons might succesfully probe as pccons. Only codrv is + * at its own.) + */ +static xf86ConsOpen_t xf86ConsTab[] = { +#ifdef PCVT_SUPPORT + xf86OpenPcvt, +#endif +#ifdef CODRV_SUPPORT + xf86OpenCodrv, +#endif +#ifdef SYSCONS_SUPPORT + xf86OpenSyscons, +#endif +#ifdef PCCONS_SUPPORT + xf86OpenPccons, +#endif + (xf86ConsOpen_t)NULL +}; + + +void +xf86OpenConsole() +{ + int i, fd; +#ifdef CODRV_SUPPORT + int onoff; +#endif + xf86ConsOpen_t *driver; +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + vtmode_t vtmode; +#endif + + if (serverGeneration == 1) + { + /* check if we are run with euid==0 */ + if (geteuid() != 0) + { + FatalError("xf86OpenConsole: Server must be running with root " + "permissions\n" + "You should be using Xwrapper to start the server or xdm.\n" + "We strongly advise against making the server SUID root!\n"); + } + + if (!KeepTty) + { + /* + * detaching the controlling tty solves problems of kbd character + * loss. This is not interesting for CO driver, because it is + * exclusive. + */ + setpgrp(0, getpid()); + if ((i = open("/dev/tty",O_RDWR)) >= 0) + { + ioctl(i,TIOCNOTTY,(char *)0); + close(i); + } + } + + /* detect which driver we are running on */ + for (driver = xf86ConsTab; *driver; driver++) + { + if((fd = (*driver)()) >= 0) + break; + } + + /* Check that a supported console driver was found */ + if (fd < 0) + { + char cons_drivers[80] = {0, }; + for (i = 0; i < sizeof(supported_drivers) / sizeof(char *); i++) + { + if (i) + { + strcat(cons_drivers, ", "); + } + strcat(cons_drivers, supported_drivers[i]); + } + FatalError( + "%s: No console driver found\n\tSupported drivers: %s\n\t%s\n", + "xf86OpenConsole", cons_drivers, CHECK_DRIVER_MSG); + } + fclose(stdin); + xf86Info.consoleFd = fd; + xf86Info.screenFd = fd; + + xf86Config(FALSE); /* Read XF86Config */ + + switch (xf86Info.consType) + { +#ifdef CODRV_SUPPORT + case CODRV011: + case CODRV01X: + onoff = X_MODE_ON; + if (ioctl (xf86Info.consoleFd, CONSOLE_X_MODE, &onoff) < 0) + { + FatalError("%s: CONSOLE_X_MODE ON failed (%s)\n%s\n", + "xf86OpenConsole", strerror(errno), + CHECK_DRIVER_MSG); + } + if (xf86Info.consType == CODRV01X) + ioctl(xf86Info.consoleFd, VGATAKECTRL, 0); + break; +#endif +#ifdef PCCONS_SUPPORT + case PCCONS: + if (ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_ON, 0) < 0) + { + FatalError("%s: CONSOLE_X_MODE_ON failed (%s)\n%s\n", + "xf86OpenConsole", strerror(errno), + CHECK_DRIVER_MSG); + } + /* + * Hack to prevent keyboard hanging when syslogd closes + * /dev/console + */ + if ((devConsoleFd = open("/dev/console", O_WRONLY,0)) < 0) + { + ErrorF("Warning: couldn't open /dev/console (%s)\n", + strerror(errno)); + } + break; +#endif +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + /* + * First activate the #1 VT. This is a hack to allow a server + * to be started while another one is active. There should be + * a better way. + */ + if (initialVT != 1) { + + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + sleep(1); + } + + /* + * now get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_WAITACTIVE failed\n"); + } + + signal(SIGUSR1, xf86VTRequest); + + vtmode.mode = VT_PROCESS; + vtmode.relsig = SIGUSR1; + vtmode.acqsig = SIGUSR1; + vtmode.frsig = SIGUSR1; + if (ioctl(xf86Info.consoleFd, VT_SETMODE, &vtmode) < 0) + { + FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n"); + } + if (ioctl(xf86Info.consoleFd, KDENABIO, 0) < 0) + { + FatalError("xf86OpenConsole: KDENABIO failed (%s)\n", + strerror(errno)); + } + if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) + { + FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n"); + } + break; +#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ + } + } + else + { + /* serverGeneration != 1 */ +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) + { + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + } +#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ + } + return; +} + + +#ifdef PCCONS_SUPPORT + +static int +xf86OpenPccons() +{ + int fd = -1; + + if ((fd = open(PCCONS_CONSOLE_DEV1, PCCONS_CONSOLE_MODE, 0)) + >= 0 || + (fd = open(PCCONS_CONSOLE_DEV2, PCCONS_CONSOLE_MODE, 0)) + >= 0) + { + if (ioctl(fd, CONSOLE_X_MODE_OFF, 0) < 0) + { + FatalError( + "%s: CONSOLE_X_MODE_OFF failed (%s)\n%s\n%s\n", + "xf86OpenPccons", + strerror(errno), + "Was expecting pccons driver with X support", + CHECK_DRIVER_MSG); + } + xf86Info.consType = PCCONS; + if (xf86Verbose) + { + ErrorF("Using pccons driver with X support\n"); + } + } + return fd; +} + +#endif /* PCCONS_SUPPORT */ + +#ifdef SYSCONS_SUPPORT + +static int +xf86OpenSyscons() +{ + int fd = -1; + vtmode_t vtmode; + char vtname[12]; + struct stat status; + long syscons_version; + + /* Check for syscons */ + if ((fd = open(SYSCONS_CONSOLE_DEV1, SYSCONS_CONSOLE_MODE, 0)) >= 0 + || (fd = open(SYSCONS_CONSOLE_DEV2, SYSCONS_CONSOLE_MODE, 0)) >= 0) + { + if (ioctl(fd, VT_GETMODE, &vtmode) >= 0) + { + /* Get syscons version */ + if (ioctl(fd, CONS_GETVERS, &syscons_version) < 0) + { + syscons_version = 0; + } + + xf86Info.vtno = VTnum; + +#ifdef VT_GETACTIVE + if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0) + initialVT = -1; +#endif + if (xf86Info.vtno == -1) + { + /* + * For old syscons versions (<0x100), VT_OPENQRY returns + * the current VT rather than the next free VT. In this + * case, the server gets started on the current VT instead + * of the next free VT. + */ + +#if 0 + /* check for the fixed VT_OPENQRY */ + if (syscons_version >= 0x100) + { +#endif + if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) + { + /* No free VTs */ + xf86Info.vtno = -1; + } +#if 0 + } +#endif + + if (xf86Info.vtno == -1) + { + /* + * All VTs are in use. If initialVT was found, use it. + * Otherwise, if stdin is a VT, use that one. + */ + if (initialVT != -1) + { + xf86Info.vtno = initialVT; + } + else if ((fstat(0, &status) >= 0) + && S_ISCHR(status.st_mode) + && (ioctl(0, VT_GETMODE, &vtmode) >= 0)) + { + /* stdin is a VT */ + xf86Info.vtno = minor(status.st_rdev) + 1; + } + else + { + if (syscons_version >= 0x100) + { + FatalError("%s: Cannot find a free VT\n", + "xf86OpenSyscons"); + } + /* Should no longer reach here */ + FatalError("%s: %s %s\n\t%s %s\n", + "xf86OpenSyscons", + "syscons versions prior to 1.0 require", + "either the", + "server's stdin be a VT", + "or the use of the vtxx server option"); + } + } + } + + close(fd); +#ifndef __OpenBSD__ + sprintf(vtname, "/dev/ttyv%01x", xf86Info.vtno - 1); +#else + sprintf(vtname, "/dev/ttyC%01x", xf86Info.vtno - 1); +#endif + if ((fd = open(vtname, SYSCONS_CONSOLE_MODE, 0)) < 0) + { + FatalError("xf86OpenSyscons: Cannot open %s (%s)\n", + vtname, strerror(errno)); + } + if (ioctl(fd, VT_GETMODE, &vtmode) < 0) + { + FatalError("xf86OpenSyscons: VT_GETMODE failed\n"); + } + xf86Info.consType = SYSCONS; + if (xf86Verbose) + { + ErrorF("Using syscons driver with X support"); + if (syscons_version >= 0x100) + { + ErrorF(" (version %d.%d)\n", syscons_version >> 8, + syscons_version & 0xFF); + } + else + { + ErrorF(" (version 0.x)\n"); + } + ErrorF("(using VT number %d)\n\n", xf86Info.vtno); + } + } + else + { + /* VT_GETMODE failed, probably not syscons */ + close(fd); + fd = -1; + } + } + return fd; +} + +#endif /* SYSCONS_SUPPORT */ + + +#ifdef CODRV_SUPPORT + +static int +xf86OpenCodrv() +{ + int fd = -1, onoff = X_MODE_OFF; + struct oldconsinfo ci; + + if ((fd = open(CODRV_CONSOLE_DEV, CODRV_CONSOLE_MODE, 0)) >= 0) + { + if (ioctl(fd, CONSOLE_X_MODE, &onoff) < 0) + { + FatalError("%s: CONSOLE_X_MODE on %s failed (%s)\n%s\n%s\n", + "xf86OpenCodrv", + CODRV_CONSOLE_DEV, strerror(errno), + "Was expecting codrv driver", + CHECK_DRIVER_MSG); + } + xf86Info.consType = CODRV011; + } + else + { + if (errno == EBUSY) + { + FatalError("xf86OpenCodrv: %s is already in use (codrv)\n", + CODRV_CONSOLE_DEV); + } + } + else + { + fd = -1; + } + + if(fd >= 0) + { + /* + * analyse whether this kernel has sufficient capabilities for + * this xserver, if not don't proceed: it won't work. Also + * find out which codrv version. + */ +#define NECESSARY (CONS_HASKBD|CONS_HASKEYNUM|CONS_HASPX386) + if ((ioctl(fd, OLDCONSGINFO, &ci) < 0 || + (ci.info1 & NECESSARY) != NECESSARY)) + { + FatalError("xf86OpenCodrv: %s\n%s\n%s\n", + "This Xserver has detected the codrv driver, but your", + "kernel doesn't appear to have the required facilities", + CHECK_DRIVER_MSG); + } + /* Check for codrv 0.1.2 or later */ + if (ci.info1 & CONS_CODRV2) + { + xf86Info.consType = CODRV01X; + if (xf86Verbose) + { + ErrorF("Using codrv 0.1.2 (or later)\n"); + } + } + else + { + if (xf86Verbose) + { + ErrorF("Using codrv 0.1.1\n"); + } + } +#undef NECESSARY + } + + return fd; +} +#endif /* CODRV_SUPPORT */ + +#ifdef PCVT_SUPPORT + +static int +xf86OpenPcvt() +{ + /* This looks much like syscons, since pcvt is API compatible */ + int fd = -1; + vtmode_t vtmode; + char vtname[12]; + struct stat status; + struct pcvtid pcvt_version; + + if ((fd = open(PCVT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0)) >= 0) + { + if (ioctl(fd, VGAPCVTID, &pcvt_version) >= 0) + { + if(ioctl(fd, VT_GETMODE, &vtmode) < 0) + { + FatalError("%s: VT_GETMODE failed\n%s%s\n%s\n", + "xf86OpenPcvt", + "Found pcvt driver but X11 seems to be", + " not supported.", CHECK_DRIVER_MSG); + } + + xf86Info.vtno = VTnum; + + if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0) + initialVT = -1; + + if (xf86Info.vtno == -1) + { + if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) + { + /* No free VTs */ + xf86Info.vtno = -1; + } + + if (xf86Info.vtno == -1) + { + /* + * All VTs are in use. If initialVT was found, use it. + * Otherwise, if stdin is a VT, use that one. + */ + if (initialVT != -1) + { + xf86Info.vtno = initialVT; + } + else if ((fstat(0, &status) >= 0) + && S_ISCHR(status.st_mode) + && (ioctl(0, VT_GETMODE, &vtmode) >= 0)) + { + /* stdin is a VT */ + xf86Info.vtno = minor(status.st_rdev) + 1; + } + else + { + FatalError("%s: Cannot find a free VT\n", + "xf86OpenPcvt"); + } + } + } + + close(fd); +#ifndef __OpenBSD__ + sprintf(vtname, "/dev/ttyv%01x", xf86Info.vtno - 1); +#else + sprintf(vtname, "/dev/ttyC%01x", xf86Info.vtno - 1); +#endif + if ((fd = open(vtname, PCVT_CONSOLE_MODE, 0)) < 0) + { + FatalError("xf86OpenPcvt: Cannot open %s (%s)\n", + vtname, strerror(errno)); + } + if (ioctl(fd, VT_GETMODE, &vtmode) < 0) + { + FatalError("xf86OpenPcvt: VT_GETMODE failed\n"); + } + xf86Info.consType = PCVT; + if (xf86Verbose) + { + ErrorF("Using pcvt driver (version %d.%d)\n", + pcvt_version.rmajor, pcvt_version.rminor); + } + } + else + { + /* Not pcvt */ + close(fd); + fd = -1; + } + } + return fd; +} + +#endif /* PCVT_SUPPORT */ + + +void +xf86CloseConsole() +{ +#if defined(CODRV_SUPPORT) + int onoff; +#endif +#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + struct vt_mode VT; +#endif + + switch (xf86Info.consType) + { +#ifdef CODRV_SUPPORT + case CODRV011: + case CODRV01X: + onoff = X_MODE_OFF; + if (xf86Info.consType == CODRV01X) + { + ioctl (xf86Info.consoleFd, VGAGIVECTRL, 0); + } + ioctl (xf86Info.consoleFd, CONSOLE_X_MODE, &onoff); + break; +#endif /* CODRV_SUPPORT */ +#ifdef PCCONS_SUPPORT + case PCCONS: + ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_OFF, 0); + break; +#endif /* PCCONS_SUPPORT */ +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode */ + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) + { + VT.mode = VT_AUTO; + ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* dflt vt handling */ + } + if (ioctl(xf86Info.consoleFd, KDDISABIO, 0) < 0) + { + xf86FatalError("xf86CloseConsole: KDDISABIO failed (%s)\n", + strerror(errno)); + } + if (initialVT != -1) + ioctl(xf86Info.consoleFd, VT_ACTIVATE, initialVT); + break; +#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ + } + + if (xf86Info.screenFd != xf86Info.consoleFd) + { + close(xf86Info.screenFd); + close(xf86Info.consoleFd); + if ((xf86Info.consoleFd = open("/dev/console",O_RDONLY,0)) <0) + { + xf86FatalError("xf86CloseConsole: Cannot open /dev/console (%s)\n", + strerror(errno)); + } + } + close(xf86Info.consoleFd); + if (devConsoleFd >= 0) + close(devConsoleFd); + return; +} + +int +xf86ProcessArgument (argc, argv, i) +int argc; +char *argv[]; +int i; +{ + /* + * Keep server from detaching from controlling tty. This is useful + * when debugging (so the server can receive keyboard signals. + */ + if (!strcmp(argv[i], "-keeptty")) + { + KeepTty = TRUE; + return(1); + } +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + if ((argv[i][0] == 'v') && (argv[i][1] == 't')) + { + if (sscanf(argv[i], "vt%2d", &VTnum) == 0 || + VTnum < 1 || VTnum > 12) + { + UseMsg(); + VTnum = -1; + return(0); + } + return(1); + } +#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ + return(0); +} + +void +xf86UseMsg() +{ +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + ErrorF("vtXX use the specified VT number (1-12)\n"); +#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ + ErrorF("-keeptty "); + ErrorF("don't detach controlling tty (for debugging only)\n"); + return; +} diff --git a/hw/xfree86/os-support/bsd/bsd_io.c b/hw/xfree86/os-support/bsd/bsd_io.c new file mode 100644 index 000000000..6741ba978 --- /dev/null +++ b/hw/xfree86/os-support/bsd/bsd_io.c @@ -0,0 +1,257 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/bsd_io.c,v 3.12 1996/12/23 06:49:37 dawes Exp $ */ +/* + * Copyright 1992 by Rich Murphey + * Copyright 1993 by David Dawes + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Rich Murphey and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Rich Murphey and + * David Dawes make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * RICH MURPHEY AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID DAWES 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. + * + */ +/* $Xorg: bsd_io.c,v 1.3 2000/08/17 19:51:21 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +void xf86SoundKbdBell(loudness, pitch, duration) +int loudness; +int pitch; +int duration; +{ + if (loudness && pitch) + { +#ifdef CODRV_SUPPORT + struct kbd_sound s; +#endif +#ifdef PCCONS_SUPPORT + int data[2]; +#endif + + switch (xf86Info.consType) { + +#ifdef PCCONS_SUPPORT + case PCCONS: + data[0] = pitch; + data[1] = (duration * loudness) / 50; + ioctl(xf86Info.consoleFd, CONSOLE_X_BELL, data); + break; +#endif +#ifdef CODRV_SUPPORT + case CODRV011: + case CODRV01X: + s.pitch = pitch; + s.duration = (duration * loudness) / 50; + ioctl(xf86Info.consoleFd, KBDSETBELL, &s); + break; +#endif +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + ioctl(xf86Info.consoleFd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration*loudness/50)<<16)); + break; +#endif + } + } +} + +void xf86SetKbdLeds(leds) +int leds; +{ + switch (xf86Info.consType) { + + case PCCONS: + break; +#ifdef CODRV_SUPPORT + case CODRV011: + case CODRV01X: + leds = (leds&0x01)<<2 | leds&0x02 | (leds&0x04)>>2; + ioctl(xf86Info.consoleFd, KBDSLEDS, &leds); + break; +#endif +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + ioctl(xf86Info.consoleFd, KDSETLED, leds); + break; +#endif + } +} + +int xf86GetKbdLeds() +{ + int leds = 0; + + switch (xf86Info.consType) { + + case PCCONS: + break; +#ifdef CODRV_SUPPORT + case CODRV011: + case CODRV01X: + ioctl(xf86Info.consoleFd, KBDGLEDS, &leds); + leds = (leds&0x01)<<2 | leds&0x02 | (leds&0x04)>>2; + break; +#endif +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + ioctl(xf86Info.consoleFd, KDGETLED, &leds); + break; +#endif + } + return(leds); +} + +#if NeedFunctionPrototypes +void xf86SetKbdRepeat(char rad) +#else +void xf86SetKbdRepeat(rad) +char rad; +#endif +{ + switch (xf86Info.consType) { + + case PCCONS: + break; +#ifdef CODRV_SUPPORT + case CODRV011: + case CODRV01X: + ioctl(xf86Info.consoleFd, KBDSTPMAT, &rad); + break; +#endif +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + ioctl(xf86Info.consoleFd, KDSETRAD, rad); + break; +#endif + } +} + +static struct termio kbdtty; + +void xf86KbdInit() +{ + switch (xf86Info.consType) { + + case CODRV011: + case CODRV01X: + break; +#if defined(PCCONS_SUPPORT) || defined(SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case PCCONS: + case SYSCONS: + case PCVT: + tcgetattr(xf86Info.consoleFd, &kbdtty); + break; +#endif + } +} + +int xf86KbdOn() +{ + struct termios nTty; + + switch (xf86Info.consType) { + + case CODRV011: + case CODRV01X: + break; + +#if defined(SYSCONS_SUPPORT) || defined(PCCONS_SUPPORT) || defined(PCVT_SUPPORT) + case SYSCONS: + case PCCONS: + case PCVT: + nTty = kbdtty; + nTty.c_iflag = IGNPAR | IGNBRK; + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; + nTty.c_cc[VTIME] = 0; + nTty.c_cc[VMIN] = 1; + cfsetispeed(&nTty, 9600); + cfsetospeed(&nTty, 9600); + tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty); + +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW); +#endif + break; +#endif + } + return(xf86Info.consoleFd); +} + +int xf86KbdOff() +{ + switch (xf86Info.consType) { + + case CODRV011: + case CODRV01X: + break; + +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + ioctl(xf86Info.consoleFd, KDSKBMODE, K_XLATE); + /* FALL THROUGH */ +#endif +#if defined(SYSCONS_SUPPORT) || defined(PCCONS_SUPPORT) || defined(PCVT_SUPPORT) + case PCCONS: + tcsetattr(xf86Info.consoleFd, TCSANOW, &kbdtty); + break; +#endif + } + return(xf86Info.consoleFd); +} + +void xf86MouseInit(mouse) +MouseDevPtr mouse; +{ + return; +} + +int xf86MouseOn(mouse) +MouseDevPtr mouse; +{ + if ((mouse->mseFd = open(mouse->mseDevice, O_RDWR | O_NDELAY)) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Cannot open mouse (%s) - Continuing...\n", + strerror(errno)); + return(-2); + } + FatalError("Cannot open mouse (%s)\n", strerror(errno)); + } + + xf86SetupMouse(mouse); + + /* Flush any pending input */ + tcflush(mouse->mseFd, TCIFLUSH); + + return(mouse->mseFd); +} diff --git a/hw/xfree86/os-support/bsd/bsd_jstk.c b/hw/xfree86/os-support/bsd/bsd_jstk.c new file mode 100644 index 000000000..ab4a31420 --- /dev/null +++ b/hw/xfree86/os-support/bsd/bsd_jstk.c @@ -0,0 +1,180 @@ +/* + * Copyright 1995 by Frederic Lepied, France. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ + +/* Modified for FreeBSD by David Dawes */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/bsd_jstk.c,v 3.2 1996/01/12 14:34:41 dawes Exp $ */ + +#include +#include +#include +#include +#include + +#define JS_RETURN sizeof(struct joystick) + +extern int errno; +extern int xf86Verbose; + +/*********************************************************************** + * + * xf86JoystickOn -- + * + * open the device and init timeout according to the device value. + * + *********************************************************************** + */ + +int +xf86JoystickOn(char * name, int *timeout, int *centerX, int *centerY) +{ + int status; + int changed = 0; + int timeinmicros; + struct joystick js; + +#ifdef DEBUG + ErrorF("xf86JoystickOn: %s\n", name); +#endif + + if ((status = open(name, O_RDWR | O_NDELAY)) < 0) + { + ErrorF("xf86JoystickOn: Cannot open joystick '%s' (%s)\n", name, + strerror(errno)); + return -1; + } + + if (*timeout <= 0) { + /* Use the current setting */ + ioctl(status, JOY_GETTIMEOUT, &timeinmicros); + *timeout = timeinmicros / 1000; + if (*timeout == 0) + *timeout = 1; + changed = 1; + } + /* Maximum allowed timeout in the FreeBSD driver is 10ms */ + if (*timeout > 10) { + *timeout = 10; + changed = 1; + } + + if (changed && xf86Verbose) + ErrorF("(--) Joystick: timeout value = %d\n", *timeout); + + timeinmicros = *timeout * 1000; + + /* Assume the joystick is centred when this is called */ + read(status, &js, JS_RETURN); + if (*centerX < 0) { + *centerX = js.x; + if (xf86Verbose) { + ErrorF("(--) Joystick: CenterX set to %d\n", *centerX); + } + } + if (*centerY < 0) { + *centerY = js.y; + if (xf86Verbose) { + ErrorF("(--) Joystick: CenterY set to %d\n", *centerY); + } + } + + return status; +} + +/*********************************************************************** + * + * xf86JoystickInit -- + * + * called when X device is initialized. + * + *********************************************************************** + */ + +void +xf86JoystickInit() +{ + return; +} + +/*********************************************************************** + * + * xf86JoystickOff -- + * + * close the handle. + * + *********************************************************************** + */ + +int +xf86JoystickOff(fd, doclose) +int *fd; +int doclose; +{ + int oldfd; + + if (((oldfd = *fd) >= 0) && doclose) { + close(*fd); + *fd = -1; + } + return oldfd; +} + +/*********************************************************************** + * + * xf86JoystickGetState -- + * + * return the state of buttons and the position of the joystick. + * + *********************************************************************** + */ + +int +xf86JoystickGetState(fd, x, y, buttons) +int fd; +int *x; +int *y; +int *buttons; +{ + struct joystick js; + int status; + + status = read(fd, &js, JS_RETURN); + + if (status != JS_RETURN) + { + Error("Joystick read"); + return 0; + } + + *x = js.x; + *y = js.y; + *buttons = js.b1 | (js.b2 << 1); +#ifdef DEBUG + ErrorF("xf86JoystickGetState: x = %d, y = %d, buttons = %d\n", *x, *y, + *buttons); +#endif + + return 1; +} + +/* end of bsd_jstk.c */ diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c new file mode 100644 index 000000000..1c0791abb --- /dev/null +++ b/hw/xfree86/os-support/linux/lnx_init.c @@ -0,0 +1,274 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c,v 3.7.2.3 1998/02/06 22:36:51 hohndel Exp $ */ +/* + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Orest Zborowski and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT 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. + * + */ +/* $Xorg: lnx_init.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +#ifdef USE_DEV_FB +extern char *getenv(const char *); +#include +char *fb_dev_name; +#endif + +static Bool KeepTty = FALSE; +static int VTnum = -1; +static int activeVT = -1; + +extern void xf86VTRequest( +#if NeedFunctionPrototypes + int +#endif +); + +void xf86OpenConsole() +{ + int i, fd; + struct vt_mode VT; + char vtname[11]; + struct vt_stat vts; +#ifdef USE_DEV_FB + struct fb_var_screeninfo var; + int fbfd; +#endif + + if (serverGeneration == 1) + { + /* check if we're run with euid==0 */ + if (geteuid() != 0) + { + FatalError("xf86OpenConsole: Server must be running with root " + "permissions\n" + "You should be using Xwrapper to start the server or xdm.\n" + "We strongly advise against making the server SUID root!\n"); + } + + /* + * setup the virtual terminal manager + */ + if (VTnum != -1) + { + xf86Info.vtno = VTnum; + } + else + { + if ((fd = open("/dev/tty0",O_WRONLY,0)) < 0) + { + FatalError( + "xf86OpenConsole: Cannot open /dev/tty0 (%s)\n", + strerror(errno)); + } + if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) || + (xf86Info.vtno == -1)) + { + FatalError("xf86OpenConsole: Cannot find a free VT\n"); + } + close(fd); + } + +#ifdef USE_DEV_FB + fb_dev_name=getenv("FRAMEBUFFER"); + if (!fb_dev_name) + fb_dev_name="/dev/fb0current"; + if ((fbfd = open(fb_dev_name, O_RDONLY)) < 0) + FatalError("xf86OpenConsole: Cannot open %s (%s)\n", + fb_dev_name, strerror(errno)); + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &var)) + FatalError("xf86OpenConsole: Unable to get screen info\n"); +#endif + ErrorF("(using VT number %d)\n\n", xf86Info.vtno); + + sprintf(vtname,"/dev/tty%d",xf86Info.vtno); /* /dev/tty1-64 */ + + xf86Config(FALSE); /* Read XF86Config */ + + if (!KeepTty) + { + setpgrp(); + } + + if ((xf86Info.consoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0) + { + FatalError("xf86OpenConsole: Cannot open %s (%s)\n", + vtname, strerror(errno)); + } + + /* change ownership of the vt */ + chown(vtname, getuid(), getgid()); + + /* + * the current VT device we're running on is not "console", we want + * to grab all consoles too + * + * Why is this needed? + */ + chown("/dev/tty0", getuid(), getgid()); + + /* + * Linux doesn't switch to an active vt after the last close of a vt, + * so we do this ourselves by remembering which is active now. + */ + if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts) == 0) + { + activeVT = vts.v_active; + } + + if (!KeepTty) + { + /* + * Detach from the controlling tty to avoid char loss + */ + if ((i = open("/dev/tty",O_RDWR)) >= 0) + { + ioctl(i, TIOCNOTTY, 0); + close(i); + } + } + + /* + * now get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_WAITACTIVE failed\n"); + } + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) + { + FatalError ("xf86OpenConsole: VT_GETMODE failed\n"); + } + + signal(SIGUSR1, xf86VTRequest); + + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0) + { + FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n"); + } + if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) + { + FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n"); + } +#ifdef USE_DEV_FB + /* copy info to new console */ + var.yoffset=0; + var.xoffset=0; + if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &var)) + FatalError("Unable to set screen info\n"); + close(fbfd); +#endif + } + else + { + /* serverGeneration != 1 */ + /* + * now get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_WAITACTIVE failed\n"); + } + } + return; +} + +void xf86CloseConsole() +{ + struct vt_mode VT; + +#if 0 + ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno); + ioctl(xf86Info.consoleFd, VT_WAITACTIVE, 0); +#endif + ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */ + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) + { + VT.mode = VT_AUTO; + ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */ + } + /* + * Perform a switch back to the active VT when we were started + */ + if (activeVT >= 0) + { + ioctl(xf86Info.consoleFd, VT_ACTIVATE, activeVT); + activeVT = -1; + } + close(xf86Info.consoleFd); /* make the vt-manager happy */ + return; +} + +int xf86ProcessArgument (argc, argv, i) +int argc; +char *argv[]; +int i; +{ + /* + * Keep server from detaching from controlling tty. This is useful + * when debugging (so the server can receive keyboard signals. + */ + if (!strcmp(argv[i], "-keeptty")) + { + KeepTty = TRUE; + return(1); + } + if ((argv[i][0] == 'v') && (argv[i][1] == 't')) + { + if (sscanf(argv[i], "vt%2d", &VTnum) == 0) + { + UseMsg(); + VTnum = -1; + return(0); + } + return(1); + } + return(0); +} + +void xf86UseMsg() +{ + ErrorF("vtXX use the specified VT number\n"); + ErrorF("-keeptty "); + ErrorF("don't detach controlling tty (for debugging only)\n"); + return; +} diff --git a/hw/xfree86/os-support/linux/lnx_io.c b/hw/xfree86/os-support/linux/lnx_io.c new file mode 100644 index 000000000..57a2979c5 --- /dev/null +++ b/hw/xfree86/os-support/linux/lnx_io.c @@ -0,0 +1,136 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c,v 3.3 1996/12/23 06:50:01 dawes Exp $ */ +/* + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Dawes + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Orest Zborowski and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Dawes make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OREST ZBOROWSKI AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES 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. + * + */ +/* $Xorg: lnx_io.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +void xf86SoundKbdBell(loudness, pitch, duration) +int loudness; +int pitch; +int duration; +{ + if (loudness && pitch) + { + ioctl(xf86Info.consoleFd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration * + loudness / 50) << 16)); + } +} + +void xf86SetKbdLeds(leds) +int leds; +{ + ioctl(xf86Info.consoleFd, KDSETLED, leds); +} + +int xf86GetKbdLeds() +{ + int leds; + + ioctl(xf86Info.consoleFd, KDGETLED, &leds); + return(leds); +} + +#if NeedFunctionPrototypes +void xf86SetKbdRepeat(char rad) +#else +void xf86SetKbdRepeat(rad) +char rad; +#endif +{ + return; +} + +static int kbdtrans; +static struct termios kbdtty; + +void xf86KbdInit() +{ + ioctl (xf86Info.consoleFd, KDGKBMODE, &kbdtrans); + tcgetattr (xf86Info.consoleFd, &kbdtty); +} + +int xf86KbdOn() +{ + struct termios nTty; + + ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW); + nTty = kbdtty; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; + nTty.c_cc[VTIME]=0; + nTty.c_cc[VMIN]=1; + cfsetispeed(&nTty, 9600); + cfsetospeed(&nTty, 9600); + tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty); + return(xf86Info.consoleFd); +} + +int xf86KbdOff() +{ + ioctl(xf86Info.consoleFd, KDSKBMODE, kbdtrans); + tcsetattr(xf86Info.consoleFd, TCSANOW, &kbdtty); + return(xf86Info.consoleFd); +} + +void xf86MouseInit(mouse) +MouseDevPtr mouse; +{ + return; +} + +int xf86MouseOn(mouse) +MouseDevPtr mouse; +{ + if ((mouse->mseFd = open(mouse->mseDevice, O_RDWR | O_NDELAY)) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Cannot open mouse (%s) - Continuing...\n", + strerror(errno)); + return(-2); + } + FatalError("Cannot open mouse (%s)\n", strerror(errno)); + } + + xf86SetupMouse(mouse); + + /* Flush any pending input */ + tcflush(mouse->mseFd, TCIFLUSH); + + return(mouse->mseFd); +} diff --git a/hw/xfree86/os-support/linux/lnx_jstk.c b/hw/xfree86/os-support/linux/lnx_jstk.c new file mode 100644 index 000000000..ea308c159 --- /dev/null +++ b/hw/xfree86/os-support/linux/lnx_jstk.c @@ -0,0 +1,173 @@ +/* $Xorg: lnx_jstk.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ +/* Id: lnx_jstk.c,v 1.1 1995/12/20 14:06:09 lepied Exp */ +/* + * Copyright 1995 by Frederic Lepied, France. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_jstk.c,v 3.6 1996/12/23 06:50:02 dawes Exp $ */ + +static const char rcs_id[] = "$Xorg: lnx_jstk.c,v 1.1 1995/12/20 14:06:09 lepied Exp"; + +#include +#include +#include +#define inline __inline__ +#include +#include +#include + +extern int errno; + +/*********************************************************************** + * + * xf86JoystickOn -- + * + * open the device and init timeout according to the device value. + * + *********************************************************************** + */ + +int +xf86JoystickOn(char *name, int *timeout, int *centerX, int *centerY) +{ + int fd; + struct JS_DATA_TYPE js; + extern int xf86Verbose; + +#ifdef DEBUG + ErrorF("xf86JoystickOn %s\n", name); +#endif + + if ((fd = open(name, O_RDWR | O_NDELAY)) < 0) + { + ErrorF("Cannot open joystick '%s' (%s)\n", name, + strerror(errno)); + return -1; + } + + if (*timeout == 0) { + if (ioctl (fd, JS_GET_TIMELIMIT, timeout) == -1) { + Error("joystick JS_GET_TIMELIMIT ioctl"); + } + else { + if (xf86Verbose) { + ErrorF("(--) Joystick: timeout value = %d\n", *timeout); + } + } + } + else { + if (ioctl(fd, JS_SET_TIMELIMIT, timeout) == -1) { + Error("joystick JS_SET_TIMELIMIT ioctl"); + } + } + + /* Assume the joystick is centred when this is called */ + read(fd, &js, JS_RETURN); + if (*centerX < 0) { + *centerX = js.x; + if (xf86Verbose) { + ErrorF("(--) Joystick: CenterX set to %d\n", *centerX); + } + } + if (*centerY < 0) { + *centerY = js.y; + if (xf86Verbose) { + ErrorF("(--) Joystick: CenterY set to %d\n", *centerY); + } + } + + return fd; +} + +/*********************************************************************** + * + * xf86JoystickInit -- + * + * called when X device is initialized. + * + *********************************************************************** + */ + +void +xf86JoystickInit() +{ + return; +} + +/*********************************************************************** + * + * xf86JoystickOff -- + * + * close the handle. + * + *********************************************************************** + */ + +int +xf86JoystickOff(fd, doclose) +int *fd; +int doclose; +{ + int oldfd; + + if (((oldfd = *fd) >= 0) && doclose) { + close(*fd); + *fd = -1; + } + return oldfd; +} + +/*********************************************************************** + * + * xf86JoystickGetState -- + * + * return the state of buttons and the position of the joystick. + * + *********************************************************************** + */ + +int +xf86JoystickGetState(fd, x, y, buttons) +int fd; +int *x; +int *y; +int *buttons; +{ + struct JS_DATA_TYPE js; + int status; + + status = read(fd, &js, JS_RETURN); + + if (status != JS_RETURN) + { + Error("Joystick read"); + return 0; + } + + *x = js.x; + *y = js.y; + *buttons = js.buttons; + + return 1; +} + +/* end of lnx_jstk.c */ diff --git a/hw/xfree86/os-support/linux/lnx_video.c b/hw/xfree86/os-support/linux/lnx_video.c new file mode 100644 index 000000000..a29db8251 --- /dev/null +++ b/hw/xfree86/os-support/linux/lnx_video.c @@ -0,0 +1,634 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_video.c,v 3.13.2.1 1997/05/11 05:04:25 dawes Exp $ */ +/* + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Orest Zborowski and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT 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. + * + */ +/* $Xorg: lnx_video.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#ifdef __alpha__ + +/* + * The Jensen lacks dense memory, thus we have to address the bus via + * the sparse addressing scheme. + * + * Martin Ostermann (ost@comnets.rwth-aachen.de) - Apr.-Sep. 1996 + */ + +#ifdef TEST_JENSEN_CODE /* define to test the Sparse addressing on a non-Jensen */ +#define SPARSE (5) +#define isJensen (1) +#else +#define isJensen (!_bus_base()) +#define SPARSE (7) +#endif + +#define BUS_BASE (isJensen ? _bus_base_sparse() : _bus_base()) +#define JENSEN_SHIFT(x) (isJensen ? ((long)x< 0x3FF) + ExtendedPorts[ScreenNum] = TRUE; + } + NumEnabledPorts[ScreenNum] += NumPorts; +} + +void xf86EnableIOPorts(ScreenNum) +int ScreenNum; +{ + int i; + + if (ScreenEnabled[ScreenNum]) + return; + + for (i = 0; i < MAXSCREENS; i++) + { + if (ExtendedPorts[i] && (ScreenEnabled[i] || i == ScreenNum)) + { +#ifndef __mc68000__ + if (iopl(3)) + { + FatalError("%s: Failed to set IOPL for extended I/O\n", + "xf86EnableIOPorts"); + } +#endif + ExtendedEnabled = TRUE; + break; + } + } + /* Extended I/O was used, but not any more */ + if (ExtendedEnabled && i == MAXSCREENS) + { +#ifndef __mc68000__ + iopl(0); +#endif + ExtendedEnabled = FALSE; + } + /* + * Turn on non-extended ports even when using extended I/O + * so they are there if extended I/O gets turned off when it's no + * longer needed. + */ + for (i = 0; i < NumEnabledPorts[ScreenNum]; i++) + { + unsigned port = EnabledPorts[ScreenNum][i]; + + if (port > 0x3FF) + continue; + + if (xf86CheckPorts(port, EnabledPorts, NumEnabledPorts, + ScreenEnabled, MAXSCREENS)) + { + if (ioperm(port, 1, TRUE) < 0) + { + FatalError("%s: Failed to enable I/O port 0x%x (%s)\n", + "xf86EnableIOPorts", port, strerror(errno)); + } + } + } + ScreenEnabled[ScreenNum] = TRUE; + return; +} + +void xf86DisableIOPorts(ScreenNum) +int ScreenNum; +{ + int i; + + if (!ScreenEnabled[ScreenNum]) + return; + + ScreenEnabled[ScreenNum] = FALSE; + for (i = 0; i < MAXSCREENS; i++) + { + if (ScreenEnabled[i] && ExtendedPorts[i]) + break; + } + if (ExtendedEnabled && i == MAXSCREENS) + { +#ifndef __mc68000__ + iopl(0); +#endif + ExtendedEnabled = FALSE; + } + for (i = 0; i < NumEnabledPorts[ScreenNum]; i++) + { + unsigned port = EnabledPorts[ScreenNum][i]; + + if (port > 0x3FF) + continue; + + if (xf86CheckPorts(port, EnabledPorts, NumEnabledPorts, + ScreenEnabled, MAXSCREENS)) + { + ioperm(port, 1, FALSE); + } + } + return; +} + +#endif /* ALWAYS_USE_EXTENDED */ + +void xf86DisableIOPrivs() +{ +#ifndef __mc68000__ + if (ExtendedEnabled) + iopl(0); +#endif + return; +} + +/***************************************************************************/ +/* Interrupt Handling section */ +/***************************************************************************/ + +Bool xf86DisableInterrupts() +{ + if (!ExtendedEnabled) +#ifndef __mc68000__ + if (iopl(3)) + return (FALSE); +#endif +#if defined(__alpha__) || defined(__mc68000__) +#else +#ifdef __GNUC__ + __asm__ __volatile__("cli"); +#else + asm("cli"); +#endif +#endif +#ifndef __mc68000__ + if (!ExtendedEnabled) + iopl(0); +#endif + return (TRUE); +} + +void xf86EnableInterrupts() +{ + if (!ExtendedEnabled) +#ifndef __mc68000__ + if (iopl(3)) + return; +#endif +#if defined(__alpha__) || defined(__mc68000__) +#else +#ifdef __GNUC__ + __asm__ __volatile__("sti"); +#else + asm("sti"); +#endif +#endif +#ifndef __mc68000__ + if (!ExtendedEnabled) + iopl(0); +#endif + return; +} + +#if defined(__alpha__) + +static int xf86SparseShift = 5; /* default to all but JENSEN */ + +pointer xf86MapVidMemSparse(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ + pointer base; + int fd; + + if (!_bus_base()) xf86SparseShift = 7; /* Uh, oh, JENSEN... */ + + Size <<= xf86SparseShift; + Base = (pointer)((unsigned long)Base << xf86SparseShift); + + if ((fd = open("/dev/mem", O_RDWR)) < 0) + { + FatalError("xf86MapVidMem: failed to open /dev/mem (%s)\n", + strerror(errno)); + } + /* This requirers linux-0.99.pl10 or above */ + base = (pointer)mmap((caddr_t)0, Size, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, + (off_t)Base + _bus_base_sparse()); + close(fd); + if ((long)base == -1) + { + FatalError("xf86MapVidMem: Could not mmap framebuffer (%s)\n", + strerror(errno)); + } + return base; +} + +void xf86UnMapVidMemSparse(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ + Size <<= xf86SparseShift; + + munmap((caddr_t)Base, Size); +} + +#define vuip volatile unsigned int * + +extern void sethae(unsigned long hae); + +int xf86ReadSparse8(Base, Offset) +pointer Base; +unsigned long Offset; +{ + unsigned long result, shift; + unsigned long msb = 0; + + shift = (Offset & 0x3) * 8; + if (xf86SparseShift != 7) { /* if not JENSEN, we may need HAE */ + if (Offset >= (1UL << 24)) { + msb = Offset & 0xf8000000UL; + Offset -= msb; + if (msb) { + sethae(msb); + } + } + } + result = *(vuip) ((unsigned long)Base + (Offset << xf86SparseShift)); + if (msb) + sethae(0); + result >>= shift; + return 0xffUL & result; +} + +int xf86ReadSparse16(Base, Offset) +pointer Base; +unsigned long Offset; +{ + unsigned long result, shift; + unsigned long msb = 0; + + shift = (Offset & 0x2) * 8; + if (xf86SparseShift != 7) { /* if not JENSEN, we may need HAE */ + if (Offset >= (1UL << 24)) { + msb = Offset & 0xf8000000UL; + Offset -= msb; + if (msb) { + sethae(msb); + } + } + } + result = *(vuip)((unsigned long)Base+(Offset<>= shift; + return 0xffffUL & result; +} + +int xf86ReadSparse32(Base, Offset) +pointer Base; +unsigned long Offset; +{ + unsigned long result; + unsigned long msb = 0; + + if (xf86SparseShift != 7) { /* if not JENSEN, we may need HAE */ + if (Offset >= (1UL << 24)) { + msb = Offset & 0xf8000000UL; + Offset -= msb; + if (msb) { + sethae(msb); + } + } + } + result = *(vuip)((unsigned long)Base+(Offset<= (1UL << 24)) { + msb = Offset & 0xf8000000; + Offset -= msb; + if (msb) { + sethae(msb); + } + } + } + *(vuip) ((unsigned long)Base + (Offset << xf86SparseShift)) = b * 0x01010101; + if (msb) + sethae(0); +} + +void xf86WriteSparse16(Value, Base, Offset) +int Value; +pointer Base; +unsigned long Offset; +{ + unsigned long msb = 0; + unsigned int w = Value & 0xffffU; + + if (xf86SparseShift != 7) { /* not JENSEN */ + if (Offset >= (1UL << 24)) { + msb = Offset & 0xf8000000; + Offset -= msb; + if (msb) { + sethae(msb); + } + } + } + *(vuip)((unsigned long)Base+(Offset<= (1UL << 24)) { + msb = Offset & 0xf8000000; + Offset -= msb; + if (msb) { + sethae(msb); + } + } + } + *(vuip)((unsigned long)Base+(Offset<mseFd = open(mouse->mseDevice, O_RDWR | O_NDELAY)) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Cannot open mouse (%s) - Continuing...\n", + strerror(errno)); + return(-2); + } + FatalError("Cannot open mouse (%s)\n", strerror(errno)); + } + + /* assert DTR */ + ioctl(mouse->mseFd, TIOCSDTR, NULL); + + xf86SetupMouse(mouse); + + return(mouse->mseFd); +} diff --git a/hw/xfree86/os-support/lynxos/lynx_mmap.c b/hw/xfree86/os-support/lynxos/lynx_mmap.c new file mode 100644 index 000000000..621f42c5d --- /dev/null +++ b/hw/xfree86/os-support/lynxos/lynx_mmap.c @@ -0,0 +1,66 @@ +/* + * Copyright 1993 by Thomas Mueller + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Mueller not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Mueller makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS MUELLER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS MUELLER 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. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_mmap.c,v 3.2 1996/09/29 13:38:29 dawes Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +/* + * Read BIOS using smem_create facility + */ + +int xf86ReadBIOS(Base, Offset, Buf, Len) +unsigned long Base; +unsigned long Offset; +unsigned char *Buf; +int Len; +{ + char *p; + int mlen; + + mlen = (Offset + Len + 4095) & ~4096; + p = smem_create("BIOS-probe", (char *)Base, mlen, SM_READ); + if (p == NULL) + { + /* check if there is a stale segment around */ + if (smem_remove("BIOS-probe") == 0) { + ErrorF("xf86ReadBios: removed stale smem_ segment\n"); + p = smem_create("BIOS-probe", (char *)Base, mlen, SM_READ); + } + if (p == NULL) { + ErrorF("xf86ReadBios: Failed to smem_create Base %x len %x %s \n", + Base, mlen, strerror(errno)); + return(-1); + } + } + memcpy(Buf, p + Offset, Len); + smem_create(NULL, p, 0, SM_DETACH); + smem_remove("BIOS-probe"); + return(Len); +} diff --git a/hw/xfree86/os-support/lynxos/lynx_video.c b/hw/xfree86/os-support/lynxos/lynx_video.c new file mode 100644 index 000000000..94b2f0ecd --- /dev/null +++ b/hw/xfree86/os-support/lynxos/lynx_video.c @@ -0,0 +1,167 @@ +/* + * Copyright 1993 by Thomas Mueller + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Mueller not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Mueller makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS MUELLER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS MUELLER 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. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_video.c,v 3.2.4.1 1997/05/09 07:15:24 hohndel Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +/***************************************************************************/ +/* Video Memory Mapping section */ +/***************************************************************************/ + +typedef struct +{ + char name[16]; + pointer Base; + long Size; + char *ptr; + int RefCnt; +} +_SMEMS; + +#define MAX_SMEMS 8 + +static _SMEMS smems[MAX_SMEMS]; + +static void +smemCleanup() +{ + int i; + + for (i = 0; i < MAX_SMEMS; i++) { + if (*smems[i].name && smems[i].ptr) { + (void)smem_create(NULL, smems[i].ptr, 0, SM_DETACH); + (void)smem_remove(smems[i].name); + *smems[i].name = '\0'; + smems[i].ptr = NULL; + smems[i].Base = NULL; + smems[i].Size = 0; + smems[i].RefCnt = 0; + } + } +} + +pointer xf86MapVidMem(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ + static int once; + int free_slot = -1; + int i; + + if (!once) + { + atexit(smemCleanup); + once = 1; + } + for (i = 0; i < MAX_SMEMS; i++) + { + if (!*smems[i].name && free_slot == -1) + free_slot = i; + if (smems[i].Base == Base && smems[i].Size == Size && *smems[i].name) { + smems[i].RefCnt++; + return smems[i].ptr; + } + } + if (i == MAX_SMEMS && free_slot == -1) + { + FatalError("xf86MapVidMem: failed to smem_create Base %x Size %x (out of SMEMS entries)\n", + Base, Size); + } + + i = free_slot; + sprintf(smems[i].name, "Video-%d", i); + smems[i].Base = Base; + smems[i].Size = Size; + smems[i].ptr = smem_create(smems[i].name, Base, Size, SM_READ|SM_WRITE); + smems[i].RefCnt = 1; + if (smems[i].ptr == NULL) + { + /* check if there is a stale segment around */ + if (smem_remove(smems[i].name) == 0) { + ErrorF("xf86MapVidMem: removed stale smem_ segment %s\n", + smems[i].name); + smems[i].ptr = smem_create(smems[i].name, + Base, Size, SM_READ|SM_WRITE); + } + if (smems[i].ptr == NULL) { + *smems[i].name = '\0'; + FatalError("xf86MapVidMem: failed to smem_create Base %x Size %x (%s)\n", + Base, Size, strerror(errno)); + } + } + return smems[i].ptr; +} + +void xf86UnMapVidMem(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ + int i; + + for (i = 0; i < MAX_SMEMS; i++) + { + if (*smems[i].name && smems[i].ptr == Base && smems[i].Size == Size) + { + if (--smems[i].RefCnt > 0) + return; + (void)smem_create(NULL, smems[i].ptr, 0, SM_DETACH); + (void)smem_remove(smems[i].name); + *smems[i].name = '\0'; + smems[i].RefCnt = 0; + return; + } + } + ErrorF("xf86UnMapVidMem: no SMEM found for Base = %lx Size = %lx\n", Base, Size); +} + +Bool xf86LinearVidMem() +{ + return(TRUE); +} + + +/***************************************************************************/ +/* Interrupt Handling section */ +/***************************************************************************/ + +Bool xf86DisableInterrupts() +{ + return(TRUE); +} + +void xf86EnableInterrupts() +{ + return; +} + diff --git a/hw/xfree86/os-support/misc/xf86_IlHack.c b/hw/xfree86/os-support/misc/xf86_IlHack.c new file mode 100644 index 000000000..204fe4717 --- /dev/null +++ b/hw/xfree86/os-support/misc/xf86_IlHack.c @@ -0,0 +1,14 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/misc/xf86_IlHack.c,v 3.4 1996/12/23 06:50:24 dawes Exp $ */ +/* + * This file is an incredible crock to get the normally-inline functions + * built into the server so that things can be debugged properly. + * + * Note: this doesn't work when using a compiler other than GCC. + */ +/* $Xorg: xf86_IlHack.c,v 1.3 2000/08/17 19:51:25 cpqbld Exp $ */ + + +#define static /**/ +#define __inline__ /**/ +#undef NO_INLINE +#include "compiler.h" diff --git a/hw/xfree86/os-support/misc/xf86_Util.c b/hw/xfree86/os-support/misc/xf86_Util.c new file mode 100644 index 000000000..a68d2ca89 --- /dev/null +++ b/hw/xfree86/os-support/misc/xf86_Util.c @@ -0,0 +1,126 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/misc/xf86_Util.c,v 3.4 1996/12/23 06:50:25 dawes Exp $ */ +/* + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Wexelblat not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. David Wexelblat makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL DAVID WEXELBLAT 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. + * + */ +/* $Xorg: xf86_Util.c,v 1.3 2000/08/17 19:51:26 cpqbld Exp $ */ + +/* + * This file is for utility functions that will be shared by other pieces + * of the system. Putting things here ensure that all the linking order + * dependencies are dealt with, as this library will be linked in last. + */ + +#include + +/* + * A portable hack at implementing strcasecmp() + * The characters '_', ' ', and '\t' are ignored in the comparison + */ +int StrCaseCmp(s1, s2) +const char *s1, *s2; +{ + char c1, c2; + + if (*s1 == 0) + if (*s2 == 0) + return(0); + else + return(1); + + while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') + s1++; + while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') + s2++; + c1 = (isupper(*s1) ? tolower(*s1) : *s1); + c2 = (isupper(*s2) ? tolower(*s2) : *s2); + while (c1 == c2) + { + if (c1 == '\0') + return(0); + s1++; s2++; + while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') + s1++; + while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') + s2++; + c1 = (isupper(*s1) ? tolower(*s1) : *s1); + c2 = (isupper(*s2) ? tolower(*s2) : *s2); + } + return(c1 - c2); +} + + +/* For use only with gcc */ +#ifdef __GNUC__ + +#include "os.h" + +char *debug_alloca(file, line, size) +char *file; +int line; +int size; +{ + char *ptr; + + ptr = (char *)Xalloc(size); + ErrorF("Alloc: %s line %d; ptr = 0x%x, length = %d\n", file, line, + ptr, size); + return ptr; +} + +void debug_dealloca(file, line, ptr) +char *file; +int line; +char *ptr; +{ + ErrorF("Dealloc: %s line %d; ptr = 0x%x\n", file, line, ptr); + Xfree(ptr); +} +#endif + +#if defined(ISC) || defined(Lynx) + +#include + +/* Needed for apm_driver.c */ +/* These functions are modeled after the functions inside gnu's libc */ + +static double copysign(double x, double y) +{ + x = fabs(x); + return y < 0 ? - x : x; +} + +double RInt(double x) +{ + double s,t; + const double one = 1.0; + const static double L = 4503599627370496.0E0; + + if (x!=x) + return(x); + if (copysign(x,one) >= L) + return(x); + s = copysign(L,x); + t = x + s; + return (t - s); +} +#endif diff --git a/hw/xfree86/os-support/sco/VTsw_sco.c b/hw/xfree86/os-support/sco/VTsw_sco.c new file mode 100644 index 000000000..386cd21ff --- /dev/null +++ b/hw/xfree86/os-support/sco/VTsw_sco.c @@ -0,0 +1,94 @@ +/* XFree86: $ */ +/* + * Copyright 1993 by David Wexelblat + * Copyright 1993 by David McCullough + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Wexelblat not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. David Wexelblat makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL DAVID WEXELBLAT 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. + * + */ +/* $Xorg: VTsw_sco.c,v 1.3 2000/08/17 19:51:28 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +/* + * Handle the VT-switching interface for SCO + */ + +/* + * This function is the signal handler for the VT-switching signal. It + * is only referenced inside the OS-support layer. + */ +void xf86VTRequest(sig) +int sig; +{ + signal(sig, (void(*)())xf86VTRequest); + xf86Info.vtRequestsPending = TRUE; + return; +} + +Bool xf86VTSwitchPending() +{ + return(xf86Info.vtRequestsPending ? TRUE : FALSE); +} + +Bool xf86VTSwitchAway() +{ + xf86Info.vtRequestsPending = FALSE; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0) + { + return(FALSE); + } + else + { + return(TRUE); + } +} + +Bool xf86VTSwitchTo() +{ + xf86Info.vtRequestsPending = FALSE; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) + { + return(FALSE); + } + else + { + /* + * make sure the console driver thinks the console is in + * graphics mode. Under mono we have to do the two as the + * console driver only allows valid modes for the current + * video card and Herc or vga are the only devices currently + * supported. + */ + if (ioctl(xf86Info.consoleFd, SW_VGA12, 0) < 0) + if (ioctl(xf86Info.consoleFd, SW_HGC_P0, 0) < 0) + { + ErrorF("Failed to set graphics mode : %s\n", + strerror(errno)); + } + + return(TRUE); + } +} diff --git a/hw/xfree86/os-support/sco/sco_init.c b/hw/xfree86/os-support/sco/sco_init.c new file mode 100644 index 000000000..a61dcdfce --- /dev/null +++ b/hw/xfree86/os-support/sco/sco_init.c @@ -0,0 +1,261 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_init.c,v 3.10.2.1 1998/02/06 22:36:53 hohndel Exp $ */ +/* + * Copyright 1993 by David McCullough + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 David McCullough and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. David McCullough and + * David Wexelblat makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID MCCULLOUGH AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL DAVID MCCULLOUGH OR DAVID WEXELBLAT 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. + * + */ +/* $Xorg: sco_init.c,v 1.3 2000/08/17 19:51:28 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +static Bool KeepTty = FALSE; +static int VTnum = -1; +static int sco_console_mode = -1; + +extern void xf86VTRequest( +#if NeedFunctionPrototypes + int +#endif +); + +void xf86OpenConsole() +{ + int fd,wc; + struct vt_mode VT; + struct stat status; + char vtname[11]; + + if (serverGeneration == 1) + { + /* check if we're run with euid==0 */ + if (geteuid() != 0) + { + FatalError("xf86OpenConsole: Server must be running with root " + "permissions\n" + "You should be using Xwrapper to start the server or xdm.\n" + "We strongly advise against making the server SUID root!\n"); + } + + /* + * setup the virtual terminal manager + * + * SCO vts start at tty01 which is vt00, if you could call them VT's. + * We use the numbers 1..X as it fits nicer with the device naming + * scheme. + * + * In os/osinit.c we took the precuation of not closing stdin so that + * we can use the current vt if no vt was specified on the command line + * + * Under SCO VT_OPENQRY does nothing at all + * if nothing was specified we try to determine the VT from stdin + */ + if ((VTnum != -1) && (VTnum != 0)) + { + wc = VTnum - 1; + } + else + { + if ((fstat(0, &status) >= 0) && (status.st_mode & S_IFCHR)) + { + wc = minor(status.st_rdev); + } + else + { + ErrorF("%s: Failed to stat stdin, using tty02 (%s)\n", + "xf86OpenConsole", strerror(errno)); + wc = 1; /* tty02 */ + } + } + ErrorF("(using VT number %d)\n\n", wc + 1); + + sprintf(vtname,"/dev/tty%02d", wc+1); /* /dev/tty[01-12] */ + + if ((xf86Info.consoleFd = open(vtname, O_RDWR | O_NDELAY, 0)) < 0) + { + FatalError("xf86OpenConsole: Cannot open %s (%s)\n", + vtname, strerror(errno)); + } + + /* now we can dispose of stdin */ + + if (freopen(vtname, "r+", stdin) == (FILE *) NULL) + { + FatalError("xf86OpenConsole: Cannot reopen stdin as %s (%s)\n", + vtname, strerror(errno)); + } + + /* now we can fixup stdout */ + + if (freopen(vtname, "r+", stdout) == (FILE *) NULL) + { + FatalError("xf86OpenConsole: Cannot reopen stdout as %s (%s)\n", + vtname, strerror(errno)); + } + + /* We activate the console just in case its not the one we are on */ + xf86Info.vtno = wc; + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, wc) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + + xf86Config(FALSE); /* Read XF86Config */ + + if (!KeepTty) + { + setpgrp(); + } + + /* + * now get the VT + */ + if ((sco_console_mode = ioctl(xf86Info.consoleFd, CONS_GET, 0L)) < 0) + { + FatalError("xf86OpenConsole: VT_GETMODE failed on console (%s)\n", + strerror(errno)); + } + if (ioctl(xf86Info.consoleFd, VGA_IOPRIVL, 1) < 0) + { + FatalError("xf86OpenConsole: VGA_IOPRIVL failed for VGA acc (%s)\n", + strerror(errno)); + } + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) + { + FatalError("xf86OpenConsole: VT_GETMODE failed (%s)\n", + strerror(errno)); + } + + signal(SIGUSR1, xf86VTRequest); + + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + VT.frsig = SIGUSR1; + VT.waitv = 0; + if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0) + { + FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n"); + } + /* + * make sure the console driver thinks the console is in graphics + * mode. Under mono we have to do the two as the console driver only + * allows valid modes for the current video card and Herc or vga are + * the only devices currently supported. + */ + if (ioctl(xf86Info.consoleFd, SW_VGA12, 0) < 0) + if (ioctl(xf86Info.consoleFd, SW_HGC_P0, 0) < 0) + { + ErrorF("Failed to set graphics mode (%s)\n", + strerror(errno)); + } + + } + else + { + /* serverGeneration != 1 */ + /* + * now get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + } + return; +} + +void xf86CloseConsole() +{ + struct vt_mode VT; + + ioctl(xf86Info.consoleFd, VT_RELDISP, 1); + if (sco_console_mode != -1) + { + ioctl(xf86Info.consoleFd, MODESWITCH | sco_console_mode, 0L); + } + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) + { + VT.mode = VT_AUTO; + ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */ + } + close(xf86Info.consoleFd); /* make the vt-manager happy */ + return; +} + +int xf86ProcessArgument(argc, argv, i) +int argc; +char *argv[]; +int i; +{ + /* + * Keep server from detaching from controlling tty. This is useful + * when debugging (so the server can receive keyboard signals. + */ + if (!strcmp(argv[i], "-keeptty")) + { + KeepTty = TRUE; + return(1); + } + if ((argv[i][0] == 'v') && (argv[i][1] == 't')) + { + if (sscanf(argv[i], "vt%2d", &VTnum) == 0) + { + UseMsg(); + VTnum = -1; + return(0); + } + return(1); + } + if (!strcmp(argv[i], "-crt")) + { + if ((++i > argc) || + (sscanf(argv[i], "/dev/tty%2d", &VTnum) == 0)) + { + UseMsg(); + VTnum = -1; + return(0); + } + else + { + return(2); + } + } + return(0); +} + +void xf86UseMsg() +{ + ErrorF("vtXX use the specified VT number\n"); + ErrorF("-crt /dev/ttyXX use the specified VT number\n"); + ErrorF("-keeptty "); + ErrorF("don't detach controlling tty (for debugging only)\n"); + return; +} diff --git a/hw/xfree86/os-support/sco/sco_io.c b/hw/xfree86/os-support/sco/sco_io.c new file mode 100644 index 000000000..162d1b76b --- /dev/null +++ b/hw/xfree86/os-support/sco/sco_io.c @@ -0,0 +1,117 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_io.c,v 3.3 1996/12/23 06:50:49 dawes Exp $ */ +/* + * Copyright 1993 by David McCullough + * Copyright 1993 by David Dawes + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 David McCullough and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. David McCullough + * and David Dawes makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID MCCULLOUGH AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL DAVID MCCULLOUGH OR DAVID DAWES 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. + * + */ +/* $Xorg: sco_io.c,v 1.3 2000/08/17 19:51:29 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "xf86_Config.h" + +void xf86SoundKbdBell(loudness, pitch, duration) +int loudness; +int pitch; +int duration; +{ + if (loudness && pitch) + { + ioctl(xf86Info.consoleFd, KIOCSOUND, 1193180 / pitch); + usleep(duration * loudness * 20); + ioctl(xf86Info.consoleFd, KIOCSOUND, 0); + } +} + +void xf86SetKbdLeds(leds) +int leds; +{ + /* + * sleep the first time through under SCO. There appears to be a + * timing problem in the driver which causes the keyboard to be lost. + * This sleep stops it from occurring. The sleep could proably be + * a lot shorter as even trace can fix the problem. You may + * prefer a usleep(100). + */ + static int once = 1; + + if (once) + { + sleep(1); + once = 0; + } + ioctl(xf86Info.consoleFd, KDSETLED, leds ); +} + +void xf86MouseInit(mouse) +MouseDevPtr mouse; +{ + if ((mouse->mseFd = open(mouse->mseDevice, O_RDWR | O_NDELAY)) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Cannot open mouse (%s) - Continuing...\n", + strerror(errno)); + return; + } + FatalError("Cannot open mouse (%s)\n", strerror(errno)); + } +} + +int xf86MouseOn(mouse) +MouseDevPtr mouse; +{ + xf86SetupMouse(mouse); + + /* Flush any pending input */ + ioctl(mouse->mseFd, TCFLSH, 0); + + return(mouse->mseFd); +} + +int xf86MouseOff(mouse, doclose) +MouseDevPtr mouse; +Bool doclose; +{ + if (mouse->mseFd >= 0) + { + if (mouse->mseType == P_LOGI) + { + write(mouse->mseFd, "U", 1); + xf86SetMouseSpeed(mouse, mouse->baudRate, + mouse->oldBaudRate, + xf86MouseCflags[P_LOGI]); + } + if (doclose) + { + close(mouse->mseFd); + } + } + return(mouse->mseFd); +} diff --git a/hw/xfree86/os-support/sco/sco_mouse.c b/hw/xfree86/os-support/sco/sco_mouse.c new file mode 100644 index 000000000..564852ae3 --- /dev/null +++ b/hw/xfree86/os-support/sco/sco_mouse.c @@ -0,0 +1,175 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_mouse.c,v 3.8 1996/12/23 06:50:50 dawes Exp $ */ + + + + + +/* $Xorg: sco_mouse.c,v 1.3 2000/08/17 19:51:29 cpqbld Exp $ */ + +/******************************************************************************/ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +/******************************************************************************/ +#ifdef USE_OSMOUSE +/******************************************************************************/ + +#include +#include +#include "xf86_Config.h" + +static dmask_t real_mask = (dmask_t) (D_REL | D_BUTTON); +static int config_buttons = 0; + +extern int miPointerGetMotionEvents(DeviceIntPtr pPtr, xTimecoord *coords, + unsigned long start, unsigned long stop, + ScreenPtr pScreen); + +/******************************************************************************/ +/* + * Handle any XF86Config options for "OsMouse", How you treat errors + * is up to you, they may or may not be Fatal + */ + +void +xf86OsMouseOption(lt, lp) + int lt; /* type returned by gettoken */ + pointer lp; /* The lexical return symbol */ +{ + if (lt != NUMBER) { + ErrorF("%s: Invalid Argument to OsMouse, %s\n", + "xf86OsMouseOption", "Number of buttons expected"); + return; + } + config_buttons = ((LexPtr)lp)->num; +} + +/******************************************************************************/ +/* + * xf86OsMouseProc -- + * Handle the initialization, etc. of a mouse + */ + +int +xf86OsMouseProc(pPointer, what) + DeviceIntPtr pPointer; + int what; +{ + unchar *map; + int i, err, buttons; + struct devinfo *dip; + dmask_t dmask; + + switch (what) { + case DEVICE_INIT: + + pPointer->public.on = FALSE; + + if (ev_init() < 0) + ErrorF("ev_init: Failed to initialize event driver\n"); + + dmask = real_mask; + xf86Info.mouseDev->mseFd = ev_open(&dmask); + switch (xf86Info.mouseDev->mseFd) { + case -1: FatalError("ev_open: Error in Configuration files\n"); + case -2: FatalError("ev_open: No mouse devices to attach\n"); + case -3: FatalError("ev_open: Unable to open a found device\n"); + case -4: FatalError("ev_open: unable to open an event queue\n"); + default: + if (xf86Info.mouseDev->mseFd < 0) + FatalError("ev_open: Failed to open device, reason unkown\n"); + break; + } + if (dmask != real_mask) + FatalError("Could not attach the mouse device (0x%x)\n", dmask); + + dip = (struct devinfo *) NULL; + if ((dip = ev_getdev(D_REL, dip)) == (struct devinfo *) NULL) + FatalError("Could not find info on mouse device\n"); + + buttons = config_buttons > 0 ? config_buttons : ((int) dip->buttons); + buttons = buttons > 0 ? buttons : 3; /* just in case */ + + ErrorF("%s OsMouse has %d buttons\n", + buttons == config_buttons ? XCONFIG_GIVEN : XCONFIG_PROBED, + buttons); + + map = (unchar *) xalloc(buttons + 1); + if (map == (unchar *) NULL) + FatalError("Failed to allocate OsMouse map structure\n"); + + for (i = 1; i <= buttons; i++) + map[i] = i; + + InitPointerDeviceStruct((DevicePtr)pPointer, + map, + buttons, + miPointerGetMotionEvents, + (PtrCtrlProcPtr)xf86MseCtrl, + 0); + xfree(map); + ev_suspend(); /* suspend device until its turned on */ + break; + + case DEVICE_ON: + ev_resume(); + AddEnabledDevice(xf86Info.mouseDev->mseFd); + xf86Info.mouseDev->lastButtons = 0; + xf86Info.mouseDev->emulateState = 0; + pPointer->public.on = TRUE; + break; + + case DEVICE_CLOSE: + case DEVICE_OFF: + pPointer->public.on = FALSE; + RemoveEnabledDevice(xf86Info.mouseDev->mseFd); + if (what == DEVICE_CLOSE) { + ev_close(); + xf86Info.mouseDev->mseFd = -1; + } else + ev_suspend(); + break; + } + + return Success; +} + +/******************************************************************************/ +/* + * xf86OsMouseEvents -- + * Get some events from our queue. Process all outstanding events now. + */ + +void +xf86OsMouseEvents() +{ + EVENT *evp; + static long time = -1; + + while ((evp = ev_read()) != (EVENT *) NULL ) { +#if DEBUG + if (time == -1) + time = EV_TIME(*evp); + ErrorF("sco_event time(%ld) tag(%d) butts(%d) x(%ld) y(%ld)\n", + EV_TIME(*evp) - time, EV_TAG(*evp), EV_BUTTONS(*evp), + EV_DX(*evp), EV_DY(*evp)); +#endif + xf86PostMseEvent(xf86Info.pMouse,EV_BUTTONS(*evp), EV_DX(*evp), -(EV_DY(*evp))); + ev_pop(); + } + + xf86Info.inputPending = TRUE; +} + +/******************************************************************************/ +#endif /* USE_OSMOUSE */ +/******************************************************************************/ diff --git a/hw/xfree86/os-support/sco/sco_video.c b/hw/xfree86/os-support/sco/sco_video.c new file mode 100644 index 000000000..14947fa85 --- /dev/null +++ b/hw/xfree86/os-support/sco/sco_video.c @@ -0,0 +1,284 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_video.c,v 3.2.2.1 1997/07/19 04:59:31 dawes Exp $ */ +/* + * Copyright 1993 by David McCullough + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 David McCullough and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. David McCullough and + * David Wexelblat makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID MCCULLOUGH AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL DAVID MCCULLOUGH OR DAVID WEXELBLAT 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. + * + */ +/* $Xorg: sco_video.c,v 1.3 2000/08/17 19:51:29 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#define _NEED_SYSI86 +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +/***************************************************************************/ +/* Video Memory Mapping section */ +/***************************************************************************/ + +static struct kd_memloc MapDSC[MAXSCREENS][NUM_REGIONS]; +static int ver_once = 1; + +/***************************************************************************/ +/* + * To map the video-memory, we use the MAP_CLASS ioctl. + * Different drivers may have to do another one of these + * for their own special registers (ie., ATI). To find + * out which strings are valid look in /etc/conf/pack.d/cn/class.h + * + * if we fail to find one of these we try for the dmmap driver + */ + +struct { + unsigned long base, size; + char *class; +} SCO_Mapping[] = { + {0xA0000, 0x10000, "VGA"}, + {0xA0000, 0x20000, "SVGA"}, + {0xB0000, 0x08000, "HGA"}, + {0x0, 0x0, ""}, +}; + +/* ARGSUSED */ +pointer xf86MapVidMem(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ + int i; + char *class = (char *)NULL; + pointer base; + + for (i=0; SCO_Mapping[i].base != 0; i++) + { + if (((pointer)SCO_Mapping[i].base == Base) && + (SCO_Mapping[i].size == Size)) + { + class = SCO_Mapping[i].class; + break; + } + } + if (class == (char *)NULL) + { + int fd; + +#if defined(SVR4) || defined(SCO325) + if ((fd = open(DEV_MEM, O_RDWR)) < 0) + { + FatalError("xf86MapVidMem: failed to open %s (%s)\n", + DEV_MEM, strerror(errno)); + } + base = (pointer)mmap((caddr_t)0, Size, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, (off_t)Base); + close(fd); + if ((long)base == -1) + { + FatalError("%s: Could not mmap framebuffer [s=%x,a=%x] (%s)\n", + "xf86MapVidMem", Size, Base, strerror(errno)); + } + + return(base); +#else + MapDSC[ScreenNum][Region].vaddr = (char *) NULL; + MapDSC[ScreenNum][Region].physaddr = (char *) Base; + MapDSC[ScreenNum][Region].length = Size; + MapDSC[ScreenNum][Region].ioflg = 1; + if ((fd = open("/dev/dmmap", O_RDWR)) >= 0) { + if (ioctl(fd, KDMAPDISP, &MapDSC[ScreenNum][Region]) == -1) + ErrorF("xf86MapVidMem: dmmap KDMAPDISP failed (%s)\n", + strerror(errno)); + else { + if (ver_once) + ErrorF("Using dmmap version 0x%04x.\n", + ioctl(fd, -1)); + ver_once = 0; + close(fd); + return(MapDSC[ScreenNum][Region].vaddr); + } + close(fd); + } + FatalError("xf86MapVidMem:No class map defined for (%x,%x)\n", + Base, Size); + /* NOTREACHED */ +#endif + } + + base = (pointer)ioctl(xf86Info.consoleFd, MAP_CLASS, class); + if ((int)base == -1) + { + FatalError("xf86MapVidMem:Failed to map video mem class %s\n", + class); + /* NOTREACHED */ + } + return(base); +} + +/* + * Nothing to do here if it wasn't mapped using the dmmap driver + */ +/* ARGSUSED */ +void xf86UnMapVidMem(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ + int fd; + +#if defined (SVR4) || defined(SCO325) + munmap(Base, Size); +#else /* SVR4 */ + if (MapDSC[ScreenNum][Region].vaddr) { + if ((fd = open("/dev/dmmap", O_RDWR)) < 0) { + if (ioctl(fd, KDUNMAPDISP, &MapDSC[ScreenNum][Region]) == -1) + ErrorF("xf86UnMapVidMem: dmmap KDUNMAPDISP failed (%s)\n", + strerror(errno)); + close(fd); + } + MapDSC[ScreenNum][Region].vaddr = (char *) NULL; + MapDSC[ScreenNum][Region].physaddr = (char *) NULL; + MapDSC[ScreenNum][Region].length = 0; + MapDSC[ScreenNum][Region].ioflg = 0; + } +#endif + return; +} + +/* ARGSUSED */ +Bool xf86LinearVidMem() +{ + int fd, ver; + +#if defined(SVR4) || defined(SCO325) + return TRUE; +#else + if ((fd = open("/dev/dmmap", O_RDWR)) >= 0) { + ver = ioctl(fd, -1); + close(fd); + if (ver >= 0) { + if (ver_once) + ErrorF("Using dmmap version 0x%04x.\n", ver); + ver_once = 0; + return(TRUE); + } + } + return(FALSE); +#endif +} + +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +static Bool ScreenEnabled[MAXSCREENS]; +static Bool IOEnabled = FALSE; +static Bool InitDone = FALSE; + +void xf86ClearIOPortList(ScreenNum) +int ScreenNum; +{ + int i; + + if (!InitDone) + { + for (i = 0; i < MAXSCREENS; i++) + ScreenEnabled[i] = FALSE; + InitDone = TRUE; + } +} + +/* ARGSUSED */ +void xf86AddIOPorts(ScreenNum, NumPorts, Ports) +int ScreenNum; +int NumPorts; +unsigned *Ports; +{ +} + +void xf86EnableIOPorts(ScreenNum) +int ScreenNum; +{ + ScreenEnabled[ScreenNum] = TRUE; + + if (IOEnabled) + return; + + if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0) + FatalError("Failed to set IOPL for extended I/O\n"); + IOEnabled = TRUE; + return; +} + +void xf86DisableIOPorts(ScreenNum) +int ScreenNum; +{ + int i; + + ScreenEnabled[ScreenNum] = FALSE; + + if (!IOEnabled) + return; + + for (i = 0; i < MAXSCREENS; i++) + if (ScreenEnabled[i]) + return; + sysi86(SI86V86, V86SC_IOPL, 0); + IOEnabled = FALSE; + return; +} + +void xf86DisableIOPrivs() +{ + if (IOEnabled) + sysi86(SI86V86, V86SC_IOPL, 0); + return; +} + +/***************************************************************************/ +/* Interrupt Handling section */ +/***************************************************************************/ + +Bool xf86DisableInterrupts() +{ +#ifdef __GNUC__ + __asm__ __volatile__("cli"); +#else + asm("cli"); +#endif /* __GNUC__ */ + + return(TRUE); +} + +void xf86EnableInterrupts() +{ +#ifdef __GNUC__ + __asm__ __volatile__("sti"); +#else + asm("sti"); +#endif /* __GNUC__ */ + + return; +} diff --git a/hw/xfree86/os-support/shared/VTsw_noop.c b/hw/xfree86/os-support/shared/VTsw_noop.c new file mode 100644 index 000000000..960ca9935 --- /dev/null +++ b/hw/xfree86/os-support/shared/VTsw_noop.c @@ -0,0 +1,51 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_noop.c,v 3.1 1996/12/23 06:50:56 dawes Exp $ */ +/* + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Wexelblat not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. David Wexelblat makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL DAVID WEXELBLAT 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. + * + */ +/* $Xorg: VTsw_noop.c,v 1.3 2000/08/17 19:51:29 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +/* + * No-op functions for OSs without VTs + */ + +Bool xf86VTSwitchPending() +{ + return(FALSE); +} + +Bool xf86VTSwitchAway() +{ + return(FALSE); +} + +Bool xf86VTSwitchTo() +{ + return(TRUE); +} diff --git a/hw/xfree86/os-support/shared/VTsw_usl.c b/hw/xfree86/os-support/shared/VTsw_usl.c new file mode 100644 index 000000000..47c4c5f9d --- /dev/null +++ b/hw/xfree86/os-support/shared/VTsw_usl.c @@ -0,0 +1,80 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_usl.c,v 3.1 1996/12/23 06:50:57 dawes Exp $ */ +/* + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Wexelblat not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. David Wexelblat makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL DAVID WEXELBLAT 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. + * + */ +/* $Xorg: VTsw_usl.c,v 1.3 2000/08/17 19:51:30 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +/* + * Handle the VT-switching interface for OSs that use USL-style ioctl()s + * (the sysv, sco, and linux subdirs). + */ + +/* + * This function is the signal handler for the VT-switching signal. It + * is only referenced inside the OS-support layer. + */ +void xf86VTRequest(sig) +int sig; +{ + signal(sig, (void(*)())xf86VTRequest); + xf86Info.vtRequestsPending = TRUE; + return; +} + +Bool xf86VTSwitchPending() +{ + return(xf86Info.vtRequestsPending ? TRUE : FALSE); +} + +Bool xf86VTSwitchAway() +{ + xf86Info.vtRequestsPending = FALSE; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0) + { + return(FALSE); + } + else + { + return(TRUE); + } +} + +Bool xf86VTSwitchTo() +{ + xf86Info.vtRequestsPending = FALSE; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) + { + return(FALSE); + } + else + { + return(TRUE); + } +} diff --git a/hw/xfree86/os-support/shared/bios_devmem.c b/hw/xfree86/os-support/shared/bios_devmem.c new file mode 100644 index 000000000..f26d7a524 --- /dev/null +++ b/hw/xfree86/os-support/shared/bios_devmem.c @@ -0,0 +1,139 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/bios_devmem.c,v 3.3 1996/12/23 06:50:58 dawes Exp $ */ +/* + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Wexelblat not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. David Wexelblat makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL DAVID WEXELBLAT 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. + * + */ +/* $Xorg: bios_devmem.c,v 1.3 2000/08/17 19:51:30 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include + +/* + * Read BIOS via /dev/mem. + */ + +#ifndef DEV_MEM +# define DEV_MEM "/dev/mem" +#endif + +int xf86ReadBIOS(Base, Offset, Buf, Len) +unsigned long Base; +unsigned long Offset; +unsigned char *Buf; +int Len; +{ +#ifdef __alpha__ + /* + * The Alpha version uses "mmap" instead of "lseek/read", + * because these (currently) don't work for BUS memory. + * We trick "mmap" into mapping BUS memory for us via BUS_BASE, + * which is the KSEG address of the start of the DENSE memory + * area. + */ + + /* + * NOTE: there prolly ought to be more validity checks and all + * re: boundaries and sizes and such... + */ + +/* + * The Jensen lacks dense memory, thus we have to address the bus via + * the sparse addressing scheme. + * + * Martin Ostermann (ost@comnets.rwth-aachen.de) - Apr.-Sep. 1996 + */ + +#ifdef TEST_JENSEN_CODE /* define to test the Sparse addressing on a non-Jensen */ +#define SPARSE (5) +#define isJensen (1) +#else +#define isJensen (!_bus_base()) +#define SPARSE (7) +#endif + +extern unsigned long _bus_base(void); +extern unsigned long _bus_base_sparse(void); +#define BUS_BASE (isJensen ? _bus_base_sparse() : _bus_base()) +#define JENSEN_SHIFT(x) (isJensen ? ((long)x< + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Wexelblat not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. David Wexelblat makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL DAVID WEXELBLAT 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. + * + */ +/* $Xorg: ioperm_noop.c,v 1.3 2000/08/17 19:51:30 cpqbld Exp $ */ + +/* + * Amoeba, Minix and 386BSD don't bother with I/O permissions, + * or the permissions are implicit with opening/enabling the console. + */ +void xf86ClearIOPortList(ScreenNum) +int ScreenNum; +{ + return; +} + +/* ARGSUSED */ +void xf86AddIOPorts(ScreenNum, NumPorts, Ports) +int ScreenNum; +int NumPorts; +unsigned *Ports; +{ + return; +} + +void xf86EnableIOPorts(ScreenNum) +int ScreenNum; +{ + return; +} + +void xf86DisableIOPorts(ScreenNum) +int ScreenNum; +{ + return; +} + +void xf86DisableIOPrivs() +{ + return; +} diff --git a/hw/xfree86/os-support/shared/posix_tty.c b/hw/xfree86/os-support/shared/posix_tty.c new file mode 100644 index 000000000..8e92511d3 --- /dev/null +++ b/hw/xfree86/os-support/shared/posix_tty.c @@ -0,0 +1,174 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/posix_tty.c,v 3.8.2.1 1998/02/07 14:27:25 dawes Exp $ */ +/* + * Copyright 1993 by David Dawes + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. + * David Dawes makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL DAVID DAWES 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. + * + */ +/* $Xorg: posix_tty.c,v 1.3 2000/08/17 19:51:30 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "xf86_Config.h" + +static Bool not_a_tty = FALSE; + +void xf86SetMouseSpeed(mouse, old, new, cflag) +MouseDevPtr mouse; +int old; +int new; +unsigned cflag; +{ + struct termios tty; + char *c; + + if (not_a_tty) + return; + + if (tcgetattr(mouse->mseFd, &tty) < 0) + { + not_a_tty = TRUE; + ErrorF("Warning: %s unable to get status of mouse fd (%s)\n", + mouse->mseDevice, strerror(errno)); + return; + } + + /* this will query the initial baudrate only once */ + if (mouse->oldBaudRate < 0) { + switch (cfgetispeed(&tty)) + { + case B9600: + mouse->oldBaudRate = 9600; + break; + case B4800: + mouse->oldBaudRate = 4800; + break; + case B2400: + mouse->oldBaudRate = 2400; + break; + case B1200: + default: + mouse->oldBaudRate = 1200; + break; + } + } + + tty.c_iflag = IGNBRK | IGNPAR; + tty.c_oflag = 0; + tty.c_lflag = 0; + tty.c_cflag = (tcflag_t)cflag; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + + switch (old) + { + case 9600: + cfsetispeed(&tty, B9600); + cfsetospeed(&tty, B9600); + break; + case 4800: + cfsetispeed(&tty, B4800); + cfsetospeed(&tty, B4800); + break; + case 2400: + cfsetispeed(&tty, B2400); + cfsetospeed(&tty, B2400); + break; + case 1200: + default: + cfsetispeed(&tty, B1200); + cfsetospeed(&tty, B1200); + } + + if (tcsetattr(mouse->mseFd, TCSADRAIN, &tty) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Unable to set status of mouse fd (%s) - Continuing...\n", + strerror(errno)); + return; + } + xf86FatalError("Unable to set status of mouse fd (%s)\n", + strerror(errno)); + } + + switch (new) + { + case 9600: + c = "*q"; + cfsetispeed(&tty, B9600); + cfsetospeed(&tty, B9600); + break; + case 4800: + c = "*p"; + cfsetispeed(&tty, B4800); + cfsetospeed(&tty, B4800); + break; + case 2400: + c = "*o"; + cfsetispeed(&tty, B2400); + cfsetospeed(&tty, B2400); + break; + case 1200: + default: + c = "*n"; + cfsetispeed(&tty, B1200); + cfsetospeed(&tty, B1200); + } + + if (mouse->mseType == P_LOGIMAN || mouse->mseType == P_LOGI) + { + if (write(mouse->mseFd, c, 2) != 2) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Unable to write to mouse fd (%s) - Continuing...\n", + strerror(errno)); + return; + } + xf86FatalError("Unable to write to mouse fd (%s)\n", + strerror(errno)); + } + } + usleep(100000); + + if (tcsetattr(mouse->mseFd, TCSADRAIN, &tty) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Unable to set status of mouse fd (%s) - Continuing...\n", + strerror(errno)); + return; + } + xf86FatalError("Unable to set status of mouse fd (%s)\n", + strerror(errno)); + } +} + +int +xf86FlushInput(fd) +int fd; +{ + return tcflush(fd, TCIFLUSH); +} + diff --git a/hw/xfree86/os-support/shared/std_kbdEv.c b/hw/xfree86/os-support/shared/std_kbdEv.c new file mode 100644 index 000000000..bca8061db --- /dev/null +++ b/hw/xfree86/os-support/shared/std_kbdEv.c @@ -0,0 +1,49 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c,v 3.1 1996/12/23 06:51:02 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Dawes + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Thomas Roell and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Thomas Roell and + * David Dawes makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THOMAS ROELL AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES 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. + * + */ +/* $Xorg: std_kbdEv.c,v 1.3 2000/08/17 19:51:30 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +void xf86KbdEvents() +{ + unsigned char rBuf[64]; + int nBytes, i; + + if ((nBytes = read( xf86Info.consoleFd, (char *)rBuf, sizeof(rBuf))) + > 0) + { + for (i = 0; i < nBytes; i++) + xf86PostKbdEvent(rBuf[i]); + } +} + diff --git a/hw/xfree86/os-support/shared/sysv_kbd.c b/hw/xfree86/os-support/shared/sysv_kbd.c new file mode 100644 index 000000000..2270be9f1 --- /dev/null +++ b/hw/xfree86/os-support/shared/sysv_kbd.c @@ -0,0 +1,105 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/sysv_kbd.c,v 3.2 1996/12/23 06:51:07 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Dawes + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Thomas Roell and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Thomas Roell and + * David Dawes makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THOMAS ROELL AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES 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. + * + */ +/* $Xorg: sysv_kbd.c,v 1.3 2000/08/17 19:51:30 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +int xf86GetKbdLeds() +{ + int leds; + + ioctl(xf86Info.consoleFd, KDGETLED, &leds); + return(leds); +} + +#if NeedFunctionPrototypes +void xf86SetKbdRepeat(char rad) +#else +void xf86SetKbdRepeat(rad) +char rad; +#endif +{ +#ifdef KDSETRAD + ioctl(xf86Info.consoleFd, KDSETRAD, rad); +#endif +} + +static int kbdtrans; +static struct termio kbdtty; +static char *kbdemap = NULL; + +void xf86KbdInit() +{ +#ifdef KDGKBMODE + ioctl (xf86Info.consoleFd, KDGKBMODE, &kbdtrans); +#endif + ioctl (xf86Info.consoleFd, TCGETA, &kbdtty); +#if defined(E_TABSZ) && !defined(SCO325) + kbdemap = (char *)xalloc(E_TABSZ); + if (ioctl(xf86Info.consoleFd, LDGMAP, kbdemap) < 0) + { + xfree(kbdemap); + kbdemap = NULL; + } +#endif +} + +int xf86KbdOn() +{ + struct termio nTty; + + ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW); + ioctl(xf86Info.consoleFd, LDNMAP, 0); /* disable mapping completely */ + nTty = kbdtty; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8 | B9600; + nTty.c_lflag = 0; + nTty.c_cc[VTIME]=0; + nTty.c_cc[VMIN]=1; + ioctl(xf86Info.consoleFd, TCSETA, &nTty); + return(xf86Info.consoleFd); +} + +int xf86KbdOff() +{ + if (kbdemap) + { + ioctl(xf86Info.consoleFd, LDSMAP, kbdemap); + } + ioctl(xf86Info.consoleFd, KDSKBMODE, kbdtrans); + ioctl(xf86Info.consoleFd, TCSETA, &kbdtty); + return(xf86Info.consoleFd); +} diff --git a/hw/xfree86/os-support/sysv/sysv_init.c b/hw/xfree86/os-support/sysv/sysv_init.c new file mode 100644 index 000000000..a253ab0b0 --- /dev/null +++ b/hw/xfree86/os-support/sysv/sysv_init.c @@ -0,0 +1,257 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sysv/sysv_init.c,v 3.4.2.1 1998/02/06 22:36:54 hohndel Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Thomas Roell and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Thomas Roell and + * David Wexelblat makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THOMAS ROELL AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID WEXELBLAT 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. + * + */ +/* $Xorg: sysv_init.c,v 1.3 2000/08/17 19:51:32 cpqbld Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "input.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +static Bool KeepTty = FALSE; +#ifdef SVR4 +static Bool Protect0 = FALSE; +#endif +static int VTnum = -1; + +extern void xf86VTRequest( +#if NeedFunctionPrototypes + int +#endif +); + +void xf86OpenConsole() +{ + int fd; + struct vt_mode VT; + char vtname1[10],vtname2[10]; + + if (serverGeneration == 1) + { + /* check if we're run with euid==0 */ + if (geteuid() != 0) + { + FatalError("xf86OpenConsole: Server must be running with root " + "permissions\n" + "You should be using Xwrapper to start the server or xdm.\n" + "We strongly advise against making the server SUID root!\n"); + } + +#ifdef SVR4 + /* Protect page 0 to help find NULL dereferencing */ + /* mprotect() doesn't seem to work */ + if (Protect0) + { + int fd = -1; + + if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0) + { + ErrorF("xf86OpenConsole: cannot open /dev/zero (%s)\n", + strerror(errno)); + } + else + { + if ((int)mmap(0, 0x1000, PROT_NONE, + MAP_FIXED | MAP_SHARED, fd, 0) == -1) + { + ErrorF("xf86OpenConsole: failed to protect page 0 (%s)\n", + strerror(errno)); + } + close(fd); + } + } +#endif + /* + * setup the virtual terminal manager + */ + if (VTnum != -1) + { + xf86Info.vtno = VTnum; + } + else + { + if ((fd = open("/dev/console",O_WRONLY,0)) < 0) + { + FatalError( + "xf86OpenConsole: Cannot open /dev/console (%s)\n", + strerror(errno)); + } + if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) || + (xf86Info.vtno == -1)) + { + FatalError("xf86OpenConsole: Cannot find a free VT\n"); + } + close(fd); + } + ErrorF("(using VT number %d)\n\n", xf86Info.vtno); + + sprintf(vtname1,"/dev/vc%02d",xf86Info.vtno); /* ESIX */ + sprintf(vtname2,"/dev/vt%02d",xf86Info.vtno); /* rest of the world */ + + xf86Config(FALSE); /* Read XF86Config */ + + if (!KeepTty) + { + setpgrp(); + } + + if (((xf86Info.consoleFd = open(vtname1, O_RDWR|O_NDELAY, 0)) < 0) && + ((xf86Info.consoleFd = open(vtname2, O_RDWR|O_NDELAY, 0)) < 0)) + { + FatalError("xf86OpenConsole: Cannot open %s (%s) (%s)\n", + vtname2, vtname1, strerror(errno)); + } + + /* change ownership of the vt */ + if (chown(vtname1, getuid(), getgid()) < 0) + { + chown(vtname2, getuid(), getgid()); + } + + /* + * now get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_WAITACTIVE failed\n"); + } + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) + { + FatalError("xf86OpenConsole: VT_GETMODE failed\n"); + } + + signal(SIGUSR1, xf86VTRequest); + + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0) + { + FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n"); + } + if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) + { + FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n"); + } + } + else + { + /* serverGeneration != 1 */ + /* + * now get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + } + if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + { + ErrorF("xf86OpenConsole: VT_WAITACTIVE failed\n"); + } + /* + * If the server doesn't have the VT when the reset occurs, + * this is to make sure we don't continue until the activate + * signal is received. + */ + if (!xf86VTSema) + sleep(5); + } + return; +} + +void xf86CloseConsole() +{ + struct vt_mode VT; + +#if 0 + ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno); + ioctl(xf86Info.consoleFd, VT_WAITACTIVE, 0); +#endif + ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */ + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) + { + VT.mode = VT_AUTO; + ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */ + } + close(xf86Info.consoleFd); /* make the vt-manager happy */ + return; +} + +int xf86ProcessArgument(argc, argv, i) +int argc; +char *argv[]; +int i; +{ + /* + * Keep server from detaching from controlling tty. This is useful + * when debugging (so the server can receive keyboard signals. + */ + if (!strcmp(argv[i], "-keeptty")) + { + KeepTty = TRUE; + return(1); + } +#ifdef SVR4 + /* + * Undocumented flag to protect page 0 from read/write to help + * catch NULL pointer dereferences. This is purely a debugging + * flag. + */ + if (!strcmp(argv[i], "-protect0")) + { + Protect0 = TRUE; + return(1); + } +#endif + if ((argv[i][0] == 'v') && (argv[i][1] == 't')) + { + if (sscanf(argv[i], "vt%2d", &VTnum) == 0) + { + UseMsg(); + VTnum = -1; + return(0); + } + return(1); + } + return(0); +} + +void xf86UseMsg() +{ + ErrorF("vtXX use the specified VT number\n"); + ErrorF("-keeptty "); + ErrorF("don't detach controlling tty (for debugging only)\n"); + return; +} diff --git a/hw/xfree86/os-support/sysv/sysv_io.c b/hw/xfree86/os-support/sysv/sysv_io.c new file mode 100644 index 000000000..150290c40 --- /dev/null +++ b/hw/xfree86/os-support/sysv/sysv_io.c @@ -0,0 +1,98 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sysv/sysv_io.c,v 3.4 1996/12/23 06:51:26 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Dawes + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Thomas Roell and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Thomas Roell and + * David Dawes makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THOMAS ROELL AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES 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. + * + */ +/* $Xorg: sysv_io.c,v 1.3 2000/08/17 19:51:32 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "compiler.h" + +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +void xf86SoundKbdBell(loudness, pitch, duration) +int loudness; +int pitch; +int duration; +{ + if (loudness && pitch) + { +#ifdef KDMKTONE + /* + * If we have KDMKTONE use it to avoid putting the server + * to sleep + */ + ioctl(xf86Info.consoleFd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration * + loudness / 50) << 16)); +#else + ioctl(xf86Info.consoleFd, KIOCSOUND, 1193180 / pitch); + usleep(xf86Info.bell_duration * loudness * 20); + ioctl(xf86Info.consoleFd, KIOCSOUND, 0); +#endif + } +} + +void xf86SetKbdLeds(leds) +int leds; +{ +#ifdef KBIO_SETMODE + ioctl(xf86Info.consoleFd, KBIO_SETMODE, KBM_AT); + ioctl(xf86Info.consoleFd, KDSETLED, leds); + ioctl(xf86Info.consoleFd, KBIO_SETMODE, KBM_XT); +#endif +} + +void xf86MouseInit(mouse) +MouseDevPtr mouse; +{ + return; +} + +int xf86MouseOn(mouse) +MouseDevPtr mouse; +{ + if ((mouse->mseFd = open(mouse->mseDevice, O_RDWR | O_NDELAY)) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Cannot open mouse (%s) - Continuing...\n", + strerror(errno)); + return(-2); + } + FatalError("Cannot open mouse (%s)\n", strerror(errno)); + } + + xf86SetupMouse(mouse); + + /* Flush any pending input */ + ioctl(mouse->mseFd, TCFLSH, 0); + + return(mouse->mseFd); +} diff --git a/hw/xfree86/os-support/sysv/sysv_video.c b/hw/xfree86/os-support/sysv/sysv_video.c new file mode 100644 index 000000000..7dd1575fc --- /dev/null +++ b/hw/xfree86/os-support/sysv/sysv_video.c @@ -0,0 +1,589 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sysv/sysv_video.c,v 3.9 1996/12/23 06:51:27 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Thomas Roell and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Thomas Roell and + * David Wexelblat makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THOMAS ROELL AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID WEXELBLAT 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. + * + */ +/* $Xorg: sysv_video.c,v 1.3 2000/08/17 19:51:33 cpqbld Exp $ */ + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#define _NEED_SYSI86 +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#ifndef SI86IOPL +#define SET_IOPL() sysi86(SI86V86,V86SC_IOPL,PS_IOPL) +#define RESET_IOPL() sysi86(SI86V86,V86SC_IOPL,0) +#else +#define SET_IOPL() sysi86(SI86IOPL,3) +#define RESET_IOPL() sysi86(SI86IOPL,0) +#endif + +/***************************************************************************/ +/* Video Memory Mapping section */ +/***************************************************************************/ + +struct kd_memloc MapDSC[MAXSCREENS][NUM_REGIONS]; +pointer AllocAddress[MAXSCREENS][NUM_REGIONS]; +#ifndef SVR4 +static int mmapFd = -2; +#endif +#if 0 +/* inserted for DGA support Tue Dec 5 21:33:00 MET 1995 mr */ +#if defined(SVR4) || defined(HAS_SVR3_MMAPDRV) +static struct xf86memMap { + int offset; + int memSize; +} xf86memMaps[MAXSCREENS]; +#endif +#endif + +Bool xf86LinearVidMem() +{ +#ifdef SVR4 + return TRUE; +#else +#ifdef HAS_SVR3_MMAPDRV + if(mmapFd >= 0) + { + return TRUE; + } + if ((mmapFd = open("/dev/mmap", O_RDWR)) != -1) + { + if(ioctl(mmapFd, GETVERSION) < 0x0222) { + ErrorF("xf86LinearVidMem: MMAP 2.2.2 or above required\n"); + ErrorF(" linear memory access disabled\n"); + return FALSE; + } + return TRUE; + } + ErrorF("xf86LinearVidMem: failed to open /dev/mmap (%s)\n", + strerror(errno)); + ErrorF(" linear memory access disabled\n"); +#endif + return FALSE; +#endif +} + +pointer xf86MapVidMem(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ + pointer base; + int fd; + +#if defined(SVR4) + if ((fd = open(DEV_MEM, O_RDWR)) < 0) + { + FatalError("xf86MapVidMem: failed to open %s (%s)\n", + DEV_MEM, strerror(errno)); + } + base = (pointer)mmap((caddr_t)0, Size, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, (off_t)Base); + close(fd); + if ((long)base == -1) + { + FatalError("%s: Could not mmap framebuffer [s=%x,a=%x] (%s)\n", + "xf86MapVidMem", Size, Base, strerror(errno)); + } +#else /* SVR4 */ +#ifdef HAS_SVR3_MMAPDRV + if (mmapFd == -2) + { + mmapFd = open("/dev/mmap", O_RDWR); + } +#endif + if (mmapFd >= 0) + { + /* To force the MMAP driver to provide the address */ + base = (pointer)0; + } + else + { + AllocAddress[ScreenNum][Region] = (pointer)xalloc(Size + 0x1000); + if (AllocAddress[ScreenNum][Region] == (pointer)0) + { + FatalError("xf86MapVidMem: can't alloc framebuffer space\n"); + /* NOTREACHED */ + } + base = (pointer)(((unsigned int)AllocAddress[ScreenNum][Region] + & ~0xFFF) + 0x1000); + } + MapDSC[ScreenNum][Region].vaddr = (char *)base; + MapDSC[ScreenNum][Region].physaddr = (char *)Base; + MapDSC[ScreenNum][Region].length = Size; + MapDSC[ScreenNum][Region].ioflg = 1; + +#ifdef HAS_SVR3_MMAPDRV + if(mmapFd >= 0) + { + if((base = (pointer)ioctl(mmapFd, MAP, + &(MapDSC[ScreenNum][Region]))) == (pointer)-1) + { + FatalError("%s: Could not mmap framebuffer [s=%x,a=%x] (%s)\n", + "xf86MapVidMem", Size, Base, strerror(errno)); + /* NOTREACHED */ + } + + /* Next time we want the same address! */ + MapDSC[ScreenNum][Region].vaddr = (char *)base; +#if 0 +/* inserted for DGA support Tue Dec 5 21:33:00 MET 1995 mr */ + xf86memMaps[ScreenNum].offset = (int) Base; + xf86memMaps[ScreenNum].memSize = Size; +#endif + return((pointer)base); + } +#endif + if (ioctl(xf86Info.consoleFd, KDMAPDISP, + &(MapDSC[ScreenNum][Region])) < 0) + { + FatalError("xf86MapVidMem: Failed to map video mem (%x,%x) (%s)\n", + Base, Size, strerror(errno)); + /* NOTREACHED */ + } +#endif /* SVR4 */ +#if 0 + xf86memMaps[ScreenNum].offset = (int) Base; + xf86memMaps[ScreenNum].memSize = Size; +#endif + return((pointer)base); +} + +#if 0 +/* inserted for DGA support Tue Dec 5 21:33:00 MET 1995 mr */ +#if defined(SVR4) || defined(HAS_SVR3_MMAPDRV) +void xf86GetVidMemData(ScreenNum, Base, Size) +int ScreenNum; +int *Base; +int *Size; +{ + *Base = xf86memMaps[ScreenNum].offset; + *Size = xf86memMaps[ScreenNum].memSize; +} + +#endif +#endif +/* ARGSUSED */ +void xf86UnMapVidMem(ScreenNum, Region, Base, Size) +int ScreenNum; +int Region; +pointer Base; +unsigned long Size; +{ +#if defined (SVR4) + munmap(Base, Size); +#else /* SVR4 */ +#ifdef HAS_SVR3_MMAPDRV + if(mmapFd >= 0) + { + ioctl(mmapFd, UNMAPRM, MapDSC[ScreenNum][Region].vaddr); + return; + } +#endif + /* XXXX This is a problem because it unmaps all regions */ + ioctl(xf86Info.consoleFd, KDUNMAPDISP, 0); + xfree(AllocAddress[ScreenNum][Region]); +#endif /* SVR4 */ +} + +/* ARGSUSED */ +void xf86MapDisplay(ScreenNum, Region) +int ScreenNum; +int Region; +{ +#if !defined(SVR4) +#ifdef HAS_SVR3_MMAPDRV + if(mmapFd >= 0) + { + ioctl(mmapFd, MAP, &(MapDSC[ScreenNum][Region])); + return; + } +#endif + ioctl(xf86Info.consoleFd, KDMAPDISP, &(MapDSC[ScreenNum][Region])); +#endif /* SVR4 */ + return; +} + +/* ARGSUSED */ +void xf86UnMapDisplay(ScreenNum, Region) +int ScreenNum; +int Region; +{ +#if !defined(SVR4) +#ifdef HAS_SVR3_MMAPDRV + if(mmapFd > 0) + { + ioctl(mmapFd, UNMAP, MapDSC[ScreenNum][Region].vaddr); + return; + } +#endif + ioctl(xf86Info.consoleFd, KDUNMAPDISP, 0); +#endif /* SVR4 */ + return; +} + +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +#define ALWAYS_USE_EXTENDED +#ifdef ALWAYS_USE_EXTENDED + +static Bool ScreenEnabled[MAXSCREENS]; +static Bool ExtendedEnabled = FALSE; +static Bool InitDone = FALSE; + +void +xf86ClearIOPortList(ScreenNum) +int ScreenNum; +{ + if (!InitDone) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + ScreenEnabled[i] = FALSE; + InitDone = TRUE; + } + return; +} + +void +xf86AddIOPorts(ScreenNum, NumPorts, Ports) +int ScreenNum; +int NumPorts; +unsigned *Ports; +{ + return; +} + +void +xf86EnableIOPorts(ScreenNum) +int ScreenNum; +{ + int i; + + ScreenEnabled[ScreenNum] = TRUE; + + if (ExtendedEnabled) + return; + + if (SET_IOPL() < 0) + { + FatalError("%s: Failed to set IOPL for extended I/O\n", + "xf86EnableIOPorts"); + } + ExtendedEnabled = TRUE; + + return; +} + +void +xf86DisableIOPorts(ScreenNum) +int ScreenNum; +{ + int i; + + ScreenEnabled[ScreenNum] = FALSE; + + if (!ExtendedEnabled) + return; + + for (i = 0; i < MAXSCREENS; i++) + if (ScreenEnabled[i]) + return; + + RESET_IOPL(); + ExtendedEnabled = FALSE; + + return; +} + +#else /* !ALWAYS_USE_EXTENDED */ + +#define DISABLED 0 +#define NON_EXTENDED 1 +#define EXTENDED 2 + +static unsigned *EnabledPorts[MAXSCREENS]; +static int NumEnabledPorts[MAXSCREENS]; +static Bool ScreenEnabled[MAXSCREENS]; +static Bool ExtendedPorts[MAXSCREENS]; +static Bool ExtendedEnabled = FALSE; +static Bool InitDone = FALSE; +static struct kd_disparam OrigParams; + +void xf86ClearIOPortList(ScreenNum) +int ScreenNum; +{ + if (!InitDone) + { + xf86InitPortLists(EnabledPorts, NumEnabledPorts, ScreenEnabled, + ExtendedPorts, MAXSCREENS); + if (ioctl(xf86Info.consoleFd, KDDISPTYPE, &OrigParams) < 0) + { + FatalError("%s: Could not get display parameters\n", + "xf86ClearIOPortList"); + } + InitDone = TRUE; + return; + } + ExtendedPorts[ScreenNum] = FALSE; + if (EnabledPorts[ScreenNum] != (unsigned *)NULL) + xfree(EnabledPorts[ScreenNum]); + EnabledPorts[ScreenNum] = (unsigned *)NULL; + NumEnabledPorts[ScreenNum] = 0; +} + +void xf86AddIOPorts(ScreenNum, NumPorts, Ports) +int ScreenNum; +int NumPorts; +unsigned *Ports; +{ + int i; + + if (!InitDone) + { + FatalError("xf86AddIOPorts: I/O control lists not initialised\n"); + } + EnabledPorts[ScreenNum] = (unsigned *)xrealloc(EnabledPorts[ScreenNum], + (NumEnabledPorts[ScreenNum]+NumPorts)*sizeof(unsigned)); + for (i = 0; i < NumPorts; i++) + { + EnabledPorts[ScreenNum][NumEnabledPorts[ScreenNum] + i] = + Ports[i]; + if (Ports[i] > 0x3FF) + ExtendedPorts[ScreenNum] = TRUE; + } + NumEnabledPorts[ScreenNum] += NumPorts; +} + +void xf86EnableIOPorts(ScreenNum) +int ScreenNum; +{ + struct kd_disparam param; + int i, j; + + if (ScreenEnabled[ScreenNum]) + return; + + for (i = 0; i < MAXSCREENS; i++) + { + if (ExtendedPorts[i] && (ScreenEnabled[i] || i == ScreenNum)) + { + if (SET_IOPL() < 0) + { + FatalError("%s: Failed to set IOPL for extended I/O\n", + "xf86EnableIOPorts"); + } + ExtendedEnabled = TRUE; + break; + } + } + /* If extended I/O was used, but isn't any more */ + if (ExtendedEnabled && i == MAXSCREENS) + { + RESET_IOPL(); + ExtendedEnabled = FALSE; + } + /* + * Turn on non-extended ports even when using extended I/O + * so they are there if extended I/O gets turned off when it's no + * longer needed. + */ + if (ioctl(xf86Info.consoleFd, KDDISPTYPE, ¶m) < 0) + { + FatalError("%s: Could not get display parameters\n", + "xf86EnableIOPorts"); + } + for (i = 0; i < NumEnabledPorts[ScreenNum]; i++) + { + unsigned port = EnabledPorts[ScreenNum][i]; + + if (port > 0x3FF) + continue; + + if (!xf86CheckPorts(port, EnabledPorts, NumEnabledPorts, + ScreenEnabled, MAXSCREENS)) + { + continue; + } + for (j=0; j < MKDIOADDR; j++) + { + if (param.ioaddr[j] == port) + { + break; + } + } + if (j == MKDIOADDR) + { + if (ioctl(xf86Info.consoleFd, KDADDIO, port) < 0) + { + FatalError("%s: Failed to enable port 0x%x\n", + "xf86EnableIOPorts", port); + } + } + } + if (ioctl(xf86Info.consoleFd, KDENABIO, 0) < 0) + { + FatalError("xf86EnableIOPorts: I/O port enable failed (%s)\n", + strerror(errno)); + } + ScreenEnabled[ScreenNum] = TRUE; + return; +} + +void xf86DisableIOPorts(ScreenNum) +int ScreenNum; +{ + struct kd_disparam param; + int i, j; + + if (!ScreenEnabled[ScreenNum]) + return; + + ScreenEnabled[ScreenNum] = FALSE; + for (i = 0; i < MAXSCREENS; i++) + { + if (ScreenEnabled[i] && ExtendedPorts[i]) + break; + } + if (ExtendedEnabled && i == MAXSCREENS) + { + RESET_IOPL(); + ExtendedEnabled = FALSE; + } + /* Turn off I/O before changing the access list */ + ioctl(xf86Info.consoleFd, KDDISABIO, 0); + if (ioctl(xf86Info.consoleFd, KDDISPTYPE, ¶m) < 0) + { + ErrorF("%s: Could not get display parameters\n", + "xf86DisableIOPorts"); + return; + } + + for (i=0; i < MKDIOADDR; i++) + { + /* 0 indicates end of list */ + if (param.ioaddr[i] == 0) + { + break; + } + if (!xf86CheckPorts(param.ioaddr[i], EnabledPorts, + NumEnabledPorts, ScreenEnabled, MAXSCREENS)) + { + continue; + } + for (j=0; j < MKDIOADDR; j++) + { + if (param.ioaddr[i] == OrigParams.ioaddr[j]) + { + /* + * Port was one of the original ones; don't + * touch it. + */ + break; + } + } + if (j == MKDIOADDR) + { + /* + * We added this port, so remove it. + */ + ioctl(xf86Info.consoleFd, KDDELIO, param.ioaddr[i]); + } + } + /* If any other screens are enabled, turn I/O back on */ + for (i = 0; i < MAXSCREENS; i++) + { + if (ScreenEnabled[i]) + { + ioctl(xf86Info.consoleFd, KDENABIO, 0); + break; + } + } + return; +} +#endif /* ALWAYS_USE_EXTENDED */ + +void xf86DisableIOPrivs() +{ + if (ExtendedEnabled) + RESET_IOPL(); + return; +} + +/***************************************************************************/ +/* Interrupt Handling section */ +/***************************************************************************/ + +Bool xf86DisableInterrupts() +{ + if (!ExtendedEnabled) + { + if (SET_IOPL() < 0) + { + return(FALSE); + } + } + +#ifdef __GNUC__ + __asm__ __volatile__("cli"); +#else + asm("cli"); +#endif /* __GNUC__ */ + + if (!ExtendedEnabled) + { + RESET_IOPL(); + } + return(TRUE); +} + +void xf86EnableInterrupts() +{ + if (!ExtendedEnabled) + { + if (SET_IOPL() < 0) + { + return; + } + } + +#ifdef __GNUC__ + __asm__ __volatile__("sti"); +#else + asm("sti"); +#endif /* __GNUC__ */ + + if (!ExtendedEnabled) + { + RESET_IOPL(); + } + return; +} diff --git a/hw/xfree86/os-support/sysv/xqueue.c b/hw/xfree86/os-support/sysv/xqueue.c new file mode 100644 index 000000000..5e3c8e9fc --- /dev/null +++ b/hw/xfree86/os-support/sysv/xqueue.c @@ -0,0 +1,406 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sysv/xqueue.c,v 3.8.2.1 1997/07/13 14:45:04 dawes Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* $Xorg: xqueue.c,v 1.3 2000/08/17 19:51:33 cpqbld Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +#ifdef XQUEUE + +static xqEventQueue *XqueQaddr; +static int xqueFd = -1; +#ifndef XQUEUE_ASYNC +static int xquePipe[2]; +#endif + +#ifdef XKB +#include +#include +#include +extern Bool noXkbExtension; +#endif + +#ifdef XINPUT +#include "xf86_Config.h" +#include "xf86Xinput.h" +#endif +extern int miPointerGetMotionEvents(DeviceIntPtr pPtr, xTimecoord *coords, + unsigned long start, unsigned long stop, + ScreenPtr pScreen); + +#ifndef XQUEUE_ASYNC +/* + * xf86XqueSignal -- + * Trap the signal from xqueue and let it be known that events are + * ready for collection + */ + +static void +xf86XqueSignal(int signum) +{ + xf86Info.mouseDev->xquePending = 1; + /* + * This is a hack, but it is the only reliable way I can find of letting + * the main select() loop know that there is more input waiting. Receiving + * a signal will interrupt select(), but there is no way I can find of + * dealing with events that come in between the end of processing the + * last set and when select() gets called. + * + * Suggestions for better ways of dealing with this without going back to + * asynchronous event processing are welcome. + */ + write(xquePipe[1], "X", 1); + signal(SIGUSR2, xf86XqueSignal); +} +#endif + + +/* + * xf86XqueRequest -- + * Notice an i/o request from the xqueue. + */ + +void +xf86XqueRequest() +{ + xqEvent *XqueEvents = XqueQaddr->xq_events; + int XqueHead = XqueQaddr->xq_head; + char buf[100]; + + while (XqueHead != XqueQaddr->xq_tail) + { + + switch(XqueEvents[XqueHead].xq_type) { + + case XQ_BUTTON: + xf86PostMseEvent(xf86Info.pMouse, + ~(XqueEvents[XqueHead].xq_code) & 0x07, 0, 0); + break; + + case XQ_MOTION: + xf86PostMseEvent(xf86Info.pMouse, + ~(XqueEvents[XqueHead].xq_code) & 0x07, + XqueEvents[XqueHead].xq_x, + XqueEvents[XqueHead].xq_y); + break; + + case XQ_KEY: + xf86PostKbdEvent(XqueEvents[XqueHead].xq_code); + break; + + default: + ErrorF("Unknown Xque Event: 0x%02x\n", XqueEvents[XqueHead].xq_type); + } + + if ((++XqueHead) == XqueQaddr->xq_size) XqueHead = 0; + } + + /* reenable the signal-processing */ + xf86Info.inputPending = TRUE; +#ifdef XQUEUE_ASYNC + signal(SIGUSR2, (void (*)()) xf86XqueRequest); +#else +#if 0 + signal(SIGUSR2, (void (*)()) xf86XqueSignal); +#endif +#endif + +#ifndef XQUEUE_ASYNC + { + int rval; + + while ((rval = read(xquePipe[0], buf, sizeof(buf))) > 0) +#ifdef DEBUG + ErrorF("Read %d bytes from xquePipe[0]\n", rval); +#else + ; +#endif + } +#endif + + XqueQaddr->xq_head = XqueQaddr->xq_tail; + xf86Info.mouseDev->xquePending = 0; + XqueQaddr->xq_sigenable = 1; /* UNLOCK */ +} + + + +/* + * xf86XqueEnable -- + * Enable the handling of the Xque + */ + +static int +xf86XqueEnable() +{ + static struct kd_quemode xqueMode; + static Bool was_here = FALSE; + + if (!was_here) { + if ((xqueFd = open("/dev/mouse", O_RDONLY|O_NDELAY)) < 0) + { + if (xf86AllowMouseOpenFail) { + ErrorF("Cannot open /dev/mouse (%s) - Continuing...\n", + strerror(errno)); + return (Success); + } else { + Error ("Cannot open /dev/mouse"); + return (!Success); + } + } +#ifndef XQUEUE_ASYNC + pipe(xquePipe); + fcntl(xquePipe[0],F_SETFL,fcntl(xquePipe[0],F_GETFL,0)|O_NDELAY); + fcntl(xquePipe[1],F_SETFL,fcntl(xquePipe[1],F_GETFL,0)|O_NDELAY); +#endif + was_here = TRUE; + } + + if (xf86Info.mouseDev->xqueSema++ == 0) + { +#ifdef XQUEUE_ASYNC + (void) signal(SIGUSR2, (void (*)()) xf86XqueRequest); +#else + (void) signal(SIGUSR2, (void (*)()) xf86XqueSignal); +#endif + xqueMode.qsize = 64; /* max events */ + xqueMode.signo = SIGUSR2; + ioctl(xf86Info.consoleFd, KDQUEMODE, NULL); + + if (ioctl(xf86Info.consoleFd, KDQUEMODE, &xqueMode) < 0) { + Error ("Cannot set KDQUEMODE"); + /* CONSTCOND */ + return (!Success); + } + + XqueQaddr = (xqEventQueue *)xqueMode.qaddr; + XqueQaddr->xq_sigenable = 1; /* UNLOCK */ + } + + return(Success); +} + + + +/* + * xf86XqueDisable -- + * disable the handling of the Xque + */ + +static int +xf86XqueDisable() +{ + if (xf86Info.mouseDev->xqueSema-- == 1) + { + + XqueQaddr->xq_sigenable = 0; /* LOCK */ + + if (ioctl(xf86Info.consoleFd, KDQUEMODE, NULL) < 0) { + Error ("Cannot unset KDQUEMODE"); + /* CONSTCOND */ + return (!Success); + } + } + + return(Success); +} + + + +/* + * xf86XqueMseProc -- + * Handle the initialization, etc. of a mouse + */ + +int +xf86XqueMseProc(pPointer, what) + DeviceIntPtr pPointer; + int what; +{ + MouseDevPtr mouse = MOUSE_DEV(pPointer); + unchar map[4]; + int ret; + + mouse->device = pPointer; + + switch (what) + { + case DEVICE_INIT: + + pPointer->public.on = FALSE; + + map[1] = 1; + map[2] = 2; + map[3] = 3; + InitPointerDeviceStruct((DevicePtr)pPointer, + map, + 3, + miPointerGetMotionEvents, + (PtrCtrlProcPtr)xf86MseCtrl, + miPointerGetMotionBufferSize()); + break; + + case DEVICE_ON: + mouse->lastButtons = 0; + mouse->emulateState = 0; + pPointer->public.on = TRUE; + ret = xf86XqueEnable(); +#ifndef XQUEUE_ASYNC + if (xquePipe[0] != -1) + AddEnabledDevice(xquePipe[0]); +#endif + return(ret); + + case DEVICE_CLOSE: + case DEVICE_OFF: + pPointer->public.on = FALSE; + ret = xf86XqueDisable(); +#ifndef XQUEUE_ASYNC + if (xquePipe[0] != -1) + RemoveEnabledDevice(xquePipe[0]); +#endif + return(ret); + } + + return Success; +} + + + +/* + * xf86XqueKbdProc -- + * Handle the initialization, etc. of a keyboard. + */ + +int +xf86XqueKbdProc (pKeyboard, what) + DeviceIntPtr pKeyboard; /* Keyboard to manipulate */ + int what; /* What to do to it */ +{ + KeySymsRec keySyms; + CARD8 modMap[MAP_LENGTH]; + + switch (what) { + + case DEVICE_INIT: + + xf86KbdGetMapping(&keySyms, modMap); + + /* + * Get also the initial led settings + */ + ioctl(xf86Info.consoleFd, KDGETLED, &xf86Info.leds); + + /* + * Perform final initialization of the system private keyboard + * structure and fill in various slots in the device record + * itself which couldn't be filled in before. + */ + pKeyboard->public.on = FALSE; + +#ifdef XKB + if (noXkbExtension) { +#endif + InitKeyboardDeviceStruct((DevicePtr)xf86Info.pKeyboard, + &keySyms, + modMap, + xf86KbdBell, + (KbdCtrlProcPtr)xf86KbdCtrl); +#ifdef XKB + } else { + XkbComponentNamesRec names; + if (XkbInitialMap) { + if ((xf86Info.xkbkeymap = strchr(XkbInitialMap, '/')) != NULL) + xf86Info.xkbkeymap++; + else + xf86Info.xkbkeymap = XkbInitialMap; + } + if (xf86Info.xkbkeymap) { + names.keymap = xf86Info.xkbkeymap; + names.keycodes = NULL; + names.types = NULL; + names.compat = NULL; + names.symbols = NULL; + names.geometry = NULL; + } else { + names.keymap = NULL; + names.keycodes = xf86Info.xkbkeycodes; + names.types = xf86Info.xkbtypes; + names.compat = xf86Info.xkbcompat; + names.symbols = xf86Info.xkbsymbols; + names.geometry = xf86Info.xkbgeometry; + } + if ((xf86Info.xkbkeymap || xf86Info.xkbcomponents_specified) + && (xf86Info.xkbmodel == NULL || xf86Info.xkblayout == NULL)) { + xf86Info.xkbrules = NULL; + } + XkbSetRulesDflts(xf86Info.xkbrules, xf86Info.xkbmodel, + xf86Info.xkblayout, xf86Info.xkbvariant, + xf86Info.xkboptions); + XkbInitKeyboardDeviceStruct(pKeyboard, + &names, + &keySyms, + modMap, + xf86KbdBell, + (KbdCtrlProcPtr)xf86KbdCtrl); + } +#endif + + xf86InitKBD(TRUE); + break; + + case DEVICE_ON: + pKeyboard->public.on = TRUE; + xf86InitKBD(FALSE); + return(xf86XqueEnable()); + + case DEVICE_CLOSE: + case DEVICE_OFF: + pKeyboard->public.on = FALSE; + return(xf86XqueDisable()); + } + + return (Success); +} + + +/* + * xf86XqueEvents -- + * Get some events from our queue. Nothing to do here ... + */ + +void +xf86XqueEvents() +{ +} + +#endif /* XQUEUE */ diff --git a/hw/xfree86/os-support/xf86_OSlib.h b/hw/xfree86/os-support/xf86_OSlib.h new file mode 100644 index 000000000..72722a2c8 --- /dev/null +++ b/hw/xfree86/os-support/xf86_OSlib.h @@ -0,0 +1,533 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86_OSlib.h,v 3.36.2.5 1998/02/15 16:09:30 hohndel Exp $ */ +/* + * Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1992 by David Dawes + * Copyright 1992 by Jim Tsillas + * Copyright 1992 by Rich Murphey + * Copyright 1992 by Robert Baron + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by Vrije Universiteit, The Netherlands + * Copyright 1993 by David Wexelblat + * Copyright 1994, 1996 by Holger Veit + * Copyright 1994, 1995 by The XFree86 Project, Inc + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 the above listed copyright holders + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS 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. + * + */ +/* $Xorg: xf86_OSlib.h,v 1.3 2000/08/17 19:51:20 cpqbld Exp $ */ + +#ifndef _XF86_OSLIB_H +#define _XF86_OSLIB_H + +#include +#include + +#include "compiler.h" + +#if defined(MACH386) || defined(__OSF__) +# undef NULL +#endif /* MACH386 || __OSF__ */ + +#include +#include + +/**************************************************************************/ +/* SYSV386 (SVR3, SVR4) */ +/**************************************************************************/ +#if defined(SYSV) || defined(SVR4) +# ifdef SCO325 +# define _SVID3 +# endif +# include +# include +# include +# include +# include +# if defined(SCO) || defined(ISC) +# include +# endif + +# include + +# if defined(_NEED_SYSI86) +# include +# if !(defined (sun) && defined (i386) && defined (SVR4)) +# include +# endif +# include +# include +# include +# if defined(SVR4) && !defined(sun) +# include +# endif /* SVR4 && !sun */ +# include +# if defined(sun) && defined (i386) && defined (SVR4) +# include +# endif +# endif /* _NEED_SYSI86 */ + +#if defined(HAS_SVR3_MMAPDRV) +# include +# if !defined(_NEED_SYSI86) +# include +# include +# endif +# include /* MMAP driver header */ +#endif + +# define HAS_USL_VTS +# if !defined(sun) +# include +# endif +# if defined(SCO) +# include +# include +# include +# include +# define LED_CAP 0x01 +# define LED_NUM 0x02 +# define LED_SCR 0x04 +# else /* SCO */ +# include +# include +# include +# endif /* SCO */ + +# if !defined(VT_ACKACQ) +# define VT_ACKACQ 2 +# endif /* !VT_ACKACQ */ + +# if defined(SCO) +# include +# define POSIX_TTY +# endif /* SCO */ + +# if defined(SVR4) || defined(SCO325) +# include +# if !(defined(sun) && defined (i386) && defined (SVR4)) +# define DEV_MEM "/dev/pmem" +# endif +# ifdef SCO325 +# undef DEV_MEM +# define DEV_MEM "/dev/mem" +# endif +# define CLEARDTR_SUPPORT +# define POSIX_TTY +# endif /* SVR4 */ + +# ifdef ISC +# include +# define POSIX_TTY +# endif + +# if defined(sun) && defined (i386) && defined (SVR4) +# define USE_VT_SYSREQ +# define VT_SYSREQ_DEFAULT TRUE +# endif + +# if defined(ATT) && !defined(i386) +# define i386 /* note defined in ANSI C mode */ +# endif /* ATT && !i386 */ + +# if (defined(ATT) || defined(SVR4)) && !(defined(sun) && defined (i386) && defined (SVR4)) && !defined(SCO325) +# define XQUEUE +# include +# endif /* ATT || SVR4 */ + +/* Hack on SVR3 and SVR4 to avoid linking in Xenix or BSD support */ +#if defined (sun) && defined (i386) && defined (SVR4) +extern int xf86_solx86usleep(unsigned long); +# define usleep(usec) xf86_solx86usleep(usec) +#else +# define usleep(usec) syscall(3112, (usec) / 1000 + 1) +#endif /* sun && i386 && SVR4 */ + +# ifdef SYSV +# if !defined(ISC) || defined(ISC202) || defined(ISC22) +# define NEED_STRERROR +# endif +# endif + +#ifndef NULL +# define NULL 0 +#endif + +#endif /* SYSV || SVR4 */ + +/**************************************************************************/ +/* Linux */ +/**************************************************************************/ +#if defined(linux) +# include +# include +# include + +# include +extern int errno; + +# include + +# define HAS_USL_VTS +# include +# include +# include +# define LDGMAP GIO_SCRNMAP +# define LDSMAP PIO_SCRNMAP +# define LDNMAP LDSMAP + +# define CLEARDTR_SUPPORT +# define USE_VT_SYSREQ + +# define POSIX_TTY + +#endif /* linux */ + +/**************************************************************************/ +/* LynxOS AT */ +/**************************************************************************/ +#if defined(Lynx) + +# include +# include +# include +# include +# include +# include +# include + +# include +extern int errno; + +/* smem_create et.al. to access physical memory */ +# include + +/* keyboard types */ +# define KB_84 1 +# define KB_101 2 +# define KB_OTHER 3 + +/* atc drivers ignores argument to VT_RELDISP ioctl */ +# define VT_ACKACQ 2 + +# include +# define POSIX_TTY + +#endif /* Lynx */ + +/**************************************************************************/ +/* 386BSD and derivatives, BSD/386 */ +/**************************************************************************/ + +#if defined(__386BSD__) && (defined(__FreeBSD__) || defined(__NetBSD__)) +# undef __386BSD__ +#endif + +#ifdef CSRG_BASED +# include +# if defined(__OpenBSD__) && defined(_status) +# undef _status +# endif +# include + +# include +# define termio termios +# define POSIX_TTY + +# include +extern int errno; + +# if !defined(LINKKIT) + /* Don't need this stuff for the Link Kit */ +# if defined(__bsdi__) +# include +# define CONSOLE_X_MODE_ON PCCONIOCRAW +# define CONSOLE_X_MODE_OFF PCCONIOCCOOK +# define CONSOLE_X_BELL PCCONIOCBEEP +# else /* __bsdi__ */ +# if defined(__OpenBSD__) +# ifdef PCCONS_SUPPORT +# include +# undef CONSOLE_X_MODE_ON +# undef CONSOLE_X_MODE_OFF +# undef CONSOLE_X_BELL +# endif +# endif +# ifdef CODRV_SUPPORT +# define COMPAT_CO011 +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# include +# else +# include +# endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ */ +# endif /* CODRV_SUPPORT */ +# ifdef SYSCONS_SUPPORT +# define COMPAT_SYSCONS +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# include +# else +# include +# endif /* __FreeBSD__ || __NetBSD__ || defined(__OpenBSD__) */ +# endif /* SYSCONS_SUPPORT */ +# if defined(PCVT_SUPPORT) +# if !defined(SYSCONS_SUPPORT) + /* no syscons, so include pcvt specific header file */ +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# include +# else +# include +# endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ */ +# else /* pcvt and syscons: hard-code the ID magic */ +# define VGAPCVTID _IOWR('V',113, struct pcvtid) + struct pcvtid { + char name[16]; + int rmajor, rminor; + }; +# endif /* PCVT_SUPPORT && SYSCONS_SUPPORT */ +# endif /* PCVT_SUPPORT */ +# if defined(__FreeBSD__) +# undef MOUSE_GETINFO +# include +# endif + /* Include these definitions in case ioctl_pc.h didn't get included */ +# ifndef CONSOLE_X_MODE_ON +# define CONSOLE_X_MODE_ON _IO('t',121) +# endif +# ifndef CONSOLE_X_MODE_OFF +# define CONSOLE_X_MODE_OFF _IO('t',122) +# endif +# ifndef CONSOLE_X_BELL +# define CONSOLE_X_BELL _IOW('t',123,int[2]) +# endif +# endif /* __bsdi__ */ +# endif /* !LINKKIT */ + +# include +# include +# include + +# if defined(__bsdi__) +# include +# if (_BSDI_VERSION < 199510) +# include +# endif +# endif /* __bsdi__ */ + +# define CLEARDTR_SUPPORT + +# if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) +# define USE_VT_SYSREQ +# endif + +# ifndef NULL +# define NULL 0 +# endif + +#endif /* CSRG_BASED */ + +/**************************************************************************/ +/* Mach and OSF/1 */ +/**************************************************************************/ +#if defined(MACH386) || defined(__OSF__) +# include + +# include + +# include +extern int errno; + +# if defined(__OSF__) +# include +# include +# else /* __OSF__ */ +# if !defined(__STDC__) +# define __STDC__ 1 +# include +# include +# undef __STDC__ +# else /* !__STDC__ */ +# include +# include +# endif /* !__STDC__ */ +# include +# define SEEK_SET L_SET +# endif /* __OSF__ */ + +# ifdef MACH386 +# define NEED_STRERROR +# endif + +# include +# include +# define MOUSE_PROTOCOL_IN_KERNEL + +#endif /* MACH386 || __OSF__ */ + +/**************************************************************************/ +/* Minix */ +/**************************************************************************/ +#if defined(MINIX) +# include +# include + +# include +# define termio termios +# define POSIX_TTY + +# include + +# include +# include +# include +# include + +# include + +#endif /* MINIX */ + +/**************************************************************************/ +/* Amoeba */ +/**************************************************************************/ +#if defined(AMOEBA) +# define port am_port_t +# include +# include +# include +# include +# include +# include +# include +# include +# undef port + +# undef _POSIX_SOURCE /* to get the BSD-compatible symbols */ +# include + + /* keyboard types */ +# define KB_84 1 +# define KB_101 2 +# define KB_OTHER 3 + +extern capability iopcap; +# define MOUSE_PROTOCOL_IN_KERNEL + +#endif /* AMOEBA */ + +/**************************************************************************/ +/* OS/2 */ +/**************************************************************************/ +/* currently OS/2 with EMX/GCC compiler only */ +#if defined(__EMX__) +# include +# include +# include + +/* I would have liked to have this included here always, but + * it causes clashes for BYTE and BOOL with Xmd.h, which is too dangerous. + * So I'll include it in place where I know it does no harm. + */ +#if defined(I_NEED_OS2_H) +# undef BOOL +# undef BYTE +# include +#endif + + /* keyboard types */ +# define KB_84 1 +# define KB_101 2 +/* could detect more keyboards */ +# define KB_OTHER 3 + + /* LEDs */ +# define LED_CAP 0x40 +# define LED_NUM 0x20 +# define LED_SCR 0x10 + + /* mouse driver */ +# define OSMOUSE_ONLY +# define MOUSE_PROTOCOL_IN_KERNEL + +extern char* __XOS2RedirRoot(char*); + +#endif + +/**************************************************************************/ +/* Generic */ +/**************************************************************************/ + +/* + * Hack originally for ISC 2.2 POSIX headers, but may apply elsewhere, + * and it's safe, so just do it. + */ +#if !defined(O_NDELAY) && defined(O_NONBLOCK) +# define O_NDELAY O_NONBLOCK +#endif /* !O_NDELAY && O_NONBLOCK */ + +#if !defined(MAXHOSTNAMELEN) +# define MAXHOSTNAMELEN 32 +#endif /* !MAXHOSTNAMELEN */ + +#if !defined(X_NOT_POSIX) +# if defined(_POSIX_SOURCE) +# include +# else +# define _POSIX_SOURCE +# include +# undef _POSIX_SOURCE +# endif /* _POSIX_SOURCE */ +#endif /* !X_NOT_POSIX */ +#if !defined(PATH_MAX) +# if defined(MAXPATHLEN) +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 1024 +# endif /* MAXPATHLEN */ +#endif /* !PATH_MAX */ + +#ifdef NEED_STRERROR +# ifndef strerror +extern char *sys_errlist[]; +extern int sys_nerr; +# define strerror(n) \ + ((n) >= 0 && (n) < sys_nerr) ? sys_errlist[n] : "unknown error" +# endif /* !strerror */ +#endif /* NEED_STRERROR */ + +#if defined(ISC) || defined(Lynx) +#define rint(x) RInt(x) +double RInt( +#if NeedFunctionPrototypes + double x +#endif +); +#endif + +#ifndef VT_SYSREQ_DEFAULT +#define VT_SYSREQ_DEFAULT FALSE +#endif + +#ifdef OSMOUSE_ONLY +# ifndef MOUSE_PROTOCOL_IN_KERNEL +# define MOUSE_PROTOCOL_IN_KERNEL +# endif +#endif + +#include "xf86_OSproc.h" + +#endif /* _XF86_OSLIB_H */ diff --git a/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h new file mode 100644 index 000000000..9f5c49e27 --- /dev/null +++ b/hw/xfree86/os-support/xf86_OSproc.h @@ -0,0 +1,394 @@ +/* $Xorg: xf86_OSproc.h,v 1.3 2000/08/17 19:51:20 cpqbld Exp $ */ +/* + * Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1992 by David Dawes + * Copyright 1992 by Jim Tsillas + * Copyright 1992 by Rich Murphey + * Copyright 1992 by Robert Baron + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by Vrije Universiteit, The Netherlands + * Copyright 1993 by David Wexelblat + * Copyright 1994, 1996 by Holger Veit + * Copyright 1994, 1995 by The XFree86 Project, Inc + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 the above listed copyright holders + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS 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. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h,v 3.0.2.1 1998/02/07 14:27:24 dawes Exp $ */ + +#ifndef _XF86_OSPROC_H +#define _XF86_OSPROC_H + +/* + * The actual prototypes have been pulled into this seperate file so + * that they can can be used without pulling in all of the OS specific + * stuff like sys/stat.h, etc. This casues problem for loadable modules. + */ + +/* The Region arg to xf86[Un]Map* */ +#define NUM_REGIONS 4 +#define VGA_REGION 0 +#define LINEAR_REGION 1 +#define EXTENDED_REGION 2 +#define MMIO_REGION 3 + +#ifndef NO_OSLIB_PROTOTYPES +/* + * This is to prevent re-entrancy to FatalError() when aborting. + * Anything that can be called as a result of AbortDDX() should use this + * instead of FatalError(). (xf86Exiting gets set to TRUE the first time + * AbortDDX() is called.) + */ + +extern Bool xf86Exiting; + +#define xf86FatalError(a, b) \ + if (xf86Exiting) { \ + ErrorF(a, b); \ + return; \ + } else FatalError(a, b) + +/***************************************************************************/ +/* Prototypes */ +/***************************************************************************/ + +#include + +_XFUNCPROTOBEGIN + +/* xf86_Util.c */ +extern int StrCaseCmp( +#if NeedFunctionPrototypes + const char *, + const char * +#endif +); + +/* OS-support layer */ +extern void xf86OpenConsole( +#if NeedFunctionPrototypes + void +#endif +); +extern void xf86CloseConsole( +#if NeedFunctionPrototypes + void +#endif +); +extern Bool xf86VTSwitchPending( +#if NeedFunctionPrototypes + void +#endif +); +extern Bool xf86VTSwitchAway( +#if NeedFunctionPrototypes + void +#endif +); +extern Bool xf86VTSwitchTo( +#if NeedFunctionPrototypes + void +#endif +); +extern Bool xf86LinearVidMem( +#if NeedFunctionPrototypes + void +#endif +); +extern pointer xf86MapVidMem( +#if NeedFunctionPrototypes + int, + int, + pointer, + unsigned long +#endif +); +extern void xf86UnMapVidMem( +#if NeedFunctionPrototypes + int, + int, + pointer, + unsigned long +#endif +); +#if defined(__alpha__) +/* entry points for SPARSE memory access routines */ +extern pointer xf86MapVidMemSparse( +#if NeedFunctionPrototypes + int, + int, + pointer, + unsigned long +#endif +); +extern void xf86UnMapVidMemSparse( +#if NeedFunctionPrototypes + int, + int, + pointer, + unsigned long +#endif +); +extern int xf86ReadSparse8( +#if NeedFunctionPrototypes + pointer, + unsigned long +#endif +); +extern int xf86ReadSparse16( +#if NeedFunctionPrototypes + pointer, + unsigned long +#endif +); +extern int xf86ReadSparse32( +#if NeedFunctionPrototypes + pointer, + unsigned long +#endif +); +extern void xf86WriteSparse8( +#if NeedFunctionPrototypes + int, + pointer, + unsigned long +#endif +); +extern void xf86WriteSparse16( +#if NeedFunctionPrototypes + int, + pointer, + unsigned long +#endif +); +extern void xf86WriteSparse32( +#if NeedFunctionPrototypes + int, + pointer, + unsigned long +#endif +); +#endif /* __alpha__ */ +extern void xf86MapDisplay( +#if NeedFunctionPrototypes + int, + int +#endif +); +extern void xf86UnMapDisplay( +#if NeedFunctionPrototypes + int, + int +#endif +); +extern int xf86ReadBIOS( +#if NeedFunctionPrototypes + unsigned long, + unsigned long, + unsigned char *, + int +#endif +); +extern void xf86ClearIOPortList( +#if NeedFunctionPrototypes + int +#endif +); +extern void xf86AddIOPorts( +#if NeedFunctionPrototypes + int, + int, + unsigned * +#endif +); +void xf86EnableIOPorts( +#if NeedFunctionPrototypes + int +#endif +); +void xf86DisableIOPorts( +#if NeedFunctionPrototypes + int +#endif +); +void xf86DisableIOPrivs( +#if NeedFunctionPrototypes + void +#endif +); +extern Bool xf86DisableInterrupts( +#if NeedFunctionPrototypes + void +#endif +); +extern void xf86EnableInterrupts( +#if NeedFunctionPrototypes + void +#endif +); +extern int xf86ProcessArgument( +#if NeedFunctionPrototypes + int, + char **, + int +#endif +); +extern void xf86UseMsg( +#if NeedFunctionPrototypes + void +#endif +); +extern void xf86SoundKbdBell( +#if NeedFunctionPrototypes + int, + int, + int +#endif +); +extern void xf86SetKbdLeds( +#if NeedFunctionPrototypes + int +#endif +); +extern int xf86GetKbdLeds( +#if NeedFunctionPrototypes + void +#endif +); +extern void xf86SetKbdRepeat( +#if NeedFunctionPrototypes + char +#endif +); +extern void xf86KbdInit( +#if NeedFunctionPrototypes + void +#endif +); +extern int xf86KbdOn( +#if NeedFunctionPrototypes + void +#endif +); +extern int xf86KbdOff( +#if NeedFunctionPrototypes + void +#endif +); +extern void xf86KbdEvents( +#if NeedFunctionPrototypes + void +#endif +); +extern void xf86SetMouseSpeed( +#if NeedFunctionPrototypes + MouseDevPtr, + int, + int, + unsigned +#endif +); +extern void xf86MouseInit( +#if NeedFunctionPrototypes + MouseDevPtr +#endif +); +extern int xf86MouseOn( +#if NeedFunctionPrototypes + MouseDevPtr +#endif +); +extern int xf86MouseOff( +#if NeedFunctionPrototypes + MouseDevPtr, + Bool +#endif +); +extern void xf86MouseEvents( +#if NeedFunctionPrototypes + MouseDevPtr +#endif +); +extern int xf86FlushInput( +#if NeedFunctionPrototypes + int +#endif +); +extern int xf86XqueKbdProc( +#if NeedFunctionPrototypes + DeviceIntPtr, + int +#endif +); +extern int xf86XqueMseProc( +#if NeedFunctionPrototypes + DeviceIntPtr, + int +#endif +); +extern void xf86XqueEvents( +#if NeedFunctionPrototypes + void +#endif +); + + +/* These are privates */ +extern void xf86InitPortLists( +#if NeedFunctionPrototypes + unsigned **, + int *, + Bool *, + Bool *, + int +#endif +); +extern Bool xf86CheckPorts( +#if NeedFunctionPrototypes + unsigned, + unsigned **, + int *, + Bool *, + int +#endif +); +extern int xf86OsMouseProc( +#if NeedFunctionPrototypes + DeviceIntPtr, + int +#endif +); +extern void xf86OsMouseEvents( +#if NeedFunctionPrototypes + void +#endif +); +extern void xf86OsMouseOption( +#if NeedFunctionPrototypes + int, + pointer /* gets cast to LexPtr later, saves include file hassles */ +#endif +); + +_XFUNCPROTOEND +#endif /* NO_OSLIB_PROTOTYPES */ + +#endif /* _XF86_OSPROC_H */ diff --git a/hw/xfree86/utils/kbd_mode/bsd-kbd_mode.c b/hw/xfree86/utils/kbd_mode/bsd-kbd_mode.c new file mode 100644 index 000000000..37c23cfea --- /dev/null +++ b/hw/xfree86/utils/kbd_mode/bsd-kbd_mode.c @@ -0,0 +1,96 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/etc/kbd_mode.c,v 3.5 1996/12/23 06:47:13 dawes Exp $ */ + + +/* Keyboard mode control program for 386BSD */ + + +/* $Xorg: kbd_mode.c,v 1.3 2000/08/17 19:51:09 cpqbld Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "X.h" +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86_OSlib.h" + +static int fd; + +void +msg (char* s) +{ + perror (s); + close (fd); + exit (-1); +} + +int +main(int argc, char** argv) +{ +#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + vtmode_t vtmode; +#endif + Bool syscons = FALSE; + + if ((fd = open("/dev/vga",O_RDONLY,0)) <0) + msg ("Cannot open /dev/vga"); + +#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + /* Check if syscons */ + if (ioctl(fd, VT_GETMODE, &vtmode) >= 0) + syscons = TRUE; +#endif + + if (0 == strcmp (argv[1], "-u")) + { + if (syscons) + { +#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + ioctl (fd, KDSKBMODE, K_RAW); +#endif + } + else + { + if (ioctl (fd, CONSOLE_X_MODE_ON, 0) < 0) + { + close (fd); + exit (0); /* Assume codrv, so nothing to do */ + } + } + } + else if (0 == strcmp (argv[1], "-a")) + { + if (syscons) + { +#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) + ioctl (fd, KDSKBMODE, K_XLATE); +#endif + } + else + { + if (ioctl (fd, CONSOLE_X_MODE_OFF, 0) < 0) + { + close (fd); + exit (0); /* Assume codrv, so nothing to do */ + } + } + } + else + { + close (fd); + fprintf (stderr,"Usage: %s [-u|-a]\n",argv[0]); + fprintf (stderr,"-u for sending up down key events in x mode.\n"); + fprintf (stderr,"-a for sending ascii keys in normal use.\n"); + exit (-1); + } + close (fd); + exit (0); +} diff --git a/hw/xfree86/utils/kbd_mode/bsd-kbd_mode.man.pre b/hw/xfree86/utils/kbd_mode/bsd-kbd_mode.man.pre new file mode 100644 index 000000000..c959d2332 --- /dev/null +++ b/hw/xfree86/utils/kbd_mode/bsd-kbd_mode.man.pre @@ -0,0 +1,36 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/etc/kbd_mode.man,v 3.2 1996/12/23 06:47:14 dawes Exp $ +.TH KBD_MODE 1 "Release 6.3 (XFree86 3.2)" "X Version 11" +.SH NAME +kbd_mode \- recover the PC console keyboard +.SH SYNOPSIS +.B kbd_mode +[ -a -u ] +.SH DESCRIPTION +.I Kbd_mode +resets the PC console keyboard to a rational state. +.SH OPTIONS +The following options are supported: +.TP 8 +.B \-a +Set the keyboard so that ASCII characters are read from the console. +.TP 8 +.B \-u +Set the keyboard so that undecoded keyboard values are read from the +console. +.SH EXAMPLES +If the server crashes or otherwise fails to put the keyboard back in +ascii mode when it exits, it can leave your keyboard dead. If you are +able to login remotely, you can reset it typing: +.sp + kbd_mode -a +.sp +.PP +Conversely, changing the keyboard to ascii mode while the server is +running will make the keyboard appear to be dead while the the mouse +continues to work. Again, if you are able to login remotely, you can +reset it typing: +.sp + kbd_mode -u +.sp + +.\" $Xorg: kbd_mode.man,v 1.3 2000/08/17 19:51:10 cpqbld Exp $ diff --git a/hw/xfree86/utils/kbd_mode/sun-kbd_mode.c b/hw/xfree86/utils/kbd_mode/sun-kbd_mode.c new file mode 100644 index 000000000..294787354 --- /dev/null +++ b/hw/xfree86/utils/kbd_mode/sun-kbd_mode.c @@ -0,0 +1,150 @@ +/* $Xorg: kbd_mode.c,v 1.3 2000/08/17 19:48:29 cpqbld Exp $ */ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ + +#ifndef lint +static char sccsid[] = "@(#)kbd_mode.c 7.1 87/04/13"; +#endif + +/* + * Copyright 1986 by Sun Microsystems, Inc. + * + * kbd_mode: set keyboard encoding mode + */ + +#include +#include +#include +#if defined(SVR4) || defined(__bsdi_) +#include +#ifndef __bsdi__ +#include +#include +#else +#include +#include +#include +#endif +#else +#ifndef CSRG_BASED +#include +#include +#else +#include +#include +#endif +#endif +#include + +static void die(), usage(); +static int kbd_fd; + +main(argc, argv) + int argc; + char** argv; +{ + int code, translate, direct = -1; + char led; + int click; + + if ((kbd_fd = open("/dev/kbd", O_RDONLY, 0)) < 0) { + die("Couldn't open /dev/kbd"); + } + argc--; argv++; + if (argc-- && **argv == '-') { + code = *(++*argv); + } else { + usage(); + } + switch (code) { + case 'a': + case 'A': + translate = TR_ASCII; + direct = 0; + break; + case 'e': + case 'E': + translate = TR_EVENT; + break; + case 'n': + case 'N': + translate = TR_NONE; + break; + case 'u': + case 'U': + translate = TR_UNTRANS_EVENT; + break; + default: + usage(); + } +#ifdef KIOCSLED + led = 0; + if (ioctl(kbd_fd, KIOCSLED, &led)) + die("Couldn't set LEDs"); +#endif +#ifdef KIOCCMD + click = KBD_CMD_NOCLICK; + if (ioctl(kbd_fd, KIOCCMD, &click)) + die("Couldn't set click"); +#endif + if (ioctl(kbd_fd, KIOCTRANS, (caddr_t) &translate)) + die("Couldn't set translation"); + if (direct != -1 && ioctl(kbd_fd, KIOCSDIRECT, (caddr_t) &direct)) + die("Couldn't set redirect"); + return 0; +} + +static void +die(msg) + char *msg; +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +static void +usage() +{ + int translate; + + if (ioctl(kbd_fd, KIOCGTRANS, (caddr_t) &translate)) { + die("Couldn't inquire current translation"); + } + fprintf(stderr, "kbd_mode {-a | -e | -n | -u }\n"); + fprintf(stderr, "\tfor ascii, encoded (normal) SunView events,\n"); + fprintf(stderr, " \tnon-encoded, or unencoded SunView events, resp.\n"); + fprintf(stderr, "Current mode is %s.\n", + ( translate == 0 ? "n (non-translated bytes)" : + ( translate == 1 ? "a (ascii bytes)" : + ( translate == 2 ? "e (encoded events)" : + /* translate == 3 */ "u (unencoded events)")))); + exit(1); +} + + diff --git a/hw/xfree86/utils/kbd_mode/sun-kbd_mode.man.pre b/hw/xfree86/utils/kbd_mode/sun-kbd_mode.man.pre new file mode 100644 index 000000000..88c4a89b4 --- /dev/null +++ b/hw/xfree86/utils/kbd_mode/sun-kbd_mode.man.pre @@ -0,0 +1,50 @@ +.\" $Xorg: kbd_mode.man,v 1.4 2001/02/09 02:04:43 xorgcvs Exp $ +.\" Copyright 1987 Sun Microsystems, Inc. +.\" Copyright 1993, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.TH KBD_MODE 1 "Release 6.4" "X Version 11" +.SH NAME +kbd_mode \- recover the Sun console keyboard +.SH SYNOPSIS +.B kbd_mode +[ -a -e -n -u ] +.SH DESCRIPTION +.I Kbd_mode +resets the Sun console keyboard to a rational state. +.SH OPTIONS +The following options are supported, see \fIkb(4S)\fP for details: +.TP 8 +.B \-a +Causes ASCII to be reported. +.TP 8 +.B \-e +Causes \fIFirm_events\fP to be reported. +.TP 8 +.B \-n +Causes up/down key codes to be reported. +.TP 8 +.B \-u +Causes undecoded keyboard values to be reported. +.SH SEE ALSO +kb(4S) diff --git a/hw/xfree86/utils/scanpci/scanpci.c b/hw/xfree86/utils/scanpci/scanpci.c new file mode 100644 index 000000000..f3a142fba --- /dev/null +++ b/hw/xfree86/utils/scanpci/scanpci.c @@ -0,0 +1,1790 @@ +/* $Xorg: scanpci.c,v 1.3 2000/08/17 19:51:10 cpqbld Exp $ */ +/* + * name: scanpci.c + * + * purpose: This program will scan for and print details of + * devices on the PCI bus. + + * author: Robin Cutshaw (robin@xfree86.org) + * + * supported O/S's: SVR4, UnixWare, SCO, Solaris, + * FreeBSD, NetBSD, 386BSD, BSDI BSD/386, + * Linux, Mach/386, ISC + * DOS (WATCOM 9.5 compiler) + * + * compiling: [g]cc scanpci.c -o scanpci + * for SVR4 (not Solaris), UnixWare use: + * [g]cc -DSVR4 scanpci.c -o scanpci + * for DOS, watcom 9.5: + * wcc386p -zq -omaxet -7 -4s -s -w3 -d2 name.c + * and link with PharLap or other dos extender for exe + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/etc/scanpci.c,v 3.34.2.10 1998/02/27 17:13:22 robin Exp $ */ + +/* + * Copyright 1995 by Robin Cutshaw + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 the above listed copyright holder(s) + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holder(s) make(s) no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + * + */ + +#if defined(__SVR4) +#if !defined(SVR4) +#define SVR4 +#endif +#endif + +#ifdef __EMX__ +#define INCL_DOSFILEMGR +#include +#endif + +#include +#include +#if defined(SVR4) +#if defined(sun) +#define __EXTENSIONS__ +#endif +#include +#include +#if defined(NCR) +#define __STDC +#include +#undef __STDC +#else +#include +#endif +#if defined(__SUNPRO_C) || defined(sun) || defined(__sun) +#include +#else +#include +#endif +#include +#endif +#if defined(__FreeBSD__) || defined(__386BSD__) +#include +#include +#ifndef GCCUSESGAS +#define GCCUSESGAS +#endif +#endif +#if defined(__NetBSD__) +#include +#include +#include +#ifndef GCCUSESGAS +#define GCCUSESGAS +#endif +#endif +#if defined(__bsdi__) +#include +#include +#include +#ifndef GCCUSESGAS +#define GCCUSESGAS +#endif +#endif +#if defined(SCO) || defined(ISC) +#ifndef ISC +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#endif +#if defined(Lynx_22) +#ifndef GCCUSESGAS +#define GCCUSESGAS +#endif +#endif + + +#if defined(__WATCOMC__) + +#include +void outl(unsigned port, unsigned data); +#pragma aux outl = "out dx, eax" parm [dx] [eax]; +void outb(unsigned port, unsigned data); +#pragma aux outb = "out dx, al" parm [dx] [eax]; +unsigned inl(unsigned port); +#pragma aux inl = "in eax, dx" parm [dx]; +unsigned inb(unsigned port); +#pragma aux inb = "xor eax,eax" "in al, dx" parm [dx]; + +#else /* __WATCOMC__ */ + +#if defined(__GNUC__) + +#if !defined(__alpha__) && !defined(__powerpc__) +#if defined(GCCUSESGAS) +#define OUTB_GCC "outb %0,%1" +#define OUTL_GCC "outl %0,%1" +#define INB_GCC "inb %1,%0" +#define INL_GCC "inl %1,%0" +#else +#define OUTB_GCC "out%B0 (%1)" +#define OUTL_GCC "out%L0 (%1)" +#define INB_GCC "in%B0 (%1)" +#define INL_GCC "in%L0 (%1)" +#endif /* GCCUSESGAS */ + +static void outb(unsigned short port, unsigned char val) { + __asm__ __volatile__(OUTB_GCC : :"a" (val), "d" (port)); } +static void outl(unsigned short port, unsigned long val) { + __asm__ __volatile__(OUTL_GCC : :"a" (val), "d" (port)); } +static unsigned char inb(unsigned short port) { unsigned char ret; + __asm__ __volatile__(INB_GCC : "=a" (ret) : "d" (port)); return ret; } +static unsigned long inl(unsigned short port) { unsigned long ret; + __asm__ __volatile__(INL_GCC : "=a" (ret) : "d" (port)); return ret; } + +#endif /* !defined(__alpha__) && !defined(__powerpc__) */ +#else /* __GNUC__ */ + +#if defined(__STDC__) && (__STDC__ == 1) +# if !defined(NCR) +# define asm __asm +# endif +#endif + +#if defined(__SUNPRO_C) +/* + * This section is a gross hack in if you tell anyone that I wrote it, + * I'll deny it. :-) + * The leave/ret instructions are the big hack to leave %eax alone on return. + */ + unsigned char inb(int port) { + asm(" movl 8(%esp),%edx"); + asm(" subl %eax,%eax"); + asm(" inb (%dx)"); + asm(" leave"); + asm(" ret"); + } + + unsigned short inw(int port) { + asm(" movl 8(%esp),%edx"); + asm(" subl %eax,%eax"); + asm(" inw (%dx)"); + asm(" leave"); + asm(" ret"); + } + + unsigned long inl(int port) { + asm(" movl 8(%esp),%edx"); + asm(" inl (%dx)"); + asm(" leave"); + asm(" ret"); + } + + void outb(int port, unsigned char value) { + asm(" movl 8(%esp),%edx"); + asm(" movl 12(%esp),%eax"); + asm(" outb (%dx)"); + } + + void outw(int port, unsigned short value) { + asm(" movl 8(%esp),%edx"); + asm(" movl 12(%esp),%eax"); + asm(" outw (%dx)"); + } + + void outl(int port, unsigned long value) { + asm(" movl 8(%esp),%edx"); + asm(" movl 12(%esp),%eax"); + asm(" outl (%dx)"); + } +#else + +#if defined(SVR4) +# if !defined(__USLC__) +# define __USLC__ +# endif +#endif + +#ifndef SCO325 +# include +#else +# include "scoasm.h" +#endif + +#endif /* SUNPRO_C */ + +#endif /* __GNUC__ */ +#endif /* __WATCOMC__ */ + + +#if defined(__alpha__) +#if defined(linux) +#include +#define BUS(tag) (((tag)>>16)&0xff) +#define DFN(tag) (((tag)>>8)&0xff) +int pciconfig_read( + unsigned char bus, + unsigned char dfn, + unsigned char off, + unsigned char len, + void * buf) +{ + return __syscall(__NR_pciconfig_read, bus, dfn, off, len, buf); +} +int pciconfig_write( + unsigned char bus, + unsigned char dfn, + unsigned char off, + unsigned char len, + void * buf) +{ + return __syscall(__NR_pciconfig_write, bus, dfn, off, len, buf); +} +#else +Generate compiler error - scanpci unsupported on non-linux alpha platforms +#endif /* linux */ +#endif /* __alpha__ */ +#if defined(Lynx) && defined(__powerpc__) +/* let's mimick the Linux Alpha stuff for LynxOS so we don't have + * to change too much code + */ +#include + +unsigned char *pciConfBase; + +static __inline__ unsigned long +swapl(unsigned long val) +{ + unsigned char *p = (unsigned char *)&val; + return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0)); +} + + +#define BUS(tag) (((tag)>>16)&0xff) +#define DFN(tag) (((tag)>>8)&0xff) + +#define PCIBIOS_DEVICE_NOT_FOUND 0x86 +#define PCIBIOS_SUCCESSFUL 0x00 + +int pciconfig_read( + unsigned char bus, + unsigned char dev, + unsigned char offset, + int len, /* unused, alway 4 */ + unsigned long *val) +{ + unsigned long _val; + unsigned long *ptr; + + dev >>= 3; + if (bus || dev >= 16) { + *val = 0xFFFFFFFF; + return PCIBIOS_DEVICE_NOT_FOUND; + } else { + ptr = (unsigned long *)(pciConfBase + ((1<>= 3; + _val = swapl(val); + if (bus || dev >= 16) { + return PCIBIOS_DEVICE_NOT_FOUND; + } else { + ptr = (unsigned long *)(pciConfBase + ((1< 0) { + pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number; + } + break; + default: + break; + } + if((func==0) && ((pcr._header_type & PCI_MULTIFUNC_DEV) == 0)) { + /* not a multi function device */ + func = 8; + } else { + func++; + } + + if (idx++ >= MAX_PCI_DEVICES) + continue; + + identify_card(&pcr, verbose); + } while( func < 8 ); + } + } while (++pcr._pcibusidx < pcr._pcinumbus); + } + +#if !defined(__alpha__) && !defined(__powerpc__) + /* Now try pci config 2 probe (deprecated) */ + + if ((pcr._configtype == 2) || do_mode2_scan) { + outb(PCI_MODE2_ENABLE_REG, 0xF1); + outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */ + + printf("\nPCI probing configuration type 2\n"); + + pcr._pcibuses[0] = 0; + pcr._pcinumbus = 1; + pcr._pcibusidx = 0; + idx = 0; + + do { + for (pcr._ioaddr = 0xC000; pcr._ioaddr < 0xD000; pcr._ioaddr += 0x0100){ + outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */ + pcr._device_vendor = inl(pcr._ioaddr); + outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */ + + if ((pcr._vendor == 0xFFFF) || (pcr._device == 0xFFFF)) + continue; + if ((pcr._vendor == 0xF0F0) || (pcr._device == 0xF0F0)) + continue; /* catch ASUS P55TP4XE motherboards */ + + printf("\npci bus 0x%x slot at 0x%04x, vendor 0x%04x device 0x%04x\n", + pcr._pcibuses[pcr._pcibusidx], pcr._ioaddr, pcr._vendor, + pcr._device); + + outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */ + pcr._status_command = inl(pcr._ioaddr + 0x04); + pcr._class_revision = inl(pcr._ioaddr + 0x08); + pcr._bist_header_latency_cache = inl(pcr._ioaddr + 0x0C); + pcr._base0 = inl(pcr._ioaddr + 0x10); + pcr._base1 = inl(pcr._ioaddr + 0x14); + pcr._base2 = inl(pcr._ioaddr + 0x18); + pcr._base3 = inl(pcr._ioaddr + 0x1C); + pcr._base4 = inl(pcr._ioaddr + 0x20); + pcr._base5 = inl(pcr._ioaddr + 0x24); + pcr._baserom = inl(pcr._ioaddr + 0x30); + pcr._max_min_ipin_iline = inl(pcr._ioaddr + 0x3C); + pcr._user_config = inl(pcr._ioaddr + 0x40); + outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */ + + /* check for pci-pci bridges (currently we only know Digital) */ + if ((pcr._vendor == 0x1011) && (pcr._device == 0x0001)) + if (pcr._secondary_bus_number > 0) + pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number; + + if (idx++ >= MAX_PCI_DEVICES) + continue; + + identify_card(&pcr, verbose); + } + } while (++pcr._pcibusidx < pcr._pcinumbus); + + outb(PCI_MODE2_ENABLE_REG, 0x00); + } + +#endif /* __alpha__ */ + + disable_os_io(); +} + + +void +identify_card(struct pci_config_reg *pcr, int verbose) +{ + + int i = 0, j, foundit = 0; + + while (pvd[i].vendorname != (char *)NULL) { + if (pvd[i].vendor_id == pcr->_vendor) { + j = 0; + printf(" %s ", pvd[i].vendorname); + while (pvd[i].device[j].devicename != (char *)NULL) { + if (pvd[i].device[j].device_id == pcr->_device) { + printf("%s", pvd[i].device[j].devicename); + foundit = 1; + break; + } + j++; + } + } + if (foundit) + break; + i++; + } + + if (!foundit) + printf(" Device unknown\n"); + else { + printf("\n"); + if (verbose) { + if (pvd[i].device[j].print_func != (void (*)())NULL) { + pvd[i].device[j].print_func(pcr); + return; + } + } + } + + if (verbose) { + if (pcr->_status_command) + printf(" STATUS 0x%04x COMMAND 0x%04x\n", + pcr->_status, pcr->_command); + if (pcr->_class_revision) + printf(" CLASS 0x%02x 0x%02x 0x%02x REVISION 0x%02x\n", + pcr->_base_class, pcr->_sub_class, pcr->_prog_if, + pcr->_rev_id); + if (pcr->_bist_header_latency_cache) + printf(" BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n", + pcr->_bist, pcr->_header_type, pcr->_latency_timer, + pcr->_cache_line_size); + if (pcr->_base0) + printf(" BASE0 0x%08x addr 0x%08x %s\n", + pcr->_base0, pcr->_base0 & (pcr->_base0 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0), + pcr->_base0 & 0x1 ? "I/O" : "MEM"); + if (pcr->_base1) + printf(" BASE1 0x%08x addr 0x%08x %s\n", + pcr->_base1, pcr->_base1 & (pcr->_base1 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0), + pcr->_base1 & 0x1 ? "I/O" : "MEM"); + if (pcr->_base2) + printf(" BASE2 0x%08x addr 0x%08x %s\n", + pcr->_base2, pcr->_base2 & (pcr->_base2 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0), + pcr->_base2 & 0x1 ? "I/O" : "MEM"); + if (pcr->_base3) + printf(" BASE3 0x%08x addr 0x%08x %s\n", + pcr->_base3, pcr->_base3 & (pcr->_base3 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0), + pcr->_base3 & 0x1 ? "I/O" : "MEM"); + if (pcr->_base4) + printf(" BASE4 0x%08x addr 0x%08x %s\n", + pcr->_base4, pcr->_base4 & (pcr->_base4 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0), + pcr->_base4 & 0x1 ? "I/O" : "MEM"); + if (pcr->_base5) + printf(" BASE5 0x%08x addr 0x%08x %s\n", + pcr->_base5, pcr->_base5 & (pcr->_base5 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0), + pcr->_base5 & 0x1 ? "I/O" : "MEM"); + if (pcr->_baserom) + printf(" BASEROM 0x%08x addr 0x%08x %sdecode-enabled\n", + pcr->_baserom, pcr->_baserom & 0xFFFF8000, + pcr->_baserom & 0x1 ? "" : "not-"); + if (pcr->_max_min_ipin_iline) + printf(" MAX_LAT 0x%02x MIN_GNT 0x%02x INT_PIN 0x%02x INT_LINE 0x%02x\n", + pcr->_max_lat, pcr->_min_gnt, + pcr->_int_pin, pcr->_int_line); + if (pcr->_user_config) + printf(" BYTE_0 0x%02x BYTE_1 0x%02x BYTE_2 0x%02x BYTE_3 0x%02x\n", + pcr->_user_config_0, pcr->_user_config_1, + pcr->_user_config_2, pcr->_user_config_3); + } +} + + +void +print_mach64(struct pci_config_reg *pcr) +{ + unsigned long sparse_io = 0; + + if (pcr->_status_command) + printf(" STATUS 0x%04x COMMAND 0x%04x\n", + pcr->_status, pcr->_command); + if (pcr->_class_revision) + printf(" CLASS 0x%02x 0x%02x 0x%02x REVISION 0x%02x\n", + pcr->_base_class, pcr->_sub_class, pcr->_prog_if, pcr->_rev_id); + if (pcr->_bist_header_latency_cache) + printf(" BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n", + pcr->_bist, pcr->_header_type, pcr->_latency_timer, + pcr->_cache_line_size); + if (pcr->_base0) + printf(" APBASE 0x%08x addr 0x%08x\n", + pcr->_base0, pcr->_base0 & (pcr->_base0 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0)); + if (pcr->_base1) + printf(" BLOCKIO 0x%08x addr 0x%08x\n", + pcr->_base1, pcr->_base1 & (pcr->_base1 & 0x1 ? + 0xFFFFFFFC : 0xFFFFFFF0)); + if (pcr->_baserom) + printf(" BASEROM 0x%08x addr 0x%08x %sdecode-enabled\n", + pcr->_baserom, pcr->_baserom & 0xFFFF8000, + pcr->_baserom & 0x1 ? "" : "not-"); + if (pcr->_max_min_ipin_iline) + printf(" MAX_LAT 0x%02x MIN_GNT 0x%02x INT_PIN 0x%02x INT_LINE 0x%02x\n", + pcr->_max_lat, pcr->_min_gnt, pcr->_int_pin, pcr->_int_line); + switch (pcr->_user_config_0 & 0x03) { + case 0: + sparse_io = 0x2ec; + break; + case 1: + sparse_io = 0x1cc; + break; + case 2: + sparse_io = 0x1c8; + break; + } + printf(" SPARSEIO 0x%03x %s %s\n", + sparse_io, pcr->_user_config_0 & 0x04 ? "Block IO enabled" : + "Sparse IO enabled", + pcr->_user_config_0 & 0x08 ? "Disable 0x46E8" : "Enable 0x46E8"); +} + +void +print_i128(struct pci_config_reg *pcr) +{ + if (pcr->_status_command) + printf(" STATUS 0x%04x COMMAND 0x%04x\n", + pcr->_status, pcr->_command); + if (pcr->_class_revision) + printf(" CLASS 0x%02x 0x%02x 0x%02x REVISION 0x%02x\n", + pcr->_base_class, pcr->_sub_class, pcr->_prog_if, pcr->_rev_id); + if (pcr->_bist_header_latency_cache) + printf(" BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n", + pcr->_bist, pcr->_header_type, pcr->_latency_timer, + pcr->_cache_line_size); + printf(" MW0_AD 0x%08x addr 0x%08x %spre-fetchable\n", + pcr->_base0, pcr->_base0 & 0xFFC00000, + pcr->_base0 & 0x8 ? "" : "not-"); + printf(" MW1_AD 0x%08x addr 0x%08x %spre-fetchable\n", + pcr->_base1, pcr->_base1 & 0xFFC00000, + pcr->_base1 & 0x8 ? "" : "not-"); + printf(" XYW_AD(A) 0x%08x addr 0x%08x\n", + pcr->_base2, pcr->_base2 & 0xFFC00000); + printf(" XYW_AD(B) 0x%08x addr 0x%08x\n", + pcr->_base3, pcr->_base3 & 0xFFC00000); + printf(" RBASE_G 0x%08x addr 0x%08x\n", + pcr->_base4, pcr->_base4 & 0xFFFF0000); + printf(" IO 0x%08x addr 0x%08x\n", + pcr->_base5, pcr->_base5 & 0xFFFFFF00); + printf(" RBASE_E 0x%08x addr 0x%08x %sdecode-enabled\n", + pcr->_baserom, pcr->_baserom & 0xFFFF8000, + pcr->_baserom & 0x1 ? "" : "not-"); + if (pcr->_max_min_ipin_iline) + printf(" MAX_LAT 0x%02x MIN_GNT 0x%02x INT_PIN 0x%02x INT_LINE 0x%02x\n", + pcr->_max_lat, pcr->_min_gnt, pcr->_int_pin, pcr->_int_line); +} + +void +print_pcibridge(struct pci_config_reg *pcr) +{ + if (pcr->_status_command) + printf(" STATUS 0x%04x COMMAND 0x%04x\n", + pcr->_status, pcr->_command); + if (pcr->_class_revision) + printf(" CLASS 0x%02x 0x%02x 0x%02x REVISION 0x%02x\n", + pcr->_base_class, pcr->_sub_class, pcr->_prog_if, pcr->_rev_id); + if (pcr->_bist_header_latency_cache) + printf(" BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n", + pcr->_bist, pcr->_header_type, pcr->_latency_timer, + pcr->_cache_line_size); + printf(" PRIBUS 0x%02x SECBUS 0x%02x SUBBUS 0x%02x SECLT 0x%02x\n", + pcr->_primary_bus_number, pcr->_secondary_bus_number, + pcr->_subordinate_bus_number, pcr->_secondary_latency_timer); + printf(" IOBASE: 0x%02x00 IOLIM 0x%02x00 SECSTATUS 0x%04x\n", + pcr->_io_base, pcr->_io_limit, pcr->_secondary_status); + printf(" NOPREFETCH MEMBASE: 0x%08x MEMLIM 0x%08x\n", + pcr->_mem_base, pcr->_mem_limit); + printf(" PREFETCH MEMBASE: 0x%08x MEMLIM 0x%08x\n", + pcr->_prefetch_mem_base, pcr->_prefetch_mem_limit); + printf(" RBASE_E 0x%08x addr 0x%08x %sdecode-enabled\n", + pcr->_baserom, pcr->_baserom & 0xFFFF8000, + pcr->_baserom & 0x1 ? "" : "not-"); + if (pcr->_max_min_ipin_iline) + printf(" MAX_LAT 0x%02x MIN_GNT 0x%02x INT_PIN 0x%02x INT_LINE 0x%02x\n", + pcr->_max_lat, pcr->_min_gnt, pcr->_int_pin, pcr->_int_line); +} + +static int io_fd; +#ifdef __EMX__ +USHORT callgate[3] = {0,0,0}; +#endif + +void +enable_os_io() +{ +#if defined(SVR4) || defined(SCO) || defined(ISC) +#if defined(SI86IOPL) + sysi86(SI86IOPL, 3); +#else + sysi86(SI86V86, V86SC_IOPL, PS_IOPL); +#endif +#endif +#if defined(linux) + iopl(3); +#endif +#if defined(__FreeBSD__) || defined(__386BSD__) || defined(__bsdi__) + if ((io_fd = open("/dev/console", O_RDWR, 0)) < 0) { + perror("/dev/console"); + exit(1); + } +#if defined(__FreeBSD__) || defined(__386BSD__) + if (ioctl(io_fd, KDENABIO, 0) < 0) { + perror("ioctl(KDENABIO)"); + exit(1); + } +#endif +#if defined(__bsdi__) + if (ioctl(io_fd, PCCONENABIOPL, 0) < 0) { + perror("ioctl(PCCONENABIOPL)"); + exit(1); + } +#endif +#endif +#if defined(__NetBSD__) +#if !defined(USE_I386_IOPL) + if ((io_fd = open("/dev/io", O_RDWR, 0)) < 0) { + perror("/dev/io"); + exit(1); + } +#else + if (i386_iopl(1) < 0) { + perror("i386_iopl"); + exit(1); + } +#endif /* USE_I386_IOPL */ +#endif /* __NetBSD__ */ +#if defined(__OpenBSD__) + if (i386_iopl(1) < 0) { + perror("i386_iopl"); + exit(1); + } +#endif /* __OpenBSD__ */ +#if defined(MACH386) + if ((io_fd = open("/dev/iopl", O_RDWR, 0)) < 0) { + perror("/dev/iopl"); + exit(1); + } +#endif +#ifdef __EMX__ + { + HFILE hfd; + ULONG dlen,action; + APIRET rc; + static char *ioDrvPath = "/dev/fastio$"; + + if (DosOpen((PSZ)ioDrvPath, (PHFILE)&hfd, (PULONG)&action, + (ULONG)0, FILE_SYSTEM, FILE_OPEN, + OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT|OPEN_ACCESS_READONLY, + (ULONG)0) != 0) { + fprintf(stderr,"Error opening fastio$ driver...\n"); + fprintf(stderr,"Please install xf86sup.sys in config.sys!\n"); + exit(42); + } + callgate[0] = callgate[1] = 0; + +/* Get callgate from driver for fast io to ports and other stuff */ + + rc = DosDevIOCtl(hfd, (ULONG)0x76, (ULONG)0x64, + NULL, 0, NULL, + (ULONG*)&callgate[2], sizeof(USHORT), &dlen); + if (rc) { + fprintf(stderr,"xf86-OS/2: EnableIOPorts failed, rc=%d, dlen=%d; emergency exit\n", + rc,dlen); + DosClose(hfd); + exit(42); + } + +/* Calling callgate with function 13 sets IOPL for the program */ + + asm volatile ("movl $13,%%ebx;.byte 0xff,0x1d;.long _callgate" + : /*no outputs */ + : /*no inputs */ + : "eax","ebx","ecx","edx","cc"); + + DosClose(hfd); + } +#endif +#if defined(Lynx) && defined(__powerpc__) + pciConfBase = (unsigned char *) smem_create("PCI-CONF", + (char *)0x80800000, 64*1024, SM_READ|SM_WRITE); + if (pciConfBase == (void *) -1) + exit(1); +#endif +} + + +void +disable_os_io() +{ +#if defined(SVR4) || defined(SCO) || defined(ISC) +#if defined(SI86IOPL) + sysi86(SI86IOPL, 0); +#else + sysi86(SI86V86, V86SC_IOPL, 0); +#endif +#endif +#if defined(linux) + iopl(0); +#endif +#if defined(__FreeBSD__) || defined(__386BSD__) + if (ioctl(io_fd, KDDISABIO, 0) < 0) { + perror("ioctl(KDDISABIO)"); + close(io_fd); + exit(1); + } + close(io_fd); +#endif +#if defined(__NetBSD__) +#if !defined(USE_I386_IOPL) + close(io_fd); +#else + if (i386_iopl(0) < 0) { + perror("i386_iopl"); + exit(1); + } +#endif /* NetBSD1_1 */ +#endif /* __NetBSD__ */ +#if defined(__bsdi__) + if (ioctl(io_fd, PCCONDISABIOPL, 0) < 0) { + perror("ioctl(PCCONDISABIOPL)"); + close(io_fd); + exit(1); + } + close(io_fd); +#endif +#if defined(MACH386) + close(io_fd); +#endif +#if defined(Lynx) && defined(__powerpc__) + smem_create(NULL, (char *) pciConfBase, 0, SM_DETACH); + smem_remove("PCI-CONF"); + pciConfBase = NULL; +#endif +} diff --git a/hw/xfree86/utils/xorgconfig/Cards b/hw/xfree86/utils/xorgconfig/Cards new file mode 100644 index 000000000..0412fdd61 --- /dev/null +++ b/hw/xfree86/utils/xorgconfig/Cards @@ -0,0 +1,2003 @@ +# $Xorg: Cards,v 1.3 2000/08/17 19:53:04 cpqbld Exp $ +# This is the database of card definitions used by xf86config. +# Each definition should have a NAME entry, CHIPSET (descriptive) and +# SERVER (one of Mono, VGA16, SVGA, S3, 8514, Mach8, Mach32, Mach64, AGX, +# P9000, W32, I128). +# A reference to another definition is made with SEE (already defined +# entries are not overridden). +# Optional entries are RAMDAC (identifier), CLOCKCHIP (identifier), +# DACSPEED, NOCLOCKPROBE (advises never to probe clocks), UNSUPPORTED +# (indicates card that is not yet properly supported by a dedicated +# server). A LINE entry adds a line of text to be included in the +# Device section (can include options or comments). +# There's no CLOCKS option (although a Clocks line can be included +# with LINE), as it is very undesirable to have a Clocks line that +# is incorrect. The idea is that the Clocks are probed for to be +# sure (a commented suggested Clocks line can be included). +# +# The majority of entries are just a binding of a model name to a +# chipset/server and untested. +# +# $XFree86: xc/programs/Xserver/hw/xfree86/xf86config/Cards,v 3.51.2.15 1998/02/27 15:28:57 dawes Exp $ + +#Chips & Technologies + +#untested +NAME Chips & Technologies CT65520 +CHIPSET ct65520 +SERVER SVGA +LINE # Device section for C&T cards. +LINE # Option "suspend_hack" +LINE # Option "STN" +LINE # Option "no_stretch" +LINE # Option "no_center" +LINE # Option "use_modeline" +LINE # Option "fix_panel_size" +LINE # videoram 512 + +NAME Chips & Technologies CT65525 +CHIPSET ct65525 +LINE # Option "nolinear" +LINE # MemBase 0x03b00000 +SEE Chips & Technologies CT65520 + +NAME Chips & Technologies CT65530 +CHIPSET ct65530 +SEE Chips & Technologies CT65525 + +NAME Chips & Technologies CT65535 +CHIPSET ct65535 +NOCLOCKPROBE +LINE # Option "hw_clocks" +LINE # Textclockfreq 25.175 +SEE Chips & Technologies CT65530 + +NAME Chips & Technologies CT65540 +CHIPSET ct65540 +NOCLOCKPROBE +LINE # Option "use_18bit_bus" +SEE Chips & Technologies CT65535 + +NAME Chips & Technologies CT65545 +CHIPSET ct65545 +NOCLOCKPROBE +LINE # Option "noaccel" +LINE # Option "no_bitblt" +LINE # Option "xaa_no_color_exp" +LINE # Option "xaa_benchmark" +LINE # Option "sw_cursor" +LINE # Option "mmio" +SEE Chips & Technologies CT65540 + +NAME Chips & Technologies CT65546 +CHIPSET ct65546 +SEE Chips & Technologies CT65545 + +NAME Chips & Technologies CT65548 +CHIPSET ct65548 +SEE Chips & Technologies CT65545 + +NAME Chips & Technologies CT65550 +CHIPSET ct65550 +NOCLOCKPROBE +LINE # Option "noaccel" +LINE # Option "no_bitblt" +LINE # Option "xaa_no_color_exp" +LINE # Option "xaa_benchmark" +LINE # Option "sw_cursor" +LINE # Option "sync_on_green" +LINE # Option "fast_dram" +LINE # Option "use_vclk1" +LINE # Textclockfreq 25.175 +SEE Chips & Technologies CT65530 + +NAME Chips & Technologies CT65554 +CHIPSET ct65554 +SEE Chips & Technologies CT65550 + +NAME Chips & Technologies CT65555 +CHIPSET ct65555 +SEE Chips & Technologies CT65550 + +NAME Chips & Technologies CT68554 +CHIPSET ct68554 +SEE Chips & Technologies CT65550 + +NAME Chips & Technologies CT64200 +CHIPSET ct64200 +SERVER SVGA +LINE # Device section for C&T cards. +LINE # videoram 1024 + +NAME Chips & Technologies CT64300 +CHIPSET ct64300 +SERVER SVGA +LINE # Option "noaccel" +LINE # Option "no_bitblt" +LINE # Option "xaa_no_color_exp" +LINE # Option "xaa_benchmark" +LINE # Option "sw_cursor" +LINE # Option "nolinear" +LINE # MemBase 0x03b00000 +LINE # Option "hw_clocks" +LINE # Textclockfreq 25.175 +SEE Chips & Technologies CT64200 + +# Cirrus Logic + +#tested +NAME Cirrus Logic GD542x +CHIPSET CL-GD5420/2/4/6/8/9 +SERVER SVGA +NOCLOCKPROBE +LINE # Device section for Cirrus Logic GD5420/2/4/6/8/9-based cards. +LINE #MemBase 0x00e00000 +LINE #MemBase 0x04e00000 +LINE #Option "linear" + +#tested +NAME Cirrus Logic GD543x +CHIPSET CL-GD5430/5434 +SERVER SVGA +NOCLOCKPROBE +LINE # Device section for Cirrus Logic GD5430/34-based cards. +LINE #MemBase 0x00e00000 # ISA card that maps to 14Mb +LINE #MemBase 0x04000000 # VLB card that maps to 64Mb +LINE #MemBase 0x80000000 # VLB card that maps to 2048Mb +LINE #MemBase 0x02000000 # VLB card that maps to 32Mb +LINE #Option "linear" + +NAME Cirrus Logic GD544x +CHIPSET CL-GD544x +SERVER SVGA +NOCLOCKPROBE + +NAME Creative Labs Graphics Blaster MA201 +SEE Cirrus Logic GD544x + +NAME Creative Labs Graphics Blaster MA202 +SEE Cirrus Logic GD544x + +#tested +NAME Cirrus Logic GD5462 +CHIPSET CL-GD5462 +SERVER SVGA +NOCLOCKPROBE + +#tested +NAME Cirrus Logic GD5464 +CHIPSET CL-GD5464 +SERVER SVGA +NOCLOCKPROBE + +NAME Creative Labs Graphics Blaster MA302 +CHIPSET CL-GD5462 +SEE Cirrus Logic GD5462 + +NAME Creative Labs Graphics Blaster MA334 +CHIPSET CL-GD5464 +SEE Cirrus Logic GD5464 + +NAME Creative Labs Graphics Blaster 3D +CHIPSET CL-GD5464 +SEE Cirrus Logic GD5464 + +#tested +NAME Diamond SpeedStar 64 +CHIPSET CL-GD5434 +SEE Cirrus Logic GD543x + +NAME Diamond SpeedStar64 Graphics 2000/2200 +CHIPSET CL-GD5434 +SEE Cirrus Logic GD543x + +NAME Diamond SpeedStar Pro SE (CL-GD5430/5434) +SEE Cirrus Logic GD543x + +NAME Diamond SpeedStar Pro 1100 +SEE Cirrus Logic GD542x + +NAME Orchid Kelvin 64 VLB Rev A +CHIPSET CL-GD5434 +SERVER SVGA +NOCLOCKPROBE +LINE # Device section for Orchid Kelvin 64 VLB Rev A +LINE # Linear framebuffer maps at 2048Mb. Some motherboards make linear addressing +LINE # impossible. Some cards map at 32Mb. +LINE #MemBase 0x02000000 # VLB card that maps to 32Mb +LINE #MemBase 0x04000000 # VLB card that maps to 64Mb +LINE MemBase 0x80000000 # VLB card that maps to 2048Mb +LINE #Option "linear" + +NAME Orchid Kelvin 64 VLB Rev B +CHIPSET CL-GD5434 +SERVER SVGA +NOCLOCKPROBE +LINE # Device section for Orchid Kelvin 64 VLB Rev B +LINE # Linear framebuffer maps at 32Mb. Some motherboards make linear addressing +LINE # impossible. Some cards map at 2048Mb. +LINE MemBase 0x02000000 # VLB card that maps to 32Mb +LINE #MemBase 0x04000000 # VLB card that maps to 64Mb +LINE #MemBase 0x80000000 # VLB card that maps to 2048Mb +LINE #Option "linear" + +NAME Orchid Kelvin 64 +CHIPSET CL-GD5434 +SEE Cirrus Logic GD543x + +NAME Intel 5430 +CHIPSET CL-GD5430 +SEE Cirrus Logic GD543x + +NAME STB Nitro (64) +CHIPSET CL-GD5434 +SEE Cirrus Logic GD543x + +NAME STB Nitro 64 Video +CHIPSET CL-GD5446 +SEE Cirrus Logic GD544x + +NAME STB Horizon +CHIPSET CL-GD5426/28 +SEE Cirrus Logic GD542x + +NAME STB Horizon Video +CHIPSET CL-GD5440 +SEE Cirrus Logic GD544x + +NAME Genoa 8500VL(-28) +CHIPSET CL-GD5426/28 +SEE Cirrus Logic GD542x + +NAME Diamond SpeedStar Pro (not SE) +CHIPSET CL-GD5426/28 +SEE Cirrus Logic GD542x + +NAME ALG-5434(E) +CHIPSET CL-GD5434 +SEE Cirrus Logic GD543x + +NAME Actix ProStar +CHIPSET CL-GD5426/5428 +SEE Cirrus Logic GD542x + +NAME Actix ProStar 64 +CHIPSET CL-GD5434 +SEE Cirrus Logic GD543x + +#tested +NAME Acumos AVGA3 +SEE Cirrus Logic GD542x + +NAME DFI-WG1000 +SEE Cirrus Logic GD542x + +NAME Spider VLB Plus +CHIPSET CL-GD5428 +SEE Cirrus Logic GD542x + +NAME VI720 +CHIPSET CL-GD5434 +SEE Cirrus Logic GD543x + +NAME Cirrus Logic GD62xx (laptop) +CHIPSET CL-GD6205/15/25/35 +SERVER SVGA +NOCLOCKPROBE + +NAME Cirrus Logic GD64xx (laptop) +CHIPSET CL-GD6420/6440 +SERVER SVGA + +NAME Cirrus Logic GD754x (laptop) +CHIPSET CL-GD7541/42/43/48 +SERVER SVGA +NOCLOCKPROBE + +# S3 801/805 + +NAME S3 801/805 (generic) +CHIPSET S3 801/805 +SERVER S3 + +NAME S3 86C801 (generic) +SEE S3 801/805 (generic) + +NAME S3 86C805 (generic) +SEE S3 801/805 (generic) + +#tested +NAME S3 801/805 with ATT20c490 RAMDAC +CHIPSET S3 801/805 +SERVER S3 +RAMDAC att20c490 +LINE #Option "dac_8_bit" # Not supported by some 20c490 clones + +NAME S3 801/805 with SC1148{2,3,4} RAMDAC +CHIPSET S3 801/805 +SERVER S3 +RAMDAC sc11482 + +NAME S3 801/805 with SC1148{5,7,9} RAMDAC +CHIPSET S3 801/805 +SERVER S3 +RAMDAC sc11485 + +NAME S3 801/805 with S3 GenDAC +CHIPSET S3 801/805 +SERVER S3 +RAMDAC s3gendac +CLOCKCHIP s3gendac + +NAME S3 801/805 with ATT20c490 RAMDAC and ICD2061A +CHIPSET S3 801/805 +SERVER S3 +RAMDAC att20c490 +CLOCKCHIP icd2061a +LINE #Option "dac_8_bit" # Not supported by some 20c490 clones + +NAME S3 801/805 with Chrontel 8391 +CHIPSET S3 801/805 +SERVER S3 +RAMDAC att20c490 +CLOCKCHIP ch8391 +LINE Option "dac_8_bit" + +#tested +NAME Actix GE32+ 2MB +CHIPSET S3 801/805 +SERVER S3 +RAMDAC att20c490 +LINE #Option "dac_8_bit" + +NAME Actix GE32i +CHIPSET S3 805i +SERVER S3 + +NAME Orchid Fahrenheit VA +CHIPSET S3 801/805 +SERVER S3 +RAMDAC att20c490 + +NAME Orchid Fahrenheit 1280 +CHIPSET S3 801 +SERVER S3 +LINE #Probable clocks: +LINE #Clocks 25.20 28.32 32.50 0.00 40.00 44.90 50.40 65.00 +LINE #Clocks 78.00 56.70 63.10 75.10 80.00 89.90 100.90 31.50 + +NAME Orchid Fahrenheit-1280+ +CHIPSET S3 801/805 +SERVER S3 +RAMDAC att20C490 +LINE Dacspeed 110 +LINE Option "dac_8_bit" +LINE #Option "nolinear" # VLB card may require this +LINE #Probable clocks: +LINE #Clocks 25.20 28.32 40.0 0.0 50.10 77.0 36.10 45.0 +LINE #Clocks 130.0 120.20 80.0 31.50 110.30 65.0 75.0 94.60 + +NAME Diamond Stealth 24 +CHIPSET S3 801/805 +SERVER S3 +CLOCKCHIP icd2061a +LINE #Option "nolinear" +LINE #Ramdac "att20c490" # The Diamond RAMDAC is reportedly compatible for 15bpp + +NAME Miro Crystal 8S +SEE S3 801/805 (generic) + +NAME Miro Crystal 10SD with GenDAC +SEE S3 801/805 with S3 GenDAC + +NAME Dell S3 805 +SEE S3 801/805 (generic) + +NAME STB Powergraph X-24 +SEE S3 801/805 with ATT20c490 RAMDAC and ICD2061A + +NAME JAX 8241 +SEE S3 801/805 with Chrontel 8391 + +NAME VL-41 +SEE S3 801/805 with Chrontel 8391 + +NAME SPEA Mirage +SEE S3 801/805 with Chrontel 8391 + +# S3 864/Trio64/Trio32/868 + +NAME S3 864 (generic) +CHIPSET S3 864 +SERVER S3 + +NAME S3 86C864 (generic) +SEE S3 864 (generic) + +NAME S3 Vision864 (generic) +SEE S3 864 (generic) + +NAME S3 864 with SDAC (86C716) +CHIPSET S3 864 +SERVER S3 +RAMDAC s3_sdac +CLOCKCHIP s3_sdac +NOCLOCKPROBE + +NAME S3 864 with ATT 20C498 or 21C498 +CHIPSET S3 864 +SERVER S3 +RAMDAC att20c498 + +NAME S3 864 with STG1703 +CHIPSET S3 864 +SERVER S3 +RAMDAC stg1703 +NOCLOCKPROBE + +NAME S3 868 (generic) +CHIPSET S3 868 +SERVER S3 + +NAME S3 86C868 (generic) +SEE S3 868 (generic) + +NAME S3 Vision868 (generic) +SEE S3 868 (generic) + +NAME S3 868 with SDAC (86C716) +CHIPSET S3 868 +SERVER S3 +NOCLOCKPROBE + +NAME S3 868 with ATT 20C498 or 21C498 +CHIPSET S3 868 +SERVER S3 +RAMDAC att20c498 + +NAME S3 868 with ATT 20C409 +CHIPSET S3 868 +SERVER S3 +RAMDAC att20c409 +NOCLOCKPROBE + +NAME Number Nine FX Motion 531 +CLOCKCHIP icd2061a +SEE S3 868 with ATT 20C498 or 21C498 + +NAME S3 Trio64 (generic) +CHIPSET S3 Trio64 +SERVER S3 +NOCLOCKPROBE + +NAME S3 86C764 (generic) +SEE S3 Trio64 (generic) + +NAME S3 Trio64V+ (generic) +CHIPSET S3 Trio64V+ +SERVER S3 +NOCLOCKPROBE + +NAME S3 86C765 (generic) +SEE S3 Trio64V+ (generic) + +NAME S3 Trio32 (generic) +CHIPSET S3 Trio32 +SERVER S3 +NOCLOCKPROBE + +NAME Genoa Phantom 64i with S3 SDAC +DACSPEED 135 +SEE S3 864 with SDAC (86C716) + +NAME Number Nine GXE64 +CHIPSET S3 864 +SERVER S3 +CLOCKCHIP icd2061a +LINE Option "number_nine" + +NAME Number Nine GXE64 with S3 Trio64 +SEE S3 Trio64 (generic) + +NAME Diamond Stealth 64 DRAM with S3 SDAC +DACSPEED 135 +SEE S3 864 with SDAC (86C716) + +NAME Diamond Stealth64 Graphics 2xx0 series (864 + SDAC) +DACSPEED 135 +SEE S3 864 with SDAC (86C716) + +NAME Diamond Stealth 64 DRAM with S3 Trio64 +SEE S3 Trio64 (generic) + +NAME Diamond Stealth64 Graphics 2xx0 series (Trio64) +SEE S3 Trio64 (generic) + +NAME Diamond Stealth 64 DRAM SE +SEE S3 Trio32 (generic) + +NAME Diamond Stealth64 Video 2001 series (2121/2201) +SEE S3 Trio64V+ (generic) + +NAME Actix GE64 +CLOCKCHIP icd2061a +SEE S3 864 (generic) + +NAME ELSA Winner 1000PRO with S3 SDAC +SEE S3 864 with SDAC (86C716) + +NAME ELSA Winner 1000PRO with STG1700 or AT&T RAMDAC +CHIPSET S3 864 +SERVER S3 +CLOCKCHIP icd2061a + +NAME ELSA Winner 1000PRO/X +SEE S3 868 with SDAC (86C716) + +NAME ELSA Winner 1000ISA +CHIPSET S3 805i +SERVER S3 +CLOCKCHIP icd2061a +LINE Option "dac_8_bit" +LINE # the following settings should be detected and set automatically by XF86_S3 +LINE # if the serial number of the ELSA card is printed correctly: +LINE #ClockChip "icd2061a" + +NAME Cardex Trio64 +SEE S3 Trio64 (generic) + +NAME Cardex Trio64Pro +SEE S3 Trio64 (generic) + +NAME Miro Crystal 12SD +SEE S3 Trio32 (generic) + +NAME Miro Crystal 22SD +SEE S3 Trio64 (generic) + +NAME Miro Crystal 20SD with ICS2494 (BIOS 1.xx) +SEE S3 864 with ATT 20C498 or 21C498 + +NAME Miro Crystal 20SD with ICD2061A (BIOS 2.xx) +CLOCKCHIP icd2061a +SEE S3 864 with ATT 20C498 or 21C498 + +NAME Miro Crystal 20SD VLB with S3 SDAC (BIOS 3.xx) +SEE S3 864 with SDAC (86C716) + +NAME Miro Crystal 20SD PCI with S3 SDAC +SEE S3 868 with SDAC (86C716) + +NAME ELSA Winner 1000AVI (SDAC version) +SEE S3 868 with SDAC (86C716) + +NAME ELSA Winner 1000AVI (AT&T 20C409 version) +SEE S3 868 with ATT 20C409 + +NAME Diamond Stealth Video DRAM +SEE S3 868 with SDAC (86C716) + +NAME Diamond Stealth64 Video 2120/2200 +SEE S3 868 with SDAC (86C716) + +NAME SPEA/V7 Mirage P64 +CLOCKCHIP ics2595 +SEE S3 864 (generic) + +NAME SPEA/V7 Mirage P64 with S3 Trio64 +SEE S3 Trio64 (generic) + +NAME Number Nine FX Vision 330 +SEE S3 Trio64 (generic) + +NAME Number Nine FX Motion 331 +SEE S3 Trio64V+ (generic) + +NAME ASUS Video Magic PCI V864 +SEE S3 864 (generic) + +NAME ASUS Video Magic PCI VT64 +SEE S3 Trio64 (generic) + +NAME VidTech FastMax P20 +SEE S3 864 (generic) + +NAME VideoLogic GrafixStar 500 +SEE S3 868 with SDAC (86C716) + +NAME VideoLogic GrafixStar 400 +SEE S3 Trio64V+ (generic) + +NAME VideoLogic GrafixStar 300 +SEE S3 Trio64 (generic) + +NAME 2 the Max MAXColor S3 Trio64V+ +SEE S3 Trio64V+ (generic) + +NAME DataExpert DSV3365 +SEE S3 Trio64V+ (generic) + +NAME ExpertColor DSV3365 +SEE S3 Trio64V+ (generic) + +NAME DSV3326 +SEE S3 Trio64V+ (generic) + +# S3 Trio64V2 + +NAME S3 Trio64V2 (generic) +CHIPSET S3 Trio64V2 +SERVER S3 +NOCLOCKPROBE + +NAME S3 Trio64V2/DX (generic) +SEE S3 Trio64V2 (generic) + +NAME S3 Trio64V2/GX (generic) +SEE S3 Trio64V2 (generic) + +NAME S3 86C775 (generic) +SEE S3 Trio64V2/DX (generic) + +NAME S3 86C785 (generic) +SEE S3 Trio64V2/GX (generic) + +NAME ELSA WINNER 1000/T2D +SEE S3 Trio64V2/DX (generic) + + +# S3 Aurora64V+ + +NAME S3 Aurora64V+ (generic) +CHIPSET S3 Aurora64V+ +SERVER S3 +NOCLOCKPROBE +LINE # Option "lcd_center" +LINE # Set_LCDClk + +NAME S3 86CM65 +SEE S3 Aurora64V+ (generic) + +NAME SHARP 9080 +SEE S3 Aurora64V+ (generic) + +NAME SHARP 9090 +SEE S3 Aurora64V+ (generic) + +NAME COMPAQ Armada 7730MT +SEE S3 Aurora64V+ (generic) + +NAME COMPAQ Armada 7380DMT +SEE S3 Aurora64V+ (generic) + + +# S3 964/968 + +NAME S3 964 (generic) +CHIPSET S3 964 +SERVER S3 +NOCLOCKPROBE + +NAME S3 86C964 (generic) +SEE S3 964 (generic) + +NAME S3 Vision964 (generic) +SEE S3 964 (generic) + +NAME S3 968 (generic) +CHIPSET S3 968 +SERVER S3 +NOCLOCKPROBE + +NAME S3 86C968 (generic) +SEE S3 968 (generic) + +NAME S3 Vision968 (generic) +SEE S3 968 (generic) + +NAME Number Nine GXE64 Pro +CHIPSET S3 964 +SERVER S3 +RAMDAC ti3025 +LINE Option "number_nine" + +NAME Diamond Stealth 64 VRAM +CLOCKCHIP icd2061a +LINE #Option "slow_vram" +SEE S3 964 (generic) + +NAME Diamond Stealth64 Video 3200 +CHIPSET S3 968 +LINE #Option "slow_vram" +SEE S3 968 (generic) + +NAME Diamond Stealth 64 Video VRAM (TI RAMDAC) +CHIPSET S3 968 +LINE #Option "slow_vram" +LINE #DacSpeed 220 +SEE S3 968 (generic) + +NAME Diamond Stealth64 Video 3240/3400 (TI RAMDAC) +CHIPSET S3 968 +LINE #Option "slow_vram" +LINE #DacSpeed 220 +SEE S3 968 (generic) + +NAME Diamond Stealth64 Video 3240/3400 (IBM RAMDAC) +CHIPSET S3 968 +LINE #Option "slow_vram" +RAMDAC ibm_rgb526 +LINE DacSpeed 220 +SEE S3 968 (generic) + +NAME Genoa VideoBlitz III AV +CHIPSET S3 968 +LINE #s3RefClk 50 +LINE #DACspeed 170 +SEE S3 968 (generic) + +NAME STB Velocity 64 Video +CHIPSET S3 968 +LINE #s3RefClk 24 +LINE #DACspeed 220 +SEE S3 968 (generic) + +NAME STB Powergraph 64 Video +SEE S3 Trio64V+ (generic) + +NAME STB Powergraph 64 +SEE S3 Trio64 (generic) + +NAME ELSA Winner 1000TRIO +SEE S3 Trio64 (generic) + +NAME ELSA Winner 1000TRIO/V +SEE S3 Trio64V+ (generic) + +NAME Hercules Graphite Terminator 64 +LINE Option "slow_vram" +LINE #s3RefClk 50 +LINE #DACspeed 170 +SEE S3 964 (generic) + +NAME Hercules Terminator 64/Video +SEE S3 Trio64V+ (generic) + +NAME Hercules Graphite Terminator 64/DRAM +SEE S3 Trio64 (generic) + +NAME Hercules Graphite Terminator Pro 64 +LINE #s3RefClk 16 +LINE #DACspeed 220 +SEE S3 968 (generic) + +NAME Number Nine FX Motion 771 +LINE #s3RefClk 16 +SEE S3 968 (generic) + +NAME Spider Tarantula 64 +SEE S3 964 (generic) + +NAME Miro Crystal 20SV +CHIPSET S3 964 +SERVER S3 +CLOCKCHIP icd2061a + +NAME Miro Crystal 40SV +CHIPSET S3 964 +SERVER S3 +CLOCKCHIP ti3025 + +NAME Miro Crystal 80SV +CHIPSET S3 968 +SERVER S3 +NOCLOCKPROBE + +NAME Miro Video 20SV +CHIPSET S3 968 +SERVER S3 +RAMDAC att20c505 +LINE #DacSpeed 150 +CLOCKCHIP ics9161a + +NAME SPEA Mercury 64 +CHIPSET S3 964 +SERVER S3 +CLOCKCHIP ics9161a +LINE #Option "spea_mercury" + +NAME ELSA Winner 2000PRO-2 +CHIPSET S3 964 +SERVER S3 +LINE #Option "ELSA_w2000pro" +NOCLOCKPROBE + +NAME ELSA Winner 2000PRO-4 +CHIPSET S3 964 +SERVER S3 +LINE #Option "ELSA_w2000pro" +NOCLOCKPROBE + +NAME ELSA Winner 2000PRO/X-2 +CHIPSET S3 968 +SERVER S3 +LINE #Option "sync_on_green" +NOCLOCKPROBE + +NAME ELSA Winner 2000PRO/X-4 +CHIPSET S3 968 +SERVER S3 +LINE #Option "sync_on_green" +NOCLOCKPROBE + +NAME ELSA Winner 2000PRO/X-8 +CHIPSET S3 968 +SERVER S3 +LINE #Option "sync_on_green" +NOCLOCKPROBE + +NAME ELSA Winner 2000AVI +CHIPSET S3 968 +SERVER S3 +LINE #Option "sync_on_green" +NOCLOCKPROBE + +NAME ELSA Gloria-4 +CHIPSET S3 968 +SERVER S3 +LINE #Option "sync_on_green" +NOCLOCKPROBE + +NAME ELSA Gloria-8 +CHIPSET S3 968 +SERVER S3 +LINE #Option "sync_on_green" +NOCLOCKPROBE + +NAME VideoLogic GrafixStar 700 +CHIPSET S3 968 +SERVER S3 +NOCLOCKPROBE + +NAME LeadTek WinFast S430 +CHIPSET S3 968 +SERVER S3 +NOCLOCKPROBE + +NAME WinFast S430 +SEE LeadTek WinFast S430 + +NAME LeadTek WinFast S510 +CHIPSET S3 968 +SERVER S3 +NOCLOCKPROBE + +NAME WinFast S510 +SEE LeadTek WinFast S510 + +# S3 928 + +NAME S3 928 (generic) +CHIPSET S3 928 +SERVER S3 + +NAME S3 86C928 (generic) +SEE S3 928 (generic) + +NAME Actix Ultra +CHIPSET S3 928 +SERVER S3 +RAMDAC att20c490 +LINE #Option "dac_8_bit" + +NAME Diamond Stealth Pro +CHIPSET S3 928 +SERVER S3 +CLOCKCHIP icd2061a +LINE #Ramdac "att20c490" # The Diamond RAMDAC is reportedly compatible for 15bpp +LINE #Option "no_linear" # Some VLB machines may require this + +NAME ELSA Winner 1000VL +CHIPSET S3 928 +SERVER S3 +LINE # the following settings should be detected and set automatically by XF86_S3 +LINE # if the serial number of the ELSA card is printed correctly: +LINE #ClockChip "icd2061a" +LINE #Membase 0xf8000000 + +NAME ELSA Winner 1000TwinBus +SEE ELSA Winner 1000VL + +NAME ELSA Winner 2000 +SEE S3 928 (generic) + +NAME Miro Crystal 16S +SEE S3 928 (generic) + +NAME SPEA/V7 Mercury +CHIPSET S3 928 +SERVER S3 +CLOCKCHIP sc11412 +LINE Option "spea_mercury" + +NAME STB Pegasus +CHIPSET S3 928 +SERVER S3 +RAMDAC bt485 +CLOCKCHIP icd2061a +LINE Option "stb_pegasus" +LINE #Option "sync_on_green" + +NAME Number Nine GXE Level 14/16 +CHIPSET S3 928 +SERVER S3 +DACSPEED 200 +CLOCKCHIP icd2061a +LINE Option "number_nine" +LINE #Option "nolinear" +LINE #Option "nomemaccess" + +NAME Number Nine GXE Level 10/11/12 +CHIPSET S3 928 +SERVER S3 +CLOCKCHIP icd2061a +LINE Option "number_nine" + +NAME 928Movie +CHIPSET S3 928 +SERVER S3 +CLOCKCHIP icd2595 +RAMDAC bt485 +LINE # pixel multiplexing not supported + +# S3 911/924 + +NAME S3 911/924 (generic) +CHIPSET S3 911/924 +SERVER S3 + +NAME S3 86C911 (generic) +SEE S3 911/924 (generic) + +NAME S3 86C924 (generic) +SEE S3 911/924 (generic) + +NAME Diamond Stealth VRAM +CHIPSET S3 911/924 +SERVER S3 +CLOCKCHIP icd2061a + +#NAME Orchid Fahrenheit 1280 +#SEE S3 911/924 (generic) + +NAME S3 924 with SC1148 DAC +CHIPSET S3 924 +SERVER S3 +LINE #Probable clocks: +LINE #Clocks 25.2 28.3 39.7 1.7 49.9 76.7 35.7 44 +LINE #Clocks 130.2 119.5 79.4 31.2 110.0 65.2 74.9 71.3 + +# S3 ViRGE,/DX,/GX and ViRGE/VX + +NAME S3 ViRGE (old S3V server) +CHIPSET S3 ViRGE +SERVER S3V +NOCLOCKPROBE + +NAME S3 ViRGE (generic) +CHIPSET S3 ViRGE +SERVER SVGA +NOCLOCKPROBE +LINE #Option "xaa_benchmark" +LINE #Option "fifo_moderate" +LINE #Option "pci_burst_on" +LINE #Option "pci_retry" + +NAME S3 ViRGE/DX (generic) +CHIPSET S3 ViRGE/DX +SERVER SVGA +NOCLOCKPROBE +LINE #Option "xaa_benchmark" +LINE #Option "fifo_moderate" +LINE #Option "pci_burst_on" +LINE #Option "pci_retry" + +NAME S3 ViRGE/GX (generic) +CHIPSET S3 ViRGE/GX +SERVER SVGA +NOCLOCKPROBE +LINE #Option "xaa_benchmark" +LINE #Option "fifo_moderate" +LINE #Option "pci_burst_on" +LINE #Option "pci_retry" + + +NAME S3 ViRGE/GX2 (generic) +CHIPSET S3 ViRGE/GX2 +SERVER SVGA +NOCLOCKPROBE +LINE #Option "xaa_benchmark" +LINE #Option "fifo_moderate" +LINE #Option "pci_burst_on" +LINE #Option "pci_retry" + +NAME S3 ViRGE/MX (generic) +CHIPSET S3 ViRGE/MX +SERVER SVGA +NOCLOCKPROBE +LINE #Option "lcd_center" +LINE #Set_LCDClk +LINE #Option "xaa_benchmark" +LINE #Option "fifo_moderate" +LINE #Option "pci_burst_on" +LINE #Option "pci_retry" + + + + +NAME S3 86C325 (generic) +SEE S3 ViRGE (generic) + +NAME S3 86C375 (generic) +SEE S3 ViRGE/DX (generic) + +NAME S3 86C385 (generic) +SEE S3 ViRGE/GX (generic) + +NAME S3 86C357 (generic) +SEE S3 ViRGE/GX2 (generic) + +NAME S3 86C260 (generic) +SEE S3 ViRGE/MX (generic) + + +NAME ELSA Victory 3D +SEE S3 ViRGE (generic) + +NAME ELSA Victory 3DX +SEE S3 ViRGE/DX (generic) + +NAME ELSA Winner 3000-S +SEE S3 ViRGE (generic) + +NAME Number Nine Visual 9FX Reality 332 +SEE S3 ViRGE (generic) + +NAME Number Nine FX Motion 332 +SEE S3 ViRGE (generic) + +NAME Diamond Stealth 3D 2000 +SEE S3 ViRGE (generic) + +NAME Diamond Stealth 3D 2000 PRO +SEE S3 ViRGE/DX (generic) + +NAME Diamond Multimedia Stealth 3D 2000 +SEE S3 ViRGE (generic) + +NAME Diamond Multimedia Stealth 3D 2000 PRO +SEE S3 ViRGE/DX (generic) + +NAME Canopus Co. Power Window 3DV +SEE S3 ViRGE (generic) + +NAME DataExpert DSV3325 +SEE S3 ViRGE (generic) + +NAME ExpertColor DSV3325 +SEE S3 ViRGE (generic) + +NAME DSV3325 +SEE S3 ViRGE (generic) + +NAME Hercules Terminator 64/3D +SEE S3 ViRGE (generic) + +NAME Hercules Terminator 3D/DX +SEE S3 ViRGE/DX (generic) + +NAME LeadTek WinFast 3D S600 +SEE S3 ViRGE (generic) + +NAME WinFast 3D S600 +SEE LeadTek WinFast 3D S600 + +NAME LeadTek WinFast 3D S680 +SEE S3 ViRGE/GX2 (generic) + +NAME WinFast 3D S600 +SEE LeadTek WinFast 3D S680 + +NAME miro miroMedia 3D +SEE S3 ViRGE (generic) + +NAME Orchid Technology Fahrenheit Video 3D +SEE S3 ViRGE (generic) + +NAME STB Systems Powergraph 3D +SEE S3 ViRGE (generic) + +NAME STB Nitro 3D +CHIPSET S3 ViRGE/GX +SEE S3 ViRGE/GX (generic) + +NAME MELCO WGP-VG4S +LINE #DACSpeed 191 162 111 83 +LINE #SetMClck 75 +SEE S3 ViRGE (generic) + + + +NAME S3 ViRGE/VX (generic) +CHIPSET S3 ViRGE/VX +SERVER SVGA +NOCLOCKPROBE +LINE #Option "xaa_benchmark" +LINE #Option "fifo_moderate" +LINE #Option "pci_burst_on" +LINE #Option "pci_retry" + + +NAME S3 86C988 (generic) +SEE S3 ViRGE/VX (generic) + +NAME ELSA Winner 3000 +SEE S3 ViRGE/VX (generic) + +NAME ELSA Winner 3000-M-22 +SEE S3 ViRGE/VX (generic) + +NAME ELSA Winner 3000-L-42 +SEE S3 ViRGE/VX (generic) + +NAME ELSA Winner 2000AVI/3D +SEE S3 ViRGE/VX (generic) + +NAME Diamond Stealth 3D 3000 +SEE S3 ViRGE/VX (generic) + +NAME STB Systems Velocity 3D +SEE S3 ViRGE/VX (generic) + +NAME MELCO WGP-VX8 +SEE S3 ViRGE/VX (generic) + + +NAME Toshiba Tecra 750CDT +SEE S3 ViRGE/MX (generic) + +NAME Toshiba Tecra 750DVD +SEE S3 ViRGE/MX (generic) + +NAME Toshiba Tecra 540CDT +SEE S3 ViRGE/MX (generic) + +NAME Toshiba Tecra 550CDT +SEE S3 ViRGE/MX (generic) + + + + + +# ET4000/ET6000 + +NAME ET3000 (generic) +CHIPSET ET3000 +SERVER SVGA + +NAME Genoa 5400 +SEE ET3000 (generic) + +NAME ET4000 (generic) +CHIPSET ET4000 +SERVER SVGA + +NAME ET4000/W32 (generic) +CHIPSET ET4000/W32 +SERVER W32 + +NAME ET4000 W32i, W32p (generic) +CHIPSET ET4000/W32(i/p) +SERVER SVGA +LINE #Option "linear" # for linear mode at 8bpp +LINE #Option "noaccel" # when problems with accelerator +LINE #Option "power_saver" # enable VESA DPMS +LINE #Option "fast_dram" +LINE #Option "pci_retry" # faster, but problematic for ISA DMA +LINE #Option "hibit_high" # see README.tseng -- most cards need this +LINE #Option "hibit_low" # see README.tseng -- mostly for older ET4000 cards +LINE #MemBase 0x3C00000 # when automatic MemBase detection doesn't work +LINE # -- see README.tseng for more (important) information on MemBase + +NAME ET6000 (generic) +CHIPSET ET6000 +SERVER SVGA +NOCLOCKPROBE +LINE #videoram 2304 # 2.25 MB, when memory probe is incorrect +LINE #Option "linear" # for linear mode at 8bpp +LINE #Option "noaccel" # when problems with accelerator +LINE #Option "power_saver" # enable VESA DPMS +LINE #Option "pci_retry" # faster, but problematic for ISA DMA +LINE #Option "hw_cursor" # Use hardware cursor (see docs for limitations) +LINE #Option "xaa_no_color_exp" # When text (or bitmap) is not rendered correctly + +NAME ET6100 (generic) +CHIPSET ET6100 +SERVER XSuSE_Tseng +NOCLOCKPROBE + +NAME Diamond Stealth 32 +CLOCKCHIP icd2061a +NOCLOCKPROBE +SEE ET4000 W32i, W32p (generic) + +NAME Cardex Cobra +SEE ET4000 W32i, W32p (generic) + +NAME Cardex Challenger (Pro) +SEE ET4000 W32i, W32p (generic) + +NAME Colorgraphic Dual Lightning +SEE ET4000 W32i, W32p (generic) + +NAME Dell onboard ET4000 +SEE ET4000 (generic) + +NAME DFI-WG5000 +SEE ET4000 W32i, W32p (generic) + +NAME Diamond SpeedStar (Plus) +SEE ET4000 (generic) + +NAME Diamond SpeedStar 24 +SEE ET4000 (generic) + +NAME Diamond SpeedStar HiColor +SEE ET4000 (generic) + +NAME Genoa 8900 Phantom 32i +SEE ET4000 W32i, W32p (generic) + +NAME Hercules Dynamite +SEE ET4000/W32 (generic) + +NAME Hercules Dynamite Power +SEE ET4000 W32i, W32p (generic) + +NAME Hercules Dynamite Pro +SEE ET4000 W32i, W32p (generic) + +NAME Integral FlashPoint +SEE ET4000 W32i, W32p (generic) + +NAME LeadTek WinFast S200 +SEE ET4000 W32i, W32p (generic) + +NAME Matrox Comet +SEE ET4000 W32i, W32p (generic) + +NAME Matrox Marvel II +SEE ET4000 W32i, W32p (generic) + +NAME Miro MiroVideo 20TD +SEE ET4000 W32i, W32p (generic) + +NAME WinFast S200 +SEE LeadTek WinFast S200 + +NAME Sigma Concorde +SEE ET4000/W32 (generic) + +NAME Sigma Legend +SEE ET4000 (generic) + +NAME SPEA/V7 ShowTime Plus +SEE ET4000 W32i, W32p (generic) + +NAME STB LightSpeed +SEE ET4000 W32i, W32p (generic) + +NAME STB MVP-2 +SEE ET4000 (generic) + +NAME STB MVP-2 PCI +SEE ET4000 W32i, W32p (generic) + +NAME STB MVP-2X +SEE ET4000 W32i, W32p (generic) + +NAME STB MVP-4 PCI +SEE ET4000 W32i, W32p (generic) + +NAME STB MVP-4X +SEE ET4000 W32i, W32p (generic) + +NAME TechWorks Thunderbolt +SEE ET4000/W32 (generic) + +NAME ViewTop PCI +SEE ET4000 W32i, W32p (generic) + +NAME SNI PC5H W32 +CLOCKCHIP stg1703 +NOCLOCKPROBE +SEE ET4000 W32i, W32p (generic) + +NAME SNI Scenic W32 +CLOCKCHIP stg1703 +NOCLOCKPROBE +SEE ET4000 W32i, W32p (generic) + +NAME Hercules Dynamite 128/Video +SEE ET6000 (generic) + +NAME STB LightSpeed 128 +SEE ET6000 (generic) + +NAME VideoLogic GrafixStar 600 +SEE ET6000 (generic) + +NAME Jazz Multimedia G-Force 128 +SEE ET6000 (generic) + +NAME Mirage Z-128 +SEE ET6000 (generic) + +NAME California Graphics SunTracer 6000 +SEE ET6000 (generic) + +NAME Binar Graphics AnyView +SEE ET6000 (generic) + +NAME MediaVision Proaxcel 128 +SEE ET6000 (generic) + +NAME ATrend ATC-2165A +SEE ET6000 (generic) + +NAME Interay PMC Viper +SEE ET6000 (generic) + +2-the-Max MAXColor 6000 +SEE ET6000 (generic) + +Gainward Challenger EV +SEE ET6000 (generic) + +MachSpeed VGA ET6000 +SEE ET6000 (generic) + +KouTech KeyVision 128 EV +SEE ET6000 (generic) + + +# ATI + +NAME ATI 8514 Ultra (no VGA) +CHIPSET ATI-Mach8 +SERVER Mach8 + +NAME ATI Graphics Ultra +CHIPSET ATI-Mach8 +SERVER Mach8 +LINE #Probable clocks: +LINE #Clocks 43 49 80 36 50 56 0 45 30 32 110 79 40 45 75 65 +LINE #Clocks 22 25 46 18 25 28 0 22 15 16 55 40 20 22 38 32 + +NAME ATI Graphics Ultra Pro +CHIPSET ATI-Mach32 +SERVER Mach32 +LINE #Probable clocks: +LINE #Clocks 100 126 92 36 51 57 0 44 135 32 110 80 39 +LINE #Clocks 45 75 65 50 63 46 18 25 28 0 22 67 16 55 40 19 23 37 33 +LINE #Option "dac_8_bit" + +NAME ATI Wonder SVGA +CHIPSET ATI vgawonder +SERVER SVGA +LINE #probable clocks: +LINE #Clocks 30 32 11 80 42 48 92 36 40 45 75 65 50 56 0 0 +LINE #Clocks 15 16 55 0 21 24 46 18 20 22 37 32 25 28 0 0 + +NAME ATI Ultra Plus +CHIPSET ATI-Mach32 +SERVER Mach32 + +NAME ATI Mach32 +CHIPSET ATI-Mach32 +SERVER Mach32 + +NAME ATI Mach64 +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Mach64 with AT&T 20C408 RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +LINE #Ramdac "att20c408" +NOCLOCKPROBE + +NAME ATI Mach64 with CH8398 RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +LINE #Ramdac "ch8398" +NOCLOCKPROBE + +NAME ATI Mach64 with IBM RGB514 RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +LINE #Ramdac "ibm_rgb514" +NOCLOCKPROBE + +NAME ATI Mach64 CT (264CT), Internal RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Mach64 VT (264VT), Internal RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Mach64 GT (264GT), aka 3D RAGE, Internal RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Mach64 3D RAGE II, Internal RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Mach64 3D RAGE II+, Internal RAMDAC +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Xpert@Play PCI and AGP, 3D Rage Pro +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Xpert@Work, 3D Rage Pro +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Pro Turbo+PC2TV, 3D Rage II+DVD +CHIPSET ATI-Mach64 +SERVER Mach64 +NOCLOCKPROBE + +NAME ATI Graphics Xpression with STG1702 RAMDAC +SEE ATI Mach64 + +NAME ATI Graphics Xpression with 68875 RAMDAC +SEE ATI Mach64 + +NAME ATI Graphics Xpression with CH8398 RAMDAC +SEE ATI Mach64 with CH8398 RAMDAC + +NAME ATI Graphics Xpression with AT&T 20C408 RAMDAC +SEE ATI Mach64 with AT&T 20C408 RAMDAC + +NAME ATI Graphics Xpression with Mach64 CT (264CT) +SEE ATI Mach64 CT (264CT), Internal RAMDAC + +NAME ATI Video Xpression +SEE ATI Mach64 VT (264VT), Internal RAMDAC + +NAME ATI 3D Xpression +SEE ATI Mach64 GT (264GT), aka 3D RAGE, Internal RAMDAC + +NAME ATI 3D Xpression+ PC2TV +SEE ATI Mach64 3D RAGE II, Internal RAMDAC + +NAME ATI 3D Pro Turbo +SEE ATI Mach64 3D RAGE II, Internal RAMDAC + +NAME ATI All-in-Wonder +SEE ATI Mach64 3D RAGE II+, Internal RAMDAC + +NAME ATI Win Boost with STG1702 RAMDAC +SEE ATI Mach64 + +NAME ATI Win Boost with CH8398 RAMDAC +SEE ATI Mach64 with CH8398 RAMDAC + +NAME ATI Win Boost with AT&T 20C408 RAMDAC +SEE ATI Mach64 with AT&T 20C408 RAMDAC + +NAME ATI Win Boost with Mach64 CT (264CT) +SEE ATI Mach64 CT (264CT), Internal RAMDAC + +NAME ATI Graphics Pro Turbo +SEE ATI Mach64 + +NAME ATI Graphics Pro Turbo 1600 +SEE ATI Mach64 with IBM RGB514 RAMDAC + +NAME ATI Win Turbo +SEE ATI Mach64 + +NAME ASUS PCI-V264CT +SEE ATI Mach64 CT (264CT), Internal RAMDAC + +NAME ASUS PCI-AV264CT +SEE ATI Mach64 CT (264CT), Internal RAMDAC + +# AGX + +NAME AGX (generic) +CHIPSET AGX-014/15/16 +SERVER AGX + +NAME Boca Vortex (Sierra RAMDAC) +CHIPSET AGX-015 +SERVER AGX +RAMDAC sc15025 +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Option "fifo_moderate" # 2x bus bw - may result in random pixels + +NAME EIZO (VRAM) +SEE AGX (generic) + +NAME Orchid Celsius (AT&T RAMDAC) +CHIPSET AGX-015 +SERVER AGX +RAMDAC att20c490 +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Option "fifo_moderate" # 2x bus bw - may result in random pixels + +NAME Orchid Celsius (Sierra RAMDAC) +CHIPSET AGX-015 +SERVER AGX +RAMDAC sc15025 +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Option "fifo_moderate" # 2x bus bw - may result in random pixels + + +NAME Spider Black Widow +CHIPSET AGX-015 +SERVER AGX +RAMDAC sc15025 +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Option "fifo_moderate" # 2x bus bw - may result in random pixels + + +NAME Spider Black Widow Plus +CHIPSET AGX-016 +SERVER AGX +RAMDAC sc15025 +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Option "fifo_moderate" # 2x bus bw - may result in random pixels +LINE #Option "fifo_aggressive" # 3x bus bw - may result in random pixels +LINE #Probable clocks: +LINE #Clocks 25.2 28.3 39.9 72.2 50.0 76.9 36.1 44.8 +LINE #Clocks 89.0 119.8 79.9 31.5 110.0 64.9 74.9 94.9 + +NAME Hercules Graphite HG210 +CHIPSET AGX-014 +SERVER AGX +RAMDAC bt482 +DACSPEED 85 +LINE Chipset "AGX-014" +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Probable clocks: +LINE #Clocks 25.0 28.0 32.0 36.0 40.0 45.0 50.0 65.0 +LINE #Clocks 70.0 75.0 80.0 85.0 90.0 95.0 100.0 110.0 + +NAME Hercules Graphite Pro +CHIPSET AGX-015 +SERVER AGX +# Card specific DAC, doesn't appear in ramdac menu +LINE Ramdac "herc_dual_dac" +LINE Chipset "AGX-015" +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Option "fifo_moderate" # 2x bus bw - may result in random pixels +LINE #Probable clocks: +LINE #Clocks 25.0 28.0 32.0 36.0 40.0 45.0 50.0 65.0 +LINE #Clocks 70.0 75.0 80.0 85.0 90.0 95.0 100.0 110.0 + +NAME Hercules Graphite Power +CHIPSET AGX-016 +SERVER AGX +# Card specific DAC, doesn't appear in ramdac menu +# The glue logic state machine for RAMDAC switching doesn't work as +# documented, for now we're stuck with the small RAMDAC +LINE Ramdac "herc_small_dac" +LINE Chipset "AGX-016" +LINE Option "dac_8_bit" +LINE Option "no_wait_state" +LINE #Option "fifo_moderate" # 2x bus bw - may result in random pixels +LINE #Option "fifo_aggressive" # 3x bus bw - may result in random pixels +LINE #Probable clocks: +LINE #Clocks 25.0 28.0 32.0 36.0 40.0 45.0 50.0 65.0 +LINE #Clocks 70.0 75.0 80.0 85.0 90.0 95.0 100.0 110.0 + +NAME XGA-2 (ISA bus) +CHIPSET XGA-2 +SERVER AGX +NOCLOCKPROBE +LINE #Instance 7 # XGA instance 0-7 +LINE #COPbase 0xC8F00 # XGA memory-mapped register address +LINE #POSbase 0 # Disable probing if above are specified + +NAME XGA-1 (ISA bus) +CHIPSET XGA-1 +SERVER AGX +LINE #Instance 7 # XGA instance 0-7 +LINE #COPbase 0xC8F00 # XGA memory-mapped register address +LINE #POSbase 0 # Disable probing if above are specified + +# WD + +NAME Paradise/WD 90CXX +CHIPSET WD90CXX +SERVER SVGA + +NAME DFI-WG6000 +CHIPSET WD90C33 +SERVER SVGA + +NAME Diamond SpeedStar 24X (not fully supported) +CHIPSET WD90C31 +SERVER SVGA + +NAME WD 90C24 (laptop) +CHIPSET WD90C24 +SERVER SVGA +LINE #Chipset "wd90c24" +LINE #Option "noaccel" # Use this if acceleration is causing problems +LINE #Clocks 25.175 28.322 65 36 # These are not programmable +LINE #Clocks 29.979 77.408 62.195 59.957 # These are programmable +LINE #Clocks 31.5 35.501 75.166 50.114 # These are not programmable +LINE #Clocks 39.822 72.038 44.744 80.092 # These are programmable +LINE #Clocks 44.297 # Must match Mclk + + +NAME WD 90C24A or 90C24A2 (laptop) +CHIPSET WD90C24A +SERVER SVGA +LINE #Chipset "wd90c24" +LINE #Clocks 25.175 28.322 65 36 # These are not programmable +LINE #Clocks 29.979 77.408 62.195 59.957 # These are programmable +LINE #Clocks 31.5 35.501 75.166 50.114 # These are not programmable +LINE #Clocks 39.822 72.038 44.744 80.092 # These are programmable +LINE #Clocks 44.297 # Must match Mclk + +# Avance Logic + +NAME Avance Logic 2101 +CHIPSET Avance Logic +LINE #chipset "al2101" +SERVER SVGA + +NAME Avance Logic 2228 +CHIPSET Avance Logic +LINE #chipset "ali2228" +SERVER SVGA + +NAME Avance Logic 2301 +CHIPSET Avance Logic +LINE #chipset "ali2301" +SERVER SVGA + +NAME Avance Logic 2302 +CHIPSET Avance Logic +LINE #chipset "ali2302" +SERVER SVGA + +NAME Avance Logic 2308 +CHIPSET Avance Logic +LINE #chipset "ali2308" +SERVER SVGA + +NAME Avance Logic 2401 +CHIPSET Avance Logic +LINE #chipset "ali2401" +SERVER SVGA + +NAME Hercules Stingray +CHIPSET ALG-2228/2301/2302 +LINE #chipset "ali2228" +SERVER SVGA + +NAME SPEA/V7 Mirage VEGA Plus +CHIPSET ALG-2228 +LINE #chipset "ali2228" +SERVER SVGA + +# ARK Logic + +NAME Ark Logic ARK1000PV (generic) +CHIPSET ARK1000PV +SERVER SVGA + +# For now, treat the VL as a PV. This may be changed later +NAME Ark Logic ARK1000VL (generic) +CHIPSET ARK1000VL +LINE Chipset "ark1000pv" +SERVER SVGA + +NAME Ark Logic ARK2000PV (generic) +CHIPSET ARK1000PV +SERVER SVGA + +NAME Ark Logic ARK2000MT (generic) +CHIPSET ARK1000MT +SERVER SVGA + +NAME Hercules Stingray Pro +SEE Ark Logic ARK1000PV (generic) + +NAME Hercules Stingray Pro/V +SEE Ark Logic ARK1000PV (generic) + +NAME Ocean (octek) VL-VGA-1000 +RAMDAC att20c490 +SEE Ark Logic ARK1000VL (generic) + +NAME Hercules Stingray 64/V with ZoomDAC +SEE Ark Logic ARK2000PV (generic) + +NAME Hercules Stingray 64/V with ICS5342 +CHIPSET ARK2000MT +RAMDAC ics5342 +SERVER SVGA + +NAME Diamond Stealth64 Graphics 2001 series +CHIPSET ARK2000PV +RAMDAC ics5342 +SERVER SVGA + +# Oak + +NAME Oak (generic) +CHIPSET Oak-067/77/87 +SERVER SVGA + +NAME Paradise Accelerator Value +CHIPSET Oak OTI-087 +SERVER SVGA + +# P9000 + +NAME Diamond Viper VLB 2Mb +CHIPSET Weitek 9000 +SERVER P9000 +LINE #Clocks must match the mode clocks (XFree86 3.1 P9000 server) +LINE #Versions later than 3.1 do not require a clocks line +LINE Chipset "vipervlb" # Required for some cards which autodetect as PCI +LINE Videoram 2048 # Required +LINE Membase 0x80000000 # Optional (0x80000000 is default) +NOCLOCKPROBE + +NAME Diamond Viper PCI 2Mb +CHIPSET Weitek 9000 +SERVER P9000 +LINE #Clocks must match the mode clocks (XFree86 3.1 P9000 server) +LINE #Versions later than 3.1 do not require a clocks line +LINE Videoram 2048 # Required +LINE #Membase 0x80000000 # Use scanpci to get the correct Membase +NOCLOCKPROBE + +NAME Orchid P9000 VLB +CHIPSET Weitek 9000 +SERVER P9000 +LINE Chipset "orchid_p9000" +LINE Membase 0xE0000000 +NOCLOCKPROBE + +# Trident + +NAME Trident 8900/9000 (generic) +CHIPSET TVGA8900/9000 +SERVER SVGA + +NAME Trident 8900D (generic) +CHIPSET TVGA8900D +SERVER SVGA + +NAME Trident TVGA9200CXr (generic) +CHIPSET TVGA9200CXr +SERVER SVGA + +NAME Trident TGUI9400CXi (generic) +CHIPSET TGUI9400CXi +SERVER SVGA + +NAME Trident TGUI9420DGi (generic) +CHIPSET TGUI9420DGi +SERVER SVGA + +NAME Trident TGUI9430DGi (generic) +CHIPSET TGUI9430DGi +SERVER SVGA + +NAME Trident TGUI9440 (generic) +CHIPSET TGUI9440 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident TGUI9660 (generic) +CHIPSET TGUI9660 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident TGUI9680 (generic) +CHIPSET TGUI9680 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident TGUI9682 (generic) +CHIPSET TGUI9682 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident TGUI9685 (generic) +CHIPSET TGUI9685 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident Cyber 9382 (generic) +CHIPSET Cyber9382 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident Cyber 9385 (generic) +CHIPSET Cyber9385 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident Cyber 9388 (generic) +CHIPSET Cyber9388 +SERVER SVGA +NOCLOCKPROBE + +NAME Trident Cyber 9397 (generic) +CHIPSET Cyber9397 +SERVER SVGA +NOCLOCKPROBE + +# SiS + +NAME SiS SG86C201 +CHIPSET SIS86C201 +SERVER SVGA + +# Alliance ProMotion + +NAME Alliance ProMotion 6422 +CHIPSET AP6422 +SERVER SVGA + +# VGA + +NAME Generic VGA compatible +CHIPSET Generic VGA +SERVER VGA16 + +NAME Unsupported VGA compatible +CHIPSET Generic VGA +SERVER VGA16 +UNSUPPORTED + +# Number 9 I128 + +NAME Number Nine Imagine I-128 (2-8MB) +CHIPSET I128 +SERVER I128 + +NAME Number Nine Imagine I-128 Series 2 (2-4MB) +CHIPSET I128 +SERVER I128 + +# Matrox + +NAME Matrox Millennium (MGA) +CHIPSET mga2064w +SERVER SVGA +NOCLOCKPROBE + +NAME Matrox Millennium II +CHIPSET mga2164w +SERVER SVGA +NOCLOCKPROBE + +NAME Matrox Millennium II AGP +CHIPSET mga2164w AGP +SERVER SVGA +NOCLOCKPROBE + +NAME Matrox Mystique +CHIPSET mga1064sg +SERVER SVGA +NOCLOCKPROBE + +# NV1 + +NAME Diamond Edge 3D +CHIPSET nv1 +SERVER SVGA +NOCLOCKPROBE + +NAME RIVA128 +CHIPSET RIVA128 +SERVER SVGA +NOCLOCKPROBE + +NAME ELSA VICTORY ERAZOR +SEE RIVA128 + +NAME Diamond Viper 330 +SEE RIVA128 + +NAME STB Velocity 128 +SEE RIVA128 + +NAME ASUS 3Dexplorer +SEE RIVA128 + +# Alliance Semiconductor + +NAME Diamond Stealth Video 2500 +CHIPSET Alliance AT24 +SERVER SVGA +NOCLOCKPROBE + +NAME AT3D +CHIPSET Alliance AT3D +SERVER SVGA +NOCLOCKPROBE +LINE #Option "no_accel" + +NAME AT25 +SEE AT3D + +NAME Hercules Stingray 128 3D +SEE AT3D + +# Misc + +NAME Techworks Ultimate 3D +CHIPSET CL-GD5464 +SEE Cirrus Logic GD5464 + +NAME VideoLogic GrafixStar 550 +CHIPSET CL-GD5464 +SEE Cirrus Logic GD5464 + +NAME Jaton Video-70P +CHIPSET CL-GD5464 +SEE Cirrus Logic GD5464 + +NAME Jaton Video-58P +SEE ET6000 (generic) + +NAME Rendition Verite 1000 +CHIPSET Verite 1000 +SEE Unsupported VGA compatible + +NAME Creative Labs 3D Blaster PCI (Verite 1000) +SEE Rendition Verite 1000 + +NAME Canopus Total-3D +SEE Rendition Verite 1000 + +NAME Sierra Screaming 3D +SEE Rendition Verite 1000 + +NAME NeoMagic (laptop/notebook) +CHIPSET NeoMagic 128/V/ZV +SEE Unsupported VGA compatible + +END diff --git a/hw/xfree86/utils/xorgconfig/cards.c b/hw/xfree86/utils/xorgconfig/cards.c new file mode 100644 index 000000000..a714d04ca --- /dev/null +++ b/hw/xfree86/utils/xorgconfig/cards.c @@ -0,0 +1,285 @@ +/* $Xorg: cards.c,v 1.3 2000/08/17 19:53:05 cpqbld Exp $ */ + + + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/xf86config/cards.c,v 3.11.2.1 1998/01/18 10:35:45 hohndel Exp $ */ + +/* + * Functions to manipulate card database. + */ + +#include +#include +#include + +#include "cards.h" + +/* + * Database format: + * + * NAME + * CHIPSET + * SERVER + * + * Optional keywords: + * RAMDAC + * CLOCKCHIP + * DACSPEED + * NOCLOCKPROBE + * UNSUPPORTED + * + * SEE refers to another card definition; parameters that + * are already defined are not overridden. + * + * is one of Mono, VGA16, SVGA, S3, Mach32, Mach8, 8514, + * P9000, AGX, W32. + * + * A useful additional keywords may be CLOCKS. + */ + + + +/* Database vars. */ + +int lastcard; + +Card card[MAX_CARDS]; + +void sort_database(); + + +static int getline(f, l) +FILE *f; +char *l; +{ + if (fgets(l, 128, f) == NULL) + return -1; +#ifdef __EMX__ + { + char *p = strchr(l,'\r'); + if (p) { + *p = '\n'; + *(p+1) = '\0'; + } + } +#endif + return 0; +} + +static void appendstring(destp, src) + char **destp; + char *src; +{ + char *newstr; + newstr = malloc(strlen(*destp) + strlen(src) + 1); + strcpy(newstr, *destp); + strcat(newstr, src); + if (strlen(*destp) > 0) + free(*destp); + *destp = newstr; +} + +int lookupcard( char *name ) { + int i; + for (i = 0; i <= lastcard; i++) + if (strcmp(name, card[i].name) == 0) + return i; + return -1; +} + +static char *s3_comment = +"# Use Option \"nolinear\" if the server doesn't start up correctly\n" +"# (this avoids the linear framebuffer probe). If that fails try\n" +"# option \"nomemaccess\".\n" +"#\n" +"# Refer to /usr/X11R6/lib/doc/README.S3, and the XF86_S3 man page.\n"; + +static char *cirrus_comment = +"# Use Option \"no_bitblt\" if you have graphics problems. If that fails\n" +"# try Option \"noaccel\".\n" +"# Refer to /usr/X11R6/lib/doc/README.cirrus.\n" +"# To allow linear addressing, uncomment the Option line and the\n" +"# address that the card maps the framebuffer to.\n"; + +int parse_database() { + FILE *f; + char buf[128]; + int i, lineno; + char filename[128]; + +#ifndef __EMX__ + strcpy(filename, CARD_DATABASE_FILE); +#else + strcpy(filename, (char*)__XOS2RedirRoot(CARD_DATABASE_FILE)); +#endif + f = fopen(filename, "r"); + if (f == NULL) + return -1; + + lastcard = -1; + lineno = 0; + + for (;;) { + if (getline(f, buf)) + break; + lineno++; + if (buf[0] == '#') + /* Comment. */ + continue; + if (strncmp(buf, "END", 3) == 0) + /* End of database. */ + break; + if (strncmp(buf, "LINE", 4) == 0 && lastcard>=0) { + /* Line of Device comment. */ + char *lines; + /* Append to existing lines. */ + appendstring(&card[lastcard].lines, buf + 5); + continue; + } + /* + * The following keywords require the trailing newline + * to be deleted. + */ + i = strlen(buf); + buf[--i] = '\0'; + + /* remove trailing spaces or tabs */ + for(--i; i>=0 && (buf[i] == ' ' || buf[i] == '\011'); i--) ; + if (i>=0) + buf[i+1] = '\0'; + else + continue; /* skip empty lines */ + + if (strncmp(buf, "NAME", 4) == 0) { + /* New entry. */ + lastcard++; + card[lastcard].name = malloc(strlen(buf + 5) + 1); + strcpy(card[lastcard].name, buf + 5); + card[lastcard].chipset = NULL; + card[lastcard].ramdac = NULL; + card[lastcard].clockchip = NULL; + card[lastcard].dacspeed = NULL; + card[lastcard].flags = 0; + card[lastcard].lines = ""; + continue; + } + if (lastcard < 0) /* no NAME line found yet */ + continue; + if (strncmp(buf, "SEE", 3) == 0) { + /* Reference to another entry. */ + int i; + i = lookupcard(buf + 4); + if (i == -1) { + printf("Error in database, invalid reference: %s.\n", + buf + 4); + free(card[lastcard].name); + lastcard--; + continue; + } + if (card[lastcard].chipset == NULL) + card[lastcard].chipset = card[i].chipset; + if (card[lastcard].server == NULL) + card[lastcard].server = card[i].server; + if (card[lastcard].ramdac == NULL) + card[lastcard].ramdac = card[i].ramdac; + if (card[lastcard].clockchip == NULL) + card[lastcard].clockchip = card[i].clockchip; + if (card[lastcard].dacspeed == NULL) + card[lastcard].dacspeed = card[i].dacspeed; + card[lastcard].flags |= card[i].flags; + appendstring(&card[lastcard].lines, card[i].lines); + continue; + } + if (strncmp(buf, "CHIPSET", 7) == 0) { + /* Chipset description. */ + card[lastcard].chipset = malloc(strlen(buf + 8) + 1); + strcpy(card[lastcard].chipset, buf + 8); + continue; + } + if (strncmp(buf, "SERVER", 6) == 0) { + /* Server identifier. */ + card[lastcard].server = malloc(strlen(buf + 7) + 1); + strcpy(card[lastcard].server, buf + 7); + continue; + } + if (strncmp(buf, "RAMDAC", 6) == 0) { + /* Ramdac indentifier. */ + card[lastcard].ramdac = malloc(strlen(buf + 7) + 1); + strcpy(card[lastcard].ramdac, buf + 7); + continue; + } + if (strncmp(buf, "CLOCKCHIP", 9) == 0) { + /* Clockchip indentifier. */ + card[lastcard].clockchip = malloc(strlen(buf + 10) + 1); + strcpy(card[lastcard].clockchip, buf + 10); + card[lastcard].flags |= NOCLOCKPROBE; + continue; + } + if (strncmp(buf, "DACSPEED", 8) == 0) { + /* Clockchip indentifier. */ + card[lastcard].dacspeed = malloc(strlen(buf + 9) + 1); + strcpy(card[lastcard].dacspeed, buf + 9); + continue; + } + if (strncmp(buf, "NOCLOCKPROBE", 12) == 0) { + card[lastcard].flags |= NOCLOCKPROBE; + continue; + } + if (strncmp(buf, "UNSUPPORTED", 12) == 0) { + card[lastcard].flags |= UNSUPPORTED; + continue; + } + /* test for missing required fields */ + if (card[lastcard].server == NULL) { + fprintf(stderr, "Warning SERVER specification missing " + "in Card database entry %s (line %d).\n", + card[lastcard].name, lineno); + keypress(); + card[lastcard].server = "unknown"; + } + if (card[lastcard].chipset == NULL) { + fprintf(stderr, "Warning CHIPSET specification missing " + "in Card database entry %s (line %d).\n", + card[lastcard].name, lineno); + keypress(); + card[lastcard].chipset = "unknown"; + } + } + + fclose(f); + + /* + * Add general comments. + */ + for (i = 0; i <= lastcard; i++) { + if (card[i].server && strcmp(card[i].server, "S3") == 0) + appendstring(&card[i].lines, s3_comment); + if (card[i].chipset && + strncmp(card[i].chipset, "CL-GD", 5) == 0) + appendstring(&card[i].lines, cirrus_comment); + } + + sort_database(); + + return 0; +} + +#ifdef __STDC__ +#define CONST const +#else +#define CONST +#endif + +static int compare_card(e1, e2) + CONST void *e1; + CONST void *e2; +{ + return strcmp(((Card *)e1)->name, ((Card *)e2)->name); +} + +void sort_database() { + /* Each element is a bunch of words, but nothing too bad. */ + qsort(card, lastcard + 1, sizeof(Card), compare_card); +} diff --git a/hw/xfree86/utils/xorgconfig/cards.h b/hw/xfree86/utils/xorgconfig/cards.h new file mode 100644 index 000000000..11976d978 --- /dev/null +++ b/hw/xfree86/utils/xorgconfig/cards.h @@ -0,0 +1,36 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/xf86config/cards.h,v 3.3 1996/12/23 07:04:44 dawes Exp $ */ + + + + + +/* $Xorg: cards.h,v 1.3 2000/08/17 19:53:05 cpqbld Exp $ */ + +#ifndef CARD_DATABASE_FILE +#define CARD_DATABASE_FILE "Cards" +#endif + +#define MAX_CARDS 1000 + +typedef struct { + char *name; /* Name of the card. */ + char *chipset; /* Chipset (decriptive). */ + char *server; /* Server identifier. */ + char *ramdac; /* Ramdac identifier. */ + char *clockchip; /* Clockchip identifier. */ + char *dacspeed; /* DAC speed rating. */ + int flags; + char *lines; /* Additional Device section lines. */ +} Card; + +/* Flags: */ +#define NOCLOCKPROBE 0x1 /* Never probe clocks of the card. */ +#define UNSUPPORTED 0x2 /* Card is not supported (only VGA). */ + +extern int lastcard; + +extern Card card[MAX_CARDS]; + + +int parse_database(); + diff --git a/hw/xnest/Args.c b/hw/xnest/Args.c new file mode 100644 index 000000000..197d6cbe1 --- /dev/null +++ b/hw/xnest/Args.c @@ -0,0 +1,188 @@ +/* $Xorg: Args.c,v 1.3 2000/08/17 19:53:26 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Args.h" + +char *xnestDisplayName = NULL; +Bool xnestSynchronize = False; +Bool xnestFullGeneration = False; +int xnestDefaultClass; +Bool xnestUserDefaultClass = False; +int xnestDefaultDepth; +Bool xnestUserDefaultDepth = False; +Bool xnestSoftwareScreenSaver = False; +int xnestX; +int xnestY; +unsigned int xnestWidth; +unsigned int xnestHeight; +int xnestUserGeometry = 0; +int xnestBorderWidth; +Bool xnestUserBorderWidth = False; +char *xnestWindowName = NULL; +int xnestNumScreens = 0; +Bool xnestDoDirectColormaps = False; +Window xnestParentWindow = 0; + +int ddxProcessArgument (argc, argv, i) + int argc; + char *argv[] ; + int i; +{ + if (!strcmp(argv[i], "-display")) { + if (++i < argc) { + xnestDisplayName = argv[i]; + return 2; + } + return 0; + } + if (!strcmp(argv[i], "-sync")) { + xnestSynchronize = True; + return 1; + } + if (!strcmp(argv[i], "-full")) { + xnestFullGeneration = True; + return 1; + } + if (!strcmp(argv[i], "-class")) { + if (++i < argc) { + if (!strcmp(argv[i], "StaticGray")) { + xnestDefaultClass = StaticGray; + xnestUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "GrayScale")) { + xnestDefaultClass = GrayScale; + xnestUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "StaticColor")) { + xnestDefaultClass = StaticColor; + xnestUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "PseudoColor")) { + xnestDefaultClass = PseudoColor; + xnestUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "TrueColor")) { + xnestDefaultClass = TrueColor; + xnestUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "DirectColor")) { + xnestDefaultClass = DirectColor; + xnestUserDefaultClass = True; + return 2; + } + } + return 0; + } + if (!strcmp(argv[i], "-cc")) { + if (++i < argc && sscanf(argv[i], "%i", &xnestDefaultClass) == 1) { + if (xnestDefaultClass >= 0 && xnestDefaultClass <= 5) { + xnestUserDefaultClass = True; + /* lex the OS layer process it as well, so return 0 */ + } + } + return 0; + } + if (!strcmp(argv[i], "-depth")) { + if (++i < argc && sscanf(argv[i], "%i", &xnestDefaultDepth) == 1) { + if (xnestDefaultDepth > 0) { + xnestUserDefaultDepth = True; + return 2; + } + } + return 0; + } + if (!strcmp(argv[i], "-sss")) { + xnestSoftwareScreenSaver = True; + return 1; + } + if (!strcmp(argv[i], "-geometry")) { + if (++i < argc) { + xnestUserGeometry = XParseGeometry(argv[i], + &xnestX, &xnestY, + &xnestWidth, &xnestHeight); + if (xnestUserGeometry) return 2; + } + return 0; + } + if (!strcmp(argv[i], "-bw")) { + if (++i < argc && sscanf(argv[i], "%i", &xnestBorderWidth) == 1) { + if (xnestBorderWidth >= 0) { + xnestUserBorderWidth = True; + return 2; + } + } + return 0; + } + if (!strcmp(argv[i], "-name")) { + if (++i < argc) { + xnestWindowName = argv[i]; + return 2; + } + return 0; + } + if (!strcmp(argv[i], "-scrns")) { + if (++i < argc && sscanf(argv[i], "%i", &xnestNumScreens) == 1) { + if (xnestNumScreens > 0) { + if (xnestNumScreens > MAXSCREENS) { + ErrorF("Maximum number of screens is %d.\n", MAXSCREENS); + xnestNumScreens = MAXSCREENS; + } + return 2; + } + } + return 0; + } + if (!strcmp(argv[i], "-install")) { + xnestDoDirectColormaps = True; + return 1; + } + if (!strcmp(argv[i], "-parent")) { + if (++i < argc) { + xnestParentWindow = (XID) strtol (argv[i], (char**)NULL, 0); + return 2; + } + } + return 0; +} + +void ddxUseMsg() +{ + ErrorF("-display string display name of the real server\n"); + ErrorF("-sync sinchronize with the real server\n"); + ErrorF("-full utilize full regeneration\n"); + ErrorF("-class string default visual class\n"); + ErrorF("-depth int default depth\n"); + ErrorF("-sss use software screen saver\n"); + ErrorF("-geometry WxH+X+Y window size and position\n"); + ErrorF("-bw int window border width\n"); + ErrorF("-name string window name\n"); + ErrorF("-scrns int number of screens to generate\n"); + ErrorF("-install instal colormaps directly\n"); +} diff --git a/hw/xnest/Args.h b/hw/xnest/Args.h new file mode 100644 index 000000000..25e5cf8e8 --- /dev/null +++ b/hw/xnest/Args.h @@ -0,0 +1,38 @@ +/* $Xorg: Args.h,v 1.3 2000/08/17 19:53:27 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTARGC_H +#define XNESTARGS_H + +extern char *xnestDisplayName; +extern Bool xnestSynchronize; +extern Bool xnestFullGeneration; +extern int xnestDefaultClass; +extern Bool xnestUserDefaultClass; +extern int xnestDefaultDepth; +extern Bool xnestUserDefaultDepth; +extern Bool xnestSoftwareScreenSaver; +extern int xnestX; +extern int xnestY; +extern unsigned int xnestWidth; +extern unsigned int xnestHeight; +extern int xnestUserGeometry; +extern int xnestBorderWidth; +extern Bool xnestUserBorderWidth; +extern char *xnestWindowName; +extern int xnestNumScreens; +extern Bool xnestDoDirectColormaps; + +#endif /* XNESTARGS_H */ diff --git a/hw/xnest/Color.c b/hw/xnest/Color.c new file mode 100644 index 000000000..76e71aeee --- /dev/null +++ b/hw/xnest/Color.c @@ -0,0 +1,501 @@ +/* $Xorg: Color.c,v 1.3 2000/08/17 19:53:27 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "window.h" +#include "windowstr.h" +#include "colormapst.h" +#include "resource.h" + +#include "Xnest.h" + + +#include "Display.h" +#include "Screen.h" +#include "Color.h" +#include "Visual.h" +#include "XNWindow.h" +#include "Args.h" + +#define lowbit(x) ((x) & (~(x) + 1)) + +static ColormapPtr InstalledMaps[MAXSCREENS]; + +Bool xnestCreateColormap(pCmap) + ColormapPtr pCmap; +{ + VisualPtr pVisual; + XColor *colors; + int i, ncolors; + Pixel red, green, blue; + Pixel redInc, greenInc, blueInc; + + pVisual = pCmap->pVisual; + ncolors = pVisual->ColormapEntries; + + pCmap->devPriv = (pointer)xalloc(sizeof(xnestPrivColormap)); + + xnestColormapPriv(pCmap)->colormap = + XCreateColormap(xnestDisplay, + xnestDefaultWindows[pCmap->pScreen->myNum], + xnestVisual(pVisual), + (pVisual->class & DynamicClass) ? + AllocAll : AllocNone); + + + switch (pVisual->class) { + case StaticGray: /* read only */ + colors = (XColor *)xalloc(ncolors * sizeof(XColor)); + for (i = 0; i < ncolors; i++) + colors[i].pixel = i; + XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->red[i].co.local.green = colors[i].red; + pCmap->red[i].co.local.blue = colors[i].red; + } + xfree(colors); + break; + + case StaticColor: /* read only */ + colors = (XColor *)xalloc(ncolors * sizeof(XColor)); + for (i = 0; i < ncolors; i++) + colors[i].pixel = i; + XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->red[i].co.local.green = colors[i].green; + pCmap->red[i].co.local.blue = colors[i].blue; + } + xfree(colors); + break; + + case TrueColor: /* read only */ + colors = (XColor *)xalloc(ncolors * sizeof(XColor)); + red = green = blue = 0L; + redInc = lowbit(pVisual->redMask); + greenInc = lowbit(pVisual->greenMask); + blueInc = lowbit(pVisual->blueMask); + for (i = 0; i < ncolors; i++) { + colors[i].pixel = red | green | blue; + red += redInc; + if (red > pVisual->redMask) red = 0L; + green += greenInc; + if (green > pVisual->greenMask) green = 0L; + blue += blueInc; + if (blue > pVisual->blueMask) blue = 0L; + } + XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->green[i].co.local.green = colors[i].green; + pCmap->blue[i].co.local.blue = colors[i].blue; + } + xfree(colors); + break; + + case GrayScale: /* read and write */ + break; + + case PseudoColor: /* read and write */ + break; + + case DirectColor: /* read and write */ + break; + } + + return True; +} + +void xnestDestroyColormap (pCmap) + ColormapPtr pCmap; +{ + XFreeColormap(xnestDisplay, xnestColormap(pCmap)); + xfree(pCmap->devPriv); +} + +#define SEARCH_PREDICATE \ + (xnestWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i]) + +static int xnestCountInstalledColormapWindows(pWin, ptr) + WindowPtr pWin; + pointer ptr; +{ + xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr; + int i; + + for (i = 0; i < icws->numCmapIDs; i++) + if (SEARCH_PREDICATE) { + icws->numWindows++; + return WT_DONTWALKCHILDREN; + } + + return WT_WALKCHILDREN; +} + +static int xnestGetInstalledColormapWindows(pWin, ptr) + WindowPtr pWin; + pointer ptr; +{ + xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr; + int i; + + for (i = 0; i < icws->numCmapIDs; i++) + if (SEARCH_PREDICATE) { + icws->windows[icws->index++] = xnestWindow(pWin); + return WT_DONTWALKCHILDREN; + } + + return WT_WALKCHILDREN; +} + +static Window *xnestOldInstalledColormapWindows = NULL; +static int xnestNumOldInstalledColormapWindows = 0; + +static Bool xnestSameInstalledColormapWindows(windows, numWindows) + Window *windows; + int numWindows; +{ + if (xnestNumOldInstalledColormapWindows != numWindows) + return False; + + if (xnestOldInstalledColormapWindows == windows) + return True; + + if (xnestOldInstalledColormapWindows == NULL || windows == NULL) + return False; + + if (memcmp(xnestOldInstalledColormapWindows, windows, + numWindows * sizeof(Window))) + return False; + + return True; +} + +void xnestSetInstalledColormapWindows(pScreen) + ScreenPtr pScreen; +{ + xnestInstalledColormapWindows icws; + int numWindows; + + icws.cmapIDs = (Colormap *)xalloc(pScreen->maxInstalledCmaps * + sizeof(Colormap)); + icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs); + icws.numWindows = 0; + WalkTree(pScreen, xnestCountInstalledColormapWindows, (pointer)&icws); + if (icws.numWindows) { + icws.windows = (Window *)xalloc((icws.numWindows + 1) * sizeof(Window)); + icws.index = 0; + WalkTree(pScreen, xnestGetInstalledColormapWindows, (pointer)&icws); + icws.windows[icws.numWindows] = xnestDefaultWindows[pScreen->myNum]; + numWindows = icws.numWindows + 1; + } + else { + icws.windows = NULL; + numWindows = 0; + } + + xfree(icws.cmapIDs); + + if (!xnestSameInstalledColormapWindows(icws.windows, icws.numWindows)) { + if (xnestOldInstalledColormapWindows) + xfree(xnestOldInstalledColormapWindows); + +#ifdef _XSERVER64 + { + int i; + Window64 *windows = (Window64 *)xalloc(numWindows * sizeof(Window64)); + + for(i = 0; i < numWindows; ++i) + windows[i] = icws.windows[i]; + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + windows, numWindows); + xfree(windows); + } +#else + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + icws.windows, numWindows); +#endif + + xnestOldInstalledColormapWindows = icws.windows; + xnestNumOldInstalledColormapWindows = icws.numWindows; + +#ifdef DUMB_WINDOW_MANAGERS + /* + This code is for dumb window managers. + This will only work with default local visual colormaps. + */ + if (icws.numWindows) + { + WindowPtr pWin; + Visual *visual; + ColormapPtr pCmap; + + pWin = xnestWindowPtr(icws.windows[0]); + visual = xnestVisualFromID(pScreen, wVisual(pWin)); + + if (visual == xnestDefaultVisual(pScreen)) + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), + RT_COLORMAP); + else + pCmap = (ColormapPtr)LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + + XSetWindowColormap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + xnestColormap(pCmap)); + } +#endif /* DUMB_WINDOW_MANAGERS */ + } + else + if (icws.windows) xfree(icws.windows); +} + +void xnestSetScreenSaverColormapWindow(pScreen) + ScreenPtr pScreen; +{ + if (xnestOldInstalledColormapWindows) + xfree(xnestOldInstalledColormapWindows); + +#ifdef _XSERVER64 + { + Window64 window; + + window = xnestScreenSaverWindows[pScreen->myNum]; + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + &window, 1); + xnestScreenSaverWindows[pScreen->myNum] = window; + } +#else + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + &xnestScreenSaverWindows[pScreen->myNum], 1); +#endif /* _XSERVER64 */ + + xnestOldInstalledColormapWindows = NULL; + xnestNumOldInstalledColormapWindows = 0; + + xnestDirectUninstallColormaps(pScreen); +} + +void xnestDirectInstallColormaps(pScreen) + ScreenPtr pScreen; +{ + int i, n; + Colormap pCmapIDs[MAXCMAPS]; + + if (!xnestDoDirectColormaps) return; + + n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); + + for (i = 0; i < n; i++) { + ColormapPtr pCmap; + + pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP); + if (pCmap) + XInstallColormap(xnestDisplay, xnestColormap(pCmap)); + } +} + +void xnestDirectUninstallColormaps(pScreen) + ScreenPtr pScreen; +{ + int i, n; + Colormap pCmapIDs[MAXCMAPS]; + + if (!xnestDoDirectColormaps) return; + + n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); + + for (i = 0; i < n; i++) { + ColormapPtr pCmap; + + pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP); + if (pCmap) + XUninstallColormap(xnestDisplay, xnestColormap(pCmap)); + } +} + +void xnestInstallColormap(pCmap) + ColormapPtr pCmap; +{ + int index; + ColormapPtr pOldCmap; + + index = pCmap->pScreen->myNum; + pOldCmap = InstalledMaps[index]; + + if(pCmap != pOldCmap) + { + xnestDirectUninstallColormaps(pCmap->pScreen); + + /* Uninstall pInstalledMap. Notify all interested parties. */ + if(pOldCmap != (ColormapPtr)None) + WalkTree(pCmap->pScreen, TellLostMap, (pointer)&pOldCmap->mid); + + InstalledMaps[index] = pCmap; + WalkTree(pCmap->pScreen, TellGainedMap, (pointer)&pCmap->mid); + + xnestSetInstalledColormapWindows(pCmap->pScreen); + xnestDirectInstallColormaps(pCmap->pScreen); + } +} + +void xnestUninstallColormap(pCmap) + ColormapPtr pCmap; +{ + int index; + ColormapPtr pCurCmap; + + index = pCmap->pScreen->myNum; + pCurCmap = InstalledMaps[index]; + + if(pCmap == pCurCmap) + { + if (pCmap->mid != pCmap->pScreen->defColormap) + { + pCurCmap = (ColormapPtr)LookupIDByType(pCmap->pScreen->defColormap, + RT_COLORMAP); + (*pCmap->pScreen->InstallColormap)(pCurCmap); + } + } +} + +static Bool xnestInstalledDefaultColormap = False; + +int xnestListInstalledColormaps(pScreen, pCmapIDs) + ScreenPtr pScreen; + Colormap *pCmapIDs; +{ + if (xnestInstalledDefaultColormap) { + *pCmapIDs = InstalledMaps[pScreen->myNum]->mid; + return 1; + } + else + return 0; +} + +void xnestStoreColors(pCmap, nColors, pColors) + ColormapPtr pCmap; + int nColors; + xColorItem *pColors; +{ + if (pCmap->pVisual->class & DynamicClass) +#ifdef _XSERVER64 + { + int i; + XColor *pColors64 = (XColor *)xalloc(nColors * sizeof(XColor) ); + + for(i = 0; i < nColors; ++i) + { + pColors64[i].pixel = pColors[i].pixel; + pColors64[i].red = pColors[i].red; + pColors64[i].green = pColors[i].green; + pColors64[i].blue = pColors[i].blue; + pColors64[i].flags = pColors[i].flags; + } + XStoreColors(xnestDisplay, xnestColormap(pCmap), pColors64, nColors); + xfree(pColors64); + } +#else + XStoreColors(xnestDisplay, xnestColormap(pCmap), + (XColor *)pColors, nColors); +#endif +} + +void xnestResolveColor(pRed, pGreen, pBlue, pVisual) + unsigned short *pRed; + unsigned short *pGreen; + unsigned short *pBlue; + VisualPtr pVisual; +{ + int shift; + unsigned int lim; + + shift = 16 - pVisual->bitsPerRGBValue; + lim = (1 << pVisual->bitsPerRGBValue) - 1; + + if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) + { + /* rescale to rgb bits */ + *pRed = ((*pRed >> shift) * 65535) / lim; + *pGreen = ((*pGreen >> shift) * 65535) / lim; + *pBlue = ((*pBlue >> shift) * 65535) / lim; + } + else if (pVisual->class == GrayScale) + { + /* rescale to gray then rgb bits */ + *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; + *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; + } + else if (pVisual->class == StaticGray) + { + unsigned int limg; + + limg = pVisual->ColormapEntries - 1; + /* rescale to gray then [0..limg] then [0..65535] then rgb bits */ + *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; + *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg; + *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; + } + else + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + /* rescale to [0..limN] then [0..65535] then rgb bits */ + *pRed = ((((((*pRed * (limr + 1)) >> 16) * + 65535) / limr) >> shift) * 65535) / lim; + *pGreen = ((((((*pGreen * (limg + 1)) >> 16) * + 65535) / limg) >> shift) * 65535) / lim; + *pBlue = ((((((*pBlue * (limb + 1)) >> 16) * + 65535) / limb) >> shift) * 65535) / lim; + } +} + +Bool xnestCreateDefaultColormap(pScreen) + ScreenPtr pScreen; +{ + VisualPtr pVisual; + ColormapPtr pCmap; + unsigned short zero = 0, ones = 0xFFFF; + Pixel wp, bp; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++); + + if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap, + (pVisual->class & DynamicClass) ? AllocNone : AllocAll, 0) + != Success) + return False; + + wp = pScreen->whitePixel; + bp = pScreen->blackPixel; + if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) != + Success) || + (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) != + Success)) + return FALSE; + pScreen->whitePixel = wp; + pScreen->blackPixel = bp; + (*pScreen->InstallColormap)(pCmap); + + xnestInstalledDefaultColormap = True; + + return True; +} diff --git a/hw/xnest/Color.h b/hw/xnest/Color.h new file mode 100644 index 000000000..6ba6cd97a --- /dev/null +++ b/hw/xnest/Color.h @@ -0,0 +1,56 @@ +/* $Xorg: Color.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTCOLOR_H +#define XNESTCOLOR_H + +#define DUMB_WINDOW_MANAGERS + +#define MAXCMAPS 1 +#define MINCMAPS 1 + +typedef struct { + Colormap colormap; +} xnestPrivColormap; + +typedef struct { + int numCmapIDs; + Colormap *cmapIDs; + int numWindows; + Window *windows; + int index; +} xnestInstalledColormapWindows; + +#define xnestColormapPriv(pCmap) \ + ((xnestPrivColormap *)((pCmap)->devPriv)) + +#define xnestColormap(pCmap) (xnestColormapPriv(pCmap)->colormap) + +#define xnestPixel(pixel) (pixel) + +Bool xnestCreateColormap(); +void xnestDestroyColormap (); +void xnestSetInstalledColormapWindows(); +void xnestSetScreenSaverColormapWindow(); +void xnestDirectInstallColormaps(); +void xnestDirectUninstallColormaps(); +void xnestInstallColormap(); +void xnestUninstallColormap(); +int xnestListInstalledColormaps(); +void xnestStoreColors(); +void xnestResolveColor(); +Bool xnestCreateDefaultColormap(); + +#endif /* XNESTCOLOR_H */ diff --git a/hw/xnest/Cursor.c b/hw/xnest/Cursor.c new file mode 100644 index 000000000..6915df7a2 --- /dev/null +++ b/hw/xnest/Cursor.c @@ -0,0 +1,214 @@ +/* $Xorg: Cursor.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "Cursor.h" +#include "Visual.h" +#include "Keyboard.h" +#include "Args.h" + +void xnestConstrainCursor(pScreen, pBox) + ScreenPtr pScreen; + BoxPtr pBox; +{ +#ifdef _XSERVER64 + Window64 wroot; +#else + Window wroot; +#endif + + int wx, wy; + unsigned int wwidth, wheight; + unsigned int wborderwidth; + unsigned int wdepth; + + XGetGeometry(xnestDisplay, xnestDefaultWindows[pScreen->myNum], &wroot, + &wx, &wy, &wwidth, &wheight, &wborderwidth, &wdepth); + + if (pBox->x1 <= 0 && pBox->y1 <= 0 && + pBox->x2 >= wwidth && pBox->y2 >= wheight) + XUngrabPointer(xnestDisplay, CurrentTime); + else { + XReparentWindow(xnestDisplay, xnestConfineWindow, + xnestDefaultWindows[pScreen->myNum], + pBox->x1, pBox->y1); + XResizeWindow(xnestDisplay, xnestConfineWindow, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); + + XGrabPointer(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + True, + xnestEventMask & (~XNEST_KEYBOARD_EVENT_MASK|KeymapStateMask), + GrabModeAsync, GrabModeAsync, + xnestConfineWindow, + None, CurrentTime); + } +} + +void xnestCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox) + ScreenPtr pScreen; + CursorPtr pCursor; + BoxPtr pHotBox; + BoxPtr pTopLeftBox; +{ + *pTopLeftBox = *pHotBox; +} + +Bool xnestDisplayCursor(pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + XDefineCursor(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + xnestCursor(pCursor, pScreen)); + return True; +} + +Bool xnestRealizeCursor(pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + XImage *ximage; + Pixmap source, mask; + XColor fg_color, bg_color; + unsigned long valuemask; + XGCValues values; + + valuemask = GCFunction | + GCPlaneMask | + GCForeground | + GCBackground | + GCClipMask; + + values.function = GXcopy; + values.plane_mask = AllPlanes; + values.foreground = 1L; + values.background = 0L; + values.clip_mask = None; + + XChangeGC(xnestDisplay, xnestBitmapGC, valuemask, &values); + + source = XCreatePixmap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + pCursor->bits->width, + pCursor->bits->height, + 1); + + mask = XCreatePixmap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + pCursor->bits->width, + pCursor->bits->height, + 1); + + ximage = XCreateImage(xnestDisplay, + xnestDefaultVisual(pScreen), + 1, XYBitmap, 0, + (char *)pCursor->bits->source, + pCursor->bits->width, + pCursor->bits->height, + BitmapPad(xnestDisplay), 0); + + XPutImage(xnestDisplay, source, xnestBitmapGC, ximage, + 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); + + XFree(ximage); + + ximage = XCreateImage(xnestDisplay, + xnestDefaultVisual(pScreen), + 1, XYBitmap, 0, + (char *)pCursor->bits->mask, + pCursor->bits->width, + pCursor->bits->height, + BitmapPad(xnestDisplay), 0); + + XPutImage(xnestDisplay, mask, xnestBitmapGC, ximage, + 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); + + XFree(ximage); + + fg_color.red = pCursor->foreRed; + fg_color.green = pCursor->foreGreen; + fg_color.blue = pCursor->foreBlue; + + bg_color.red = pCursor->backRed; + bg_color.green = pCursor->backGreen; + bg_color.blue = pCursor->backBlue; + + pCursor->devPriv[pScreen->myNum] = (pointer)xalloc(sizeof(xnestPrivCursor)); + xnestCursorPriv(pCursor, pScreen)->cursor = + XCreatePixmapCursor(xnestDisplay, source, mask, &fg_color, &bg_color, + pCursor->bits->xhot, pCursor->bits->yhot); + + XFreePixmap(xnestDisplay, source); + XFreePixmap(xnestDisplay, mask); + + return True; +} + +Bool xnestUnrealizeCursor(pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + XFreeCursor(xnestDisplay, xnestCursor(pCursor, pScreen)); + xfree(xnestCursorPriv(pCursor, pScreen)); + return True; +} + +void xnestRecolorCursor(pScreen, pCursor, displayed) + ScreenPtr pScreen; + CursorPtr pCursor; + Bool displayed; +{ + XColor fg_color, bg_color; + + fg_color.red = pCursor->foreRed; + fg_color.green = pCursor->foreGreen; + fg_color.blue = pCursor->foreBlue; + + bg_color.red = pCursor->backRed; + bg_color.green = pCursor->backGreen; + bg_color.blue = pCursor->backBlue; + + XRecolorCursor(xnestDisplay, + xnestCursor(pCursor, pScreen), + &fg_color, &bg_color); +} + +Bool xnestSetCursorPosition(pScreen, x, y, generateEvent) + ScreenPtr pScreen; + int x, y; + Bool generateEvent; +{ + int i; + + for (i = 0; i < xnestNumScreens; i++) + XWarpPointer(xnestDisplay, xnestDefaultWindows[i], + xnestDefaultWindows[pScreen->myNum], + 0, 0, 0, 0, x, y); + + return True; +} diff --git a/hw/xnest/Display.c b/hw/xnest/Display.c new file mode 100644 index 000000000..5f3bdb9a5 --- /dev/null +++ b/hw/xnest/Display.c @@ -0,0 +1,201 @@ +/* $Xorg: Display.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + + +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Init.h" +#include "Args.h" + +#include "icon" +#include "screensaver" + +Display *xnestDisplay = NULL; +XVisualInfo *xnestVisuals; +int xnestNumVisuals; +int xnestDefaultVisualIndex; +Colormap *xnestDefaultColormaps; +int xnestNumDefaultColormaps; +int *xnestDepths; +int xnestNumDepths; +XPixmapFormatValues *xnestPixmapFormats; +int xnestNumPixmapFormats; +Pixel xnestBlackPixel; +Pixel xnestWhitePixel; +Drawable xnestDefaultDrawables[MAXDEPTH + 1]; +Pixmap xnestIconBitmap; +Pixmap xnestScreenSaverPixmap; +XlibGC xnestBitmapGC; +Window xnestConfineWindow; +unsigned long xnestEventMask; + +void xnestOpenDisplay(argc, argv) + int argc; + char *argv[]; +{ + XVisualInfo vi; + long mask; + int i, j; + extern Window xnestParentWindow; + + if (!xnestDoFullGeneration) return; + + xnestCloseDisplay(); + + xnestDisplay = XOpenDisplay(xnestDisplayName); + if (xnestDisplay == NULL) + FatalError("Unable to open display \"%s\".\n", + XDisplayName(xnestDisplayName)); + + if (xnestSynchronize) + XSynchronize(xnestDisplay, True); + + mask = VisualScreenMask; + vi.screen = DefaultScreen(xnestDisplay); + xnestVisuals = XGetVisualInfo(xnestDisplay, mask, &vi, &xnestNumVisuals); + if (xnestNumVisuals == 0 || xnestVisuals == NULL) + FatalError("Unable to find any visuals.\n"); + + if (xnestUserDefaultClass || xnestUserDefaultDepth) { + xnestDefaultVisualIndex = UNDEFINED; + for (i = 0; i < xnestNumVisuals; i++) + if ((!xnestUserDefaultClass || + xnestVisuals[i].class == xnestDefaultClass) + && + (!xnestUserDefaultDepth || + xnestVisuals[i].depth == xnestDefaultDepth)) { + xnestDefaultVisualIndex = i; + break; + } + if (xnestDefaultVisualIndex == UNDEFINED) + FatalError("Uable to find desird default visual.\n"); + } + else { + vi.visualid = XVisualIDFromVisual(DefaultVisual(xnestDisplay, + DefaultScreen(xnestDisplay))); + xnestDefaultVisualIndex = 0; + for (i = 0; i < xnestNumVisuals; i++) + if (vi.visualid == xnestVisuals[i].visualid) + xnestDefaultVisualIndex = i; + } + + xnestNumDefaultColormaps = xnestNumVisuals; + xnestDefaultColormaps = (Colormap *)xalloc(xnestNumDefaultColormaps * + sizeof(Colormap)); + for (i = 0; i < xnestNumDefaultColormaps; i++) + xnestDefaultColormaps[i] = XCreateColormap(xnestDisplay, + DefaultRootWindow(xnestDisplay), + xnestVisuals[i].visual, + AllocNone); + + xnestDepths = XListDepths(xnestDisplay, DefaultScreen(xnestDisplay), + &xnestNumDepths); + + xnestPixmapFormats = XListPixmapFormats(xnestDisplay, + &xnestNumPixmapFormats); + + xnestBlackPixel = BlackPixel(xnestDisplay, DefaultScreen(xnestDisplay)); + xnestWhitePixel = WhitePixel(xnestDisplay, DefaultScreen(xnestDisplay)); + + if (xnestParentWindow != (Window) 0) + xnestEventMask = StructureNotifyMask; + else + xnestEventMask = 0L; + + for (i = 0; i <= MAXDEPTH; i++) + xnestDefaultDrawables[i] = None; + + for (i = 0; i < xnestNumPixmapFormats; i++) + for (j = 0; j < xnestNumDepths; j++) + if (xnestPixmapFormats[i].depth == 1 || + xnestPixmapFormats[i].depth == xnestDepths[j]) { + xnestDefaultDrawables[xnestPixmapFormats[i].depth] = + XCreatePixmap(xnestDisplay, DefaultRootWindow(xnestDisplay), + 1, 1, xnestPixmapFormats[i].depth); + } + + xnestBitmapGC = XCreateGC(xnestDisplay, xnestDefaultDrawables[1], 0L, NULL); + + xnestConfineWindow = XCreateWindow(xnestDisplay, + DefaultRootWindow(xnestDisplay), + 0, 0, 1, 1, 0, 0, + InputOnly, + CopyFromParent, + 0L, NULL); + + if (!(xnestUserGeometry & XValue)) + xnestX = 0; + + if (!(xnestUserGeometry & YValue)) + xnestY = 0; + + if (xnestParentWindow == 0) { + if (!(xnestUserGeometry & WidthValue)) + xnestWidth = 3 * DisplayWidth(xnestDisplay, + DefaultScreen(xnestDisplay)) / 4; + + if (!(xnestUserGeometry & HeightValue)) + xnestHeight = 3 * DisplayHeight(xnestDisplay, + DefaultScreen(xnestDisplay)) / 4; + } + + if (!xnestUserBorderWidth) + xnestBorderWidth = 1; + + xnestIconBitmap = + XCreateBitmapFromData(xnestDisplay, + DefaultRootWindow(xnestDisplay), + (char *)icon_bits, + icon_width, + icon_height); + + xnestScreenSaverPixmap = + XCreatePixmapFromBitmapData(xnestDisplay, + DefaultRootWindow(xnestDisplay), + (char *)screensaver_bits, + screensaver_width, + screensaver_height, + xnestWhitePixel, + xnestBlackPixel, + DefaultDepth(xnestDisplay, + DefaultScreen(xnestDisplay))); +} + +void xnestCloseDisplay() +{ + int i; + + if (!xnestDoFullGeneration || !xnestDisplay) return; + + /* + If xnestDoFullGeneration all x resources will be destroyed upon closing + the display connection. There is no need to generate extra protocol. + */ + + xfree(xnestDefaultColormaps); + XFree(xnestVisuals); + XFree(xnestDepths); + XFree(xnestPixmapFormats); + XCloseDisplay(xnestDisplay); +} diff --git a/hw/xnest/Display.h b/hw/xnest/Display.h new file mode 100644 index 000000000..3699d18d5 --- /dev/null +++ b/hw/xnest/Display.h @@ -0,0 +1,46 @@ +/* $Xorg: Display.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTCOMMON_H +#define XNESTCOMMON_H + +#define UNDEFINED -1 + +#define MAXDEPTH 32 +#define MAXVISUALSPERDEPTH 6 + +extern Display *xnestDisplay; +extern XVisualInfo *xnestVisuals; +extern int xnestNumVisuals; +extern int xnestDefaultVisualIndex; +extern Colormap *xnestDefaultColormaps; +extern int xnestNumDefaultClormaps; +extern int *xnestDepths; +extern int xnestNumDepths; +extern XPixmapFormatValues *xnestPixmapFormats; +extern int xnestNumPixmapFormats; +extern Pixel xnestBlackPixel; +extern Pixel xnestWhitePixel; +extern Drawable xnestDefaultDrawables[MAXDEPTH + 1]; +extern Pixmap xnestIconBitmap; +extern Pixmap xnestScreenSaverPixmap; +extern XlibGC xnestBitmapGC; +extern Window xnestConfineWindow; +extern unsigned long xnestEventMask; + +void xnestOpenDisplay(); +void xnestCloseDisplay(); + +#endif /* XNESTCOMMON_H */ diff --git a/hw/xnest/Drawable.h b/hw/xnest/Drawable.h new file mode 100644 index 000000000..47b723731 --- /dev/null +++ b/hw/xnest/Drawable.h @@ -0,0 +1,27 @@ +/* $Xorg: Drawable.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTDRAWABLE_H +#define XNESTDRAWABLE_H + +#include "XNWindow.h" +#include "Pixmap.h" + +#define xnestDrawable(pDrawable) \ + ((pDrawable)->type == DRAWABLE_WINDOW ? \ + xnestWindow((WindowPtr)pDrawable) : \ + xnestPixmap((PixmapPtr)pDrawable)) + +#endif /* XNESTDRAWABLE_H */ diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c new file mode 100644 index 000000000..760f1962a --- /dev/null +++ b/hw/xnest/Events.c @@ -0,0 +1,189 @@ +/* $Xorg: Events.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "XNWindow.h" +#include "Events.h" + +CARD32 lastEventTime = 0; + +void ProcessInputEvents() +{ + mieqProcessInputEvents(); +} + +int TimeSinceLastInputEvent() +{ + if (lastEventTime == 0) + lastEventTime = GetTimeInMillis(); + return GetTimeInMillis() - lastEventTime; +} + +void SetTimeSinceLastInputEvent() +{ + lastEventTime = GetTimeInMillis(); +} + +static Bool xnestExposurePredicate(display, event, args) + Display *display; + XEvent *event; + char *args; +{ + return (event->type == Expose || event->type == ProcessedExpose); +} + +static Bool xnestNotExposurePredicate(display, event, args) + Display *display; + XEvent *event; + char *args; +{ + return !xnestExposurePredicate(display, event, args); +} + +void xnestCollectExposures() +{ + XEvent X; + WindowPtr pWin; + RegionRec Rgn; + BoxRec Box; + + while (XCheckIfEvent(xnestDisplay, &X, xnestExposurePredicate, NULL)) { + pWin = xnestWindowPtr(X.xexpose.window); + + if (pWin) { + Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + X.xexpose.x; + Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + X.xexpose.y; + Box.x2 = Box.x1 + X.xexpose.width; + Box.y2 = Box.y1 + X.xexpose.height; + + REGION_INIT(pWin->drawable.pScreen, &Rgn, &Box, 1); + + miWindowExposures(pWin, &Rgn, NullRegion); + } + } +} + +void xnestCollectEvents() +{ + XEvent X; + xEvent x; + ScreenPtr pScreen; + extern Window xnestParentWindow; + + while (XCheckIfEvent(xnestDisplay, &X, xnestNotExposurePredicate, NULL)) { + switch (X.type) { + case KeyPress: + x.u.u.type = KeyPress; + x.u.u.detail = X.xkey.keycode; + x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis(); + mieqEnqueue(&x); + break; + + case KeyRelease: + x.u.u.type = KeyRelease; + x.u.u.detail = X.xkey.keycode; + x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis(); + mieqEnqueue(&x); + break; + + case ButtonPress: + x.u.u.type = ButtonPress; + x.u.u.detail = X.xbutton.button; + x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis(); + mieqEnqueue(&x); + break; + + case ButtonRelease: + x.u.u.type = ButtonRelease; + x.u.u.detail = X.xbutton.button; + x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis(); + mieqEnqueue(&x); + break; + + case MotionNotify: + x.u.u.type = MotionNotify; + x.u.keyButtonPointer.rootX = X.xmotion.x; + x.u.keyButtonPointer.rootY = X.xmotion.y; + x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis(); + mieqEnqueue(&x); + break; + + case FocusIn: + if (X.xfocus.detail != NotifyInferior) { + pScreen = xnestScreen(X.xfocus.window); + if (pScreen) + xnestDirectInstallColormaps(pScreen); + } + break; + + case FocusOut: + if (X.xfocus.detail != NotifyInferior) { + pScreen = xnestScreen(X.xfocus.window); + if (pScreen) + xnestDirectUninstallColormaps(pScreen); + } + break; + + case KeymapNotify: + break; + + case EnterNotify: + if (X.xcrossing.detail != NotifyInferior) { + pScreen = xnestScreen(X.xcrossing.window); + if (pScreen) { + NewCurrentScreen(pScreen, X.xcrossing.x, X.xcrossing.y); + x.u.u.type = MotionNotify; + x.u.keyButtonPointer.rootX = X.xcrossing.x; + x.u.keyButtonPointer.rootY = X.xcrossing.y; + x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis(); + mieqEnqueue(&x); + xnestDirectInstallColormaps(pScreen); + } + } + break; + + case LeaveNotify: + if (X.xcrossing.detail != NotifyInferior) { + pScreen = xnestScreen(X.xcrossing.window); + if (pScreen) { + xnestDirectUninstallColormaps(pScreen); + } + } + break; + + case DestroyNotify: + if (xnestParentWindow != (Window) 0 && + X.xdestroywindow.window == xnestParentWindow) + exit (0); + break; + + default: + ErrorF("xnest warning: unhandled event\n"); + break; + } + } +} diff --git a/hw/xnest/Events.h b/hw/xnest/Events.h new file mode 100644 index 000000000..dfb44acf5 --- /dev/null +++ b/hw/xnest/Events.h @@ -0,0 +1,28 @@ +/* $Xorg: Events.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTEVENTS_H +#define XNESTEVENTS_H + +#include + +#define ProcessedExpose (LASTEvent + 1) + +extern CARD32 lastEventTime; + +void xnestCollectExposures(); +void xnestCollectEvents(); + +#endif /* XNESTEVENTS_H */ diff --git a/hw/xnest/Font.c b/hw/xnest/Font.c new file mode 100644 index 000000000..562db362d --- /dev/null +++ b/hw/xnest/Font.c @@ -0,0 +1,87 @@ +/* $Xorg: Font.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xatom.h" +#include "Xproto.h" +#include "misc.h" +#include "miscstruct.h" +#include "font.h" +#include "fontstruct.h" +#include "scrnintstr.h" + +#include "Xnest.h" + +#include "Display.h" +#include "XNFont.h" + +int xnestFontPrivateIndex; + +Bool xnestRealizeFont(pScreen, pFont) + ScreenPtr pScreen; + FontPtr pFont; +{ + pointer priv; + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + + FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); + + if (requestingClient && XpClientIsPrintClient(requestingClient, NULL)) + return True; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if (props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return False; + + name = (char *)NameForAtom(value_atom); + + if (!name) return False; + + priv = (pointer)xalloc(sizeof(xnestPrivFont)); + FontSetPrivate(pFont, xnestFontPrivateIndex, priv); + + xnestFontPriv(pFont)->font_struct = XLoadQueryFont(xnestDisplay, name); + + if (!xnestFontStruct(pFont)) return False; + + return True; +} + + +Bool xnestUnrealizeFont(pScreen, pFont) + ScreenPtr pScreen; + FontPtr pFont; +{ + if (xnestFontPriv(pFont)) { + if (xnestFontStruct(pFont)) + XFreeFont(xnestDisplay, xnestFontStruct(pFont)); + xfree(xnestFontPriv(pFont)); + FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); + } + return True; +} diff --git a/hw/xnest/GC.c b/hw/xnest/GC.c new file mode 100644 index 000000000..3e16c95c2 --- /dev/null +++ b/hw/xnest/GC.c @@ -0,0 +1,345 @@ +/* $Xorg: GC.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "fontstruct.h" +#include "mistruct.h" +#include "region.h" + +#include "Xnest.h" + +#include "Display.h" +#include "XNGC.h" +#include "GCOps.h" +#include "Drawable.h" +#include "XNFont.h" +#include "Color.h" + +int xnestGCPrivateIndex; + +static GCFuncs xnestFuncs = { + xnestValidateGC, + xnestChangeGC, + xnestCopyGC, + xnestDestroyGC, + xnestChangeClip, + xnestDestroyClip, + xnestCopyClip, +}; + +static GCOps xnestOps = { + xnestFillSpans, + xnestSetSpans, + xnestPutImage, + xnestCopyArea, + xnestCopyPlane, + xnestPolyPoint, + xnestPolylines, + xnestPolySegment, + xnestPolyRectangle, + xnestPolyArc, + xnestFillPolygon, + xnestPolyFillRect, + xnestPolyFillArc, + xnestPolyText8, + xnestPolyText16, + xnestImageText8, + xnestImageText16, + xnestImageGlyphBlt, + xnestPolyGlyphBlt, + xnestPushPixels +}; + +Bool xnestCreateGC(pGC) + GCPtr pGC; +{ + pGC->clientClipType = CT_NONE; + pGC->clientClip = NULL; + + pGC->funcs = &xnestFuncs; + pGC->ops = &xnestOps; + + pGC->miTranslate = 1; + + xnestGCPriv(pGC)->gc = XCreateGC(xnestDisplay, + xnestDefaultDrawables[pGC->depth], + 0L, NULL); + xnestGCPriv(pGC)->nClipRects = 0; + + return True; +} + +void xnestValidateGC(pGC, changes, pDrawable) + GCPtr pGC; + unsigned long changes; + DrawablePtr pDrawable; +{ + pGC->lastWinOrg.x = pDrawable->x; + pGC->lastWinOrg.y = pDrawable->y; +} + +void xnestChangeGC(pGC, mask) + GC *pGC; + unsigned long mask; +{ + XGCValues values; + + if (mask & GCFunction) + values.function = pGC->alu; + + if (mask & GCPlaneMask) + values.plane_mask = pGC->planemask; + + if (mask & GCForeground) + values.foreground = xnestPixel(pGC->fgPixel); + + if (mask & GCBackground) + values.background = xnestPixel(pGC->bgPixel); + + if (mask & GCLineWidth) + values.line_width = pGC->lineWidth; + + if (mask & GCLineStyle) + values.line_style = pGC->lineStyle; + + if (mask & GCCapStyle) + values.cap_style = pGC->capStyle; + + if (mask & GCJoinStyle) + values.join_style = pGC->joinStyle; + + if (mask & GCFillStyle) + values.fill_style = pGC->fillStyle; + + if (mask & GCFillRule) + values.fill_rule = pGC->fillRule; + + if (mask & GCTile) + if (pGC->tileIsPixel) + mask &= ~GCTile; + else + values.tile = xnestPixmap(pGC->tile.pixmap); + + if (mask & GCStipple) + values.stipple = xnestPixmap(pGC->stipple); + + if (mask & GCTileStipXOrigin) + values.ts_x_origin = pGC->patOrg.x; + + if (mask & GCTileStipYOrigin) + values.ts_y_origin = pGC->patOrg.y; + + if (mask & GCFont) + values.font = xnestFont(pGC->font); + + if (mask & GCSubwindowMode) + values.subwindow_mode = pGC->subWindowMode; + + if (mask & GCGraphicsExposures) + values.graphics_exposures = pGC->graphicsExposures; + + if (mask & GCClipXOrigin) + values.clip_x_origin = pGC->clipOrg.x; + + if (mask & GCClipYOrigin) + values.clip_y_origin = pGC->clipOrg.y; + + if (mask & GCClipMask) /* this is handled in change clip */ + mask &= ~GCClipMask; + + if (mask & GCDashOffset) + values.dash_offset = pGC->dashOffset; + + if (mask & GCDashList) { + mask &= ~GCDashList; + XSetDashes(xnestDisplay, xnestGC(pGC), + pGC->dashOffset, (char *)pGC->dash, pGC->numInDashList); + } + + if (mask & GCArcMode) + values.arc_mode = pGC->arcMode; + + if (mask) + XChangeGC(xnestDisplay, xnestGC(pGC), mask, &values); +} + +void xnestCopyGC(pGCSrc, mask, pGCDst) + GCPtr pGCSrc; + unsigned long mask; + GCPtr pGCDst; +{ + XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst)); +} + +void xnestDestroyGC(pGC) + GC *pGC; +{ + XFreeGC(xnestDisplay, xnestGC(pGC)); +} + +void xnestChangeClip(pGC, type, pValue, nRects) + GCPtr pGC; + int type; + pointer pValue; + int nRects; +{ + int i, size; + BoxPtr pBox; + XRectangle *pRects; + + xnestDestroyClipHelper(pGC); + + switch(type) + { + case CT_NONE: + XSetClipMask(xnestDisplay, xnestGC(pGC), None); + break; + + case CT_REGION: + nRects = REGION_NUM_RECTS((RegionPtr)pValue); + size = nRects * sizeof(*pRects); + pRects = (XRectangle *) xalloc(size); + pBox = REGION_RECTS((RegionPtr)pValue); + for (i = nRects; i-- > 0; ) { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + XSetClipRectangles(xnestDisplay, xnestGC(pGC), 0, 0, + pRects, nRects, Unsorted); + xfree((char *) pRects); + break; + + case CT_PIXMAP: + XSetClipMask(xnestDisplay, xnestGC(pGC), + xnestPixmap((PixmapPtr)pValue)); + /* + * Need to change into region, so subsequent uses are with + * current pixmap contents. + */ + pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr)pValue); + (*pGC->pScreen->DestroyPixmap)((PixmapPtr)pValue); + pValue = pGC->clientClip; + type = CT_REGION; + break; + + case CT_UNSORTED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, Unsorted); + break; + + case CT_YSORTED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YSorted); + break; + + case CT_YXSORTED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXSorted); + break; + + case CT_YXBANDED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXBanded); + break; + } + + switch(type) + { + default: + break; + + case CT_UNSORTED: + case CT_YSORTED: + case CT_YXSORTED: + case CT_YXBANDED: + + /* + * other parts of server can only deal with CT_NONE, + * CT_PIXMAP and CT_REGION client clips. + */ + pGC->clientClip = (pointer) (*pGC->pScreen->RectsToRegion)(nRects, + (xRectangle *)pValue, + type); + xfree(pValue); + pValue = pGC->clientClip; + type = CT_REGION; + + break; + } + + pGC->clientClipType = type; + pGC->clientClip = pValue; + xnestGCPriv(pGC)->nClipRects = nRects; +} + +void xnestDestroyClip(pGC) + GCPtr pGC; +{ + xnestDestroyClipHelper(pGC); + + XSetClipMask(xnestDisplay, xnestGC(pGC), None); + + pGC->clientClipType = CT_NONE; + pGC->clientClip = NULL; + xnestGCPriv(pGC)->nClipRects = 0; +} + +void xnestDestroyClipHelper(pGC) + GCPtr pGC; +{ + switch (pGC->clientClipType) + { + default: + case CT_NONE: + break; + + case CT_REGION: + REGION_DESTROY(pGC->pScreen, pGC->clientClip); + break; + } +} + +void xnestCopyClip(pGCDst, pGCSrc) + GCPtr pGCSrc; + GCPtr pGCDst; +{ + RegionPtr pRgn; + int nRects, size; + xRectangle *pRects; + + switch (pGCSrc->clientClipType) + { + default: + case CT_NONE: + xnestDestroyClip(pGCDst); + break; + + case CT_REGION: + pRgn = REGION_CREATE(pGCDst->pScreen, NULL, 1); + REGION_COPY(pGCDst->pScreen, pRgn, pGCSrc->clientClip); + xnestChangeClip(pGCDst, CT_REGION, pRgn, 0); + break; + } +} diff --git a/hw/xnest/GCOps.c b/hw/xnest/GCOps.c new file mode 100644 index 000000000..745fd602f --- /dev/null +++ b/hw/xnest/GCOps.c @@ -0,0 +1,387 @@ +/* $Xorg: GCOps.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "miscstruct.h" +#include "fontstruct.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "region.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "XNGC.h" +#include "XNFont.h" +#include "GCOps.h" +#include "Drawable.h" +#include "Visual.h" + +void xnestFillSpans(pDrawable, pGC, nSpans, pPoints, pWidths, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nSpans; + xPoint *pPoints; + int *pWidths; + int fSorted; +{ + ErrorF("xnest warning: function xnestFillSpans not implemented\n"); +} + +void xnestSetSpans(pDrawable, pGC, pSrc, pPoints, pWidths, nSpans, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned char * pSrc; + xPoint *pPoints; + int *pWidths; + int nSpans; + int fSorted; +{ + ErrorF("xnest warning: function xnestSetSpans not implemented\n"); +} + +void xnestGetSpans(pDrawable, maxWidth, pPoints, pWidths, nSpans, pBuffer) + DrawablePtr pDrawable; + int maxWidth; + xPoint *pPoints; + int *pWidths; + int nSpans; + int *pBuffer; +{ + ErrorF("xnest warning: function xnestGetSpans not implemented\n"); +} + +void xnestQueryBestSize(class, pWidth, pHeight, pScreen) + int class; + short *pWidth; + short *pHeight; + ScreenPtr pScreen; +{ + unsigned int width, height; + + width = *pWidth; + height = *pHeight; + + XQueryBestSize(xnestDisplay, class, + xnestDefaultWindows[pScreen->myNum], + width, height, &width, &height); + + *pWidth = width; + *pHeight = height; +} + +void xnestPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pImage) + DrawablePtr pDrawable; + GCPtr pGC; + int depth, x, y, w, h; + int leftPad; + unsigned int format; + unsigned char *pImage; +{ + XImage *ximage; + + ximage = XCreateImage(xnestDisplay, xnestDefaultVisual(pDrawable->pScreen), + depth, format, leftPad, (char *)pImage, + w, h, BitmapPad(xnestDisplay), + (format == ZPixmap) ? + PixmapBytePad(w, depth) : BitmapBytePad(w+leftPad)); + + if (ximage) { + XPutImage(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + ximage, 0, 0, x, y, w, h); + XFree(ximage); + } +} + +void xnestGetImage(pDrawable, x, y, w, h, format, planeMask, pImage) + DrawablePtr pDrawable; + int x, y, w, h; + unsigned int format; + unsigned long planeMask; + unsigned char *pImage; +{ + XImage *ximage; + int length; + + ximage = XGetImage(xnestDisplay, xnestDrawable(pDrawable), + x, y, w, h, planeMask, format); + + if (ximage) { + length = ximage->bytes_per_line * ximage->height; + + memmove(pImage, ximage->data, length); + + XDestroyImage(ximage); + } +} + +static Bool xnestBitBlitPredicate(display, event, args) + Display *display; + XEvent *event; + char *args; +{ + return (event->type == GraphicsExpose || event->type == NoExpose); +} + +RegionPtr xnestBitBlitHelper(pGC) + GC *pGC; +{ + if (!pGC->graphicsExposures) + return NullRegion; + else { + XEvent event; + RegionPtr pReg, pTmpReg; + BoxRec Box; + Bool pending, overlap; + + pReg = REGION_CREATE(pGC->pScreen, NULL, 1); + pTmpReg = REGION_CREATE(pGC->pScreen, NULL, 1); + if(!pReg || !pTmpReg) return NullRegion; + + pending = True; + while (pending) { + XIfEvent(xnestDisplay, &event, xnestBitBlitPredicate, NULL); + + switch (event.type) { + case NoExpose: + pending = False; + break; + + case GraphicsExpose: + Box.x1 = event.xgraphicsexpose.x; + Box.y1 = event.xgraphicsexpose.y; + Box.x2 = event.xgraphicsexpose.x + event.xgraphicsexpose.width; + Box.y2 = event.xgraphicsexpose.y + event.xgraphicsexpose.height; + REGION_RESET(pGC->pScreen, pTmpReg, &Box); + REGION_APPEND(pGC->pScreen, pReg, pTmpReg); + pending = event.xgraphicsexpose.count; + break; + } + } + + REGION_DESTROY(pGC->pScreen, pTmpReg); + REGION_VALIDATE(pGC->pScreen, pReg, &overlap); + return(pReg); + } +} + +RegionPtr xnestCopyArea(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty) + DrawablePtr pSrcDrawable; + DrawablePtr pDstDrawable; + GC *pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; +{ + XCopyArea(xnestDisplay, + xnestDrawable(pSrcDrawable), xnestDrawable(pDstDrawable), + xnestGC(pGC), srcx, srcy, width, height, dstx, dsty); + + return xnestBitBlitHelper(pGC); +} + +RegionPtr xnestCopyPlane(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + DrawablePtr pSrcDrawable; + DrawablePtr pDstDrawable; + GC *pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + XCopyPlane(xnestDisplay, + xnestDrawable(pSrcDrawable), xnestDrawable(pDstDrawable), + xnestGC(pGC), srcx, srcy, width, height, dstx, dsty, plane); + + return xnestBitBlitHelper(pGC); +} + +void xnestPolyPoint(pDrawable, pGC, mode, nPoints, pPoints) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int nPoints; + XPoint *pPoints; +{ + XDrawPoints(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pPoints, nPoints, mode); +} + +void xnestPolylines(pDrawable, pGC, mode, nPoints, pPoints) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int nPoints; + XPoint *pPoints; +{ + XDrawLines(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pPoints, nPoints, mode); +} + +void xnestPolySegment(pDrawable, pGC, nSegments, pSegments) + DrawablePtr pDrawable; + GCPtr pGC; + int nSegments; + XSegment *pSegments; +{ + XDrawSegments(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pSegments, nSegments); +} + +void xnestPolyRectangle(pDrawable, pGC, nRectangles, pRectangles) + DrawablePtr pDrawable; + GCPtr pGC; + int nRectangles; + XRectangle *pRectangles; +{ + XDrawRectangles(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pRectangles, nRectangles); +} + +void xnestPolyArc(pDrawable, pGC, nArcs, pArcs) + DrawablePtr pDrawable; + GCPtr pGC; + int nArcs; + XArc *pArcs; +{ + XDrawArcs(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pArcs, nArcs); +} + +void xnestFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints) + DrawablePtr pDrawable; + GCPtr pGC; + int shape; + int mode; + int nPoints; + XPoint *pPoints; +{ + XFillPolygon(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pPoints, nPoints, shape, mode); +} + +void xnestPolyFillRect(pDrawable, pGC, nRectangles, pRectangles) + DrawablePtr pDrawable; + GCPtr pGC; + int nRectangles; + XRectangle *pRectangles; +{ + XFillRectangles(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pRectangles, nRectangles); +} + +void xnestPolyFillArc(pDrawable, pGC, nArcs, pArcs) + DrawablePtr pDrawable; + GCPtr pGC; + int nArcs; + XArc *pArcs; +{ + XFillArcs(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + pArcs, nArcs); +} + +int xnestPolyText8(pDrawable, pGC, x, y, count, string) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + char *string; +{ + int width; + + XDrawString(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + x, y, string, count); + + width = XTextWidth(xnestFontStruct(pGC->font), string, count); + + return width + x; +} + +int xnestPolyText16(pDrawable, pGC, x, y, count, string) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + XChar2b *string; +{ + int width; + + XDrawString16(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + x, y, string, count); + + width = XTextWidth16(xnestFontStruct(pGC->font), string, count); + + return width + x; +} + +void xnestImageText8(pDrawable, pGC, x, y, count, string) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + char *string; +{ + XDrawImageString(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + x, y, string, count); +} + +void xnestImageText16(pDrawable, pGC, x, y, count, string) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + XChar2b *string; +{ + XDrawImageString16(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC), + x, y, string, count); +} + +void xnestImageGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase) + DrawablePtr pDrawable; + GC pGC; + int x, y; + int nGlyphs; + CharInfoPtr pCharInfo; + char pGlyphBase; +{ + ErrorF("xnest warning: function xnestImageGlyphBlt not implemented\n"); +} + +void xnestPolyGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase) + DrawablePtr pDrawable; + GC pGC; + int x, y; + int nGlyphs; + CharInfoPtr pCharInfo; + char pGlyphBase; +{ + ErrorF("xnest warning: function xnestPolyGlyphBlt not implemented\n"); +} + +void xnestPushPixels(pDrawable, pGC, pBitmap, width, height, x, y) + DrawablePtr pDrawable; + GC pGC; + PixmapPtr pBitmap; + int width, height; + int x, y; +{ + ErrorF("xnest warning: function xnestPushPixels not implemented\n"); +} diff --git a/hw/xnest/GCOps.h b/hw/xnest/GCOps.h new file mode 100644 index 000000000..3d4f3d2d4 --- /dev/null +++ b/hw/xnest/GCOps.h @@ -0,0 +1,43 @@ +/* $Xorg: GCOps.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTGCOPS_H +#define XNESTGCOPS_H + +void xnestFillSpans(); +void xnestSetSpans(); +void xnestGetSpans(); +void xnestPutImage(); +void xnestGetImage(); +RegionPtr xnestCopyArea(); +RegionPtr xnestCopyPlane(); +void xnestQueryBestSize(); +void xnestPolyPoint(); +void xnestPolylines(); +void xnestPolySegment(); +void xnestPolyRectangle(); +void xnestPolyArc(); +void xnestFillPolygon(); +void xnestPolyFillRect(); +void xnestPolyFillArc(); +int xnestPolyText8(); +int xnestPolyText16(); +void xnestImageText8(); +void xnestImageText16(); +void xnestImageGlyphBlt(); +void xnestPolyGlyphBlt(); +void xnestPushPixels(); + +#endif /* XNESTGCOPS_H */ diff --git a/hw/xnest/GetTime.c b/hw/xnest/GetTime.c new file mode 100644 index 000000000..5fdef2a12 --- /dev/null +++ b/hw/xnest/GetTime.c @@ -0,0 +1,43 @@ +/* $Xorg: GetTime.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright (c) 1993 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the X Consortium. + +*/ + + +#include "Xos.h" +#include + +long +GetTimeInMillis() +{ + struct timeval tp; + + X_GETTIMEOFDAY(&tp); + return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} diff --git a/hw/xnest/Handlers.c b/hw/xnest/Handlers.c new file mode 100644 index 000000000..6feddebd7 --- /dev/null +++ b/hw/xnest/Handlers.c @@ -0,0 +1,43 @@ +/* $Xorg: Handlers.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Handlers.h" + +void xnestBlockHandler(blockData, pTimeout, pReadMask) + pointer blockData; + pointer pTimeout; + pointer pReadMask; +{ + xnestCollectExposures(); + XFlush(xnestDisplay); +} + +void xnestWakeupHandler(result, pReadMask) + int result; + pointer pReadMask; +{ + xnestCollectEvents(); +} diff --git a/hw/xnest/Handlers.h b/hw/xnest/Handlers.h new file mode 100644 index 000000000..b33e9890d --- /dev/null +++ b/hw/xnest/Handlers.h @@ -0,0 +1,22 @@ +/* $Xorg: Handlers.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTHANDLERS_H +#define XNESTHANDLERS_H + +void xnestBlockHandler(); +void xnestWakeupHandler(); + +#endif /* XNESTHANDLERS_H */ diff --git a/hw/xnest/Init.c b/hw/xnest/Init.c new file mode 100644 index 000000000..00cd4f9ac --- /dev/null +++ b/hw/xnest/Init.c @@ -0,0 +1,147 @@ +/* $Xorg: Init.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "Pointer.h" +#include "Keyboard.h" +#include "Handlers.h" +#include "Init.h" +#include "Args.h" +#include "Drawable.h" +#include "XNGC.h" +#include "XNFont.h" + +Bool xnestDoFullGeneration = True; + +void InitOutput(screenInfo, argc, argv) + ScreenInfo *screenInfo; + int argc; + char *argv[]; +{ + int i, j; + + xnestOpenDisplay(argc, argv); + + screenInfo->imageByteOrder = ImageByteOrder(xnestDisplay); + screenInfo->bitmapScanlineUnit = BitmapUnit(xnestDisplay); + screenInfo->bitmapScanlinePad = BitmapPad(xnestDisplay); + screenInfo->bitmapBitOrder = BitmapBitOrder(xnestDisplay); + + screenInfo->numPixmapFormats = 0; + for (i = 0; i < xnestNumPixmapFormats; i++) + for (j = 0; j < xnestNumDepths; j++) + if (xnestPixmapFormats[i].depth == xnestDepths[j]) { + screenInfo->formats[screenInfo->numPixmapFormats].depth = + xnestPixmapFormats[i].depth; + screenInfo->formats[screenInfo->numPixmapFormats].bitsPerPixel = + xnestPixmapFormats[i].bits_per_pixel; + screenInfo->formats[screenInfo->numPixmapFormats].scanlinePad = + xnestPixmapFormats[i].scanline_pad; + screenInfo->numPixmapFormats++; + } + + xnestWindowPrivateIndex = AllocateWindowPrivateIndex(); + xnestGCPrivateIndex = AllocateGCPrivateIndex(); + xnestFontPrivateIndex = AllocateFontPrivateIndex(); + + if (!xnestNumScreens) xnestNumScreens = 1; + + for (i = 0; i < xnestNumScreens; i++) + AddScreen(xnestOpenScreen, argc, argv); + + xnestNumScreens = screenInfo->numScreens; + + xnestDoFullGeneration = xnestFullGeneration; +} + +void InitInput(argc, argv) + int argc; + char *argv[]; +{ + DevicePtr ptr, kbd; + + ptr = AddInputDevice(xnestPointerProc, TRUE); + kbd = AddInputDevice(xnestKeyboardProc, TRUE); + + RegisterPointerDevice(ptr); + RegisterKeyboardDevice(kbd); + + mieqInit(kbd, ptr); + + AddEnabledDevice(XConnectionNumber(xnestDisplay)); + + RegisterBlockAndWakeupHandlers(xnestBlockHandler, xnestWakeupHandler, NULL); +} + +/* + * DDX - specific abort routine. Called by AbortServer(). + */ +void AbortDDX() +{ + xnestDoFullGeneration = True; + xnestCloseDisplay(); +} + +/* Called by GiveUp(). */ +void ddxGiveUp() +{ + AbortDDX(); +} + +void OsVendorInit() +{ + return; +} + +/* this is just to get the server to link on AIX */ +#ifdef AIXV3 +int SelectWaitTime = 10000; /* usec */ +#endif + +#ifdef DPMSExtension +/************************************************************** + * DPMSSet(), DPMSGet(), DPMSSupported() + * + * stubs + * + ***************************************************************/ + +void DPMSSet (level) + int level; +{ +} + +int DPMSGet (level) + int* level; +{ + return -1; +} + +Bool DPMSSupported () +{ + return FALSE; +} +#endif diff --git a/hw/xnest/Init.h b/hw/xnest/Init.h new file mode 100644 index 000000000..8fb9956eb --- /dev/null +++ b/hw/xnest/Init.h @@ -0,0 +1,21 @@ +/* $Xorg: Init.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTINIT_H +#define XNESTINIT_H + +extern Bool xnestDoFullGeneration; + +#endif /* XNESTINIT_H */ diff --git a/hw/xnest/Keyboard.c b/hw/xnest/Keyboard.c new file mode 100644 index 000000000..ce5d57f5d --- /dev/null +++ b/hw/xnest/Keyboard.c @@ -0,0 +1,165 @@ +/* $Xorg: Keyboard.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "keysym.h" +#include "screenint.h" +#include "inputstr.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "Keyboard.h" +#include "Args.h" + +void xnestBell(volume, pDev, ctrl, cls) + int volume; + DeviceIntPtr pDev; + pointer ctrl; + int cls; +{ + XBell(xnestDisplay, volume); +} + +void xnestChangeKeyboardControl(pDev, ctrl) + DeviceIntPtr pDev; + KeybdCtrl *ctrl; +{ + unsigned long value_mask; + XKeyboardControl values; + int i; + + value_mask = KBKeyClickPercent | + KBBellPercent | + KBBellPitch | + KBBellDuration | + KBAutoRepeatMode; + + values.key_click_percent = ctrl->click; + values.bell_percent = ctrl->bell; + values.bell_pitch = ctrl->bell_pitch; + values.bell_duration = ctrl->bell_duration; + values.auto_repeat_mode = ctrl->autoRepeat ? + AutoRepeatModeOn : AutoRepeatModeOff; + + XChangeKeyboardControl(xnestDisplay, value_mask, &values); + + /* + value_mask = KBKey | KBAutoRepeatMode; + At this point, we need to walk through the vector and compare it + to the current server vector. If there are differences, report them. + */ + + value_mask = KBLed | KBLedMode; + for (i = 1; i <= 32; i++) { + values.led = i; + values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff; + XChangeKeyboardControl(xnestDisplay, value_mask, &values); + } +} + +int xnestKeyboardProc(pDev, onoff, argc, argv) + DevicePtr pDev; + int onoff, argc; + char *argv[]; +{ + XModifierKeymap *modifier_keymap; + KeySym *keymap; + int mapWidth; + int min_keycode, max_keycode; + KeySymsRec keySyms; + CARD8 modmap[256]; + int i, j; + XKeyboardState values; + + switch (onoff) + { + case DEVICE_INIT: + modifier_keymap = XGetModifierMapping(xnestDisplay); + XDisplayKeycodes(xnestDisplay, &min_keycode, &max_keycode); +#ifdef _XSERVER64 + { + KeySym64 *keymap64; + int i, len; + keymap64 = XGetKeyboardMapping(xnestDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); + len = (max_keycode - min_keycode + 1) * mapWidth; + keymap = (KeySym *)xalloc(len * sizeof(KeySym)); + for(i = 0; i < len; ++i) + keymap[i] = keymap64[i]; + XFree(keymap64); + } +#else + keymap = XGetKeyboardMapping(xnestDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); +#endif + + for (i = 0; i < 256; i++) + modmap[i] = 0; + for (j = 0; j < 8; j++) + for(i = 0; i < modifier_keymap->max_keypermod; i++) { + CARD8 keycode; + if (keycode = + modifier_keymap-> + modifiermap[j * modifier_keymap->max_keypermod + i]) + modmap[keycode] |= 1<drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = depth; + pPixmap->drawable.id = 0; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->refcnt = 1; + pPixmap->devKind = PixmapBytePad(width, depth); + pPixmap->devPrivate.ptr = (pointer)(pPixmap + 1); + if (width && height) + xnestPixmapPriv(pPixmap)->pixmap = + XCreatePixmap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + width, height, depth); + else + xnestPixmapPriv(pPixmap)->pixmap = 0; + + return pPixmap; +} + +Bool xnestDestroyPixmap(pPixmap) + PixmapPtr pPixmap; +{ + if(--pPixmap->refcnt) + return TRUE; + XFreePixmap(xnestDisplay, xnestPixmap(pPixmap)); + xfree(pPixmap); + return TRUE; +} + +RegionPtr xnestPixmapToRegion(pPixmap) + PixmapPtr pPixmap; +{ + XImage *ximage; + register RegionPtr pReg, pTmpReg; + register int x, y; + unsigned long previousPixel, currentPixel; + BoxRec Box; + int nWidth; + Bool overlap; + + ximage = XGetImage(xnestDisplay, xnestPixmap(pPixmap), 0, 0, + pPixmap->drawable.width, pPixmap->drawable.height, + 1, XYPixmap); + + pReg = REGION_CREATE(pPixmap->drawable.pScreen, NULL, 1); + pTmpReg = REGION_CREATE(pPixmap->drawable.pScreen, NULL, 1); + if(!pReg || !pTmpReg) return NullRegion; + + for (y = 0; y < pPixmap->drawable.height; y++) { + Box.y1 = y; + Box.y2 = y + 1; + previousPixel = 0L; + for (x = 0; x < pPixmap->drawable.width; x++) { + currentPixel = XGetPixel(ximage, x, y); + if (previousPixel != currentPixel) { + if (previousPixel == 0L) { + /* left edge */ + Box.x1 = x; + } + else if (currentPixel == 0L) { + /* right edge */ + Box.x2 = x; + REGION_RESET(pPixmap->drawable.pScreen, pTmpReg, &Box); + REGION_APPEND(pPixmap->drawable.pScreen, pReg, pTmpReg); + } + previousPixel = currentPixel; + } + } + if (previousPixel != 0L) { + /* right edge because of the end of pixmap */ + Box.x2 = pPixmap->drawable.width; + REGION_RESET(pPixmap->drawable.pScreen, pTmpReg, &Box); + REGION_APPEND(pPixmap->drawable.pScreen, pReg, pTmpReg); + } + } + + REGION_DESTROY(pPixmap->drawable.pScreen, pTmpReg); + XDestroyImage(ximage); + + REGION_VALIDATE(pPixmap->drawable.pScreen, pReg, &overlap); + + return(pReg); +} diff --git a/hw/xnest/Pointer.c b/hw/xnest/Pointer.c new file mode 100644 index 000000000..741989652 --- /dev/null +++ b/hw/xnest/Pointer.c @@ -0,0 +1,73 @@ +/* $Xorg: Pointer.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "mipointer.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "Pointer.h" +#include "Args.h" + +void xnestChangePointerControl(pDev, ctrl) + DeviceIntPtr pDev; + PtrCtrl *ctrl; +{ + XChangePointerControl(xnestDisplay, True, True, + ctrl->num, ctrl->den, ctrl->threshold); +} + +int xnestPointerProc(pDev, onoff, argc, argv) + DevicePtr pDev; + int onoff, argc; + char *argv[]; +{ + CARD8 map[MAXBUTTONS]; + int nmap; + int i; + + switch (onoff) + { + case DEVICE_INIT: + nmap = XGetPointerMapping(xnestDisplay, map, MAXBUTTONS); + for (i = 0; i <= nmap; i++) + map[i] = i; /* buttons are already mapped */ + InitPointerDeviceStruct(pDev, map, nmap, + miPointerGetMotionEvents, + xnestChangePointerControl, + miPointerGetMotionBufferSize()); + break; + case DEVICE_ON: + xnestEventMask |= XNEST_POINTER_EVENT_MASK; + for (i = 0; i < xnestNumScreens; i++) + XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); + break; + case DEVICE_OFF: + xnestEventMask &= ~XNEST_POINTER_EVENT_MASK; + for (i = 0; i < xnestNumScreens; i++) + XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); + break; + case DEVICE_CLOSE: + break; + } + return Success; +} diff --git a/hw/xnest/Pointer.h b/hw/xnest/Pointer.h new file mode 100644 index 000000000..2fced12e2 --- /dev/null +++ b/hw/xnest/Pointer.h @@ -0,0 +1,28 @@ +/* $Xorg: Pointer.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTPOINTER_H +#define XNESTPOINTER_H + +#define MAXBUTTONS 256 + +#define XNEST_POINTER_EVENT_MASK \ + (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ + EnterWindowMask | LeaveWindowMask) + +void xnestChangePointerControl(); +int xnestPointerProc(); + +#endif /* XNESTPOINTER_H */ diff --git a/hw/xnest/Screen.c b/hw/xnest/Screen.c new file mode 100644 index 000000000..4d718cb5d --- /dev/null +++ b/hw/xnest/Screen.c @@ -0,0 +1,376 @@ +/* $Xorg: Screen.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "dix.h" +#include "mi.h" +#include "mibstore.h" +#include "colormapst.h" +#include "resource.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "Args.h" +#include "XNGC.h" +#include "GCOps.h" +#include "Drawable.h" +#include "XNFont.h" +#include "Color.h" +#include "Cursor.h" +#include "Visual.h" +#include "Events.h" +#include "Init.h" +#include "Args.h" + +extern Bool miModifyPixmapHeader(); +extern Bool miCreateScreenResources(); +extern Bool miCloseScreen(); +extern Bool miScreenInit(); +extern Window xnestParentWindow; + +Window xnestDefaultWindows[MAXSCREENS]; +Window xnestScreenSaverWindows[MAXSCREENS]; + +ScreenPtr xnestScreen(window) + Window window; +{ + int i; + + for (i = 0; i < xnestNumScreens; i++) + if (xnestDefaultWindows[i] == window) + return screenInfo.screens[i]; + + return NULL; +} + +static int offset(mask) + unsigned long mask; +{ + int count; + + for (count = 0; !(mask & 1) && count < 32; count++) + mask >>= 1; + + return count; +} + +static Bool xnestSaveScreen(pScreen, what) + ScreenPtr pScreen; + int what; +{ + if (xnestSoftwareScreenSaver) + return False; + else { + switch (what) { + case SCREEN_SAVER_ON: + XMapRaised(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetScreenSaverColormapWindow(pScreen); + break; + + case SCREEN_SAVER_OFF: + XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetInstalledColormapWindows(pScreen); + break; + + case SCREEN_SAVER_FORCER: + lastEventTime = GetTimeInMillis(); + XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetInstalledColormapWindows(pScreen); + break; + + case SCREEN_SAVER_CYCLE: + XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetInstalledColormapWindows(pScreen); + break; + } + return True; + } +} + +Bool xnestOpenScreen(index, pScreen, argc, argv) + int index; + register ScreenPtr pScreen; + int argc; + char *argv[]; +{ + VisualPtr visuals; + DepthPtr depths; + int numVisuals, numDepths; + int i, j, depthIndex; + unsigned long valuemask; + XSetWindowAttributes attributes; + XWindowAttributes gattributes; + XSizeHints sizeHints; + + if (!(AllocateWindowPrivate(pScreen, xnestWindowPrivateIndex, + sizeof(xnestPrivWin)) && + AllocateGCPrivate(pScreen, xnestGCPrivateIndex, + sizeof(xnestPrivGC)))) + return False; + + visuals = (VisualPtr)xalloc(xnestNumVisuals * sizeof(VisualRec)); + numVisuals = 0; + + depths = (DepthPtr)xalloc(MAXDEPTH * sizeof(DepthRec)); + depths[0].depth = 1; + depths[0].numVids = 0; + depths[0].vids = (VisualID *)xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); + numDepths = 1; + + for (i = 0; i < xnestNumVisuals; i++) { + visuals[numVisuals].vid = FakeClientID(0); + visuals[numVisuals].class = xnestVisuals[i].class; + visuals[numVisuals].bitsPerRGBValue = xnestVisuals[i].bits_per_rgb; + visuals[numVisuals].ColormapEntries = xnestVisuals[i].colormap_size; + visuals[numVisuals].nplanes = xnestVisuals[i].depth; + visuals[numVisuals].redMask = xnestVisuals[i].red_mask; + visuals[numVisuals].greenMask = xnestVisuals[i].green_mask; + visuals[numVisuals].blueMask = xnestVisuals[i].blue_mask; + visuals[numVisuals].offsetRed = offset(xnestVisuals[i].red_mask); + visuals[numVisuals].offsetGreen = offset(xnestVisuals[i].green_mask); + visuals[numVisuals].offsetBlue = offset(xnestVisuals[i].blue_mask); + + depthIndex = UNDEFINED; + for (j = 0; j < numDepths; j++) + if (depths[j].depth == xnestVisuals[i].depth) { + depthIndex = j; + break; + } + + if (depthIndex == UNDEFINED) { + depthIndex = numDepths; + depths[depthIndex].depth = xnestVisuals[i].depth; + depths[depthIndex].numVids = 0; + depths[depthIndex].vids = + (VisualID *)xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); + numDepths++; + } + depths[depthIndex].vids[depths[depthIndex].numVids] = + visuals[numVisuals].vid; + depths[depthIndex].numVids++; + + numVisuals++; + } + + if (xnestParentWindow != 0) { + XGetWindowAttributes(xnestDisplay, xnestParentWindow, &gattributes); + xnestWidth = gattributes.width; + xnestHeight = gattributes.height; + } + + /* myNum */ + /* id */ + miScreenInit(pScreen, NULL, xnestWidth, xnestHeight, 1, 1, xnestWidth, + visuals[xnestDefaultVisualIndex].nplanes, /* rootDepth */ + numDepths, depths, + visuals[xnestDefaultVisualIndex].vid, /* root visual */ + numVisuals, visuals, NULL); + + pScreen->mmWidth = xnestWidth * DisplayWidthMM(xnestDisplay, + DefaultScreen(xnestDisplay)) / + DisplayWidth(xnestDisplay, + DefaultScreen(xnestDisplay)); + pScreen->mmHeight = xnestHeight * DisplayHeightMM(xnestDisplay, + DefaultScreen(xnestDisplay)) / + DisplayHeight(xnestDisplay, + DefaultScreen(xnestDisplay)); + + pScreen->defColormap = (Colormap) FakeClientID(0); + pScreen->minInstalledCmaps = MINCMAPS; + pScreen->maxInstalledCmaps = MAXCMAPS; + pScreen->backingStoreSupport = NotUseful; + pScreen->saveUnderSupport = NotUseful; + pScreen->whitePixel = xnestWhitePixel; + pScreen->blackPixel = xnestBlackPixel; + /* rgf */ + /* GCperDepth */ + /* PixmapPerDepth */ + pScreen->devPrivate = NULL; + /* WindowPrivateLen */ + /* WindowPrivateSizes */ + /* totalWindowSize */ + /* GCPrivateLen */ + /* GCPrivateSizes */ + /* totalGCSize */ + + /* Random screen procedures */ + + pScreen->CloseScreen = xnestCloseScreen; + pScreen->QueryBestSize = xnestQueryBestSize; + pScreen->SaveScreen = xnestSaveScreen; + pScreen->GetImage = xnestGetImage; + pScreen->GetSpans = xnestGetSpans; + pScreen->PointerNonInterestBox = (void (*)()) 0; + pScreen->SourceValidate = (void (*)()) 0; + + /* Window Procedures */ + + pScreen->CreateWindow = xnestCreateWindow; + pScreen->DestroyWindow = xnestDestroyWindow; + pScreen->PositionWindow = xnestPositionWindow; + pScreen->ChangeWindowAttributes = xnestChangeWindowAttributes; + pScreen->RealizeWindow = xnestRealizeWindow; + pScreen->UnrealizeWindow = xnestUnrealizeWindow; + pScreen->PostValidateTree = (void (*)()) 0; + pScreen->WindowExposures = xnestWindowExposures; + pScreen->PaintWindowBackground = xnestPaintWindowBackground; + pScreen->PaintWindowBorder = xnestPaintWindowBorder; + pScreen->CopyWindow = xnestCopyWindow; + pScreen->ClipNotify = xnestClipNotify; + + /* Pixmap procedures */ + + pScreen->CreatePixmap = xnestCreatePixmap; + pScreen->DestroyPixmap = xnestDestroyPixmap; + + /* Backing store procedures */ + + pScreen->SaveDoomedAreas = (void (*)()) 0; + pScreen->RestoreAreas = (RegionPtr (*)()) 0; + pScreen->ExposeCopy = (void (*)()) 0; + pScreen->TranslateBackingStore = (RegionPtr (*)()) 0; + pScreen->ClearBackingStore = (RegionPtr (*)()) 0; + pScreen->DrawGuarantee = (void (*)()) 0; + + /* Font procedures */ + + pScreen->RealizeFont = xnestRealizeFont; + pScreen->UnrealizeFont = xnestUnrealizeFont; + + /* Cursor Procedures */ + + pScreen->ConstrainCursor = xnestConstrainCursor; + pScreen->CursorLimits = xnestCursorLimits; + pScreen->DisplayCursor = xnestDisplayCursor; + pScreen->RealizeCursor = xnestRealizeCursor; + pScreen->UnrealizeCursor = xnestUnrealizeCursor; + pScreen->RecolorCursor = xnestRecolorCursor; + pScreen->SetCursorPosition = xnestSetCursorPosition; + + /* GC procedures */ + + pScreen->CreateGC = xnestCreateGC; + + /* Colormap procedures */ + + pScreen->CreateColormap = xnestCreateColormap; + pScreen->DestroyColormap = xnestDestroyColormap; + pScreen->InstallColormap = xnestInstallColormap; + pScreen->UninstallColormap = xnestUninstallColormap; + pScreen->ListInstalledColormaps = xnestListInstalledColormaps; + pScreen->StoreColors = xnestStoreColors; + pScreen->ResolveColor = xnestResolveColor; + + pScreen->BitmapToRegion = xnestPixmapToRegion; + + /* OS layer procedures */ + + pScreen->BlockHandler = (void (*)())NoopDDA; + pScreen->WakeupHandler = (void (*)())NoopDDA; + pScreen->blockData = (pointer)0; + pScreen->wakeupData = (pointer)0; + if (!miScreenDevPrivateInit(pScreen, xnestWidth, NULL)) + return FALSE; + + /* devPrivates */ + +#define POSITION_OFFSET (pScreen->myNum * (xnestWidth + xnestHeight) / 32) + + if (xnestDoFullGeneration) { + + valuemask = CWBackPixel | CWEventMask | CWColormap; + attributes.background_pixel = xnestWhitePixel; + attributes.event_mask = xnestEventMask; + attributes.colormap = xnestDefaultVisualColormap(xnestDefaultVisual(pScreen)); + + if (xnestParentWindow != 0) { + xnestDefaultWindows[pScreen->myNum] = xnestParentWindow; + XSelectInput (xnestDisplay, xnestDefaultWindows[pScreen->myNum], + xnestEventMask); + } else + xnestDefaultWindows[pScreen->myNum] = + XCreateWindow(xnestDisplay, + DefaultRootWindow(xnestDisplay), + xnestX + POSITION_OFFSET, + xnestY + POSITION_OFFSET, + xnestWidth, xnestHeight, + xnestBorderWidth, + pScreen->rootDepth, + InputOutput, + xnestDefaultVisual(pScreen), + valuemask, &attributes); + + if (!xnestWindowName) + xnestWindowName = argv[0]; + + sizeHints.flags = PPosition | PSize | PMaxSize; + sizeHints.x = xnestX + POSITION_OFFSET; + sizeHints.y = xnestY + POSITION_OFFSET; + sizeHints.width = sizeHints.max_width = xnestWidth; + sizeHints.height = sizeHints.max_height = xnestHeight; + if (xnestUserGeometry & XValue || xnestUserGeometry & YValue) + sizeHints.flags |= USPosition; + if (xnestUserGeometry & WidthValue || xnestUserGeometry & HeightValue) + sizeHints.flags |= USSize; + XSetStandardProperties(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + xnestWindowName, + xnestWindowName, + xnestIconBitmap, + argv, argc, &sizeHints); + + XMapWindow(xnestDisplay, xnestDefaultWindows[pScreen->myNum]); + + valuemask = CWBackPixmap | CWColormap; + attributes.background_pixmap = xnestScreenSaverPixmap; + attributes.colormap = + DefaultColormap(xnestDisplay, DefaultScreen(xnestDisplay)); + xnestScreenSaverWindows[pScreen->myNum] = + XCreateWindow(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + 0, 0, xnestWidth, xnestHeight, 0, + DefaultDepth(xnestDisplay, DefaultScreen(xnestDisplay)), + InputOutput, + DefaultVisual(xnestDisplay, DefaultScreen(xnestDisplay)), + valuemask, &attributes); + } + + if (!xnestCreateDefaultColormap(pScreen)) return False; + + return True; +} + +Bool xnestCloseScreen(index, pScreen) + int index; + ScreenPtr pScreen; +{ + int i; + + for (i = 0; i < pScreen->numDepths; i++) + xfree(pScreen->allowedDepths[i].vids); + xfree(pScreen->allowedDepths); + xfree(pScreen->visuals); + xfree(pScreen->devPrivate); + + /* + If xnestDoFullGeneration all x resources will be destroyed upon closing + the display connection. There is no need to generate extra protocol. + */ + + return True; +} diff --git a/hw/xnest/Screen.h b/hw/xnest/Screen.h new file mode 100644 index 000000000..7c8115d8a --- /dev/null +++ b/hw/xnest/Screen.h @@ -0,0 +1,26 @@ +/* $Xorg: Screen.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTSCREEN_H +#define XNESTSCREEN_H + +extern Window xnestDefaultWindows[MAXSCREENS]; +extern Window xnestScreenSaverWindows[MAXSCREENS]; + +ScreenPtr xnestScreen(); +Bool xnestOpenScreen(); +Bool xnestCloseScreen(); + +#endif /* XNESTSCREEN_H */ diff --git a/hw/xnest/TestExt.c b/hw/xnest/TestExt.c new file mode 100644 index 000000000..7898bcd14 --- /dev/null +++ b/hw/xnest/TestExt.c @@ -0,0 +1,65 @@ +/* $Xorg: TestExt.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" +#define XTestSERVER_SIDE +#include "xtestext1.h" + +extern CARD32 lastEventTime; + +void XTestGetPointerPos(fmousex, fmousey) + short *fmousex; + short *fmousey; +{ + int x,y; + + miPointerPosition(&x, &y); + *fmousex = x; + *fmousey = y; +} + +void XTestJumpPointer(jx, jy, dev_type) + int jx; + int jy; + int dev_type; +{ + miPointerAbsoluteCursor(jx, jy, GetTimeInMillis()); +} + +void XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey) + int dev_type; + int keycode; + int keystate; + int mousex; + int mousey; +{ +/* + xEvent tevent; + + tevent.u.u.type = (dev_type == XE_POINTER) ? + (keystate == XTestKEY_UP) ? ButtonRelease : ButtonPress : + (keystate == XTestKEY_UP) ? KeyRelease : KeyPress; + tevent.u.u.detail = keycode; + tevent.u.keyButtonPointer.rootX = mousex; + tevent.u.keyButtonPointer.rootY = mousey; + tevent.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis(); + mieqEnqueue(&tevent); +*/ +} diff --git a/hw/xnest/Visual.c b/hw/xnest/Visual.c new file mode 100644 index 000000000..d512dba95 --- /dev/null +++ b/hw/xnest/Visual.c @@ -0,0 +1,67 @@ +/* $Xorg: Visual.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "dix.h" +#include "mi.h" +#include "mibstore.h" +#include "Xnest.h" + +#include "Display.h" +#include "Visual.h" + +Visual *xnestVisual(pVisual) + VisualPtr pVisual; +{ + int i; + + for (i = 0; i < xnestNumVisuals; i++) + if (pVisual->class == xnestVisuals[i].class && + pVisual->bitsPerRGBValue == xnestVisuals[i].bits_per_rgb && + pVisual->ColormapEntries == xnestVisuals[i].colormap_size && + pVisual->nplanes == xnestVisuals[i].depth && + pVisual->redMask == xnestVisuals[i].red_mask && + pVisual->greenMask == xnestVisuals[i].green_mask && + pVisual->blueMask == xnestVisuals[i].blue_mask) + return xnestVisuals[i].visual; + + return NULL; +} + +Visual *xnestVisualFromID(pScreen, visual) + ScreenPtr pScreen; + VisualID visual; +{ + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + if (pScreen->visuals[i].vid == visual) + return xnestVisual(&pScreen->visuals[i]); + + return NULL; +} + +Colormap xnestDefaultVisualColormap(visual) + Visual *visual; +{ + int i; + + for (i = 0; i < xnestNumVisuals; i++) + if (xnestVisuals[i].visual == visual) + return xnestDefaultColormaps[i]; + + return None; +} diff --git a/hw/xnest/Visual.h b/hw/xnest/Visual.h new file mode 100644 index 000000000..818393178 --- /dev/null +++ b/hw/xnest/Visual.h @@ -0,0 +1,26 @@ +/* $Xorg: Visual.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTVISUAL_H +#define XNESTVISUAL_H + +Visual *xnestVisual(); +Visual *xnestVisualFromID(); +Colormap xnestDefaultVisualColormap(); + +#define xnestDefaultVisual(pScreen) \ + xnestVisualFromID((pScreen), (pScreen)->rootVisual) + +#endif /* XNESTVISUAL_H */ diff --git a/hw/xnest/Window.c b/hw/xnest/Window.c new file mode 100644 index 000000000..e345b49d1 --- /dev/null +++ b/hw/xnest/Window.c @@ -0,0 +1,555 @@ +/* $Xorg: Window.c,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include "X.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "window.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "region.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "XNGC.h" +#include "Drawable.h" +#include "Color.h" +#include "Visual.h" +#include "Events.h" +#include "Args.h" + +int xnestWindowPrivateIndex; + +static int xnestFindWindowMatch(pWin, ptr) + WindowPtr pWin; + pointer ptr; +{ + xnestWindowMatch *wm = (xnestWindowMatch *)ptr; + if (wm->window == xnestWindow(pWin)) { + wm->pWin = pWin; + return WT_STOPWALKING; + } + else + return WT_WALKCHILDREN; +} + +WindowPtr xnestWindowPtr(window) + Window window; +{ + xnestWindowMatch wm; + int i; + + wm.pWin = NullWindow; + wm.window = window; + + for (i = 0; i < xnestNumScreens; i++) { + WalkTree(screenInfo.screens[i], xnestFindWindowMatch, (pointer) &wm); + if (wm.pWin) break; + } + + return wm.pWin; +} + +Bool xnestCreateWindow(pWin) + WindowPtr pWin; +{ + unsigned long mask; + XSetWindowAttributes attributes; + Visual *visual; + ColormapPtr pCmap; + + if (pWin->drawable.class == InputOnly) { + mask = 0L; + visual = CopyFromParent; + } + else { + mask = CWEventMask | CWBackingStore; + attributes.event_mask = ExposureMask; + attributes.backing_store = NotUseful; + + if (pWin->parent) { + if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent)) { + visual = xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); + mask |= CWColormap; + if (pWin->optional->colormap) { + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP); + attributes.colormap = xnestColormap(pCmap); + } + else + attributes.colormap = xnestDefaultVisualColormap(visual); + } + else + visual = CopyFromParent; + } + else { /* root windows have their own colormaps at creation time */ + visual = xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP); + mask |= CWColormap; + attributes.colormap = xnestColormap(pCmap); + } + } + + xnestWindowPriv(pWin)->window = XCreateWindow(xnestDisplay, + xnestWindowParent(pWin), + pWin->origin.x - + wBorderWidth(pWin), + pWin->origin.y - + wBorderWidth(pWin), + pWin->drawable.width, + pWin->drawable.height, + pWin->borderWidth, + pWin->drawable.depth, + pWin->drawable.class, + visual, + mask, &attributes); + xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin); + xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin); + xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin); + xnestWindowPriv(pWin)->width = pWin->drawable.width; + xnestWindowPriv(pWin)->height = pWin->drawable.height; + xnestWindowPriv(pWin)->border_width = pWin->borderWidth; + xnestWindowPriv(pWin)->sibling_above = None; + if (pWin->nextSib) + xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin); +#ifdef SHAPE + xnestWindowPriv(pWin)->bounding_shape = + REGION_CREATE(pWin->drawable.pScreen, NULL, 1); + xnestWindowPriv(pWin)->clip_shape = + REGION_CREATE(pWin->drawable.pScreen, NULL, 1); +#endif /* SHAPE */ + + if (!pWin->parent) /* only the root window will have the right colormap */ + xnestSetInstalledColormapWindows(pWin->drawable.pScreen); + + return True; +} + +Bool xnestDestroyWindow(pWin) + WindowPtr pWin; +{ + if (pWin->nextSib) + xnestWindowPriv(pWin->nextSib)->sibling_above = + xnestWindowPriv(pWin)->sibling_above; +#ifdef SHAPE + REGION_DESTROY(pWin->drawable.pScreen, + xnestWindowPriv(pWin)->bounding_shape); + REGION_DESTROY(pWin->drawable.pScreen, + xnestWindowPriv(pWin)->clip_shape); +#endif + XDestroyWindow(xnestDisplay, xnestWindow(pWin)); + xnestWindowPriv(pWin)->window = None; + + if (pWin->optional && pWin->optional->colormap && pWin->parent) + xnestSetInstalledColormapWindows(pWin->drawable.pScreen); + + return True; +} + +Bool xnestPositionWindow(pWin, x, y) + WindowPtr pWin; + int x, y; +{ + xnestConfigureWindow(pWin, + CWParent | + CWX | CWY | + CWWidth | CWHeight | + CWBorderWidth); + + return True; +} + +void xnestConfigureWindow(pWin, mask) + WindowPtr pWin; + unsigned int mask; +{ + unsigned int valuemask; + XWindowChanges values; + + if (mask & CWParent && + xnestWindowPriv(pWin)->parent != xnestWindowParent(pWin)) { + XReparentWindow(xnestDisplay, xnestWindow(pWin), + xnestWindowParent(pWin), + pWin->origin.x - wBorderWidth(pWin), + pWin->origin.y - wBorderWidth(pWin)); + xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin); + xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin); + xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin); + xnestWindowPriv(pWin)->sibling_above = None; + if (pWin->nextSib) + xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin); + } + + valuemask = 0; + + if (mask & CWX && + xnestWindowPriv(pWin)->x != pWin->origin.x - wBorderWidth(pWin)) { + valuemask |= CWX; + values.x = + xnestWindowPriv(pWin)->x = + pWin->origin.x - wBorderWidth(pWin); + } + + if (mask & CWY && + xnestWindowPriv(pWin)->y != pWin->origin.y - wBorderWidth(pWin)) { + valuemask |= CWY; + values.y = + xnestWindowPriv(pWin)->y = + pWin->origin.y - wBorderWidth(pWin); + } + + if (mask & CWWidth && + xnestWindowPriv(pWin)->width != pWin->drawable.width) { + valuemask |= CWWidth; + values.width = + xnestWindowPriv(pWin)->width = + pWin->drawable.width; + } + + if (mask & CWHeight && + xnestWindowPriv(pWin)->height != pWin->drawable.height) { + valuemask |= CWHeight; + values.height = + xnestWindowPriv(pWin)->height = + pWin->drawable.height; + } + + if (mask & CWBorderWidth && + xnestWindowPriv(pWin)->border_width != pWin->borderWidth) { + valuemask |= CWBorderWidth; + values.border_width = + xnestWindowPriv(pWin)->border_width = + pWin->borderWidth; + } + + if (valuemask) + XConfigureWindow(xnestDisplay, xnestWindow(pWin), valuemask, &values); + + if (mask & CWStackingOrder && + xnestWindowPriv(pWin)->sibling_above != xnestWindowSiblingAbove(pWin)) { + WindowPtr pSib; + + /* find the top sibling */ + for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib); + + /* the top sibling */ + valuemask = CWStackMode; + values.stack_mode = Above; + XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, &values); + xnestWindowPriv(pSib)->sibling_above = None; + + /* the rest of siblings */ + for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib) { + valuemask = CWSibling | CWStackMode; + values.sibling = xnestWindowSiblingAbove(pSib); + values.stack_mode = Below; + XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, &values); + xnestWindowPriv(pSib)->sibling_above = xnestWindowSiblingAbove(pSib); + } + } +} + +Bool xnestChangeWindowAttributes(pWin, mask) + WindowPtr pWin; + unsigned long mask; +{ + XSetWindowAttributes attributes; + + if (mask & CWBackPixmap) + switch (pWin->backgroundState) { + case None: + attributes.background_pixmap = None; + break; + + case ParentRelative: + attributes.background_pixmap = ParentRelative; + break; + + case BackgroundPixmap: + attributes.background_pixmap = xnestPixmap(pWin->background.pixmap); + break; + + case BackgroundPixel: + mask &= ~CWBackPixmap; + break; + } + + if (mask & CWBackPixel) + if (pWin->backgroundState == BackgroundPixel) + attributes.background_pixel = xnestPixel(pWin->background.pixel); + else + mask &= ~CWBackPixel; + + if (mask & CWBorderPixmap) + if (pWin->borderIsPixel) + mask &= ~CWBorderPixmap; + else + attributes.border_pixmap = xnestPixmap(pWin->border.pixmap); + + if (mask & CWBorderPixel) + if (pWin->borderIsPixel) + attributes.border_pixel = xnestPixel(pWin->border.pixel); + else + mask &= ~CWBorderPixel; + + if (mask & CWBitGravity) + attributes.bit_gravity = pWin->bitGravity; + + if (mask & CWWinGravity) /* dix does this for us */ + mask &= ~CWWinGravity; + + if (mask & CWBackingStore) /* this is really not useful */ + mask &= ~CWBackingStore; + + if (mask & CWBackingPlanes) /* this is really not useful */ + mask &= ~CWBackingPlanes; + + if (mask & CWBackingPixel) /* this is really not useful */ + mask &= ~CWBackingPixel; + + if (mask & CWOverrideRedirect) + attributes.override_redirect = pWin->overrideRedirect; + + if (mask & CWSaveUnder) /* this is really not useful */ + mask &= ~CWSaveUnder; + + if (mask & CWEventMask) /* events are handled elsewhere */ + mask &= ~CWEventMask; + + if (mask & CWDontPropagate) /* events are handled elsewhere */ + mask &= ~CWDontPropagate; + + if (mask & CWColormap) { + ColormapPtr pCmap; + + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP); + + attributes.colormap = xnestColormap(pCmap); + + xnestSetInstalledColormapWindows(pWin->drawable.pScreen); + } + + if (mask & CWCursor) /* this is handeled in cursor code */ + mask &= ~CWCursor; + + if (mask) + XChangeWindowAttributes(xnestDisplay, xnestWindow(pWin), + mask, &attributes); + + return True; +} + +Bool xnestRealizeWindow(pWin) + WindowPtr pWin; +{ + xnestConfigureWindow(pWin, CWStackingOrder); +#ifdef SHAPE + xnestShapeWindow(pWin); +#endif /* SHAPE */ + XMapWindow(xnestDisplay, xnestWindow(pWin)); + + return True; +} + +Bool xnestUnrealizeWindow(pWin) + WindowPtr pWin; +{ + XUnmapWindow(xnestDisplay, xnestWindow(pWin)); + + return True; +} + +void xnestPaintWindowBackground(pWin, pRegion, what) + WindowPtr pWin; + RegionPtr pRegion; + int what; +{ + int i; + BoxPtr pBox; + + xnestConfigureWindow(pWin, CWWidth | CWHeight); + + pBox = REGION_RECTS(pRegion); + for (i = 0; i < REGION_NUM_RECTS(pRegion); i++) + XClearArea(xnestDisplay, xnestWindow(pWin), + pBox[i].x1 - pWin->drawable.x, + pBox[i].y1 - pWin->drawable.y, + pBox[i].x2 - pBox[i].x1, + pBox[i].y2 - pBox[i].y1, + False); +} + +void xnestPaintWindowBorder(pWin, pRegion, what) + WindowPtr pWin; + RegionPtr pRegion; + int what; +{ + xnestConfigureWindow(pWin, CWBorderWidth); +} + +void xnestCopyWindow(pWin, oldOrigin, oldRegion) + WindowPtr pWin; + xPoint oldOrigin; + RegionPtr oldRegion; +{ +} + +void xnestClipNotify(pWin, dx, dy) + WindowPtr pWin; + int dx, dy; +{ + xnestConfigureWindow(pWin, CWStackingOrder); +#ifdef SHAPE + xnestShapeWindow(pWin); +#endif /* SHAPE */ +} + +static Bool xnestWindowExposurePredicate(display, event, ptr) + Display *display; + XEvent *event; + XPointer ptr; +{ + return (event->type == Expose && event->xexpose.window == *(Window *)ptr); +} + +void xnestWindowExposures(pWin, pRgn, other_exposed) + WindowPtr pWin; + RegionPtr pRgn, other_exposed; +{ + XEvent event; + Window window; + BoxRec Box; + + XSync(xnestDisplay, False); + + window = xnestWindow(pWin); + + while (XCheckIfEvent(xnestDisplay, &event, + xnestWindowExposurePredicate, (char *)&window)) { + + Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + event.xexpose.x; + Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + event.xexpose.y; + Box.x2 = Box.x1 + event.xexpose.width; + Box.y2 = Box.y1 + event.xexpose.height; + + event.xexpose.type = ProcessedExpose; + + if (RECT_IN_REGION(pWin->drawable.pScreen, pRgn, &Box) != rgnIN) + XPutBackEvent(xnestDisplay, &event); + } + + miWindowExposures(pWin, pRgn, other_exposed); +} + +#ifdef SHAPE +static Bool xnestRegionEqual(pReg1, pReg2) + RegionPtr pReg1, pReg2; +{ + BoxPtr pBox1, pBox2; + unsigned int n1, n2; + + if (pReg1 == pReg2) return True; + + if (pReg1 == NullRegion || pReg2 == NullRegion) return False; + + pBox1 = REGION_RECTS(pReg1); + n1 = REGION_NUM_RECTS(pReg1); + + pBox2 = REGION_RECTS(pReg2); + n2 = REGION_NUM_RECTS(pReg2); + + if (n1 != n2) return False; + + if (pBox1 == pBox2) return True; + + if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec))) return False; + + return True; +} + +void xnestShapeWindow(pWin) + WindowPtr pWin; +{ + Region reg; + BoxPtr pBox; + XRectangle rect; + int i; + Bool overlap; + + if (!xnestRegionEqual(xnestWindowPriv(pWin)->bounding_shape, + wBoundingShape(pWin))) { + + if (wBoundingShape(pWin)) { + REGION_COPY(pWin->drawable.pScreen, + xnestWindowPriv(pWin)->bounding_shape, wBoundingShape(pWin)); + + reg = XCreateRegion(); + pBox = REGION_RECTS(xnestWindowPriv(pWin)->bounding_shape); + for (i = 0; + i < REGION_NUM_RECTS(xnestWindowPriv(pWin)->bounding_shape); + i++) { + rect.x = pBox[i].x1; + rect.y = pBox[i].y1; + rect.width = pBox[i].x2 - pBox[i].x1; + rect.height = pBox[i].y2 - pBox[i].y1; + XUnionRectWithRegion(&rect, reg, reg); + } + XShapeCombineRegion(xnestDisplay, xnestWindow(pWin), + ShapeBounding, 0, 0, reg, ShapeSet); + XDestroyRegion(reg); + } + else { + REGION_EMPTY(pWin->drawable.pScreen, + xnestWindowPriv(pWin)->bounding_shape); + + XShapeCombineMask(xnestDisplay, xnestWindow(pWin), + ShapeBounding, 0, 0, None, ShapeSet); + } + } + + if (!xnestRegionEqual(xnestWindowPriv(pWin)->clip_shape, + wClipShape(pWin))) { + + if (wClipShape(pWin)) { + REGION_COPY(pWin->drawable.pScreen, + xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin)); + + reg = XCreateRegion(); + pBox = REGION_RECTS(xnestWindowPriv(pWin)->clip_shape); + for (i = 0; + i < REGION_NUM_RECTS(xnestWindowPriv(pWin)->clip_shape); + i++) { + rect.x = pBox[i].x1; + rect.y = pBox[i].y1; + rect.width = pBox[i].x2 - pBox[i].x1; + rect.height = pBox[i].y2 - pBox[i].y1; + XUnionRectWithRegion(&rect, reg, reg); + } + XShapeCombineRegion(xnestDisplay, xnestWindow(pWin), + ShapeClip, 0, 0, reg, ShapeSet); + XDestroyRegion(reg); + } + else { + REGION_EMPTY(pWin->drawable.pScreen, + xnestWindowPriv(pWin)->clip_shape); + + XShapeCombineMask(xnestDisplay, xnestWindow(pWin), + ShapeClip, 0, 0, None, ShapeSet); + } + } +} +#endif /* SHAPE */ diff --git a/hw/xnest/XNFont.h b/hw/xnest/XNFont.h new file mode 100644 index 000000000..2885517ac --- /dev/null +++ b/hw/xnest/XNFont.h @@ -0,0 +1,36 @@ +/* $Xorg: XNFont.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + + +#ifndef XNESTFONT_H +#define XNESTFONT_H + +typedef struct { + XFontStruct *font_struct; +} xnestPrivFont; + +extern int xnestFontPrivateIndex; + +#define xnestFontPriv(pFont) \ + ((xnestPrivFont *)FontGetPrivate(pFont, xnestFontPrivateIndex)) + +#define xnestFontStruct(pFont) (xnestFontPriv(pFont)->font_struct) + +#define xnestFont(pFont) (xnestFontStruct(pFont)->fid) + +Bool xnestRealizeFont(); +Bool xnestUnrealizeFont(); + +#endif /* XNESTFONT_H */ diff --git a/hw/xnest/XNGC.h b/hw/xnest/XNGC.h new file mode 100644 index 000000000..fe2d77de3 --- /dev/null +++ b/hw/xnest/XNGC.h @@ -0,0 +1,43 @@ +/* $Xorg: XNGC.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTGC_H +#define XNESTGC_H + +/* This file uses the GC definition form Xlib.h as XlibGC. */ + +typedef struct { + XlibGC gc; + int nClipRects; +} xnestPrivGC; + +extern int xnestGCPrivateIndex; + +#define xnestGCPriv(pGC) \ + ((xnestPrivGC *)((pGC)->devPrivates[xnestGCPrivateIndex].ptr)) + +#define xnestGC(pGC) (xnestGCPriv(pGC)->gc) + +Bool xnestCreateGC(); +void xnestValidateGC(); +void xnestChangeGC(); +void xnestCopyGC(); +void xnestDestroyGC(); +void xnestChangeClip(); +void xnestDestroyClip(); +void xnestDestroyClipHelper(); +void xnestCopyClip(); + +#endif /* XNESTGC_H */ diff --git a/hw/xnest/XNWindow.h b/hw/xnest/XNWindow.h new file mode 100644 index 000000000..28d95941e --- /dev/null +++ b/hw/xnest/XNWindow.h @@ -0,0 +1,79 @@ +/* $Xorg: XNWindow.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef XNESTWINDOW_H +#define XNESTWINDOW_H + +typedef struct { + Window window; + Window parent; + int x; + int y; + unsigned int width; + unsigned int height; + unsigned int border_width; + Window sibling_above; +#ifdef SHAPE + RegionPtr bounding_shape; + RegionPtr clip_shape; +#endif /* SHAPE */ +} xnestPrivWin; + +typedef struct { + WindowPtr pWin; + Window window; +} xnestWindowMatch; + +extern int xnestWindowPrivateIndex; + +#define xnestWindowPriv(pWin) \ + ((xnestPrivWin *)((pWin)->devPrivates[xnestWindowPrivateIndex].ptr)) + +#define xnestWindow(pWin) (xnestWindowPriv(pWin)->window) + +#define xnestWindowParent(pWin) \ + ((pWin)->parent ? \ + xnestWindow((pWin)->parent) : \ + xnestDefaultWindows[pWin->drawable.pScreen->myNum]) + +#define xnestWindowSiblingAbove(pWin) \ + ((pWin)->prevSib ? xnestWindow((pWin)->prevSib) : None) + +#define xnestWindowSiblingBelow(pWin) \ + ((pWin)->nextSib ? xnestWindow((pWin)->nextSib) : None) + +#define CWParent CWSibling +#define CWStackingOrder CWStackMode + +extern WindowPtr *WindowTable; + +WindowPtr xnestWindowPtr(); +Bool xnestCreateWindow(); +Bool xnestDestroyWindow(); +Bool xnestPositionWindow(); +void xnestConfigureWindow(); +Bool xnestChangeWindowAttributes(); +Bool xnestRealizeWindow(); +Bool xnestUnrealizeWindow(); +void xnestPaintWindowBackground(); +void xnestPaintWindowBorder(); +void xnestCopyWindow(); +void xnestClipNotify(); +void xnestWindowExposures(); +#ifdef SHAPE +void xnestShapeWindow(); +#endif /* SHAPE */ + +#endif /* XNESTWINDOW_H */ diff --git a/hw/xnest/Xnest.h b/hw/xnest/Xnest.h new file mode 100644 index 000000000..5ced40e28 --- /dev/null +++ b/hw/xnest/Xnest.h @@ -0,0 +1,95 @@ +/* $Xorg: Xnest.h,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ */ +/* + +Copyright (c) 1995 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the X Consortium. + +*/ + +/* +** Machines with a 64 bit library interface and a 32 bit server require +** name changes to protect the guilty. +*/ +#ifdef _XSERVER64 +#define _XSERVER64_tmp +#undef _XSERVER64 +typedef unsigned long XID64; +typedef unsigned long Mask64; +typedef unsigned long Atom64; +typedef unsigned long VisualID64; +typedef unsigned long Time64; +#define XID XID64 +#define Mask Mask64 +#define Atom Atom64 +#define VisualID VisualID64 +#define Time Time64 +typedef XID Window64; +typedef XID Drawable64; +typedef XID Font64; +typedef XID Pixmap64; +typedef XID Cursor64; +typedef XID Colormap64; +typedef XID GContext64; +typedef XID KeySym64; +#define Window Window64 +#define Drawable Drawable64 +#define Font Font64 +#define Pixmap Pixmap64 +#define Cursor Cursor64 +#define Colormap Colormap64 +#define GContext GContext64 +#define KeySym KeySym64 +#endif /*_XSERVER64*/ + +#define GC XlibGC +#include "Xlib.h" +#include "Xutil.h" +#include +#undef GC + +#ifdef _XSERVER64_tmp +#define _XSERVER64 +#undef _XSERVER64_tmp +#undef XID +#undef Mask +#undef Atom +#undef VisualID +#undef Time +#undef Window +#undef Drawable +#undef Font +#undef Pixmap +#undef Cursor +#undef Colormap +#undef GContext +#undef KeySym +#endif /*_XSERVER64_tmp*/ + + + + + + diff --git a/hw/xnest/Xnest.man.pre b/hw/xnest/Xnest.man.pre new file mode 100644 index 000000000..608c30dd1 --- /dev/null +++ b/hw/xnest/Xnest.man.pre @@ -0,0 +1,261 @@ +.\" $Xorg: Xnest.man,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ +.\" Copyright (c) 1993, 1994 X Consortium +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of the X Consortium shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from the X Consortium. +.TH XNEST 1 "Release 6.4" "X Version 11" +.SH NAME +Xnest \- a nested X server +.SH SYNOPSIS +.B Xnest +[-options] +.SH DESCRIPTION +\fIXnest\fP is a client and a server. \fIXnest\fP is a client of the +real server which manages windows and graphics requests on its behalf. +\fIXnest\fP is a server to its own clients. \fIXnest\fP manages +windows and graphics requests on their behalf. To these clients +\fIXnest\fP appears to be a conventional server. +.SH OPTIONS +\fIXnest\fP supports all standard options of the sample server +implementation. For more details, please see the manual page on your +system for \fIXserver\fP. The following additional arguments are +supported as well. +.TP 4 +.B \-display \fIstring\fP +This option specifies the display name of the real server that +\fIXnest\fP should try to connect with. If it is not provided on the +command line \fIXnest\fP will read the \fIDISPLAY\fP environment +variable in order to find out the same information. +.TP 4 +.B \-sync +This option tells \fIXnest\fP to synchronize its window and graphics +operations with the real server. This is a useful option for +debugging, but it will slow down the performance considerably. It +should not be used unless absolutely necessary. +.TP 4 +.B \-full +This option tells \fIXnest\fP to utilize full regeneration of real +server objects and reopen a new connection to the real server each +time the nested server regenerates. The sample server implementation +regenerates all objects in the server when the last client of this +server terminates. When this happens, \fIXnest\fP by default +maintains the same top level window and the same real server +connection in each new generation. If the user selects full +regeneration, even the top level window and the connection to the real +server will be regenerated for each server generation. +.TP 4 +.B \-class \fIstring\fP +This option specifies the default visual class of the nested server. +It is similar to the \fI-cc\fP option from the set of standard options +except that it will accept a string rather than a number for the +visual class specification. The string must be one of the following +six values: \fIStaticGray\fP, \fIGrayScale\fP, \fIStaticColor\fP, +\fIPseudoColor\fP, \fITrueColor\fP, or \fIDirectColor\fP. If both, +\fI-class\fP and \fI-cc\fP options are specified, the last instance of +either option assumes precedence. The class of the default visual of +the nested server need not be the same as the class of the default +visual of the real server; although, it has to be supported by the +real server. See \fIxdpyinfo\fP for a list of supported visual +classes on the real server before starting \fIXnest\fP. If the user +chooses a static class, all the colors in the default colormap will be +preallocated. If the user chooses a dynamic class, colors in the +default colormap will be available to individual clients for +allocation. +.TP 4 +.B \-depth \fIint\fP +This option specifies the default visual depth of the nested server. +The depth of the default visual of the nested server need not be the +same as the depth of the default visual of the real server; although, +it has to be supported by the real server. See \fIxdpyinfo\fP for a +list of supported visual depths on the real server before starting +\fIXnest\fP. +.TP 4 +.B \-sss +This option tells \fIXnest\fP to use the software screen saver. By +default \fIXnest\fP will use the screen saver that corresponds to the +hardware screen saver in the real server. Of course, even this screen +saver is software generated since \fIXnest\fP does not control any +actual hardware. However, it is treated as a hardware screen saver +within the sample server code. +.TP 4 +.B \-geometry \fIW+H+X+Y\fP +This option specifies geometry parameters for the top level +\fIXnest\fP windows. These windows corresponds to the root windows of +the nested server. The width and height specified with this option +will be the maximum width and height of each top level \fIXnest\fP +window. \fIXnest\fP will allow the user to make any top level window +smaller, but it will not actually change the size of the nested server +root window. As of yet, there is no mechanism within the sample +server implementation to change the size of the root window after +screen initialization. In order to do so, one would probably need to +extend the X protocol. Therefore, it is not likely that this will be +available any time soon. If this option is not specified \fIXnest\fP +will choose width and height to be 3/4 of the dimensions of the root +window of the real server. +.TP 4 +.B \-bw \fIint\fP +This option specifies the border width of the top level \fIXnest\fP +window. The integer parameter must be a positive number. The default +border width is 1. +.TP 4 +.B \-name \fIstring\fP +This option specifies the name of the top level \fIXnest\fP window. +The default value is the program name. +.TP 4 +.B \-scrns \fIint\fP +This option specifies the number of screens to create in the nested +server. For each screen, \fIXnest\fP will create a separate top level +window. Each screen is referenced by the number after the dot in the +client display name specification. For example, \fIxterm -display +:1.1\fP will open an \fIxterm\fP client in the nested server with the +display number \fI:1\fP on the second screen. The number of screens +is limited by the hard coded constant in the server sample code which +is usually 3. +.TP 4 +.B \-install +This option tells \fIXnest\fP to do its own colormap installation by +bypassing the real window manager. For it to work properly the user +will probably have to temporarily quit the real window manager. By +default \fIXnest\fP will keep the nested client window whose colormap +should be installed in the real server in the +\fIWM\_COLORMAP\_WINDOWS\fP property of the top level \fIXnest\fP +window. If this colormap is of the same visual type as the root +window of the nested server, \fIXnest\fP will associate this colormap +with the top level \fIXnest\fP window as well. Since this does not +have to be the case, window managers should look primarily at the +\fIWM\_COLORMAP\_WINDOWS\fP property rather than the colormap +associated with the top level \fIXnest\fP window. Unfortunately, +window managers are not very good at doing that yet so this option +might come in handy. +.TP 4 +.B \-parent \fIwindow_id\fP +This option tells \fIXnest\fP to use the \fIwindow_id\fP as the +root window instead of creating a window. This option is used +by the xrx xnestplugin. +.SH USAGE +Starting up \fIXnest\fP is as simple as starting up \fIxclock\fP from +a terminal emulator. If a user wishes to run \fIXnest\fP on the same +workstation as the real server, it is important that the nested server +is given its own listening socket address. Therefore, if there is a +server already running on the user's workstation, \fIXnest\fP will +have to be started up with a new display number. Since there is +usually no more than one server running on a workstation, specifying +\fIXnest :1\fP on the command line will be sufficient for most users. +For each server running on the workstation the display number needs to +be incremented by one. Thus, if you wish to start another +\fIXnest\fP, you will need to type \fIXnest :2\fP on the command line. +.PP +To run clients in the nested server each client needs to be given the +same display number as the nested server. For example, \fIxterm +-display :1\fP will start up an \fIxterm\fP in the first nested server +and \fIxterm -display :2\fP will start an \fIxterm\fP in the second +nested server from the example above. Additional clients can be +started from these \fIxterm\fPs in each nested server. +.SH XNEST AS A CLIENT +\fIXnest\fP behaves and looks to the real server and other real +clients as another real client. It is a rather demanding client, +however, since almost any window or graphics request from a nested +client will result in a window or graphics request from \fIXnest\fP to +the real server. Therefore, it is desirable that \fIXnest\fP and the +real server are on a local network, or even better, on the same +machine. As of now, \fIXnest\fP assumes that the real server supports +the shape extension. There is no way to turn off this assumption +dynamically. \fIXnest\fP can be compiled without the shape extension +built in, and in that case the real server need not support it. The +dynamic shape extension selection support should be considered in +further development of \fIXnest\fP. +.PP +Since \fIXnest\fP need not use the same default visual as the the real +server, the top level window of the \fIXnest\fP client always has its +own colormap. This implies that other windows' colors will not be +displayed properly while the keyboard or pointer focus is in the +\fIXnest\fP window, unless the real server has support for more than +one installed colormap at any time. The colormap associated with the +top window of the \fIXnest\fP client need not be the appropriate +colormap that the nested server wants installed in the real server. +In the case that a nested client attempts to install a colormap of a +different visual from the default visual of the nested server, +\fIXnest\fP will put the top window of this nested client and all +other top windows of the nested clients that use the same colormap +into the \fIWM\_COLORMAP\_WINDOWS\fP property of the top level +\fIXnest\fP window on the real server. Thus, it is important that the +real window manager that manages the \fIXnest\fP top level window +looks at the \fIWM\_COLORMAP\_WINDOWS\fP property rather than the +colormap associated with the top level \fIXnest\fP window. Since most +window managers appear to not implement this convention properly as of +yet, \fIXnest\fP can optionally do direct installation of colormaps +into the real server bypassing the real window manager. If the user +chooses this option, it is usually necessary to temporarily disable +the real window manager since it will interfere with the \fIXnest\fP +scheme of colormap installation. +.PP +Keyboard and pointer control procedures of the nested server change +the keyboard and pointer control parameters of the real server. +Therefore, after \fIXnest\fP is started up, it will change the +keyboard and pointer controls of the real server to its own internal +defaults. Perhaps there should be a command line option to tell +\fIXnest\fP to inherit the keyboard and pointer control parameters +from the real server rather than imposing its own. This is a future +consideration. +.SH XNEST AS A SERVER +\fIXnest\fP as a server looks exactly like a real server to its own +clients. For the clients there is no way of telling if they are +running on a real or a nested server. +.PP +As already mentioned, \fIXnest\fP is a very user friendly server when +it comes to customization. \fIXnest\fP will pick up a number of +command line arguments that can configure its default visual class and +depth, number of screens, etc. In the future, \fIXnest\fP should read +a customization input file to provide even greater freedom and +simplicity in selecting the desired layout. Unfortunately, there is +no support for backing store and save under as of yet, but this should +also be considered in the future development of \fIXnest\fP. +.PP +The only apparent intricacy from the users' perspective about using +\fIXnest\fP as a server is the selection of fonts. \fIXnest\fP +manages fonts by loading them locally and then passing the font name +to the real server and asking it to load that font remotely. This +approach avoids the overload of sending the glyph bits across the +network for every text operation, although it is really a bug. The +proper implementation of fonts should be moved into the \fIos\fP +layer. The consequence of this approach is that the user will have to +worry about two different font paths - a local one for the nested +server and a remote one for the real server - since \fIXnest\fP does +not propagate its font path to the real server. The reason for this +is because real and nested servers need not run on the same file +system which makes the two font paths mutually incompatible. Thus, if +there is a font in the local font path of the nested server, there is +no guarantee that this font exists in the remote font path of the real +server. \fIXlsfonts\fP client, if run on the nested server will list +fonts in the local font path and if run on the real server will list +fonts in the remote font path. Before a font can be successfully +opened by the nested server it has to exist in local and remote font +paths. It is the users' responsibility to make sure that this is the +case. +.SH BUGS +Won't run well on servers supporting different visual depths. +Still crashes randomly. Probably has some memory leaks. +.SH AUTHOR +Davor Matic, MIT X Consortium + diff --git a/hw/xnest/icon b/hw/xnest/icon new file mode 100644 index 000000000..725f1131a --- /dev/null +++ b/hw/xnest/icon @@ -0,0 +1,14 @@ +#define icon_width 32 +#define icon_height 32 +static unsigned char icon_bits[] = { + 0xff, 0x00, 0x00, 0xc0, 0xfe, 0x01, 0x00, 0xc0, 0xfc, 0x03, 0x00, 0x60, + 0xf8, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x00, 0x18, 0xf0, 0x0f, 0x00, 0x0c, + 0xe0, 0x1f, 0x00, 0x06, 0xc0, 0x3f, 0x00, 0x06, 0xc0, 0x3f, 0x00, 0x03, + 0x80, 0x7f, 0x80, 0x01, 0x00, 0xff, 0xc0, 0x00, 0x00, 0xfe, 0x61, 0x00, + 0x00, 0xfe, 0x31, 0x00, 0x00, 0xfc, 0x33, 0x00, 0x00, 0xf8, 0x1b, 0x00, + 0x00, 0xf0, 0x0d, 0x00, 0x00, 0xf0, 0x0e, 0x00, 0x00, 0x60, 0x1f, 0x00, + 0x00, 0xb0, 0x3f, 0x00, 0x00, 0x98, 0x7f, 0x00, 0x00, 0x98, 0x7f, 0x00, + 0x00, 0x0c, 0xff, 0x00, 0x00, 0x06, 0xfe, 0x01, 0x00, 0x03, 0xfc, 0x03, + 0x80, 0x01, 0xfc, 0x03, 0xc0, 0x00, 0xf8, 0x07, 0xc0, 0x00, 0xf0, 0x0f, + 0x60, 0x00, 0xe0, 0x1f, 0x30, 0x00, 0xe0, 0x1f, 0x18, 0x00, 0xc0, 0x3f, + 0x0c, 0x00, 0x80, 0x7f, 0x06, 0x00, 0x00, 0xff}; diff --git a/hw/xnest/screensaver b/hw/xnest/screensaver new file mode 100644 index 000000000..4940f2650 --- /dev/null +++ b/hw/xnest/screensaver @@ -0,0 +1,686 @@ +#define screensaver_width 256 +#define screensaver_height 256 +static unsigned char screensaver_bits[] = { + 0xa8, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x40, 0x55, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x55, 0x05, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0xa0, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xaa, + 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0xaa, 0x0a, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x2a, 0x80, 0x02, 0x80, 0xaa, 0xaa, 0x82, 0x0a, 0xa8, 0x28, 0x80, + 0x8a, 0x80, 0x2a, 0x80, 0x80, 0x8a, 0xa2, 0x82, 0x0a, 0xaa, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x80, 0x82, 0x41, 0x40, 0x00, 0x50, + 0x55, 0x41, 0x00, 0x00, 0x04, 0x00, 0x54, 0x40, 0x10, 0x00, 0x40, 0x00, + 0x51, 0x55, 0x00, 0x15, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x10, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x8a, 0x02, 0x00, 0x02, + 0x00, 0x20, 0xa2, 0x00, 0x80, 0x00, 0x08, 0x00, 0xaa, 0x2a, 0x00, 0x2a, + 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, + 0x01, 0x00, 0x01, 0x50, 0x45, 0x05, 0x00, 0x01, 0x10, 0x10, 0x40, 0x11, + 0x40, 0x00, 0x44, 0x00, 0x50, 0x15, 0x01, 0x15, 0x04, 0x00, 0x40, 0x00, + 0x05, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x50, 0x20, 0x00, 0x00, 0xa2, + 0xaa, 0x2a, 0x00, 0x00, 0x02, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x00, 0x00, + 0xa2, 0xaa, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x01, 0x40, 0x44, 0x15, 0x10, 0x01, + 0x10, 0x10, 0x40, 0x01, 0x40, 0x00, 0x00, 0x00, 0x54, 0x55, 0x41, 0x45, + 0x04, 0x00, 0x40, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x54, + 0x20, 0x80, 0x00, 0x82, 0xaa, 0x0a, 0x00, 0x00, 0x22, 0x00, 0x80, 0x0a, + 0x00, 0x00, 0x82, 0x00, 0xa0, 0x8a, 0x22, 0x02, 0x00, 0x08, 0x20, 0x00, + 0xa8, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x2a, 0x10, 0x40, 0x00, 0x01, + 0x54, 0x45, 0x10, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, + 0x50, 0x45, 0x05, 0x41, 0x00, 0x04, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x28, 0x00, 0xaa, 0xaa, 0x0a, 0x0a, 0x00, + 0x20, 0x08, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0xa8, 0xa2, 0x22, 0x2a, + 0x00, 0x00, 0x0a, 0x00, 0xa8, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0a, + 0x50, 0x05, 0x00, 0x01, 0x55, 0x45, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x40, 0x55, 0x11, 0x00, 0x00, 0x54, 0x01, 0x00, + 0x44, 0x01, 0x00, 0x00, 0x05, 0x40, 0x00, 0x05, 0x00, 0x08, 0x00, 0x80, + 0xaa, 0xaa, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x80, 0x00, + 0x80, 0xaa, 0x28, 0x20, 0x00, 0x00, 0x02, 0x00, 0x80, 0x02, 0x00, 0x00, + 0x28, 0x00, 0x80, 0x02, 0x10, 0x10, 0x00, 0x01, 0x54, 0x45, 0x01, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x55, 0x14, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x40, 0x40, 0x01, + 0x08, 0x00, 0x80, 0x00, 0xa8, 0xa2, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xa0, 0xaa, 0x00, 0x80, 0x28, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x80, 0x02, 0x00, 0x00, 0x80, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x14, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x40, 0x00, 0x00, 0x08, 0x20, 0x80, 0x00, 0x08, 0x08, 0x80, 0x80, + 0x80, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x8a, 0x00, + 0x02, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, + 0x10, 0x10, 0x00, 0x01, 0x10, 0x45, 0x55, 0x01, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, + 0x20, 0xa2, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x80, 0x00, 0x02, 0x04, 0x00, 0x40, 0x00, 0x04, 0x04, 0x40, 0x40, + 0x00, 0x01, 0x00, 0x04, 0x04, 0x00, 0x00, 0x01, 0x00, 0x51, 0x45, 0x05, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x45, 0x01, + 0x2a, 0x80, 0xaa, 0xaa, 0x82, 0xaa, 0x2a, 0xa0, 0x02, 0x02, 0x80, 0xa8, + 0x00, 0x2a, 0xa0, 0x02, 0x80, 0xa2, 0x00, 0xa0, 0xa0, 0x0a, 0xa0, 0x00, + 0x00, 0x00, 0x80, 0x88, 0x02, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x41, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa0, 0xaa, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x55, 0x55, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xa8, 0xaa, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x2a, 0x20, 0x00, 0x00, 0x41, 0x05, 0x55, 0x54, 0x11, 0x04, 0x00, 0x14, + 0x40, 0x10, 0x44, 0x15, 0x15, 0x00, 0x00, 0x50, 0x01, 0x00, 0x50, 0x55, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x10, 0x50, 0x40, + 0x82, 0x08, 0x02, 0x08, 0x20, 0x08, 0x00, 0x22, 0xa0, 0x20, 0x88, 0x00, + 0x22, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x80, 0x02, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x08, 0x88, 0x20, 0x44, 0x10, 0x01, 0x04, + 0x50, 0x04, 0x00, 0x41, 0x10, 0x11, 0x44, 0x00, 0x41, 0x00, 0x00, 0x54, + 0x41, 0x00, 0x40, 0x55, 0x15, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x11, 0x04, 0x11, 0x80, 0x20, 0x02, 0x08, 0xa0, 0x08, 0x00, 0x02, + 0x88, 0x20, 0x88, 0x00, 0x82, 0x00, 0x00, 0x2a, 0x22, 0x00, 0x80, 0xaa, + 0x2a, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x08, 0x20, + 0x40, 0x10, 0x01, 0x04, 0x50, 0x04, 0x00, 0x01, 0x04, 0x41, 0x44, 0x00, + 0x41, 0x00, 0x00, 0x15, 0x05, 0x14, 0x15, 0x50, 0x10, 0x05, 0x40, 0x41, + 0x41, 0x10, 0x45, 0x05, 0x50, 0x04, 0x04, 0x10, 0x80, 0x20, 0x02, 0x08, + 0xa0, 0x08, 0x00, 0x02, 0x08, 0x22, 0x82, 0x00, 0x82, 0x00, 0x00, 0x0a, + 0x2a, 0x22, 0x8a, 0x22, 0x22, 0x08, 0x80, 0x22, 0x22, 0x88, 0x88, 0x02, + 0x28, 0x02, 0x08, 0x20, 0x40, 0x10, 0x15, 0x54, 0x10, 0x05, 0x00, 0x14, + 0x04, 0x41, 0x44, 0x05, 0x41, 0x00, 0x00, 0x05, 0x50, 0x01, 0x41, 0x04, + 0x05, 0x11, 0x00, 0x05, 0x44, 0x44, 0x50, 0x00, 0x10, 0x05, 0x50, 0x10, + 0x80, 0x0a, 0x02, 0x08, 0x20, 0x0a, 0x00, 0x20, 0xa8, 0x82, 0x82, 0x00, + 0x2a, 0x00, 0x80, 0x02, 0x22, 0x02, 0x82, 0x20, 0x20, 0x08, 0x20, 0x88, + 0x82, 0x88, 0x8a, 0x00, 0x88, 0x0a, 0x80, 0x20, 0x40, 0x04, 0x01, 0x04, + 0x10, 0x05, 0x00, 0x40, 0x04, 0x41, 0x41, 0x00, 0x11, 0x00, 0x40, 0x01, + 0x41, 0x41, 0x41, 0x14, 0x15, 0x11, 0x40, 0x44, 0x04, 0x44, 0x40, 0x00, + 0x44, 0x15, 0x00, 0x11, 0x80, 0x08, 0x02, 0x08, 0x20, 0x0a, 0x00, 0x80, + 0x08, 0x82, 0x82, 0x00, 0x22, 0x00, 0xa0, 0x00, 0x22, 0x22, 0x82, 0x20, + 0x22, 0x0a, 0x20, 0x28, 0x82, 0x82, 0x88, 0x00, 0x88, 0x2a, 0x00, 0x22, + 0x44, 0x10, 0x01, 0x04, 0x10, 0x04, 0x00, 0x41, 0x04, 0x01, 0x41, 0x00, + 0x41, 0x00, 0x50, 0x01, 0x14, 0x14, 0x01, 0x55, 0x10, 0x15, 0x40, 0x45, + 0x05, 0x01, 0x45, 0x00, 0x04, 0x55, 0x04, 0x11, 0x82, 0x20, 0x02, 0x08, + 0x20, 0x08, 0x00, 0x22, 0x08, 0x82, 0x80, 0x00, 0x82, 0x00, 0xa8, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xaa, 0x88, 0x20, 0x41, 0x10, 0x55, 0x54, 0x11, 0x04, 0x00, 0x14, + 0x04, 0x01, 0x41, 0x15, 0x41, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x54, 0x51, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x15, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xa8, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x15, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x14, 0x40, 0x01, 0x41, 0x40, 0x01, 0x14, 0x10, 0x01, 0x00, 0x40, + 0x01, 0x04, 0x14, 0x14, 0x14, 0x10, 0x04, 0x00, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xaa, 0x00, 0x00, 0x00, 0x80, 0x82, 0xa0, 0x20, 0x82, + 0xa2, 0x20, 0x02, 0x22, 0x28, 0x02, 0x00, 0x08, 0x8a, 0x22, 0x08, 0x08, + 0x22, 0x28, 0x0a, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x54, + 0x01, 0x00, 0x00, 0x40, 0x41, 0x40, 0x10, 0x04, 0x11, 0x11, 0x04, 0x41, + 0x10, 0x04, 0x00, 0x04, 0x04, 0x40, 0x10, 0x00, 0x41, 0x10, 0x11, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xaa, 0x02, 0x00, 0x00, 0xa0, + 0x82, 0x80, 0x08, 0x08, 0x02, 0x08, 0x88, 0x80, 0x08, 0x08, 0x00, 0x08, + 0x08, 0x20, 0x20, 0x80, 0x80, 0x20, 0x00, 0x00, 0x10, 0x50, 0x14, 0x14, + 0x45, 0x05, 0x40, 0x05, 0x41, 0x14, 0x15, 0x50, 0x41, 0x01, 0x04, 0x00, + 0x01, 0x04, 0x50, 0x00, 0x11, 0x04, 0x00, 0x14, 0x00, 0x40, 0x10, 0x44, + 0x00, 0x11, 0x00, 0x00, 0xa0, 0x88, 0x22, 0xa2, 0x88, 0x08, 0x00, 0x2a, + 0x82, 0x22, 0x22, 0xa8, 0x80, 0x0a, 0x08, 0x00, 0x02, 0xa8, 0x8a, 0xaa, + 0x08, 0x08, 0x00, 0xa8, 0x00, 0x2a, 0x20, 0x80, 0xaa, 0x20, 0x00, 0x00, + 0x00, 0x05, 0x04, 0x15, 0x55, 0x04, 0x40, 0x04, 0x50, 0x54, 0x01, 0x54, + 0x00, 0x54, 0x04, 0x00, 0x01, 0x04, 0x40, 0x00, 0x10, 0x04, 0x00, 0x40, + 0x05, 0x41, 0x40, 0x40, 0x00, 0x10, 0x00, 0x00, 0x80, 0x08, 0x02, 0x82, + 0x80, 0x08, 0x80, 0x20, 0x02, 0x02, 0x02, 0x2a, 0x00, 0xa0, 0x08, 0x00, + 0x02, 0x08, 0x80, 0x00, 0x08, 0x08, 0x00, 0x00, 0x8a, 0x20, 0x20, 0x82, + 0x00, 0x20, 0x00, 0x00, 0x10, 0x45, 0x04, 0x11, 0x51, 0x04, 0x50, 0x44, + 0x44, 0x44, 0x01, 0x15, 0x00, 0x40, 0x05, 0x00, 0x01, 0x04, 0x40, 0x00, + 0x10, 0x04, 0x00, 0x00, 0x54, 0x40, 0x40, 0x41, 0x00, 0x10, 0x00, 0x00, + 0xa0, 0x28, 0x02, 0x0a, 0x8a, 0x08, 0x20, 0x0a, 0x0a, 0x28, 0x02, 0x0a, + 0x00, 0x80, 0x08, 0x00, 0x02, 0x08, 0x80, 0x00, 0x08, 0x08, 0x00, 0x00, + 0x88, 0x20, 0x80, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x05, 0x40, 0x00, 0x11, 0x00, + 0x01, 0x10, 0x10, 0x01, 0x11, 0x04, 0x00, 0x04, 0x50, 0x40, 0x41, 0x01, + 0x01, 0x11, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, + 0xaa, 0x00, 0x80, 0x02, 0x80, 0x80, 0x20, 0x02, 0x02, 0x20, 0x08, 0x82, + 0x08, 0x08, 0x00, 0x08, 0x88, 0x20, 0x80, 0x00, 0x82, 0x20, 0x00, 0x00, + 0x00, 0x40, 0x01, 0x10, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x40, 0x01, + 0x40, 0x14, 0x40, 0x41, 0x05, 0x40, 0x01, 0x14, 0x14, 0x14, 0x00, 0x44, + 0x01, 0x45, 0x00, 0x00, 0x14, 0x54, 0x00, 0x00, 0x00, 0x80, 0x02, 0x08, + 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x50, + 0x55, 0x05, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x02, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0xa8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, + 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0xaa, 0x0a, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x15, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x15, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x8a, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xa2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x05, 0x50, 0x00, 0x50, 0x40, 0x45, 0x11, 0x00, 0x50, + 0x40, 0x41, 0x01, 0x00, 0x14, 0x00, 0x51, 0x40, 0x40, 0x00, 0x05, 0x14, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0a, + 0x88, 0x02, 0xaa, 0xa8, 0x80, 0x00, 0x00, 0xaa, 0xa8, 0xa2, 0x02, 0x00, + 0xa2, 0xa0, 0x22, 0xa8, 0xa0, 0xa0, 0x8a, 0x2a, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x14, 0x04, 0x01, 0x45, 0x51, + 0x04, 0x40, 0x00, 0x45, 0x41, 0x51, 0x01, 0x00, 0x41, 0x50, 0x54, 0x50, + 0x50, 0x50, 0x14, 0x14, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0xa2, 0xa0, 0x02, 0xa0, 0x88, 0x82, + 0xa0, 0x88, 0x02, 0x80, 0x82, 0x28, 0x28, 0xa0, 0x20, 0x28, 0x08, 0x8a, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x45, 0x54, 0x00, + 0x14, 0x40, 0x41, 0x50, 0x05, 0x51, 0x10, 0x41, 0x41, 0x41, 0x01, 0x00, + 0x05, 0x14, 0x10, 0x50, 0x40, 0x10, 0x14, 0x54, 0x04, 0x00, 0x41, 0x55, + 0x04, 0x45, 0x01, 0x04, 0x20, 0x02, 0x08, 0x00, 0x2a, 0xa0, 0x00, 0xa0, + 0x8a, 0x20, 0xa8, 0xa2, 0xa0, 0xa0, 0x00, 0x80, 0x0a, 0x28, 0x28, 0xa0, + 0x20, 0x28, 0x0a, 0x2a, 0x00, 0x00, 0x22, 0x0a, 0x80, 0x88, 0x02, 0x88, + 0x04, 0x50, 0x01, 0x00, 0x54, 0x40, 0x01, 0x50, 0x15, 0x10, 0x14, 0x51, + 0x40, 0x41, 0x01, 0x00, 0x15, 0x14, 0x14, 0x40, 0x11, 0x14, 0x05, 0x14, + 0x00, 0x40, 0x10, 0x00, 0x15, 0x45, 0x04, 0x01, 0x00, 0x00, 0x08, 0x00, + 0xa8, 0xa0, 0x00, 0x28, 0x8a, 0x08, 0x0a, 0x28, 0xa0, 0xa0, 0x00, 0x00, + 0x2a, 0x0a, 0x28, 0xa0, 0x08, 0x8a, 0x02, 0x0a, 0x00, 0x80, 0x00, 0x08, + 0x80, 0x00, 0x00, 0x82, 0x44, 0x11, 0x00, 0x00, 0x50, 0x50, 0x00, 0x10, + 0x05, 0x40, 0x15, 0x05, 0x50, 0x50, 0x00, 0x00, 0x14, 0x14, 0x14, 0x40, + 0x11, 0x54, 0x00, 0x05, 0x00, 0x00, 0x11, 0x00, 0x01, 0x40, 0x04, 0x44, + 0x80, 0x20, 0x0a, 0x00, 0xa0, 0xa0, 0x00, 0x88, 0x82, 0xa8, 0x0a, 0x00, + 0xa0, 0xa0, 0x00, 0x00, 0x28, 0x0a, 0x0a, 0xa0, 0x08, 0x0a, 0x00, 0x0a, + 0x00, 0x00, 0x22, 0x0a, 0xa2, 0x00, 0x00, 0x88, 0x01, 0x40, 0x15, 0x00, + 0x50, 0x51, 0x40, 0x00, 0x01, 0x51, 0x15, 0x00, 0x50, 0x50, 0x00, 0x00, + 0x54, 0x14, 0x54, 0x40, 0x05, 0x14, 0x00, 0x05, 0x00, 0x40, 0x41, 0x15, + 0x14, 0x45, 0x04, 0x05, 0x00, 0x00, 0x00, 0x80, 0xa0, 0xa0, 0x20, 0x88, + 0x80, 0xaa, 0x08, 0x82, 0x28, 0x28, 0x02, 0x20, 0x28, 0x0a, 0x2a, 0xa0, + 0x02, 0x0a, 0x88, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x40, 0x11, 0x44, 0x00, 0x55, 0x14, 0x44, + 0x50, 0x50, 0x01, 0x40, 0x10, 0x54, 0x15, 0x40, 0x01, 0x14, 0x04, 0x45, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x22, 0xa0, 0x0a, 0x00, 0x00, 0x0a, 0x2a, 0x20, 0x28, 0xa8, 0x00, 0xa0, + 0x08, 0xa8, 0x08, 0xa0, 0x00, 0xa8, 0x82, 0x82, 0x02, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x05, 0x00, + 0x00, 0x54, 0x55, 0x10, 0x50, 0x50, 0x00, 0x00, 0x05, 0x50, 0x04, 0x40, + 0x00, 0x50, 0x40, 0x05, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x80, 0xaa, 0x2a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, + 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0x55, 0x55, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, + 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa8, 0xaa, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x50, 0x55, + 0x05, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x28, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x80, 0xaa, + 0x2a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x50, 0x15, + 0x55, 0x11, 0x55, 0x00, 0x15, 0x00, 0x54, 0x01, 0x00, 0x54, 0x01, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x00, 0x20, 0x82, 0x20, 0x08, 0x82, 0x00, 0x22, 0x80, + 0x08, 0x08, 0x28, 0xa2, 0x28, 0x20, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa2, + 0x00, 0x04, 0x41, 0x10, 0x04, 0x11, 0x00, 0x40, 0x10, 0x14, 0x10, 0x54, + 0x54, 0x11, 0x10, 0x00, 0x01, 0x00, 0x50, 0x14, 0x15, 0x05, 0x45, 0x01, + 0x50, 0x50, 0x44, 0x14, 0x05, 0x00, 0x04, 0x40, 0x20, 0x02, 0x22, 0x02, + 0x22, 0x08, 0x20, 0x20, 0x00, 0x08, 0x20, 0xa8, 0x28, 0x22, 0x08, 0x80, + 0x02, 0x00, 0x88, 0x22, 0xa2, 0x88, 0x28, 0x02, 0x88, 0x80, 0x22, 0xa2, + 0x08, 0x00, 0x08, 0x22, 0x00, 0x04, 0x41, 0x00, 0x04, 0x00, 0x01, 0x40, + 0x00, 0x10, 0x40, 0x04, 0x11, 0x10, 0x04, 0x10, 0x05, 0x00, 0x10, 0x04, + 0x01, 0x55, 0x45, 0x04, 0x10, 0x50, 0x44, 0x15, 0x01, 0x00, 0x14, 0x10, + 0x00, 0x2a, 0xa0, 0x02, 0x2a, 0x20, 0x22, 0x80, 0x02, 0x22, 0x20, 0x02, + 0x0a, 0xa0, 0x02, 0x08, 0x0a, 0x00, 0x20, 0x02, 0x82, 0x80, 0x20, 0x02, + 0x80, 0x88, 0x28, 0x82, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x44, 0x40, 0x01, + 0x14, 0x00, 0x04, 0x00, 0x05, 0x10, 0x40, 0x00, 0x11, 0x10, 0x05, 0x04, + 0x14, 0x00, 0x44, 0x44, 0x01, 0x51, 0x44, 0x04, 0x10, 0x45, 0x14, 0x11, + 0x01, 0x00, 0x50, 0x11, 0x00, 0x82, 0x20, 0x02, 0x22, 0x20, 0x28, 0x20, + 0x08, 0x2a, 0x80, 0x02, 0x02, 0x20, 0x08, 0x00, 0x00, 0x00, 0x28, 0x28, + 0x02, 0x8a, 0x22, 0x02, 0xa0, 0xa8, 0x08, 0x8a, 0x00, 0x00, 0x80, 0x22, + 0x00, 0x04, 0x41, 0x10, 0x04, 0x01, 0x10, 0x00, 0x10, 0x41, 0x40, 0x01, + 0x11, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x51, 0x20, 0x82, 0x20, 0x00, + 0x02, 0x20, 0x28, 0x20, 0x88, 0x20, 0x80, 0x00, 0x82, 0x20, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x22, 0x10, 0x04, 0x45, 0x10, 0x04, 0x01, 0x10, 0x40, + 0x04, 0x40, 0x00, 0x00, 0x41, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x41, + 0x8a, 0x0a, 0xaa, 0x8a, 0xaa, 0xa8, 0x20, 0xa0, 0x82, 0xa2, 0x80, 0x80, + 0xaa, 0xa8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0xa2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x10, 0x50, + 0x41, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x15, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xa0, 0x80, 0x02, 0xa8, 0x28, + 0x0a, 0xa0, 0x02, 0xa8, 0x00, 0x8a, 0x02, 0x28, 0x00, 0x00, 0x00, 0x0a, + 0x28, 0x80, 0x2a, 0x80, 0x22, 0x80, 0x0a, 0x00, 0xa8, 0x00, 0x28, 0x2a, + 0x00, 0x05, 0x00, 0x50, 0x00, 0x00, 0x55, 0x51, 0x14, 0x14, 0x54, 0x54, + 0x01, 0x54, 0x01, 0x50, 0x50, 0x05, 0x00, 0x05, 0x00, 0x50, 0x55, 0x40, + 0x51, 0x50, 0x15, 0x00, 0x54, 0x05, 0x14, 0x55, 0x00, 0x0a, 0x00, 0xa0, + 0x00, 0x80, 0xaa, 0x2a, 0x2a, 0x08, 0x2a, 0xa8, 0x02, 0xaa, 0x02, 0xa0, + 0xa0, 0x02, 0x00, 0x0a, 0x00, 0xa8, 0xaa, 0x80, 0x2a, 0xa8, 0x2a, 0x80, + 0xaa, 0x0a, 0xa8, 0xaa, 0x01, 0x05, 0x00, 0x50, 0x05, 0x40, 0x55, 0x55, + 0x14, 0x00, 0x14, 0x50, 0x05, 0x54, 0x01, 0x40, 0x51, 0x01, 0x00, 0x55, + 0x00, 0x54, 0x55, 0x41, 0x15, 0x54, 0x55, 0x40, 0x55, 0x15, 0x54, 0x55, + 0x02, 0x0a, 0x00, 0xa0, 0x0a, 0xa0, 0x02, 0x2a, 0x2a, 0x00, 0x0a, 0x88, + 0x0a, 0x2a, 0x00, 0x80, 0xaa, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0xa0, 0xa2, + 0x0a, 0x2a, 0xa8, 0xa0, 0x0a, 0x0a, 0xaa, 0xa0, 0x01, 0x14, 0x01, 0x40, + 0x55, 0x50, 0x01, 0x14, 0x14, 0x00, 0x05, 0x04, 0x15, 0x15, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x54, 0x05, 0x14, 0x40, 0x45, 0x05, 0x15, 0x50, 0x41, + 0x01, 0x14, 0x54, 0x40, 0x02, 0xa8, 0x00, 0x80, 0xaa, 0xa8, 0x00, 0x2a, + 0x28, 0x88, 0x02, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x0a, 0x0a, 0xa0, 0xa2, 0x82, 0x0a, 0xa0, 0xa0, 0x00, 0x28, 0x2a, 0xa0, + 0x01, 0x50, 0x00, 0x00, 0x55, 0x50, 0x00, 0x14, 0x54, 0x54, 0x05, 0x15, + 0x14, 0x15, 0x00, 0x00, 0x11, 0x00, 0x00, 0x50, 0x05, 0x15, 0x00, 0x40, + 0x01, 0x05, 0x40, 0x51, 0x00, 0x14, 0x14, 0x40, 0x00, 0xa8, 0x00, 0x00, + 0xa8, 0x28, 0x00, 0x28, 0x28, 0xa8, 0x02, 0x80, 0x0a, 0x0a, 0x00, 0x80, + 0x08, 0x00, 0x00, 0x80, 0x8a, 0x0a, 0x00, 0xa0, 0x80, 0xaa, 0xaa, 0xa8, + 0xaa, 0x2a, 0x0a, 0xa0, 0x01, 0x44, 0x01, 0x00, 0x50, 0x55, 0x00, 0x14, + 0x50, 0x14, 0x01, 0x00, 0x15, 0x05, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, + 0x15, 0x05, 0x00, 0x50, 0x41, 0x55, 0x55, 0x51, 0x55, 0x15, 0x15, 0x40, + 0x00, 0x80, 0x02, 0x00, 0xa0, 0x28, 0x00, 0x0a, 0x28, 0x0a, 0x02, 0x00, + 0x8a, 0x0a, 0x00, 0xa0, 0x2a, 0x00, 0x00, 0x00, 0x8a, 0x0a, 0x00, 0xa0, + 0x80, 0xaa, 0xaa, 0xa8, 0xaa, 0x2a, 0x0a, 0xa0, 0x01, 0x40, 0x01, 0x00, + 0x50, 0x55, 0x00, 0x14, 0x50, 0x05, 0x00, 0x00, 0x14, 0x05, 0x00, 0x50, + 0x50, 0x00, 0x00, 0x00, 0x15, 0x05, 0x00, 0x50, 0x40, 0x55, 0x55, 0x51, + 0x55, 0x15, 0x05, 0x50, 0x00, 0x80, 0x02, 0x2a, 0xa8, 0x28, 0x00, 0x0a, + 0xa8, 0x0a, 0x80, 0xaa, 0x82, 0x02, 0x00, 0x20, 0xa0, 0x00, 0xa0, 0x82, + 0x8a, 0x0a, 0x00, 0xa0, 0x80, 0x02, 0x00, 0x28, 0x00, 0x00, 0x0a, 0xa0, + 0x00, 0x00, 0x05, 0x14, 0x50, 0x54, 0x00, 0x15, 0x50, 0x05, 0x40, 0x55, + 0x01, 0x05, 0x00, 0x10, 0x40, 0x01, 0x40, 0x01, 0x05, 0x15, 0x50, 0x51, + 0x40, 0x01, 0x00, 0x50, 0x00, 0x00, 0x05, 0x50, 0x00, 0x00, 0x0a, 0x2a, + 0xa8, 0xa8, 0x80, 0x0a, 0xa0, 0x02, 0x80, 0x0a, 0x80, 0x02, 0x00, 0x08, + 0x80, 0x02, 0xa0, 0x82, 0x0a, 0x2a, 0xa8, 0xa0, 0x80, 0x02, 0x2a, 0xa8, + 0x80, 0x8a, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x54, 0x55, 0x50, 0x55, 0x05, + 0x50, 0x01, 0x00, 0x00, 0x44, 0x05, 0x00, 0x04, 0x00, 0x05, 0x40, 0x55, + 0x05, 0x54, 0x55, 0x50, 0x00, 0x55, 0x15, 0x50, 0x55, 0x05, 0x05, 0x50, + 0x00, 0x00, 0x00, 0xa8, 0x2a, 0xa0, 0xaa, 0x0a, 0xa0, 0x00, 0x08, 0x00, + 0x8a, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x80, 0xaa, 0x02, 0xaa, 0x2a, 0x28, + 0x80, 0xaa, 0x0a, 0xa0, 0xaa, 0x82, 0x02, 0x28, 0x00, 0x00, 0x00, 0x50, + 0x15, 0x40, 0x55, 0x05, 0x40, 0x01, 0x10, 0x00, 0x55, 0x01, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x55, 0x01, 0x54, 0x15, 0x50, 0x00, 0x55, 0x05, 0x40, + 0x55, 0x01, 0x05, 0x50, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x80, 0x0a, 0x0a, + 0xa0, 0x00, 0x00, 0xa0, 0xaa, 0x02, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0xa0, 0x0a, 0x28, 0x00, 0xa8, 0x00, 0x80, 0x2a, 0x80, 0x02, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + 0x55, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0xa0, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, + 0xaa, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x55, 0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xaa, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x45, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x22, 0xa0, 0x22, 0xa8, 0x0a, 0xa8, 0x00, + 0xa8, 0xa0, 0x28, 0x80, 0xaa, 0x22, 0x28, 0xa0, 0x02, 0x2a, 0x2a, 0xa0, + 0x02, 0x8a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x15, 0x50, 0x15, 0x54, 0x15, 0x54, 0x01, 0x55, 0x41, 0x55, 0x00, + 0x55, 0x11, 0x54, 0x50, 0x05, 0x54, 0x54, 0x54, 0x05, 0x54, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x08, 0x08, + 0x20, 0x08, 0x02, 0x82, 0x82, 0x82, 0x82, 0x00, 0xaa, 0x08, 0x20, 0x20, + 0x08, 0x08, 0x08, 0x0a, 0x0a, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, 0x04, 0x10, 0x10, 0x00, 0x01, 0x04, + 0x01, 0x01, 0x01, 0x01, 0x54, 0x14, 0x11, 0x00, 0x10, 0x10, 0x04, 0x04, + 0x04, 0x10, 0x00, 0x14, 0x51, 0x10, 0x44, 0x01, 0x50, 0x44, 0x44, 0x14, + 0xa0, 0x00, 0x02, 0x08, 0x08, 0x80, 0x00, 0x82, 0x00, 0x82, 0x80, 0x00, + 0xa8, 0x28, 0x00, 0xa0, 0x0a, 0x20, 0x08, 0x02, 0x08, 0x08, 0x00, 0x00, + 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x05, 0x04, 0x00, + 0x10, 0x00, 0x55, 0x45, 0x55, 0x41, 0x40, 0x00, 0x54, 0x54, 0x00, 0x50, + 0x05, 0x10, 0x04, 0x55, 0x05, 0x04, 0x00, 0x44, 0x10, 0x14, 0x45, 0x04, + 0x10, 0x54, 0x54, 0x04, 0x00, 0x0a, 0x02, 0x00, 0x08, 0x80, 0xaa, 0x82, + 0xaa, 0x82, 0x80, 0x00, 0x2a, 0xaa, 0x00, 0x08, 0x08, 0x20, 0x02, 0xaa, + 0x0a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x10, 0x14, 0x04, 0x00, 0x04, 0x00, 0x01, 0x40, 0x00, 0x40, 0x40, 0x00, + 0x15, 0x45, 0x15, 0x04, 0x04, 0x10, 0x01, 0x01, 0x00, 0x04, 0x00, 0x05, + 0x15, 0x10, 0x44, 0x04, 0x14, 0x14, 0x41, 0x04, 0x08, 0x08, 0x0a, 0x08, + 0x08, 0x80, 0x02, 0x82, 0x80, 0x20, 0x20, 0x80, 0x8a, 0x8a, 0x22, 0x02, + 0x02, 0xa0, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x05, 0x54, 0x15, 0x55, 0x01, 0x55, 0x01, + 0x55, 0x51, 0x51, 0x01, 0x45, 0x05, 0x00, 0x54, 0x15, 0x40, 0x00, 0x54, + 0x45, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0x02, 0xa8, 0x82, 0xaa, 0x00, 0xaa, 0x00, 0x2a, 0xa8, 0xa8, 0x80, + 0x82, 0x22, 0x20, 0xa8, 0x0a, 0x20, 0x00, 0xa8, 0x80, 0xaa, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x55, 0x55, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0xa8, 0xaa, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x2a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x54, 0x55, 0x01, 0x00, 0x40, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x80, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x50, 0x55, 0x05, + 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x0a, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x0a, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, + 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x80, 0xaa, 0x2a, + 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0x02, 0x08, 0x00, 0x10, 0x50, 0x50, 0x50, 0x40, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x50, 0x00, + 0x50, 0x00, 0x05, 0x04, 0x01, 0x05, 0x50, 0x40, 0x54, 0x05, 0x04, 0x05, + 0x8a, 0x20, 0x20, 0x88, 0xa0, 0x28, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, + 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x20, 0x00, 0x82, 0x82, 0x08, 0x8a, + 0x82, 0x08, 0x88, 0xa0, 0xa8, 0x0a, 0x22, 0x28, 0x00, 0x41, 0x00, 0x04, + 0x41, 0x44, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x55, 0x55, + 0x00, 0x00, 0x10, 0x00, 0x01, 0x41, 0x10, 0x44, 0x44, 0x10, 0x04, 0x41, + 0x50, 0x15, 0x11, 0x10, 0x80, 0x80, 0x00, 0x02, 0x82, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x80, 0x00, + 0x02, 0x22, 0x20, 0x08, 0x20, 0x20, 0x02, 0x22, 0xa0, 0x2a, 0x22, 0x20, + 0x00, 0x41, 0x10, 0x01, 0x44, 0x00, 0x00, 0x40, 0x41, 0x51, 0x04, 0x14, + 0x15, 0x00, 0x11, 0x44, 0x50, 0x54, 0x40, 0x01, 0x05, 0x10, 0x00, 0x04, + 0x10, 0x40, 0x01, 0x44, 0x10, 0x15, 0x51, 0x00, 0xa8, 0x80, 0x00, 0xaa, + 0x82, 0x00, 0x00, 0x20, 0x22, 0x8a, 0xa2, 0x22, 0x22, 0x80, 0xa0, 0x88, + 0x88, 0x88, 0x88, 0x02, 0x2a, 0x20, 0x00, 0x08, 0xa0, 0x2a, 0xaa, 0x22, + 0x20, 0x8a, 0xa0, 0x02, 0x04, 0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x40, + 0x10, 0x10, 0x41, 0x54, 0x11, 0x00, 0x11, 0x40, 0x54, 0x05, 0x04, 0x05, + 0x50, 0x11, 0x00, 0x04, 0x10, 0x00, 0x01, 0x40, 0x10, 0x45, 0x00, 0x15, + 0x82, 0x80, 0x08, 0x02, 0x80, 0x00, 0x00, 0x00, 0x22, 0x88, 0x02, 0x02, + 0x22, 0x00, 0x82, 0x08, 0x02, 0x08, 0x02, 0x0a, 0x80, 0x22, 0x00, 0x08, + 0x20, 0x00, 0x02, 0x20, 0x20, 0xa2, 0x00, 0x28, 0x01, 0x01, 0x05, 0x01, + 0x40, 0x00, 0x00, 0x40, 0x14, 0x51, 0x41, 0x44, 0x11, 0x40, 0x04, 0x11, + 0x04, 0x05, 0x01, 0x14, 0x00, 0x15, 0x00, 0x04, 0x10, 0x00, 0x01, 0x40, + 0x10, 0x51, 0x01, 0x50, 0x82, 0x00, 0x02, 0x02, 0x80, 0x00, 0x00, 0x80, + 0xa2, 0x88, 0x2a, 0x28, 0x22, 0x80, 0x02, 0x28, 0x8a, 0x88, 0x00, 0x28, + 0x00, 0x22, 0x00, 0x08, 0x20, 0x00, 0x02, 0x20, 0xa0, 0xa8, 0x02, 0x20, + 0x01, 0x05, 0x05, 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, + 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x01, 0x44, 0x00, 0x04, + 0x40, 0x40, 0x04, 0x44, 0x10, 0x51, 0x15, 0x40, 0x82, 0x00, 0x02, 0x08, + 0x82, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, + 0x2a, 0x00, 0x00, 0x00, 0x02, 0x82, 0x08, 0x08, 0x80, 0x20, 0x08, 0x22, + 0xa0, 0xa0, 0x2a, 0x20, 0x14, 0x01, 0x00, 0x50, 0x50, 0x01, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x15, 0x00, 0x05, 0x50, 0x50, 0x50, 0x40, 0x15, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x54, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa0, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x55, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xaa, 0x15, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, + 0xa2, 0x00, 0x80, 0x02, 0x0a, 0xa2, 0x82, 0x02, 0x0a, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xa8, 0xa0, 0x80, 0x82, 0xa0, 0x11, 0x01, 0x00, 0x04, + 0x11, 0x50, 0x41, 0x04, 0x11, 0x10, 0x00, 0x14, 0x44, 0x40, 0x00, 0x41, + 0x11, 0x00, 0x14, 0x00, 0x44, 0x05, 0x05, 0x04, 0x45, 0x00, 0x10, 0x44, + 0x11, 0x11, 0x04, 0x44, 0xa2, 0x02, 0x20, 0x80, 0x20, 0x28, 0x20, 0x08, + 0x02, 0x20, 0x80, 0x22, 0xa8, 0xa8, 0xa0, 0x82, 0x28, 0x00, 0x28, 0x80, + 0x22, 0x08, 0x82, 0x0a, 0x22, 0x80, 0x00, 0x82, 0x20, 0x00, 0x88, 0x8a, + 0x51, 0x05, 0x50, 0x00, 0x10, 0x11, 0x11, 0x10, 0x01, 0x50, 0x40, 0x10, + 0x54, 0x04, 0x11, 0x04, 0x41, 0x00, 0x50, 0x40, 0x10, 0x04, 0x44, 0x10, + 0x44, 0x40, 0x01, 0x01, 0x10, 0x10, 0x44, 0x14, 0xa2, 0x00, 0xa0, 0x00, + 0xa8, 0x02, 0xa0, 0x0a, 0x02, 0xa0, 0xa0, 0x00, 0x0a, 0x82, 0x08, 0x82, + 0x20, 0x00, 0xa0, 0x20, 0x20, 0x08, 0x22, 0x08, 0x02, 0x80, 0x02, 0x02, + 0x20, 0xa8, 0x8a, 0x82, 0x51, 0x01, 0x40, 0x01, 0x55, 0x01, 0x10, 0x00, + 0x01, 0x40, 0x41, 0x00, 0x04, 0x54, 0x50, 0x41, 0x40, 0x00, 0x40, 0x10, + 0x10, 0x04, 0x41, 0x05, 0x01, 0x00, 0x05, 0x01, 0x10, 0x10, 0x40, 0x50, + 0xa2, 0x08, 0x80, 0x82, 0xa0, 0x8a, 0x20, 0x00, 0x02, 0x80, 0x22, 0x00, + 0x02, 0x0a, 0x28, 0x80, 0x20, 0x00, 0x80, 0x20, 0x08, 0x88, 0xa0, 0x00, + 0x02, 0x00, 0x0a, 0x02, 0x20, 0x08, 0x80, 0xa0, 0x51, 0x01, 0x00, 0x44, + 0x50, 0x11, 0x10, 0x00, 0x01, 0x00, 0x11, 0x00, 0x01, 0x01, 0x04, 0x40, + 0x10, 0x00, 0x40, 0x11, 0x10, 0x10, 0x11, 0x00, 0x01, 0x00, 0x10, 0x01, + 0x10, 0x10, 0x40, 0x50, 0xa2, 0x08, 0x00, 0x88, 0x80, 0x08, 0x20, 0x00, + 0x02, 0x02, 0x22, 0x00, 0x02, 0x02, 0x08, 0x20, 0x20, 0x00, 0x80, 0x08, + 0x08, 0x88, 0x20, 0x80, 0x00, 0x00, 0x20, 0x02, 0x20, 0x28, 0x80, 0xa0, + 0x51, 0x11, 0x10, 0x44, 0x40, 0x50, 0x40, 0x10, 0x01, 0x00, 0x11, 0x00, + 0x01, 0x01, 0x04, 0x40, 0x10, 0x00, 0x01, 0x11, 0x04, 0x50, 0x10, 0x00, + 0x01, 0x40, 0x10, 0x04, 0x11, 0x50, 0x00, 0x01, 0xa2, 0x28, 0x20, 0x82, + 0x0a, 0x20, 0xa0, 0x0a, 0x02, 0x02, 0x22, 0x88, 0x00, 0x82, 0x08, 0x22, + 0x08, 0x80, 0x80, 0x28, 0x08, 0x28, 0x20, 0x88, 0x00, 0x80, 0x08, 0xaa, + 0x20, 0xa0, 0x82, 0xaa, 0x41, 0x50, 0x50, 0x01, 0x55, 0x00, 0x00, 0x05, + 0x05, 0x05, 0x51, 0x04, 0x01, 0x45, 0x14, 0x11, 0x50, 0x00, 0x41, 0x50, + 0x04, 0x10, 0x50, 0x44, 0x00, 0x40, 0x05, 0x50, 0x50, 0x40, 0x01, 0x14, + 0xaa, 0xaa, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa0, 0x82, + 0x00, 0x2a, 0xa8, 0x20, 0x28, 0x80, 0x2a, 0x20, 0x08, 0x08, 0xa0, 0x82, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x80, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x55, 0x01, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0xa0, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa0, 0xaa, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x55, 0x55, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x2a, 0x2a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xaa, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x45, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0xa2, 0x22, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x88, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x0a, 0x00, 0x0a, 0x08, + 0x02, 0x22, 0xa0, 0x80, 0x08, 0x00, 0xa0, 0x00, 0x20, 0xa0, 0xa0, 0xa0, + 0x41, 0x01, 0x51, 0x45, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, + 0x00, 0x00, 0x55, 0x55, 0x14, 0x00, 0x11, 0x14, 0x05, 0x45, 0x10, 0x41, + 0x11, 0x00, 0x40, 0x01, 0x14, 0x41, 0x40, 0x10, 0x82, 0x28, 0xa2, 0xaa, + 0x80, 0xa2, 0xa2, 0xa0, 0xa8, 0x00, 0x28, 0x28, 0x08, 0xa2, 0x02, 0xaa, + 0xa8, 0x80, 0x20, 0x88, 0x88, 0x0a, 0x08, 0x82, 0x20, 0x00, 0x80, 0x0a, + 0x00, 0x82, 0x00, 0x08, 0x04, 0x51, 0x51, 0x55, 0x45, 0x44, 0x11, 0x11, + 0x11, 0x01, 0x50, 0x44, 0x04, 0x11, 0x05, 0x55, 0x41, 0x41, 0x40, 0x10, + 0x40, 0x55, 0x04, 0x44, 0x40, 0x00, 0x00, 0x14, 0x00, 0x01, 0x01, 0x04, + 0x88, 0xa8, 0xa8, 0x2a, 0x2a, 0x20, 0x08, 0x0a, 0x0a, 0x02, 0xa0, 0x80, + 0x88, 0x08, 0xa2, 0xaa, 0x02, 0x22, 0x00, 0x08, 0xa0, 0x8a, 0x02, 0x88, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x82, 0x20, 0x02, 0x05, 0x55, 0x54, 0x55, + 0x44, 0x40, 0x50, 0x51, 0x11, 0x01, 0x04, 0x51, 0x10, 0x51, 0x41, 0x55, + 0x05, 0x44, 0x00, 0x10, 0x00, 0x50, 0x54, 0x45, 0x40, 0x00, 0x00, 0x40, + 0x50, 0x01, 0x01, 0x54, 0x80, 0x2a, 0xaa, 0x0a, 0x28, 0x28, 0x08, 0x08, + 0x08, 0x02, 0x88, 0x88, 0x80, 0x08, 0xa8, 0xaa, 0x0a, 0x28, 0x00, 0x08, + 0xa0, 0x02, 0x02, 0x80, 0x20, 0x00, 0x00, 0x80, 0x08, 0x02, 0x02, 0x02, + 0x00, 0x15, 0x55, 0x15, 0x44, 0x44, 0x10, 0x11, 0x11, 0x01, 0x04, 0x45, + 0x50, 0x10, 0x51, 0x55, 0x15, 0x44, 0x00, 0x10, 0x00, 0x01, 0x04, 0x40, + 0x40, 0x00, 0x00, 0x40, 0x04, 0x01, 0x11, 0x04, 0x80, 0x0a, 0xaa, 0x2a, + 0x82, 0x22, 0xa0, 0xa0, 0x08, 0x02, 0xa8, 0xa8, 0x20, 0xa0, 0xa8, 0xaa, + 0x0a, 0x28, 0x00, 0x08, 0x80, 0x00, 0x02, 0x80, 0x20, 0x00, 0x00, 0x80, + 0x02, 0x02, 0x0a, 0x02, 0x00, 0x04, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x44, 0x00, 0x10, + 0x10, 0x00, 0x04, 0x40, 0x40, 0x00, 0x00, 0x40, 0x04, 0x01, 0x04, 0x04, + 0x08, 0x02, 0xa8, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xaa, 0x28, 0x82, 0x00, 0x08, 0xa8, 0x80, 0x08, 0x88, + 0x20, 0x00, 0x20, 0x20, 0x02, 0x0a, 0x0a, 0x08, 0x44, 0x00, 0x50, 0x55, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + 0x51, 0x01, 0x11, 0x10, 0x54, 0x41, 0x10, 0x44, 0x40, 0x00, 0x40, 0x10, + 0x04, 0x01, 0x04, 0x10, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0x00, 0x08, 0x00, 0x00, 0x00, 0xaa, 0x08, 0x00, 0x0a, 0x2a, + 0x2a, 0x0a, 0xa0, 0xa0, 0xa0, 0x00, 0x20, 0x0a, 0x28, 0x02, 0x00, 0xa0, + 0x50, 0x01, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/include/closestr.h b/include/closestr.h new file mode 100644 index 000000000..323a971bb --- /dev/null +++ b/include/closestr.h @@ -0,0 +1,138 @@ +/* $Xorg: closestr.h,v 1.4 2001/02/09 02:05:14 xorgcvs Exp $ */ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +#ifndef CLOSESTR_H +#define CLOSESTR_H + +#define NEED_REPLIES +#include "Xproto.h" +#include "closure.h" +#include "dix.h" +#include "misc.h" +#include "gcstruct.h" + +/* closure structures */ + +/* OpenFont */ + +typedef struct _OFclosure { + ClientPtr client; + short current_fpe; + short num_fpes; + FontPathElementPtr *fpe_list; + Mask flags; + Bool slept; + +/* XXX -- get these from request buffer instead? */ + char *origFontName; + int origFontNameLen; + XID fontid; + char *fontname; + int fnamelen; + FontPtr non_cachable_font; +} OFclosureRec; + +/* ListFontsWithInfo */ + +#define XLFDMAXFONTNAMELEN 256 +typedef struct _LFWIstate { + char pattern[XLFDMAXFONTNAMELEN]; + int patlen; + int current_fpe; + int max_names; + Bool list_started; + pointer private; +} LFWIstateRec, *LFWIstatePtr; + +typedef struct _LFWIclosure { + ClientPtr client; + int num_fpes; + FontPathElementPtr *fpe_list; + xListFontsWithInfoReply *reply; + int length; + LFWIstateRec current; + LFWIstateRec saved; + int savedNumFonts; + Bool haveSaved; + Bool slept; + char *savedName; +} LFWIclosureRec; + +/* ListFonts */ + +typedef struct _LFclosure { + ClientPtr client; + int num_fpes; + FontPathElementPtr *fpe_list; + FontNamesPtr names; + LFWIstateRec current; + LFWIstateRec saved; + Bool haveSaved; + Bool slept; + char *savedName; + int savedNameLen; +} LFclosureRec; + +/* PolyText */ + +typedef struct _PTclosure { + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + unsigned char *pElt; + unsigned char *endReq; + unsigned char *data; + int xorg; + int yorg; + CARD8 reqType; + int (* polyText)(); + int itemSize; + XID did; + int err; + Bool slept; +} PTclosureRec; + +/* ImageText */ + +typedef struct _ITclosure { + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + BYTE nChars; + unsigned char *data; + int xorg; + int yorg; + CARD8 reqType; + void (* imageText)(); + int itemSize; + XID did; + Bool slept; +} ITclosureRec; +#endif /* CLOSESTR_H */ diff --git a/include/closure.h b/include/closure.h new file mode 100644 index 000000000..d80388bf4 --- /dev/null +++ b/include/closure.h @@ -0,0 +1,57 @@ +/* $Xorg: closure.h,v 1.4 2001/02/09 02:05:14 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef CLOSURE_H +#define CLOSURE_H 1 + +typedef struct _LFclosure *LFclosurePtr; +typedef struct _LFWIclosure *LFWIclosurePtr; +typedef struct _OFclosure *OFclosurePtr; +typedef struct _PTclosure *PTclosurePtr; +typedef struct _ITclosure *ITclosurePtr; + +#endif /* CLOSURE_H */ diff --git a/include/colormap.h b/include/colormap.h new file mode 100644 index 000000000..e2515a8ed --- /dev/null +++ b/include/colormap.h @@ -0,0 +1,233 @@ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +*/ +/* $Xorg: colormap.h,v 1.4 2001/02/09 02:05:14 xorgcvs Exp $ */ +#ifndef CMAP_H +#define CMAP_H 1 + +#include "X11/Xproto.h" +#include "screenint.h" +#include "window.h" + +/* these follow X.h's AllocNone and AllocAll */ +#define CM_PSCREEN 2 +#define CM_PWIN 3 +/* Passed internally in colormap.c */ +#define REDMAP 0 +#define GREENMAP 1 +#define BLUEMAP 2 +#define PSEUDOMAP 3 +#define AllocPrivate (-1) +#define AllocTemporary (-2) +#define DynamicClass 1 + +/* Values for the flags field of a colormap. These should have 1 bit set + * and not overlap */ +#define IsDefault 1 +#define AllAllocated 2 +#define BeingCreated 4 + + +typedef CARD32 Pixel; +typedef struct _CMEntry *EntryPtr; +typedef struct _ColormapRec *ColormapPtr; +typedef struct _colorResource *colorResourcePtr; + +extern int CreateColormap( +#if NeedFunctionPrototypes + Colormap /*mid*/, + ScreenPtr /*pScreen*/, + VisualPtr /*pVisual*/, + ColormapPtr* /*ppcmap*/, + int /*alloc*/, + int /*client*/ +#endif +); + +extern int FreeColormap( +#if NeedFunctionPrototypes + pointer /*pmap*/, + XID /*mid*/ +#endif +); + +extern int TellLostMap( +#if NeedFunctionPrototypes + WindowPtr /*pwin*/, + pointer /* Colormap *pmid */ +#endif +); + +extern int TellGainedMap( +#if NeedFunctionPrototypes + WindowPtr /*pwin*/, + pointer /* Colormap *pmid */ +#endif +); + +extern int CopyColormapAndFree( +#if NeedFunctionPrototypes + Colormap /*mid*/, + ColormapPtr /*pSrc*/, + int /*client*/ +#endif +); + +extern int AllocColor( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + unsigned short* /*pred*/, + unsigned short* /*pgreen*/, + unsigned short* /*pblue*/, + Pixel* /*pPix*/, + int /*client*/ +#endif +); + +extern void FakeAllocColor( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + xColorItem * /*item*/ +#endif +); + +extern void FakeFreeColor( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + Pixel /*pixel*/ +#endif +); + +typedef int (*ColorCompareProcPtr)( +#if NeedNestedPrototypes + EntryPtr /*pent*/, + xrgb * /*prgb*/ +#endif +); + +extern int FindColor( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + EntryPtr /*pentFirst*/, + int /*size*/, + xrgb* /*prgb*/, + Pixel* /*pPixel*/, + int /*channel*/, + int /*client*/, + ColorCompareProcPtr /*comp*/ +#endif +); + +extern int QueryColors( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + int /*count*/, + Pixel* /*ppixIn*/, + xrgb* /*prgbList*/ +#endif +); + +extern int FreeClientPixels( +#if NeedFunctionPrototypes + pointer /*pcr*/, + XID /*fakeid*/ +#endif +); + +extern int AllocColorCells( +#if NeedFunctionPrototypes + int /*client*/, + ColormapPtr /*pmap*/, + int /*colors*/, + int /*planes*/, + Bool /*contig*/, + Pixel* /*ppix*/, + Pixel* /*masks*/ +#endif +); + +extern int AllocColorPlanes( +#if NeedFunctionPrototypes + int /*client*/, + ColormapPtr /*pmap*/, + int /*colors*/, + int /*r*/, + int /*g*/, + int /*b*/, + Bool /*contig*/, + Pixel* /*pixels*/, + Pixel* /*prmask*/, + Pixel* /*pgmask*/, + Pixel* /*pbmask*/ +#endif +); + +extern int FreeColors( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + int /*client*/, + int /*count*/, + Pixel* /*pixels*/, + Pixel /*mask*/ +#endif +); + +extern int StoreColors( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/, + int /*count*/, + xColorItem* /*defs*/ +#endif +); + +extern int IsMapInstalled( +#if NeedFunctionPrototypes + Colormap /*map*/, + WindowPtr /*pWin*/ +#endif +); + +#endif /* CMAP_H */ diff --git a/include/colormapst.h b/include/colormapst.h new file mode 100644 index 000000000..b176f7dc3 --- /dev/null +++ b/include/colormapst.h @@ -0,0 +1,120 @@ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +*/ +/* $Xorg: colormapst.h,v 1.4 2001/02/09 02:05:14 xorgcvs Exp $ */ +#ifndef CMAPSTRUCT_H +#define CMAPSTRUCT_H 1 + +#include "colormap.h" +#include "screenint.h" + +/* Shared color -- the color is used by AllocColorPlanes */ +typedef struct +{ + unsigned short color; + short refcnt; +} SHAREDCOLOR; + +/* LOCO -- a local color for a PseudoColor cell. DirectColor maps always + * use the first value (called red) in the structure. What channel they + * are really talking about depends on which map they are in. */ +typedef struct +{ + unsigned short red, green, blue; +} LOCO; + +/* SHCO -- a shared color for a PseudoColor cell. Used with AllocColorPlanes. + * DirectColor maps always use the first value (called red) in the structure. + * What channel they are really talking about depends on which map they + * are in. */ +typedef struct +{ + SHAREDCOLOR *red, *green, *blue; +} SHCO; + + +/* color map entry */ +typedef struct _CMEntry +{ + union + { + LOCO local; + SHCO shco; + } co; + short refcnt; + Bool fShared; +} Entry; + +/* COLORMAPs can be used for either Direct or Pseudo color. PseudoColor + * only needs one cell table, we arbitrarily pick red. We keep track + * of that table with freeRed, numPixelsRed, and clientPixelsRed */ + +typedef struct _ColormapRec +{ + VisualPtr pVisual; + short class; /* PseudoColor or DirectColor */ + long mid; /* client's name for colormap */ + ScreenPtr pScreen; /* screen map is associated with */ + short flags; /* 1 = IsDefault + * 2 = AllAllocated */ + int freeRed; + int freeGreen; + int freeBlue; + int *numPixelsRed; + int *numPixelsGreen; + int *numPixelsBlue; + Pixel **clientPixelsRed; + Pixel **clientPixelsGreen; + Pixel **clientPixelsBlue; + Entry *red; + Entry *green; + Entry *blue; + pointer devPriv; + DevUnion *devPrivates; /* dynamic devPrivates added after devPriv + already existed - must keep devPriv */ +} ColormapRec; + +#endif /* COLORMAP_H */ diff --git a/include/cursor.h b/include/cursor.h new file mode 100644 index 000000000..24200837c --- /dev/null +++ b/include/cursor.h @@ -0,0 +1,151 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: cursor.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +#ifndef CURSOR_H +#define CURSOR_H + +#include "misc.h" +#include "screenint.h" +#include "window.h" + +#define NullCursor ((CursorPtr)NULL) + +typedef struct _Cursor *CursorPtr; +typedef struct _CursorMetric *CursorMetricPtr; + +extern CursorPtr rootCursor; + +extern int FreeCursor( +#if NeedFunctionPrototypes + pointer /*pCurs*/, + XID /*cid*/ +#endif +); + +extern CursorPtr AllocCursor( +#if NeedFunctionPrototypes + unsigned char* /*psrcbits*/, + unsigned char* /*pmaskbits*/, + CursorMetricPtr /*cm*/, + unsigned /*foreRed*/, + unsigned /*foreGreen*/, + unsigned /*foreBlue*/, + unsigned /*backRed*/, + unsigned /*backGreen*/, + unsigned /*backBlue*/ +#endif +); + +extern int AllocGlyphCursor( +#if NeedFunctionPrototypes + Font /*source*/, + unsigned int /*sourceChar*/, + Font /*mask*/, + unsigned int /*maskChar*/, + unsigned /*foreRed*/, + unsigned /*foreGreen*/, + unsigned /*foreBlue*/, + unsigned /*backRed*/, + unsigned /*backGreen*/, + unsigned /*backBlue*/, + CursorPtr* /*ppCurs*/, + ClientPtr /*client*/ +#endif +); + +extern CursorPtr CreateRootCursor( +#if NeedFunctionPrototypes + char* /*pfilename*/, + unsigned int /*glyph*/ +#endif +); + +extern int ServerBitsFromGlyph( +#if NeedFunctionPrototypes + FontPtr /*pfont*/, + unsigned int /*ch*/, + register CursorMetricPtr /*cm*/, + unsigned char ** /*ppbits*/ +#endif +); + +extern Bool CursorMetricsFromGlyph( +#if NeedFunctionPrototypes + FontPtr /*pfont*/, + unsigned /*ch*/, + CursorMetricPtr /*cm*/ +#endif +); + +extern void CheckCursorConfinement( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void NewCurrentScreen( +#if NeedFunctionPrototypes + ScreenPtr /*newScreen*/, + int /*x*/, + int /*y*/ +#endif +); + +extern Bool PointerConfinedToScreen( +#if NeedFunctionPrototypes + void +#endif +); + +extern void GetSpritePosition( +#if NeedFunctionPrototypes + int * /*px*/, + int * /*py*/ +#endif +); + +#endif /* CURSOR_H */ diff --git a/include/cursorstr.h b/include/cursorstr.h new file mode 100644 index 000000000..4d9efffda --- /dev/null +++ b/include/cursorstr.h @@ -0,0 +1,80 @@ +/* $Xorg: cursorstr.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef CURSORSTRUCT_H +#define CURSORSTRUCT_H + +#include "cursor.h" +/* + * device-independent cursor storage + */ + +/* + * source and mask point directly to the bits, which are in the server-defined + * bitmap format. + */ +typedef struct _CursorBits { + unsigned char *source; /* points to bits */ + unsigned char *mask; /* points to bits */ + unsigned short width, height, xhot, yhot; /* metrics */ + int refcnt; /* can be shared */ + pointer devPriv[MAXSCREENS]; /* set by pScr->RealizeCursor*/ +} CursorBits, *CursorBitsPtr; + +typedef struct _Cursor { + CursorBitsPtr bits; + unsigned short foreRed, foreGreen, foreBlue; /* device-independent color */ + unsigned short backRed, backGreen, backBlue; /* device-independent color */ + int refcnt; + pointer devPriv[MAXSCREENS]; /* set by pScr->RealizeCursor*/ +} CursorRec; + +typedef struct _CursorMetric { + unsigned short width, height, xhot, yhot; +} CursorMetricRec; + +#endif /* CURSORSTRUCT_H */ diff --git a/include/dix.h b/include/dix.h new file mode 100644 index 000000000..b53deb374 --- /dev/null +++ b/include/dix.h @@ -0,0 +1,1090 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: dix.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ + +#ifndef DIX_H +#define DIX_H + +#include "gc.h" +#include "window.h" +#include "input.h" + +#define EARLIER -1 +#define SAMETIME 0 +#define LATER 1 + +#define NullClient ((ClientPtr) 0) +#define REQUEST(type) \ + register type *stuff = (type *)client->requestBuffer + + +#define REQUEST_SIZE_MATCH(req)\ + if ((sizeof(req) >> 2) != client->req_len)\ + return(BadLength) + +#define REQUEST_AT_LEAST_SIZE(req) \ + if ((sizeof(req) >> 2) > client->req_len )\ + return(BadLength) + +#define REQUEST_FIXED_SIZE(req, n)\ + if (((sizeof(req) >> 2) > client->req_len) || \ + (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \ + return(BadLength) + +#define LEGAL_NEW_RESOURCE(id,client)\ + if (!LegalNewID(id,client)) \ + {\ + client->errorValue = id;\ + return(BadIDChoice);\ + } + +/* XXX if you are using this macro, you are probably not generating Match + * errors where appropriate */ +#define LOOKUP_DRAWABLE(did, client)\ + ((client->lastDrawableID == did) ? \ + client->lastDrawable : (DrawablePtr)LookupDrawable(did, client)) + +#ifdef XCSECURITY + +#define SECURITY_VERIFY_DRAWABLE(pDraw, did, client, mode)\ + if (client->lastDrawableID == did && !client->trustLevel)\ + pDraw = client->lastDrawable;\ + else \ + {\ + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, did, \ + RC_DRAWABLE, mode);\ + if (!pDraw) \ + {\ + client->errorValue = did; \ + return BadDrawable;\ + }\ + if (pDraw->type == UNDRAWABLE_WINDOW)\ + return BadMatch;\ + } + +#define SECURITY_VERIFY_GEOMETRABLE(pDraw, did, client, mode)\ + if (client->lastDrawableID == did && !client->trustLevel)\ + pDraw = client->lastDrawable;\ + else \ + {\ + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, did, \ + RC_DRAWABLE, mode);\ + if (!pDraw) \ + {\ + client->errorValue = did; \ + return BadDrawable;\ + }\ + } + +#define SECURITY_VERIFY_GC(pGC, rid, client, mode)\ + if (client->lastGCID == rid && !client->trustLevel)\ + pGC = client->lastGC;\ + else\ + pGC = (GC *) SecurityLookupIDByType(client, rid, RT_GC, mode);\ + if (!pGC)\ + {\ + client->errorValue = rid;\ + return (BadGC);\ + } + +#define VERIFY_DRAWABLE(pDraw, did, client)\ + SECURITY_VERIFY_DRAWABLE(pDraw, did, client, SecurityUnknownAccess) + +#define VERIFY_GEOMETRABLE(pDraw, did, client)\ + SECURITY_VERIFY_GEOMETRABLE(pDraw, did, client, SecurityUnknownAccess) + +#define VERIFY_GC(pGC, rid, client)\ + SECURITY_VERIFY_GC(pGC, rid, client, SecurityUnknownAccess) + +#else /* not XCSECURITY */ + +#define VERIFY_DRAWABLE(pDraw, did, client)\ + if (client->lastDrawableID == did)\ + pDraw = client->lastDrawable;\ + else \ + {\ + pDraw = (DrawablePtr) LookupIDByClass(did, RC_DRAWABLE);\ + if (!pDraw) \ + {\ + client->errorValue = did; \ + return BadDrawable;\ + }\ + if (pDraw->type == UNDRAWABLE_WINDOW)\ + return BadMatch;\ + } + +#define VERIFY_GEOMETRABLE(pDraw, did, client)\ + if (client->lastDrawableID == did)\ + pDraw = client->lastDrawable;\ + else \ + {\ + pDraw = (DrawablePtr) LookupIDByClass(did, RC_DRAWABLE);\ + if (!pDraw) \ + {\ + client->errorValue = did; \ + return BadDrawable;\ + }\ + } + +#define VERIFY_GC(pGC, rid, client)\ + if (client->lastGCID == rid)\ + pGC = client->lastGC;\ + else\ + pGC = (GC *)LookupIDByType(rid, RT_GC);\ + if (!pGC)\ + {\ + client->errorValue = rid;\ + return (BadGC);\ + } + +#define SECURITY_VERIFY_DRAWABLE(pDraw, did, client, mode)\ + VERIFY_DRAWABLE(pDraw, did, client) + +#define SECURITY_VERIFY_GEOMETRABLE(pDraw, did, client, mode)\ + VERIFY_GEOMETRABLE(pDraw, did, client) + +#define SECURITY_VERIFY_GC(pGC, rid, client, mode)\ + VERIFY_GC(pGC, rid, client) + +#endif /* XCSECURITY */ + +/* + * We think that most hardware implementations of DBE will want + * LookupID*(dbe_back_buffer_id) to return the window structure that the + * id is a back buffer for. Since both front and back buffers will + * return the same structure, you need to be able to distinguish + * somewhere what kind of buffer (front/back) was being asked for, so + * that ddx can render to the right place. That's the problem that the + * following code solves. Note: we couldn't embed this in the LookupID* + * functions because the VALIDATE_DRAWABLE_AND_GC macro often circumvents + * those functions by checking a one-element cache. That's why we're + * mucking with VALIDATE_DRAWABLE_AND_GC. + * + * If you put -DNEED_DBE_BUF_BITS into PervasiveDBEDefines, the window + * structure will have two additional bits defined, srcBuffer and + * dstBuffer, and their values will be maintained via the macros + * SET_DBE_DSTBUF and SET_DBE_SRCBUF (below). If you also + * put -DNEED_DBE_BUF_VALIDATE into PervasiveDBEDefines, the function + * DbeValidateBuffer will be called any time the bits change to give you + * a chance to do some setup. See the DBE code for more details on this + * function. We put in these levels of conditionality so that you can do + * just what you need to do, and no more. If neither of these defines + * are used, the bits won't be there, and VALIDATE_DRAWABLE_AND_GC will + * be unchanged. dpw + */ + +#if defined(NEED_DBE_BUF_BITS) +#define SET_DBE_DSTBUF(_pDraw, _drawID) \ + SET_DBE_BUF(_pDraw, _drawID, dstBuffer, TRUE) +#define SET_DBE_SRCBUF(_pDraw, _drawID) \ + SET_DBE_BUF(_pDraw, _drawID, srcBuffer, FALSE) +#if defined (NEED_DBE_BUF_VALIDATE) +#define SET_DBE_BUF(_pDraw, _drawID, _whichBuffer, _dstbuf) \ + if (_pDraw->type == DRAWABLE_WINDOW)\ + {\ + int thisbuf = (_pDraw->id == _drawID);\ + if (thisbuf != ((WindowPtr)_pDraw)->_whichBuffer)\ + {\ + ((WindowPtr)_pDraw)->_whichBuffer = thisbuf;\ + DbeValidateBuffer((WindowPtr)_pDraw, _drawID, _dstbuf);\ + }\ + } +#else /* want buffer bits, but don't need to call DbeValidateBuffer */ +#define SET_DBE_BUF(_pDraw, _drawID, _whichBuffer, _dstbuf) \ + if (_pDraw->type == DRAWABLE_WINDOW)\ + {\ + ((WindowPtr)_pDraw)->_whichBuffer = (_pDraw->id == _drawID);\ + } +#endif /* NEED_DBE_BUF_VALIDATE */ +#else /* don't want buffer bits in window */ +#define SET_DBE_DSTBUF(_pDraw, _drawID) /**/ +#define SET_DBE_SRCBUF(_pDraw, _drawID) /**/ +#endif /* NEED_DBE_BUF_BITS */ + +#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, pGC, client)\ + if ((stuff->gc == INVALID) || (client->lastGCID != stuff->gc) ||\ + (client->lastDrawableID != drawID))\ + {\ + SECURITY_VERIFY_GEOMETRABLE(pDraw, drawID, client, SecurityWriteAccess);\ + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityReadAccess);\ + if ((pGC->depth != pDraw->depth) ||\ + (pGC->pScreen != pDraw->pScreen))\ + return (BadMatch);\ + client->lastDrawable = pDraw;\ + client->lastDrawableID = drawID;\ + client->lastGC = pGC;\ + client->lastGCID = stuff->gc;\ + }\ + else\ + {\ + pGC = client->lastGC;\ + pDraw = client->lastDrawable;\ + }\ + SET_DBE_DSTBUF(pDraw, drawID);\ + if (pGC->serialNumber != pDraw->serialNumber)\ + ValidateGC(pDraw, pGC); + + +#define WriteReplyToClient(pClient, size, pReply) \ + if ((pClient)->swapped) \ + (*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \ + (pClient, (int)(size), pReply); \ + else (void) WriteToClient(pClient, (int)(size), (char *)(pReply)); + +#define WriteSwappedDataToClient(pClient, size, pbuf) \ + if ((pClient)->swapped) \ + (*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \ + else (void) WriteToClient (pClient, (int)(size), (char *)(pbuf)); + +typedef struct _TimeStamp *TimeStampPtr; + +#ifndef _XTYPEDEF_CLIENTPTR +typedef struct _Client *ClientPtr; /* also in misc.h */ +#define _XTYPEDEF_CLIENTPTR +#endif + +typedef struct _WorkQueue *WorkQueuePtr; + + +extern ClientPtr requestingClient; +extern ClientPtr *clients; +extern ClientPtr serverClient; +extern int currentMaxClients; + +#ifndef __alpha +typedef long HWEventQueueType; +#else +typedef int HWEventQueueType; +#endif +typedef HWEventQueueType* HWEventQueuePtr; + +extern HWEventQueuePtr checkForInput[2]; + +typedef struct _TimeStamp { + CARD32 months; /* really ~49.7 days */ + CARD32 milliseconds; +} TimeStamp; + +/* dispatch.c */ + +extern void SetInputCheck( +#if NeedFunctionPrototypes + HWEventQueuePtr /*c0*/, + HWEventQueuePtr /*c1*/ +#endif +); + +extern void CloseDownClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void UpdateCurrentTime( +#if NeedFunctionPrototypes + void +#endif +); + +extern void UpdateCurrentTimeIf( +#if NeedFunctionPrototypes + void +#endif +); + +extern void InitSelections( +#if NeedFunctionPrototypes + void +#endif +); + +extern void FlushClientCaches( +#if NeedFunctionPrototypes + XID /*id*/ +#endif +); + +extern int dixDestroyPixmap( +#if NeedFunctionPrototypes + pointer /*value*/, + XID /*pid*/ +#endif +); + +extern void CloseDownRetainedResources( +#if NeedFunctionPrototypes + void +#endif +); + +extern void InitClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + int /*i*/, + pointer /*ospriv*/ +#endif +); + +extern ClientPtr NextAvailableClient( +#if NeedFunctionPrototypes + pointer /*ospriv*/ +#endif +); + +extern void SendErrorToClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + unsigned int /*majorCode*/, + unsigned int /*minorCode*/, + XID /*resId*/, + int /*errorCode*/ +#endif +); + +extern void DeleteWindowFromAnySelections( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void MarkClientException( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern int GetGeometry( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + xGetGeometryReply* /* wa */ +#endif +); + +/* dixutils.c */ + +extern void CopyISOLatin1Lowered( +#if NeedFunctionPrototypes + unsigned char * /*dest*/, + unsigned char * /*source*/, + int /*length*/ +#endif +); + +#ifdef XCSECURITY + +extern WindowPtr SecurityLookupWindow( +#if NeedFunctionPrototypes + XID /*rid*/, + ClientPtr /*client*/, + Mask /*access_mode*/ +#endif +); + +extern pointer SecurityLookupDrawable( +#if NeedFunctionPrototypes + XID /*rid*/, + ClientPtr /*client*/, + Mask /*access_mode*/ +#endif +); + +extern WindowPtr LookupWindow( +#if NeedFunctionPrototypes + XID /*rid*/, + ClientPtr /*client*/ +#endif +); + +extern pointer LookupDrawable( +#if NeedFunctionPrototypes + XID /*rid*/, + ClientPtr /*client*/ +#endif +); + +#else + +extern WindowPtr LookupWindow( +#if NeedFunctionPrototypes + XID /*rid*/, + ClientPtr /*client*/ +#endif +); + +extern pointer LookupDrawable( +#if NeedFunctionPrototypes + XID /*rid*/, + ClientPtr /*client*/ +#endif +); + +#define SecurityLookupWindow(rid, client, access_mode) \ + LookupWindow(rid, client) + +#define SecurityLookupDrawable(rid, client, access_mode) \ + LookupDrawable(rid, client) + +#endif /* XCSECURITY */ + +extern ClientPtr LookupClient( +#if NeedFunctionPrototypes + XID /*rid*/, + ClientPtr /*client*/ +#endif +); + +extern void NoopDDA( +#if NeedVarargsPrototypes + void *, + ... +#endif +); + +extern int AlterSaveSetForClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + WindowPtr /*pWin*/, + unsigned /*mode*/ +#endif +); + +extern void DeleteWindowFromAnySaveSet( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void BlockHandler( +#if NeedFunctionPrototypes + pointer /*pTimeout*/, + pointer /*pReadmask*/ +#endif +); + +extern void WakeupHandler( +#if NeedFunctionPrototypes + int /*result*/, + pointer /*pReadmask*/ +#endif +); + +typedef struct timeval ** OSTimePtr; + +typedef void (* BlockHandlerProcPtr)( +#if NeedNestedPrototypes + pointer /* blockData */, + OSTimePtr /* pTimeout */, + pointer /* pReadmask */ +#endif +); + +typedef void (* WakeupHandlerProcPtr)( +#if NeedNestedPrototypes + pointer /* blockData */, + int /* result */, + pointer /* pReadmask */ +#endif +); + +extern Bool RegisterBlockAndWakeupHandlers( +#if NeedFunctionPrototypes + BlockHandlerProcPtr /*blockHandler*/, + WakeupHandlerProcPtr /*wakeupHandler*/, + pointer /*blockData*/ +#endif +); + +extern void RemoveBlockAndWakeupHandlers( +#if NeedFunctionPrototypes + BlockHandlerProcPtr /*blockHandler*/, + WakeupHandlerProcPtr /*wakeupHandler*/, + pointer /*blockData*/ +#endif +); + +extern void InitBlockAndWakeupHandlers( +#if NeedFunctionPrototypes + void +#endif +); + +extern void ProcessWorkQueue( +#if NeedFunctionPrototypes + void +#endif +); + +extern Bool QueueWorkProc( +#if NeedFunctionPrototypes + Bool (* /*function*/)(), + ClientPtr /*client*/, + pointer /*closure*/ +#endif +); + +extern Bool ClientSleep( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + Bool (* /*function*/)(), + pointer /*closure*/ +#endif +); + +extern Bool ClientSignal( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void ClientWakeup( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern Bool ClientIsAsleep( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +/* atom.c */ + +extern Atom MakeAtom( +#if NeedFunctionPrototypes + char * /*string*/, + unsigned /*len*/, + Bool /*makeit*/ +#endif +); + +extern Bool ValidAtom( +#if NeedFunctionPrototypes + Atom /*atom*/ +#endif +); + +extern char *NameForAtom( +#if NeedFunctionPrototypes + Atom /*atom*/ +#endif +); + +extern void AtomError( +#if NeedFunctionPrototypes + void +#endif +); + +extern void FreeAllAtoms( +#if NeedFunctionPrototypes + void +#endif +); + +extern void InitAtoms( +#if NeedFunctionPrototypes + void +#endif +); + +/* events.c */ + +extern void SetMaskForEvent( +#if NeedFunctionPrototypes + Mask /* mask */, + int /* event */ +#endif +); + +extern Bool PointerConfinedToScreen( +#if NeedFunctionPrototypes + void +#endif +); + +extern Bool IsParent( +#if NeedFunctionPrototypes + WindowPtr /* maybeparent */, + WindowPtr /* child */ +#endif +); + +extern WindowPtr GetCurrentRootWindow( +#if NeedFunctionPrototypes + void +#endif +); + +extern WindowPtr GetSpriteWindow( +#if NeedFunctionPrototypes + void +#endif +); + +extern void GetSpritePosition( +#if NeedFunctionPrototypes + int * /* px */, + int * /* py */ +#endif +); + +extern void NoticeEventTime( +#if NeedFunctionPrototypes + xEventPtr /* xE */ +#endif +); + +extern void EnqueueEvent( +#if NeedFunctionPrototypes + xEventPtr /* xE */, + DeviceIntPtr /* device */, + int /* count */ +#endif +); + +extern void ComputeFreezes( +#if NeedFunctionPrototypes + void +#endif +); + +extern void CheckGrabForSyncs( +#if NeedFunctionPrototypes + DeviceIntPtr /* dev */, + Bool /* thisMode */, + Bool /* otherMode */ +#endif +); + +extern void ActivatePointerGrab( +#if NeedFunctionPrototypes + DeviceIntPtr /* mouse */, + GrabPtr /* grab */, + TimeStamp /* time */, + Bool /* autoGrab */ +#endif +); + +extern void DeactivatePointerGrab( +#if NeedFunctionPrototypes + DeviceIntPtr /* mouse */ +#endif +); + +extern void ActivateKeyboardGrab( +#if NeedFunctionPrototypes + DeviceIntPtr /* keybd */, + GrabPtr /* grab */, + TimeStamp /* time */, + Bool /* passive */ +#endif +); + +extern void DeactivateKeyboardGrab( +#if NeedFunctionPrototypes + DeviceIntPtr /* keybd */ +#endif +); + +extern void AllowSome( +#if NeedFunctionPrototypes + ClientPtr /* client */, + TimeStamp /* time */, + DeviceIntPtr /* thisDev */, + int /* newState */ +#endif +); + +extern void ReleaseActiveGrabs( +#if NeedFunctionPrototypes +ClientPtr client +#endif +); + +extern int DeliverEventsToWindow( +#if NeedFunctionPrototypes + WindowPtr /* pWin */, + xEventPtr /* pEvents */, + int /* count */, + Mask /* filter */, + GrabPtr /* grab */, + int /* mskidx */ +#endif +); + +extern int DeliverDeviceEvents( +#if NeedFunctionPrototypes + WindowPtr /* pWin */, + xEventPtr /* xE */, + GrabPtr /* grab */, + WindowPtr /* stopAt */, + DeviceIntPtr /* dev */, + int /* count */ +#endif +); + +extern void DefineInitialRootWindow( +#if NeedFunctionPrototypes + WindowPtr /* win */ +#endif +); + +extern void WindowHasNewCursor( +#if NeedFunctionPrototypes + WindowPtr /* pWin */ +#endif +); + +extern Bool CheckDeviceGrabs( +#if NeedFunctionPrototypes + DeviceIntPtr /* device */, + xEventPtr /* xE */, + int /* checkFirst */, + int /* count */ +#endif +); + +extern void DeliverFocusedEvent( +#if NeedFunctionPrototypes + DeviceIntPtr /* keybd */, + xEventPtr /* xE */, + WindowPtr /* window */, + int /* count */ +#endif +); + +extern void DeliverGrabbedEvent( +#if NeedFunctionPrototypes + xEventPtr /* xE */, + DeviceIntPtr /* thisDev */, + Bool /* deactivateGrab */, + int /* count */ +#endif +); + +extern void RecalculateDeliverableEvents( +#if NeedFunctionPrototypes + WindowPtr /* pWin */ +#endif +); + +extern int OtherClientGone( +#if NeedFunctionPrototypes + pointer /* value */, + XID /* id */ +#endif +); + +extern void DoFocusEvents( +#if NeedFunctionPrototypes + DeviceIntPtr /* dev */, + WindowPtr /* fromWin */, + WindowPtr /* toWin */, + int /* mode */ +#endif +); + +extern int SetInputFocus( +#if NeedFunctionPrototypes + ClientPtr /* client */, + DeviceIntPtr /* dev */, + Window /* focusID */, + int /* revertTo */, + Time /* ctime */, + Bool /* followOK */ +#endif +); + +extern int GrabDevice( +#if NeedFunctionPrototypes + ClientPtr /* client */, + DeviceIntPtr /* dev */, + unsigned /* this_mode */, + unsigned /* other_mode */, + Window /* grabWindow */, + unsigned /* ownerEvents */, + Time /* ctime */, + Mask /* mask */, + CARD8 * /* status */ +#endif +); + +extern void InitEvents( +#if NeedFunctionPrototypes + void +#endif +); + +extern void DeleteWindowFromAnyEvents( +#if NeedFunctionPrototypes + WindowPtr /* pWin */, + Bool /* freeResources */ +#endif +); + +extern void CheckCursorConfinement( +#if NeedFunctionPrototypes + WindowPtr /* pWin */ +#endif +); + +extern Mask EventMaskForClient( +#if NeedFunctionPrototypes + WindowPtr /* pWin */, + ClientPtr /* client */ +#endif +); + + + +extern int DeliverEvents( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + xEventPtr /*xE*/, + int /*count*/, + WindowPtr /*otherParent*/ +#endif +); + +extern void WriteEventsToClient( +#if NeedFunctionPrototypes + ClientPtr /*pClient*/, + int /*count*/, + xEventPtr /*events*/ +#endif +); + +extern int TryClientEvents( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + xEventPtr /*pEvents*/, + int /*count*/, + Mask /*mask*/, + Mask /*filter*/, + GrabPtr /*grab*/ +#endif +); + +extern int EventSelectForWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + ClientPtr /*client*/, + Mask /*mask*/ +#endif +); + +extern int EventSuppressForWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + ClientPtr /*client*/, + Mask /*mask*/, + Bool * /*checkOptional*/ +#endif +); + +extern int MaybeDeliverEventsToClient( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + xEventPtr /*pEvents*/, + int /*count*/, + Mask /*filter*/, + ClientPtr /*dontClient*/ +#endif +); + +extern void WindowsRestructured( +#if NeedFunctionPrototypes + void +#endif +); + +extern void ResetClientPrivates( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AllocateClientPrivateIndex( +#if NeedFunctionPrototypes + void +#endif +); + +extern Bool AllocateClientPrivate( +#if NeedFunctionPrototypes + int /*index*/, + unsigned /*amount*/ +#endif +); + +/* + * callback manager stuff + */ + +#ifndef _XTYPEDEF_CALLBACKLISTPTR +typedef struct _CallbackList *CallbackListPtr; /* also in misc.h */ +#define _XTYPEDEF_CALLBACKLISTPTR +#endif + +typedef void (*CallbackProcPtr) ( +#if NeedNestedPrototypes + CallbackListPtr *, pointer, pointer +#endif +); + +typedef Bool (*AddCallbackProcPtr) ( +#if NeedNestedPrototypes + CallbackListPtr *, CallbackProcPtr, pointer +#endif +); + +typedef Bool (*DeleteCallbackProcPtr) ( +#if NeedNestedPrototypes + CallbackListPtr *, CallbackProcPtr, pointer +#endif +); + +typedef void (*CallCallbacksProcPtr) ( +#if NeedNestedPrototypes + CallbackListPtr *, pointer +#endif +); + +typedef void (*DeleteCallbackListProcPtr) ( +#if NeedNestedPrototypes + CallbackListPtr * +#endif +); + +typedef struct _CallbackProcs { + AddCallbackProcPtr AddCallback; + DeleteCallbackProcPtr DeleteCallback; + CallCallbacksProcPtr CallCallbacks; + DeleteCallbackListProcPtr DeleteCallbackList; +} CallbackFuncsRec, *CallbackFuncsPtr; + +extern Bool CreateCallbackList( +#if NeedFunctionPrototypes + CallbackListPtr * /*pcbl*/, + CallbackFuncsPtr /*cbfuncs*/ +#endif +); + +extern Bool AddCallback( +#if NeedFunctionPrototypes + CallbackListPtr * /*pcbl*/, + CallbackProcPtr /*callback*/, + pointer /*data*/ +#endif +); + +extern Bool DeleteCallback( +#if NeedFunctionPrototypes + CallbackListPtr * /*pcbl*/, + CallbackProcPtr /*callback*/, + pointer /*data*/ +#endif +); + +extern void CallCallbacks( +#if NeedFunctionPrototypes + CallbackListPtr * /*pcbl*/, + pointer /*call_data*/ +#endif +); + +extern void DeleteCallbackList( +#if NeedFunctionPrototypes + CallbackListPtr * /*pcbl*/ +#endif +); + +extern void InitCallbackManager( +#if NeedFunctionPrototypes + void +#endif +); + +/* + * ServerGrabCallback stuff + */ + +extern CallbackListPtr ServerGrabCallback; + +typedef enum {SERVER_GRABBED, SERVER_UNGRABBED, + CLIENT_PERVIOUS, CLIENT_IMPERVIOUS } ServerGrabState; + +typedef struct { + ClientPtr client; + ServerGrabState grabstate; +} ServerGrabInfoRec; + +/* + * EventCallback stuff + */ + +extern CallbackListPtr EventCallback; + +typedef struct { + ClientPtr client; + xEventPtr events; + int count; +} EventInfoRec; + +/* + * DeviceEventCallback stuff + */ + +extern CallbackListPtr DeviceEventCallback; + +typedef struct { + xEventPtr events; + int count; +} DeviceEventInfoRec; + +#endif /* DIX_H */ diff --git a/include/dixfont.h b/include/dixfont.h new file mode 100644 index 000000000..b35e252bf --- /dev/null +++ b/include/dixfont.h @@ -0,0 +1,331 @@ +/* $Xorg: dixfont.h,v 1.3 2000/08/17 19:53:29 cpqbld Exp $ */ +/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#ifndef DIXFONT_H +#define DIXFONT_H 1 + +#include +#include +#include + +#define NullDIXFontProp ((DIXFontPropPtr)0) + +typedef struct _DIXFontProp *DIXFontPropPtr; + +extern int FontToXError( +#if NeedFunctionPrototypes + int /*err*/ +#endif +); + +extern Bool SetDefaultFont( +#if NeedFunctionPrototypes + char * /*defaultfontname*/ +#endif +); + +extern void QueueFontWakeup( +#if NeedFunctionPrototypes + FontPathElementPtr /*fpe*/ +#endif +); + +extern void RemoveFontWakeup( +#if NeedFunctionPrototypes + FontPathElementPtr /*fpe*/ +#endif +); + +extern void FontWakeup( +#if NeedFunctionPrototypes + pointer /*data*/, + int /*count*/, + pointer /*LastSelectMask*/ +#endif +); + +extern int OpenFont( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + XID /*fid*/, + Mask /*flags*/, + unsigned /*lenfname*/, + char * /*pfontname*/ +#endif +); + +extern int CloseFont( +#if NeedFunctionPrototypes + pointer /*pfont*/, + XID /*fid*/ +#endif +); + +typedef struct _xQueryFontReply *xQueryFontReplyPtr; + +extern void QueryFont( +#if NeedFunctionPrototypes + FontPtr /*pFont*/, + xQueryFontReplyPtr /*pReply*/, + int /*nProtoCCIStructs*/ +#endif +); + +extern int ListFonts( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + unsigned char * /*pattern*/, + unsigned int /*length*/, + unsigned int /*max_names*/ +#endif +); + +extern int doPolyText( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + PTclosurePtr /*c*/ +#endif +); + +extern int PolyText( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + unsigned char * /*pElt*/, + unsigned char * /*endReq*/, + int /*xorg*/, + int /*yorg*/, + int /*reqType*/, + XID /*did*/ +#endif +); + +extern int doImageText( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + ITclosurePtr /*c*/ +#endif +); + +extern int ImageText( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*nChars*/, + unsigned char * /*data*/, + int /*xorg*/, + int /*yorg*/, + int /*reqType*/, + XID /*did*/ +#endif +); + +extern int SetFontPath( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + int /*npaths*/, + unsigned char * /*paths*/, + int * /*error*/ +#endif +); + +extern int SetDefaultFontPath( +#if NeedFunctionPrototypes + char * /*path*/ +#endif +); + +extern unsigned char *GetFontPath( +#if NeedFunctionPrototypes + int * /*count*/, + int * /*length*/ +#endif +); + +extern int LoadGlyphs( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + FontPtr /*pfont*/, + unsigned /*nchars*/, + int /*item_size*/, + unsigned char * /*data*/ +#endif +); + +extern void DeleteClientFontStuff( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void InitFonts( +#if NeedFunctionPrototypes + void +#endif +); + +extern int GetDefaultPointSize( +#if NeedFunctionPrototypes + void +#endif +); + +extern FontResolutionPtr GetClientResolutions( +#if NeedFunctionPrototypes + int * /*num*/ +#endif +); + +/* XXX leave these unprototyped for now -- need to do groundwork in + * fonts/include/fontstruct.h before we do these + */ +extern int RegisterFPEFunctions( +#if NeedFunctionPrototypes + Bool (* /*name_func*/)(), + int (* /*init_func*/)(), + int (* /*free_func*/)(), + int (* /*reset_func*/)(), + int (* /*open_func*/)(), + int (* /*close_func*/)(), + int (* /*list_func*/)(), + int (* /*start_lfwi_func*/)(), + int (* /*next_lfwi_func*/)(), + int (* /*wakeup_func*/)(), + int (* /*client_died*/)(), + int (* /*load_glyphs*/)(), + int (* /*start_list_alias_func*/)(), + int (* /*next_list_alias_func*/)(), + void (* /* set_path_func*/) () +#endif +); + +extern void FreeFonts( +#if NeedFunctionPrototypes + void +#endif +); + +extern FontPtr find_old_font( +#if NeedFunctionPrototypes + XID /*id*/ +#endif +); + +extern Font GetNewFontClientID( +#if NeedFunctionPrototypes + void +#endif +); + +extern int StoreFontClientFont( +#if NeedFunctionPrototypes + FontPtr /*pfont*/, + Font /*id*/ +#endif +); + +extern void DeleteFontClientID( +#if NeedFunctionPrototypes + Font /*id*/ +#endif +); + +extern int client_auth_generation( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern int init_fs_handlers( +#if NeedFunctionPrototypes + FontPathElementPtr /*fpe*/, + BlockHandlerProcPtr /*block_handler*/ +#endif +); + +extern void remove_fs_handlers( +#if NeedFunctionPrototypes + FontPathElementPtr /*fpe*/, + BlockHandlerProcPtr /*block_handler*/, + Bool /*all*/ +#endif +); + +extern void GetGlyphs( +#if NeedFunctionPrototypes + FontPtr /*font*/, + unsigned long /*count*/, + unsigned char * /*chars*/, + FontEncoding /*fontEncoding*/, + unsigned long * /*glyphcount*/, + CharInfoPtr * /*glyphs*/ +#endif +); + +extern void QueryGlyphExtents( +#if NeedFunctionPrototypes + FontPtr /*pFont*/, + CharInfoPtr * /*charinfo*/, + unsigned long /*count*/, + ExtentInfoPtr /*info*/ +#endif +); + +extern Bool QueryTextExtents( +#if NeedFunctionPrototypes + FontPtr /*pFont*/, + unsigned long /*count*/, + unsigned char * /*chars*/, + ExtentInfoPtr /*info*/ +#endif +); + +extern Bool ParseGlyphCachingMode( +#if NeedFunctionPrototypes + char * /*str*/ +#endif +); + +extern void InitGlyphCaching( +#if NeedFunctionPrototypes + void +#endif +); + +extern void SetGlyphCachingMode( +#if NeedFunctionPrototypes + int /*newmode*/ +#endif +); + +void +ResetFontPrivateIndex( +#if NeedFunctionPrototypes + void +#endif +); + +#endif /* DIXFONT_H */ diff --git a/include/dixfontstr.h b/include/dixfontstr.h new file mode 100644 index 000000000..d1d0449dc --- /dev/null +++ b/include/dixfontstr.h @@ -0,0 +1,95 @@ +/* $Xorg: dixfontstr.h,v 1.3 2000/08/17 19:53:29 cpqbld Exp $ */ +/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#ifndef DIXFONTSTRUCT_H +#define DIXFONTSTRUCT_H + +#include "servermd.h" +#include "dixfont.h" +#include "fontstruct.h" +#include "closure.h" +#define NEED_REPLIES +#include "X11/Xproto.h" /* for xQueryFontReply */ + +#define FONTCHARSET(font) (font) +#define FONTMAXBOUNDS(font,field) (font)->info.maxbounds.field +#define FONTMINBOUNDS(font,field) (font)->info.minbounds.field +#define TERMINALFONT(font) (font)->info.terminalFont +#define FONTASCENT(font) (font)->info.fontAscent +#define FONTDESCENT(font) (font)->info.fontDescent +#define FONTGLYPHS(font) 0 +#define FONTCONSTMETRICS(font) (font)->info.constantMetrics +#define FONTCONSTWIDTH(font) (font)->info.constantWidth +#define FONTALLEXIST(font) (font)->info.allExist +#define FONTFIRSTCOL(font) (font)->info.firstCol +#define FONTLASTCOL(font) (font)->info.lastCol +#define FONTFIRSTROW(font) (font)->info.firstRow +#define FONTLASTROW(font) (font)->info.lastRow +#define FONTDEFAULTCH(font) (font)->info.defaultCh +#define FONTINKMIN(font) (&((font)->info.ink_minbounds)) +#define FONTINKMAX(font) (&((font)->info.ink_maxbounds)) +#define FONTPROPS(font) (font)->info.props +#define FONTGLYPHBITS(base,pci) ((unsigned char *) (pci)->bits) +#define FONTINFONPROPS(font) (font)->info.nprops + +/* some things haven't changed names, but we'll be careful anyway */ + +#define FONTREFCNT(font) (font)->refcnt + +/* + * for linear char sets + */ +#define N1dChars(pfont) (FONTLASTCOL(pfont) - FONTFIRSTCOL(pfont) + 1) + +/* + * for 2D char sets + */ +#define N2dChars(pfont) (N1dChars(pfont) * \ + (FONTLASTROW(pfont) - FONTFIRSTROW(pfont) + 1)) + +#ifndef GLYPHPADBYTES +#define GLYPHPADBYTES -1 +#endif + +#if GLYPHPADBYTES == 0 || GLYPHPADBYTES == 1 +#define GLYPHWIDTHBYTESPADDED(pci) (GLYPHWIDTHBYTES(pci)) +#define PADGLYPHWIDTHBYTES(w) (((w)+7)>>3) +#endif + +#if GLYPHPADBYTES == 2 +#define GLYPHWIDTHBYTESPADDED(pci) ((GLYPHWIDTHBYTES(pci)+1) & ~0x1) +#define PADGLYPHWIDTHBYTES(w) (((((w)+7)>>3)+1) & ~0x1) +#endif + +#if GLYPHPADBYTES == 4 +#define GLYPHWIDTHBYTESPADDED(pci) ((GLYPHWIDTHBYTES(pci)+3) & ~0x3) +#define PADGLYPHWIDTHBYTES(w) (((((w)+7)>>3)+3) & ~0x3) +#endif + +#if GLYPHPADBYTES == 8 /* for a cray? */ +#define GLYPHWIDTHBYTESPADDED(pci) ((GLYPHWIDTHBYTES(pci)+7) & ~0x7) +#define PADGLYPHWIDTHBYTES(w) (((((w)+7)>>3)+7) & ~0x7) +#endif + +#endif /* DIXFONTSTRUCT_H */ diff --git a/include/dixstruct.h b/include/dixstruct.h new file mode 100644 index 000000000..d6db3f2b6 --- /dev/null +++ b/include/dixstruct.h @@ -0,0 +1,220 @@ +/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: dixstruct.h,v 1.3 2000/08/17 19:53:29 cpqbld Exp $ */ + +#ifndef DIXSTRUCT_H +#define DIXSTRUCT_H + +#include "dix.h" +#include "resource.h" +#include "cursor.h" +#include "gc.h" +#include "pixmap.h" +#include + +/* + * direct-mapped hash table, used by resource manager to store + * translation from client ids to server addresses. + */ + +#ifdef DEBUG +#define MAX_REQUEST_LOG 100 +#endif + +extern CallbackListPtr ClientStateCallback; + +typedef struct { + ClientPtr client; + xConnSetupPrefix *prefix; + xConnSetup *setup; +} NewClientInfoRec; + +typedef enum {ClientStateInitial, + ClientStateAuthenticating, + ClientStateRunning, + ClientStateRetained, + ClientStateGone, + ClientStateCheckingSecurity, + ClientStateCheckedSecurity} ClientState; + +typedef struct _Client { + int index; + Mask clientAsMask; + pointer requestBuffer; + pointer osPrivate; /* for OS layer, including scheduler */ + Bool swapped; + void (*pSwapReplyFunc) ( +#if NeedNestedPrototypes + ClientPtr /* pClient */, + int /* size */, + void * /* pbuf */ +#endif +); + XID errorValue; + int sequence; + int closeDownMode; + int clientGone; + int noClientException; /* this client died or needs to be + * killed */ + DrawablePtr lastDrawable; + Drawable lastDrawableID; + GCPtr lastGC; + GContext lastGCID; + pointer *saveSet; + int numSaved; + pointer screenPrivate[MAXSCREENS]; + int (**requestVector) ( +#if NeedNestedPrototypes + ClientPtr /* pClient */ +#endif +); + CARD32 req_len; /* length of current request */ + Bool big_requests; /* supports large requests */ + int priority; + ClientState clientState; + DevUnion *devPrivates; +#ifdef XKB + unsigned short xkbClientFlags; + unsigned short mapNotifyMask; + unsigned short newKeyboardNotifyMask; + unsigned short vMajor,vMinor; + KeyCode minKC,maxKC; +#endif + +#ifdef DEBUG + unsigned char requestLog[MAX_REQUEST_LOG]; + int requestLogIndex; +#endif +#ifdef LBX + int (*readRequest)( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); +#endif + unsigned long replyBytesRemaining; +#ifdef XCSECURITY + XID authId; + unsigned int trustLevel; + pointer (* CheckAccess)( +#if NeedNestedPrototypes + ClientPtr /*pClient*/, + XID /*id*/, + RESTYPE /*classes*/, + Mask /*access_mode*/, + pointer /*resourceval*/ +#endif +); +#endif +#ifdef XAPPGROUP + struct _AppGroupRec* appgroup; +#endif + struct _FontResolution * (*fontResFunc) ( /* no need for font.h */ +#if NeedNestedPrototypes + ClientPtr /* pClient */, + int * /* num */ +#endif +); +} ClientRec; + + +typedef struct _WorkQueue { + struct _WorkQueue *next; + Bool (*function) ( +#if NeedNestedPrototypes + ClientPtr /* pClient */, + pointer /* closure */ +#endif +); + ClientPtr client; + pointer closure; +} WorkQueueRec; + +extern TimeStamp currentTime; +extern TimeStamp lastDeviceEventTime; + +extern int CompareTimeStamps( +#if NeedFunctionPrototypes + TimeStamp /*a*/, + TimeStamp /*b*/ +#endif +); + +extern TimeStamp ClientTimeToServerTime( +#if NeedFunctionPrototypes + CARD32 /*c*/ +#endif +); + +typedef struct _CallbackRec { + CallbackProcPtr proc; + pointer data; + Bool deleted; + struct _CallbackRec *next; +} CallbackRec, *CallbackPtr; + +typedef struct _CallbackList { + CallbackFuncsRec funcs; + int inCallback; + Bool deleted; + int numDeleted; + CallbackPtr list; +} CallbackListRec; + +/* proc vectors */ + +extern int (* InitialVector[3]) ( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); + +extern int (* ProcVector[256]) ( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); + +extern int (* SwappedProcVector[256]) ( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); + +#ifdef K5AUTH +extern int (*k5_Vector[256])() = +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); +#endif + +extern void (* ReplySwapVector[256]) (); + +extern int ProcBadRequest( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +#endif /* DIXSTRUCT_H */ diff --git a/include/extension.h b/include/extension.h new file mode 100644 index 000000000..69b32feb1 --- /dev/null +++ b/include/extension.h @@ -0,0 +1,80 @@ +/* $Xorg: extension.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef EXTENSION_H +#define EXTENSION_H + +_XFUNCPROTOBEGIN + +extern unsigned short StandardMinorOpcode( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern unsigned short MinorOpcodeOfRequest( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void InitExtensions( +#if NeedFunctionPrototypes + int argc, + char **argv +#endif +); + +extern void CloseDownExtensions( +#if NeedFunctionPrototypes + void +#endif +); + +_XFUNCPROTOEND + +#endif /* EXTENSION_H */ diff --git a/include/extnsionst.h b/include/extnsionst.h new file mode 100644 index 000000000..6bb52767d --- /dev/null +++ b/include/extnsionst.h @@ -0,0 +1,174 @@ +/* $Xorg: extnsionst.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef EXTENSIONSTRUCT_H +#define EXTENSIONSTRUCT_H + +#include "misc.h" +#include "screenint.h" +#include "extension.h" +#include "gc.h" + +typedef struct _ExtensionEntry { + int index; + void (* CloseDown)( /* called at server shutdown */ +#if NeedNestedPrototypes + struct _ExtensionEntry * /* extension */ +#endif +); + char *name; /* extension name */ + int base; /* base request number */ + int eventBase; + int eventLast; + int errorBase; + int errorLast; + int num_aliases; + char **aliases; + pointer extPrivate; + unsigned short (* MinorOpcode)( /* called for errors */ +#if NeedNestedPrototypes + ClientPtr /* client */ +#endif +); +#ifdef XCSECURITY + Bool secure; /* extension visible to untrusted clients? */ +#endif +} ExtensionEntry; + +/* any attempt to declare the types of the parameters to the functions + * in EventSwapVector fails. The functions take pointers to two events, + * but the exact event types that are declared vary from one function + * to another. You can't even put void *, void * (the ibm compiler + * complains, anyway). + */ +extern void (* EventSwapVector[128]) (); + +typedef void (* ExtensionLookupProc)(/*args indeterminate*/); + +typedef struct _ProcEntry { + char *name; + ExtensionLookupProc proc; +} ProcEntryRec, *ProcEntryPtr; + +typedef struct _ScreenProcEntry { + int num; + ProcEntryPtr procList; +} ScreenProcEntry; + +#define SetGCVector(pGC, VectorElement, NewRoutineAddress, Atom) \ + pGC->VectorElement = NewRoutineAddress; + +#define GetGCValue(pGC, GCElement) (pGC->GCElement) + + +extern ExtensionEntry *AddExtension( +#if NeedFunctionPrototypes + char* /*name*/, + int /*NumEvents*/, + int /*NumErrors*/, + int (* /*MainProc*/)( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +), + int (* /*SwappedMainProc*/)( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +), + void (* /*CloseDownProc*/)( +#if NeedNestedPrototypes + ExtensionEntry * /*extension*/ +#endif +), + unsigned short (* /*MinorOpcodeProc*/)( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif + ) +#endif /* NeedFunctionPrototypes */ +); + +extern Bool AddExtensionAlias( +#if NeedFunctionPrototypes + char* /*alias*/, + ExtensionEntry * /*extension*/ +#endif +); + +extern ExtensionLookupProc LookupProc( +#if NeedFunctionPrototypes + char* /*name*/, + GCPtr /*pGC*/ +#endif +); + +extern Bool RegisterProc( +#if NeedFunctionPrototypes + char* /*name*/, + GCPtr /*pGC*/, + ExtensionLookupProc /*proc*/ +#endif +); + +extern Bool RegisterScreenProc( +#if NeedFunctionPrototypes + char* /*name*/, + ScreenPtr /*pScreen*/, + ExtensionLookupProc /*proc*/ +#endif +); + +extern void DeclareExtensionSecurity( +#if NeedFunctionPrototypes + char * /*extname*/, + Bool /*secure*/ +#endif +); + +#endif /* EXTENSIONSTRUCT_H */ + diff --git a/include/gc.h b/include/gc.h new file mode 100644 index 000000000..5e220d68c --- /dev/null +++ b/include/gc.h @@ -0,0 +1,231 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: gc.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ + +#ifndef GC_H +#define GC_H + +#include "misc.h" /* for Bool */ +#include "X11/X.h" /* for GContext, Mask */ +#include "X11/Xproto.h" +#include "screenint.h" /* for ScreenPtr */ +#include "pixmap.h" /* for DrawablePtr */ + +/* clientClipType field in GC */ +#define CT_NONE 0 +#define CT_PIXMAP 1 +#define CT_REGION 2 +#define CT_UNSORTED 6 +#define CT_YSORTED 10 +#define CT_YXSORTED 14 +#define CT_YXBANDED 18 + +#define GCQREASON_VALIDATE 1 +#define GCQREASON_CHANGE 2 +#define GCQREASON_COPY_SRC 3 +#define GCQREASON_COPY_DST 4 +#define GCQREASON_DESTROY 5 + +#define GC_CHANGE_SERIAL_BIT (((unsigned long)1)<<31) +#define GC_CALL_VALIDATE_BIT (1L<<30) +#define GCExtensionInterest (1L<<29) + +#define DRAWABLE_SERIAL_BITS (~(GC_CHANGE_SERIAL_BIT)) + +#define MAX_SERIAL_NUM (1L<<28) + +#define NEXT_SERIAL_NUMBER ((++globalSerialNumber) > MAX_SERIAL_NUM ? \ + (globalSerialNumber = 1): globalSerialNumber) + +typedef struct _GCInterest *GCInterestPtr; +typedef struct _GC *GCPtr; +typedef struct _GCOps *GCOpsPtr; + +extern void ValidateGC( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/ +#endif +); + +extern int ChangeGC( +#if NeedFunctionPrototypes + GCPtr/*pGC*/, + BITS32 /*mask*/, + XID* /*pval*/ +#endif +); + +extern int DoChangeGC( +#if NeedFunctionPrototypes + GCPtr/*pGC*/, + BITS32 /*mask*/, + XID* /*pval*/, + int /*fPointer*/ +#endif +); + +typedef union { + CARD32 val; + pointer ptr; +} ChangeGCVal, *ChangeGCValPtr; + +extern int dixChangeGC( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + GCPtr /*pGC*/, + BITS32 /*mask*/, + CARD32 * /*pval*/, + ChangeGCValPtr /*pCGCV*/ +#endif +); + +extern GCPtr CreateGC( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + BITS32 /*mask*/, + XID* /*pval*/, + int* /*pStatus*/ +#endif +); + +extern int CopyGC( +#if NeedFunctionPrototypes + GCPtr/*pgcSrc*/, + GCPtr/*pgcDst*/, + BITS32 /*mask*/ +#endif +); + +extern int FreeGC( +#if NeedFunctionPrototypes + pointer /*pGC*/, + XID /*gid*/ +#endif +); + +extern void SetGCMask( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + Mask /*selectMask*/, + Mask /*newDataMask*/ +#endif +); + +extern GCPtr CreateScratchGC( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + unsigned /*depth*/ +#endif +); + +extern void FreeGCperDepth( +#if NeedFunctionPrototypes + int /*screenNum*/ +#endif +); + +extern Bool CreateGCperDepth( +#if NeedFunctionPrototypes + int /*screenNum*/ +#endif +); + +extern Bool CreateDefaultStipple( +#if NeedFunctionPrototypes + int /*screenNum*/ +#endif +); + +extern void FreeDefaultStipple( +#if NeedFunctionPrototypes + int /*screenNum*/ +#endif +); + +extern int SetDashes( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + unsigned /*offset*/, + unsigned /*ndash*/, + unsigned char* /*pdash*/ +#endif +); + +extern int VerifyRectOrder( +#if NeedFunctionPrototypes + int /*nrects*/, + xRectangle* /*prects*/, + int /*ordering*/ +#endif +); + +extern int SetClipRects( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + int /*xOrigin*/, + int /*yOrigin*/, + int /*nrects*/, + xRectangle* /*prects*/, + int /*ordering*/ +#endif +); + +extern GCPtr GetScratchGC( +#if NeedFunctionPrototypes + unsigned /*depth*/, + ScreenPtr /*pScreen*/ +#endif +); + +extern void FreeScratchGC( +#if NeedFunctionPrototypes + GCPtr /*pGC*/ +#endif +); + +#endif /* GC_H */ diff --git a/include/gcstruct.h b/include/gcstruct.h new file mode 100644 index 000000000..9d6040c9d --- /dev/null +++ b/include/gcstruct.h @@ -0,0 +1,396 @@ +/* $Xorg: gcstruct.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#ifndef GCSTRUCT_H +#define GCSTRUCT_H + +#include "gc.h" + +#include "miscstruct.h" +#include "region.h" +#include "pixmap.h" +#include "screenint.h" +#include "Xprotostr.h" + +/* + * functions which modify the state of the GC + */ + +typedef struct _GCFuncs { + void (* ValidateGC)( +#if NeedNestedPrototypes + GCPtr /*pGC*/, + unsigned long /*stateChanges*/, + DrawablePtr /*pDrawable*/ +#endif +); + + void (* ChangeGC)( +#if NeedNestedPrototypes + GCPtr /*pGC*/, + unsigned long /*mask*/ +#endif +); + + void (* CopyGC)( +#if NeedNestedPrototypes + GCPtr /*pGCSrc*/, + unsigned long /*mask*/, + GCPtr /*pGCDst*/ +#endif +); + + void (* DestroyGC)( +#if NeedNestedPrototypes + GCPtr /*pGC*/ +#endif +); + + void (* ChangeClip)( +#if NeedNestedPrototypes + GCPtr /*pGC*/, + int /*type*/, + pointer /*pvalue*/, + int /*nrects*/ +#endif +); + + void (* DestroyClip)( +#if NeedNestedPrototypes + GCPtr /*pGC*/ +#endif +); + + void (* CopyClip)( +#if NeedNestedPrototypes + GCPtr /*pgcDst*/, + GCPtr /*pgcSrc*/ +#endif +); + DevUnion devPrivate; +} GCFuncs; + +/* + * graphics operations invoked through a GC + */ + +typedef struct _GCOps { + void (* FillSpans)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + + void (* SetSpans)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + char * /*psrc*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + int /*nspans*/, + int /*fSorted*/ +#endif +); + + void (* PutImage)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*depth*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*leftPad*/, + int /*format*/, + char * /*pBits*/ +#endif +); + + RegionPtr (* CopyArea)( +#if NeedNestedPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + GCPtr /*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*w*/, + int /*h*/, + int /*dstx*/, + int /*dsty*/ +#endif +); + + RegionPtr (* CopyPlane)( +#if NeedNestedPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr /*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/, + unsigned long /*bitPlane*/ +#endif +); + void (* PolyPoint)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/ +#endif +); + + void (* Polylines)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/ +#endif +); + + void (* PolySegment)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegs*/ +#endif +); + + void (* PolyRectangle)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nrects*/, + xRectangle * /*pRects*/ +#endif +); + + void (* PolyArc)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); + + void (* FillPolygon)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*pPts*/ +#endif +); + + void (* PolyFillRect)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nrectFill*/, + xRectangle * /*prectInit*/ +#endif +); + + void (* PolyFillArc)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); + + int (* PolyText8)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/ +#endif +); + + int (* PolyText16)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/ +#endif +); + + void (* ImageText8)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/ +#endif +); + + void (* ImageText16)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/ +#endif +); + + void (* ImageGlyphBlt)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); + + void (* PolyGlyphBlt)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); + + void (* PushPixels)( +#if NeedNestedPrototypes + GCPtr /*pGC*/, + PixmapPtr /*pBitMap*/, + DrawablePtr /*pDst*/, + int /*w*/, + int /*h*/, + int /*x*/, + int /*y*/ +#endif +); + +#ifdef NEED_LINEHELPER + void (* LineHelper)(); +#endif + + DevUnion devPrivate; +} GCOps; + +/* there is padding in the bit fields because the Sun compiler doesn't + * force alignment to 32-bit boundaries. losers. + */ +typedef struct _GC { + ScreenPtr pScreen; + unsigned char depth; + unsigned char alu; + unsigned short lineWidth; + unsigned short dashOffset; + unsigned short numInDashList; + unsigned char *dash; + unsigned int lineStyle : 2; + unsigned int capStyle : 2; + unsigned int joinStyle : 2; + unsigned int fillStyle : 2; + unsigned int fillRule : 1; + unsigned int arcMode : 1; + unsigned int subWindowMode : 1; + unsigned int graphicsExposures : 1; + unsigned int clientClipType : 2; /* CT_ */ + unsigned int miTranslate:1; /* should mi things translate? */ + unsigned int tileIsPixel:1; /* tile is solid pixel */ + unsigned int unused:16; /* see comment above */ + unsigned long planemask; + unsigned long fgPixel; + unsigned long bgPixel; + /* + * alas -- both tile and stipple must be here as they + * are independently specifiable + */ + PixUnion tile; + PixmapPtr stipple; + DDXPointRec patOrg; /* origin for (tile, stipple) */ + struct _Font *font; + DDXPointRec clipOrg; + DDXPointRec lastWinOrg; /* position of window last validated */ + pointer clientClip; + unsigned long stateChanges; /* masked with GC_ */ + unsigned long serialNumber; + GCFuncs *funcs; + GCOps *ops; + DevUnion *devPrivates; +} GC; + +#endif /* GCSTRUCT_H */ diff --git a/include/input.h b/include/input.h new file mode 100644 index 000000000..161af2d63 --- /dev/null +++ b/include/input.h @@ -0,0 +1,496 @@ +/* $Xorg: input.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ +#ifndef INPUT_H +#define INPUT_H + +#include "misc.h" +#include "screenint.h" +#include "X11/Xmd.h" +#include "X11/Xproto.h" +#include "window.h" /* for WindowPtr */ + +#define DEVICE_INIT 0 +#define DEVICE_ON 1 +#define DEVICE_OFF 2 +#define DEVICE_CLOSE 3 + +#define MAP_LENGTH 256 +#define DOWN_LENGTH 32 /* 256/8 => number of bytes to hold 256 bits */ +#define NullGrab ((GrabPtr)NULL) +#define PointerRootWin ((WindowPtr)PointerRoot) +#define NoneWin ((WindowPtr)None) +#define NullDevice ((DevicePtr)NULL) + +#ifndef FollowKeyboard +#define FollowKeyboard 3 +#endif +#ifndef FollowKeyboardWin +#define FollowKeyboardWin ((WindowPtr) FollowKeyboard) +#endif +#ifndef RevertToFollowKeyboard +#define RevertToFollowKeyboard 3 +#endif + +typedef unsigned long Leds; +typedef struct _OtherClients *OtherClientsPtr; +typedef struct _InputClients *InputClientsPtr; +typedef struct _DeviceIntRec *DeviceIntPtr; + +typedef int (*DeviceProc)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + int /*what*/ +#endif +); + +typedef void (*ProcessInputProc)( +#if NeedNestedPrototypes + xEventPtr /*events*/, + DeviceIntPtr /*device*/, + int /*count*/ +#endif +); + +typedef struct _DeviceRec { + pointer devicePrivate; + ProcessInputProc processInputProc; /* current */ + ProcessInputProc realInputProc; /* deliver */ + ProcessInputProc enqueueInputProc; /* enqueue */ + Bool on; /* used by DDX to keep state */ +} DeviceRec, *DevicePtr; + +typedef struct { + int click, bell, bell_pitch, bell_duration; + Bool autoRepeat; + unsigned char autoRepeats[32]; + Leds leds; + unsigned char id; +} KeybdCtrl; + +typedef struct { + KeySym *map; + KeyCode minKeyCode, + maxKeyCode; + int mapWidth; +} KeySymsRec, *KeySymsPtr; + +typedef struct { + int num, den, threshold; + unsigned char id; +} PtrCtrl; + +typedef struct { + int resolution, min_value, max_value; + int integer_displayed; + unsigned char id; +} IntegerCtrl; + +typedef struct { + int max_symbols, num_symbols_supported; + int num_symbols_displayed; + KeySym *symbols_supported; + KeySym *symbols_displayed; + unsigned char id; +} StringCtrl; + +typedef struct { + int percent, pitch, duration; + unsigned char id; +} BellCtrl; + +typedef struct { + Leds led_values; + Mask led_mask; + unsigned char id; +} LedCtrl; + +extern KeybdCtrl defaultKeyboardControl; +extern PtrCtrl defaultPointerControl; + +extern DevicePtr AddInputDevice( +#if NeedFunctionPrototypes + DeviceProc /*deviceProc*/, + Bool /*autoStart*/ +#endif +); + +extern Bool EnableDevice( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/ +#endif +); + +extern Bool DisableDevice( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/ +#endif +); + +extern int InitAndStartDevices( +#if NeedFunctionPrototypes + void +#endif +); + +extern void CloseDownDevices( +#if NeedFunctionPrototypes + void +#endif +); + +extern int NumMotionEvents( +#if NeedFunctionPrototypes + void +#endif +); + +extern void RegisterPointerDevice( +#if NeedFunctionPrototypes + DevicePtr /*device*/ +#endif +); + +extern void RegisterKeyboardDevice( +#if NeedFunctionPrototypes + DevicePtr /*device*/ +#endif +); + +extern DevicePtr LookupKeyboardDevice( +#if NeedFunctionPrototypes + void +#endif +); + +extern DevicePtr LookupPointerDevice( +#if NeedFunctionPrototypes + void +#endif +); + +extern DevicePtr LookupDevice( +#if NeedFunctionPrototypes + int /* id */ +#endif +); + +extern void QueryMinMaxKeyCodes( +#if NeedFunctionPrototypes + KeyCode* /*minCode*/, + KeyCode* /*maxCode*/ +#endif +); + +extern Bool SetKeySymsMap( +#if NeedFunctionPrototypes + KeySymsPtr /*dst*/, + KeySymsPtr /*src*/ +#endif +); + +extern Bool InitKeyClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + KeySymsPtr /*pKeySyms*/, + CARD8 /*pModifiers*/[] +#endif +); + +extern Bool InitButtonClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + int /*numButtons*/, + CARD8* /*map*/ +#endif +); + +typedef int (*ValuatorMotionProcPtr)( +#if NeedNestedPrototypes + DeviceIntPtr /*pdevice*/, + xTimecoord * /*coords*/, + unsigned long /*start*/, + unsigned long /*stop*/, + ScreenPtr /*pScreen*/ +#endif +); + +extern Bool InitValuatorClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + int /*numAxes*/, + ValuatorMotionProcPtr /* motionProc */, + int /*numMotionEvents*/, + int /*mode*/ +#endif +); + +extern Bool InitFocusClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/ +#endif +); + +typedef void (*BellProcPtr)( +#if NeedNestedPrototypes + int /*percent*/, + DeviceIntPtr /*device*/, + pointer /*ctrl*/, + int +#endif +); + +typedef void (*KbdCtrlProcPtr)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + KeybdCtrl * /*ctrl*/ +#endif +); + +extern Bool InitKbdFeedbackClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + BellProcPtr /*bellProc*/, + KbdCtrlProcPtr /*controlProc*/ +#endif +); + +typedef void (*PtrCtrlProcPtr)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + PtrCtrl * /*ctrl*/ +#endif +); + +extern Bool InitPtrFeedbackClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + PtrCtrlProcPtr /*controlProc*/ +#endif +); + +typedef void (*StringCtrlProcPtr)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + StringCtrl * /*ctrl*/ +#endif +); + +extern Bool InitStringFeedbackClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + StringCtrlProcPtr /*controlProc*/, + int /*max_symbols*/, + int /*num_symbols_supported*/, + KeySym* /*symbols*/ +#endif +); + +typedef void (*BellCtrlProcPtr)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + BellCtrl * /*ctrl*/ +#endif +); + +extern Bool InitBellFeedbackClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + BellProcPtr /*bellProc*/, + BellCtrlProcPtr /*controlProc*/ +#endif +); + +typedef void (*LedCtrlProcPtr)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + LedCtrl * /*ctrl*/ +#endif +); + +extern Bool InitLedFeedbackClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + LedCtrlProcPtr /*controlProc*/ +#endif +); + +typedef void (*IntegerCtrlProcPtr)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + IntegerCtrl * /*ctrl*/ +#endif +); + + +extern Bool InitIntegerFeedbackClassDeviceStruct( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + IntegerCtrlProcPtr /*controlProc*/ +#endif +); + +extern Bool InitPointerDeviceStruct( +#if NeedFunctionPrototypes + DevicePtr /*device*/, + CARD8* /*map*/, + int /*numButtons*/, + ValuatorMotionProcPtr /*motionProc*/, + PtrCtrlProcPtr /*controlProc*/, + int /*numMotionEvents*/ +#endif +); + +extern Bool InitKeyboardDeviceStruct( +#if NeedFunctionPrototypes + DevicePtr /*device*/, + KeySymsPtr /*pKeySyms*/, + CARD8 /*pModifiers*/[], + BellProcPtr /*bellProc*/, + KbdCtrlProcPtr /*controlProc*/ +#endif +); + +extern void SendMappingNotify( +#if NeedFunctionPrototypes + unsigned int /*request*/, + unsigned int /*firstKeyCode*/, + unsigned int /*count*/, + ClientPtr /* client */ +#endif +); + +extern Bool BadDeviceMap( +#if NeedFunctionPrototypes + BYTE* /*buff*/, + int /*length*/, + unsigned /*low*/, + unsigned /*high*/, + XID* /*errval*/ +#endif +); + +extern Bool AllModifierKeysAreUp( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + CARD8* /*map1*/, + int /*per1*/, + CARD8* /*map2*/, + int /*per2*/ +#endif +); + +extern void NoteLedState( +#if NeedFunctionPrototypes + DeviceIntPtr /*keybd*/, + int /*led*/, + Bool /*on*/ +#endif +); + +extern void MaybeStopHint( +#if NeedFunctionPrototypes + DeviceIntPtr /*device*/, + ClientPtr /*client*/ +#endif +); + +extern void ProcessPointerEvent( +#if NeedFunctionPrototypes + xEventPtr /*xE*/, + DeviceIntPtr /*mouse*/, + int /*count*/ +#endif +); + +extern void ProcessKeyboardEvent( +#if NeedFunctionPrototypes + xEventPtr /*xE*/, + DeviceIntPtr /*keybd*/, + int /*count*/ +#endif +); + +#ifdef XKB +extern void CoreProcessPointerEvent( +#if NeedFunctionPrototypes + xEventPtr /*xE*/, + DeviceIntPtr /*mouse*/, + int /*count*/ +#endif +); + +extern void CoreProcessKeyboardEvent( +#if NeedFunctionPrototypes + xEventPtr /*xE*/, + DeviceIntPtr /*keybd*/, + int /*count*/ +#endif +); +#endif + +extern Bool LegalModifier( +#if NeedFunctionPrototypes + unsigned int /*key*/, + DevicePtr /*pDev*/ +#endif +); + +extern void ProcessInputEvents( +#if NeedFunctionPrototypes + void +#endif +); + +extern void InitInput( +#if NeedFunctionPrototypes + int /*argc*/, + char ** /*argv*/ +#endif +); + +#endif /* INPUT_H */ diff --git a/include/inputstr.h b/include/inputstr.h new file mode 100644 index 000000000..43a50eb56 --- /dev/null +++ b/include/inputstr.h @@ -0,0 +1,316 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + +/* $Xorg: inputstr.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ + +#ifndef INPUTSTRUCT_H +#define INPUTSTRUCT_H + +#include "input.h" +#include "window.h" +#include "dixstruct.h" + +#define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) + +#define SameClient(obj,client) \ + (CLIENT_BITS((obj)->resource) == (client)->clientAsMask) + +#define MAX_DEVICES 9 + +#define EMASKSIZE MAX_DEVICES + +/* Kludge: OtherClients and InputClients must be compatible, see code */ + +typedef struct _OtherClients { + OtherClientsPtr next; + XID resource; /* id for putting into resource manager */ + Mask mask; +} OtherClients; + +typedef struct _InputClients { + InputClientsPtr next; + XID resource; /* id for putting into resource manager */ + Mask mask[EMASKSIZE]; +} InputClients; + +typedef struct _OtherInputMasks { + Mask deliverableEvents[EMASKSIZE]; + Mask inputEvents[EMASKSIZE]; + Mask dontPropagateMask[EMASKSIZE]; + InputClientsPtr inputClients; +} OtherInputMasks; + +/* + * The following structure gets used for both active and passive grabs. For + * active grabs some of the fields (e.g. modifiers) are not used. However, + * that is not much waste since there aren't many active grabs (one per + * keyboard/pointer device) going at once in the server. + */ + +#define MasksPerDetailMask 8 /* 256 keycodes and 256 possible + modifier combinations, but only + 3 buttons. */ + + typedef struct _DetailRec { /* Grab details may be bit masks */ + unsigned short exact; + Mask *pMask; + } DetailRec; + + typedef struct _GrabRec { + GrabPtr next; /* for chain of passive grabs */ + XID resource; + DeviceIntPtr device; + WindowPtr window; + unsigned ownerEvents:1; + unsigned keyboardMode:1; + unsigned pointerMode:1; + unsigned coreGrab:1; /* grab is on core device */ + unsigned coreMods:1; /* modifiers are on core keyboard */ + CARD8 type; /* event type */ + DetailRec modifiersDetail; + DeviceIntPtr modifierDevice; + DetailRec detail; /* key or button */ + WindowPtr confineTo; /* always NULL for keyboards */ + CursorPtr cursor; /* always NULL for keyboards */ + Mask eventMask; +} GrabRec; + +typedef struct _KeyClassRec { + CARD8 down[DOWN_LENGTH]; + KeyCode *modifierKeyMap; + KeySymsRec curKeySyms; + int modifierKeyCount[8]; + CARD8 modifierMap[MAP_LENGTH]; + CARD8 maxKeysPerModifier; + unsigned short state; + unsigned short prev_state; +#ifdef XKB + struct _XkbSrvInfo *xkbInfo; +#endif +} KeyClassRec, *KeyClassPtr; + +typedef struct _AxisInfo { + int resolution; + int min_resolution; + int max_resolution; + int min_value; + int max_value; +} AxisInfo, *AxisInfoPtr; + +typedef struct _ValuatorClassRec { + ValuatorMotionProcPtr GetMotionProc; + int numMotionEvents; + WindowPtr motionHintWindow; + AxisInfoPtr axes; + unsigned short numAxes; + int *axisVal; + CARD8 mode; +} ValuatorClassRec, *ValuatorClassPtr; + +typedef struct _ButtonClassRec { + CARD8 numButtons; + CARD8 buttonsDown; /* number of buttons currently down */ + unsigned short state; + Mask motionMask; + CARD8 down[DOWN_LENGTH]; + CARD8 map[MAP_LENGTH]; +#ifdef XKB + union _XkbAction * xkb_acts; +#endif +} ButtonClassRec, *ButtonClassPtr; + +typedef struct _FocusClassRec { + WindowPtr win; + int revert; + TimeStamp time; + WindowPtr *trace; + int traceSize; + int traceGood; +} FocusClassRec, *FocusClassPtr; + +typedef struct _ProximityClassRec { + char pad; +} ProximityClassRec, *ProximityClassPtr; + +typedef struct _KbdFeedbackClassRec *KbdFeedbackPtr; +typedef struct _PtrFeedbackClassRec *PtrFeedbackPtr; +typedef struct _IntegerFeedbackClassRec *IntegerFeedbackPtr; +typedef struct _StringFeedbackClassRec *StringFeedbackPtr; +typedef struct _BellFeedbackClassRec *BellFeedbackPtr; +typedef struct _LedFeedbackClassRec *LedFeedbackPtr; + +typedef struct _KbdFeedbackClassRec { + BellProcPtr BellProc; + KbdCtrlProcPtr CtrlProc; + KeybdCtrl ctrl; + KbdFeedbackPtr next; +#ifdef XKB + struct _XkbSrvLedInfo *xkb_sli; +#endif +} KbdFeedbackClassRec; + +typedef struct _PtrFeedbackClassRec { + PtrCtrlProcPtr CtrlProc; + PtrCtrl ctrl; + PtrFeedbackPtr next; +} PtrFeedbackClassRec; + +typedef struct _IntegerFeedbackClassRec { + IntegerCtrlProcPtr CtrlProc; + IntegerCtrl ctrl; + IntegerFeedbackPtr next; +} IntegerFeedbackClassRec; + +typedef struct _StringFeedbackClassRec { + StringCtrlProcPtr CtrlProc; + StringCtrl ctrl; + StringFeedbackPtr next; +} StringFeedbackClassRec; + +typedef struct _BellFeedbackClassRec { + BellProcPtr BellProc; + BellCtrlProcPtr CtrlProc; + BellCtrl ctrl; + BellFeedbackPtr next; +} BellFeedbackClassRec; + +typedef struct _LedFeedbackClassRec { + LedCtrlProcPtr CtrlProc; + LedCtrl ctrl; + LedFeedbackPtr next; +#ifdef XKB + struct _XkbSrvLedInfo *xkb_sli; +#endif +} LedFeedbackClassRec; + +/* states for devices */ + +#define NOT_GRABBED 0 +#define THAWED 1 +#define THAWED_BOTH 2 /* not a real state */ +#define FREEZE_NEXT_EVENT 3 +#define FREEZE_BOTH_NEXT_EVENT 4 +#define FROZEN 5 /* any state >= has device frozen */ +#define FROZEN_NO_EVENT 5 +#define FROZEN_WITH_EVENT 6 +#define THAW_OTHERS 7 + +typedef struct _DeviceIntRec { + DeviceRec public; + DeviceIntPtr next; + TimeStamp grabTime; + Bool startup; /* true if needs to be turned on at + server intialization time */ + DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is + used to initialize, turn on, or + turn off the device */ + Bool inited; /* TRUE if INIT returns Success */ + GrabPtr grab; /* the grabber - used by DIX */ + struct { + Bool frozen; + int state; + GrabPtr other; /* if other grab has this frozen */ + xEvent *event; /* saved to be replayed */ + int evcount; + } sync; + Atom type; + char *name; + CARD8 id; + CARD8 activatingKey; + Bool fromPassiveGrab; + GrabRec activeGrab; + void (*ActivateGrab) ( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/, + GrabPtr /*grab*/, + TimeStamp /*time*/, + Bool /*autoGrab*/ +#endif +); + void (*DeactivateGrab)( +#if NeedNestedPrototypes + DeviceIntPtr /*device*/ +#endif +); + KeyClassPtr key; + ValuatorClassPtr valuator; + ButtonClassPtr button; + FocusClassPtr focus; + ProximityClassPtr proximity; + KbdFeedbackPtr kbdfeed; + PtrFeedbackPtr ptrfeed; + IntegerFeedbackPtr intfeed; + StringFeedbackPtr stringfeed; + BellFeedbackPtr bell; + LedFeedbackPtr leds; +#ifdef XKB + struct _XkbInterest * xkb_interest; +#endif +} DeviceIntRec; + +typedef struct { + int numDevices; /* total number of devices */ + DeviceIntPtr devices; /* all devices turned on */ + DeviceIntPtr off_devices; /* all devices turned off */ + DeviceIntPtr keyboard; /* the main one for the server */ + DeviceIntPtr pointer; +} InputInfo; + +extern InputInfo inputInfo; + +/* for keeping the events for devices grabbed synchronously */ +typedef struct _QdEvent *QdEventPtr; +typedef struct _QdEvent { + QdEventPtr next; + DeviceIntPtr device; + ScreenPtr pScreen; /* what screen the pointer was on */ + unsigned long months; /* milliseconds is in the event */ + xEvent *event; + int evcount; +} QdEventRec; + +#endif /* INPUTSTRUCT_H */ diff --git a/include/misc.h b/include/misc.h new file mode 100644 index 000000000..9627810d8 --- /dev/null +++ b/include/misc.h @@ -0,0 +1,271 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +Copyright 1992, 1993 Data General Corporation; +Copyright 1992, 1993 OMRON Corporation + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, 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 +neither the name OMRON or DATA GENERAL be used in advertising or publicity +pertaining to distribution of the software without specific, written prior +permission of the party whose name is to be used. Neither OMRON or +DATA GENERAL make any representation about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +OMRON AND DATA GENERAL EACH DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL OMRON OR DATA GENERAL 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. + +******************************************************************/ +/* $Xorg: misc.h,v 1.5 2001/02/09 02:05:15 xorgcvs Exp $ */ +#ifndef MISC_H +#define MISC_H 1 +/* + * X internal definitions + * + */ + +extern unsigned long globalSerialNumber; +extern unsigned long serverGeneration; + +#include +#include +#include +#include + +#ifndef NULL +#ifndef X_NOT_STDC_ENV +#include +#else +#define NULL 0 +#endif +#endif + +#ifndef MAXSCREENS +#define MAXSCREENS 3 +#endif +#define MAXCLIENTS 256 +#define MAXDITS 1 +#define MAXEXTENSIONS 128 +#define MAXFORMATS 8 +#define MAXVISUALS_PER_SCREEN 50 + +#if NeedFunctionPrototypes +typedef void *pointer; +#else +typedef unsigned char *pointer; +#endif +typedef int Bool; +typedef unsigned long PIXEL; +typedef unsigned long ATOM; + + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifndef _XTYPEDEF_FONTPTR +typedef struct _Font *FontPtr; /* also in fonts/include/font.h */ +#define _XTYPEDEF_FONTPTR +#endif + +#ifndef _XTYPEDEF_CLIENTPTR +typedef struct _Client *ClientPtr; /* also in dix.h */ +#define _XTYPEDEF_CLIENTPTR +#endif + +#ifndef _XTYPEDEF_CALLBACKLISTPTR +typedef struct _CallbackList *CallbackListPtr; /* also in dix.h */ +#define _XTYPEDEF_CALLBACKLISTPTR +#endif + +typedef struct _xReq *xReqPtr; + +#include "os.h" /* for ALLOCATE_LOCAL and DEALLOCATE_LOCAL */ +#include /* for bcopy, bzero, and bcmp */ + +#define NullBox ((BoxPtr)0) +#define MILLI_PER_MIN (1000 * 60) +#define MILLI_PER_SECOND (1000) + + /* this next is used with None and ParentRelative to tell + PaintWin() what to use to paint the background. Also used + in the macro IS_VALID_PIXMAP */ + +#define USE_BACKGROUND_PIXEL 3 +#define USE_BORDER_PIXEL 3 + + +/* byte swap a 32-bit literal */ +#define lswapl(x) ((((x) & 0xff) << 24) |\ + (((x) & 0xff00) << 8) |\ + (((x) & 0xff0000) >> 8) |\ + (((x) >> 24) & 0xff)) + +/* byte swap a short literal */ +#define lswaps(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff)) + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#ifndef abs +#define abs(a) ((a) > 0 ? (a) : -(a)) +#endif +#ifndef Fabs +#define Fabs(a) ((a) > 0.0 ? (a) : -(a)) /* floating absolute value */ +#endif +#define sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0)) +/* this assumes b > 0 */ +#define modulus(a, b, d) if (((d) = (a) % (b)) < 0) (d) += (b) +/* + * return the least significant bit in x which is set + * + * This works on 1's complement and 2's complement machines. + * If you care about the extra instruction on 2's complement + * machines, change to ((x) & (-(x))) + */ +#define lowbit(x) ((x) & (~(x) + 1)) + +#ifndef MAXSHORT +#define MAXSHORT 32767 +#endif +#ifndef MINSHORT +#define MINSHORT -MAXSHORT +#endif + + +/* some macros to help swap requests, replies, and events */ + +#define LengthRestB(stuff) \ + ((client->req_len << 2) - sizeof(*stuff)) + +#define LengthRestS(stuff) \ + ((client->req_len << 1) - (sizeof(*stuff) >> 1)) + +#define LengthRestL(stuff) \ + (client->req_len - (sizeof(*stuff) >> 2)) + +#define SwapRestS(stuff) \ + SwapShorts((short *)(stuff + 1), LengthRestS(stuff)) + +#define SwapRestL(stuff) \ + SwapLongs((CARD32 *)(stuff + 1), LengthRestL(stuff)) + +/* byte swap a 32-bit value */ +#define swapl(x, n) { \ + n = ((char *) (x))[0];\ + ((char *) (x))[0] = ((char *) (x))[3];\ + ((char *) (x))[3] = n;\ + n = ((char *) (x))[1];\ + ((char *) (x))[1] = ((char *) (x))[2];\ + ((char *) (x))[2] = n; } + +/* byte swap a short */ +#define swaps(x, n) { \ + n = ((char *) (x))[0];\ + ((char *) (x))[0] = ((char *) (x))[1];\ + ((char *) (x))[1] = n; } + +/* copy 32-bit value from src to dst byteswapping on the way */ +#define cpswapl(src, dst) { \ + ((char *)&(dst))[0] = ((char *) &(src))[3];\ + ((char *)&(dst))[1] = ((char *) &(src))[2];\ + ((char *)&(dst))[2] = ((char *) &(src))[1];\ + ((char *)&(dst))[3] = ((char *) &(src))[0]; } + +/* copy short from src to dst byteswapping on the way */ +#define cpswaps(src, dst) { \ + ((char *) &(dst))[0] = ((char *) &(src))[1];\ + ((char *) &(dst))[1] = ((char *) &(src))[0]; } + +extern void SwapLongs( +#if NeedFunctionPrototypes + CARD32 *list, + unsigned long count +#endif +); + +extern void SwapShorts( +#if NeedFunctionPrototypes + short *list, + unsigned long count +#endif +); + +extern int MakePredeclaredAtoms( +#if NeedFunctionPrototypes + void +#endif +); + +extern int Ones( +#if NeedFunctionPrototypes + unsigned long /*mask*/ +#endif +); + +typedef struct _xPoint *DDXPointPtr; +typedef struct _Box *BoxPtr; +typedef struct _xEvent *xEventPtr; +typedef struct _xRectangle *xRectanglePtr; +typedef struct _GrabRec *GrabPtr; + +/* typedefs from other places - duplicated here to minimize the amount + * of unnecessary junk that one would normally have to include to get + * these symbols defined + */ + +#ifndef _XTYPEDEF_CHARINFOPTR +typedef struct _CharInfo *CharInfoPtr; /* also in fonts/include/font.h */ +#define _XTYPEDEF_CHARINFOPTR +#endif + +#endif /* MISC_H */ diff --git a/include/miscstruct.h b/include/miscstruct.h new file mode 100644 index 000000000..01dd2821c --- /dev/null +++ b/include/miscstruct.h @@ -0,0 +1,67 @@ +/* $Xorg: miscstruct.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef MISCSTRUCT_H +#define MISCSTRUCT_H 1 + +#include "misc.h" +#include "X11/Xprotostr.h" + +typedef xPoint DDXPointRec; + +typedef struct _Box { + short x1, y1, x2, y2; +} BoxRec; + +typedef union _DevUnion { + pointer ptr; + long val; + unsigned long uval; + pointer (*fptr)(); +} DevUnion; + +#endif /* MISCSTRUCT_H */ diff --git a/include/opaque.h b/include/opaque.h new file mode 100644 index 000000000..f35f39d29 --- /dev/null +++ b/include/opaque.h @@ -0,0 +1,56 @@ +/* $Xorg: opaque.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef OPAQUE_H +#define OPAQUE_H + +#include + +extern char *defaultFontPath; +extern char *defaultTextFont; +extern char *defaultCursorFont; +extern char *rgbPath; +extern int MaxClients; +extern char isItTimeToYield; +extern char dispatchException; + +/* bit values for dispatchException */ +#define DE_RESET 1 +#define DE_TERMINATE 2 +#define DE_PRIORITYCHANGE 4 /* set when a client's priority changes */ + +extern CARD32 TimeOutValue; +extern CARD32 ScreenSaverTime; +extern CARD32 ScreenSaverInterval; +extern int ScreenSaverBlanking; +extern int ScreenSaverAllowExposures; +extern int argcGlobal; +extern char **argvGlobal; + +#endif /* OPAQUE_H */ diff --git a/include/os.h b/include/os.h new file mode 100644 index 000000000..99bfd386c --- /dev/null +++ b/include/os.h @@ -0,0 +1,707 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: os.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ + +#ifndef OS_H +#define OS_H +#include "misc.h" +#define ALLOCATE_LOCAL_FALLBACK(_size) Xalloc((unsigned long)(_size)) +#define DEALLOCATE_LOCAL_FALLBACK(_ptr) Xfree((pointer)(_ptr)) +#include "Xalloca.h" + +#define NullFID ((FID) 0) + +#define SCREEN_SAVER_ON 0 +#define SCREEN_SAVER_OFF 1 +#define SCREEN_SAVER_FORCER 2 +#define SCREEN_SAVER_CYCLE 3 + +#ifndef MAX_REQUEST_SIZE +#define MAX_REQUEST_SIZE 65535 +#endif +#ifndef MAX_BIG_REQUEST_SIZE +#define MAX_BIG_REQUEST_SIZE 1048575 +#endif + +typedef pointer FID; +typedef struct _FontPathRec *FontPathPtr; +typedef struct _NewClientRec *NewClientPtr; + +#define xnfalloc(size) XNFalloc((unsigned long)(size)) +#define xnfrealloc(ptr, size) XNFrealloc((pointer)(ptr), (unsigned long)(size)) + +#define xalloc(size) Xalloc((unsigned long)(size)) +#define xrealloc(ptr, size) Xrealloc((pointer)(ptr), (unsigned long)(size)) +#define xfree(ptr) Xfree((pointer)(ptr)) + +#ifndef X_NOT_STDC_ENV +#include +#else +#ifdef SYSV +#include +#else +#include +#endif +#endif + +/* have to put $(SIGNAL_DEFINES) in DEFINES in Imakefile to get this right */ +#ifdef SIGNALRETURNSINT +#define SIGVAL int +#else +#define SIGVAL void +#endif + +extern int WaitForSomething( +#if NeedFunctionPrototypes + int* /*pClientsReady*/ +#endif +); + +#ifdef LBX +#define ReadRequestFromClient(client) ((client)->readRequest(client)) +extern int StandardReadRequestFromClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); +#else +extern int ReadRequestFromClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); +#endif /* LBX */ + +extern Bool InsertFakeRequest( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + char* /*data*/, + int /*count*/ +#endif +); + +extern int ResetCurrentRequest( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void FlushAllOutput( +#if NeedFunctionPrototypes + void +#endif +); + +extern void FlushIfCriticalOutputPending( +#if NeedFunctionPrototypes + void +#endif +); + +extern void SetCriticalOutputPending( +#if NeedFunctionPrototypes + void +#endif +); + +extern int WriteToClient( +#if NeedFunctionPrototypes + ClientPtr /*who*/, + int /*count*/, + char* /*buf*/ +#endif +); + +extern void ResetOsBuffers( +#if NeedFunctionPrototypes + void +#endif +); + +extern void CreateWellKnownSockets( +#if NeedFunctionPrototypes + void +#endif +); + +extern void ResetWellKnownSockets( +#if NeedFunctionPrototypes + void +#endif +); + +extern XID +AuthorizationIDOfClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern char *ClientAuthorized( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + unsigned int /*proto_n*/, + char* /*auth_proto*/, + unsigned int /*string_n*/, + char* /*auth_string*/ +#endif +); + +extern Bool EstablishNewConnections( +#if NeedFunctionPrototypes + ClientPtr /*clientUnused*/, + pointer /*closure*/ +#endif +); + +extern void CheckConnections( +#if NeedFunctionPrototypes + void +#endif +); + +extern void CloseDownConnection( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern int AddEnabledDevice( +#if NeedFunctionPrototypes + int /*fd*/ +#endif +); + +extern int RemoveEnabledDevice( +#if NeedFunctionPrototypes + int /*fd*/ +#endif +); + +extern int OnlyListenToOneClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern int ListenToAllClients( +#if NeedFunctionPrototypes + void +#endif +); + +extern int IgnoreClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern int AttendClient( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern int MakeClientGrabImpervious( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern int MakeClientGrabPervious( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void Error( +#if NeedFunctionPrototypes + char* /*str*/ +#endif +); + +extern CARD32 GetTimeInMillis( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AdjustWaitForDelay( +#if NeedFunctionPrototypes + pointer /*waitTime*/, + unsigned long /*newdelay*/ +#endif +); + +typedef struct _OsTimerRec *OsTimerPtr; + +typedef CARD32 (*OsTimerCallback)( +#if NeedFunctionPrototypes + OsTimerPtr /* timer */, + CARD32 /* time */, + pointer /* arg */ +#endif +); + +extern void TimerInit( +#if NeedFunctionPrototypes + void +#endif +); + +extern Bool TimerForce( +#if NeedFunctionPrototypes + OsTimerPtr /* timer */ +#endif +); + +#define TimerAbsolute (1<<0) +#define TimerForceOld (1<<1) + +extern OsTimerPtr TimerSet( +#if NeedFunctionPrototypes + OsTimerPtr /* timer */, + int /* flags */, + CARD32 /* millis */, + OsTimerCallback /* func */, + pointer /* arg */ +#endif +); + +extern void TimerCheck( +#if NeedFunctionPrototypes + void +#endif +); + +extern void TimerCancel( +#if NeedFunctionPrototypes + OsTimerPtr /* pTimer */ +#endif +); + +extern void TimerFree( +#if NeedFunctionPrototypes + OsTimerPtr /* pTimer */ +#endif +); + +extern SIGVAL AutoResetServer( +#if NeedFunctionPrototypes + int /*sig*/ +#endif +); + +extern SIGVAL GiveUp( +#if NeedFunctionPrototypes + int /*sig*/ +#endif +); + +extern void UseMsg( +#if NeedFunctionPrototypes + void +#endif +); + +extern void ProcessCommandLine( +#if NeedFunctionPrototypes + int /*argc*/, + char* /*argv*/[] +#endif +); + +extern unsigned long *Xalloc( +#if NeedFunctionPrototypes + unsigned long /*amount*/ +#endif +); + +extern unsigned long *XNFalloc( +#if NeedFunctionPrototypes + unsigned long /*amount*/ +#endif +); + +extern unsigned long *Xcalloc( +#if NeedFunctionPrototypes + unsigned long /*amount*/ +#endif +); + +extern unsigned long *Xrealloc( +#if NeedFunctionPrototypes + pointer /*ptr*/, + unsigned long /*amount*/ +#endif +); + +extern unsigned long *XNFrealloc( +#if NeedFunctionPrototypes + pointer /*ptr*/, + unsigned long /*amount*/ +#endif +); + +extern void Xfree( +#if NeedFunctionPrototypes + pointer /*ptr*/ +#endif +); + +extern int OsInitAllocator( +#if NeedFunctionPrototypes + void +#endif +); + +typedef SIGVAL (*OsSigHandlerPtr)( +#if NeedFunctionPrototypes + int /* sig */ +#endif +); + +extern OsSigHandlerPtr OsSignal( +#if NeedFunctionPrototypes + int /* sig */, + OsSigHandlerPtr /* handler */ +#endif +); + +extern int auditTrailLevel; + +extern void AuditF( +#if NeedVarargsPrototypes + char* /*f*/, + ... +#endif +); + +extern void FatalError( +#if NeedVarargsPrototypes + char* /*f*/, + ... +#endif +); + +extern void ErrorF( +#if NeedVarargsPrototypes + char* /*f*/, + ... +#endif +); + +extern int OsLookupColor( +#if NeedFunctionPrototypes + int /*screen*/, + char * /*name*/, + unsigned /*len*/, + unsigned short * /*pred*/, + unsigned short * /*pgreen*/, + unsigned short * /*pblue*/ +#endif +); + +extern void OsInit( +#if NeedFunctionPrototypes + void +#endif +); + +extern void OsVendorInit( +#if NeedFunctionPrototypes + void +#endif +); + +extern int OsInitColors( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AddHost( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + int /*family*/, + unsigned /*length*/, + pointer /*pAddr*/ +#endif +); + +extern Bool ForEachHostInFamily ( +#if NeedFunctionPrototypes + int /*family*/, + Bool (* /*func*/ )(), + pointer /*closure*/ +#endif +); + +extern int RemoveHost( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + int /*family*/, + unsigned /*length*/, + pointer /*pAddr*/ +#endif +); + +extern int GetHosts( +#if NeedFunctionPrototypes + pointer * /*data*/, + int * /*pnHosts*/, + int * /*pLen*/, + BOOL * /*pEnabled*/ +#endif +); + +typedef struct sockaddr * sockaddrPtr; + +extern int InvalidHost( +#if NeedFunctionPrototypes + sockaddrPtr /*saddr*/, + int /*len*/ +#endif +); + +extern int LocalClient( +#if NeedFunctionPrototypes + ClientPtr /* client */ +#endif +); + +extern int ChangeAccessControl( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + int /*fEnabled*/ +#endif +); + +extern int GetAccessControl( +#if NeedFunctionPrototypes + void +#endif +); + + +extern void AddLocalHosts( +#if NeedFunctionPrototypes + void +#endif +); + +extern void ResetHosts( +#if NeedFunctionPrototypes + char *display +#endif +); + +extern void EnableLocalHost( +#if NeedFunctionPrototypes + void +#endif +); + +extern void DisableLocalHost( +#if NeedFunctionPrototypes + void +#endif +); + +extern void AccessUsingXdmcp( +#if NeedFunctionPrototypes + void +#endif +); + +extern void DefineSelf( +#if NeedFunctionPrototypes + int /*fd*/ +#endif +); + +extern void AugmentSelf( +#if NeedFunctionPrototypes + pointer /*from*/, + int /*len*/ +#endif +); + +extern void InitAuthorization( +#if NeedFunctionPrototypes + char * /*filename*/ +#endif +); + +extern int LoadAuthorization( +#if NeedFunctionPrototypes + void +#endif +); + +extern void RegisterAuthorizations( +#if NeedFunctionPrototypes + void +#endif +); + +extern XID CheckAuthorization( +#if NeedFunctionPrototypes + unsigned int /*namelength*/, + char * /*name*/, + unsigned int /*datalength*/, + char * /*data*/, + ClientPtr /*client*/, + char ** /*reason*/ +#endif +); + +extern void ResetAuthorization( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AddAuthorization( +#if NeedFunctionPrototypes + unsigned int /*name_length*/, + char * /*name*/, + unsigned int /*data_length*/, + char * /*data*/ +#endif +); + +extern XID GenerateAuthorization( +#if NeedFunctionPrototypes + unsigned int /* name_length */, + char * /* name */, + unsigned int /* data_length */, + char * /* data */, + unsigned int * /* data_length_return */, + char ** /* data_return */ +#endif +); + +#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS +extern void ExpandCommandLine( +#if NeedFunctionPrototypes + int * /*pargc*/, + char *** /*pargv*/ +#endif +); +#endif + +extern int ddxProcessArgument( +#if NeedFunctionPrototypes + int /*argc*/, + char * /*argv*/ [], + int /*i*/ +#endif +); + +/* + * idiom processing stuff + */ + +xReqPtr PeekNextRequest( +#if NeedFunctionPrototypes + xReqPtr req, ClientPtr client, Bool readmore +#endif +); + +void SkipRequests( +#if NeedFunctionPrototypes + xReqPtr req, ClientPtr client, int numskipped +#endif +); + +/* int ReqLen(xReq *req, ClientPtr client) + * Given a pointer to a *complete* request, return its length in bytes. + * Note that if the request is a big request (as defined in the Big + * Requests extension), the macro lies by returning 4 less than the + * length that it actually occupies in the request buffer. This is so you + * can blindly compare the length with the various sz_ constants + * in Xproto.h without having to know/care about big requests. + */ +#define ReqLen(_pxReq, _client) \ + ((_pxReq->length ? \ + (_client->swapped ? lswaps(_pxReq->length) : _pxReq->length) \ + : ((_client->swapped ? \ + lswapl(((CARD32*)_pxReq)[1]) : ((CARD32*)_pxReq)[1])-1) \ + ) << 2) + +/* otherReqTypePtr CastxReq(xReq *req, otherReqTypePtr) + * Cast the given request to one of type otherReqTypePtr to access + * fields beyond the length field. + */ +#define CastxReq(_pxReq, otherReqTypePtr) \ + (_pxReq->length ? (otherReqTypePtr)_pxReq \ + : (otherReqTypePtr)(((CARD32*)_pxReq)+1)) + +/* stuff for SkippedRequestsCallback */ +extern CallbackListPtr SkippedRequestsCallback; +typedef struct { + xReqPtr req; + ClientPtr client; + int numskipped; +} SkippedRequestInfoRec; + +/* stuff for ReplyCallback */ +extern CallbackListPtr ReplyCallback; +typedef struct { + ClientPtr client; + pointer replyData; + unsigned long dataLenBytes; + unsigned long bytesRemaining; + Bool startOfReply; +} ReplyInfoRec; + +/* stuff for FlushCallback */ +extern CallbackListPtr FlushCallback; + +#endif /* OS_H */ diff --git a/include/pixmap.h b/include/pixmap.h new file mode 100644 index 000000000..766091046 --- /dev/null +++ b/include/pixmap.h @@ -0,0 +1,123 @@ +/* $Xorg: pixmap.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef PIXMAP_H +#define PIXMAP_H + +#include "misc.h" +#include "screenint.h" + +/* types for Drawable */ +#define DRAWABLE_WINDOW 0 +#define DRAWABLE_PIXMAP 1 +#define UNDRAWABLE_WINDOW 2 +#define DRAWABLE_BUFFER 3 + +/* flags to PaintWindow() */ +#define PW_BACKGROUND 0 +#define PW_BORDER 1 + +#define NullPixmap ((PixmapPtr)0) + +typedef struct _Drawable *DrawablePtr; +typedef struct _Pixmap *PixmapPtr; + +typedef union _PixUnion { + PixmapPtr pixmap; + unsigned long pixel; +} PixUnion; + +#define SamePixUnion(a,b,isPixel)\ + ((isPixel) ? (a).pixel == (b).pixel : (a).pixmap == (b).pixmap) + +#define EqualPixUnion(as, a, bs, b) \ + ((as) == (bs) && (SamePixUnion (a, b, as))) + +#define OnScreenDrawable(type) \ + ((type == DRAWABLE_WINDOW) || (type == DRAWABLE_BUFFER)) + +#define WindowDrawable(type) \ + ((type == DRAWABLE_WINDOW) || (type == UNDRAWABLE_WINDOW)) + +extern PixmapPtr GetScratchPixmapHeader( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int /*width*/, + int /*height*/, + int /*depth*/, + int /*bitsPerPixel*/, + int /*devKind*/, + pointer /*pPixData*/ +#endif +); + +extern void FreeScratchPixmapHeader( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/ +#endif +); + +extern Bool CreateScratchPixmapsForScreen( +#if NeedFunctionPrototypes + int /*scrnum*/ +#endif +); + +extern void FreeScratchPixmapsForScreen( +#if NeedFunctionPrototypes + int /*scrnum*/ +#endif +); + +extern PixmapPtr AllocatePixmap( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int /*pixDataSize*/ +#endif +); + +#endif /* PIXMAP_H */ diff --git a/include/pixmapstr.h b/include/pixmapstr.h new file mode 100644 index 000000000..d84ae79fc --- /dev/null +++ b/include/pixmapstr.h @@ -0,0 +1,83 @@ +/* $Xorg: pixmapstr.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#ifndef PIXMAPSTRUCT_H +#define PIXMAPSTRUCT_H +#include "pixmap.h" +#include "screenint.h" +#include "miscstruct.h" + +typedef struct _Drawable { + unsigned char type; /* DRAWABLE_ */ + unsigned char class; /* specific to type */ + unsigned char depth; + unsigned char bitsPerPixel; + unsigned long id; /* resource id */ + short x; /* window: screen absolute, pixmap: 0 */ + short y; /* window: screen absolute, pixmap: 0 */ + unsigned short width; + unsigned short height; + ScreenPtr pScreen; + unsigned long serialNumber; +} DrawableRec; + +/* + * PIXMAP -- device dependent + */ + +typedef struct _Pixmap { + DrawableRec drawable; + int refcnt; + int devKind; + DevUnion devPrivate; +#ifdef PIXPRIV + DevUnion *devPrivates; /* real devPrivates like gcs & windows */ +#endif +} PixmapRec; + +#endif /* PIXMAPSTRUCT_H */ diff --git a/include/property.h b/include/property.h new file mode 100644 index 000000000..a5dfbc914 --- /dev/null +++ b/include/property.h @@ -0,0 +1,78 @@ +/* $Xorg: property.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef PROPERTY_H +#define PROPERTY_H +typedef struct _Property *PropertyPtr; + +extern int ChangeWindowProperty( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + Atom /*property*/, + Atom /*type*/, + int /*format*/, + int /*mode*/, + unsigned long /*len*/, + pointer /*value*/, + Bool /*sendevent*/ +#endif +); + +extern int DeleteProperty( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + Atom /*propName*/ +#endif +); + +extern void DeleteAllWindowProperties( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +#endif /* PROPERTY_H */ diff --git a/include/propertyst.h b/include/propertyst.h new file mode 100644 index 000000000..b704b61fb --- /dev/null +++ b/include/propertyst.h @@ -0,0 +1,74 @@ +/* $Xorg: propertyst.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef PROPERTYSTRUCT_H +#define PROPERTYSTRUCT_H +#include "misc.h" +#include "property.h" +/* + * PROPERTY -- property element + */ + +typedef struct _Property { + struct _Property *next; + ATOM propertyName; + ATOM type; /* ignored by server */ + short format; /* format of data for swapping - 8,16,32 */ + long size; /* size of data in (format/8) bytes */ + pointer data; /* private to client */ +#ifdef LBX + /* If space is at a premium and binary compatibility is not + * an issue, you may want to put the owner_pid next to format + * so that the two shorts pack together without padding. + */ + short owner_pid; /* proxy that has the data */ + XID tag_id; +#endif +} PropertyRec; + +#endif /* PROPERTYSTRUCT_H */ + diff --git a/include/region.h b/include/region.h new file mode 100644 index 000000000..64f0ff444 --- /dev/null +++ b/include/region.h @@ -0,0 +1,53 @@ +/* $Xorg: region.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef REGION_H +#define REGION_H + +#include "regionstr.h" + +#endif /* REGION_H */ diff --git a/include/regionstr.h b/include/regionstr.h new file mode 100644 index 000000000..55dc99656 --- /dev/null +++ b/include/regionstr.h @@ -0,0 +1,408 @@ +/* $Xorg: regionstr.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef REGIONSTRUCT_H +#define REGIONSTRUCT_H + +#include "miscstruct.h" + +/* Return values from RectIn() */ + +#define rgnOUT 0 +#define rgnIN 1 +#define rgnPART 2 + +#define NullRegion ((RegionPtr)0) + +/* + * clip region + */ + +typedef struct _RegData { + long size; + long numRects; +/* BoxRec rects[size]; in memory but not explicitly declared */ +} RegDataRec, *RegDataPtr; + +typedef struct _Region { + BoxRec extents; + RegDataPtr data; +} RegionRec, *RegionPtr; + +extern BoxRec miEmptyBox; +extern RegDataRec miEmptyData; + +#define REGION_NIL(reg) ((reg)->data && !(reg)->data->numRects) +#define REGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1) +#define REGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0) +#define REGION_RECTS(reg) ((reg)->data ? (BoxPtr)((reg)->data + 1) \ + : &(reg)->extents) +#define REGION_BOXPTR(reg) ((BoxPtr)((reg)->data + 1)) +#define REGION_BOX(reg,i) (®ION_BOXPTR(reg)[i]) +#define REGION_TOP(reg) REGION_BOX(reg, (reg)->data->numRects) +#define REGION_END(reg) REGION_BOX(reg, (reg)->data->numRects - 1) +#define REGION_SZOF(n) (sizeof(RegDataRec) + ((n) * sizeof(BoxRec))) + +#ifdef NEED_SCREEN_REGIONS + +#define REGION_CREATE(_pScreen, _rect, _size) \ + (*(_pScreen)->RegionCreate)(_rect, _size) + +#define REGION_INIT(_pScreen, _pReg, _rect, _size) \ + (*(_pScreen)->RegionInit)(_pReg, _rect, _size) + +#define REGION_COPY(_pScreen, dst, src) \ + (*(_pScreen)->RegionCopy)(dst, src) + +#define REGION_DESTROY(_pScreen, _pReg) \ + (*(_pScreen)->RegionDestroy)(_pReg) + +#define REGION_UNINIT(_pScreen, _pReg) \ + (*(_pScreen)->RegionUninit)(_pReg) + +#define REGION_INTERSECT(_pScreen, newReg, reg1, reg2) \ + (*(_pScreen)->Intersect)(newReg, reg1, reg2) + +#define REGION_UNION(_pScreen, newReg, reg1, reg2) \ + (*(_pScreen)->Union)(newReg, reg1, reg2) + +#define REGION_SUBTRACT(_pScreen, newReg, reg1, reg2) \ + (*(_pScreen)->Subtract)(newReg, reg1, reg2) + +#define REGION_INVERSE(_pScreen, newReg, reg1, invRect) \ + (*(_pScreen)->Inverse)(newReg, reg1, invRect) + +#define REGION_RESET(_pScreen, _pReg, _pBox) \ + (*(_pScreen)->RegionReset)(_pReg, _pBox) + +#define REGION_TRANSLATE(_pScreen, _pReg, _x, _y) \ + (*(_pScreen)->TranslateRegion)(_pReg, _x, _y) + +#define RECT_IN_REGION(_pScreen, _pReg, prect) \ + (*(_pScreen)->RectIn)(_pReg, prect) + +#define POINT_IN_REGION(_pScreen, _pReg, _x, _y, prect) \ + (*(_pScreen)->PointInRegion)(_pReg, _x, _y, prect) + +#define REGION_NOTEMPTY(_pScreen, _pReg) \ + (*(_pScreen)->RegionNotEmpty)(_pReg) + +#define REGION_EMPTY(_pScreen, _pReg) \ + (*(_pScreen)->RegionEmpty)(_pReg) + +#define REGION_EXTENTS(_pScreen, _pReg) \ + (*(_pScreen)->RegionExtents)(_pReg) + +#define REGION_APPEND(_pScreen, dstrgn, rgn) \ + (*(_pScreen)->RegionAppend)(dstrgn, rgn) + +#define REGION_VALIDATE(_pScreen, badreg, pOverlap) \ + (*(_pScreen)->RegionValidate)(badreg, pOverlap) + +#define BITMAP_TO_REGION(_pScreen, pPix) \ + (*(_pScreen)->BitmapToRegion)(pPix) + +#define RECTS_TO_REGION(_pScreen, nrects, prect, ctype) \ + (*(_pScreen)->RectsToRegion)(nrects, prect, ctype) + +#else /* !NEED_SCREEN_REGIONS */ + +#define REGION_CREATE(_pScreen, _rect, _size) \ + miRegionCreate(_rect, _size) + +#define REGION_COPY(_pScreen, dst, src) \ + miRegionCopy(dst, src) + +#define REGION_DESTROY(_pScreen, _pReg) \ + miRegionDestroy(_pReg) + +#define REGION_INTERSECT(_pScreen, newReg, reg1, reg2) \ + miIntersect(newReg, reg1, reg2) + +#define REGION_UNION(_pScreen, newReg, reg1, reg2) \ + miUnion(newReg, reg1, reg2) + +#define REGION_SUBTRACT(_pScreen, newReg, reg1, reg2) \ + miSubtract(newReg, reg1, reg2) + +#define REGION_INVERSE(_pScreen, newReg, reg1, invRect) \ + miInverse(newReg, reg1, invRect) + +#define REGION_TRANSLATE(_pScreen, _pReg, _x, _y) \ + miTranslateRegion(_pReg, _x, _y) + +#define RECT_IN_REGION(_pScreen, _pReg, prect) \ + miRectIn(_pReg, prect) + +#define POINT_IN_REGION(_pScreen, _pReg, _x, _y, prect) \ + miPointInRegion(_pReg, _x, _y, prect) + +#define REGION_APPEND(_pScreen, dstrgn, rgn) \ + miRegionAppend(dstrgn, rgn) + +#define REGION_VALIDATE(_pScreen, badreg, pOverlap) \ + miRegionValidate(badreg, pOverlap) + +#define BITMAP_TO_REGION(_pScreen, pPix) \ + (*(_pScreen)->BitmapToRegion)(pPix) /* no mi version?! */ + +#define RECTS_TO_REGION(_pScreen, nrects, prect, ctype) \ + miRectsToRegion(nrects, prect, ctype) + +#ifdef DONT_INLINE_REGION_OPS + +#define REGION_INIT(_pScreen, _pReg, _rect, _size) \ + miRegionInit(_pReg, _rect, _size) + +#define REGION_UNINIT(_pScreen, _pReg) \ + miRegionUninit(_pReg) + +#define REGION_RESET(_pScreen, _pReg, _pBox) \ + miRegionReset(_pReg, _pBox) + +#define REGION_NOTEMPTY(_pScreen, _pReg) \ + miRegionNotEmpty(_pReg) + +#define REGION_EMPTY(_pScreen, _pReg) \ + miRegionEmpty(_pReg) + +#define REGION_EXTENTS(_pScreen, _pReg) \ + miRegionExtents(_pReg) + +#else /* inline certain simple region ops for performance */ + +#define REGION_INIT(_pScreen, _pReg, _rect, _size) \ +{ \ + if (_rect) \ + { \ + (_pReg)->extents = *(_rect); \ + (_pReg)->data = (RegDataPtr)NULL; \ + } \ + else \ + { \ + (_pReg)->extents = miEmptyBox; \ + if (((_size) > 1) && ((_pReg)->data = \ + (RegDataPtr)xalloc(REGION_SZOF(_size)))) \ + { \ + (_pReg)->data->size = (_size); \ + (_pReg)->data->numRects = 0; \ + } \ + else \ + (_pReg)->data = &miEmptyData; \ + } \ +} + +#define REGION_UNINIT(_pScreen, _pReg) \ +{ \ + if ((_pReg)->data && (_pReg)->data->size) xfree((_pReg)->data); \ +} + +#define REGION_RESET(_pScreen, _pReg, _pBox) \ +{ \ + (_pReg)->extents = *(_pBox); \ + REGION_UNINIT(_pScreen, _pReg); \ + (_pReg)->data = (RegDataPtr)NULL; \ +} + +#define REGION_NOTEMPTY(_pScreen, _pReg) \ + !REGION_NIL(_pReg) + +#define REGION_EMPTY(_pScreen, _pReg) \ +{ \ + REGION_UNINIT(_pScreen, _pReg); \ + (_pReg)->extents.x2 = (_pReg)->extents.x1; \ + (_pReg)->extents.y2 = (_pReg)->extents.y1; \ + (_pReg)->data = &miEmptyData; \ +} + +#define REGION_EXTENTS(_pScreen, _pReg) \ + &(_pReg)->extents + +#endif /* DONT_INLINE_REGION_OPS */ + +#endif /* NEED_SCREEN_REGIONS */ + +/* moved from mi.h */ + +extern RegionPtr miRegionCreate( +#if NeedFunctionPrototypes + BoxPtr /*rect*/, + int /*size*/ +#endif +); + +extern void miRegionInit( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/, + BoxPtr /*rect*/, + int /*size*/ +#endif +); + +extern void miRegionDestroy( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/ +#endif +); + +extern void miRegionUninit( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/ +#endif +); + +extern Bool miRegionCopy( +#if NeedFunctionPrototypes + RegionPtr /*dst*/, + RegionPtr /*src*/ +#endif +); + +extern Bool miIntersect( +#if NeedFunctionPrototypes + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + RegionPtr /*reg2*/ +#endif +); + +extern Bool miUnion( +#if NeedFunctionPrototypes + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + RegionPtr /*reg2*/ +#endif +); + +extern Bool miRegionAppend( +#if NeedFunctionPrototypes + RegionPtr /*dstrgn*/, + RegionPtr /*rgn*/ +#endif +); + +extern Bool miRegionValidate( +#if NeedFunctionPrototypes + RegionPtr /*badreg*/, + Bool * /*pOverlap*/ +#endif +); + +extern RegionPtr miRectsToRegion( +#if NeedFunctionPrototypes + int /*nrects*/, + xRectanglePtr /*prect*/, + int /*ctype*/ +#endif +); + +extern Bool miSubtract( +#if NeedFunctionPrototypes + RegionPtr /*regD*/, + RegionPtr /*regM*/, + RegionPtr /*regS*/ +#endif +); + +extern Bool miInverse( +#if NeedFunctionPrototypes + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + BoxPtr /*invRect*/ +#endif +); + +extern int miRectIn( +#if NeedFunctionPrototypes + RegionPtr /*region*/, + BoxPtr /*prect*/ +#endif +); + +extern void miTranslateRegion( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/, + int /*x*/, + int /*y*/ +#endif +); + +extern void miRegionReset( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/, + BoxPtr /*pBox*/ +#endif +); + +extern Bool miPointInRegion( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/, + int /*x*/, + int /*y*/, + BoxPtr /*box*/ +#endif +); + +extern Bool miRegionNotEmpty( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/ +#endif +); + +extern void miRegionEmpty( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/ +#endif +); + +extern BoxPtr miRegionExtents( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/ +#endif +); + +#endif /* REGIONSTRUCT_H */ diff --git a/include/resource.h b/include/resource.h new file mode 100644 index 000000000..537093061 --- /dev/null +++ b/include/resource.h @@ -0,0 +1,281 @@ +/* $Xorg: resource.h,v 1.5 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef RESOURCE_H +#define RESOURCE_H 1 +#include "misc.h" + +/***************************************************************** + * STUFF FOR RESOURCES + *****************************************************************/ + +/* classes for Resource routines */ + +typedef unsigned long RESTYPE; + +#define RC_VANILLA ((RESTYPE)0) +#define RC_CACHED ((RESTYPE)1<<31) +#define RC_DRAWABLE ((RESTYPE)1<<30) +/* Use class RC_NEVERRETAIN for resources that should not be retained + * regardless of the close down mode when the client dies. (A client's + * event selections on objects that it doesn't own are good candidates.) + * Extensions can use this too! + */ +#define RC_NEVERRETAIN ((RESTYPE)1<<29) +#define RC_LASTPREDEF RC_NEVERRETAIN +#define RC_ANY (~(RESTYPE)0) + +/* types for Resource routines */ + +#define RT_WINDOW ((RESTYPE)1|RC_CACHED|RC_DRAWABLE) +#define RT_PIXMAP ((RESTYPE)2|RC_CACHED|RC_DRAWABLE) +#define RT_GC ((RESTYPE)3|RC_CACHED) +#define RT_FONT ((RESTYPE)4) +#define RT_CURSOR ((RESTYPE)5) +#define RT_COLORMAP ((RESTYPE)6) +#define RT_CMAPENTRY ((RESTYPE)7) +#define RT_OTHERCLIENT ((RESTYPE)8|RC_NEVERRETAIN) +#define RT_PASSIVEGRAB ((RESTYPE)9|RC_NEVERRETAIN) +#define RT_LASTPREDEF ((RESTYPE)9) +#define RT_NONE ((RESTYPE)0) + +/* bits and fields within a resource id */ +#define CLIENTOFFSET 22 /* client field */ +#define RESOURCE_ID_MASK 0x3FFFFF /* low 22 bits */ +#define CLIENT_BITS(id) ((id) & 0x3fc00000) /* next 8 bits */ +#define CLIENT_ID(id) ((int)(CLIENT_BITS(id) >> CLIENTOFFSET)) +#define SERVER_BIT 0x40000000 /* use illegal bit */ + +#ifdef INVALID +#undef INVALID /* needed on HP/UX */ +#endif + +/* Invalid resource id */ +#define INVALID (0) + +#define BAD_RESOURCE 0xe0000000 + +typedef int (*DeleteType)( +#if NeedNestedPrototypes + pointer /*value*/, + XID /*id*/ +#endif +); + +typedef void (*FindResType)( +#if NeedNestedPrototypes + pointer /*value*/, + XID /*id*/, + pointer /*cdata*/ +#endif +); + +extern RESTYPE CreateNewResourceType( +#if NeedFunctionPrototypes + DeleteType /*deleteFunc*/ +#endif +); + +extern RESTYPE CreateNewResourceClass( +#if NeedFunctionPrototypes +void +#endif +); + +extern Bool InitClientResources( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern XID FakeClientID( +#if NeedFunctionPrototypes + int /*client*/ +#endif +); + +extern Bool AddResource( +#if NeedFunctionPrototypes + XID /*id*/, + RESTYPE /*type*/, + pointer /*value*/ +#endif +); + +extern void FreeResource( +#if NeedFunctionPrototypes + XID /*id*/, + RESTYPE /*skipDeleteFuncType*/ +#endif +); + +extern void FreeResourceByType( +#if NeedFunctionPrototypes + XID /*id*/, + RESTYPE /*type*/, + Bool /*skipFree*/ +#endif +); + +extern Bool ChangeResourceValue( +#if NeedFunctionPrototypes + XID /*id*/, + RESTYPE /*rtype*/, + pointer /*value*/ +#endif +); + +extern void FindClientResourcesByType( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + RESTYPE /*type*/, + FindResType /*func*/, + pointer /*cdata*/ +#endif +); + +extern void FreeClientNeverRetainResources( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void FreeClientResources( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern void FreeAllResources( +#if NeedFunctionPrototypes +void +#endif +); + +extern Bool LegalNewID( +#if NeedFunctionPrototypes + XID /*id*/, + ClientPtr /*client*/ +#endif +); + +extern pointer LookupIDByType( +#if NeedFunctionPrototypes + XID /*id*/, + RESTYPE /*rtype*/ +#endif +); + +extern pointer LookupIDByClass( +#if NeedFunctionPrototypes + XID /*id*/, + RESTYPE /*classes*/ +#endif +); + +/* These are the access modes that can be passed in the last parameter + * to SecurityLookupIDByType/Class. The Security extension doesn't + * currently make much use of these; they're mainly provided as an + * example of what you might need for discretionary access control. + * You can or these values together to indicate multiple modes + * simultaneously. + */ + +#define SecurityUnknownAccess 0 /* don't know intentions */ +#define SecurityReadAccess (1<<0) /* inspecting the object */ +#define SecurityWriteAccess (1<<1) /* changing the object */ +#define SecurityDestroyAccess (1<<2) /* destroying the object */ + +#ifdef XCSECURITY + +extern pointer SecurityLookupIDByType( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + XID /*id*/, + RESTYPE /*rtype*/, + Mask /*access_mode*/ +#endif +); + +extern pointer SecurityLookupIDByClass( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + XID /*id*/, + RESTYPE /*classes*/, + Mask /*access_mode*/ +#endif +); + +#else /* not XCSECURITY */ + +#define SecurityLookupIDByType(client, id, rtype, access_mode) \ + LookupIDByType(id, rtype) + +#define SecurityLookupIDByClass(client, id, classes, access_mode) \ + LookupIDByClass(id, classes) + +#endif /* XCSECURITY */ + +extern void GetXIDRange( +#if NeedFunctionPrototypes + int /*client*/, + Bool /*server*/, + XID * /*minp*/, + XID * /*maxp*/ +#endif +); + +extern unsigned int GetXIDList( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + unsigned int /*count*/, + XID * /*pids*/ +#endif +); + +#endif /* RESOURCE_H */ + diff --git a/include/rgb.h b/include/rgb.h new file mode 100644 index 000000000..5741a4efa --- /dev/null +++ b/include/rgb.h @@ -0,0 +1,54 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: rgb.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ + +#ifndef RGB_H +#define RGB_H +typedef struct _RGB { + unsigned short red, green, blue; + } RGB; +#endif /* RGB_H */ diff --git a/include/screenint.h b/include/screenint.h new file mode 100644 index 000000000..f4eb79725 --- /dev/null +++ b/include/screenint.h @@ -0,0 +1,164 @@ +/* $Xorg: screenint.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef SCREENINT_H +#define SCREENINT_H + +#include "misc.h" + +typedef struct _PixmapFormat *PixmapFormatPtr; +typedef struct _Visual *VisualPtr; +typedef struct _Depth *DepthPtr; +typedef struct _Screen *ScreenPtr; + +extern void ResetScreenPrivates( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AllocateScreenPrivateIndex( +#if NeedFunctionPrototypes + void +#endif +); + +extern void ResetWindowPrivates( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AllocateWindowPrivateIndex( +#if NeedFunctionPrototypes + void +#endif +); + +extern Bool AllocateWindowPrivate( +#if NeedFunctionPrototypes + ScreenPtr /* pScreen */, + int /* index */, + unsigned /* amount */ +#endif +); + +extern void ResetGCPrivates( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AllocateGCPrivateIndex( +#if NeedFunctionPrototypes + void +#endif +); + +extern Bool AllocateGCPrivate( +#if NeedFunctionPrototypes + ScreenPtr /* pScreen */, + int /* index */, + unsigned /* amount */ +#endif +); + +extern int AddScreen( +#if NeedFunctionPrototypes + Bool (* /*pfnInit*/)( +#if NeedNestedPrototypes + int /*index*/, + ScreenPtr /*pScreen*/, + int /*argc*/, + char ** /*argv*/ +#endif + ), + int /*argc*/, + char** /*argv*/ +#endif +); + +#ifdef PIXPRIV + +extern void ResetPixmapPrivates( +#if NeedFunctionPrototypes + void +#endif +); + +extern int AllocatePixmapPrivateIndex( +#if NeedFunctionPrototypes + void +#endif +); + +extern Bool AllocatePixmapPrivate( +#if NeedFunctionPrototypes + ScreenPtr /* pScreen */, + int /* index */, + unsigned /* amount */ +#endif +); + +#endif /* PIXPRIV */ + +extern void ResetColormapPrivates( +#if NeedFunctionPrototypes + void +#endif +); + + +typedef int (*InitCmapPrivFunc)(/* ColormapPtr */); + +extern int AllocateColormapPrivateIndex( +#if NeedFunctionPrototypes + InitCmapPrivFunc /* initPrivFunc */ +#endif +); + +#endif /* SCREENINT_H */ diff --git a/include/scrnintstr.h b/include/scrnintstr.h new file mode 100644 index 000000000..ea821c7ff --- /dev/null +++ b/include/scrnintstr.h @@ -0,0 +1,933 @@ +/* $Xorg: scrnintstr.h,v 1.4 2001/02/09 02:05:15 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef SCREENINTSTRUCT_H +#define SCREENINTSTRUCT_H + +#include "screenint.h" +#include "miscstruct.h" +#include "region.h" +#include "pixmap.h" +#include "gc.h" +#include "colormap.h" +#include "cursor.h" +#include "validate.h" +#include "window.h" +#include "X11/Xproto.h" +#include "dix.h" + +typedef struct _PixmapFormat { + unsigned char depth; + unsigned char bitsPerPixel; + unsigned char scanlinePad; + } PixmapFormatRec; + +typedef struct _Visual { + VisualID vid; + short class; + short bitsPerRGBValue; + short ColormapEntries; + short nplanes;/* = log2 (ColormapEntries). This does not + * imply that the screen has this many planes. + * it may have more or fewer */ + unsigned long redMask, greenMask, blueMask; + int offsetRed, offsetGreen, offsetBlue; + } VisualRec; + +typedef struct _Depth { + unsigned char depth; + short numVids; + VisualID *vids; /* block of visual ids for this depth */ + } DepthRec; + + +/* + * There is a typedef for each screen function pointer so that code that + * needs to declare a screen function pointer (e.g. in a screen private + * or as a local variable) can easily do so and retain full type checking. + */ + +typedef Bool (* CloseScreenProcPtr)( +#if NeedNestedPrototypes + int /*index*/, + ScreenPtr /*pScreen*/ +#endif +); + +typedef void (* QueryBestSizeProcPtr)( +#if NeedNestedPrototypes + int /*class*/, + unsigned short * /*pwidth*/, + unsigned short * /*pheight*/, + ScreenPtr /*pScreen*/ +#endif +); + +typedef Bool (* SaveScreenProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*on*/ +#endif +); + +typedef void (* GetImageProcPtr)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + int /*sx*/, + int /*sy*/, + int /*w*/, + int /*h*/, + unsigned int /*format*/, + unsigned long /*planeMask*/, + char * /*pdstLine*/ +#endif +); + +typedef void (* GetSpansProcPtr)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + int /*wMax*/, + DDXPointPtr /*ppt*/, + int* /*pwidth*/, + int /*nspans*/, + char * /*pdstStart*/ +#endif +); + +typedef void (* PointerNonInterestBoxProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + BoxPtr /*pBox*/ +#endif +); + +typedef void (* SourceValidateProcPtr)( +#if NeedNestedPrototypes + DrawablePtr /*pDrawable*/, + int /*x*/, + int /*y*/, + int /*width*/, + int /*height*/ +#endif +); + +typedef Bool (* CreateWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/ +#endif +); + +typedef Bool (* DestroyWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/ +#endif +); + +typedef Bool (* PositionWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + int /*x*/, + int /*y*/ +#endif +); + +typedef Bool (* ChangeWindowAttributesProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + unsigned long /*mask*/ +#endif +); + +typedef Bool (* RealizeWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/ +#endif +); + +typedef Bool (* UnrealizeWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/ +#endif +); + +typedef int (* ValidateTreeProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pParent*/, + WindowPtr /*pChild*/, + VTKind /*kind*/ +#endif +); + +typedef void (* PostValidateTreeProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pParent*/, + WindowPtr /*pChild*/, + VTKind /*kind*/ +#endif +); + +typedef void (* WindowExposuresProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + RegionPtr /*prgn*/, + RegionPtr /*other_exposed*/ +#endif +); + +typedef void (* PaintWindowBackgroundProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + RegionPtr /*pRegion*/, + int /*what*/ +#endif +); + +typedef void (* PaintWindowBorderProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + RegionPtr /*pRegion*/, + int /*what*/ +#endif +); + +typedef void (* CopyWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + DDXPointRec /*ptOldOrg*/, + RegionPtr /*prgnSrc*/ +#endif +); + +typedef void (* ClearToBackgroundProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + Bool /*generateExposures*/ +#endif +); + +typedef void (* ClipNotifyProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + int /*dx*/, + int /*dy*/ +#endif +); + +typedef PixmapPtr (* CreatePixmapProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*width*/, + int /*height*/, + int /*depth*/ +#endif +); + +typedef Bool (* DestroyPixmapProcPtr)( +#if NeedNestedPrototypes + PixmapPtr /*pPixmap*/ +#endif +); + +typedef void (* SaveDoomedAreasProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + RegionPtr /*prgnSave*/, + int /*xorg*/, + int /*yorg*/ +#endif +); + +typedef RegionPtr (* RestoreAreasProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + RegionPtr /*prgnRestore*/ +#endif +); + +typedef void (* ExposeCopyProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pSrc*/, + DrawablePtr /*pDst*/, + GCPtr /*pGC*/, + RegionPtr /*prgnExposed*/, + int /*srcx*/, + int /*srcy*/, + int /*dstx*/, + int /*dsty*/, + unsigned long /*plane*/ +#endif +); + +typedef RegionPtr (* TranslateBackingStoreProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + int /*windx*/, + int /*windy*/, + RegionPtr /*oldClip*/, + int /*oldx*/, + int /*oldy*/ +#endif +); + +typedef RegionPtr (* ClearBackingStoreProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + Bool /*generateExposures*/ +#endif +); + +typedef void (* DrawGuaranteeProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWindow*/, + GCPtr /*pGC*/, + int /*guarantee*/ +#endif +); + +typedef Bool (* RealizeFontProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + FontPtr /*pFont*/ +#endif +); + +typedef Bool (* UnrealizeFontProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + FontPtr /*pFont*/ +#endif +); + +typedef void (* ConstrainCursorProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + BoxPtr /*pBox*/ +#endif +); + +typedef void (* CursorLimitsProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/, + BoxPtr /*pHotBox*/, + BoxPtr /*pTopLeftBox*/ +#endif +); + +typedef Bool (* DisplayCursorProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/ +#endif +); + +typedef Bool (* RealizeCursorProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/ +#endif +); + +typedef Bool (* UnrealizeCursorProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/ +#endif +); + +typedef void (* RecolorCursorProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/, + Bool /*displayed*/ +#endif +); + +typedef Bool (* SetCursorPositionProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*x*/, + int /*y*/, + Bool /*generateEvent*/ +#endif +); + +typedef Bool (* CreateGCProcPtr)( +#if NeedNestedPrototypes + GCPtr /*pGC*/ +#endif +); + +typedef Bool (* CreateColormapProcPtr)( +#if NeedNestedPrototypes + ColormapPtr /*pColormap*/ +#endif +); + +typedef void (* DestroyColormapProcPtr)( +#if NeedNestedPrototypes + ColormapPtr /*pColormap*/ +#endif +); + +typedef void (* InstallColormapProcPtr)( +#if NeedNestedPrototypes + ColormapPtr /*pColormap*/ +#endif +); + +typedef void (* UninstallColormapProcPtr)( +#if NeedNestedPrototypes + ColormapPtr /*pColormap*/ +#endif +); + +typedef int (* ListInstalledColormapsProcPtr) ( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + XID* /*pmaps */ +#endif +); + +typedef void (* StoreColorsProcPtr)( +#if NeedNestedPrototypes + ColormapPtr /*pColormap*/, + int /*ndef*/, + xColorItem * /*pdef*/ +#endif +); + +typedef void (* ResolveColorProcPtr)( +#if NeedNestedPrototypes + unsigned short* /*pred*/, + unsigned short* /*pgreen*/, + unsigned short* /*pblue*/, + VisualPtr /*pVisual*/ +#endif +); + +typedef RegionPtr (* RegionCreateProcPtr)( +#if NeedNestedPrototypes + BoxPtr /*rect*/, + int /*size*/ +#endif +); + +typedef void (* RegionInitProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/, + BoxPtr /*rect*/, + int /*size*/ +#endif +); + +typedef Bool (* RegionCopyProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*dst*/, + RegionPtr /*src*/ +#endif +); + +typedef void (* RegionDestroyProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/ +#endif +); + +typedef void (* RegionUninitProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/ +#endif +); + +typedef Bool (* IntersectProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + RegionPtr /*reg2*/ +#endif +); + +typedef Bool (* UnionProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + RegionPtr /*reg2*/ +#endif +); + +typedef Bool (* SubtractProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*regD*/, + RegionPtr /*regM*/, + RegionPtr /*regS*/ +#endif +); + +typedef Bool (* InverseProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + BoxPtr /*invRect*/ +#endif +); + +typedef void (* RegionResetProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/, + BoxPtr /*pBox*/ +#endif +); + +typedef void (* TranslateRegionProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/, + int /*x*/, + int /*y*/ +#endif +); + +typedef int (* RectInProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*region*/, + BoxPtr /*prect*/ +#endif +); + +typedef Bool (* PointInRegionProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/, + int /*x*/, + int /*y*/, + BoxPtr /*box*/ +#endif +); + +typedef Bool (* RegionNotEmptyProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/ +#endif +); + +typedef void (* RegionEmptyProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/ +#endif +); + +typedef BoxPtr (* RegionExtentsProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*pReg*/ +#endif +); + +typedef Bool (* RegionAppendProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*dstrgn*/, + RegionPtr /*rgn*/ +#endif +); + +typedef Bool (* RegionValidateProcPtr)( +#if NeedNestedPrototypes + RegionPtr /*badreg*/, + Bool* /*pOverlap*/ +#endif +); + +typedef RegionPtr (* BitmapToRegionProcPtr)( +#if NeedNestedPrototypes + PixmapPtr /*pPix*/ +#endif +); + +typedef RegionPtr (* RectsToRegionProcPtr)( +#if NeedNestedPrototypes + int /*nrects*/, + xRectangle* /*prect*/, + int /*ctype*/ +#endif +); + +typedef void (* SendGraphicsExposeProcPtr)( +#if NeedNestedPrototypes + ClientPtr /*client*/, + RegionPtr /*pRgn*/, + XID /*drawable*/, + int /*major*/, + int /*minor*/ +#endif +); + +typedef void (* ScreenBlockHandlerProcPtr)( +#if NeedNestedPrototypes + int /*screenNum*/, + pointer /*blockData*/, + struct timeval ** /*pTimeout*/, + pointer /*pReadmask*/ +#endif +); + +typedef void (* ScreenWakeupHandlerProcPtr)( +#if NeedNestedPrototypes + int /*screenNum*/, + pointer /*wakeupData*/, + unsigned long /*result*/, + pointer /*pReadMask*/ +#endif +); + +typedef Bool (* CreateScreenResourcesProcPtr)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/ +#endif +); + +typedef Bool (* ModifyPixmapHeaderProcPtr)( +#if NeedNestedPrototypes + PixmapPtr /*pPixmap*/, + int /*width*/, + int /*height*/, + int /*depth*/, + int /*bitsPerPixel*/, + int /*devKind*/, + pointer /*pPixData*/ +#endif +); + +typedef void (* MarkWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/ +#endif +); + +typedef Bool (* MarkOverlappedWindowsProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*parent*/, + WindowPtr /*firstChild*/, + WindowPtr * /*pLayerWin*/ +#endif +); + +typedef Bool (* ChangeSaveUnderProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pLayerWin*/, + WindowPtr /*firstChild*/ +#endif +); + +typedef void (* PostChangeSaveUnderProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pLayerWin*/, + WindowPtr /*firstChild*/ +#endif +); + +typedef void (* MoveWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + WindowPtr /*pSib*/, + VTKind /*kind*/ +#endif +); + +typedef void (* ResizeWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + unsigned int /*w*/, + unsigned int /*h*/, + WindowPtr /*pSib*/ +#endif +); + +typedef WindowPtr (* GetLayerWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/ +#endif +); + +typedef void (* HandleExposuresProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/ +#endif +); + +typedef void (* ReparentWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/, + WindowPtr /*pPriorParent*/ +#endif +); + +#ifdef SHAPE +typedef void (* SetShapeProcPtr)( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); +#endif /* SHAPE */ + +typedef void (* ChangeBorderWidthProcPtr)( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + unsigned int /*width*/ +#endif +); + +typedef void (* MarkUnrealizedWindowProcPtr)( +#if NeedFunctionPrototypes + WindowPtr /*pChild*/, + WindowPtr /*pWin*/, + Bool /*fromConfigure*/ +#endif +); + +typedef struct _Screen { + int myNum; /* index of this instance in Screens[] */ + ATOM id; + short width, height; + short mmWidth, mmHeight; + short numDepths; + unsigned char rootDepth; + DepthPtr allowedDepths; + unsigned long rootVisual; + unsigned long defColormap; + short minInstalledCmaps, maxInstalledCmaps; + char backingStoreSupport, saveUnderSupport; + unsigned long whitePixel, blackPixel; + unsigned long rgf; /* array of flags; she's -- HUNGARIAN */ + GCPtr GCperDepth[MAXFORMATS+1]; + /* next field is a stipple to use as default in + a GC. we don't build default tiles of all depths + because they are likely to be of a color + different from the default fg pixel, so + we don't win anything by building + a standard one. + */ + PixmapPtr PixmapPerDepth[1]; + pointer devPrivate; + short numVisuals; + VisualPtr visuals; + int WindowPrivateLen; + unsigned *WindowPrivateSizes; + unsigned totalWindowSize; + int GCPrivateLen; + unsigned *GCPrivateSizes; + unsigned totalGCSize; + + /* Random screen procedures */ + + CloseScreenProcPtr CloseScreen; + QueryBestSizeProcPtr QueryBestSize; + SaveScreenProcPtr SaveScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + PointerNonInterestBoxProcPtr PointerNonInterestBox; + SourceValidateProcPtr SourceValidate; + + /* Window Procedures */ + + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + PositionWindowProcPtr PositionWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + ValidateTreeProcPtr ValidateTree; + PostValidateTreeProcPtr PostValidateTree; + WindowExposuresProcPtr WindowExposures; + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + ClearToBackgroundProcPtr ClearToBackground; + ClipNotifyProcPtr ClipNotify; + + /* Pixmap procedures */ + + CreatePixmapProcPtr CreatePixmap; + DestroyPixmapProcPtr DestroyPixmap; + + /* Backing store procedures */ + + SaveDoomedAreasProcPtr SaveDoomedAreas; + RestoreAreasProcPtr RestoreAreas; + ExposeCopyProcPtr ExposeCopy; + TranslateBackingStoreProcPtr TranslateBackingStore; + ClearBackingStoreProcPtr ClearBackingStore; + DrawGuaranteeProcPtr DrawGuarantee; + + /* Font procedures */ + + RealizeFontProcPtr RealizeFont; + UnrealizeFontProcPtr UnrealizeFont; + + /* Cursor Procedures */ + + ConstrainCursorProcPtr ConstrainCursor; + CursorLimitsProcPtr CursorLimits; + DisplayCursorProcPtr DisplayCursor; + RealizeCursorProcPtr RealizeCursor; + UnrealizeCursorProcPtr UnrealizeCursor; + RecolorCursorProcPtr RecolorCursor; + SetCursorPositionProcPtr SetCursorPosition; + + /* GC procedures */ + + CreateGCProcPtr CreateGC; + + /* Colormap procedures */ + + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + UninstallColormapProcPtr UninstallColormap; + ListInstalledColormapsProcPtr ListInstalledColormaps; + StoreColorsProcPtr StoreColors; + ResolveColorProcPtr ResolveColor; + + /* Region procedures */ + + RegionCreateProcPtr RegionCreate; + RegionInitProcPtr RegionInit; + RegionCopyProcPtr RegionCopy; + RegionDestroyProcPtr RegionDestroy; + RegionUninitProcPtr RegionUninit; + IntersectProcPtr Intersect; + UnionProcPtr Union; + SubtractProcPtr Subtract; + InverseProcPtr Inverse; + RegionResetProcPtr RegionReset; + TranslateRegionProcPtr TranslateRegion; + RectInProcPtr RectIn; + PointInRegionProcPtr PointInRegion; + RegionNotEmptyProcPtr RegionNotEmpty; + RegionEmptyProcPtr RegionEmpty; + RegionExtentsProcPtr RegionExtents; + RegionAppendProcPtr RegionAppend; + RegionValidateProcPtr RegionValidate; + BitmapToRegionProcPtr BitmapToRegion; + RectsToRegionProcPtr RectsToRegion; + SendGraphicsExposeProcPtr SendGraphicsExpose; + + /* os layer procedures */ + + ScreenBlockHandlerProcPtr BlockHandler; + ScreenWakeupHandlerProcPtr WakeupHandler; + + pointer blockData; + pointer wakeupData; + + /* anybody can get a piece of this array */ + DevUnion *devPrivates; + + CreateScreenResourcesProcPtr CreateScreenResources; + ModifyPixmapHeaderProcPtr ModifyPixmapHeader; + + PixmapPtr pScratchPixmap; /* scratch pixmap "pool" */ + +#ifdef PIXPRIV + int PixmapPrivateLen; + unsigned *PixmapPrivateSizes; + unsigned totalPixmapSize; +#endif + + MarkWindowProcPtr MarkWindow; + MarkOverlappedWindowsProcPtr MarkOverlappedWindows; + ChangeSaveUnderProcPtr ChangeSaveUnder; + PostChangeSaveUnderProcPtr PostChangeSaveUnder; + MoveWindowProcPtr MoveWindow; + ResizeWindowProcPtr ResizeWindow; + GetLayerWindowProcPtr GetLayerWindow; + HandleExposuresProcPtr HandleExposures; + ReparentWindowProcPtr ReparentWindow; + +#ifdef SHAPE + SetShapeProcPtr SetShape; +#endif /* SHAPE */ + + ChangeBorderWidthProcPtr ChangeBorderWidth; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + +} ScreenRec; + +typedef struct _ScreenInfo { + int imageByteOrder; + int bitmapScanlineUnit; + int bitmapScanlinePad; + int bitmapBitOrder; + int numPixmapFormats; + PixmapFormatRec + formats[MAXFORMATS]; + int arraySize; + int numScreens; + ScreenPtr screens[MAXSCREENS]; + int numVideoScreens; +} ScreenInfo; + +extern ScreenInfo screenInfo; + +extern void InitOutput( +#if NeedFunctionPrototypes + ScreenInfo * /*pScreenInfo*/, + int /*argc*/, + char ** /*argv*/ +#endif +); + +#endif /* SCREENINTSTRUCT_H */ diff --git a/include/selection.h b/include/selection.h new file mode 100644 index 000000000..520cfd4aa --- /dev/null +++ b/include/selection.h @@ -0,0 +1,68 @@ +/* $Xorg: selection.h,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ +#ifndef SELECTION_H +#define SELECTION_H 1 + +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "dixstruct.h" +/* + * + * Selection data structures + */ + +typedef struct _Selection { + Atom selection; + TimeStamp lastTimeChanged; + Window window; + WindowPtr pWin; + ClientPtr client; +} Selection; + +#endif /* SELECTION_H */ + + diff --git a/include/servermd.h b/include/servermd.h new file mode 100644 index 000000000..eb6b7b272 --- /dev/null +++ b/include/servermd.h @@ -0,0 +1,483 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef SERVERMD_H +#define SERVERMD_H 1 +/* $Xorg: servermd.h,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ + +/* + * Machine dependent values: + * GLYPHPADBYTES should be chosen with consideration for the space-time + * trade-off. Padding to 0 bytes means that there is no wasted space + * in the font bitmaps (both on disk and in memory), but that access of + * the bitmaps will cause odd-address memory references. Padding to + * 2 bytes would ensure even address memory references and would + * be suitable for a 68010-class machine, but at the expense of wasted + * space in the font bitmaps. Padding to 4 bytes would be good + * for real 32 bit machines, etc. Be sure that you tell the font + * compiler what kind of padding you want because its defines are + * kept separate from this. See server/include/font.h for how + * GLYPHPADBYTES is used. + * + * Along with this, you should choose an appropriate value for + * GETLEFTBITS_ALIGNMENT, which is used in ddx/mfb/maskbits.h. This + * constant choses what kind of memory references are guarenteed during + * font access; either 1, 2 or 4, for byte, word or longword access, + * respectively. For instance, if you have decided to to have + * GLYPHPADBYTES == 4, then it is pointless for you to have a + * GETLEFTBITS_ALIGNMENT > 1, because the padding of the fonts has already + * guarenteed you that your fonts are longword aligned. On the other + * hand, even if you have chosen GLYPHPADBYTES == 1 to save space, you may + * also decide that the computing involved in aligning the pointer is more + * costly than an odd-address access; you choose GETLEFTBITS_ALIGNMENT == 1. + * + * Next, choose the tuning parameters which are appropriate for your + * hardware; these modify the behaviour of the raw frame buffer code + * in ddx/mfb and ddx/cfb. Defining these incorrectly will not cause + * the server to run incorrectly, but defining these correctly will + * cause some noticeable speed improvements: + * + * AVOID_MEMORY_READ - (8-bit cfb only) + * When stippling pixels on the screen (polytext and pushpixels), + * don't read long words from the display and mask in the + * appropriate values. Rather, perform multiple byte/short/long + * writes as appropriate. This option uses many more instructions + * but runs much faster when the destination is much slower than + * the CPU and at least 1 level of write buffer is availible (2 + * is much better). Defined currently for SPARC and MIPS. + * + * FAST_CONSTANT_OFFSET_MODE - (cfb and mfb) + * This define is used on machines which have no auto-increment + * addressing mode, but do have an effectively free constant-offset + * addressing mode. Currently defined for MIPS and SPARC, even though + * I remember the cg6 as performing better without it (cg3 definitely + * performs better with it). + * + * LARGE_INSTRUCTION_CACHE - + * This define increases the number of times some loops are + * unrolled. On 68020 machines (with 256 bytes of i-cache), + * this define will slow execution down as instructions miss + * the cache frequently. On machines with real i-caches, this + * reduces loop overhead, causing a slight performance improvement. + * Currently defined for MIPS and SPARC + * + * FAST_UNALIGNED_READS - + * For machines with more memory bandwidth than CPU, this + * define uses unaligned reads for 8-bit BitBLT instead of doing + * aligned reads and combining the results with shifts and + * logical-ors. Currently defined for 68020 and vax. + * PLENTIFUL_REGISTERS - + * For machines with > 20 registers. Currently used for + * unrolling the text painting code a bit more. Currently + * defined for MIPS. + * SHARED_IDCACHE - + * For non-Harvard RISC machines, those which share the same + * CPU memory bus for instructions and data. This unrolls some + * solid fill loops which are otherwise best left rolled up. + * Currently defined for SPARC. + */ + +#ifdef vax + +#define IMAGE_BYTE_ORDER LSBFirst /* Values for the VAX only */ +#define BITMAP_BIT_ORDER LSBFirst +#define GLYPHPADBYTES 1 +#define GETLEFTBITS_ALIGNMENT 4 +#define FAST_UNALIGNED_READS + +#endif /* vax */ + +#if (defined(sun) && !(defined(i386) && defined(SVR4))) || \ + (defined(AMOEBA) && (defined(sparc) || defined(mc68000))) || \ + (defined(__uxp__) && (defined(sparc) || defined(mc68000))) || \ + (defined(Lynx) && defined(__sparc__)) || \ + ((defined(__NetBSD__) || defined(__OpenBSD__)) && \ + (defined(__sparc__) || defined(__mc68000__))) + +#if defined(sun386) || defined(sun5) +# define IMAGE_BYTE_ORDER LSBFirst /* Values for the SUN only */ +# define BITMAP_BIT_ORDER LSBFirst +#else +# define IMAGE_BYTE_ORDER MSBFirst /* Values for the SUN only */ +# define BITMAP_BIT_ORDER MSBFirst +#endif + +#ifdef sparc +# define AVOID_MEMORY_READ +# define LARGE_INSTRUCTION_CACHE +# define FAST_CONSTANT_OFFSET_MODE +# define SHARED_IDCACHE +#endif + +#ifdef mc68020 +#define FAST_UNALIGNED_READS +#endif + +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +#endif /* sun */ + + +#if defined(AIXV3) + +#define IMAGE_BYTE_ORDER MSBFirst /* Values for the RISC/6000 */ +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +#define LARGE_INSTRUCTION_CACHE +#define FAST_CONSTANT_OFFSET_MODE +#define PLENTIFUL_REGISTERS +#define AVOID_MEMORY_READ + +#define FAST_MEMCPY +#endif /* AIXV3 */ + +#if defined(ibm032) || defined (ibm) + +#ifdef i386 +# define IMAGE_BYTE_ORDER LSBFirst /* Value for PS/2 only */ +#else +# define IMAGE_BYTE_ORDER MSBFirst /* Values for the RT only*/ +#endif +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 1 +#define GETLEFTBITS_ALIGNMENT 4 +/* ibm pcc doesn't understand pragmas. */ + +#ifdef i386 +#define BITMAP_SCANLINE_UNIT 8 +#endif + +#endif /* ibm */ + +#ifdef hpux + +#define IMAGE_BYTE_ORDER MSBFirst /* Values for the HP only */ +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 2 /* to match product server */ +#define GETLEFTBITS_ALIGNMENT 4 /* PA forces longs to 4 */ + /* byte boundries */ +#define AVOID_MEMORY_READ +#define FAST_CONSTANT_OFFSET_MODE +#define LARGE_INSTRUCTION_CACHE +#define PLENTIFUL_REGISTERS + +#endif /* hpux */ + +#if defined (M4310) || defined(M4315) || defined(M4317) || defined(M4319) || defined(M4330) + +#define IMAGE_BYTE_ORDER MSBFirst /* Values for Pegasus only */ +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +#define FAST_UNALIGNED_READS + +#endif /* tektronix */ + +#ifdef macII + +#define IMAGE_BYTE_ORDER MSBFirst /* Values for the MacII only */ +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +/* might want FAST_UNALIGNED_READS for frame buffers with < 1us latency */ + +#endif /* macII */ + +#if (defined(mips) || defined(__mips)) && !defined(sgi) + +#if defined(MIPSEL) || defined(__MIPSEL__) +# define IMAGE_BYTE_ORDER LSBFirst /* Values for the PMAX only */ +# define BITMAP_BIT_ORDER LSBFirst +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +#else +# define IMAGE_BYTE_ORDER MSBFirst /* Values for the MIPS only */ +# define BITMAP_BIT_ORDER MSBFirst +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +#endif + +#define AVOID_MEMORY_READ +#define FAST_CONSTANT_OFFSET_MODE +#define LARGE_INSTRUCTION_CACHE +#define PLENTIFUL_REGISTERS + +#endif /* mips */ + +#if defined(__alpha) || defined(__alphaCross) +# define IMAGE_BYTE_ORDER LSBFirst /* Values for the Alpha only */ +# define BITMAP_BIT_ORDER LSBFirst +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +# define FAST_CONSTANT_OFFSET_MODE +# define LARGE_INSTRUCTION_CACHE +# define PLENTIFUL_REGISTERS + +/* pad scanline to a longword */ +#define BITMAP_SCANLINE_UNIT 64 + +#define BITMAP_SCANLINE_PAD 64 +#define LOG2_BITMAP_PAD 6 +#define LOG2_BYTES_PER_SCANLINE_PAD 3 + +/* Add for handling protocol XPutImage and XGetImage; see comment below */ +#define INTERNAL_VS_EXTERNAL_PADDING +#define BITMAP_SCANLINE_UNIT_PROTO 32 + +#define BITMAP_SCANLINE_PAD_PROTO 32 +#define LOG2_BITMAP_PAD_PROTO 5 +#define LOG2_BYTES_PER_SCANLINE_PAD_PROTO 2 + +#endif /* alpha */ + +#ifdef stellar + +#define IMAGE_BYTE_ORDER MSBFirst /* Values for the stellar only*/ +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 4 +#define IMAGE_BUFSIZE (64*1024) +/* + * Use SysV random number generator. + */ +#define random rand + +#endif /* stellar */ + +#ifdef luna + +#define IMAGE_BYTE_ORDER MSBFirst /* Values for the OMRON only*/ +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +#ifndef mc68000 +#define FAST_CONSTANT_OFFSET_MODE +#define AVOID_MEMORY_READ +#define LARGE_INSTRUCTION_CACHE +#define PLENTIFUL_REGISTERS +#endif + +#endif /* luna */ + +#if ((defined(SVR4) && defined(i386)) || \ + (defined(SYSV) && defined(i386)) || \ + (defined(sun) && defined (i386) && defined(SVR4)) || \ + defined(__bsdi__) || \ + (defined(__NetBSD__) && defined(__i386__)) || \ + defined(__FreeBSD__) || \ + defined(MACH386) || \ + defined(linux) || \ + (defined(AMOEBA) && defined(i80386)) || \ + defined(MINIX) || \ + defined(WIN32)) + +#ifndef IMAGE_BYTE_ORDER +#define IMAGE_BYTE_ORDER LSBFirst +#endif + +#ifndef BITMAP_BIT_ORDER +# if defined(XF86MONOVGA) || defined(XF86VGA16) || defined(XF86MONO) +# define BITMAP_BIT_ORDER MSBFirst +# else +# define BITMAP_BIT_ORDER LSBFirst +# endif +#endif + +#ifndef BITMAP_SCANLINE_UNIT +# if defined(XF86MONOVGA) || defined(XF86VGA16) +# define BITMAP_SCANLINE_UNIT 8 +# endif +#endif + +#ifndef GLYPHPADBYTES +#define GLYPHPADBYTES 4 +#endif + +#define GETLEFTBITS_ALIGNMENT 1 +#define AVOID_MEMORY_READ +#ifdef XSVGA +#define AVOID_GLYPHBLT +#define FAST_CONSTANT_OFFSET_MODE +#define FAST_MEMCPY +#define NO_ONE_RECT +#endif + +#endif /* SVR4 / BSD / i386 */ + + +#ifdef sgi + +#define IMAGE_BYTE_ORDER MSBFirst +#define BITMAP_BIT_ORDER MSBFirst + +#if (_MIPS_SZLONG == 64) + +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 + +/* pad scanline to a longword */ +#define BITMAP_SCANLINE_UNIT 64 + +#define BITMAP_SCANLINE_PAD 64 +#define LOG2_BITMAP_PAD 6 +#define LOG2_BYTES_PER_SCANLINE_PAD 3 + +/* Add for handling protocol XPutImage and XGetImage; see comment below */ +#define INTERNAL_VS_EXTERNAL_PADDING +#define BITMAP_SCANLINE_UNIT_PROTO 32 + +#define BITMAP_SCANLINE_PAD_PROTO 32 +#define LOG2_BITMAP_PAD_PROTO 5 +#define LOG2_BYTES_PER_SCANLINE_PAD_PROTO 2 + +#else + +#define GLYPHPADBYTES 2 +#define GETLEFTBITS_ALIGNMENT 4 + +#endif + +#define AVOID_MEMORY_READ +#define FAST_CONSTANT_OFFSET_MODE +#define LARGE_INSTRUCTION_CACHE +#define PLENTIFUL_REGISTERS + +#endif + +/* size of buffer to use with GetImage, measured in bytes. There's obviously + * a trade-off between the amount of stack (or whatever ALLOCATE_LOCAL gives + * you) used and the number of times the ddx routine has to be called. + * + * for a 1024 x 864 bit monochrome screen with a 32 bit word we get + * 8192/4 words per buffer + * (1024/32) = 32 words per scanline + * 2048 words per buffer / 32 words per scanline = 64 scanlines per buffer + * 864 scanlines / 64 scanlines = 14 buffers to draw a full screen + */ +#ifndef IMAGE_BUFSIZE +#define IMAGE_BUFSIZE 8192 +#endif + +/* pad scanline to a longword */ +#ifndef BITMAP_SCANLINE_UNIT +#define BITMAP_SCANLINE_UNIT 32 +#endif + +#ifndef BITMAP_SCANLINE_PAD +#define BITMAP_SCANLINE_PAD 32 +#define LOG2_BITMAP_PAD 5 +#define LOG2_BYTES_PER_SCANLINE_PAD 2 +#endif + +/* + * This returns the number of padding units, for depth d and width w. + * For bitmaps this can be calculated with the macros above. + * Other depths require either grovelling over the formats field of the + * screenInfo or hardwired constants. + */ + +typedef struct _PaddingInfo { + int padRoundUp; /* pixels per pad unit - 1 */ + int padPixelsLog2; /* log 2 (pixels per pad unit) */ + int padBytesLog2; /* log 2 (bytes per pad unit) */ +} PaddingInfo; +extern PaddingInfo PixmapWidthPaddingInfo[]; + +#define PixmapWidthInPadUnits(w, d) \ + ((int)((w) + PixmapWidthPaddingInfo[d].padRoundUp) >> \ + PixmapWidthPaddingInfo[d].padPixelsLog2) + +/* + * Return the number of bytes to which a scanline of the given + * depth and width will be padded. + */ +#define PixmapBytePad(w, d) \ + (PixmapWidthInPadUnits(w, d) << PixmapWidthPaddingInfo[d].padBytesLog2) + +#define BitmapBytePad(w) \ + (((int)((w) + BITMAP_SCANLINE_PAD - 1) >> LOG2_BITMAP_PAD) << LOG2_BYTES_PER_SCANLINE_PAD) + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + +/* This is defined if the server's internal padding is different from the padding + * advertised in the protocol. The protocol does not allow for padding to + * 64 bits, for example, so if the server wants to use 64 bit padding internally, + * it has to advertise 32 bit padding and do padding fixups whenever images + * cross the wire. (See ProcGetImage and ProcPutImage.) + * + * The macros and constants that end in Proto or PROTO refer to the advertised + * padding, and the ones without Proto are for internal padding. + */ + +extern PaddingInfo PixmapWidthPaddingInfoProto[]; + +#define PixmapWidthInPadUnitsProto(w, d) \ + ((int)((w) + PixmapWidthPaddingInfoProto[d].padRoundUp) >> \ + PixmapWidthPaddingInfoProto[d].padPixelsLog2) + +#define PixmapBytePadProto(w, d) \ + (PixmapWidthInPadUnitsProto(w, d) << \ + PixmapWidthPaddingInfoProto[d].padBytesLog2) + +#define BitmapBytePadProto(w) \ + ((((w) + BITMAP_SCANLINE_PAD_PROTO - 1) >> LOG2_BITMAP_PAD_PROTO) \ + << LOG2_BYTES_PER_SCANLINE_PAD_PROTO) + +#else /* protocol and internal padding is the same */ + +#define PixmapWidthInPadUnitsProto(w, d) PixmapWidthInPadUnits(w, d) +#define PixmapBytePadProto(w, d) PixmapBytePad(w, d) +#define BitmapBytePadProto(w) BitmapBytePad(w) + +#endif /* protocol vs. internal padding */ + +#endif /* SERVERMD_H */ diff --git a/include/site.h b/include/site.h new file mode 100644 index 000000000..426842183 --- /dev/null +++ b/include/site.h @@ -0,0 +1,137 @@ +/* $Xorg: site.h,v 1.6 2001/02/09 02:05:16 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +********************************************************/ + +#ifndef SITE_H +#define SITE_H +/* + * The vendor string identifies the vendor responsible for the + * server executable. + */ +#ifndef VENDOR_STRING +#define VENDOR_STRING "The X.Org Group" +#endif + +/* + * The vendor release number identifies, for the purpose of submitting + * traceable bug reports, the release number of software produced + * by the vendor. + */ +#ifndef VENDOR_RELEASE +#define VENDOR_RELEASE 6600 +#endif + +/* + * The following constants are provided solely as a last line of defense. The + * normal build ALWAYS overrides them using a special rule given in + * server/dix/Imakefile. If you want to change either of these constants, + * you should set the DefaultFontPath or DefaultRGBDatabase configuration + * parameters. + * DO NOT CHANGE THESE VALUES OR THE DIX IMAKEFILE! + */ +#ifndef COMPILEDDEFAULTFONTPATH +#define COMPILEDDEFAULTFONTPATH "/usr/lib/X11/fonts/misc/" +#endif +#ifndef RGB_DB +#define RGB_DB "/usr/lib/X11/rgb" +#endif + +/* + * The following constants contain default values for all of the variables + * that can be initialized on the server command line or in the environment. + */ +#define COMPILEDDEFAULTFONT "fixed" +#define COMPILEDCURSORFONT "cursor" +#ifndef COMPILEDDISPLAYCLASS +#define COMPILEDDISPLAYCLASS "MIT-unspecified" +#endif +#define DEFAULT_TIMEOUT 60 /* seconds */ +#define DEFAULT_KEYBOARD_CLICK 0 +#define DEFAULT_BELL 50 +#define DEFAULT_BELL_PITCH 400 +#define DEFAULT_BELL_DURATION 100 +#ifdef XKB +#define DEFAULT_AUTOREPEAT TRUE +#else +#define DEFAULT_AUTOREPEAT FALSE +#endif +#ifdef hpux +#define DEFAULT_AUTOREPEATS {\ + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#else +#define DEFAULT_AUTOREPEATS {\ + 0, 0, 0, 0, 0, 0, 0, 0,\ + 0, 0, 0, 0, 0, 0, 0, 0,\ + 0, 0, 0, 0, 0, 0, 0, 0,\ + 0, 0, 0, 0, 0, 0, 0, 0 } +#endif +#define DEFAULT_LEDS 0x0 /* all off */ +#define DEFAULT_LEDS_MASK 0xffffffff /* 32 */ +#define DEFAULT_INT_RESOLUTION 1000 +#define DEFAULT_INT_MIN_VALUE 0 +#define DEFAULT_INT_MAX_VALUE 100 +#define DEFAULT_INT_DISPLAYED 0 + +#define DEFAULT_PTR_NUMERATOR 2 +#define DEFAULT_PTR_DENOMINATOR 1 +#define DEFAULT_PTR_THRESHOLD 4 + +#define DEFAULT_SCREEN_SAVER_TIME (10 * (60 * 1000)) +#define DEFAULT_SCREEN_SAVER_INTERVAL (10 * (60 * 1000)) +#define DEFAULT_SCREEN_SAVER_BLANKING PreferBlanking +#define DEFAULT_SCREEN_SAVER_EXPOSURES AllowExposures +#ifndef NOLOGOHACK +#define DEFAULT_LOGO_SCREEN_SAVER 1 +#endif +#ifndef DEFAULT_ACCESS_CONTROL +#define DEFAULT_ACCESS_CONTROL TRUE +#endif + +#endif /* SITE_H */ diff --git a/include/validate.h b/include/validate.h new file mode 100644 index 000000000..7cff3a63d --- /dev/null +++ b/include/validate.h @@ -0,0 +1,41 @@ +/* $Xorg: validate.h,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +#ifndef VALIDATE_H +#define VALIDATE_H + +#include "miscstruct.h" +#include "regionstr.h" + +typedef enum { VTOther, VTStack, VTMove, VTUnmap, VTMap } VTKind; + +/* union _Validate is now device dependent; see mivalidate.h for an example */ +typedef union _Validate *ValidatePtr; + +#define UnmapValData ((ValidatePtr)1) + +#endif /* VALIDATE_H */ diff --git a/include/window.h b/include/window.h new file mode 100644 index 000000000..5c17f43be --- /dev/null +++ b/include/window.h @@ -0,0 +1,350 @@ +/* $Xorg: window.h,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include "misc.h" +#include "region.h" +#include "screenint.h" +#include "X11/Xproto.h" + +#define TOTALLY_OBSCURED 0 +#define UNOBSCURED 1 +#define OBSCURED 2 + +#define VisibilityNotViewable 3 + +/* return values for tree-walking callback procedures */ +#define WT_STOPWALKING 0 +#define WT_WALKCHILDREN 1 +#define WT_DONTWALKCHILDREN 2 +#define WT_NOMATCH 3 +#define NullWindow ((WindowPtr) 0) + +typedef struct _BackingStore *BackingStorePtr; +typedef struct _Window *WindowPtr; + +typedef int (*VisitWindowProcPtr)( +#if NeedNestedPrototypes + WindowPtr /*pWin*/, + pointer /*data*/ +#endif +); + +extern int TraverseTree( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + VisitWindowProcPtr /*func*/, + pointer /*data*/ +#endif +); + +extern int WalkTree( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + VisitWindowProcPtr /*func*/, + pointer /*data*/ +#endif +); + +extern WindowPtr AllocateWindow( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/ +#endif +); + +extern Bool CreateRootWindow( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/ +#endif +); + +extern void InitRootWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void ClippedRegionFromBox( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + RegionPtr /*Rgn*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/ +#endif +); + +extern WindowPtr RealChildHead( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern WindowPtr CreateWindow( +#if NeedFunctionPrototypes + Window /*wid*/, + WindowPtr /*pParent*/, + int /*x*/, + int /*y*/, + unsigned int /*w*/, + unsigned int /*h*/, + unsigned int /*bw*/, + unsigned int /*class*/, + Mask /*vmask*/, + XID* /*vlist*/, + int /*depth*/, + ClientPtr /*client*/, + VisualID /*visual*/, + int* /*error*/ +#endif +); + +extern int DeleteWindow( +#if NeedFunctionPrototypes + pointer /*pWin*/, + XID /*wid*/ +#endif +); + +extern void DestroySubwindows( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + ClientPtr /*client*/ +#endif +); + +extern int ChangeWindowAttributes( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + Mask /*vmask*/, + XID* /*vlist*/, + ClientPtr /*client*/ +#endif +); + +extern void GetWindowAttributes( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + ClientPtr /*client*/, + xGetWindowAttributesReply* /* wa */ +#endif +); + +extern RegionPtr CreateUnclippedWinSize( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void GravityTranslate( +#if NeedFunctionPrototypes + int /*x*/, + int /*y*/, + int /*oldx*/, + int /*oldy*/, + int /*dw*/, + int /*dh*/, + unsigned /*gravity*/, + int* /*destx*/, + int* /*desty*/ +#endif +); + +extern int ConfigureWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + Mask /*mask*/, + XID* /*vlist*/, + ClientPtr /*client*/ +#endif +); + +extern int CirculateWindow( +#if NeedFunctionPrototypes + WindowPtr /*pParent*/, + int /*direction*/, + ClientPtr /*client*/ +#endif +); + +extern int ReparentWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + WindowPtr /*pParent*/, + int /*x*/, + int /*y*/, + ClientPtr /*client*/ +#endif +); + +extern int MapWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + ClientPtr /*client*/ +#endif +); + +extern void MapSubwindows( +#if NeedFunctionPrototypes + WindowPtr /*pParent*/, + ClientPtr /*client*/ +#endif +); + +extern int UnmapWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + Bool /*fromConfigure*/ +#endif +); + +extern void UnmapSubwindows( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void HandleSaveSet( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +extern Bool VisibleBoundingBoxFromPoint( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + BoxPtr /*box*/ +#endif +); + +extern Bool PointInWindowIsVisible( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/ +#endif +); + +extern RegionPtr NotClippedByChildren( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void SendVisibilityNotify( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void SaveScreens( +#if NeedFunctionPrototypes + int /*on*/, + int /*mode*/ +#endif +); + +extern WindowPtr FindWindowWithOptional( +#if NeedFunctionPrototypes + WindowPtr /*w*/ +#endif +); + +extern void CheckWindowOptionalNeed( +#if NeedFunctionPrototypes + WindowPtr /*w*/ +#endif +); + +extern Bool MakeWindowOptional( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void DisposeWindowOptional( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern WindowPtr MoveWindowInStack( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + WindowPtr /*pNextSib*/ +#endif +); + +void SetWinSize( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +void SetBorderSize( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +void ResizeChildrenWinSize( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*dx*/, + int /*dy*/, + int /*dw*/, + int /*dh*/ +#endif +); + +#endif /* WINDOW_H */ diff --git a/include/windowstr.h b/include/windowstr.h new file mode 100644 index 000000000..31de609b8 --- /dev/null +++ b/include/windowstr.h @@ -0,0 +1,227 @@ +/* $Xorg: windowstr.h,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#ifndef WINDOWSTRUCT_H +#define WINDOWSTRUCT_H + +#include "window.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cursor.h" +#include "property.h" +#include "resource.h" /* for ROOT_WINDOW_ID_BASE */ +#include "dix.h" +#include "miscstruct.h" +#include "X11/Xprotostr.h" +#include "opaque.h" + +#define GuaranteeNothing 0 +#define GuaranteeVisBack 1 + +#define SameBackground(as, a, bs, b) \ + ((as) == (bs) && ((as) == None || \ + (as) == ParentRelative || \ + SamePixUnion(a,b,as == BackgroundPixel))) + +#define SameBorder(as, a, bs, b) \ + EqualPixUnion(as, a, bs, b) + +typedef struct _WindowOpt { + VisualID visual; /* default: same as parent */ + CursorPtr cursor; /* default: window.cursorNone */ + Colormap colormap; /* default: same as parent */ + Mask dontPropagateMask; /* default: window.dontPropagate */ + Mask otherEventMasks; /* default: 0 */ + struct _OtherClients *otherClients; /* default: NULL */ + struct _GrabRec *passiveGrabs; /* default: NULL */ + PropertyPtr userProps; /* default: NULL */ + unsigned long backingBitPlanes; /* default: ~0L */ + unsigned long backingPixel; /* default: 0 */ +#ifdef SHAPE + RegionPtr boundingShape; /* default: NULL */ + RegionPtr clipShape; /* default: NULL */ +#endif +#ifdef XINPUT + struct _OtherInputMasks *inputMasks; /* default: NULL */ +#endif +} WindowOptRec, *WindowOptPtr; + +#define BackgroundPixel 2L +#define BackgroundPixmap 3L + +typedef struct _Window { + DrawableRec drawable; + WindowPtr parent; /* ancestor chain */ + WindowPtr nextSib; /* next lower sibling */ + WindowPtr prevSib; /* next higher sibling */ + WindowPtr firstChild; /* top-most child */ + WindowPtr lastChild; /* bottom-most child */ + RegionRec clipList; /* clipping rectangle for output */ + RegionRec borderClip; /* NotClippedByChildren + border */ + union _Validate *valdata; + RegionRec winSize; + RegionRec borderSize; + DDXPointRec origin; /* position relative to parent */ + unsigned short borderWidth; + unsigned short deliverableEvents; + Mask eventMask; + PixUnion background; + PixUnion border; + pointer backStorage; /* null when BS disabled */ + WindowOptPtr optional; + unsigned backgroundState:2; /* None, Relative, Pixel, Pixmap */ + unsigned borderIsPixel:1; + unsigned cursorIsNone:1; /* else real cursor (might inherit) */ + unsigned backingStore:2; + unsigned saveUnder:1; + unsigned DIXsaveUnder:1; + unsigned bitGravity:4; + unsigned winGravity:4; + unsigned overrideRedirect:1; + unsigned visibility:2; + unsigned mapped:1; + unsigned realized:1; /* ancestors are all mapped */ + unsigned viewable:1; /* realized && InputOutput */ + unsigned dontPropagate:3;/* index into DontPropagateMasks */ + unsigned forcedBS:1; /* system-supplied backingStore */ +#ifdef NEED_DBE_BUF_BITS +#define DBE_FRONT_BUFFER 1 +#define DBE_BACK_BUFFER 0 + unsigned dstBuffer:1; /* destination buffer for rendering */ + unsigned srcBuffer:1; /* source buffer for rendering */ +#endif + DevUnion *devPrivates; +} WindowRec; + +/* + * Ok, a bunch of macros for accessing the optional record + * fields (or filling the appropriate default value) + */ + +extern Mask DontPropagateMasks[]; + +#define wTrackParent(w,field) ((w)->optional ? \ + (w)->optional->field \ + : FindWindowWithOptional(w)->optional->field) +#define wUseDefault(w,field,def) ((w)->optional ? \ + (w)->optional->field \ + : def) + +#define wVisual(w) wTrackParent(w, visual) +#define wCursor(w) ((w)->cursorIsNone ? None : wTrackParent(w, cursor)) +#define wColormap(w) ((w)->drawable.class == InputOnly ? None : wTrackParent(w, colormap)) +#define wDontPropagateMask(w) wUseDefault(w, dontPropagateMask, DontPropagateMasks[(w)->dontPropagate]) +#define wOtherEventMasks(w) wUseDefault(w, otherEventMasks, 0) +#define wOtherClients(w) wUseDefault(w, otherClients, NULL) +#ifdef XINPUT +#define wOtherInputMasks(w) wUseDefault(w, inputMasks, NULL) +#else +#define wOtherInputMasks(w) NULL +#endif +#define wPassiveGrabs(w) wUseDefault(w, passiveGrabs, NULL) +#define wUserProps(w) wUseDefault(w, userProps, NULL) +#define wBackingBitPlanes(w) wUseDefault(w, backingBitPlanes, ~0L) +#define wBackingPixel(w) wUseDefault(w, backingPixel, 0) +#ifdef SHAPE +#define wBoundingShape(w) wUseDefault(w, boundingShape, NULL) +#define wClipShape(w) wUseDefault(w, clipShape, NULL) +#endif +#define wClient(w) (clients[CLIENT_ID((w)->drawable.id)]) +#define wBorderWidth(w) ((int) (w)->borderWidth) + +/* true when w needs a border drawn. */ + +#ifdef SHAPE +#define HasBorder(w) ((w)->borderWidth || wClipShape(w)) +#else +#define HasBorder(w) ((w)->borderWidth) +#endif + +typedef struct _ScreenSaverStuff { + WindowPtr pWindow; + XID wid; + char blanked; + Bool (*ExternalScreenSaver)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*xstate*/, + Bool /*force*/ +#endif + ); +} ScreenSaverStuffRec, *ScreenSaverStuffPtr; + +#define SCREEN_IS_BLANKED 0 +#define SCREEN_ISNT_SAVED 1 +#define SCREEN_IS_TILED 2 +#define SCREEN_IS_BLACK 3 + +#define HasSaverWindow(i) (savedScreenInfo[i].pWindow != NullWindow) + +extern int screenIsSaved; +extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +/* + * this is the configuration parameter "NO_BACK_SAVE" + * it means that any existant backing store should not + * be used to implement save unders. + */ + +#ifndef NO_BACK_SAVE +#define DO_SAVE_UNDERS(pWin) ((pWin)->drawable.pScreen->saveUnderSupport ==\ + USE_DIX_SAVE_UNDERS) +/* + * saveUnderSupport is set to this magic value when using DIXsaveUnders + */ + +#define USE_DIX_SAVE_UNDERS 0x40 +#endif + +extern int numSaveUndersViewable; +extern int deltaSaveUndersViewable; + +#endif /* WINDOWSTRUCT_H */ diff --git a/lbx/lbxcmap.c b/lbx/lbxcmap.c new file mode 100644 index 000000000..6af20b03b --- /dev/null +++ b/lbx/lbxcmap.c @@ -0,0 +1,1148 @@ +/* $Xorg: lbxcmap.c,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ + +/* +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. +*/ + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "colormapst.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "Xfuncproto.h" +#include + +static int lbxScreenPrivIndex; /* lbx screen private index */ +static int lbxColormapPrivIndex; /* lbx colormap private index */ + +typedef struct { /* lbx screen private */ + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; +} LbxScreenPriv; + +typedef struct _LbxStalled { + XID id; + struct _LbxStalled *next; +} LbxStalled; + +typedef struct _LbxColormapPriv { /* lbx colormap private */ + char grab_status; + char smart_grab; + LbxProxyPtr grabber; + int last_grabber; /* uid, not pid */ + LbxStalled *stalled_clients; + ColormapPtr next; /* proxy chain */ +} LbxColormapPriv; + +#define CMAP_NOT_GRABBED 0 +#define CMAP_GRABBED 1 +#define CMAP_WAITING_FOR_UNGRAB 2 + +static int LbxUnstallClient(); +void LbxReleaseCmap(); + +static RESTYPE StalledResType; + +/* + * Initialize the fields in the colormap private allocated for LBX. + */ + +static LbxColormapPriv * +LbxColormapPrivInit (pmap) + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv; + + cmapPriv = (LbxColormapPriv *) xalloc (sizeof (LbxColormapPriv)); + if (!cmapPriv) + return cmapPriv; + + pmap->devPrivates[lbxColormapPrivIndex].ptr = (pointer) cmapPriv; + + cmapPriv->grab_status = CMAP_NOT_GRABBED; + cmapPriv->grabber = NULL; + cmapPriv->last_grabber = 0; + cmapPriv->smart_grab = FALSE; + cmapPriv->stalled_clients = NULL; + cmapPriv->next = NULL; + + return cmapPriv; +} + + +static int +LbxDefCmapPrivInit (pmap) + ColormapPtr pmap; +{ + pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL; + return 1; +} + +static Bool +LbxCreateColormap (pmap) + ColormapPtr pmap; +{ + ScreenPtr pScreen = pmap->pScreen; + Bool ret; + + pScreen->CreateColormap = ((LbxScreenPriv *) (pScreen->devPrivates[ + lbxScreenPrivIndex].ptr))->CreateColormap; + + pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL; + ret = (*pScreen->CreateColormap) (pmap); + + pScreen->CreateColormap = LbxCreateColormap; + + return ret; +} + +static void +LbxDestroyColormap (pmap) + ColormapPtr pmap; +{ + ScreenPtr pScreen = pmap->pScreen; + + LbxReleaseCmap(pmap, FALSE); + pScreen->DestroyColormap = ((LbxScreenPriv *) (pScreen->devPrivates[ + lbxScreenPrivIndex].ptr))->DestroyColormap; + (*pScreen->DestroyColormap) (pmap); + if (pmap->devPrivates && pmap->devPrivates[lbxColormapPrivIndex].ptr) + xfree(pmap->devPrivates[lbxColormapPrivIndex].ptr); + pScreen->DestroyColormap = LbxDestroyColormap; +} + +/* + * Initialize LBX colormap private. + */ + +int +LbxCmapInit () + +{ + LbxScreenPriv *pScreenPriv; + ScreenPtr pScreen; + int i; + + StalledResType = CreateNewResourceType(LbxUnstallClient); + + lbxScreenPrivIndex = AllocateScreenPrivateIndex (); + if (lbxScreenPrivIndex < 0) + return 0; + + lbxColormapPrivIndex = AllocateColormapPrivateIndex (LbxDefCmapPrivInit); + if (lbxColormapPrivIndex < 0) + return 0; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pScreenPriv = (LbxScreenPriv *) xalloc (sizeof (LbxScreenPriv)); + if (!pScreenPriv) + return 0; + + pScreenPriv->CreateColormap = pScreen->CreateColormap; + pScreen->CreateColormap = LbxCreateColormap; + pScreenPriv->DestroyColormap = pScreen->DestroyColormap; + pScreen->DestroyColormap = LbxDestroyColormap; + pScreen->devPrivates[lbxScreenPrivIndex].ptr = (pointer) pScreenPriv; + } + + return 1; +} + + +/* + * Return the number of allocated cells in the PSEUDO colormap. + */ + +static int +NumAllocatedCells (pent, size) + EntryPtr pent; + int size; +{ + Pixel pixel; + int count = 0; + + for (pixel = 0; pixel < size; pixel++) + { + if (pent[pixel].refcnt != 0 && pent[pixel].refcnt != AllocTemporary) + count++; + } + + return count; +} + +#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1) +#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1) +#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1) + +#define PIX_OUT(ptr,is2,val) \ + if (is2) *ptr++ = (val) >> 8; \ + *ptr++ = (val) +#define RGB_OUT(ptr,is2,shift,val) \ + *ptr++ = (val) >> shift; \ + if (is2) *ptr++ = (val) + +/* + * Return the list of allocated cells in the channel in + * the format required by LbxGrabCmapReply. + */ + +static CARD8 * +OutputChannel(pmap, chan, size, ptr, flags, channels) + ColormapPtr pmap; + EntryPtr chan; + int size; + CARD8 *ptr; + CARD8 flags; + CARD8 channels; +{ + Bool px2; + Bool rgb2; + int shift; + int rgb_sz; + Pixel pixel; + EntryPtr pent; + CARD8 *pixel_private_range_ptr = NULL; + CARD8 *pixel_shared_range_ptr = NULL; + int allocpriv; + + px2 = (flags & LBX_2BYTE_PIXELS) != 0; + rgb2 = (flags & LBX_RGB_BITS_MASK) > 7; + if (rgb2) + shift = 8; + else + shift = 15 - (flags & LBX_RGB_BITS_MASK); + rgb_sz = rgb2 + 1; + if (channels == DoRed|DoGreen|DoBlue) + rgb_sz *= 3; + /* kinda gross, but ddxen use AllocAll on static maps */ + allocpriv = (pmap->pVisual->class & DynamicClass) ? AllocPrivate : 0; + for (pixel = 0; pixel < size; pixel++) + { + pent = (EntryPtr) &chan[pixel]; + + if (pent->refcnt == 0 || pent->refcnt == AllocTemporary) + { + /* + * A free pixel. This disrupts all ranges. + */ + + pixel_private_range_ptr = pixel_shared_range_ptr = NULL; + + continue; + } + else if (pent->refcnt == allocpriv) + { + /* + * A private pixel. This disrupts any PIXEL_SHARED_RANGE. + */ + + pixel_shared_range_ptr = NULL; + + if (!pixel_private_range_ptr) + { + pixel_private_range_ptr = ptr; + + *ptr++ = LBX_PIXEL_PRIVATE; + PIX_OUT(ptr, px2, pixel); + } + else + { + CARD8 *pos = pixel_private_range_ptr + 2 + px2; + if (*pixel_private_range_ptr == LBX_PIXEL_PRIVATE) { + *pixel_private_range_ptr = LBX_PIXEL_RANGE_PRIVATE; + ptr += 1 + px2; + } + PIX_OUT(pos, px2, pixel); + } + } + else + { + /* + * A shared pixel. This disrupts any PIXEL_PRIVATE_RANGE. + */ + + pixel_private_range_ptr = NULL; + + if (!pixel_shared_range_ptr) + { + pixel_shared_range_ptr = ptr; + + *ptr++ = LBX_PIXEL_SHARED; + PIX_OUT(ptr, px2, pixel); + } + else + { + CARD8 *pos = pixel_shared_range_ptr + 2 + px2; + if (*pixel_shared_range_ptr == LBX_PIXEL_SHARED) + { + *pixel_shared_range_ptr = LBX_PIXEL_RANGE_SHARED; + memmove (pos + 1 + px2, pos, rgb_sz); + ptr += 1 + px2; + } + PIX_OUT(pos, px2, pixel); + } + + if (channels & DoRed) { + RGB_OUT(ptr, rgb2, shift, pent->co.local.red); + } + if (channels & DoGreen) { + RGB_OUT(ptr, rgb2, shift, pent->co.local.green); + } + if (channels & DoBlue) { + RGB_OUT(ptr, rgb2, shift, pent->co.local.blue); + } + } + } + return ptr; +} + +static void +GetAllocatedCells (pmap, flags, buf, bytes) + ColormapPtr pmap; + CARD8 *flags; + CARD8 *buf; + int *bytes; +{ + CARD8 *ptr; + + *flags = pmap->pVisual->bitsPerRGBValue - 1; + if (pmap->pVisual->ColormapEntries > 256) + *flags |= LBX_2BYTE_PIXELS; + if (!(pmap->pVisual->class & DynamicClass)) + *flags |= LBX_AUTO_RELEASE; + if ((pmap->pVisual->class | DynamicClass) == DirectColor) { + *flags |= LBX_3CHANNELS; + ptr = OutputChannel(pmap, pmap->red, NUMRED(pmap->pVisual), + buf, *flags, DoRed); + *ptr++ = LBX_NEXT_CHANNEL; + ptr = OutputChannel(pmap, pmap->green, NUMGREEN(pmap->pVisual), + ptr, *flags, DoGreen); + *ptr++ = LBX_NEXT_CHANNEL; + ptr = OutputChannel(pmap, pmap->blue, NUMBLUE(pmap->pVisual), + ptr, *flags, DoBlue); + } else + ptr = OutputChannel(pmap, pmap->red, pmap->pVisual->ColormapEntries, + buf, *flags, DoRed|DoGreen|DoBlue); + *ptr++ = LBX_LIST_END; + *bytes = ptr - buf; +} + + +/* + * Send an LbxReleaseCmapEvent to a proxy. + */ + +static void +SendReleaseCmapEvent (proxy, cmap) + LbxProxyPtr proxy; + Colormap cmap; +{ + xLbxReleaseCmapEvent ev; + ClientPtr client; + LbxClientPtr lbxcp; + int n; + + lbxcp = proxy->lbxClients[0]; + + if (lbxcp && (client = lbxcp->client)) + { + ev.type = LbxEventCode; + ev.lbxType = LbxReleaseCmapEvent; + ev.sequenceNumber = client->sequence; + ev.colormap = cmap; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = ev.pad6 = 0; + + if (client->swapped) + { + swaps(&ev.sequenceNumber, n); + swapl(&ev.colormap, n); + } + + WriteToClient(client, sz_xLbxReleaseCmapEvent, (char *) &ev); + LbxForceOutput(proxy); + +#ifdef COLOR_DEBUG + fprintf (stderr, + "Sent LbxReleaseCmapEvent to proxy %d, seq = 0x%x, cmap = 0x%x\n", + proxy->pid, client->sequence, cmap); +#endif + } +} + + +/* + * WaitForServerCmapControl checks if the colormap is grabbed by a proxy, + * and if so, sends an LbxReleaseCmapEvent to the proxy. It then suspends + * the current request until the server gets the ReleaseCmap message from + * the proxy. + */ + +static Bool +WaitForServerCmapControl (client, pmap) + register ClientPtr client; + register ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + LbxStalled *stalled; + + if (cmapPriv->grab_status == CMAP_GRABBED) + { + /* + * Send an LbxReleaseCmapEvent to the proxy that has the grab. + */ + + SendReleaseCmapEvent (cmapPriv->grabber, pmap->mid); + cmapPriv->grab_status = CMAP_WAITING_FOR_UNGRAB; + } + + stalled = (LbxStalled *)xalloc(sizeof(LbxStalled)); + if (!stalled) + return FALSE; + stalled->id = FakeClientID(client->index); + stalled->next = cmapPriv->stalled_clients; + cmapPriv->stalled_clients = stalled; + return AddResource(stalled->id, StalledResType, (pointer)cmapPriv); +} + + +/* + * When the X server gets any of the requests that allocate color cells, + * it calls LbxCheckColorRequest on the request. This function will check + * if the colormap is grabbed by a proxy, and if so, will suspend the + * current request and wait for the proxy to release the colormap. + */ + +Bool +LbxCheckColorRequest (client, pmap, req) + ClientPtr client; + ColormapPtr pmap; + xReq *req; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + if (!cmapPriv) + return FALSE; + + if (cmapPriv->grab_status != CMAP_NOT_GRABBED) + { + /* + * The colormap is grabbed by a proxy. Reset this request, and + * process it after the server gets back control of the colormap. + * Before we reset the request, we must put it back in the + * client's byte order. + */ + + if (!WaitForServerCmapControl (client, pmap)) + return FALSE; + + if (client->swapped) + { + register int n; + + switch (req->reqType) + { + case X_AllocColor: + { + xAllocColorReq *stuff = (xAllocColorReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + break; + } + case X_AllocNamedColor: + { + xAllocNamedColorReq *stuff = (xAllocNamedColorReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->nbytes, n); + break; + } + case X_AllocColorCells: + { + xAllocColorCellsReq *stuff = (xAllocColorCellsReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->planes, n); + break; + } + case X_AllocColorPlanes: + { + xAllocColorPlanesReq *stuff = (xAllocColorPlanesReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + break; + } + default: + break; + } + } + + ResetCurrentRequest(client); + client->sequence--; + IgnoreClient(client); + + return TRUE; + } + + if (!LbxClient(client) || + LbxProxy(client)->uid != cmapPriv->last_grabber) + { + /* + * Next time the proxy for this client does a colormap grab, it + * will have to get the colormap state (a non-smart grab). + */ + + cmapPriv->smart_grab = FALSE; + } + + return FALSE; +} + +static Bool +LbxGrabbedByClient (client, pmap) + ClientPtr client; + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + return (cmapPriv && + (cmapPriv->grab_status != CMAP_NOT_GRABBED) && + (cmapPriv->grabber == LbxProxy(client))); +} + +/* + * Check if a colormap is grabbed by a proxy. + */ + +int +LbxCheckCmapGrabbed (pmap) + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + return (cmapPriv && (cmapPriv->grab_status == CMAP_GRABBED)); +} + + +/* + * Disable a smart grab on the specified colormap. + */ + +void +LbxDisableSmartGrab (pmap) + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + if (cmapPriv) + cmapPriv->smart_grab = FALSE; +} + + +/* + * Send an LbxFreeCellsEvent to the specified proxy. + */ + +static void +SendFreeCellsEvent (proxy, cmap, pixel_start, pixel_end) + LbxProxyPtr proxy; + Colormap cmap; + Pixel pixel_start; + Pixel pixel_end; +{ + xLbxFreeCellsEvent ev; + ClientPtr client; + LbxClientPtr lbxcp; + int n; + + lbxcp = proxy->lbxClients[0]; + + if (lbxcp && (client = lbxcp->client)) + { + ev.type = LbxEventCode; + ev.lbxType = LbxFreeCellsEvent; + ev.sequenceNumber = client->sequence; + ev.colormap = cmap; + ev.pixelStart = pixel_start; + ev.pixelEnd = pixel_end; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = 0; + + if (client->swapped) + { + swaps(&ev.sequenceNumber, n); + swapl(&ev.colormap, n); + swapl(&ev.pixelStart, n); + swapl(&ev.pixelEnd, n); + } + + WriteToClient(client, sz_xLbxFreeCellsEvent, (char *) &ev); + LbxForceOutput(proxy); +#ifdef COLOR_DEBUG + fprintf (stderr, "Sent LbxFreeCellsEvent to proxy %d, seq = 0x%x\n", + proxy->pid, client->sequence); + fprintf (stderr, " cmap = 0x%x, pixelStart = %d, pixelEnd = %d\n", + cmap, pixel_start, pixel_end); +#endif + } +} + +/* XXX use of globals like this is gross */ +static long pixel_start; +static long pixel_end; + + +/* + * LbxFreeCellsEvent generation functions. + */ + +/*ARGSUSED*/ +void +LbxBeginFreeCellsEvent (pmap) + ColormapPtr pmap; +{ + pixel_start = -1; + pixel_end = -1; +} + + +void +LbxAddFreeCellToEvent (pmap, pixel) + ColormapPtr pmap; + Pixel pixel; +{ + /* + * We must notify the proxy that has this colormap + * grabbed which cells are being freed (their refcount + * has reached zero). + */ + + if (pixel_start == -1) + pixel_start = pixel; + else + { + if (pixel_end == -1) + pixel_end = pixel; + else + { + if (pixel_end + 1 == pixel) + pixel_end = pixel; + else if (pixel > pixel_end + 1) + { + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + SendFreeCellsEvent (cmapPriv->grabber, + pmap->mid, pixel_start, pixel_end); + + pixel_start = pixel; + pixel_end = -1; + } + } + } +} + +void +LbxEndFreeCellsEvent (pmap) + ColormapPtr pmap; +{ + /* + * Check if there is an LbxFreeCellEvent we need to write. + */ + + if (pixel_start != -1) + { + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + SendFreeCellsEvent (cmapPriv->grabber, + pmap->mid, pixel_start, + pixel_end == -1 ? pixel_start : pixel_end); + } +} + + +/* + * Sort the specified pixel list. This optimizes generation + * of LbxFreeCellsEvent. + */ + +void +LbxSortPixelList (pixels, count) + Pixel *pixels; + int count; +{ + int i, j; + + for (i = 0; i <= count - 2; i++) + for (j = count - 1; j > i; j--) + if (pixels[j - 1] > pixels[j]) + { + Pixel temp = pixels[j - 1]; + pixels[j - 1] = pixels[j]; + pixels[j] = temp; + } +} + + +/* + * Handle a colormap grab request from a proxy. + */ + +int +ProcLbxGrabCmap(client) + register ClientPtr client; +{ + REQUEST(xLbxGrabCmapReq); + xLbxGrabCmapReply *reply; + Bool smartGrab; + LbxColormapPriv *cmapPriv; + ColormapPtr pmap; + int bytes, n; + LbxProxyPtr proxy = LbxProxy(client); + + client->sequence--; /* not a counted request */ + + pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + + if (!pmap) + { + client->errorValue = stuff->cmap; + return BadColor; + } + + cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + if (!cmapPriv) + { + cmapPriv = LbxColormapPrivInit (pmap); + if (!cmapPriv) + return BadAlloc; + } + + + /* + * We have a SMART GRAB if since this proxy last ungrabbed the + * colormap, no color cell was alloc'd by an entity other than + * this proxy (this includes other proxies as well as clients + * directly connected to the X server without a proxy). + * + * We want to optimize this special case because a proxy may give + * up a grab because it got a request that it could not handle + * (e.g. AllocNamedColor or LookupColor). When it asks back for + * the grab, there is no need for the server to send the colormap + * state, because the proxy is already up to date on the state of + * the colormap. + * + * In order for this to work, the following assumptions are made + * about the proxy: + * + * - the proxy is kept up to date on all cell allocations made on its + * behalf resulting from the following requests: AllocNamedColor, + * AllocColorCells, AllocColorPlanes + * - the proxy is kept up to date on all cells freed by any client + * via the LbxFreeCell event. + */ + + /* if proxy is this confused, give it full info */ + if (cmapPriv->grab_status == CMAP_GRABBED && cmapPriv->grabber == proxy) + LbxReleaseCmap(pmap, FALSE); + + if (proxy->uid != cmapPriv->last_grabber) + cmapPriv->smart_grab = FALSE; + smartGrab = cmapPriv->smart_grab; + +#ifdef COLOR_DEBUG + fprintf (stderr, "\nGot colormap grab request, "); + fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n", + client->sequence, proxy->pid, client->index, stuff->cmap); + + if (cmapPriv->grab_status == CMAP_NOT_GRABBED) + { + fprintf (stderr, "cmap 0x%x is not grabbed by any proxy\n", + stuff->cmap); + if (smartGrab) + fprintf (stderr, "This is a smart grab\n"); + } + else if (cmapPriv->grab_status == CMAP_GRABBED) + { + if (cmapPriv->grabber == proxy) + { + fprintf (stderr, "cmap 0x%x is already grabbed by proxy %d\n", + stuff->cmap, proxy->pid); + } + else + { + fprintf (stderr, "cmap 0x%x is currently grabbed by proxy %d\n", + stuff->cmap, cmapPriv->grabber->pid); + } + } + else if (cmapPriv->grab_status == CMAP_WAITING_FOR_UNGRAB) + { + fprintf (stderr, + "Already waiting for cmap 0x%x to be ungrabbed by proxy %d\n", + stuff->cmap, cmapPriv->grabber->pid); + } +#endif + + if (cmapPriv->grab_status != CMAP_NOT_GRABBED && + cmapPriv->grabber != proxy) + { + /* + * The colormap is grabbed by a proxy other than the one that + * is requesting this grab. Reset this grab request, and process + * it after the server gets back control of the colormap. Before + * we reset the request, we must put it back in the client's byte + * order. + */ + + if (!WaitForServerCmapControl (client, pmap)) + return BadAlloc; + + if (client->swapped) + { + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + } + + ResetCurrentRequest(client); + IgnoreClient(client); + + return Success; + } + + if (pmap->pVisual->class & DynamicClass) { + cmapPriv->grabber = proxy; + cmapPriv->grab_status = CMAP_GRABBED; + cmapPriv->next = proxy->grabbedCmaps; + proxy->grabbedCmaps = pmap; + } else + smartGrab = FALSE; + + /* + * For an smart grab (see comments above), there is no information + * sent about the colormap cells because the proxy is all up to date. + * Otherwise, the server sends the proxy the state of all allocated + * cells in the colormap. All cells not specified are assumed free. + */ + + bytes = 0; + if (!smartGrab) { + if ((pmap->pVisual->class | DynamicClass) == DirectColor) { + bytes = NumAllocatedCells(pmap->red, + NUMRED(pmap->pVisual)) * 9; + bytes += NumAllocatedCells(pmap->green, + NUMGREEN(pmap->pVisual)) * 9; + bytes += NumAllocatedCells(pmap->blue, + NUMBLUE(pmap->pVisual)) * 9; + bytes += 2; + } else + bytes = NumAllocatedCells(pmap->red, + pmap->pVisual->ColormapEntries) * 9; + } + bytes += sz_xLbxGrabCmapReply + 1; + reply = (xLbxGrabCmapReply *) xalloc (bytes); + bzero (reply, sz_xLbxGrabCmapReply); + + if (smartGrab) + { + reply->flags = LBX_SMART_GRAB; + reply->length = 0; + } + else + { + GetAllocatedCells (pmap, &reply->flags, + (CARD8 *) reply + sz_xLbxGrabCmapReplyHdr, &bytes); + if (bytes <= (sz_xLbxGrabCmapReply - sz_xLbxGrabCmapReplyHdr)) + reply->length = 0; + else + reply->length = (sz_xLbxGrabCmapReplyHdr + + bytes - sz_xLbxGrabCmapReply + 3) >> 2; + } + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + + bytes = sz_xLbxGrabCmapReply + (reply->length << 2); + + if (client->swapped) + { + register char n; + + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + } + + WriteToClient (client, bytes, (char *)reply); + + xfree (reply); + + return (client->noClientException); +} + +static int +LbxUnstallClient(data, id) + pointer data; + XID id; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *)data; + LbxStalled **prev; + ClientPtr client; + + for (prev = &cmapPriv->stalled_clients; *prev && (*prev)->id != id; ) + prev = &(*prev)->next; + *prev = (*prev)->next; + client = clients[CLIENT_ID(id)]; + if (!client->clientGone) + AttendClient(client); + return 0; +} + +void +LbxReleaseCmap(pmap, smart) + ColormapPtr pmap; + Bool smart; +{ + LbxColormapPriv *cmapPriv; + ColormapPtr *prev; + + if (!pmap->devPrivates) + return; + cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + if (!cmapPriv || (cmapPriv->grab_status == CMAP_NOT_GRABBED)) + return; + + for (prev = &cmapPriv->grabber->grabbedCmaps; *prev && *prev != pmap; ) + prev = &((LbxColormapPriv *) + (*prev)->devPrivates[lbxColormapPrivIndex].ptr)->next; + if (*prev == pmap) + *prev = cmapPriv->next; + + while (cmapPriv->stalled_clients) + FreeResource(cmapPriv->stalled_clients->id, 0); + + cmapPriv->grab_status = CMAP_NOT_GRABBED; + cmapPriv->last_grabber = smart ? cmapPriv->grabber->uid : 0; + cmapPriv->grabber = NULL; + cmapPriv->smart_grab = smart; +} + +/* + * Handle a colormap release request from a proxy. + */ + +int +ProcLbxReleaseCmap(client) + register ClientPtr client; +{ + REQUEST(xLbxReleaseCmapReq); + ColormapPtr pmap; + +#ifdef COLOR_DEBUG + fprintf (stderr, "Got colormap release request, "); + fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n", + client->sequence, LbxProxyID(client), client->index, stuff->cmap); +#endif + + pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + + if (!pmap) + { + client->errorValue = stuff->cmap; + return BadColor; + } + + if (LbxGrabbedByClient(client, pmap)) + LbxReleaseCmap(pmap, TRUE); + return Success; +} + + +/* + * Handle an LbxAllocColor request. The proxy did the alloc and + * is telling the server what rgb and pixel value to use. + */ + +int +ProcLbxAllocColor(client) + register ClientPtr client; +{ + REQUEST(xLbxAllocColorReq); + ColormapPtr pmap; + CARD32 pixel = stuff->pixel; + + REQUEST_SIZE_MATCH (xLbxAllocColorReq); + pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + +#ifdef COLOR_DEBUG + fprintf (stderr, + "Got LBX alloc color: seq = 0x%x, proxy = %d, client = %d\n", + client->sequence, LbxProxyID(client), client->index); + fprintf (stderr, " cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n", + stuff->cmap, stuff->pixel, stuff->red, stuff->green, stuff->blue); +#endif + + if (pmap) + { + int status; + if (!LbxGrabbedByClient(client, pmap)) + return BadAccess; + + status = AllocColor (pmap, + &stuff->red, &stuff->green, &stuff->blue, + &pixel, client->index); + + if (status == Success && pixel != stuff->pixel) + { + /* + * Internal error - Proxy allocated different pixel from server + */ +#ifdef COLOR_DEBUG + fprintf(stderr, "got pixel %d (%d, %d, %d), expected %d\n", + pixel, stuff->red, stuff->green, stuff->blue, stuff->pixel); +#endif + FreeColors (pmap, client->index, 1, &pixel, 0L); + return BadAlloc; + } + + return status; + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + + +/* + * The proxy sends an LbxIncrementPixel request when it short circuits + * an AllocColor. The server must bump up the reference count the + * specified amount. + */ + +int +ProcLbxIncrementPixel(client) + register ClientPtr client; +{ + REQUEST(xLbxIncrementPixelReq); + ColormapPtr pmap; + EntryPtr pent; + Pixel pixel; + unsigned short red, green, blue; + VisualPtr pVisual; + int status; + +#ifdef COLOR_DEBUG + fprintf (stderr, + "Got LBX increment pixel: seq = 0x%x, proxy = %d, client = %d\n", + client->sequence, LbxProxyID(client), client->index); + fprintf (stderr, " cmap = 0x%x, pixel = %d\n", + stuff->cmap, stuff->pixel); +#endif + + /* + * Looks up the color associated with the pixel, and then call + * AllocColor() - a bit round-about, but it should work. + */ + + pmap = (ColormapPtr) SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + if (!pmap) { + client->errorValue = stuff->cmap; + return BadColor; + } + + pixel = stuff->pixel; + + switch (pmap->class) { + case StaticColor: + case StaticGray: + red = pmap->red[pixel].co.local.red; + green = pmap->red[pixel].co.local.green; + blue = pmap->red[pixel].co.local.blue; + break; + case GrayScale: + case PseudoColor: + pent = pmap->red + pixel; + red = pent->co.local.red; + green = pent->co.local.green; + blue = pent->co.local.blue; + break; + default: + pVisual = pmap->pVisual; + red = pmap->red[(pixel & pVisual->redMask) >> pVisual->offsetRed].co.local.red; + green = pmap->green[(pixel & pVisual->greenMask) >> pVisual->offsetGreen].co.local.green; + blue = pmap->blue[(pixel & pVisual->blueMask) >> pVisual->offsetBlue].co.local.blue; + break; + } + + status = AllocColor(pmap, &red, &green, &blue, &pixel, client->index); + + if (status == Success && pixel != stuff->pixel) + { + /* + * Internal error - Proxy allocated different pixel from server + */ +#ifdef COLOR_DEBUG + fprintf(stderr, "got pixel %d, expected %d\n", pixel, stuff->pixel); +#endif + FreeColors (pmap, client->index, 1, &pixel, 0L); + return BadAlloc; + } + + return status; +} diff --git a/lbx/lbxdata.h b/lbx/lbxdata.h new file mode 100644 index 000000000..d5240f7ea --- /dev/null +++ b/lbx/lbxdata.h @@ -0,0 +1,44 @@ +/* $Xorg: lbxdata.h,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */ +/* + * Copyright 1994 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef _LBXDATA_H_ +#define _LBXDATA_H_ +#define NEED_REPLIES +#include "X.h" +#include "Xproto.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "dixfontstr.h" + +extern int lbx_font_private; + +typedef struct _fonttaginfo { + XID tid; + FontPtr pfont; + unsigned long size; + int compression; + xLbxFontInfo *fontinfo; +} FontTagInfoRec, *FontTagInfoPtr; + +#endif /* _LBXDATA_H_ */ diff --git a/lbx/lbxdix.c b/lbx/lbxdix.c new file mode 100644 index 000000000..e4822f190 --- /dev/null +++ b/lbx/lbxdix.c @@ -0,0 +1,887 @@ +/* $Xorg: lbxdix.c,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ +/* + +Copyright 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1993 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* various bits of DIX-level mangling */ + +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "inputstr.h" +#include "servermd.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "propertyst.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbxtags.h" +#include "lbxdata.h" +#include "Xfuncproto.h" + +extern void CopySwap32Write(); +extern int (*ProcVector[256]) (); +extern int (*SwappedProcVector[256]) (); +extern void (*ReplySwapVector[256]) (); + +extern void LbxWriteSConnSetupPrefix(); + +int lbx_font_private; + +void +LbxDixInit() +{ + TagInit(); + lbx_font_private = AllocateFontPrivateIndex(); +} + +/* ARGSUSED */ +void +LbxAllowMotion(client, num) + ClientPtr client; + int num; +{ + LbxProxyPtr proxy = LbxProxy(client); + proxy->motion_allowed_events += num; +} + +extern WindowPtr *WindowTable; +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; +extern int connBlockScreenStart; + +int +LbxSendConnSetup(client, reason) + ClientPtr client; + char *reason; +{ + int dlength; + int i, ndex, lim, wndex; + CARD32 dataBuf[16]; + xLbxConnSetupPrefix csp; + NewClientInfoRec nci; + LbxProxyPtr proxy = LbxProxy(client); + + if (reason) { + SendConnSetup(client, reason); + LbxForceOutput(proxy); /* expedient to avoid another state variable */ + return (client->noClientException); + } + + IncrementClientCount(); + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; + dataBuf[0] = client->clientAsMask; + + csp.success = TRUE; + csp.majorVersion = connSetupPrefix.majorVersion; + csp.minorVersion = connSetupPrefix.minorVersion; + csp.tag = 0; +#ifdef XAPPGROUP + if (!client->appgroup) { +#endif + csp.changeType = 1; /* LbxNormalDeltas */ + csp.length = 2 + /* tag + resource-id-base */ + screenInfo.numScreens; /* input-mask per screen */ + wndex = 0; ndex = 1; lim = screenInfo.numScreens; +#ifdef XAPPGROUP + } else { + csp.changeType = 2; /* LbxAppGroupDeltas */ + csp.length = 7 + /* tag, res-id-base, root, visual, colormap, b&w-pix */ + 1 + screenInfo.numScreens - screenInfo.numVideoScreens; + XagGetDeltaInfo (client, &dataBuf[1]); + for (i = 0; i < MAXSCREENS; i++) { + if ((CARD32) WindowTable[i]->drawable.id == dataBuf[1]) { + dataBuf[6] = WindowTable[i]->eventMask | wOtherEventMasks(WindowTable[i]); + break; + } + } + wndex = screenInfo.numVideoScreens; + ndex = 7; + lim = screenInfo.numScreens - screenInfo.numVideoScreens; + } +#endif + for (i = 0; i < lim; i++, ndex++, wndex++) { + dataBuf[ndex] = + WindowTable[wndex]->eventMask | wOtherEventMasks(WindowTable[wndex]); + } + dlength = (csp.length - 1) << 2; + + if (LbxProxyClient(proxy)->swapped) { + swaps(&csp.length, i); + } + + if (client->swapped) { + LbxWriteSConnSetupPrefix(client, &csp); + SwapLongs(dataBuf, (1 + screenInfo.numScreens)); + WriteToClient(client, dlength, (pointer) dataBuf); + } else { + WriteToClient(client, sizeof(xLbxConnSetupPrefix), (char *) &csp); + WriteToClient(client, dlength, (pointer) dataBuf); + } + + LbxForceOutput(proxy); /* expedient to avoid another state variable */ + client->clientState = ClientStateRunning; + if (ClientStateCallback) { + if (LbxProxyClient(proxy)->swapped != client->swapped) { + swaps(&csp.length, i); + } + nci.client = client; + nci.prefix = (xConnSetupPrefix*) &csp; + nci.setup = (xConnSetup *) ConnectionInfo; + CallCallbacks(&ClientStateCallback, (pointer) &nci); + } + + return client->noClientException; +} + +extern InputInfo inputInfo; + +static XID modifier_map_tag; + +int +LbxGetModifierMapping(client) + ClientPtr client; +{ + TagData td; + pointer tagdata; + xLbxGetModifierMappingReply rep; + register KeyClassPtr keyc = inputInfo.keyboard->key; + int dlength = keyc->maxKeysPerModifier << 3; + Bool tag_known = FALSE, + send_data; + int n; + + if (!modifier_map_tag) { + tagdata = (pointer) keyc->modifierKeyMap; + TagSaveTag(LbxTagTypeModmap, dlength, tagdata, &modifier_map_tag); + } else { + td = TagGetTag(modifier_map_tag); + tagdata = td->tdata; + tag_known = TagProxyMarked(modifier_map_tag, LbxProxyID(client)); + } + if (modifier_map_tag) + TagMarkProxy(modifier_map_tag, LbxProxyID(client)); + + send_data = (!modifier_map_tag || !tag_known); + + rep.type = X_Reply; + rep.keyspermod = keyc->maxKeysPerModifier; + rep.sequenceNumber = client->sequence; + rep.tag = modifier_map_tag; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + if (send_data) + rep.length = dlength >> 2; + else + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.tag, n); + } + WriteToClient(client, sizeof(xLbxGetModifierMappingReply), (char *)&rep); + + if (send_data) + WriteToClient(client, dlength, (char *) tagdata); + + return client->noClientException; +} + +void +LbxFlushModifierMapTag() +{ + + if (modifier_map_tag) + TagDeleteTag(modifier_map_tag); +} + +static XID keyboard_map_tag; + +int +LbxGetKeyboardMapping(client) + ClientPtr client; +{ + TagData td; + pointer tagdata; + xLbxGetKeyboardMappingReply rep; + + REQUEST(xLbxGetKeyboardMappingReq); + KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + int dlength; + Bool tag_known = FALSE, + send_data; + int n; + + REQUEST_SIZE_MATCH(xLbxGetKeyboardMappingReq); + + if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || + (stuff->firstKeyCode > curKeySyms->maxKeyCode)) { + client->errorValue = stuff->firstKeyCode; + return BadValue; + } + if (stuff->firstKeyCode + stuff->count > curKeySyms->maxKeyCode + 1) { + client->errorValue = stuff->count; + return BadValue; + } + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.keysperkeycode = curKeySyms->mapWidth; + /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ + + if (!keyboard_map_tag) { + tagdata = (pointer) &curKeySyms->map[(stuff->firstKeyCode - + curKeySyms->minKeyCode) * curKeySyms->mapWidth]; + dlength = (curKeySyms->mapWidth * stuff->count); + TagSaveTag(LbxTagTypeKeymap, dlength, tagdata, &keyboard_map_tag); + } else { + td = TagGetTag(keyboard_map_tag); + tagdata = td->tdata; + tag_known = TagProxyMarked(keyboard_map_tag, LbxProxyID(client)); + } + if (keyboard_map_tag) + TagMarkProxy(keyboard_map_tag, LbxProxyID(client)); + + send_data = (!keyboard_map_tag || !tag_known); + rep.type = X_Reply; + rep.keysperkeycode = curKeySyms->mapWidth; + rep.sequenceNumber = client->sequence; + rep.tag = keyboard_map_tag; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + if (send_data) + rep.length = (curKeySyms->mapWidth * stuff->count); + else + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.tag, n); + } + WriteToClient(client, sizeof(xLbxGetKeyboardMappingReply), (char *)&rep); + + if (send_data) { + client->pSwapReplyFunc = CopySwap32Write; + WriteSwappedDataToClient(client, + curKeySyms->mapWidth * stuff->count * sizeof(KeySym), + &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) * + curKeySyms->mapWidth]); + } + return client->noClientException; +} + +void +LbxFlushKeyboardMapTag() +{ + if (keyboard_map_tag) + TagDeleteTag(keyboard_map_tag); +} + +/* counts number of bits needed to hold value */ +static int +_bitsize(val) + int val; +{ + int bits = 1; /* always need one for sign bit */ + + if (val == 0) + return (bits); + + if (val < 0) { + val = -val; + } + while (val) { + bits++; + val >>= 1; + } + + return bits; + +} + +/* + * squashes the font (if possible), returning the new length and + * a pointer to the new data (which has been allocated). if it can't + * squish, it just returns a 0 and the data is sent in raw form. + */ +int _lbx_fi_junklen = sizeof(BYTE) * 2 + sizeof(CARD16) + sizeof(CARD32); + +static int +squish_font_info(qfr, rlen, sqrep) + xQueryFontReply *qfr; + int rlen; + xLbxFontInfo **sqrep; +{ + int len, + hlen; + xLbxFontInfo *new; + xCharInfo *minb, + *maxb, + *ci, + bbox; + int i; + char *t; + xLbxCharInfo *chars; + int num_chars; + + num_chars = qfr->nCharInfos; + + if (num_chars == 0) + return 0; + + minb = &qfr->minBounds; + maxb = &qfr->maxBounds; + /* + * first do the quick check -- if the attribute fields aren't all the + * same, punt + */ + + if (minb->attributes != maxb->attributes) + return 0; + +#define compute(field) \ + bbox.field = max(_bitsize(minb->field), _bitsize(maxb->field)) + + compute(characterWidth); + compute(leftSideBearing); + compute(rightSideBearing); + compute(ascent); + compute(descent); + +#undef compute + + /* make sure it fits */ + if (!((bbox.characterWidth <= LBX_WIDTH_BITS) && + (bbox.leftSideBearing <= LBX_LEFT_BITS) && + (bbox.rightSideBearing <= LBX_RIGHT_BITS) && + (bbox.ascent <= LBX_ASCENT_BITS) && + (bbox.descent <= LBX_DESCENT_BITS))) { + return 0; + } + + hlen = sizeof(xLbxFontInfo) + qfr->nFontProps * sizeof(xFontProp); + + len = hlen + (num_chars * sizeof(xLbxCharInfo)); + + new = (xLbxFontInfo *) xalloc(len); + if (!new) + return 0; + + /* gross hack to avoid copying all the fields */ + t = (char *) qfr; + t += _lbx_fi_junklen; + + /* copy all but the char infos */ + memcpy((char *) new, (char *) t, hlen); + + t = (char *) new; + t += hlen; + chars = (xLbxCharInfo *) t; + + t = (char *) qfr; + t += sizeof(xQueryFontReply) + qfr->nFontProps * sizeof(xFontProp); + ci = (xCharInfo *) t; + + /* now copy & pack the charinfos */ + for (i = 0; i < num_chars; i++, chars++, ci++) { + chars->metrics = 0; + chars->metrics |= (LBX_MASK_BITS(ci->characterWidth, LBX_WIDTH_BITS) + << LBX_WIDTH_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->leftSideBearing, LBX_LEFT_BITS) + << LBX_LEFT_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->rightSideBearing, LBX_RIGHT_BITS) + << LBX_RIGHT_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->ascent, LBX_ASCENT_BITS) + << LBX_ASCENT_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->descent, LBX_DESCENT_BITS) + << LBX_DESCENT_SHIFT); + } + + *sqrep = new; + return len; +} + +int +LbxQueryFont(client) + ClientPtr client; +{ + xQueryFontReply *reply; + xLbxQueryFontReply lbxrep; + FontPtr pFont; + register GC *pGC; + Bool send_data = FALSE; + Bool free_data = FALSE; + int rlength = 0; + FontTagInfoPtr ftip; + int sqlen = 0; + xLbxFontInfo *sqrep, + *sreply = NULL; + + REQUEST(xLbxQueryFontReq); + + REQUEST_SIZE_MATCH(xLbxQueryFontReq); + + client->errorValue = stuff->fid; /* EITHER font or gc */ + pFont = (FontPtr) SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC || !pGC->font) { /* catch a non-existent builtin font */ + client->errorValue = stuff->fid; + return (BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + + /* get tag (if any) */ + ftip = (FontTagInfoPtr) FontGetPrivate(pFont, lbx_font_private); + + if (!ftip) { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = (xQueryFontReply *) xalloc(rlength); + if (!reply) { + return (BadAlloc); + } + free_data = TRUE; + send_data = TRUE; + QueryFont(pFont, reply, nprotoxcistructs); + + sqlen = squish_font_info(reply, rlength, &sqrep); + if (!sqlen) { /* if it failed to squish, send it raw */ + char *t; + + lbxrep.compression = 0; + + sqlen = rlength - _lbx_fi_junklen; + t = (char *) reply; + sqrep = (xLbxFontInfo *) (t + _lbx_fi_junklen); + } else { + lbxrep.compression = 1; + xfree(reply); /* no longer needed */ + } + } else { /* just get data from tag */ + sqrep = ftip->fontinfo; + sqlen = ftip->size; + lbxrep.compression = ftip->compression; + } + + if (!ftip) { + /* data allocation is done when font is first queried */ + ftip = (FontTagInfoPtr) xalloc(sizeof(FontTagInfoRec)); + if (ftip && + TagSaveTag(LbxTagTypeFont, sqlen, (pointer) ftip, &ftip->tid)) { + FontSetPrivate(pFont, lbx_font_private, (pointer) ftip); + ftip->pfont = pFont; + ftip->size = sqlen; + ftip->fontinfo = sqrep; + ftip->compression = lbxrep.compression; + free_data = FALSE; + } else { + xfree(ftip); + } + } + if (ftip) { + if (!TagProxyMarked(ftip->tid, LbxProxyID(client))) + send_data = TRUE; + TagMarkProxy(ftip->tid, LbxProxyID(client)); + lbxrep.tag = ftip->tid; + } else { + lbxrep.tag = 0; + send_data = TRUE; + } + + lbxrep.type = X_Reply; + lbxrep.sequenceNumber = client->sequence; + lbxrep.pad0 = lbxrep.pad1 = lbxrep.pad2 = lbxrep.pad3 = lbxrep.pad4 = 0; + + if (send_data) + lbxrep.length = sqlen >> 2; + else + lbxrep.length = 0; + + if (client->swapped) { + int n; + + swaps(&lbxrep.sequenceNumber, n); + swapl(&lbxrep.length, n); + swapl(&lbxrep.tag, n); + sreply = (xLbxFontInfo *) ALLOCATE_LOCAL(sqlen); + if (!sreply) + return BadAlloc; + memcpy((char *) sreply, (char *) sqrep, sqlen); + LbxSwapFontInfo(sreply, lbxrep.compression); + sqrep = sreply; + } + WriteToClient(client, sizeof(xLbxQueryFontReply), (char *) &lbxrep); + if (send_data) + WriteToClient(client, sqlen, (char *)sqrep); + if (free_data) + xfree(sqrep); + if (sreply) + DEALLOCATE_LOCAL(sreply); + return (client->noClientException); +} + +void +LbxFreeFontTag(pfont) + FontPtr pfont; +{ + FontTagInfoPtr ftip; + + ftip = (FontTagInfoPtr) FontGetPrivate(pfont, lbx_font_private); + if (ftip) + TagDeleteTag(ftip->tid); +} + +LbxInvalidateTag(client, tag) + ClientPtr client; + XID tag; +{ + TagClearProxy(tag, LbxProxyID(client)); + return client->noClientException; +} + +void +LbxSendInvalidateTag(client, tag, tagtype) + ClientPtr client; + XID tag; + int tagtype; +{ + xLbxInvalidateTagEvent ev; + int n; + + ev.type = LbxEventCode; + ev.lbxType = LbxInvalidateTagEvent; + ev.sequenceNumber = client->sequence; + ev.tag = tag; + ev.tagType = tagtype; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = 0; + + if (client->swapped) { + swaps(&ev.sequenceNumber, n); + swapl(&ev.tag, n); + swapl(&ev.tagType, n); + } + DBG(DBG_CLIENT, (stderr, "Invalidating tag %d\n", tag)); + WriteToClient(client, sizeof(xLbxInvalidateTagEvent), (char *) &ev); + LbxForceOutput(LbxProxy(client)); +} + +static void +LbxSendSendTagData(pid, tag, tagtype) + int pid; + XID tag; + int tagtype; +{ + xLbxSendTagDataEvent ev; + int n; + LbxProxyPtr proxy; + ClientPtr client; + LbxClientPtr lbxcp; + + proxy = LbxPidToProxy(pid); + lbxcp = (proxy != NULL) ? proxy->lbxClients[0] : NULL; + if (lbxcp && (client = lbxcp->client)) { + ev.type = LbxEventCode; + ev.lbxType = LbxSendTagDataEvent; + ev.sequenceNumber = client->sequence; + ev.tag = tag; + ev.tagType = tagtype; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = 0; + + if (client->swapped) { + swaps(&ev.sequenceNumber, n); + swapl(&ev.tag, n); + swapl(&ev.tagType, n); + } + DBG(DBG_CLIENT, (stderr, "Requesting tag %d\n", tag)); + WriteToClient(client, sizeof(xLbxSendTagDataEvent), (char *) &ev); + LbxForceOutput(proxy); + } +} + +/* + * keep track of clients stalled waiting for tags to come back from + * a proxy. since multiple clinets can be waiting for the same tag, + * we have to keep a list of all of them. + */ + +typedef struct _sendtagq { + XID tag; + int num_stalled; + ClientPtr *stalled_clients; + struct _sendtagq *next; +} SendTagQRec, *SendTagQPtr; + +static SendTagQPtr queried_tags = NULL; + +#define LbxSendTagFailed -1 +#define LbxSendTagSendIt 0 +#define LbxSendTagAlreadySent 1 + +static Bool +LbxQueueSendTag(client, tag) + ClientPtr client; + XID tag; +{ + SendTagQPtr stqp, *prev, new; + ClientPtr *newlist; + + + /* see if we're asking for one already in the pipeline */ + for (prev = &queried_tags; stqp = *prev; prev = &stqp->next) { + if (stqp->tag == tag) { + /* add new client to list */ + newlist = (ClientPtr *) xrealloc(stqp->stalled_clients, + (sizeof(ClientPtr) * (stqp->num_stalled + 1))); + if (!newlist) + return LbxSendTagFailed; + newlist[stqp->num_stalled++] = client; + stqp->stalled_clients = newlist; + DBG(DBG_CLIENT, (stderr, "Additional client requesting tag %d\n", tag)); + return LbxSendTagAlreadySent; + } + } + + /* make new one */ + new = (SendTagQPtr) xalloc(sizeof(SendTagQRec)); + newlist = (ClientPtr *) xalloc(sizeof(ClientPtr)); + if (!new || !newlist) { + xfree(new); + xfree(newlist); + return LbxSendTagFailed; + } + *newlist = client; + new->stalled_clients = newlist; + new->num_stalled = 1; + new->tag = tag; + new->next = NULL; + + /* stick on end of list */ + *prev = new; + return LbxSendTagSendIt; +} + +SendTagQPtr +LbxFindQTag(tag) + XID tag; +{ + SendTagQPtr stqp; + + for (stqp = queried_tags; stqp; stqp = stqp->next) { + if (stqp->tag == tag) + return stqp; + } + return NULL; +} + +static void +LbxFreeQTag(stqp) + SendTagQPtr stqp; +{ + xfree(stqp->stalled_clients); + xfree(stqp); +} + +static void +LbxRemoveQTag(tag) + XID tag; +{ + SendTagQPtr stqp, *prev; + + for (prev = &queried_tags; stqp = *prev; prev = &stqp->next) { + if (stqp->tag == tag) { + *prev = stqp->next; + LbxFreeQTag(stqp); + return; + } + } +} + +Bool +LbxFlushQTag(tag) + XID tag; +{ + SendTagQPtr stqp; + ClientPtr *cp; + + stqp = LbxFindQTag(tag); + if (!stqp) + return FALSE; + for (cp = stqp->stalled_clients; --stqp->num_stalled >= 0; cp++) + AttendClient(*cp); + LbxRemoveQTag(tag); + return TRUE; +} + +void +ProcessQTagZombies() +{ + SendTagQPtr stqp; + ClientPtr *out, *in; + int i; + + for (stqp = queried_tags; stqp; stqp = stqp->next) { + out = stqp->stalled_clients; + for (in = out, i = stqp->num_stalled; --i >= 0; in++) { + if ((*in)->clientGone) + --stqp->num_stalled; + else + *out++ = *in; + } + } +} + +/* + * server sends this + */ + +void +LbxQueryTagData(client, owner_pid, tag, tagtype) + ClientPtr client; + int owner_pid; + XID tag; + int tagtype; +{ + /* save the info and the client being stalled */ + if (LbxQueueSendTag(client, tag) == LbxSendTagSendIt) + LbxSendSendTagData(owner_pid, tag, tagtype); +} + +/* + * server recieves this + */ +int +LbxTagData(client, tag, len, data) + ClientPtr client; + XID tag; + unsigned long len; + pointer data; +{ + TagData td; + PropertyPtr pProp; + + td = TagGetTag(tag); + if (!td || td->data_type != LbxTagTypeProperty) + return Success; + if (!td->global) { + /* somebody changed contents while we were querying */ + TagDeleteTag(tag); + return Success; + } + LbxFlushQTag(tag); + pProp = (PropertyPtr) td->tdata; + if (pProp->tag_id != tag || pProp->owner_pid != LbxProxyID(client)) + return Success; + pProp->owner_pid = 0; + if (len != td->size) + pProp->size = len / (pProp->format >> 3); + pProp->data = xrealloc(pProp->data, len); + if (!pProp->data) { + pProp->size = 0; + return Success; + } + if (client->swapped) { + switch (pProp->format) { + case 32: + SwapLongs((CARD32 *) data, len >> 2); + break; + case 16: + SwapShorts((short *) data, len >> 1); + break; + default: + break; + } + } + memmove((char *) pProp->data, (char *) data, len); + return Success; +} + +/* when server resets, need to reset global tags */ +void +LbxResetTags() +{ + SendTagQPtr stqp; + + modifier_map_tag = 0; + keyboard_map_tag = 0; + + /* clean out any pending tag requests */ + while (stqp = queried_tags) { + queried_tags = stqp->next; + LbxFreeQTag(stqp); + } +} diff --git a/lbx/lbxexts.c b/lbx/lbxexts.c new file mode 100644 index 000000000..4ee5f87c6 --- /dev/null +++ b/lbx/lbxexts.c @@ -0,0 +1,270 @@ +/* $Xorg: lbxexts.c,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */ +/* + * Copyright 1994 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +typedef struct _lbxext { + char *name; + char **aliases; + int num_aliases; + int idx; + int opcode; + int ev_base; + int err_base; + int num_reqs; + CARD8 *rep_mask; + CARD8 *ev_mask; +#ifdef XCSECURITY + Bool secure; +#endif +} LbxExtensionEntry; + +static LbxExtensionEntry **lbx_extensions = NULL; +static int num_exts = 0; + + +Bool +LbxAddExtension(name, opcode, ev_base, err_base) + char *name; + int opcode; + int ev_base, + err_base; +{ + int i; + register LbxExtensionEntry *ext, + **newexts; + + ext = (LbxExtensionEntry *) xalloc(sizeof(LbxExtensionEntry)); + if (!ext) + return FALSE; + ext->name = (char *) xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **) NULL; + if (!ext->name) { + xfree(ext); + return FALSE; + } + strcpy(ext->name, name); + i = num_exts; + newexts = (LbxExtensionEntry **) xrealloc(lbx_extensions, + (i + 1) * sizeof(LbxExtensionEntry *)); + if (!newexts) { + xfree(ext->name); + xfree(ext); + return FALSE; + } + num_exts++; + lbx_extensions = newexts; + lbx_extensions[i] = ext; + ext->idx = i; + + ext->opcode = opcode;; + ext->ev_base = ev_base;; + ext->err_base = err_base; + ext->ev_mask = NULL; + ext->rep_mask = NULL; + ext->num_reqs = 0; +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + + return TRUE; +} + +Bool +LbxAddExtensionAlias(idx, alias) + int idx; + char *alias; +{ + char *name; + char **aliases; + LbxExtensionEntry *ext = lbx_extensions[idx]; + + aliases = (char **) xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *) xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; + return TRUE; +} + +static int +LbxFindExtension(extname, len) + char *extname; + int len; +{ + int i, j; + + for (i = 0; i < num_exts; i++) { + if ((strlen(lbx_extensions[i]->name) == len) && + (strncmp(lbx_extensions[i]->name, extname, len) == 0)) + return i; + for (j = lbx_extensions[i]->num_aliases; --j >= 0;) { + if ((strlen(lbx_extensions[i]->aliases[j]) == len) && + (strncmp(lbx_extensions[i]->aliases[j], extname, len) == 0)) + return i; + } + } + return -1; +} + +void +LbxDeclareExtensionSecurity(extname, secure) + char *extname; + Bool secure; +{ +#ifdef XCSECURITY + int i = LbxFindExtension(extname, strlen(extname)); + if (i >= 0) + lbx_extensions[i]->secure = secure; +#endif +} + +Bool +LbxRegisterExtensionGenerationMasks(idx, num_reqs, rep_mask, ev_mask) + int idx; + int num_reqs; + char *rep_mask, + *ev_mask; +{ + LbxExtensionEntry *ext = lbx_extensions[idx]; + CARD8 *nrm, + *nem; + int mlen = mlen = num_reqs / (8 * sizeof(CARD8)) + 1; + + nrm = (CARD8 *) xalloc(sizeof(CARD8) * mlen); + nem = (CARD8 *) xalloc(sizeof(CARD8) * mlen); + + if (!nrm || !nem) { + xfree(nrm); + xfree(nem); + return FALSE; + } + memcpy((char *) nrm, (char *) rep_mask, mlen); + memcpy((char *) nem, (char *) ev_mask, mlen); + ext->rep_mask = nrm; + ext->ev_mask = nem; + ext->num_reqs = num_reqs; + + return TRUE; +} + +int +LbxQueryExtension(client, ename, nlen) + ClientPtr client; + char *ename; + int nlen; +{ + xLbxQueryExtensionReply rep; + int i; + int mlen = 0; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.major_opcode = 0; + rep.present = FALSE; + rep.length = 0; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + i = LbxFindExtension(ename, nlen); + + if (i < 0 +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !lbx_extensions[i]->secure) +#endif + ) + rep.present = FALSE; + else { + rep.present = TRUE; + rep.major_opcode = lbx_extensions[i]->opcode; + rep.first_event = lbx_extensions[i]->ev_base; + rep.first_error = lbx_extensions[i]->err_base; + rep.numReqs = lbx_extensions[i]->num_reqs; + if (lbx_extensions[i]->rep_mask) { + mlen = (lbx_extensions[i]->num_reqs + 7) >> 3; + rep.length = ((mlen + 3) >> 2) * 2; + } + } + if (client->swapped) { + char n; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xLbxQueryExtensionReply), (char *)&rep); + if (mlen) { + WriteToClient(client, mlen, (char *)lbx_extensions[i]->rep_mask); + WriteToClient(client, mlen, (char *)lbx_extensions[i]->ev_mask); + } + return Success; +} + +LbxCloseDownExtensions() +{ + int i; + + for (i = 0; i < num_exts; i++) { + xfree(lbx_extensions[i]->name); + xfree(lbx_extensions[i]->aliases); + xfree(lbx_extensions[i]->rep_mask); + xfree(lbx_extensions[i]->ev_mask); + xfree(lbx_extensions[i]); + } + xfree(lbx_extensions); + lbx_extensions = NULL; + num_exts = 0; +} + +void +LbxSetReqMask(mask, req, on) + CARD8 *mask; + int req; + Bool on; +{ + int mword = req / (8 * sizeof(CARD8)); + + req = req % (8 * sizeof(CARD8)); + if (on) { + mask[mword] |= (1 << req); + } else { + mask[mword] &= ~(1 << req); + } +} diff --git a/lbx/lbxgfx.c b/lbx/lbxgfx.c new file mode 100644 index 000000000..25e87cc63 --- /dev/null +++ b/lbx/lbxgfx.c @@ -0,0 +1,867 @@ +/* $Xorg: lbxgfx.c,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */ +/* + * Copyright 1993 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* various bits of DIX-level mangling */ + +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "servermd.h" +#include "windowstr.h" +#include "scrnintstr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbxtags.h" +#include "Xfuncproto.h" +#include "lbximage.h" +#include "lbxsrvopts.h" + +#define DrawableCache(client) (LbxClient(client)->drawableCache) +#define GContextCache(client) (LbxClient(client)->gcontextCache) + +extern int (*ProcVector[256])(); + +static void +push (cache, xid) + XID cache[GFX_CACHE_SIZE]; + XID xid; +{ + memmove (cache+1, cache, (GFX_CACHE_SIZE - 1) * sizeof (cache[0])); + cache[0] = xid; +} + +static XID +use (cache, i) + XID cache[GFX_CACHE_SIZE]; + int i; +{ + XID tmp; + + tmp = cache[i]; + if (i != 0) + { + memmove (cache + 1, cache, i * sizeof (cache[0])); + cache[0] = tmp; + } + return tmp; +} + +extern char *ConnectionInfo; + +int +LbxDecodeGFXCache(client, cacheEnts, after, drawp, gcp) + ClientPtr client; + CARD8 cacheEnts; + char *after; + Drawable *drawp; + GContext *gcp; +{ + int skip; + int dcache, gcache; + + dcache = GFXdCacheEnt (cacheEnts); + gcache = GFXgCacheEnt (cacheEnts); + skip = 0; + if (dcache == GFXCacheNone) + { + memcpy (drawp, after, sizeof (Drawable)); + push (DrawableCache(client), *drawp); + after += sizeof (Drawable); + skip += sizeof (Drawable); + } + else + *drawp = use (DrawableCache(client), dcache); + if (gcache == GFXCacheNone) + { + memcpy (gcp, after, sizeof (GContext)); + push (GContextCache(client), *gcp); + skip += sizeof (GContext); + } + else + *gcp = use (GContextCache(client), gcache); + return skip; +} + +int +LbxDecodeDrawableCache(client, cacheEnts, after, drawp) + ClientPtr client; + CARD8 cacheEnts; + char *after; + Drawable *drawp; +{ + int skip; + int dcache; + + dcache = GFXdCacheEnt (cacheEnts); + skip = 0; + if (dcache == GFXCacheNone) + { + memcpy (drawp, after, sizeof (Drawable)); + push (DrawableCache(client), *drawp); + after += sizeof (Drawable); + skip += sizeof (Drawable); + } + else + *drawp = use (DrawableCache(client), dcache); + return skip; +} + +int +LbxDecodeGCCache(client, cacheEnts, after, gcp) + ClientPtr client; + CARD8 cacheEnts; + char *after; + GContext *gcp; +{ + int skip; + int gcache; + + gcache = GFXgCacheEnt (cacheEnts); + skip = 0; + if (gcache == GFXCacheNone) + { + memcpy (gcp, after, sizeof (GContext)); + push (GContextCache(client), *gcp); + after += sizeof (GContext); + skip += sizeof (GContext); + } + else + *gcp = use (GContextCache(client), gcache); + return skip; +} + +#define GFX_GET_DRAWABLE_AND_GC(type,in,len) {\ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type);\ + skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \ + &drawable, &gc); \ + in += skip; \ + len -= skip; \ +} + +#define GFX_GET_DST_DRAWABLE_AND_GC(type,in,len) {\ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type);\ + skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \ + &dstDrawable, &gc); \ + in += skip; \ + len -= skip; \ +} + +#define GFX_GET_SRC_DST_DRAWABLE_AND_GC(type, in, len) { \ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type); \ + skip = LbxDecodeDrawableCache(client, stuff->srcCache, in, \ + &srcDrawable); \ + in += skip; \ + len -= skip; \ + skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \ + &dstDrawable, &gc); \ + in += skip; \ + len -= skip; \ +} + +#define GFX_GET_GC(type, in, len) { \ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type); \ + skip = LbxDecodeGCCache(client, stuff->gcCache, in, &gc); \ + in += skip; \ + len -= skip; \ +} + +int +LbxDecodePoly(client, xreqtype, decode_rtn) + register ClientPtr client; + CARD8 xreqtype; + int (*decode_rtn)(); +{ + REQUEST(xLbxPolyPointReq); + char *in; + xPolyPointReq *xreq; + int len; + int retval; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxPolyPointReq, in, len); + if ((xreq = (xPolyPointReq *) + xalloc(sizeof(xPolyPointReq) + (len << 1))) == NULL) + return BadAlloc; + len = (*decode_rtn)(in, in + len - stuff->padBytes, &xreq[1]); + xreq->reqType = xreqtype; + xreq->coordMode = 1; + xreq->drawable = drawable; + xreq->gc = gc; + xreq->length = client->req_len = (sizeof(xPolyPointReq) + len) >> 2; + client->requestBuffer = (pointer)xreq; + + retval = (*ProcVector[xreqtype])(client); + xfree(xreq); + return retval; +} + +int +LbxDecodeFillPoly(client) + register ClientPtr client; +{ + REQUEST(xLbxFillPolyReq); + char *in; + xFillPolyReq *xreq; + int len; + int retval; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxFillPolyReq, in, len); + if ((xreq = (xFillPolyReq *) + xalloc(sizeof(xFillPolyReq) + (len << 1))) == NULL) + return BadAlloc; + len = LbxDecodePoints(in, in + len - stuff->padBytes, (short *) &xreq[1]); + xreq->reqType = X_FillPoly; + xreq->drawable = drawable; + xreq->gc = gc; + xreq->shape = stuff->shape; + xreq->coordMode = 1; + xreq->length = client->req_len = (sizeof(xFillPolyReq) + len) >> 2; + client->requestBuffer = (pointer)xreq; + + retval = (*ProcVector[X_FillPoly])(client); + xfree(xreq); + return retval; +} + +/* + * Routines for decoding line drawing requests + */ + +#define DECODE_PSHORT(in, val) \ + if ((*(in) & 0xf0) != 0xf0) \ + (val) = *(CARD8 *)(in)++; \ + else { \ + (val) = ((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1); \ + if ((val) >= 0xe00) \ + (val) -= 0x1000; \ + else \ + (val) += 0xf0; \ + (in) += 2; \ + } + +#define DECODE_SHORT(in, val) \ + if ((*(in) & 0xf0) != 0x80) \ + (val) = *(INT8 *)(in)++; \ + else { \ + (val) = ((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1); \ + if ((val) & 0x0800) \ + (val) = ((val) | 0xf000) - 0x70; \ + else \ + (val) += 0x80; \ + (in) += 2; \ + } + +#define DECODE_USHORT(in, val) \ + if ((*(in) & 0xf0) != 0xf0) \ + (val) = *(CARD8 *)(in)++; \ + else { \ + (val) = (((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1)) + 0xf0; \ + (in) += 2; \ + } + +#define DECODE_ANGLE(in, val) \ + if (*(INT8 *)(in) >= 0x6e) \ + (val) = (*(INT8 *)(in)++ - 0x67) * (15 << 6); \ + else if (*(INT8 *)(in) >= 0x5a) \ + (val) = (*(INT8 *)(in)++ - 0x5a) * (5 << 6); \ + else if (*(INT8 *)(in) <= (INT8)0x91) \ + (val) = (*(INT8 *)(in)++ - (INT8)0x98) * (15 << 6); \ + else if (*(INT8 *)(in) <= (INT8)0xa5) \ + (val) = (*(INT8 *)(in)++ - (INT8)0xa6) * (5 << 6); \ + else { \ + (val) = (*(CARD8 *)(in) << 8) | *(CARD8 *)((in) + 1); \ + (in) += 2; \ + } + +int +LbxDecodePoints(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, *out); + out++; + DECODE_SHORT(in, *out); + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeSegment(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + register short diff; + short last_x = 0; + short last_y = 0; + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, diff); + *out = last_x + diff; + last_x += diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + last_y += diff; + out++; + + DECODE_SHORT(in, diff); + *out = last_x + diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeRectangle(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + register short diff; + short last_x = 0; + short last_y = 0; + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, diff); + *out = last_x + diff; + last_x += diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + last_y += diff; + out++; + + DECODE_USHORT(in, *(unsigned short *)out); + out++; + DECODE_USHORT(in, *(unsigned short *)out); + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeArc(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + register short diff; + short last_x = 0; + short last_y = 0; + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, diff); + *out = last_x + diff; + last_x += diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + last_y += diff; + out++; + + DECODE_USHORT(in, *(unsigned short *)out); + out++; + DECODE_USHORT(in, *(unsigned short *)out); + out++; + + DECODE_ANGLE(in, *out); + out++; + DECODE_ANGLE(in, *out); + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeCopyArea (client) + ClientPtr client; +{ + REQUEST(xLbxCopyAreaReq); + char *in; + xCopyAreaReq req; + int len; + Drawable srcDrawable, dstDrawable; + GContext gc; + + GFX_GET_SRC_DST_DRAWABLE_AND_GC(xLbxCopyAreaReq, in, len); + req.reqType = X_CopyArea; + req.length = client->req_len = SIZEOF(xCopyAreaReq) >> 2; + req.srcDrawable = srcDrawable; + req.dstDrawable = dstDrawable; + req.gc = gc; + DECODE_PSHORT (in, req.srcX); + DECODE_PSHORT (in, req.srcY); + DECODE_PSHORT (in, req.dstX); + DECODE_PSHORT (in, req.dstY); + DECODE_USHORT (in, req.width); + DECODE_USHORT (in, req.height); + client->requestBuffer = (pointer) &req; + return (*ProcVector[X_CopyArea])(client); +} + +int +LbxDecodeCopyPlane (client) + ClientPtr client; +{ + REQUEST(xLbxCopyPlaneReq); + char *in; + xCopyPlaneReq req; + int len; + Drawable srcDrawable, dstDrawable; + GContext gc; + + GFX_GET_SRC_DST_DRAWABLE_AND_GC(xLbxCopyPlaneReq, in, len); + req.reqType = X_CopyPlane; + req.length = client->req_len = SIZEOF(xCopyPlaneReq) >> 2; + req.srcDrawable = srcDrawable; + req.dstDrawable = dstDrawable; + req.gc = gc; + DECODE_PSHORT (in, req.srcX); + DECODE_PSHORT (in, req.srcY); + DECODE_PSHORT (in, req.dstX); + DECODE_PSHORT (in, req.dstY); + DECODE_USHORT (in, req.width); + DECODE_USHORT (in, req.height); + req.bitPlane = stuff->bitPlane; + client->requestBuffer = (pointer) &req; + return (*ProcVector[X_CopyPlane])(client); +} + +static pointer +get_gfx_buffer(client, len) + ClientPtr client; + int len; +{ + LbxClientPtr lbxClient = LbxClient(client); + pointer tmp; + + /* XXX should probably shrink this sucker too */ + if (len > lbxClient->gb_size) { + tmp = (pointer) xrealloc(lbxClient->gfx_buffer, len); + if (!tmp) + return (pointer) NULL; + lbxClient->gfx_buffer = tmp; + lbxClient->gb_size = len; + } + return lbxClient->gfx_buffer; +} + +int +LbxDecodePolyText (client) + ClientPtr client; +{ + REQUEST(xLbxPolyTextReq); + char *in, *pos; + xPolyTextReq *xreq; + int len; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxPolyTextReq, in, len); + xreq = (xPolyTextReq *) get_gfx_buffer(client, sizeof (xPolyTextReq) + len); + if (!xreq) + return BadAlloc; + xreq->reqType = stuff->lbxReqType == X_LbxPolyText8? X_PolyText8 : X_PolyText16; + xreq->drawable = drawable; + xreq->gc = gc; + pos = in; + DECODE_PSHORT(in, xreq->x); + DECODE_PSHORT(in, xreq->y); + len -= (in - pos); + memmove ((char *) (xreq + 1), in, len); + xreq->length = client->req_len = (sizeof (xPolyTextReq) + len) >> 2; + client->requestBuffer = (pointer) xreq; + return (*ProcVector[xreq->reqType])(client); +} + +int +LbxDecodeImageText (client) + ClientPtr client; +{ + REQUEST(xLbxImageTextReq); + char *in, *pos; + xImageTextReq *xreq; + int len; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxImageTextReq, in, len); + xreq = (xImageTextReq *) get_gfx_buffer(client, sizeof (xImageTextReq) + len); + if (!xreq) + return BadAlloc; + xreq->reqType = stuff->lbxReqType == X_LbxImageText8? X_ImageText8 : X_ImageText16; + xreq->drawable = drawable; + xreq->gc = gc; + xreq->nChars = stuff->nChars; + pos = in; + DECODE_PSHORT(in, xreq->x); + DECODE_PSHORT(in, xreq->y); + len -= (in - pos); + memmove ((char *) (xreq + 1), in, len); + xreq->length = client->req_len = (sizeof (xImageTextReq) + len) >> 2; + client->requestBuffer = (pointer) xreq; + return (*ProcVector[xreq->reqType])(client); +} + +int +LbxDecodePutImage (client) + register ClientPtr client; +{ + REQUEST (xLbxPutImageReq); + char *in, *data; + xPutImageReq xreq; + int ppl, bpl, nbytes; + int retval; + int n; + + xreq.reqType = X_PutImage; + + in = (char *) stuff + sz_xLbxPutImageReq; + + if (stuff->bitPacked & 0x80) { + xreq.format = (stuff->bitPacked >> 5) & 0x3; + xreq.depth = ((stuff->bitPacked >> 2) & 0x7) + 1; + xreq.leftPad = 0; + } else { + xreq.depth = (stuff->bitPacked >> 2) + 1; + xreq.format = (*in >> 5) & 0x3; + xreq.leftPad = *in++ & 0x1f; + } + DECODE_USHORT(in, xreq.width); + DECODE_USHORT(in, xreq.height); + DECODE_PSHORT(in, xreq.dstX); + DECODE_PSHORT(in, xreq.dstY); + if (client->swapped) { + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone || + GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (in, n); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone && + GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (in + 4, n); + } + } + in += LbxDecodeGFXCache(client, stuff->cacheEnts, in, + &xreq.drawable, &xreq.gc); + + ppl = xreq.width + xreq.leftPad; + if (xreq.format != ZPixmap || + (xreq.depth == 1 && screenInfo.formats->bitsPerPixel == 1)) { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + bpl = BitmapBytePadProto(ppl); +#else + bpl = BitmapBytePad(ppl); +#endif + nbytes = bpl; + if (xreq.format == XYPixmap) + nbytes *= xreq.depth; + } else { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + bpl = PixmapBytePadProto(ppl, xreq.depth); +#else + bpl = PixmapBytePad(ppl, xreq.depth); +#endif + nbytes = bpl; + } + nbytes *= xreq.height; + xreq.length = ((nbytes + 3) >> 2) + (sz_xPutImageReq >> 2); + /* +1 is because fillspan in DecodeFaxG42D seems to go 1 byte too far, + * and I don't want to mess with that code */ + if ((data = (char *) xalloc ((xreq.length << 2) + 1)) == NULL) + return BadAlloc; + + *((xPutImageReq *)data) = xreq; + + if (!stuff->compressionMethod) + { + memcpy(data + sz_xPutImageReq, in, nbytes); + } + else if (xreq.format != ZPixmap || + (xreq.depth == 1 && screenInfo.formats->bitsPerPixel == 1)) + { + LbxBitmapCompMethod *compMethod; + + compMethod = LbxSrvrLookupBitmapCompMethod (LbxProxy(client), + stuff->compressionMethod); + + if (!compMethod) + { + xfree (data); + return (BadValue); + } + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + (*compMethod->decompFunc) ( + (unsigned char *) in, (unsigned char *) data + sz_xPutImageReq, + nbytes, +#if BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER + (ppl + BITMAP_SCANLINE_UNIT - 1) & ~BITMAP_SCANLINE_UNIT, +#else + ppl, +#endif + bpl, + ((xConnSetup *) ConnectionInfo)->bitmapBitOrder == LSBFirst); + } + } + else + { + LbxPixmapCompMethod *compMethod; + + compMethod = LbxSrvrLookupPixmapCompMethod (LbxProxy(client), + stuff->compressionMethod); + + if (!compMethod) + { + xfree (data); + return (BadValue); + } + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + (*compMethod->decompFunc) ( + in, (char *) data + sz_xPutImageReq, + (int) xreq.height, bpl); + } + } + + client->req_len = xreq.length; + client->requestBuffer = (pointer) data; + + retval = (*ProcVector[X_PutImage])(client); + xfree(data); + return retval; +} + +int +LbxDecodeGetImage (client) + register ClientPtr client; +{ + REQUEST (xLbxGetImageReq); + xLbxGetImageReply *reply = NULL; + int lbxLen, xLen, n; + int method, bytes, status; + xGetImageReply *theImage; + + REQUEST_SIZE_MATCH(xLbxGetImageReq); + + status = DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, &theImage); + + if (status != Success) + return (status); + + if ((reply = (xLbxGetImageReply *) xalloc ( + sz_xLbxGetImageReply + theImage->length)) == NULL) + { + xfree(theImage); + return (BadAlloc); + } + + if (stuff->format != ZPixmap || + (theImage->depth == 1 && screenInfo.formats->bitsPerPixel == 1)) + { + LbxBitmapCompMethod *compMethod; + + compMethod = LbxSrvrFindPreferredBitmapCompMethod (LbxProxy(client)); + + if (!compMethod) + status = LBX_IMAGE_COMPRESS_NO_SUPPORT; + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + status = (*compMethod->compFunc) ( + (unsigned char *) &theImage[1], + (unsigned char *) &reply[1], + theImage->length, + theImage->length, +#if BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER + (int) (stuff->width + BITMAP_SCANLINE_UNIT - 1) & + ~BITMAP_SCANLINE_UNIT, +#else + (int) stuff->width, +#endif +#ifdef INTERNAL_VS_EXTERNAL_PADDING + BitmapBytePadProto(stuff->width), +#else + BitmapBytePad(stuff->width), +#endif + ((xConnSetup *) ConnectionInfo)->bitmapBitOrder == LSBFirst, + &bytes); + + method = compMethod->methodOpCode; + } + } + else + { + LbxPixmapCompMethod *compMethod; + + compMethod = LbxSrvrFindPreferredPixmapCompMethod ( + LbxProxy(client), (int) stuff->format, theImage->depth); + + if (!compMethod) + status = LBX_IMAGE_COMPRESS_NO_SUPPORT; + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + status = (*compMethod->compFunc) ( + (char *) &theImage[1], + (char *) &reply[1], + theImage->length, + (int) stuff->format, + theImage->depth, + (int) stuff->height, +#ifdef INTERNAL_VS_EXTERNAL_PADDING + PixmapBytePadProto(stuff->width, theImage->depth), +#else + PixmapBytePad(stuff->width, theImage->depth), +#endif + &bytes); + + method = compMethod->methodOpCode; + } + } + + reply->type = X_Reply; + reply->depth = theImage->depth; + reply->sequenceNumber = client->sequence; + reply->visual = theImage->visual; + reply->pad1 = reply->pad2 = reply->pad3 = reply->pad4 = reply->pad5 = 0; + + if (status != LBX_IMAGE_COMPRESS_SUCCESS) + { + reply->compressionMethod = LbxImageCompressNone; + reply->lbxLength = reply->xLength = (theImage->length + 3) >> 2; + } + else + { + reply->compressionMethod = method; + reply->lbxLength = (bytes + 3) >> 2; + reply->xLength = (theImage->length + 3) >> 2; + } + + lbxLen = reply->lbxLength; + xLen = reply->xLength; + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->lbxLength, n); + swapl (&reply->xLength, n); + swapl (&reply->visual, n); + } + + if (reply->compressionMethod != LbxImageCompressNone) + { + /* + * If the compressed image is greater that 25% of the original + * image, run the GetImage reply through the regular stream + * compressor. Otherwise, just write the compressed image. + */ + + if (lbxLen > (xLen / 4)) + { + WriteToClient (client, + sz_xLbxGetImageReply + (lbxLen << 2), (char *)reply); + } + else + { + UncompressedWriteToClient (client, + sz_xLbxGetImageReply + (lbxLen << 2), (char *)reply); + } + } + else + { + /* + * Write back the original uncompressed image. + */ + + WriteToClient (client, sz_xLbxGetImageReply, (char *)reply); + WriteToClient (client, lbxLen << 2, (char *)&theImage[1]); + } + + xfree (theImage); + + if (reply) + xfree ((char *) reply); + + return (Success); +} diff --git a/lbx/lbxmain.c b/lbx/lbxmain.c new file mode 100644 index 000000000..3fa565fef --- /dev/null +++ b/lbx/lbxmain.c @@ -0,0 +1,1819 @@ +/* $Xorg: lbxmain.c,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1992 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of NCD. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. NCD. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD. + * 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. + * + */ + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#include "lbxdeltastr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbximage.h" +#include "lbxsrvopts.h" +#include "Xfuncproto.h" +#include +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif +#include +#include + +#ifndef X_NOT_POSIX +#include +#endif + +#define CloseLbxClient 0xff + +#define MAXBYTESDIFF 8 + +extern void LbxAllowMotion(); +extern int LbxDecodePoints(); +extern int LbxDecodeSegment(); +extern int LbxDecodeRectangle(); +extern int LbxDecodeArc(); + +extern int GrabInProgress; + +int LbxWhoAmI = 1; /* + * for lbx zlib library to know who we are + * server = 1 + * proxy = 0 + */ + +int ProcLbxDispatch(); +extern int SProcLbxDispatch(); +static void LbxResetProc(); +static int DecodeLbxDelta(); +static void LbxFreeClient (); +static void LbxShutdownProxy (); + +static LbxProxyPtr proxyList; +unsigned char LbxReqCode; +int LbxEventCode; +static int BadLbxClientCode; +static int uid_seed; + +static int lbxCompressWorkProcCount; + +LbxClientPtr lbxClients[MAXCLIENTS]; + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; +extern int (*LbxInitialVector[3])(); + +#ifdef DEBUG +int lbxDebug = 0; +#endif + + +void +LbxExtensionInit() +{ + ExtensionEntry *extEntry; + + lbxCompressWorkProcCount = 0; + proxyList = NULL; + uid_seed = 0; + if ((extEntry = AddExtension(LBXNAME, LbxNumberEvents, LbxNumberErrors, + ProcLbxDispatch, SProcLbxDispatch, + LbxResetProc, StandardMinorOpcode))) + { + LbxReqCode = (unsigned char)extEntry->base; + LbxEventCode = extEntry->eventBase; + BadLbxClientCode = extEntry->errorBase + BadLbxClient; + LbxDixInit(); + + LbxCmapInit (); + DeclareExtensionSecurity(LBXNAME, TRUE); + } +} + +/*ARGSUSED*/ +static void +LbxResetProc (extEntry) +ExtensionEntry *extEntry; +{ + LbxResetTags(); + uid_seed = 0; +} + +void +LbxCloseClient (client) + ClientPtr client; +{ + xLbxCloseEvent closeEvent; + ClientPtr master; + LbxProxyPtr proxy; + LbxClientPtr lbxClient = LbxClient(client); + CARD32 id; + + if (!lbxClient) + return; + id = lbxClient->id; + proxy = lbxClient->proxy; + + DBG (DBG_CLIENT, (stderr, "Close client %d\n", client->index)); + LbxFreeClient (client); + if (!id) + { + isItTimeToYield = TRUE; + CloseDownFileDescriptor (client); + LbxShutdownProxy (proxy); + } + else + { + master = NULL; + if (proxy->lbxClients[0]) + master = LbxProxyClient(proxy); + if (master && !master->clientGone) + { + closeEvent.type = LbxEventCode; + closeEvent.lbxType = LbxCloseEvent; + closeEvent.client = id; + closeEvent.sequenceNumber = master->sequence; + closeEvent.pad1 = closeEvent.pad2 = closeEvent.pad3 = + closeEvent.pad4 = closeEvent.pad5 = closeEvent.pad6 = 0; + if (master->swapped) { + int n; + + swaps(&closeEvent.sequenceNumber, n); + swapl(&closeEvent.client, n); + } + WriteToClient(master, sizeof (closeEvent), (char *)&closeEvent); + LbxForceOutput(proxy); + } + } +} + +static int +LbxReencodeEvent(client, proxy, buf) + ClientPtr client; + LbxProxyPtr proxy; + char *buf; +{ + xEvent *ev = (xEvent *)buf; + int n; + lbxMotionCache *motionCache = &proxy->motionCache; + int motionDelta = 0; + Bool swapCache; + xEvent tev, *sev; + + if (ev->u.u.type != MotionNotify) { + if (proxy->dosquishing) + return LbxSquishEvent(buf); + return 0; + } + + /* + * Check if we can generate a motion delta event. + * + * The motion cache contains the last motion event the server sent. + * + * The following are always stored in the cache in the server's + * byte order: + * sequenceNumber, time, rootX, rootY, eventX, eventY + * This is because when determining if we can do a delta, all + * arithmetic must be done using the server's byte order. + * + * The following are stored in the byte order of the latest client + * receiving a motion event (indicated by motionCache->swapped): + * root, event, child, state + * These fields do not need to be stored in the server's byte order + * because we only use the '==' operator on them. + */ + + if (!proxy->motion_allowed_events) { + DBG(DBG_CLIENT, (stderr, "throttling motion event for client %d\n", client->index)); + return sz_xEvent; + } + proxy->motion_allowed_events--; + + motionCache = &proxy->motionCache; + + if (!client->swapped) + { + swapCache = motionCache->swapped; + sev = ev; + } + else + { + swapCache = !motionCache->swapped; + sev = &tev; + cpswaps (ev->u.keyButtonPointer.rootX, + sev->u.keyButtonPointer.rootX); + cpswaps (ev->u.keyButtonPointer.rootY, + sev->u.keyButtonPointer.rootY); + cpswaps (ev->u.keyButtonPointer.eventX, + sev->u.keyButtonPointer.eventX); + cpswaps (ev->u.keyButtonPointer.eventY, + sev->u.keyButtonPointer.eventY); + cpswaps (ev->u.u.sequenceNumber, + sev->u.u.sequenceNumber); + cpswapl (ev->u.keyButtonPointer.time, + sev->u.keyButtonPointer.time); + } + + if (swapCache) + { + swapl (&motionCache->root, n); + swapl (&motionCache->event, n); + swapl (&motionCache->child, n); + swaps (&motionCache->state, n); + + motionCache->swapped = !motionCache->swapped; + } + + motionDelta = 0; + + if (ev->u.u.detail == motionCache->detail && + ev->u.keyButtonPointer.root == motionCache->root && + ev->u.keyButtonPointer.event == motionCache->event && + ev->u.keyButtonPointer.child == motionCache->child && + ev->u.keyButtonPointer.state == motionCache->state && + ev->u.keyButtonPointer.sameScreen == motionCache->sameScreen) { + + int root_delta_x = + sev->u.keyButtonPointer.rootX - motionCache->rootX; + int root_delta_y = + sev->u.keyButtonPointer.rootY - motionCache->rootY; + int event_delta_x = + sev->u.keyButtonPointer.eventX - motionCache->eventX; + int event_delta_y = + sev->u.keyButtonPointer.eventY - motionCache->eventY; + unsigned long sequence_delta = + sev->u.u.sequenceNumber - motionCache->sequenceNumber; + unsigned long time_delta = + sev->u.keyButtonPointer.time - motionCache->time; + + if (root_delta_x == event_delta_x && + event_delta_x >= -128 && event_delta_x < 128 && + root_delta_y == event_delta_y && + event_delta_y >= -128 && event_delta_y < 128) { + + if (sequence_delta == 0 && time_delta < 256) { + + lbxQuickMotionDeltaEvent *mev = + (lbxQuickMotionDeltaEvent *)(buf + sz_xEvent - + sz_lbxQuickMotionDeltaEvent); + + mev->type = LbxEventCode + LbxQuickMotionDeltaEvent; + mev->deltaTime = time_delta; + mev->deltaX = event_delta_x; + mev->deltaY = event_delta_y; + + motionDelta = sz_xEvent - sz_lbxQuickMotionDeltaEvent; + + } else if (sequence_delta < 65536 && time_delta < 65536) { + + lbxMotionDeltaEvent *mev = + (lbxMotionDeltaEvent *)(buf + sz_xEvent - + sz_lbxMotionDeltaEvent); + + mev->type = LbxEventCode; + mev->lbxType = LbxMotionDeltaEvent; + mev->deltaTime = time_delta; + mev->deltaSequence = sequence_delta; + mev->deltaX = event_delta_x; + mev->deltaY = event_delta_y; + + if (LbxProxyClient(proxy)->swapped) + { + swaps (&mev->deltaTime, n); + swaps (&mev->deltaSequence, n); + } + + motionDelta = sz_xEvent - sz_lbxMotionDeltaEvent; + } + } + } + + motionCache->sequenceNumber = sev->u.u.sequenceNumber; + motionCache->time = sev->u.keyButtonPointer.time; + motionCache->rootX = sev->u.keyButtonPointer.rootX; + motionCache->rootY = sev->u.keyButtonPointer.rootY; + motionCache->eventX = sev->u.keyButtonPointer.eventX; + motionCache->eventY = sev->u.keyButtonPointer.eventY; + + if (motionDelta) + return motionDelta; + + ev->u.keyButtonPointer.pad1 = 0; + motionCache->detail = ev->u.u.detail; + motionCache->root = ev->u.keyButtonPointer.root; + motionCache->event = ev->u.keyButtonPointer.event; + motionCache->child = ev->u.keyButtonPointer.child; + motionCache->state = ev->u.keyButtonPointer.state; + motionCache->sameScreen = ev->u.keyButtonPointer.sameScreen; + return 0; +} + +static int +LbxComposeDelta(proxy, reply, len, buf) + LbxProxyPtr proxy; + char *reply; + int len; + char *buf; +{ + int diffs; + int cindex; + int n; + xLbxDeltaReq *p = (xLbxDeltaReq *)buf; + + diffs = LBXDeltaMinDiffs(&proxy->outdeltas, reply, len, + min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1), + &cindex); + if (diffs < 0) { + LBXAddDeltaOut(&proxy->outdeltas, reply, len); + return 0; + } + LBXEncodeDelta(&proxy->outdeltas, reply, diffs, cindex, + &buf[sz_xLbxDeltaReq]); + LBXAddDeltaOut(&proxy->outdeltas, reply, len); + p->reqType = LbxEventCode; + p->lbxReqType = LbxDeltaEvent; + p->diffs = diffs; + p->cindex = cindex; + len = (sz_xLbxDeltaReq + sz_xLbxDiffItem * diffs + 3) & ~3; + p->length = len >> 2; + if (LbxProxyClient(proxy)->swapped) { + swaps(&p->length, n); + } + return len; +} + +void +LbxReencodeOutput(client, pbuf, pcount, cbuf, ccount) + ClientPtr client; + char *pbuf; + int *pcount; + char *cbuf; + int *ccount; +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + CARD32 len; + int n; + int count = *ccount; + char *obuf = cbuf; + + if (client->clientState != ClientStateRunning) { + if (DELTA_CACHEABLE(&proxy->outdeltas, count) && + (n = LbxComposeDelta(proxy, cbuf, count, proxy->oDeltaBuf))) { + memcpy(obuf, proxy->oDeltaBuf, n); + *ccount -= (count - n); + } + return; + } + if (lbxClient->bytes_remaining) { + if (count < lbxClient->bytes_remaining) { + lbxClient->bytes_remaining -= count; + return; + } + if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply)) { + len = lbxClient->bytes_in_reply - lbxClient->bytes_remaining; + pbuf += (*pcount - len); + memcpy(proxy->replyBuf, pbuf, len); + memcpy(proxy->replyBuf + len, cbuf, lbxClient->bytes_remaining); + n = LbxComposeDelta(proxy, proxy->replyBuf, + lbxClient->bytes_in_reply, proxy->oDeltaBuf); + if (!n) + obuf += lbxClient->bytes_remaining; + else if (n <= len) { + memcpy(pbuf, proxy->oDeltaBuf, n); + *pcount -= (len - n); + *ccount -= lbxClient->bytes_remaining; + } else { + memcpy(pbuf, proxy->oDeltaBuf, len); + memcpy(obuf, proxy->oDeltaBuf + len, n - len); + *ccount -= lbxClient->bytes_remaining - (n - len); + obuf += n - len; + } + } else + obuf += lbxClient->bytes_remaining; + cbuf += lbxClient->bytes_remaining; + count -= lbxClient->bytes_remaining; + lbxClient->bytes_remaining = 0; + } + while (count) { + lbxClient->bytes_in_reply = sz_xEvent; + if (((xGenericReply *)cbuf)->type == X_Reply) { + len = ((xGenericReply *)cbuf)->length; + if (client->swapped) { + swapl(&len, n); + } + lbxClient->bytes_in_reply += (len << 2); + if (LbxProxyClient(proxy)->swapped != client->swapped) { + swapl(&((xGenericReply *)cbuf)->length, n); + } + if (count < lbxClient->bytes_in_reply) { + lbxClient->bytes_remaining = lbxClient->bytes_in_reply - count; + if (obuf != cbuf) + memmove(obuf, cbuf, count); + return; + } + } else if (((xGenericReply *)cbuf)->type > X_Reply && + ((xGenericReply *)cbuf)->type < LASTEvent && + (n = LbxReencodeEvent(client, proxy, cbuf))) { + cbuf += n; + *ccount -= n; + count -= n; + if (n == sz_xEvent) + continue; + lbxClient->bytes_in_reply -= n; + } + if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply) && + (n = LbxComposeDelta(proxy, cbuf, lbxClient->bytes_in_reply, + proxy->oDeltaBuf))) { + memcpy(obuf, proxy->oDeltaBuf, n); + obuf += n; + *ccount -= (lbxClient->bytes_in_reply - n); + } else { + if (obuf != cbuf) + memmove(obuf, cbuf, lbxClient->bytes_in_reply); + obuf += lbxClient->bytes_in_reply; + } + cbuf += lbxClient->bytes_in_reply; + count -= lbxClient->bytes_in_reply; + } +} + +/*ARGSUSED*/ +static void +LbxReplyCallback(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + ReplyInfoRec *pri = (ReplyInfoRec *)calldata; + ClientPtr client = pri->client; + LbxClientPtr lbxClient; + REQUEST(xReq); + + if (!pri->startOfReply || stuff->reqType > 127) + return; + lbxClient = LbxClient(client); + if (lbxClient) + ZeroReplyPadBytes(pri->replyData, stuff->reqType); +} + +/* + * XXX If you think this is moronic, you're in good company, + * but things definitely hang if we don't have this. + */ +/* ARGSUSED */ +static Bool +LbxCheckCompressInput (dummy1, dummy2) + ClientPtr dummy1; + pointer dummy2; +{ + LbxProxyPtr proxy; + + if (!lbxCompressWorkProcCount) + return TRUE; + + for (proxy = proxyList; proxy; proxy = proxy->next) { + if (proxy->compHandle && + proxy->streamOpts.streamCompInputAvail(proxy->fd)) + AvailableClientInput (LbxProxyClient(proxy)); + } + return FALSE; +} + +static Bool +LbxIsClientBlocked (lbxClient) + LbxClientPtr lbxClient; +{ + LbxProxyPtr proxy = lbxClient->proxy; + + return (lbxClient->ignored || + (GrabInProgress && lbxClient->client->index != GrabInProgress && + lbxClient != proxy->lbxClients[0])); +} + +static void +LbxSwitchRecv (proxy, lbxClient) + LbxProxyPtr proxy; + LbxClientPtr lbxClient; +{ + ClientPtr client; + + proxy->curRecv = lbxClient; + if (!lbxClient || lbxClient->client->clientGone) + { + DBG(DBG_CLIENT, (stderr, "switching to dispose input\n")); + lbxClient = proxy->lbxClients[0]; + if (!lbxClient) + return; + } + client = lbxClient->client; + DBG (DBG_SWITCH, (stderr, "switching input to client %d\n", client->index)); + + SwitchClientInput (client, FALSE); + proxy->curDix = lbxClient; +} + +/* ARGSUSED */ +static Bool +LbxWaitForUnblocked (client, closure) + ClientPtr client; + pointer closure; +{ + LbxClientPtr lbxClient; + LbxProxyPtr proxy; + + if (client->clientGone) + return TRUE; + lbxClient = LbxClient(client); + if (!lbxClient) + return TRUE; + proxy = lbxClient->proxy; + if (LbxIsClientBlocked (lbxClient) || + ((lbxClient != proxy->curDix) && proxy->curDix->reqs_pending && + !LbxIsClientBlocked(proxy->curDix))) + return FALSE; + lbxClient->input_blocked = FALSE; + DBG (DBG_BLOCK, (stderr, "client %d no longer blocked, switching\n", + client->index)); + SwitchClientInput (client, TRUE); + proxy->curDix = lbxClient; + return TRUE; +} + +void +LbxSetForBlock(lbxClient) + LbxClientPtr lbxClient; +{ + lbxClient->reqs_pending++; + if (!lbxClient->input_blocked) + { + lbxClient->input_blocked = TRUE; + QueueWorkProc(LbxWaitForUnblocked, lbxClient->client, NULL); + } +} + +/* ARGSUSED */ +static int +LbxWaitForUngrab (client, closure) + ClientPtr client; + pointer closure; +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy; + xLbxListenToAllEvent ungrabEvent; + + if (client->clientGone || !lbxClient) + return TRUE; + if (GrabInProgress) + return FALSE; + proxy = lbxClient->proxy; + proxy->grabClient = 0; + ungrabEvent.type = LbxEventCode; + ungrabEvent.lbxType = LbxListenToAll; + ungrabEvent.pad1 = ungrabEvent.pad2 = ungrabEvent.pad3 = + ungrabEvent.pad4 = ungrabEvent.pad5 = ungrabEvent.pad6 = + ungrabEvent.pad7 = 0; + WriteToClient (client, + sizeof(xLbxListenToAllEvent), (char *)&ungrabEvent); + LbxForceOutput(proxy); + return TRUE; +} + +static void +LbxServerGrab(proxy) + LbxProxyPtr proxy; +{ + LbxClientPtr grabbingLbxClient; + xLbxListenToOneEvent grabEvent; + + /* + * If the current grabbing client has changed, then we need + * to send a message to update the proxy. + */ + + grabEvent.type = LbxEventCode; + grabEvent.lbxType = LbxListenToOne; + if (!(grabbingLbxClient = lbxClients[GrabInProgress]) || + grabbingLbxClient->proxy != proxy) + grabEvent.client = 0xffffffff; /* client other than a proxy client */ + else + grabEvent.client = grabbingLbxClient->id; + grabEvent.pad1 = grabEvent.pad2 = grabEvent.pad3 = + grabEvent.pad4 = grabEvent.pad5 = grabEvent.pad6 = 0; + if (LbxProxyClient(proxy)->swapped) { + int n; + swapl(&grabEvent.client, n); + } + WriteToClient(LbxProxyClient(proxy), + sizeof(xLbxListenToOneEvent), (char *)&grabEvent); + LbxForceOutput(proxy); + if (!proxy->grabClient) + QueueWorkProc(LbxWaitForUngrab, LbxProxyClient(proxy), NULL); + proxy->grabClient = GrabInProgress; +} + +#define MAJOROP(client) ((xReq *)client->requestBuffer)->reqType +#define MINOROP(client) ((xReq *)client->requestBuffer)->data + +static Bool lbxCacheable[] = { + FALSE, /* LbxQueryVersion 0 */ + FALSE, /* LbxStartProxy 1 */ + TRUE, /* LbxStopProxy 2 */ + FALSE, /* LbxSwitch 3 */ + FALSE, /* LbxNewClient 4 */ + TRUE, /* LbxCloseClient 5 */ + TRUE, /* LbxModifySequence 6 */ + FALSE, /* LbxAllowMotion 7 */ + TRUE, /* LbxIncrementPixel 8 */ + FALSE, /* LbxDelta 9 */ + TRUE, /* LbxGetModifierMapping 10 */ + FALSE, /* nothing 11 */ + TRUE, /* LbxInvalidateTag 12 */ + TRUE, /* LbxPolyPoint 13 */ + TRUE, /* LbxPolyLine 14 */ + TRUE, /* LbxPolySegment 15 */ + TRUE, /* LbxPolyRectangle 16 */ + TRUE, /* LbxPolyArc 17 */ + TRUE, /* LbxFillPoly 18 */ + TRUE, /* LbxPolyFillRectangle 19 */ + TRUE, /* LbxPolyFillArc 20 */ + TRUE, /* LbxGetKeyboardMapping 21 */ + TRUE, /* LbxQueryFont 22 */ + TRUE, /* LbxChangeProperty 23 */ + TRUE, /* LbxGetProperty 24 */ + TRUE, /* LbxTagData 25 */ + TRUE, /* LbxCopyArea 26 */ + TRUE, /* LbxCopyPlane 27 */ + TRUE, /* LbxPolyText8 28 */ + TRUE, /* LbxPolyText16 29 */ + TRUE, /* LbxImageText8 30 */ + TRUE, /* LbxImageText16 31 */ + FALSE, /* LbxQueryExtension 32 */ + TRUE, /* LbxPutImage 33 */ + TRUE, /* LbxGetImage 34 */ + FALSE, /* LbxBeginLargeRequest 35 */ + FALSE, /* LbxLargeRequestData 36 */ + FALSE, /* LbxEndLargeRequest 37 */ + FALSE, /* LbxInternAtoms 38 */ + TRUE, /* LbxGetWinAttrAndGeom 39 */ + TRUE, /* LbxGrabCmap 40 */ + TRUE, /* LbxReleaseCmap 41 */ + TRUE, /* LbxAllocColor 42 */ + TRUE, /* LbxSync 43 */ +}; + +#define NUM(a) (sizeof (a) / sizeof (a[0])) + +static int +LbxReadRequestFromClient (client) + ClientPtr client; +{ + int ret; + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + ClientPtr masterClient = LbxProxyClient(proxy); + Bool isblocked; + Bool cacheable; + + DBG (DBG_READ_REQ, (stderr, "Reading request from client %d\n", client->index)); + + if (GrabInProgress && (proxy->grabClient != GrabInProgress)) + LbxServerGrab(proxy); + isblocked = LbxIsClientBlocked(lbxClient); + + if (lbxClient->reqs_pending && !isblocked) { + ret = StandardReadRequestFromClient(client); + if (ret > 0 && (MAJOROP(client) == LbxReqCode) && + (MINOROP(client) == X_LbxEndLargeRequest)) + ret = PrepareLargeReqBuffer(client); + if (!--lbxClient->reqs_pending && (lbxClient != proxy->curRecv)) + LbxSwitchRecv (proxy, proxy->curRecv); + return ret; + } + while (1) { + ret = StandardReadRequestFromClient(masterClient); + if (ret <= 0) + return ret; + client->requestBuffer = masterClient->requestBuffer; + client->req_len = masterClient->req_len; + cacheable = client->clientState == ClientStateRunning; + if (cacheable && (MAJOROP(client) == LbxReqCode)) { + /* Check to see if this request is delta cached */ + if (MINOROP(client) < NUM(lbxCacheable)) + cacheable = lbxCacheable[MINOROP(client)]; + switch (MINOROP(client)) { + case X_LbxSwitch: + /* Switch is sent by proxy */ + if (masterClient->swapped) + SProcLbxSwitch (client); + else + ProcLbxSwitch (client); + return 0; + case X_LbxDelta: + ret = DecodeLbxDelta (client); + DBG(DBG_DELTA, + (stderr,"delta decompressed msg %d, len = %d\n", + (unsigned)((unsigned char *)client->requestBuffer)[0], + ret)); + break; + case X_LbxEndLargeRequest: + if (!isblocked) + ret = PrepareLargeReqBuffer(client); + break; + } + } + if (cacheable && DELTA_CACHEABLE(&proxy->indeltas, ret)) { + DBG(DBG_DELTA, + (stderr, "caching msg %d, len = %d, index = %d\n", + (unsigned)((unsigned char *)client->requestBuffer)[0], + ret, proxy->indeltas.nextDelta)); + LBXAddDeltaIn(&proxy->indeltas, client->requestBuffer, ret); + } + if (client->swapped != masterClient->swapped) { + char n; + /* put length in client order */ + swaps(&((xReq *)client->requestBuffer)->length, n); + } + if (!isblocked) + return ret; + DBG (DBG_BLOCK, (stderr, "Stashing %d bytes for %d\n", + ret, client->index)); + AppendFakeRequest (client, client->requestBuffer, ret); + LbxSetForBlock(lbxClient); + } +} + +static LbxClientPtr +LbxInitClient (proxy, client, id) + LbxProxyPtr proxy; + ClientPtr client; + CARD32 id; +{ + LbxClientPtr lbxClient; + int i; + + lbxClient = (LbxClientPtr) xalloc (sizeof (LbxClientRec)); + if (!lbxClient) + return NULL; + lbxClient->id = id; + lbxClient->client = client; + lbxClient->proxy = proxy; + lbxClient->ignored = FALSE; + lbxClient->input_blocked = FALSE; + lbxClient->reqs_pending = 0; + lbxClient->bytes_in_reply = 0; + lbxClient->bytes_remaining = 0; + client->readRequest = LbxReadRequestFromClient; + bzero (lbxClient->drawableCache, sizeof (lbxClient->drawableCache)); + bzero (lbxClient->gcontextCache, sizeof (lbxClient->gcontextCache)); + lbxClients[client->index] = lbxClient; + for (i = 0; proxy->lbxClients[i]; i++) + ; + if (i > proxy->maxIndex) + proxy->maxIndex = i; + proxy->lbxClients[i] = lbxClient; + proxy->numClients++; + lbxClient->gfx_buffer = (pointer) NULL; + lbxClient->gb_size = 0; + return lbxClient; +} + +static void +LbxFreeClient (client) + ClientPtr client; +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + int i; + + if (lbxClient != proxy->lbxClients[0]) { + if (lbxClient == proxy->curRecv) + LbxSwitchRecv(proxy, NULL); + else if (lbxClient == proxy->curDix) + LbxSwitchRecv(proxy, proxy->curRecv); + } + + --proxy->numClients; + lbxClients[client->index] = NULL; + for (i = 0; i <= proxy->maxIndex; i++) { + if (proxy->lbxClients[i] == lbxClient) { + proxy->lbxClients[i] = NULL; + break; + } + } + while (proxy->maxIndex >= 0 && !proxy->lbxClients[proxy->maxIndex]) + --proxy->maxIndex; + xfree(lbxClient->gfx_buffer); + client->readRequest = StandardReadRequestFromClient; + xfree (lbxClient); +} + +static void +LbxFreeProxy (proxy) + LbxProxyPtr proxy; +{ + LbxProxyPtr *p; + + LBXFreeDeltaCache(&proxy->indeltas); + LBXFreeDeltaCache(&proxy->outdeltas); + LbxFreeOsBuffers(proxy); + if (proxy->iDeltaBuf) + xfree(proxy->iDeltaBuf); + if (proxy->replyBuf) + xfree(proxy->replyBuf); + if (proxy->oDeltaBuf) + xfree(proxy->oDeltaBuf); + if (proxy->compHandle) + proxy->streamOpts.streamCompFreeHandle(proxy->compHandle); + if (proxy->bitmapCompMethods) + xfree (proxy->bitmapCompMethods); + if (proxy->pixmapCompMethods) + xfree (proxy->pixmapCompMethods); + if (proxy->pixmapCompDepths) + { + int i; + for (i = 0; i < proxy->numPixmapCompMethods; i++) + xfree (proxy->pixmapCompDepths[i]); + xfree (proxy->pixmapCompDepths); + } + + for (p = &proxyList; *p; p = &(*p)->next) { + if (*p == proxy) { + *p = proxy->next; + break; + } + } + if (!proxyList) + DeleteCallback(&ReplyCallback, LbxReplyCallback, NULL); + + xfree (proxy); +} + +LbxProxyPtr +LbxPidToProxy(pid) + int pid; +{ + LbxProxyPtr proxy; + + for (proxy = proxyList; proxy; proxy = proxy->next) { + if (proxy->pid == pid) + return proxy; + } + return NULL; +} + +static void +LbxShutdownProxy (proxy) + LbxProxyPtr proxy; +{ + int i; + ClientPtr client; + + if (proxy->compHandle) + --lbxCompressWorkProcCount; + while (proxy->grabbedCmaps) + LbxReleaseCmap(proxy->grabbedCmaps, FALSE); + for (i = 0; i <= proxy->maxIndex; i++) + { + if (proxy->lbxClients[i]) + { + client = proxy->lbxClients[i]->client; + if (!client->clientGone) + CloseDownClient (client); + } + } + LbxFlushTags(proxy); + LbxFreeProxy(proxy); +} + + +int +ProcLbxQueryVersion(client) + register ClientPtr client; +{ + REQUEST(xLbxQueryVersionReq); + xLbxQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xLbxQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = LBX_MAJOR_VERSION; + rep.minorVersion = LBX_MINOR_VERSION; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xLbxQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +NextProxyID() +{ + LbxProxyPtr proxy; + int id; + + for (id = 1; id < MAX_NUM_PROXIES; id++) { + for (proxy = proxyList; proxy && proxy->pid != id; proxy = proxy->next) + ; + if (!proxy) + return id; + } + return -1; +} + +int +ProcLbxStartProxy(client) + register ClientPtr client; +{ + REQUEST(xLbxStartProxyReq); + LbxProxyPtr proxy; + LbxClientPtr lbxClient; + int reqlen; + int replylen; + xLbxStartReply *replybuf; + LbxNegOptsRec negopt; + register int n; + pointer compHandle = NULL; + + REQUEST_AT_LEAST_SIZE(xLbxStartProxyReq); + if (lbxClients[client->index]) + return BadLbxClientCode; + proxy = (LbxProxyPtr) xalloc (sizeof (LbxProxyRec)); + if (!proxy) + return BadAlloc; + bzero(proxy, sizeof (LbxProxyRec)); + proxy->pid = NextProxyID(); + if (proxy->pid < 0) { /* too many proxies */ + xfree(proxy); + return BadAlloc; + } + proxy->uid = ++uid_seed; + if (!proxyList) + AddCallback(&ReplyCallback, LbxReplyCallback, NULL); + + if(!proxyList) + proxyList = proxy; + else{ + proxy->next = proxyList; + proxyList = proxy; + } + + /* + * Don't know exactly how big the reply will be, but it won't be + * bigger than the request + */ + reqlen = client->req_len << 2; + replybuf = (xLbxStartReply *) xalloc(max(reqlen, sz_xLbxStartReply)); + if (!replybuf) { + LbxFreeProxy(proxy); + return BadAlloc; + } + + LbxOptionInit(&negopt); + + replylen = LbxOptionParse(&negopt, + &stuff[1], + reqlen - sz_xLbxStartProxyReq, + &replybuf->optDataStart); + if (replylen < 0) { + /* + * Didn't understand option format, so we'll just end up + * using the defaults. Set nopts so that the proxy will + * be informed that we rejected the options because of + * decoding problems. + */ + LbxOptionInit(&negopt); + negopt.nopts = 0xff; + replylen = 0; + } + + if (LBXInitDeltaCache(&proxy->indeltas, negopt.proxyDeltaN, + negopt.proxyDeltaMaxLen) < 0 + || + LBXInitDeltaCache(&proxy->outdeltas, negopt.serverDeltaN, + negopt.serverDeltaMaxLen) < 0) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + + n = 0; + if (negopt.proxyDeltaN) + n = negopt.proxyDeltaMaxLen; + if (negopt.serverDeltaN && negopt.serverDeltaMaxLen > n) + n = negopt.serverDeltaMaxLen; + if (n && + (!(proxy->iDeltaBuf = (char *)xalloc (n)) || + !(proxy->replyBuf = (char *)xalloc (n)) || + !(proxy->oDeltaBuf = (char *)xalloc (n)))) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + + MakeClientGrabImpervious(client); /* proxy needs to be grab-proof */ + proxy->fd = ClientConnectionNumber(client); + if (negopt.streamOpts.streamCompInit) { + compHandle = + (*negopt.streamOpts.streamCompInit)(proxy->fd, negopt.streamOpts.streamCompArg); + if (!compHandle) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + } + proxy->ofirst = NULL; + proxy->olast = NULL; + if (!LbxInitClient (proxy, client, 0)) + { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + proxy->dosquishing = negopt.squish; + proxy->numBitmapCompMethods = negopt.numBitmapCompMethods; + proxy->bitmapCompMethods = negopt.bitmapCompMethods; + proxy->numPixmapCompMethods = negopt.numPixmapCompMethods; + proxy->pixmapCompMethods = negopt.pixmapCompMethods; + proxy->pixmapCompDepths = negopt.pixmapCompDepths; + + proxy->streamOpts = negopt.streamOpts; + proxy->useTags = negopt.useTags; + + proxy->grabbedCmaps = NULL; + + /* send reply */ + replybuf->type = X_Reply; + replybuf->nOpts = negopt.nopts; + replybuf->sequenceNumber = client->sequence; + + replylen += sz_xLbxStartReplyHdr; + if (replylen < sz_xLbxStartReply) + replylen = sz_xLbxStartReply; + replybuf->length = (replylen - sz_xLbxStartReply + 3) >> 2; + if (client->swapped) { + swaps(&replybuf->sequenceNumber, n); + swapl(&replybuf->length, n); + } + lbxClient = LbxClient(client); + WriteToClient(client, replylen, (char *)replybuf); + + LbxProxyConnection(client, proxy); + lbxClient = proxy->lbxClients[0]; + proxy->curDix = lbxClient; + proxy->curRecv = lbxClient; + proxy->compHandle = compHandle; + + if (proxy->compHandle && !lbxCompressWorkProcCount++) + QueueWorkProc(LbxCheckCompressInput, NULL, NULL); + + xfree(replybuf); + return Success; +} + +int +ProcLbxStopProxy(client) + register ClientPtr client; +{ + REQUEST(xLbxStopProxyReq); + LbxProxyPtr proxy; + LbxClientPtr lbxClient = LbxClient(client); + + REQUEST_SIZE_MATCH(xLbxStopProxyReq); + + if (!lbxClient) + return BadLbxClientCode; + if (lbxClient->id) + return BadLbxClientCode; + + proxy = lbxClient->proxy; + LbxFreeClient (client); + LbxShutdownProxy (proxy); + return Success; +} + +int +ProcLbxSwitch(client) + register ClientPtr client; +{ + REQUEST(xLbxSwitchReq); + LbxProxyPtr proxy = LbxMaybeProxy(client); + LbxClientPtr lbxClient; + int i; + + REQUEST_SIZE_MATCH(xLbxSwitchReq); + if (!proxy) + return BadLbxClientCode; + for (i = 0; i <= proxy->maxIndex; i++) { + lbxClient = proxy->lbxClients[i]; + if (lbxClient && lbxClient->id == stuff->client) { + LbxSwitchRecv (proxy, lbxClient); + return Success; + } + } + LbxSwitchRecv (proxy, NULL); + return BadLbxClientCode; +} + +int +ProcLbxBeginLargeRequest(client) + register ClientPtr client; +{ + REQUEST(xLbxBeginLargeRequestReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxBeginLargeRequestReq); + if (!AllocateLargeReqBuffer(client, stuff->largeReqLength << 2)) + return BadAlloc; + return Success; +} + + +int +ProcLbxLargeRequestData(client) + register ClientPtr client; +{ + REQUEST(xLbxLargeRequestDataReq); + + client->sequence--; + REQUEST_AT_LEAST_SIZE(xLbxLargeRequestDataReq); + if (!AddToLargeReqBuffer(client, (char *) (stuff + 1), + (client->req_len - 1) << 2)) + return BadAlloc; + return Success; +} + + +int +ProcLbxEndLargeRequest(client) + register ClientPtr client; +{ + REQUEST(xReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xReq); + return BadAlloc; +} + + +int +ProcLbxInternAtoms(client) + register ClientPtr client; +{ + REQUEST(xLbxInternAtomsReq); + LbxClientPtr lbxClient = LbxClient(client); + xLbxInternAtomsReply *replyRet; + char *ptr = (char *) stuff + sz_xLbxInternAtomsReq; + Atom *atomsRet; + int replyLen, i; + char lenbuf[2]; + CARD16 len; + char n; + + REQUEST_AT_LEAST_SIZE(xLbxInternAtomsReq); + + if (!lbxClient) + return BadLbxClientCode; + if (lbxClient->id) + return BadLbxClientCode; + + replyLen = sz_xLbxInternAtomsReplyHdr + stuff->num * sizeof (Atom); + if (replyLen < sz_xLbxInternAtomsReply) + replyLen = sz_xLbxInternAtomsReply; + + if (!(replyRet = (xLbxInternAtomsReply *) xalloc (replyLen))) + return BadAlloc; + + atomsRet = (Atom *) ((char *) replyRet + sz_xLbxInternAtomsReplyHdr); + + for (i = 0; i < stuff->num; i++) + { + lenbuf[0] = ptr[0]; + lenbuf[1] = ptr[1]; + len = *((CARD16 *) lenbuf); + ptr += 2; + + if ((atomsRet[i] = MakeAtom (ptr, len, TRUE)) == BAD_RESOURCE) + { + xfree (replyRet); + return BadAlloc; + } + + ptr += len; + } + + if (client->swapped) + for (i = 0; i < stuff->num; i++) + swapl (&atomsRet[i], n); + + replyRet->type = X_Reply; + replyRet->sequenceNumber = client->sequence; + replyRet->length = (replyLen - sz_xLbxInternAtomsReply + 3) >> 2; + + if (client->swapped) { + swaps(&replyRet->sequenceNumber, n); + swapl(&replyRet->length, n); + } + + WriteToClient (client, replyLen, (char *) replyRet); + + xfree (replyRet); + + return Success; +} + + +int +ProcLbxGetWinAttrAndGeom(client) + register ClientPtr client; +{ + REQUEST(xLbxGetWinAttrAndGeomReq); + xGetWindowAttributesReply wa; + xGetGeometryReply wg; + xLbxGetWinAttrAndGeomReply reply; + WindowPtr pWin; + int status; + + REQUEST_SIZE_MATCH(xLbxGetWinAttrAndGeomReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + + if ((status = GetGeometry(client, &wg)) != Success) + return status; + + reply.type = X_Reply; + reply.length = (sz_xLbxGetWinAttrAndGeomReply - 32) >> 2; + reply.sequenceNumber = client->sequence; + + reply.backingStore = wa.backingStore; + reply.visualID = wa.visualID; +#if defined(__cplusplus) || defined(c_plusplus) + reply.c_class = wa.c_class; +#else + reply.class = wa.class; +#endif + reply.bitGravity = wa.bitGravity; + reply.winGravity = wa.winGravity; + reply.backingBitPlanes = wa.backingBitPlanes; + reply.backingPixel = wa.backingPixel; + reply.saveUnder = wa.saveUnder; + reply.mapInstalled = wa.mapInstalled; + reply.mapState = wa.mapState; + reply.override = wa.override; + reply.colormap = wa.colormap; + reply.allEventMasks = wa.allEventMasks; + reply.yourEventMask = wa.yourEventMask; + reply.doNotPropagateMask = wa.doNotPropagateMask; + reply.pad1 = 0; + reply.root = wg.root; + reply.x = wg.x; + reply.y = wg.y; + reply.width = wg.width; + reply.height = wg.height; + reply.borderWidth = wg.borderWidth; + reply.depth = wg.depth; + reply.pad2 = 0; + + if (client->swapped) + { + register char n; + + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swapl(&reply.visualID, n); + swaps(&reply.class, n); + swapl(&reply.backingBitPlanes, n); + swapl(&reply.backingPixel, n); + swapl(&reply.colormap, n); + swapl(&reply.allEventMasks, n); + swapl(&reply.yourEventMask, n); + swaps(&reply.doNotPropagateMask, n); + swapl(&reply.root, n); + swaps(&reply.x, n); + swaps(&reply.y, n); + swaps(&reply.width, n); + swaps(&reply.height, n); + swaps(&reply.borderWidth, n); + } + + WriteToClient(client, sizeof(xLbxGetWinAttrAndGeomReply), (char *)&reply); + return(client->noClientException); +} + +int +ProcLbxNewClient(client) + register ClientPtr client; +{ + REQUEST(xLbxNewClientReq); + ClientPtr newClient; + LbxProxyPtr proxy = LbxMaybeProxy(client); + CARD32 id; + int len, i; + char *setupbuf; + LbxClientPtr lbxClient; + + REQUEST_AT_LEAST_SIZE(xLbxNewClientReq); + + /* save info before our request disappears */ + id = stuff->client; + if (!proxy || !id) + return BadLbxClientCode; + if (proxy->numClients == MAX_LBX_CLIENTS) + return BadAlloc; + for (i = 1; i <= proxy->maxIndex; i++) { + if (proxy->lbxClients[i] && proxy->lbxClients[i]->id == id) + return BadLbxClientCode; + } + len = (client->req_len << 2) - sizeof(xLbxNewClientReq); + setupbuf = (char *)xalloc (len); + if (!setupbuf) + return BadAlloc; + memcpy (setupbuf, (char *)&stuff[1], len); + + newClient = AllocLbxClientConnection (client, proxy); + if (!newClient) + return BadAlloc; + newClient->requestVector = LbxInitialVector; + lbxClient = LbxInitClient (proxy, newClient, id); + if (!lbxClient) + { + CloseDownClient (newClient); + return BadAlloc; + } + + AppendFakeRequest (newClient, setupbuf, len); + xfree (setupbuf); + LbxSetForBlock(lbxClient); + + DBG (DBG_CLIENT, (stderr, "lbxNewClient X %d\n", newClient->index)); + return Success; +} + +int +ProcLbxEstablishConnection(client) + register ClientPtr client; +{ + char *reason = NULL; + char *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + prefix->nbytesAuthProto, + auth_proto, + prefix->nbytesAuthString, + auth_string); + + if (client->clientState == ClientStateCheckingSecurity || + client->clientState == ClientStateAuthenticating) + return (client->noClientException = -1); /* XXX some day */ + return(LbxSendConnSetup(client, reason)); +} + +int +ProcLbxCloseClient (client) + register ClientPtr client; +{ + REQUEST(xLbxCloseClientReq); + LbxClientPtr lbxClient = LbxClient(client); + + REQUEST_SIZE_MATCH(xLbxCloseClientReq); + if (!lbxClient || lbxClient->id != stuff->client) + return BadLbxClientCode; + + /* this will cause the client to be closed down back in Dispatch() */ + return(client->noClientException = CloseLbxClient); +} + +int +ProcLbxModifySequence (client) + register ClientPtr client; +{ + REQUEST(xLbxModifySequenceReq); + + REQUEST_SIZE_MATCH(xLbxModifySequenceReq); + client->sequence += (stuff->adjust - 1); /* Dispatch() adds 1 */ + return Success; +} + +int +ProcLbxAllowMotion (client) + register ClientPtr client; +{ + REQUEST(xLbxAllowMotionReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxAllowMotionReq); + LbxAllowMotion(client, stuff->num); + return Success; +} + + +static int +DecodeLbxDelta(client) + register ClientPtr client; +{ + REQUEST(xLbxDeltaReq); + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + int len; + char *buf; + + /* Note that LBXDecodeDelta decodes and adds current msg to the cache */ + len = LBXDecodeDelta(&proxy->indeltas, ((char *)stuff) + sz_xLbxDeltaReq, + stuff->diffs, stuff->cindex, &buf); + /* + * Some requests, such as FillPoly, result in the protocol input + * buffer being modified. So we need to copy the request + * into a temporary buffer where a write would be harmless. + * Maybe some day do this copying on a case by case basis, + * since not all requests are guilty of this. + */ + memcpy(proxy->iDeltaBuf, buf, len); + + client->requestBuffer = proxy->iDeltaBuf; + client->req_len = len >> 2; + return len; +} + +int +ProcLbxGetModifierMapping(client) + ClientPtr client; +{ + REQUEST(xLbxGetModifierMappingReq); + + REQUEST_SIZE_MATCH(xLbxGetModifierMappingReq); + return LbxGetModifierMapping(client); +} + +int +ProcLbxGetKeyboardMapping(client) + ClientPtr client; +{ + REQUEST(xLbxGetKeyboardMappingReq); + + REQUEST_SIZE_MATCH(xLbxGetKeyboardMappingReq); + return LbxGetKeyboardMapping(client); +} + +int +ProcLbxQueryFont(client) + ClientPtr client; +{ + REQUEST(xLbxQueryFontReq); + + REQUEST_SIZE_MATCH(xLbxQueryFontReq); + return LbxQueryFont(client); +} + +int +ProcLbxChangeProperty(client) + ClientPtr client; +{ + REQUEST(xLbxChangePropertyReq); + + REQUEST_SIZE_MATCH(xLbxChangePropertyReq); + return LbxChangeProperty(client); +} + +int +ProcLbxGetProperty(client) + ClientPtr client; +{ + REQUEST(xLbxGetPropertyReq); + + REQUEST_SIZE_MATCH(xLbxGetPropertyReq); + return LbxGetProperty(client); +} + +int +ProcLbxTagData(client) + ClientPtr client; +{ + REQUEST(xLbxTagDataReq); + + client->sequence--; /* not a counted request */ + REQUEST_AT_LEAST_SIZE(xLbxTagDataReq); + + return LbxTagData(client, stuff->tag, stuff->real_length, + (pointer)&stuff[1]); /* better not give any errors */ +} + +int +ProcLbxInvalidateTag(client) + ClientPtr client; +{ + REQUEST(xLbxInvalidateTagReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxInvalidateTagReq); + return LbxInvalidateTag(client, stuff->tag); +} + +int +ProcLbxPolyPoint(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyPoint, LbxDecodePoints); +} + +int +ProcLbxPolyLine(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyLine, LbxDecodePoints); +} + +int +ProcLbxPolySegment(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolySegment, LbxDecodeSegment); +} + +int +ProcLbxPolyRectangle(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyRectangle, LbxDecodeRectangle); +} + +int +ProcLbxPolyArc(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyArc, LbxDecodeArc); +} + +int +ProcLbxFillPoly(client) + register ClientPtr client; +{ + return LbxDecodeFillPoly(client); +} + +int +ProcLbxPolyFillRectangle(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyFillRectangle, LbxDecodeRectangle); +} + +int +ProcLbxPolyFillArc(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyFillArc, LbxDecodeArc); +} + +int +ProcLbxCopyArea (client) + register ClientPtr client; +{ + return LbxDecodeCopyArea(client); +} + +int +ProcLbxCopyPlane (client) + register ClientPtr client; +{ + return LbxDecodeCopyPlane(client); +} + + +int +ProcLbxPolyText (client) + register ClientPtr client; +{ + return LbxDecodePolyText(client); +} + +int +ProcLbxImageText (client) + register ClientPtr client; +{ + return LbxDecodeImageText(client); +} + +int +ProcLbxQueryExtension(client) + ClientPtr client; +{ + REQUEST(xLbxQueryExtensionReq); + char *ename; + + REQUEST_AT_LEAST_SIZE(xLbxQueryExtensionReq); + ename = (char *) &stuff[1]; + return LbxQueryExtension(client, ename, stuff->nbytes); +} + +int +ProcLbxPutImage(client) + register ClientPtr client; +{ + return LbxDecodePutImage(client); +} + +int +ProcLbxGetImage(client) + register ClientPtr client; +{ + return LbxDecodeGetImage(client); +} + + +int +ProcLbxSync(client) + register ClientPtr client; +{ + xLbxSyncReply reply; + + client->sequence--; /* not a counted request */ + +#ifdef COLOR_DEBUG + fprintf (stderr, "Got LBX sync, seq = 0x%x\n", client->sequence); +#endif + + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.pad0 = reply.pad1 = reply.pad2 = reply.pad3 = reply.pad4 = + reply.pad5 = reply.pad6 = 0; + + if (client->swapped) + { + register char n; + swaps (&reply.sequenceNumber, n); + } + + WriteToClient (client, sz_xLbxSyncReply, (char *)&reply); + + return (client->noClientException); +} + + +int +ProcLbxDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_LbxQueryVersion: + return ProcLbxQueryVersion(client); + case X_LbxStartProxy: + return ProcLbxStartProxy(client); + case X_LbxStopProxy: + return ProcLbxStopProxy(client); + case X_LbxNewClient: + return ProcLbxNewClient(client); + case X_LbxCloseClient: + return ProcLbxCloseClient(client); + case X_LbxModifySequence: + return ProcLbxModifySequence(client); + case X_LbxAllowMotion: + return ProcLbxAllowMotion(client); + case X_LbxIncrementPixel: + return ProcLbxIncrementPixel(client); + case X_LbxGrabCmap: + return ProcLbxGrabCmap(client); + case X_LbxReleaseCmap: + return ProcLbxReleaseCmap(client); + case X_LbxAllocColor: + return ProcLbxAllocColor(client); + case X_LbxGetModifierMapping: + return ProcLbxGetModifierMapping(client); + case X_LbxGetKeyboardMapping: + return ProcLbxGetKeyboardMapping(client); + case X_LbxInvalidateTag: + return ProcLbxInvalidateTag(client); + case X_LbxPolyPoint: + return ProcLbxPolyPoint (client); + case X_LbxPolyLine: + return ProcLbxPolyLine (client); + case X_LbxPolySegment: + return ProcLbxPolySegment (client); + case X_LbxPolyRectangle: + return ProcLbxPolyRectangle (client); + case X_LbxPolyArc: + return ProcLbxPolyArc (client); + case X_LbxFillPoly: + return ProcLbxFillPoly (client); + case X_LbxPolyFillRectangle: + return ProcLbxPolyFillRectangle (client); + case X_LbxPolyFillArc: + return ProcLbxPolyFillArc (client); + case X_LbxQueryFont: + return ProcLbxQueryFont (client); + case X_LbxChangeProperty: + return ProcLbxChangeProperty (client); + case X_LbxGetProperty: + return ProcLbxGetProperty (client); + case X_LbxTagData: + return ProcLbxTagData (client); + case X_LbxCopyArea: + return ProcLbxCopyArea (client); + case X_LbxCopyPlane: + return ProcLbxCopyPlane (client); + case X_LbxPolyText8: + case X_LbxPolyText16: + return ProcLbxPolyText (client); + case X_LbxImageText8: + case X_LbxImageText16: + return ProcLbxImageText (client); + case X_LbxQueryExtension: + return ProcLbxQueryExtension (client); + case X_LbxPutImage: + return ProcLbxPutImage (client); + case X_LbxGetImage: + return ProcLbxGetImage (client); + case X_LbxInternAtoms: + return ProcLbxInternAtoms(client); + case X_LbxGetWinAttrAndGeom: + return ProcLbxGetWinAttrAndGeom(client); + case X_LbxSync: + return ProcLbxSync(client); + case X_LbxBeginLargeRequest: + return ProcLbxBeginLargeRequest(client); + case X_LbxLargeRequestData: + return ProcLbxLargeRequestData(client); + case X_LbxEndLargeRequest: + return ProcLbxLargeRequestData(client); + default: + return BadRequest; + } +} diff --git a/lbx/lbxopts.c b/lbx/lbxopts.c new file mode 100644 index 000000000..fe9af687e --- /dev/null +++ b/lbx/lbxopts.c @@ -0,0 +1,817 @@ +/* $Xorg: lbxopts.c,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */ +/* + * Copyright 1994 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef OPTDEBUG +#include +#endif +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "lbxserve.h" +#include "lbxstr.h" +#include "lbximage.h" +#include "lbxopts.h" +#include "lbxsrvopts.h" +#ifndef NO_ZLIB +#include "lbxzlib.h" +#endif /* NO_ZLIB */ + +static int LbxDeltaOpt(); +static int LbxProxyDeltaOpt(); +static int LbxServerDeltaOpt(); +static int LbxStreamCompOpt(); +static int LbxBitmapCompOpt(); +static int LbxPixmapCompOpt(); +static int LbxMessageCompOpt(); +static int LbxUseTagsOpt(); +static int LbxCmapAllOpt(); + +/* + * List of LBX options we recognize and are willing to negotiate + */ +static struct _LbxOptionParser { + CARD8 optcode; + int (*parser)(); +} LbxOptions[] = { + { LBX_OPT_DELTA_PROXY, LbxProxyDeltaOpt }, + { LBX_OPT_DELTA_SERVER, LbxServerDeltaOpt }, + { LBX_OPT_STREAM_COMP, LbxStreamCompOpt }, + { LBX_OPT_BITMAP_COMP, LbxBitmapCompOpt }, + { LBX_OPT_PIXMAP_COMP, LbxPixmapCompOpt }, + { LBX_OPT_MSG_COMP, LbxMessageCompOpt }, + { LBX_OPT_USE_TAGS, LbxUseTagsOpt }, + { LBX_OPT_CMAP_ALL, LbxCmapAllOpt } +}; + +#define LBX_N_OPTS (sizeof(LbxOptions) / sizeof(struct _LbxOptionParser)) + +/* + * Set option defaults + */ +LbxOptionInit(pno) + LbxNegOptsPtr pno; +{ + bzero(pno, sizeof(LbxNegOptsRec)); + pno->proxyDeltaN = pno->serverDeltaN = LBX_OPT_DELTA_NCACHE_DFLT; + pno->proxyDeltaMaxLen = pno->serverDeltaMaxLen = LBX_OPT_DELTA_MSGLEN_DFLT; + pno->squish = TRUE; + pno->numBitmapCompMethods = 0; + pno->bitmapCompMethods = NULL; + pno->numPixmapCompMethods = 0; + pno->pixmapCompMethods = NULL; + pno->pixmapCompDepths = NULL; + pno->useTags = TRUE; +} + +int +LbxOptionParse(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + int i; + int nopts = *popt++; + unsigned char *pout = preply; + + for (i = 0; i < nopts; i++) { + int j; + int len; + int hdrlen; + int replylen; + + LBX_OPT_DECODE_LEN(popt + 1, len, hdrlen); + if (len < ++hdrlen || len > optlen) { +#ifdef OPTDEBUG + fprintf(stderr, "bad option length, len = %d, hdrlen = %d, optlen = %d\n", len, hdrlen, optlen); +#endif + return -1; + } + + for (j = 0; j < LBX_N_OPTS; j++) { + if (popt[0] == LbxOptions[j].optcode) { + replylen = (*LbxOptions[j].parser)(pno, + popt + hdrlen, + len - hdrlen, + pout + LBX_OPT_SMALLHDR_LEN); + if (replylen < 0) + return -1; + else if (replylen > 0) { + /* + * None of the current options require big headers, + * so this works for now. + */ + *pout++ = i; + *pout++ = LBX_OPT_SMALLHDR_LEN + replylen; + pout += replylen; + pno->nopts++; + } + break; + } + } + + optlen -= len; + popt += len; + } + + return (pout - preply); +} + +static int +LbxProxyDeltaOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + return LbxDeltaOpt(popt, optlen, preply, + &pno->proxyDeltaN, &pno->proxyDeltaMaxLen); +} + +static int +LbxServerDeltaOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + return LbxDeltaOpt(popt, optlen, preply, + &pno->serverDeltaN, &pno->serverDeltaMaxLen); +} + +static int +LbxDeltaOpt(popt, optlen, preply, pn, pmaxlen) + unsigned char *popt; + int optlen; + unsigned char *preply; + short *pn; + short *pmaxlen; +{ + short n; + short maxlen; + + /* + * If there's more data than we expect, we just ignore it. + */ + if (optlen < LBX_OPT_DELTA_REQLEN) { +#ifdef OPTDEBUG + fprintf(stderr, "bad delta option length = %d\n", optlen); +#endif + return -1; + } + + /* + * Accept whatever value the proxy prefers, so skip the + * min/max offerings. Note that the max message len value is + * encoded as the number of 4-byte values. + */ + popt += 2; + n = *popt++; + popt += 2; + maxlen = *popt++; + if ((maxlen <<= 2) == 0) + n = 0; + else if (maxlen < 32) { +#ifdef OPTDEBUG + fprintf(stderr, "bad delta max msg length %d\n", maxlen); +#endif + return -1; + } + + /* + * Put the response in the reply buffer + */ + *preply++ = n; + *preply++ = maxlen >> 2; + + *pn = n; + *pmaxlen = maxlen; + + return LBX_OPT_DELTA_REPLYLEN; +} + +static int ZlibParse(); + +static struct _LbxStreamCompParser { + int typelen; + char *type; + int (*parser)(); +} LbxStreamComp[] = { +#ifndef NO_ZLIB + { ZLIB_STRCOMP_OPT_LEN, ZLIB_STRCOMP_OPT, ZlibParse }, +#endif /* NO_ZLIB */ +}; + +#define LBX_N_STRCOMP \ + (sizeof(LbxStreamComp) / sizeof(struct _LbxStreamCompParser)) + +static int +LbxStreamCompOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + int i; + int typelen; + int nopts = *popt++; + + for (i = 0; i < nopts; i++) { + int j; + int len; + int lensize; + int replylen; + + typelen = popt[0]; + for (j = 0; j < LBX_N_STRCOMP; j++) { + if (typelen == LbxStreamComp[j].typelen && + !strncmp((char *) popt + 1, LbxStreamComp[j].type, typelen)) + break; + } + + popt += 1 + typelen; + optlen -= 1 + typelen; + LBX_OPT_DECODE_LEN(popt, len, lensize); + + if (j < LBX_N_STRCOMP) { + if (len > optlen) + return -1; + replylen = (*LbxStreamComp[j].parser)(pno, + popt + lensize, + len - lensize, + preply + 1); + if (replylen == -1) + return -1; + else if (replylen >= 0) { + *preply = i; + return replylen + 1; + } + } + + optlen -= len; + popt += len; + } + + return 0; +} + + +extern LbxStreamCompHandle ZlibInit(); +extern int ZlibStuffInput(), ZlibInputAvail(), ZlibFlush(), + ZlibRead(), ZlibWriteV(); +extern void ZlibCompressOn(), ZlibCompressOff(), ZlibFree(); + + +static int +ZlibParse(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + int level; /* compression level */ + + if (*popt++ != 1) /* length should be 1 */ + return (-1); + + level = *popt; + if (level < 1 || level > 9) + return (-1); + + pno->streamOpts.streamCompInit = ZlibInit; + pno->streamOpts.streamCompArg = (pointer) level; + pno->streamOpts.streamCompStuffInput = ZlibStuffInput; + pno->streamOpts.streamCompInputAvail = ZlibInputAvail; + pno->streamOpts.streamCompFlush = ZlibFlush; + pno->streamOpts.streamCompRead = ZlibRead; + pno->streamOpts.streamCompWriteV = ZlibWriteV; + pno->streamOpts.streamCompOn = ZlibCompressOn; + pno->streamOpts.streamCompOff = ZlibCompressOff; + pno->streamOpts.streamCompFreeHandle = ZlibFree; + + return (0); +} + +static int +LbxMessageCompOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + + if (optlen == 0) { +#ifdef OPTDEBUG + fprintf(stderr, "bad message-comp option length specified %d\n", optlen); +#endif + return -1; + } + + pno->squish = *preply = *popt; + return 1; +} + + +static int +LbxUseTagsOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + + if (optlen == 0) { +#ifdef OPTDEBUG + fprintf(stderr, "bad use-tags option length specified %d\n", optlen); +#endif + return -1; + } + + pno->useTags = *preply = *popt; + return 1; +} + + +/* + * Option negotiation for image compression + */ + +LbxBitmapCompMethod +LbxBitmapCompMethods [] = { + { + "XC-FaxG42D", /* compression method name */ + 0, /* inited */ + 2, /* method opcode */ + NULL, /* init function */ + LbxImageEncodeFaxG42D, /* encode function */ + LbxImageDecodeFaxG42D /* decode function */ + } +}; + +#define NUM_BITMAP_METHODS \ + (sizeof (LbxBitmapCompMethods) / sizeof (LbxBitmapCompMethod)) + + +#if 1 +/* + * Currently, we don't support any pixmap compression algorithms + * because regular stream compression does much better than PackBits. + * If we want to plug in a better pixmap image compression algorithm, + * it would go here. + */ + +#define NUM_PIXMAP_METHODS 0 +LbxPixmapCompMethod LbxPixmapCompMethods [1]; /* dummy */ + +#else + +LbxPixmapCompMethod +LbxPixmapCompMethods [] = { + { + "XC-PackBits", /* compression method name */ + 1 << ZPixmap, /* formats supported */ + 1, {8}, /* depths supported */ + 0, /* inited */ + 1, /* method opcode */ + NULL, /* init function */ + LbxImageEncodePackBits, /* encode function */ + LbxImageDecodePackBits /* decode function */ + } +}; + +#define NUM_PIXMAP_METHODS \ + (sizeof (LbxPixmapCompMethods) / sizeof (LbxPixmapCompMethod)) +#endif + +static int MergeDepths (); + + +static int +LbxImageCompOpt (pixmap, pno, popt, optlen, preply) + +Bool pixmap; +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + unsigned char *preplyStart = preply; + int numMethods = *popt++; + char *myIndices, *hisIndices; + unsigned *retFormats; + int **retDepths; + int replyCount = 0; + int status, i, j; + + if (numMethods == 0) + { + if (pixmap) + pno->numPixmapCompMethods = 0; + else + pno->numBitmapCompMethods = 0; + + *preply++ = 0; + return (1); + } + + myIndices = (char *) xalloc (numMethods); + hisIndices = (char *) xalloc (numMethods); + + if (!myIndices || !hisIndices) + { + if (myIndices) + xfree (myIndices); + if (hisIndices) + xfree (hisIndices); + return -1; + } + + if (pixmap) + { + retFormats = (unsigned *) xalloc (numMethods); + retDepths = (int **) xalloc (numMethods * sizeof (int *)); + + if (!retFormats || !retDepths) + { + if (retFormats) + xfree (retFormats); + if (retDepths) + xfree (retDepths); + xfree (myIndices); + xfree (hisIndices); + return -1; + } + } + + /* + * For each method in the list sent by the proxy, see if the server + * supports this method. If YES, update the following lists: + * + * myIndices[] is a list of indices into the server's + * LbxBit[Pix]mapCompMethods table. + * + * hisIndices[] is a list of indices into the list of + * method names sent by the proxy. + * + * retFormats[] indicates for each pixmap compression method, + * the pixmap formats supported. + * + * retDepths[] indicates for each pixmap compression method, + * the pixmap depths supported. + */ + + for (i = 0; i < numMethods; i++) + { + unsigned formatMask, newFormatMask; + int depthCount, *depths, len; + int freeDepths; + char *methodName; + + freeDepths = 0; + len = *popt++; + methodName = (char *) popt; + popt += len; + + if (pixmap) + { + formatMask = *popt++; + depthCount = *popt++; + depths = (int *) xalloc ((depthCount + 1) * sizeof (int)); + freeDepths = 1; + depths[0] = depthCount; + for (j = 1; j <= depthCount; j++) + depths[j] = *popt++; + } + + for (j = 0; + j < (pixmap ? NUM_PIXMAP_METHODS : NUM_BITMAP_METHODS); j++) + { + + status = strncmp (methodName, + (pixmap ? LbxPixmapCompMethods[j].methodName : + LbxBitmapCompMethods[j].methodName), + len); + + if (status == 0 && pixmap) + { + newFormatMask = + formatMask & LbxPixmapCompMethods[j].formatMask; + + depthCount = MergeDepths (depths, &LbxPixmapCompMethods[j]); + + if (newFormatMask == 0 || depthCount == 0) + status = 1; + } + + if (status == 0) + { + myIndices[replyCount] = j; + hisIndices[replyCount] = i; + + if (pixmap) + { + retFormats[replyCount] = newFormatMask; + retDepths[replyCount] = depths; + freeDepths = 0; + } + + replyCount++; + break; + } + } + + if (freeDepths) + xfree (depths); + } + + *preply++ = replyCount; + + /* + * Sort the lists by LBX server preference (increasing myIndices[] vals) + */ + + for (i = 0; i <= replyCount - 2; i++) + for (j = replyCount - 1; j >= i; j--) + if (myIndices[j - 1] > myIndices[j]) + { + char temp1 = myIndices[j - 1]; + char temp2 = hisIndices[j - 1]; + + myIndices[j - 1] = myIndices[j]; + myIndices[j] = temp1; + + hisIndices[j - 1] = hisIndices[j]; + hisIndices[j] = temp2; + + if (pixmap) + { + unsigned temp3 = retFormats[j - 1]; + int *temp4 = retDepths[j - 1]; + + retFormats[j - 1] = retFormats[j]; + retFormats[j] = temp3; + + retDepths[j - 1] = retDepths[j]; + retDepths[j] = temp4; + } + } + + /* + * For each method supported, return to the proxy an index into + * the list sent by the proxy, the opcode to be used for the method, + * the pixmap formats supported, and the list of depths supported. + */ + + for (i = 0; i < replyCount; i++) + { + *preply++ = hisIndices[i]; + + if (pixmap) + { + int left; + *preply++ = LbxPixmapCompMethods[myIndices[i]].methodOpCode; + *preply++ = retFormats[i]; + *preply++ = left = retDepths[i][0]; + j = 1; + while (left > 0) + { + *preply++ = retDepths[i][j]; + left--; + } + } + else + { + *preply++ = LbxBitmapCompMethods[myIndices[i]].methodOpCode; + } + } + + if (pixmap) + { + pno->numPixmapCompMethods = replyCount; + pno->pixmapCompMethods = myIndices; + pno->pixmapCompDepths = retDepths; + } + else + { + pno->numBitmapCompMethods = replyCount; + pno->bitmapCompMethods = myIndices; + } + + if (hisIndices) + xfree (hisIndices); + + if (pixmap) + { + if (retFormats) + xfree (retFormats); + } + + return (preply - preplyStart); +} + + + +static int +LbxBitmapCompOpt (pno, popt, optlen, preply) + +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + return (LbxImageCompOpt (0 /* bitmap */, pno, popt, optlen, preply)); +} + + +static int +LbxPixmapCompOpt (pno, popt, optlen, preply) + +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + return (LbxImageCompOpt (1 /* Pixmap */, pno, popt, optlen, preply)); +} + + +LbxBitmapCompMethod * +LbxSrvrLookupBitmapCompMethod (proxy, methodOpCode) + +LbxProxyPtr proxy; +int methodOpCode; + +{ + int i; + + for (i = 0; i < proxy->numBitmapCompMethods; i++) + { + LbxBitmapCompMethod *method; + + method = &LbxBitmapCompMethods[proxy->bitmapCompMethods[i]]; + + if (method->methodOpCode == methodOpCode) + return (method); + } + + return (NULL); +} + + +LbxPixmapCompMethod * +LbxSrvrLookupPixmapCompMethod (proxy, methodOpCode) + +LbxProxyPtr proxy; +int methodOpCode; + +{ + int i; + + for (i = 0; i < proxy->numPixmapCompMethods; i++) + { + LbxPixmapCompMethod *method; + + method = &LbxPixmapCompMethods[proxy->pixmapCompMethods[i]]; + + if (method->methodOpCode == methodOpCode) + return (method); + } + + return (NULL); +} + + +LbxBitmapCompMethod * +LbxSrvrFindPreferredBitmapCompMethod (proxy) + +LbxProxyPtr proxy; + +{ + if (proxy->numBitmapCompMethods == 0) + return NULL; + else + return (&LbxBitmapCompMethods[proxy->bitmapCompMethods[0]]); +} + + + +LbxPixmapCompMethod * +LbxSrvrFindPreferredPixmapCompMethod (proxy, format, depth) + +LbxProxyPtr proxy; +int format; +int depth; + +{ + if (proxy->numPixmapCompMethods == 0) + return NULL; + else + { + LbxPixmapCompMethod *method; + int i, j; + + for (i = 0; i < proxy->numPixmapCompMethods; i++) + { + method = &LbxPixmapCompMethods[proxy->pixmapCompMethods[i]]; + + if ((method->formatMask & (1 << format))) + { + int n = proxy->pixmapCompDepths[i][0]; + j = 1; + while (n > 0) + { + if (depth == proxy->pixmapCompDepths[i][j]) + return method; + else + n--; + } + } + } + + return NULL; + } +} + + +static int MergeDepths (depths, method) + +int *depths; +LbxPixmapCompMethod *method; + +{ + int i, j, count; + int temp[LBX_MAX_DEPTHS + 1]; + + temp[0] = count = 0; + + for (i = 1; i <= depths[0]; i++) + { + for (j = 0; j < method->depthCount; j++) + if (method->depths[j] == depths[i]) + { + temp[0]++; + temp[++count] = depths[i]; + break; + } + } + + memcpy (depths, temp, (count + 1) * sizeof (int)); + + return (count); +} + + +#define LbxCmapAllMethod "XC-CMAP" + +static int +LbxCmapAllOpt (pno, popt, optlen, preply) + +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + int numMethods = *popt++; + int i; + + for (i = 0; i < numMethods; i++) + { + int len; + char *methodName; + + len = *popt++; + methodName = (char *) popt; + popt += len; + if (!strncmp(methodName, LbxCmapAllMethod, len)) + break; + } + if (i >= numMethods) + i = 0; /* assume first one is proxy's favorite */ + *preply = i; + return 1; +} diff --git a/lbx/lbxprop.c b/lbx/lbxprop.c new file mode 100644 index 000000000..b70fade72 --- /dev/null +++ b/lbx/lbxprop.c @@ -0,0 +1,552 @@ +/* $Xorg: lbxprop.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1986, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1993 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* various bits of DIX-level mangling */ + +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "servermd.h" +#include "propertyst.h" +#include "windowstr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbxtags.h" +#include "Xfuncproto.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +extern int (*ProcVector[256]) (); +extern void (*ReplySwapVector[256]) (); +extern void CopySwap16Write(), CopySwap32Write(), Swap32Write(); + +void +LbxStallPropRequest(client, pProp) + ClientPtr client; + PropertyPtr pProp; +{ + xReq *req = (xReq *) client->requestBuffer; + register char n; + + LbxQueryTagData(client, pProp->owner_pid, + pProp->tag_id, LbxTagTypeProperty); + + /* + * Before we reset the request, we must make sure + * it is in the client's byte order. + */ + + if (client->swapped) { + if (req->reqType == X_ChangeProperty) { + xChangePropertyReq *stuff = (xChangePropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch ( stuff->format ) { + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + } + } else if (req->reqType == X_GetProperty) { + xGetPropertyReq *stuff = (xGetPropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + } else if (req->data == X_LbxChangeProperty) { + xLbxChangePropertyReq *stuff = (xLbxChangePropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + } else if (req->data == X_LbxGetProperty) { + xLbxGetPropertyReq *stuff = (xLbxGetPropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + } + } + ResetCurrentRequest(client); + client->sequence--; + IgnoreClient(client); +} + +int +LbxChangeWindowProperty(client, pWin, property, type, format, mode, len, + have_data, value, sendevent, tag) + ClientPtr client; + WindowPtr pWin; + Atom property, + type; + int format, + mode; + unsigned long len; + Bool have_data; + pointer value; + Bool sendevent; + XID *tag; +{ + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format >> 3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps(pWin); + while (pProp) { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) { /* just add to list */ + if (!pWin->optional && !MakeWindowOptional(pWin)) + return (BadAlloc); + pProp = (PropertyPtr) xalloc(sizeof(PropertyRec)); + if (!pProp) + return (BadAlloc); + data = (pointer) xalloc(totalSize); + if (!data && len) { + xfree(pProp); + return (BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (have_data) { + if (len) + memmove((char *) data, (char *) value, totalSize); + pProp->tag_id = 0; + pProp->owner_pid = 0; + } else { + if (!TagSaveTag(LbxTagTypeProperty, totalSize, + (pointer)pProp, &pProp->tag_id)) { + xfree(pProp); + xfree(pProp->data); + return BadAlloc; + } + pProp->owner_pid = LbxProxyID(client); + TagMarkProxy(pProp->tag_id, pProp->owner_pid); + } + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } else { + /* + * To append or prepend to a property the request format and type must + * match those of the already defined property. The existing format + * and type are irrelevant when using the mode "PropModeReplace" since + * they will be written over. + */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return (BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return (BadMatch); + + /* + * if its a modify instead of replace, make sure we have the current + * value + */ + if ((mode != PropModeReplace) && pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return (client->noClientException); + } + /* make sure any old tag is flushed first */ + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); + if (mode == PropModeReplace) { + if (totalSize != pProp->size * (pProp->format >> 3)) { + data = (pointer) xrealloc(pProp->data, totalSize); + if (!data && len) + return (BadAlloc); + pProp->data = data; + } + if (have_data) { + if (len) + memmove((char *) pProp->data, (char *) value, totalSize); + } else { + if (!TagSaveTag(LbxTagTypeProperty, totalSize, + (pointer)pProp, &pProp->tag_id)) { + xfree(pProp); + xfree(pProp->data); + return BadAlloc; + } + pProp->owner_pid = LbxProxyID(client); + TagMarkProxy(pProp->tag_id, pProp->owner_pid); + } + pProp->size = len; + pProp->type = type; + pProp->format = format; + } else if (len == 0) { + /* do nothing */ + } else if (mode == PropModeAppend) { + data = (pointer) xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return (BadAlloc); + pProp->data = data; + memmove(&((char *) data)[pProp->size * sizeInBytes], + (char *) value, + totalSize); + pProp->size += len; + } else if (mode == PropModePrepend) { + data = (pointer) xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return (BadAlloc); + memmove(&((char *) data)[totalSize], (char *) pProp->data, + (int) (pProp->size * sizeInBytes)); + memmove((char *) data, (char *) value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr) NULL); + } + if (pProp->tag_id) + *tag = pProp->tag_id; + return (Success); +} + +int +LbxChangeProperty(client) + ClientPtr client; +{ + WindowPtr pWin; + char format, + mode; + unsigned long len; + int err; + int n; + XID newtag; + xLbxChangePropertyReply rep; + REQUEST(xLbxChangePropertyReq); + + REQUEST_SIZE_MATCH(xLbxChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return (BadWindow); + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return (BadAtom); + } + if (!ValidAtom(stuff->type)) { + client->errorValue = stuff->type; + return (BadAtom); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.pad = rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + rep.tag = 0; + WriteToClient(client, sizeof(xLbxChangePropertyReply), (char *)&rep); + return client->noClientException; + } +#endif + + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int) format, (int) mode, len, FALSE, (pointer) &stuff[1], + TRUE, &newtag); + if (err) + return err; + + rep.tag = newtag; + + if (client->swapped) { + swapl(&rep.tag, n); + } + WriteToClient(client, sizeof(xLbxChangePropertyReply), (char *)&rep); + + return client->noClientException; +} + +static void +LbxWriteGetpropReply(client, rep) + ClientPtr client; + xLbxGetPropertyReply *rep; +{ + int n; + + if (client->swapped) { + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->propertyType, n); + swapl(&rep->bytesAfter, n); + swapl(&rep->nItems, n); + swapl(&rep->tag, n); + } + WriteToClient(client, sizeof(xLbxGetPropertyReply), (char *)rep); +} + +int +LbxGetProperty(client) + ClientPtr client; +{ + PropertyPtr pProp, + prevProp; + unsigned long n, + len, + ind; + WindowPtr pWin; + xLbxGetPropertyReply reply; + Bool send_data = FALSE; + + REQUEST(xLbxGetPropertyReq); + + REQUEST_SIZE_MATCH(xLbxGetPropertyReq); + + reply.pad1 = 0; + reply.pad2 = 0; + + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return (BadWindow); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return (BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { + client->errorValue = stuff->delete; + return (BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + pProp = wUserProps(pWin); + prevProp = (PropertyPtr) NULL; + while (pProp) { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) { + reply.nItems = 0; + reply.length = 0; + reply.bytesAfter = 0; + reply.propertyType = None; + reply.format = 0; + reply.tag = 0; + LbxWriteGetpropReply(client, &reply); + return client->noClientException; + } + /* + * If the request type and actual type don't match. Return the + * property information, but not the data. + */ + if ((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + reply.tag = 0; + LbxWriteGetpropReply(client, &reply); + return client->noClientException; + } + /* + * Return type, format, value to client + */ + n = (pProp->format >> 3) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* + * If longOffset is invalid such that it causes "len" to be + * negative, it's a value error. + */ + + if (n < ind) { + client->errorValue = stuff->longOffset; + return BadValue; + } + + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } + + len = min(n - ind, stuff->longLength << 2); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.propertyType = pProp->type; + + if (!pProp->tag_id) { + if (n && (!stuff->delete || reply.bytesAfter)) { + TagSaveTag(LbxTagTypeProperty, n, (pointer)pProp, &pProp->tag_id); + pProp->owner_pid = 0; + } + send_data = TRUE; + } else + send_data = !TagProxyMarked(pProp->tag_id, LbxProxyID(client)); + if (pProp->tag_id && send_data) + TagMarkProxy(pProp->tag_id, LbxProxyID(client)); + reply.tag = pProp->tag_id; + + if (!send_data) + len = 0; + else if (reply.tag) { + len = n; + ind = 0; + } + reply.nItems = len / (pProp->format >> 3); + reply.length = (len + 3) >> 2; + + if (stuff->delete && (reply.bytesAfter == 0)) { + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr) NULL); + } + LbxWriteGetpropReply(client, &reply); + if (len) { + switch (reply.format) { + case 32: + client->pSwapReplyFunc = CopySwap32Write; + break; + case 16: + client->pSwapReplyFunc = CopySwap16Write; + break; + default: + client->pSwapReplyFunc = (void (*) ()) WriteToClient; + break; + } + WriteSwappedDataToClient(client, len, + (char *) pProp->data + ind); + } + if (stuff->delete && (reply.bytesAfter == 0)) { + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); + if (prevProp == (PropertyPtr) NULL) { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed(pWin); + } else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return client->noClientException; +} diff --git a/lbx/lbxserve.h b/lbx/lbxserve.h new file mode 100644 index 000000000..3151207be --- /dev/null +++ b/lbx/lbxserve.h @@ -0,0 +1,173 @@ +/* $Xorg: lbxserve.h,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1992 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of NCD. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. NCD. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD. + * 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. + * + */ + +#ifndef _LBXSERVE_H_ +#define _LBXSERVE_H_ +#include "lbxdeltastr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxopts.h" + +#define MAX_LBX_CLIENTS MAXCLIENTS +#define MAX_NUM_PROXIES (MAXCLIENTS >> 1) + +typedef struct _LbxClient *LbxClientPtr; +typedef struct _LbxProxy *LbxProxyPtr; + +typedef struct _LbxClient { + CARD32 id; + ClientPtr client; + LbxProxyPtr proxy; + Bool ignored; + Bool input_blocked; + int reqs_pending; + long bytes_in_reply; + long bytes_remaining; + Drawable drawableCache[GFX_CACHE_SIZE]; + GContext gcontextCache[GFX_CACHE_SIZE]; + pointer gfx_buffer; /* tmp buffer for unpacking gfx requests */ + unsigned long gb_size; +} LbxClientRec; + +typedef struct _connectionOutput *OSBufPtr; + +typedef struct _LbxProxy { + LbxProxyPtr next; + /* this array is indexed by lbx proxy index */ + LbxClientPtr lbxClients[MAX_LBX_CLIENTS]; + LbxClientPtr curRecv, + curDix; + int fd; + int pid; /* proxy ID */ + int uid; + int numClients; + int maxIndex; + Bool aborted; + int grabClient; + pointer compHandle; + Bool dosquishing; + Bool useTags; + LBXDeltasRec indeltas; + LBXDeltasRec outdeltas; + char *iDeltaBuf; + char *replyBuf; + char *oDeltaBuf; + OSBufPtr ofirst; + OSBufPtr olast; + CARD32 cur_send_id; + + LbxStreamOpts streamOpts; + + int numBitmapCompMethods; + char *bitmapCompMethods; /* array of indices */ + int numPixmapCompMethods; + char *pixmapCompMethods; /* array of indices */ + int **pixmapCompDepths; /* depths supported from each method */ + + struct _ColormapRec *grabbedCmaps; /* chained via lbx private */ + int motion_allowed_events; + lbxMotionCache motionCache; +} LbxProxyRec; + +/* This array is indexed by server client index, not lbx proxy index */ + +extern LbxClientPtr lbxClients[MAXCLIENTS]; + +#define LbxClient(client) (lbxClients[(client)->index]) +#define LbxProxy(client) (LbxClient(client)->proxy) +#define LbxMaybeProxy(client) (LbxClient(client) ? LbxProxy(client) : 0) +#define LbxProxyID(client) (LbxProxy(client)->pid) +#define LbxProxyClient(proxy) ((proxy)->lbxClients[0]->client) + +extern int LbxEventCode; + +extern void LbxDixInit( +#if NeedFunctionPrototypes + void +#endif +); + +extern LbxProxyPtr LbxPidToProxy( +#if NeedFunctionPrototypes + int /* pid */ +#endif +); + +extern void LbxReencodeOutput( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + char* /*pbuf*/, + int* /*pcount*/, + char* /*cbuf*/, + int* /*ccount*/ +#endif +); + +extern int UncompressedWriteToClient( +#if NeedFunctionPrototypes + ClientPtr /*who*/, + int /*count*/, + char* /*buf*/ +#endif +); + +extern ClientPtr AllocLbxClientConnection( +#if NeedFunctionPrototypes + ClientPtr /* client */, + LbxProxyPtr /* proxy */ +#endif +); + +extern void LbxProxyConnection( +#if NeedFunctionPrototypes + ClientPtr /* client */, + LbxProxyPtr /* proxy */ +#endif +); + +#endif /* _LBXSERVE_H_ */ diff --git a/lbx/lbxsquish.c b/lbx/lbxsquish.c new file mode 100644 index 000000000..6d3eddbfc --- /dev/null +++ b/lbx/lbxsquish.c @@ -0,0 +1,152 @@ +/* $Xorg: lbxsquish.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1994 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "lbxserve.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" + +/* handles server-side protocol squishing */ + +static char lbxevdelta[] = { + 0, + 0, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_EnterLeaveEvent, + sz_xEvent - lbxsz_EnterLeaveEvent, + sz_xEvent - lbxsz_FocusEvent, + sz_xEvent - lbxsz_FocusEvent, + sz_xEvent - lbxsz_KeymapEvent, + sz_xEvent - lbxsz_ExposeEvent, + sz_xEvent - lbxsz_GfxExposeEvent, + sz_xEvent - lbxsz_NoExposeEvent, + sz_xEvent - lbxsz_VisibilityEvent, + sz_xEvent - lbxsz_CreateNotifyEvent, + sz_xEvent - lbxsz_DestroyNotifyEvent, + sz_xEvent - lbxsz_UnmapNotifyEvent, + sz_xEvent - lbxsz_MapNotifyEvent, + sz_xEvent - lbxsz_MapRequestEvent, + sz_xEvent - lbxsz_ReparentEvent, + sz_xEvent - lbxsz_ConfigureNotifyEvent, + sz_xEvent - lbxsz_ConfigureRequestEvent, + sz_xEvent - lbxsz_GravityEvent, + sz_xEvent - lbxsz_ResizeRequestEvent, + sz_xEvent - lbxsz_CirculateEvent, + sz_xEvent - lbxsz_CirculateEvent, + sz_xEvent - lbxsz_PropertyEvent, + sz_xEvent - lbxsz_SelectionClearEvent, + sz_xEvent - lbxsz_SelectionRequestEvent, + sz_xEvent - lbxsz_SelectionNotifyEvent, + sz_xEvent - lbxsz_ColormapEvent, + sz_xEvent - lbxsz_ClientMessageEvent, + sz_xEvent - lbxsz_MappingNotifyEvent +}; + +static char lbxevpad[] = { + 0, + 0, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_EnterLeaveEvent - lbxupsz_EnterLeaveEvent, + lbxsz_EnterLeaveEvent - lbxupsz_EnterLeaveEvent, + lbxsz_FocusEvent - lbxupsz_FocusEvent, + lbxsz_FocusEvent - lbxupsz_FocusEvent, + lbxsz_KeymapEvent - lbxupsz_KeymapEvent, + lbxsz_ExposeEvent - lbxupsz_ExposeEvent, + lbxsz_GfxExposeEvent - lbxupsz_GfxExposeEvent, + lbxsz_NoExposeEvent - lbxupsz_NoExposeEvent, + lbxsz_VisibilityEvent - lbxupsz_VisibilityEvent, + lbxsz_CreateNotifyEvent - lbxupsz_CreateNotifyEvent, + lbxsz_DestroyNotifyEvent - lbxupsz_DestroyNotifyEvent, + lbxsz_UnmapNotifyEvent - lbxupsz_UnmapNotifyEvent, + lbxsz_MapNotifyEvent - lbxupsz_MapNotifyEvent, + lbxsz_MapRequestEvent - lbxupsz_MapRequestEvent, + lbxsz_ReparentEvent - lbxupsz_ReparentEvent, + lbxsz_ConfigureNotifyEvent - lbxupsz_ConfigureNotifyEvent, + lbxsz_ConfigureRequestEvent - lbxupsz_ConfigureRequestEvent, + lbxsz_GravityEvent - lbxupsz_GravityEvent, + lbxsz_ResizeRequestEvent - lbxupsz_ResizeRequestEvent, + lbxsz_CirculateEvent - lbxupsz_CirculateEvent, + lbxsz_CirculateEvent - lbxupsz_CirculateEvent, + lbxsz_PropertyEvent - lbxupsz_PropertyEvent, + lbxsz_SelectionClearEvent - lbxupsz_SelectionClearEvent, + lbxsz_SelectionRequestEvent - lbxupsz_SelectionRequestEvent, + lbxsz_SelectionNotifyEvent - lbxupsz_SelectionNotifyEvent, + lbxsz_ColormapEvent - lbxupsz_ColormapEvent, + lbxsz_ClientMessageEvent - lbxupsz_ClientMessageEvent, + lbxsz_MappingNotifyEvent - lbxupsz_MappingNotifyEvent +}; + +int +LbxSquishEvent(buf) + char *buf; +{ + int delta = lbxevdelta[((xEvent *)buf)->u.u.type]; + int pad = lbxevpad[((xEvent *)buf)->u.u.type]; + + if (delta) + memmove(buf + delta, buf, sz_xEvent - delta); + if (pad) { + buf += sz_xEvent; + while (--pad >= 0) + *--buf = 0; + } + return delta; +} diff --git a/lbx/lbxsrvopts.h b/lbx/lbxsrvopts.h new file mode 100644 index 000000000..a08f1fec8 --- /dev/null +++ b/lbx/lbxsrvopts.h @@ -0,0 +1,78 @@ +/* $Xorg: lbxsrvopts.h,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */ +/* + * Copyright 1994 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef _LBX_SRVOPTS_H_ +#define _LBX_SRVOPTS_H_ + +#include "lbxopts.h" + +typedef struct _LbxNegOpts { + int nopts; + short proxyDeltaN; + short proxyDeltaMaxLen; + short serverDeltaN; + short serverDeltaMaxLen; + LbxStreamOpts streamOpts; + int numBitmapCompMethods; + char *bitmapCompMethods; /* array of indices */ + int numPixmapCompMethods; + char *pixmapCompMethods; /* array of indices */ + int **pixmapCompDepths; /* depths supported from each method */ + Bool squish; + Bool useTags; +} LbxNegOptsRec; + +typedef LbxNegOptsRec *LbxNegOptsPtr; + + +extern LbxBitmapCompMethod *LbxSrvrLookupBitmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr, /* proxy */ + int /* methodOpCode */ +#endif +); + +extern LbxPixmapCompMethod *LbxSrvrLookupPixmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr, /* proxy */ + int /* methodOpCode */ +#endif +); + +extern LbxBitmapCompMethod *LbxSrvrFindPreferredBitmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr /* proxy */ +#endif +); + +extern LbxPixmapCompMethod *LbxSrvrFindPreferredPixmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr, /* proxy */ + int, /* format */ + int /* depth */ +#endif +); + + +#endif /* _LBX_SRVOPTS_H_ */ diff --git a/lbx/lbxswap.c b/lbx/lbxswap.c new file mode 100644 index 000000000..38ba66b70 --- /dev/null +++ b/lbx/lbxswap.c @@ -0,0 +1,858 @@ +/* $Xorg: lbxswap.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1992 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 name of NCD. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. NCD. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD. + * 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. + * + */ + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "Xfuncproto.h" + +#include + +static int +SProcLbxQueryVersion(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxQueryVersionReq); + + swaps(&stuff->length, n); + return ProcLbxQueryVersion(client); +} + +static int +SProcLbxStartProxy(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxStartProxyReq); + + swaps(&stuff->length, n); + return ProcLbxStartProxy(client); +} + +static int +SProcLbxStopProxy(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxStopProxyReq); + + swaps(&stuff->length, n); + return ProcLbxStopProxy(client); +} + +int +SProcLbxSwitch(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxSwitchReq); + + swaps(&stuff->length, n); + swapl(&stuff->client, n); + return ProcLbxSwitch(client); +} + +int +SProcLbxBeginLargeRequest (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxBeginLargeRequestReq); + + swaps(&stuff->length, n); + swapl(&stuff->largeReqLength, n); + return ProcLbxBeginLargeRequest(client); +} + +int +SProcLbxLargeRequestData (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxLargeRequestDataReq); + + swaps(&stuff->length, n); + return ProcLbxLargeRequestData(client); +} + +int +SProcLbxEndLargeRequest (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxEndLargeRequestReq); + + swaps(&stuff->length, n); + return ProcLbxEndLargeRequest(client); +} + +static int +SProcLbxNewClient(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxNewClientReq); + + swaps(&stuff->length, n); + swapl(&stuff->client, n); + return ProcLbxNewClient(client); +} + +static int +SProcLbxCloseClient(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxCloseClientReq); + + swaps(&stuff->length, n); + swapl(&stuff->client, n); + return ProcLbxCloseClient(client); +} + +static int +SProcLbxModifySequence(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxModifySequenceReq); + + swaps(&stuff->length, n); + swapl(&stuff->adjust, n); + return ProcLbxModifySequence(client); +} + +static int +SProcLbxAllowMotion(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxAllowMotionReq); + + swaps(&stuff->length, n); + swapl(&stuff->num, n); + return ProcLbxAllowMotion(client); +} + +static int +SProcLbxIncrementPixel(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxIncrementPixelReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swapl(&stuff->pixel, n); + return ProcLbxIncrementPixel(client); +} + +static int +SProcLbxGrabCmap(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGrabCmapReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + + return ProcLbxGrabCmap(client); +} + +static int +SProcLbxReleaseCmap(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxReleaseCmapReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + + return ProcLbxReleaseCmap(client); +} + +static int +SProcLbxAllocColor(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxAllocColorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swapl(&stuff->pixel, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + + return ProcLbxAllocColor(client); +} + +static int +SProcLbxGetModifierMapping(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetModifierMappingReq); + + swaps(&stuff->length, n); + return ProcLbxGetModifierMapping(client); +} + +static int +SProcLbxGetKeyboardMapping(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetKeyboardMappingReq); + + swaps(&stuff->length, n); + return ProcLbxGetKeyboardMapping(client); +} + +static int +SProcLbxQueryFont(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxQueryFontReq); + + swaps(&stuff->length, n); + swapl(&stuff->fid, n); + return ProcLbxQueryFont(client); +} + +static int +SProcLbxChangeProperty(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxChangePropertyReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xLbxChangePropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch (stuff->format) { + case 8: + break; + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + } + return ProcLbxChangeProperty(client); +} + +static int +SProcLbxGetProperty(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetPropertyReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + return ProcLbxGetProperty(client); +} + +static int +SProcLbxTagData(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxTagDataReq); + + swaps(&stuff->length, n); + swapl(&stuff->tag, n); + swapl(&stuff->real_length, n); + return ProcLbxTagData(client); +} + +static int +SProcLbxInvalidateTag(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxInvalidateTagReq); + + swaps(&stuff->length, n); + swapl(&stuff->tag, n); + return ProcLbxInvalidateTag(client); +} + +static int +SProcLbxPoly(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxPolyPointReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxPolyPointReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxDispatch(client); +} + +static int +SProcLbxFillPoly(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxFillPolyReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxFillPolyReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxFillPoly(client); +} + +static int +SProcLbxCopyArea (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxCopyAreaReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxCopyAreaReq); + if (GFXdCacheEnt (stuff->srcCache) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxCopyArea(client); +} + +static int +SProcLbxCopyPlane (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxCopyPlaneReq); + char *after; + + swaps(&stuff->length, n); + swapl(&stuff->bitPlane, n); + after = ((char *) stuff) + SIZEOF(xLbxCopyPlaneReq); + if (GFXdCacheEnt (stuff->srcCache) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxCopyPlane(client); +} + +static int +SProcLbxPolyText(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxPolyTextReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxPolyTextReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxDispatch(client); +} + +static int +SProcLbxImageText(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxImageTextReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxImageTextReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxDispatch(client); +} + + +static int +SProcLbxPutImage(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxPutImageReq); + + swaps (&stuff->length, n); + return ProcLbxPutImage(client); +} + +static int +SProcLbxGetImage(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetImageReq); + + swaps (&stuff->length, n); + swapl (&stuff->drawable, n); + swaps (&stuff->x, n); + swaps (&stuff->y, n); + swaps (&stuff->width, n); + swaps (&stuff->height, n); + swapl (&stuff->planeMask, n); + return ProcLbxGetImage(client); +} + +static int +SProcLbxInternAtoms(client) + register ClientPtr client; +{ + register int n; + char *ptr; + char lenbuf[2]; + CARD16 len; + int i; + + REQUEST(xLbxInternAtomsReq); + + swaps (&stuff->length, n); + swaps (&stuff->num, n); + + ptr = (char *) stuff + sz_xLbxInternAtomsReq; + for (i = 0; i < stuff->num; i++) + { + swaps (ptr, n); + lenbuf[0] = ptr[0]; + lenbuf[1] = ptr[1]; + len = *((CARD16 *) lenbuf); + ptr += (len + 2); + } + + return ProcLbxInternAtoms(client); +} + + +static int +SProcLbxGetWinAttrAndGeom(client) + ClientPtr client; +{ + int n; + + REQUEST(xLbxGetWinAttrAndGeomReq); + + swaps(&stuff->length, n); + swapl(&stuff->id, n); + + return ProcLbxGetWinAttrAndGeom(client); +} + + + +static int +SProcLbxQueryExtension(client) + ClientPtr client; +{ + int n; + + REQUEST(xLbxQueryExtensionReq); + + swaps(&stuff->length, n); + swapl(&stuff->nbytes, n); + return ProcLbxQueryExtension(client); +} + +int +SProcLbxDispatch(client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_LbxQueryVersion: + return SProcLbxQueryVersion(client); + case X_LbxStartProxy: + return SProcLbxStartProxy(client); + case X_LbxStopProxy: + return SProcLbxStopProxy(client); + case X_LbxNewClient: + return SProcLbxNewClient(client); + case X_LbxCloseClient: + return SProcLbxCloseClient(client); + case X_LbxModifySequence: + return SProcLbxModifySequence(client); + case X_LbxAllowMotion: + return SProcLbxAllowMotion(client); + case X_LbxIncrementPixel: + return SProcLbxIncrementPixel(client); + case X_LbxGrabCmap: + return SProcLbxGrabCmap(client); + case X_LbxReleaseCmap: + return SProcLbxReleaseCmap(client); + case X_LbxAllocColor: + return SProcLbxAllocColor(client); + case X_LbxGetModifierMapping: + return SProcLbxGetModifierMapping(client); + case X_LbxGetKeyboardMapping: + return SProcLbxGetKeyboardMapping(client); + case X_LbxInvalidateTag: + return SProcLbxInvalidateTag(client); + case X_LbxPolyPoint: + case X_LbxPolyLine: + case X_LbxPolySegment: + case X_LbxPolyRectangle: + case X_LbxPolyArc: + case X_LbxPolyFillRectangle: + case X_LbxPolyFillArc: + return SProcLbxPoly(client); + case X_LbxFillPoly: + return SProcLbxFillPoly(client); + case X_LbxQueryFont: + return SProcLbxQueryFont(client); + case X_LbxChangeProperty: + return SProcLbxChangeProperty(client); + case X_LbxGetProperty: + return SProcLbxGetProperty(client); + case X_LbxTagData: + return SProcLbxTagData(client); + case X_LbxCopyArea: + return SProcLbxCopyArea(client); + case X_LbxCopyPlane: + return SProcLbxCopyPlane(client); + case X_LbxPolyText8: + case X_LbxPolyText16: + return SProcLbxPolyText(client); + case X_LbxImageText8: + case X_LbxImageText16: + return SProcLbxImageText (client); + case X_LbxQueryExtension: + return SProcLbxQueryExtension(client); + case X_LbxPutImage: + return SProcLbxPutImage(client); + case X_LbxGetImage: + return SProcLbxGetImage(client); + case X_LbxInternAtoms: + return SProcLbxInternAtoms(client); + case X_LbxGetWinAttrAndGeom: + return SProcLbxGetWinAttrAndGeom(client); + case X_LbxSync: + return ProcLbxSync(client); /* nothing to swap */ + case X_LbxBeginLargeRequest: + return SProcLbxBeginLargeRequest(client); + case X_LbxLargeRequestData: + return SProcLbxLargeRequestData(client); + default: + return BadRequest; + } +} + +#ifdef notyet +void +LbxWriteSConnectionInfo(pClient, size, pInfo) + ClientPtr pClient; + unsigned long size; + char *pInfo; +{ + int i, j, k; + ScreenPtr pScreen; + DepthPtr pDepth; + char *pInfoT, *pInfoTBase; + xConnSetup *pConnSetup = (xConnSetup *)pInfo; + + pInfoT = pInfoTBase = (char *) ALLOCATE_LOCAL(size); + if (!pInfoTBase) + { + pClient->noClientException = -1; + return; + } + SwapConnSetup(pConnSetup, (xConnSetup *)pInfoT); + pInfo += sizeof(xConnSetup); + pInfoT += sizeof(xConnSetup); + + /* Copy the vendor string */ + i = (pConnSetup->nbytesVendor + 3) & ~3; + memmove(pInfoT, pInfo, i); + pInfo += i; + pInfoT += i; + + /* The Pixmap formats don't need to be swapped, just copied. */ + i = sizeof(xPixmapFormat) * screenInfo.numPixmapFormats; + memmove(pInfoT, pInfo, i); + pInfo += i; + pInfoT += i; + + for(i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + SwapWinRoot((xWindowRoot *)pInfo, (xWindowRoot *)pInfoT); + pInfo += sizeof(xWindowRoot); + pInfoT += sizeof(xWindowRoot); + pDepth = pScreen->allowedDepths; + for(j = 0; j < pScreen->numDepths; j++, pDepth++) + { + ((xDepth *)pInfoT)->depth = ((xDepth *)pInfo)->depth; + cpswaps(((xDepth *)pInfo)->nVisuals, ((xDepth *)pInfoT)->nVisuals); + pInfo += sizeof(xDepth); + pInfoT += sizeof(xDepth); + for(k = 0; k < pDepth->numVids; k++) + { + SwapVisual((xVisualType *)pInfo, (xVisualType *)pInfoT); + pInfo += sizeof(xVisualType); + pInfoT += sizeof(xVisualType); + } + } + } + (void)WriteToClient(pClient, (int)size, (char *) pInfoTBase); + DEALLOCATE_LOCAL(pInfoTBase); +} + +void +SwapConnSetup(pConnSetup, pConnSetupT) + xConnSetup *pConnSetup, *pConnSetupT; +{ + cpswapl(pConnSetup->release, pConnSetupT->release); + cpswapl(pConnSetup->ridBase, pConnSetupT->ridBase); + cpswapl(pConnSetup->ridMask, pConnSetupT->ridMask); + cpswapl(pConnSetup->motionBufferSize, pConnSetupT->motionBufferSize); + cpswaps(pConnSetup->nbytesVendor, pConnSetupT->nbytesVendor); + cpswaps(pConnSetup->maxRequestSize, pConnSetupT->maxRequestSize); + pConnSetupT->minKeyCode = pConnSetup->minKeyCode; + pConnSetupT->maxKeyCode = pConnSetup->maxKeyCode; + pConnSetupT->numRoots = pConnSetup->numRoots; + pConnSetupT->numFormats = pConnSetup->numFormats; + pConnSetupT->imageByteOrder = pConnSetup->imageByteOrder; + pConnSetupT->bitmapBitOrder = pConnSetup->bitmapBitOrder; + pConnSetupT->bitmapScanlineUnit = pConnSetup->bitmapScanlineUnit; + pConnSetupT->bitmapScanlinePad = pConnSetup->bitmapScanlinePad; +} + +void +SwapWinRoot(pRoot, pRootT) + xWindowRoot *pRoot, *pRootT; +{ + cpswapl(pRoot->windowId, pRootT->windowId); + cpswapl(pRoot->defaultColormap, pRootT->defaultColormap); + cpswapl(pRoot->whitePixel, pRootT->whitePixel); + cpswapl(pRoot->blackPixel, pRootT->blackPixel); + cpswapl(pRoot->currentInputMask, pRootT->currentInputMask); + cpswaps(pRoot->pixWidth, pRootT->pixWidth); + cpswaps(pRoot->pixHeight, pRootT->pixHeight); + cpswaps(pRoot->mmWidth, pRootT->mmWidth); + cpswaps(pRoot->mmHeight, pRootT->mmHeight); + cpswaps(pRoot->minInstalledMaps, pRootT->minInstalledMaps); + cpswaps(pRoot->maxInstalledMaps, pRootT->maxInstalledMaps); + cpswapl(pRoot->rootVisualID, pRootT->rootVisualID); + pRootT->backingStore = pRoot->backingStore; + pRootT->saveUnders = pRoot->saveUnders; + pRootT->rootDepth = pRoot->rootDepth; + pRootT->nDepths = pRoot->nDepths; +} + +void +SwapVisual(pVis, pVisT) + xVisualType *pVis, *pVisT; +{ + cpswapl(pVis->visualID, pVisT->visualID); + pVisT->class = pVis->class; + pVisT->bitsPerRGB = pVis->bitsPerRGB; + cpswaps(pVis->colormapEntries, pVisT->colormapEntries); + cpswapl(pVis->redMask, pVisT->redMask); + cpswapl(pVis->greenMask, pVisT->greenMask); + cpswapl(pVis->blueMask, pVisT->blueMask); +} +#endif + +void +LbxWriteSConnSetupPrefix(pClient, pcsp) + ClientPtr pClient; + xLbxConnSetupPrefix *pcsp; +{ + xLbxConnSetupPrefix cspT; + + cspT.success = pcsp->success; + cspT.changeType = pcsp->changeType; + cspT.length = pcsp->length; + cpswaps(pcsp->majorVersion, cspT.majorVersion); + cpswaps(pcsp->minorVersion, cspT.minorVersion); + cpswapl(pcsp->tag, cspT.tag); + + (void)WriteToClient(pClient, sizeof(cspT), (char *) &cspT); +} + +void +LbxSwapFontInfo(pr, compressed) + xLbxFontInfo *pr; + Bool compressed; +{ + unsigned i; + xCharInfo *pxci; + unsigned nchars, + nprops; + char *pby; + register char n; + + nchars = pr->nCharInfos; + nprops = pr->nFontProps; + swaps(&pr->minCharOrByte2, n); + swaps(&pr->maxCharOrByte2, n); + swaps(&pr->defaultChar, n); + swaps(&pr->nFontProps, n); + swaps(&pr->fontAscent, n); + swaps(&pr->fontDescent, n); + SwapCharInfo(&pr->minBounds); + SwapCharInfo(&pr->maxBounds); + swapl(&pr->nCharInfos, n); + + pby = (char *) &pr[1]; + /* + * Font properties are an atom and either an int32 or a CARD32, so they + * are always 2 4 byte values + */ + for (i = 0; i < nprops; i++) { + swapl(pby, n); + pby += 4; + swapl(pby, n); + pby += 4; + } + if (!compressed) { + pxci = (xCharInfo *) pby; + for (i = 0; i < nchars; i++, pxci++) + SwapCharInfo(pxci); + } else { + SwapLongs((CARD32 *) pby, nchars); + } +} diff --git a/lbx/lbxtables.c b/lbx/lbxtables.c new file mode 100644 index 000000000..c3d4f1270 --- /dev/null +++ b/lbx/lbxtables.c @@ -0,0 +1,33 @@ +/* $Xorg: lbxtables.c,v 1.3 2000/08/17 19:53:32 cpqbld Exp $ */ +/* + * Copyright 1993 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +extern int ProcInitialConnection(); +extern int ProcLbxEstablishConnection(); + +int (* LbxInitialVector[3]) () = +{ + 0, + ProcInitialConnection, + ProcLbxEstablishConnection +}; diff --git a/lbx/lbxtags.c b/lbx/lbxtags.c new file mode 100644 index 000000000..b2bc40ade --- /dev/null +++ b/lbx/lbxtags.c @@ -0,0 +1,238 @@ +/* $Xorg: lbxtags.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1993 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "X.h" +#include "misc.h" +#include "lbxdata.h" +#include "resource.h" +#include "lbxtags.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "propertyst.h" + +static int tag_free(); + +static RESTYPE TagResType; + +/* ARGSUSED */ +static int +tag_free(data, id) + pointer data; + XID id; +{ + TagData td = (TagData) data; + FontTagInfoPtr ftip; + char *t; + extern int _lbx_fi_junklen; + + if (td->global) + *(td->global) = 0; + /* some types need to be freed, others are shared */ + if (td->data_type == LbxTagTypeFont) { + /* remove any back links */ + ftip = (FontTagInfoPtr) td->tdata; + FontSetPrivate(ftip->pfont, lbx_font_private, NULL); + t = (char *) ftip->fontinfo; + if (!ftip->compression) /* points to xQueryFont, so back up to it */ + t -= _lbx_fi_junklen; + xfree(t); + xfree(ftip); + } + xfree(data); + return 0; +} + +TagInit() +{ + TagResType = CreateNewResourceType(tag_free); +} + +XID +TagNewTag() +{ + return FakeClientID(0); +} + +void +TagClearProxy(tid, pid) + XID tid; + int pid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + if (td) + td->sent_to_proxy[pid >> 3] &= ~(1 << (pid & 7)); +} + +void +TagMarkProxy(tid, pid) + XID tid; + int pid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + td->sent_to_proxy[pid >> 3] |= 1 << (pid & 7); +} + +Bool +TagProxyMarked(tid, pid) + XID tid; + int pid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + return (td->sent_to_proxy[pid >> 3] & (1 << (pid & 7))) != 0; +} + +XID +TagSaveTag(dtype, size, data, global) + int dtype; + int size; + pointer data; + XID *global; +{ + TagData td; + + td = (TagData) xalloc(sizeof(TagDataRec)); + if (!td) { + if (global) + *global = 0; + return 0; + } + bzero((char *) td->sent_to_proxy, (MAX_NUM_PROXIES + 7) / 8); + td->tid = TagNewTag(); + td->data_type = dtype; + td->tdata = data; + td->size = size; + td->global = global; + if (!AddResource(td->tid, TagResType, (pointer) td)) + return 0; + if (global) + *global = td->tid; + return td->tid; +} + +void +TagDeleteTag(tid) + XID tid; +{ + int pid; + TagData td; + LbxProxyPtr proxy; + ClientPtr client; + LbxClientPtr lbxcp; + + td = (TagData) LookupIDByType(tid, TagResType); + if (!td) /* shouldn't happen, but play it safe */ + return; + for (pid = 1; pid < MAX_NUM_PROXIES; pid++) { + if (td->sent_to_proxy[pid >> 3] & (1 << (pid & 7))) { + proxy = LbxPidToProxy(pid); + lbxcp = (proxy != NULL) ? proxy->lbxClients[0] : NULL; + if (lbxcp && (client = lbxcp->client)) + LbxSendInvalidateTag(client, tid, td->data_type); + td->sent_to_proxy[pid >> 3] &= ~(1 << (pid & 7)); + } + } + if (td->data_type != LbxTagTypeProperty || !LbxFlushQTag(tid)) + FreeResource(tid, 0); + else if (td->global) { + *(td->global) = 0; + td->global = NULL; + } +} + +TagData +TagGetTag(tid) + XID tid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + return td; +} + +static void +LbxFlushTag(value, tid, cdata) + pointer value; + XID tid; + pointer cdata; +{ + TagData td = (TagData)value; + LbxProxyPtr proxy = (LbxProxyPtr)cdata; + int i; + + if ((td->data_type == LbxTagTypeProperty) && td->global) { + PropertyPtr pProp = (PropertyPtr)td->tdata; + if ((pProp->tag_id == tid) && (pProp->owner_pid == proxy->pid)) { + LbxFlushQTag(tid); + pProp->size = 0; + FreeResource(tid, 0); + return; + } + } + td->sent_to_proxy[proxy->pid >> 3] &= ~(1 << (proxy->pid & 7)); + for (i = 0; i < (MAX_NUM_PROXIES + 7) / 8; i++) { + if (td->sent_to_proxy[i]) + return; + } + FreeResource(tid, 0); +} + +/* + * clear out markers for proxies + */ +LbxFlushTags(proxy) + LbxProxyPtr proxy; +{ + FindClientResourcesByType(NULL, TagResType, LbxFlushTag, (pointer)proxy); +} diff --git a/lbx/lbxtags.h b/lbx/lbxtags.h new file mode 100644 index 000000000..3b6ab731a --- /dev/null +++ b/lbx/lbxtags.h @@ -0,0 +1,119 @@ +/* $Xorg: lbxtags.h,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1993 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 name Network Computing Devices, Inc. not be + * used in advertising or publicity pertaining to distribution of this + * software without specific, written prior permission. + * + * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC., + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT + * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK + * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING + * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, + * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF + * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef _LBXTAGS_H_ +#define _LBXTAGS_H_ +#include "lbxserve.h" + +#include "os.h" +#include "opaque.h" +#include "resource.h" +#include "X.h" +#include "Xproto.h" + +typedef struct _tagdata { + XID tid; + short data_type; + unsigned char sent_to_proxy[(MAX_NUM_PROXIES + 7) / 8]; + int size; + pointer tdata; + XID *global; +} TagDataRec; + +typedef struct _tagdata *TagData; + +extern TagData TagGetTag( +#if NeedFunctionPrototypes + XID /*tid*/ +#endif +); + +extern XID TagNewTag( +#if NeedFunctionPrototypes + void +#endif +); + +extern void TagClearProxy( +#if NeedFunctionPrototypes + XID /*tid*/, + int /*pid*/ +#endif +); + +extern void TagMarkProxy( +#if NeedFunctionPrototypes + XID /*tid*/, + int /*pid*/ +#endif +); + +extern Bool TagProxyMarked( +#if NeedFunctionPrototypes + XID /*tid*/, + int /*pid*/ +#endif +); + +extern void TagDeleteTag( +#if NeedFunctionPrototypes + XID /*tid*/ +#endif +); + +extern XID TagSaveTag( +#if NeedFunctionPrototypes + int /*dtype*/, + int /*size*/, + pointer /*data*/, + XID* /*global*/ +#endif +); + +#endif /* _LBXTAGS_H_ */ diff --git a/lbx/lbxzerorep.c b/lbx/lbxzerorep.c new file mode 100644 index 000000000..350d7f0f9 --- /dev/null +++ b/lbx/lbxzerorep.c @@ -0,0 +1,416 @@ +/* $Xorg: lbxzerorep.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ + +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * This module handles zeroing out unused pad bytes in core X replies. + * This will hopefully improve both stream and delta compression, + * since we are removing the random values in pad bytes. + */ + +#define NEED_REPLIES +#include "X.h" +#include + + +ZeroReplyPadBytes (buf, reqType) + char *buf; + int reqType; +{ + switch (reqType) { + case X_GetWindowAttributes: + { + xGetWindowAttributesReply *reply = (xGetWindowAttributesReply *) buf; + reply->pad = 0; + break; + } + case X_GetGeometry: + { + xGetGeometryReply *reply = (xGetGeometryReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + break; + } + case X_QueryTree: + { + xQueryTreeReply *reply = (xQueryTreeReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_InternAtom: + { + xInternAtomReply *reply = (xInternAtomReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GetAtomName: + { + xGetAtomNameReply *reply = (xGetAtomNameReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetProperty: + { + xGetPropertyReply *reply = (xGetPropertyReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + break; + } + case X_ListProperties: + { + xListPropertiesReply *reply = (xListPropertiesReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetSelectionOwner: + { + xGetSelectionOwnerReply *reply = (xGetSelectionOwnerReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GrabKeyboard: + case X_GrabPointer: + { + xGrabKeyboardReply *reply = (xGrabKeyboardReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_QueryPointer: + { + xQueryPointerReply *reply = (xQueryPointerReply *) buf; + reply->pad1 = 0; + reply->pad = 0; + break; + } + case X_GetMotionEvents: + { + xGetMotionEventsReply *reply = (xGetMotionEventsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_TranslateCoords: + { + xTranslateCoordsReply *reply = (xTranslateCoordsReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_GetInputFocus: + { + xGetInputFocusReply *reply = (xGetInputFocusReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_QueryKeymap: + { + xQueryKeymapReply *reply = (xQueryKeymapReply *) buf; + reply->pad1 = 0; + break; + } + case X_QueryFont: + { + xQueryFontReply *reply = (xQueryFontReply *) buf; + reply->pad1 = 0; + break; + } + case X_QueryTextExtents: + { + xQueryTextExtentsReply *reply = (xQueryTextExtentsReply *) buf; + reply->pad = 0; + break; + } + case X_ListFonts: + { + xListFontsReply *reply = (xListFontsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetFontPath: + { + xGetFontPathReply *reply = (xGetFontPathReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetImage: + { + xGetImageReply *reply = (xGetImageReply *) buf; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_ListInstalledColormaps: + { + xListInstalledColormapsReply *reply = + (xListInstalledColormapsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_AllocColor: + { + xAllocColorReply *reply = (xAllocColorReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_AllocNamedColor: + { + xAllocNamedColorReply *reply = (xAllocNamedColorReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + break; + } + case X_AllocColorCells: + { + xAllocColorCellsReply *reply = (xAllocColorCellsReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_AllocColorPlanes: + { + xAllocColorPlanesReply *reply = (xAllocColorPlanesReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + break; + } + case X_QueryColors: + { + xQueryColorsReply *reply = (xQueryColorsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_LookupColor: + { + xLookupColorReply *reply = (xLookupColorReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_QueryBestSize: + { + xQueryBestSizeReply *reply = (xQueryBestSizeReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_QueryExtension: + { + xQueryExtensionReply *reply = (xQueryExtensionReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_ListExtensions: + { + xListExtensionsReply *reply = (xListExtensionsReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_SetPointerMapping: + case X_SetModifierMapping: + { + xSetMappingReply *reply = (xSetMappingReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetPointerMapping: + { + xGetPointerMappingReply *reply = (xGetPointerMappingReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetKeyboardMapping: + { + xGetKeyboardMappingReply *reply = (xGetKeyboardMappingReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetModifierMapping: + { + xGetModifierMappingReply *reply = (xGetModifierMappingReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GetKeyboardControl: + { + xGetKeyboardControlReply *reply = (xGetKeyboardControlReply *) buf; + reply->pad = 0; + break; + } + case X_GetPointerControl: + { + xGetPointerControlReply *reply = (xGetPointerControlReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GetScreenSaver: + { + xGetScreenSaverReply *reply = (xGetScreenSaverReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_ListHosts: + { + xListHostsReply *reply = (xListHostsReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + } +} diff --git a/mfb/fastblt.h b/mfb/fastblt.h new file mode 100644 index 000000000..6567a8936 --- /dev/null +++ b/mfb/fastblt.h @@ -0,0 +1,118 @@ +/* $Xorg: fastblt.h,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Fast bitblt macros for certain hardware. If your machine has an addressing + * mode of small constant + register, you'll probably want this magic specific + * code. It's 25% faster for the R2000. I haven't studied the Sparc + * instruction set, but I suspect it also has this addressing mode. Also, + * unrolling the loop by 32 is possibly excessive for mfb. The number of times + * the loop is actually looped through is pretty small. + */ + +/* + * WARNING: These macros make *a lot* of assumptions about + * the environment they are invoked in. Plenty of implicit + * arguments, lots of side effects. Don't use them casually. + */ + +#define SwitchOdd(n) case n: BodyOdd(n) +#define SwitchEven(n) case n: BodyEven(n) + +/* to allow mfb and cfb to share code... */ +#ifndef BitRight +#define BitRight(a,b) SCRRIGHT(a,b) +#define BitLeft(a,b) SCRLEFT(a,b) +#endif + +#ifdef LARGE_INSTRUCTION_CACHE +#define UNROLL 8 +#define PackedLoop \ + switch (nl & (UNROLL-1)) { \ + SwitchOdd( 7) SwitchEven( 6) SwitchOdd( 5) SwitchEven( 4) \ + SwitchOdd( 3) SwitchEven( 2) SwitchOdd( 1) \ + } \ + while ((nl -= UNROLL) >= 0) { \ + LoopReset \ + BodyEven( 8) \ + BodyOdd( 7) BodyEven( 6) BodyOdd( 5) BodyEven( 4) \ + BodyOdd( 3) BodyEven( 2) BodyOdd( 1) \ + } +#else +#define UNROLL 4 +#define PackedLoop \ + switch (nl & (UNROLL-1)) { \ + SwitchOdd( 3) SwitchEven( 2) SwitchOdd( 1) \ + } \ + while ((nl -= UNROLL) >= 0) { \ + LoopReset \ + BodyEven( 4) \ + BodyOdd( 3) BodyEven( 2) BodyOdd( 1) \ + } +#endif + +#if PPW == 32 +#define DuffL(counter,label,body) \ + switch (counter & 3) { \ + label: \ + body \ + case 3: \ + body \ + case 2: \ + body \ + case 1: \ + body \ + case 0: \ + if ((counter -= 4) >= 0) \ + goto label; \ + } +#else /* PPW == 64 */ +#define DuffL(counter,label,body) \ + switch (counter & 7) { \ + label: \ + body \ + case 7: \ + body \ + case 6: \ + body \ + case 5: \ + body \ + case 4: \ + body \ + case 3: \ + body \ + case 2: \ + body \ + case 1: \ + body \ + case 0: \ + if ((counter -= 8) >= 0) \ + goto label; \ + } +#endif /* PPW */ diff --git a/mfb/maskbits.c b/mfb/maskbits.c new file mode 100644 index 000000000..deb62618a --- /dev/null +++ b/mfb/maskbits.c @@ -0,0 +1,9871 @@ +/* $Xorg: maskbits.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +*/ + +#include "maskbits.h" +#include "servermd.h" + +/* +these tables are used by several macros in the mfb code. + + the vax numbers everything left to right, so bit indices on the +screen match bit indices in longwords. the pc-rt and Sun number +bits on the screen the way they would be written on paper, +(i.e. msb to the left), and so a bit index n on the screen is +bit index PPW-n in a longword + + see also maskbits.h +*/ + +#if (BITMAP_BIT_ORDER == MSBFirst) +/* NOTE: +the first element in starttab could be 0xffffffff. making it 0 +lets us deal with a full first word in the middle loop, rather +than having to do the multiple reads and masks that we'd +have to do if we thought it was partial. +*/ +PixelType starttab[PPW+1] = + { + LONG2CHARS( 0x00000000 ), +#if PPW == 64 + LONG2CHARS( 0x7FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x07FFFFFFFFFFFFFF ), + LONG2CHARS( 0x03FFFFFFFFFFFFFF ), + LONG2CHARS( 0x01FFFFFFFFFFFFFF ), + LONG2CHARS( 0x00FFFFFFFFFFFFFF ), + LONG2CHARS( 0x007FFFFFFFFFFFFF ), + LONG2CHARS( 0x003FFFFFFFFFFFFF ), + LONG2CHARS( 0x001FFFFFFFFFFFFF ), + LONG2CHARS( 0x000FFFFFFFFFFFFF ), + LONG2CHARS( 0x0007FFFFFFFFFFFF ), + LONG2CHARS( 0x0003FFFFFFFFFFFF ), + LONG2CHARS( 0x0001FFFFFFFFFFFF ), + LONG2CHARS( 0x0000FFFFFFFFFFFF ), + LONG2CHARS( 0x00007FFFFFFFFFFF ), + LONG2CHARS( 0x00003FFFFFFFFFFF ), + LONG2CHARS( 0x00001FFFFFFFFFFF ), + LONG2CHARS( 0x00000FFFFFFFFFFF ), + LONG2CHARS( 0x000007FFFFFFFFFF ), + LONG2CHARS( 0x000003FFFFFFFFFF ), + LONG2CHARS( 0x000001FFFFFFFFFF ), + LONG2CHARS( 0x000000FFFFFFFFFF ), + LONG2CHARS( 0x0000007FFFFFFFFF ), + LONG2CHARS( 0x0000003FFFFFFFFF ), + LONG2CHARS( 0x0000001FFFFFFFFF ), + LONG2CHARS( 0x0000000FFFFFFFFF ), + LONG2CHARS( 0x00000007FFFFFFFF ), + LONG2CHARS( 0x00000003FFFFFFFF ), + LONG2CHARS( 0x00000001FFFFFFFF ), + LONG2CHARS( 0x00000000FFFFFFFF ), +#endif /* PPW == 64 */ + LONG2CHARS( 0x7FFFFFFF ), + LONG2CHARS( 0x3FFFFFFF ), + LONG2CHARS( 0x1FFFFFFF ), + LONG2CHARS( 0x0FFFFFFF ), + LONG2CHARS( 0x07FFFFFF ), + LONG2CHARS( 0x03FFFFFF ), + LONG2CHARS( 0x01FFFFFF ), + LONG2CHARS( 0x00FFFFFF ), + LONG2CHARS( 0x007FFFFF ), + LONG2CHARS( 0x003FFFFF ), + LONG2CHARS( 0x001FFFFF ), + LONG2CHARS( 0x000FFFFF ), + LONG2CHARS( 0x0007FFFF ), + LONG2CHARS( 0x0003FFFF ), + LONG2CHARS( 0x0001FFFF ), + LONG2CHARS( 0x0000FFFF ), + LONG2CHARS( 0x00007FFF ), + LONG2CHARS( 0x00003FFF ), + LONG2CHARS( 0x00001FFF ), + LONG2CHARS( 0x00000FFF ), + LONG2CHARS( 0x000007FF ), + LONG2CHARS( 0x000003FF ), + LONG2CHARS( 0x000001FF ), + LONG2CHARS( 0x000000FF ), + LONG2CHARS( 0x0000007F ), + LONG2CHARS( 0x0000003F ), + LONG2CHARS( 0x0000001F ), + LONG2CHARS( 0x0000000F ), + LONG2CHARS( 0x00000007 ), + LONG2CHARS( 0x00000003 ), + LONG2CHARS( 0x00000001 ), + LONG2CHARS( 0x00000000 ) + }; + +PixelType endtab[PPW+1] = + { +#if PPW == 32 + LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x80000000 ), + LONG2CHARS( 0xC0000000 ), + LONG2CHARS( 0xE0000000 ), + LONG2CHARS( 0xF0000000 ), + LONG2CHARS( 0xF8000000 ), + LONG2CHARS( 0xFC000000 ), + LONG2CHARS( 0xFE000000 ), + LONG2CHARS( 0xFF000000 ), + LONG2CHARS( 0xFF800000 ), + LONG2CHARS( 0xFFC00000 ), + LONG2CHARS( 0xFFE00000 ), + LONG2CHARS( 0xFFF00000 ), + LONG2CHARS( 0xFFF80000 ), + LONG2CHARS( 0xFFFC0000 ), + LONG2CHARS( 0xFFFE0000 ), + LONG2CHARS( 0xFFFF0000 ), + LONG2CHARS( 0xFFFF8000 ), + LONG2CHARS( 0xFFFFC000 ), + LONG2CHARS( 0xFFFFE000 ), + LONG2CHARS( 0xFFFFF000 ), + LONG2CHARS( 0xFFFFF800 ), + LONG2CHARS( 0xFFFFFC00 ), + LONG2CHARS( 0xFFFFFE00 ), + LONG2CHARS( 0xFFFFFF00 ), + LONG2CHARS( 0xFFFFFF80 ), + LONG2CHARS( 0xFFFFFFC0 ), + LONG2CHARS( 0xFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFFC ), + LONG2CHARS( 0xFFFFFFFE ), + LONG2CHARS( 0xFFFFFFFF ) +#else /* PPW */ + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x8000000000000000 ), + LONG2CHARS( 0xC000000000000000 ), + LONG2CHARS( 0xE000000000000000 ), + LONG2CHARS( 0xF000000000000000 ), + LONG2CHARS( 0xF800000000000000 ), + LONG2CHARS( 0xFC00000000000000 ), + LONG2CHARS( 0xFE00000000000000 ), + LONG2CHARS( 0xFF00000000000000 ), + LONG2CHARS( 0xFF80000000000000 ), + LONG2CHARS( 0xFFC0000000000000 ), + LONG2CHARS( 0xFFE0000000000000 ), + LONG2CHARS( 0xFFF0000000000000 ), + LONG2CHARS( 0xFFF8000000000000 ), + LONG2CHARS( 0xFFFC000000000000 ), + LONG2CHARS( 0xFFFE000000000000 ), + LONG2CHARS( 0xFFFF000000000000 ), + LONG2CHARS( 0xFFFF800000000000 ), + LONG2CHARS( 0xFFFFC00000000000 ), + LONG2CHARS( 0xFFFFE00000000000 ), + LONG2CHARS( 0xFFFFF00000000000 ), + LONG2CHARS( 0xFFFFF80000000000 ), + LONG2CHARS( 0xFFFFFC0000000000 ), + LONG2CHARS( 0xFFFFFE0000000000 ), + LONG2CHARS( 0xFFFFFF0000000000 ), + LONG2CHARS( 0xFFFFFF8000000000 ), + LONG2CHARS( 0xFFFFFFC000000000 ), + LONG2CHARS( 0xFFFFFFE000000000 ), + LONG2CHARS( 0xFFFFFFF000000000 ), + LONG2CHARS( 0xFFFFFFF800000000 ), + LONG2CHARS( 0xFFFFFFFC00000000 ), + LONG2CHARS( 0xFFFFFFFE00000000 ), + LONG2CHARS( 0xFFFFFFFF00000000 ), + LONG2CHARS( 0xFFFFFFFF80000000 ), + LONG2CHARS( 0xFFFFFFFFC0000000 ), + LONG2CHARS( 0xFFFFFFFFE0000000 ), + LONG2CHARS( 0xFFFFFFFFF0000000 ), + LONG2CHARS( 0xFFFFFFFFF8000000 ), + LONG2CHARS( 0xFFFFFFFFFC000000 ), + LONG2CHARS( 0xFFFFFFFFFE000000 ), + LONG2CHARS( 0xFFFFFFFFFF000000 ), + LONG2CHARS( 0xFFFFFFFFFF800000 ), + LONG2CHARS( 0xFFFFFFFFFFC00000 ), + LONG2CHARS( 0xFFFFFFFFFFE00000 ), + LONG2CHARS( 0xFFFFFFFFFFF00000 ), + LONG2CHARS( 0xFFFFFFFFFFF80000 ), + LONG2CHARS( 0xFFFFFFFFFFFC0000 ), + LONG2CHARS( 0xFFFFFFFFFFFE0000 ), + LONG2CHARS( 0xFFFFFFFFFFFF0000 ), + LONG2CHARS( 0xFFFFFFFFFFFF8000 ), + LONG2CHARS( 0xFFFFFFFFFFFFC000 ), + LONG2CHARS( 0xFFFFFFFFFFFFE000 ), + LONG2CHARS( 0xFFFFFFFFFFFFF000 ), + LONG2CHARS( 0xFFFFFFFFFFFFF800 ), + LONG2CHARS( 0xFFFFFFFFFFFFFC00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFE00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF80 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFC0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFC ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFE ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFF ) +#endif /* PPW */ + }; + +#ifndef LOWMEMFTPT + +#if NEED_OLD_MFB_MASKS +/* a hack, for now, since the entries for 0 need to be all + 1 bits, not all zeros. + this means the code DOES NOT WORK for segments of length + 0 (which is only a problem in the horizontal line code.) +*/ +PixelType startpartial[33] = + { + LONG2CHARS( 0xFFFFFFFF ), + LONG2CHARS( 0x7FFFFFFF ), + LONG2CHARS( 0x3FFFFFFF ), + LONG2CHARS( 0x1FFFFFFF ), + LONG2CHARS( 0x0FFFFFFF ), + LONG2CHARS( 0x07FFFFFF ), + LONG2CHARS( 0x03FFFFFF ), + LONG2CHARS( 0x01FFFFFF ), + LONG2CHARS( 0x00FFFFFF ), + LONG2CHARS( 0x007FFFFF ), + LONG2CHARS( 0x003FFFFF ), + LONG2CHARS( 0x001FFFFF ), + LONG2CHARS( 0x000FFFFF ), + LONG2CHARS( 0x0007FFFF ), + LONG2CHARS( 0x0003FFFF ), + LONG2CHARS( 0x0001FFFF ), + LONG2CHARS( 0x0000FFFF ), + LONG2CHARS( 0x00007FFF ), + LONG2CHARS( 0x00003FFF ), + LONG2CHARS( 0x00001FFF ), + LONG2CHARS( 0x00000FFF ), + LONG2CHARS( 0x000007FF ), + LONG2CHARS( 0x000003FF ), + LONG2CHARS( 0x000001FF ), + LONG2CHARS( 0x000000FF ), + LONG2CHARS( 0x0000007F ), + LONG2CHARS( 0x0000003F ), + LONG2CHARS( 0x0000001F ), + LONG2CHARS( 0x0000000F ), + LONG2CHARS( 0x00000007 ), + LONG2CHARS( 0x00000003 ), + LONG2CHARS( 0x00000001 ), + LONG2CHARS( 0x00000000 ) + }; + +PixelType endpartial[33] = + { + LONG2CHARS( 0xFFFFFFFF ), + LONG2CHARS( 0x80000000 ), + LONG2CHARS( 0xC0000000 ), + LONG2CHARS( 0xE0000000 ), + LONG2CHARS( 0xF0000000 ), + LONG2CHARS( 0xF8000000 ), + LONG2CHARS( 0xFC000000 ), + LONG2CHARS( 0xFE000000 ), + LONG2CHARS( 0xFF000000 ), + LONG2CHARS( 0xFF800000 ), + LONG2CHARS( 0xFFC00000 ), + LONG2CHARS( 0xFFE00000 ), + LONG2CHARS( 0xFFF00000 ), + LONG2CHARS( 0xFFF80000 ), + LONG2CHARS( 0xFFFC0000 ), + LONG2CHARS( 0xFFFE0000 ), + LONG2CHARS( 0xFFFF0000 ), + LONG2CHARS( 0xFFFF8000 ), + LONG2CHARS( 0xFFFFC000 ), + LONG2CHARS( 0xFFFFE000 ), + LONG2CHARS( 0xFFFFF000 ), + LONG2CHARS( 0xFFFFF800 ), + LONG2CHARS( 0xFFFFFC00 ), + LONG2CHARS( 0xFFFFFE00 ), + LONG2CHARS( 0xFFFFFF00 ), + LONG2CHARS( 0xFFFFFF80 ), + LONG2CHARS( 0xFFFFFFC0 ), + LONG2CHARS( 0xFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFFC ), + LONG2CHARS( 0xFFFFFFFE ), + LONG2CHARS( 0xFFFFFFFF ) + }; +#endif /* NEED_OLD_MFB_MASKS */ + +#endif /* ifndef LOWMEMFTPT */ + +#if PPW == 32 +PixelType partmasks[PPW][PPW] = { + {LONG2CHARS( 0xFFFFFFFF ), LONG2CHARS( 0x80000000 ), LONG2CHARS( 0xC0000000 ), LONG2CHARS( 0xE0000000 ), + LONG2CHARS( 0xF0000000 ), LONG2CHARS( 0xF8000000 ), LONG2CHARS( 0xFC000000 ), LONG2CHARS( 0xFE000000 ), + LONG2CHARS( 0xFF000000 ), LONG2CHARS( 0xFF800000 ), LONG2CHARS( 0xFFC00000 ), LONG2CHARS( 0xFFE00000 ), + LONG2CHARS( 0xFFF00000 ), LONG2CHARS( 0xFFF80000 ), LONG2CHARS( 0xFFFC0000 ), LONG2CHARS( 0xFFFE0000 ), + LONG2CHARS( 0xFFFF0000 ), LONG2CHARS( 0xFFFF8000 ), LONG2CHARS( 0xFFFFC000 ), LONG2CHARS( 0xFFFFE000 ), + LONG2CHARS( 0xFFFFF000 ), LONG2CHARS( 0xFFFFF800 ), LONG2CHARS( 0xFFFFFC00 ), LONG2CHARS( 0xFFFFFE00 ), + LONG2CHARS( 0xFFFFFF00 ), LONG2CHARS( 0xFFFFFF80 ), LONG2CHARS( 0xFFFFFFC0 ), LONG2CHARS( 0xFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFF0 ), LONG2CHARS( 0xFFFFFFF8 ), LONG2CHARS( 0xFFFFFFFC ), LONG2CHARS( 0xFFFFFFFE )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x40000000 ), LONG2CHARS( 0x60000000 ), LONG2CHARS( 0x70000000 ), + LONG2CHARS( 0x78000000 ), LONG2CHARS( 0x7C000000 ), LONG2CHARS( 0x7E000000 ), LONG2CHARS( 0x7F000000 ), + LONG2CHARS( 0x7F800000 ), LONG2CHARS( 0x7FC00000 ), LONG2CHARS( 0x7FE00000 ), LONG2CHARS( 0x7FF00000 ), + LONG2CHARS( 0x7FF80000 ), LONG2CHARS( 0x7FFC0000 ), LONG2CHARS( 0x7FFE0000 ), LONG2CHARS( 0x7FFF0000 ), + LONG2CHARS( 0x7FFF8000 ), LONG2CHARS( 0x7FFFC000 ), LONG2CHARS( 0x7FFFE000 ), LONG2CHARS( 0x7FFFF000 ), + LONG2CHARS( 0x7FFFF800 ), LONG2CHARS( 0x7FFFFC00 ), LONG2CHARS( 0x7FFFFE00 ), LONG2CHARS( 0x7FFFFF00 ), + LONG2CHARS( 0x7FFFFF80 ), LONG2CHARS( 0x7FFFFFC0 ), LONG2CHARS( 0x7FFFFFE0 ), LONG2CHARS( 0x7FFFFFF0 ), + LONG2CHARS( 0x7FFFFFF8 ), LONG2CHARS( 0x7FFFFFFC ), LONG2CHARS( 0x7FFFFFFE ), LONG2CHARS( 0x7FFFFFFF )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x20000000 ), LONG2CHARS( 0x30000000 ), LONG2CHARS( 0x38000000 ), + LONG2CHARS( 0x3C000000 ), LONG2CHARS( 0x3E000000 ), LONG2CHARS( 0x3F000000 ), LONG2CHARS( 0x3F800000 ), + LONG2CHARS( 0x3FC00000 ), LONG2CHARS( 0x3FE00000 ), LONG2CHARS( 0x3FF00000 ), LONG2CHARS( 0x3FF80000 ), + LONG2CHARS( 0x3FFC0000 ), LONG2CHARS( 0x3FFE0000 ), LONG2CHARS( 0x3FFF0000 ), LONG2CHARS( 0x3FFF8000 ), + LONG2CHARS( 0x3FFFC000 ), LONG2CHARS( 0x3FFFE000 ), LONG2CHARS( 0x3FFFF000 ), LONG2CHARS( 0x3FFFF800 ), + LONG2CHARS( 0x3FFFFC00 ), LONG2CHARS( 0x3FFFFE00 ), LONG2CHARS( 0x3FFFFF00 ), LONG2CHARS( 0x3FFFFF80 ), + LONG2CHARS( 0x3FFFFFC0 ), LONG2CHARS( 0x3FFFFFE0 ), LONG2CHARS( 0x3FFFFFF0 ), LONG2CHARS( 0x3FFFFFF8 ), + LONG2CHARS( 0x3FFFFFFC ), LONG2CHARS( 0x3FFFFFFE ), LONG2CHARS( 0x3FFFFFFF ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x10000000 ), LONG2CHARS( 0x18000000 ), LONG2CHARS( 0x1C000000 ), + LONG2CHARS( 0x1E000000 ), LONG2CHARS( 0x1F000000 ), LONG2CHARS( 0x1F800000 ), LONG2CHARS( 0x1FC00000 ), + LONG2CHARS( 0x1FE00000 ), LONG2CHARS( 0x1FF00000 ), LONG2CHARS( 0x1FF80000 ), LONG2CHARS( 0x1FFC0000 ), + LONG2CHARS( 0x1FFE0000 ), LONG2CHARS( 0x1FFF0000 ), LONG2CHARS( 0x1FFF8000 ), LONG2CHARS( 0x1FFFC000 ), + LONG2CHARS( 0x1FFFE000 ), LONG2CHARS( 0x1FFFF000 ), LONG2CHARS( 0x1FFFF800 ), LONG2CHARS( 0x1FFFFC00 ), + LONG2CHARS( 0x1FFFFE00 ), LONG2CHARS( 0x1FFFFF00 ), LONG2CHARS( 0x1FFFFF80 ), LONG2CHARS( 0x1FFFFFC0 ), + LONG2CHARS( 0x1FFFFFE0 ), LONG2CHARS( 0x1FFFFFF0 ), LONG2CHARS( 0x1FFFFFF8 ), LONG2CHARS( 0x1FFFFFFC ), + LONG2CHARS( 0x1FFFFFFE ), LONG2CHARS( 0x1FFFFFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x08000000 ), LONG2CHARS( 0x0C000000 ), LONG2CHARS( 0x0E000000 ), + LONG2CHARS( 0x0F000000 ), LONG2CHARS( 0x0F800000 ), LONG2CHARS( 0x0FC00000 ), LONG2CHARS( 0x0FE00000 ), + LONG2CHARS( 0x0FF00000 ), LONG2CHARS( 0x0FF80000 ), LONG2CHARS( 0x0FFC0000 ), LONG2CHARS( 0x0FFE0000 ), + LONG2CHARS( 0x0FFF0000 ), LONG2CHARS( 0x0FFF8000 ), LONG2CHARS( 0x0FFFC000 ), LONG2CHARS( 0x0FFFE000 ), + LONG2CHARS( 0x0FFFF000 ), LONG2CHARS( 0x0FFFF800 ), LONG2CHARS( 0x0FFFFC00 ), LONG2CHARS( 0x0FFFFE00 ), + LONG2CHARS( 0x0FFFFF00 ), LONG2CHARS( 0x0FFFFF80 ), LONG2CHARS( 0x0FFFFFC0 ), LONG2CHARS( 0x0FFFFFE0 ), + LONG2CHARS( 0x0FFFFFF0 ), LONG2CHARS( 0x0FFFFFF8 ), LONG2CHARS( 0x0FFFFFFC ), LONG2CHARS( 0x0FFFFFFE ), + LONG2CHARS( 0x0FFFFFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x04000000 ), LONG2CHARS( 0x06000000 ), LONG2CHARS( 0x07000000 ), + LONG2CHARS( 0x07800000 ), LONG2CHARS( 0x07C00000 ), LONG2CHARS( 0x07E00000 ), LONG2CHARS( 0x07F00000 ), + LONG2CHARS( 0x07F80000 ), LONG2CHARS( 0x07FC0000 ), LONG2CHARS( 0x07FE0000 ), LONG2CHARS( 0x07FF0000 ), + LONG2CHARS( 0x07FF8000 ), LONG2CHARS( 0x07FFC000 ), LONG2CHARS( 0x07FFE000 ), LONG2CHARS( 0x07FFF000 ), + LONG2CHARS( 0x07FFF800 ), LONG2CHARS( 0x07FFFC00 ), LONG2CHARS( 0x07FFFE00 ), LONG2CHARS( 0x07FFFF00 ), + LONG2CHARS( 0x07FFFF80 ), LONG2CHARS( 0x07FFFFC0 ), LONG2CHARS( 0x07FFFFE0 ), LONG2CHARS( 0x07FFFFF0 ), + LONG2CHARS( 0x07FFFFF8 ), LONG2CHARS( 0x07FFFFFC ), LONG2CHARS( 0x07FFFFFE ), LONG2CHARS( 0x07FFFFFF ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x02000000 ), LONG2CHARS( 0x03000000 ), LONG2CHARS( 0x03800000 ), + LONG2CHARS( 0x03C00000 ), LONG2CHARS( 0x03E00000 ), LONG2CHARS( 0x03F00000 ), LONG2CHARS( 0x03F80000 ), + LONG2CHARS( 0x03FC0000 ), LONG2CHARS( 0x03FE0000 ), LONG2CHARS( 0x03FF0000 ), LONG2CHARS( 0x03FF8000 ), + LONG2CHARS( 0x03FFC000 ), LONG2CHARS( 0x03FFE000 ), LONG2CHARS( 0x03FFF000 ), LONG2CHARS( 0x03FFF800 ), + LONG2CHARS( 0x03FFFC00 ), LONG2CHARS( 0x03FFFE00 ), LONG2CHARS( 0x03FFFF00 ), LONG2CHARS( 0x03FFFF80 ), + LONG2CHARS( 0x03FFFFC0 ), LONG2CHARS( 0x03FFFFE0 ), LONG2CHARS( 0x03FFFFF0 ), LONG2CHARS( 0x03FFFFF8 ), + LONG2CHARS( 0x03FFFFFC ), LONG2CHARS( 0x03FFFFFE ), LONG2CHARS( 0x03FFFFFF ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x01000000 ), LONG2CHARS( 0x01800000 ), LONG2CHARS( 0x01C00000 ), + LONG2CHARS( 0x01E00000 ), LONG2CHARS( 0x01F00000 ), LONG2CHARS( 0x01F80000 ), LONG2CHARS( 0x01FC0000 ), + LONG2CHARS( 0x01FE0000 ), LONG2CHARS( 0x01FF0000 ), LONG2CHARS( 0x01FF8000 ), LONG2CHARS( 0x01FFC000 ), + LONG2CHARS( 0x01FFE000 ), LONG2CHARS( 0x01FFF000 ), LONG2CHARS( 0x01FFF800 ), LONG2CHARS( 0x01FFFC00 ), + LONG2CHARS( 0x01FFFE00 ), LONG2CHARS( 0x01FFFF00 ), LONG2CHARS( 0x01FFFF80 ), LONG2CHARS( 0x01FFFFC0 ), + LONG2CHARS( 0x01FFFFE0 ), LONG2CHARS( 0x01FFFFF0 ), LONG2CHARS( 0x01FFFFF8 ), LONG2CHARS( 0x01FFFFFC ), + LONG2CHARS( 0x01FFFFFE ), LONG2CHARS( 0x01FFFFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00800000 ), LONG2CHARS( 0x00C00000 ), LONG2CHARS( 0x00E00000 ), + LONG2CHARS( 0x00F00000 ), LONG2CHARS( 0x00F80000 ), LONG2CHARS( 0x00FC0000 ), LONG2CHARS( 0x00FE0000 ), + LONG2CHARS( 0x00FF0000 ), LONG2CHARS( 0x00FF8000 ), LONG2CHARS( 0x00FFC000 ), LONG2CHARS( 0x00FFE000 ), + LONG2CHARS( 0x00FFF000 ), LONG2CHARS( 0x00FFF800 ), LONG2CHARS( 0x00FFFC00 ), LONG2CHARS( 0x00FFFE00 ), + LONG2CHARS( 0x00FFFF00 ), LONG2CHARS( 0x00FFFF80 ), LONG2CHARS( 0x00FFFFC0 ), LONG2CHARS( 0x00FFFFE0 ), + LONG2CHARS( 0x00FFFFF0 ), LONG2CHARS( 0x00FFFFF8 ), LONG2CHARS( 0x00FFFFFC ), LONG2CHARS( 0x00FFFFFE ), + LONG2CHARS( 0x00FFFFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00400000 ), LONG2CHARS( 0x00600000 ), LONG2CHARS( 0x00700000 ), + LONG2CHARS( 0x00780000 ), LONG2CHARS( 0x007C0000 ), LONG2CHARS( 0x007E0000 ), LONG2CHARS( 0x007F0000 ), + LONG2CHARS( 0x007F8000 ), LONG2CHARS( 0x007FC000 ), LONG2CHARS( 0x007FE000 ), LONG2CHARS( 0x007FF000 ), + LONG2CHARS( 0x007FF800 ), LONG2CHARS( 0x007FFC00 ), LONG2CHARS( 0x007FFE00 ), LONG2CHARS( 0x007FFF00 ), + LONG2CHARS( 0x007FFF80 ), LONG2CHARS( 0x007FFFC0 ), LONG2CHARS( 0x007FFFE0 ), LONG2CHARS( 0x007FFFF0 ), + LONG2CHARS( 0x007FFFF8 ), LONG2CHARS( 0x007FFFFC ), LONG2CHARS( 0x007FFFFE ), LONG2CHARS( 0x007FFFFF ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00200000 ), LONG2CHARS( 0x00300000 ), LONG2CHARS( 0x00380000 ), + LONG2CHARS( 0x003C0000 ), LONG2CHARS( 0x003E0000 ), LONG2CHARS( 0x003F0000 ), LONG2CHARS( 0x003F8000 ), + LONG2CHARS( 0x003FC000 ), LONG2CHARS( 0x003FE000 ), LONG2CHARS( 0x003FF000 ), LONG2CHARS( 0x003FF800 ), + LONG2CHARS( 0x003FFC00 ), LONG2CHARS( 0x003FFE00 ), LONG2CHARS( 0x003FFF00 ), LONG2CHARS( 0x003FFF80 ), + LONG2CHARS( 0x003FFFC0 ), LONG2CHARS( 0x003FFFE0 ), LONG2CHARS( 0x003FFFF0 ), LONG2CHARS( 0x003FFFF8 ), + LONG2CHARS( 0x003FFFFC ), LONG2CHARS( 0x003FFFFE ), LONG2CHARS( 0x003FFFFF ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00100000 ), LONG2CHARS( 0x00180000 ), LONG2CHARS( 0x001C0000 ), + LONG2CHARS( 0x001E0000 ), LONG2CHARS( 0x001F0000 ), LONG2CHARS( 0x001F8000 ), LONG2CHARS( 0x001FC000 ), + LONG2CHARS( 0x001FE000 ), LONG2CHARS( 0x001FF000 ), LONG2CHARS( 0x001FF800 ), LONG2CHARS( 0x001FFC00 ), + LONG2CHARS( 0x001FFE00 ), LONG2CHARS( 0x001FFF00 ), LONG2CHARS( 0x001FFF80 ), LONG2CHARS( 0x001FFFC0 ), + LONG2CHARS( 0x001FFFE0 ), LONG2CHARS( 0x001FFFF0 ), LONG2CHARS( 0x001FFFF8 ), LONG2CHARS( 0x001FFFFC ), + LONG2CHARS( 0x001FFFFE ), LONG2CHARS( 0x001FFFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00080000 ), LONG2CHARS( 0x000C0000 ), LONG2CHARS( 0x000E0000 ), + LONG2CHARS( 0x000F0000 ), LONG2CHARS( 0x000F8000 ), LONG2CHARS( 0x000FC000 ), LONG2CHARS( 0x000FE000 ), + LONG2CHARS( 0x000FF000 ), LONG2CHARS( 0x000FF800 ), LONG2CHARS( 0x000FFC00 ), LONG2CHARS( 0x000FFE00 ), + LONG2CHARS( 0x000FFF00 ), LONG2CHARS( 0x000FFF80 ), LONG2CHARS( 0x000FFFC0 ), LONG2CHARS( 0x000FFFE0 ), + LONG2CHARS( 0x000FFFF0 ), LONG2CHARS( 0x000FFFF8 ), LONG2CHARS( 0x000FFFFC ), LONG2CHARS( 0x000FFFFE ), + LONG2CHARS( 0x000FFFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00040000 ), LONG2CHARS( 0x00060000 ), LONG2CHARS( 0x00070000 ), + LONG2CHARS( 0x00078000 ), LONG2CHARS( 0x0007C000 ), LONG2CHARS( 0x0007E000 ), LONG2CHARS( 0x0007F000 ), + LONG2CHARS( 0x0007F800 ), LONG2CHARS( 0x0007FC00 ), LONG2CHARS( 0x0007FE00 ), LONG2CHARS( 0x0007FF00 ), + LONG2CHARS( 0x0007FF80 ), LONG2CHARS( 0x0007FFC0 ), LONG2CHARS( 0x0007FFE0 ), LONG2CHARS( 0x0007FFF0 ), + LONG2CHARS( 0x0007FFF8 ), LONG2CHARS( 0x0007FFFC ), LONG2CHARS( 0x0007FFFE ), LONG2CHARS( 0x0007FFFF ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00020000 ), LONG2CHARS( 0x00030000 ), LONG2CHARS( 0x00038000 ), + LONG2CHARS( 0x0003C000 ), LONG2CHARS( 0x0003E000 ), LONG2CHARS( 0x0003F000 ), LONG2CHARS( 0x0003F800 ), + LONG2CHARS( 0x0003FC00 ), LONG2CHARS( 0x0003FE00 ), LONG2CHARS( 0x0003FF00 ), LONG2CHARS( 0x0003FF80 ), + LONG2CHARS( 0x0003FFC0 ), LONG2CHARS( 0x0003FFE0 ), LONG2CHARS( 0x0003FFF0 ), LONG2CHARS( 0x0003FFF8 ), + LONG2CHARS( 0x0003FFFC ), LONG2CHARS( 0x0003FFFE ), LONG2CHARS( 0x0003FFFF ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00010000 ), LONG2CHARS( 0x00018000 ), LONG2CHARS( 0x0001C000 ), + LONG2CHARS( 0x0001E000 ), LONG2CHARS( 0x0001F000 ), LONG2CHARS( 0x0001F800 ), LONG2CHARS( 0x0001FC00 ), + LONG2CHARS( 0x0001FE00 ), LONG2CHARS( 0x0001FF00 ), LONG2CHARS( 0x0001FF80 ), LONG2CHARS( 0x0001FFC0 ), + LONG2CHARS( 0x0001FFE0 ), LONG2CHARS( 0x0001FFF0 ), LONG2CHARS( 0x0001FFF8 ), LONG2CHARS( 0x0001FFFC ), + LONG2CHARS( 0x0001FFFE ), LONG2CHARS( 0x0001FFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00008000 ), LONG2CHARS( 0x0000C000 ), LONG2CHARS( 0x0000E000 ), + LONG2CHARS( 0x0000F000 ), LONG2CHARS( 0x0000F800 ), LONG2CHARS( 0x0000FC00 ), LONG2CHARS( 0x0000FE00 ), + LONG2CHARS( 0x0000FF00 ), LONG2CHARS( 0x0000FF80 ), LONG2CHARS( 0x0000FFC0 ), LONG2CHARS( 0x0000FFE0 ), + LONG2CHARS( 0x0000FFF0 ), LONG2CHARS( 0x0000FFF8 ), LONG2CHARS( 0x0000FFFC ), LONG2CHARS( 0x0000FFFE ), + LONG2CHARS( 0x0000FFFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00004000 ), LONG2CHARS( 0x00006000 ), LONG2CHARS( 0x00007000 ), + LONG2CHARS( 0x00007800 ), LONG2CHARS( 0x00007C00 ), LONG2CHARS( 0x00007E00 ), LONG2CHARS( 0x00007F00 ), + LONG2CHARS( 0x00007F80 ), LONG2CHARS( 0x00007FC0 ), LONG2CHARS( 0x00007FE0 ), LONG2CHARS( 0x00007FF0 ), + LONG2CHARS( 0x00007FF8 ), LONG2CHARS( 0x00007FFC ), LONG2CHARS( 0x00007FFE ), LONG2CHARS( 0x00007FFF ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00002000 ), LONG2CHARS( 0x00003000 ), LONG2CHARS( 0x00003800 ), + LONG2CHARS( 0x00003C00 ), LONG2CHARS( 0x00003E00 ), LONG2CHARS( 0x00003F00 ), LONG2CHARS( 0x00003F80 ), + LONG2CHARS( 0x00003FC0 ), LONG2CHARS( 0x00003FE0 ), LONG2CHARS( 0x00003FF0 ), LONG2CHARS( 0x00003FF8 ), + LONG2CHARS( 0x00003FFC ), LONG2CHARS( 0x00003FFE ), LONG2CHARS( 0x00003FFF ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00001000 ), LONG2CHARS( 0x00001800 ), LONG2CHARS( 0x00001C00 ), + LONG2CHARS( 0x00001E00 ), LONG2CHARS( 0x00001F00 ), LONG2CHARS( 0x00001F80 ), LONG2CHARS( 0x00001FC0 ), + LONG2CHARS( 0x00001FE0 ), LONG2CHARS( 0x00001FF0 ), LONG2CHARS( 0x00001FF8 ), LONG2CHARS( 0x00001FFC ), + LONG2CHARS( 0x00001FFE ), LONG2CHARS( 0x00001FFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000800 ), LONG2CHARS( 0x00000C00 ), LONG2CHARS( 0x00000E00 ), + LONG2CHARS( 0x00000F00 ), LONG2CHARS( 0x00000F80 ), LONG2CHARS( 0x00000FC0 ), LONG2CHARS( 0x00000FE0 ), + LONG2CHARS( 0x00000FF0 ), LONG2CHARS( 0x00000FF8 ), LONG2CHARS( 0x00000FFC ), LONG2CHARS( 0x00000FFE ), + LONG2CHARS( 0x00000FFF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000400 ), LONG2CHARS( 0x00000600 ), LONG2CHARS( 0x00000700 ), + LONG2CHARS( 0x00000780 ), LONG2CHARS( 0x000007C0 ), LONG2CHARS( 0x000007E0 ), LONG2CHARS( 0x000007F0 ), + LONG2CHARS( 0x000007F8 ), LONG2CHARS( 0x000007FC ), LONG2CHARS( 0x000007FE ), LONG2CHARS( 0x000007FF ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000200 ), LONG2CHARS( 0x00000300 ), LONG2CHARS( 0x00000380 ), + LONG2CHARS( 0x000003C0 ), LONG2CHARS( 0x000003E0 ), LONG2CHARS( 0x000003F0 ), LONG2CHARS( 0x000003F8 ), + LONG2CHARS( 0x000003FC ), LONG2CHARS( 0x000003FE ), LONG2CHARS( 0x000003FF ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000100 ), LONG2CHARS( 0x00000180 ), LONG2CHARS( 0x000001C0 ), + LONG2CHARS( 0x000001E0 ), LONG2CHARS( 0x000001F0 ), LONG2CHARS( 0x000001F8 ), LONG2CHARS( 0x000001FC ), + LONG2CHARS( 0x000001FE ), LONG2CHARS( 0x000001FF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000080 ), LONG2CHARS( 0x000000C0 ), LONG2CHARS( 0x000000E0 ), + LONG2CHARS( 0x000000F0 ), LONG2CHARS( 0x000000F8 ), LONG2CHARS( 0x000000FC ), LONG2CHARS( 0x000000FE ), + LONG2CHARS( 0x000000FF ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000040 ), LONG2CHARS( 0x00000060 ), LONG2CHARS( 0x00000070 ), + LONG2CHARS( 0x00000078 ), LONG2CHARS( 0x0000007C ), LONG2CHARS( 0x0000007E ), LONG2CHARS( 0x0000007F ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000020 ), LONG2CHARS( 0x00000030 ), LONG2CHARS( 0x00000038 ), + LONG2CHARS( 0x0000003C ), LONG2CHARS( 0x0000003E ), LONG2CHARS( 0x0000003F ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000010 ), LONG2CHARS( 0x00000018 ), LONG2CHARS( 0x0000001C ), + LONG2CHARS( 0x0000001E ), LONG2CHARS( 0x0000001F ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000008 ), LONG2CHARS( 0x0000000C ), LONG2CHARS( 0x0000000E ), + LONG2CHARS( 0x0000000F ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000004 ), LONG2CHARS( 0x00000006 ), LONG2CHARS( 0x00000007 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000002 ), LONG2CHARS( 0x00000003 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000001 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, +}; +#else /* PPW == 64 */ +unsigned long partmasks[PPW][PPW] = { + { + LONG2CHARS( 0xFFFFFFFFFFFFFFFF ), + LONG2CHARS( 0x8000000000000000 ), + LONG2CHARS( 0xC000000000000000 ), + LONG2CHARS( 0xE000000000000000 ), + LONG2CHARS( 0xF000000000000000 ), + LONG2CHARS( 0xF800000000000000 ), + LONG2CHARS( 0xFC00000000000000 ), + LONG2CHARS( 0xFE00000000000000 ), + LONG2CHARS( 0xFF00000000000000 ), + LONG2CHARS( 0xFF80000000000000 ), + LONG2CHARS( 0xFFC0000000000000 ), + LONG2CHARS( 0xFFE0000000000000 ), + LONG2CHARS( 0xFFF0000000000000 ), + LONG2CHARS( 0xFFF8000000000000 ), + LONG2CHARS( 0xFFFC000000000000 ), + LONG2CHARS( 0xFFFE000000000000 ), + LONG2CHARS( 0xFFFF000000000000 ), + LONG2CHARS( 0xFFFF800000000000 ), + LONG2CHARS( 0xFFFFC00000000000 ), + LONG2CHARS( 0xFFFFE00000000000 ), + LONG2CHARS( 0xFFFFF00000000000 ), + LONG2CHARS( 0xFFFFF80000000000 ), + LONG2CHARS( 0xFFFFFC0000000000 ), + LONG2CHARS( 0xFFFFFE0000000000 ), + LONG2CHARS( 0xFFFFFF0000000000 ), + LONG2CHARS( 0xFFFFFF8000000000 ), + LONG2CHARS( 0xFFFFFFC000000000 ), + LONG2CHARS( 0xFFFFFFE000000000 ), + LONG2CHARS( 0xFFFFFFF000000000 ), + LONG2CHARS( 0xFFFFFFF800000000 ), + LONG2CHARS( 0xFFFFFFFC00000000 ), + LONG2CHARS( 0xFFFFFFFE00000000 ), + LONG2CHARS( 0xFFFFFFFF00000000 ), + LONG2CHARS( 0xFFFFFFFF80000000 ), + LONG2CHARS( 0xFFFFFFFFC0000000 ), + LONG2CHARS( 0xFFFFFFFFE0000000 ), + LONG2CHARS( 0xFFFFFFFFF0000000 ), + LONG2CHARS( 0xFFFFFFFFF8000000 ), + LONG2CHARS( 0xFFFFFFFFFC000000 ), + LONG2CHARS( 0xFFFFFFFFFE000000 ), + LONG2CHARS( 0xFFFFFFFFFF000000 ), + LONG2CHARS( 0xFFFFFFFFFF800000 ), + LONG2CHARS( 0xFFFFFFFFFFC00000 ), + LONG2CHARS( 0xFFFFFFFFFFE00000 ), + LONG2CHARS( 0xFFFFFFFFFFF00000 ), + LONG2CHARS( 0xFFFFFFFFFFF80000 ), + LONG2CHARS( 0xFFFFFFFFFFFC0000 ), + LONG2CHARS( 0xFFFFFFFFFFFE0000 ), + LONG2CHARS( 0xFFFFFFFFFFFF0000 ), + LONG2CHARS( 0xFFFFFFFFFFFF8000 ), + LONG2CHARS( 0xFFFFFFFFFFFFC000 ), + LONG2CHARS( 0xFFFFFFFFFFFFE000 ), + LONG2CHARS( 0xFFFFFFFFFFFFF000 ), + LONG2CHARS( 0xFFFFFFFFFFFFF800 ), + LONG2CHARS( 0xFFFFFFFFFFFFFC00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFE00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF80 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFC0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFC ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFE ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x4000000000000000 ), + LONG2CHARS( 0x6000000000000000 ), + LONG2CHARS( 0x7000000000000000 ), + LONG2CHARS( 0x7800000000000000 ), + LONG2CHARS( 0x7C00000000000000 ), + LONG2CHARS( 0x7E00000000000000 ), + LONG2CHARS( 0x7F00000000000000 ), + LONG2CHARS( 0x7F80000000000000 ), + LONG2CHARS( 0x7FC0000000000000 ), + LONG2CHARS( 0x7FE0000000000000 ), + LONG2CHARS( 0x7FF0000000000000 ), + LONG2CHARS( 0x7FF8000000000000 ), + LONG2CHARS( 0x7FFC000000000000 ), + LONG2CHARS( 0x7FFE000000000000 ), + LONG2CHARS( 0x7FFF000000000000 ), + LONG2CHARS( 0x7FFF800000000000 ), + LONG2CHARS( 0x7FFFC00000000000 ), + LONG2CHARS( 0x7FFFE00000000000 ), + LONG2CHARS( 0x7FFFF00000000000 ), + LONG2CHARS( 0x7FFFF80000000000 ), + LONG2CHARS( 0x7FFFFC0000000000 ), + LONG2CHARS( 0x7FFFFE0000000000 ), + LONG2CHARS( 0x7FFFFF0000000000 ), + LONG2CHARS( 0x7FFFFF8000000000 ), + LONG2CHARS( 0x7FFFFFC000000000 ), + LONG2CHARS( 0x7FFFFFE000000000 ), + LONG2CHARS( 0x7FFFFFF000000000 ), + LONG2CHARS( 0x7FFFFFF800000000 ), + LONG2CHARS( 0x7FFFFFFC00000000 ), + LONG2CHARS( 0x7FFFFFFE00000000 ), + LONG2CHARS( 0x7FFFFFFF00000000 ), + LONG2CHARS( 0x7FFFFFFF80000000 ), + LONG2CHARS( 0x7FFFFFFFC0000000 ), + LONG2CHARS( 0x7FFFFFFFE0000000 ), + LONG2CHARS( 0x7FFFFFFFF0000000 ), + LONG2CHARS( 0x7FFFFFFFF8000000 ), + LONG2CHARS( 0x7FFFFFFFFC000000 ), + LONG2CHARS( 0x7FFFFFFFFE000000 ), + LONG2CHARS( 0x7FFFFFFFFF000000 ), + LONG2CHARS( 0x7FFFFFFFFF800000 ), + LONG2CHARS( 0x7FFFFFFFFFC00000 ), + LONG2CHARS( 0x7FFFFFFFFFE00000 ), + LONG2CHARS( 0x7FFFFFFFFFF00000 ), + LONG2CHARS( 0x7FFFFFFFFFF80000 ), + LONG2CHARS( 0x7FFFFFFFFFFC0000 ), + LONG2CHARS( 0x7FFFFFFFFFFE0000 ), + LONG2CHARS( 0x7FFFFFFFFFFF0000 ), + LONG2CHARS( 0x7FFFFFFFFFFF8000 ), + LONG2CHARS( 0x7FFFFFFFFFFFC000 ), + LONG2CHARS( 0x7FFFFFFFFFFFE000 ), + LONG2CHARS( 0x7FFFFFFFFFFFF000 ), + LONG2CHARS( 0x7FFFFFFFFFFFF800 ), + LONG2CHARS( 0x7FFFFFFFFFFFFC00 ), + LONG2CHARS( 0x7FFFFFFFFFFFFE00 ), + LONG2CHARS( 0x7FFFFFFFFFFFFF00 ), + LONG2CHARS( 0x7FFFFFFFFFFFFF80 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFFC ), + LONG2CHARS( 0x7FFFFFFFFFFFFFFE ), + LONG2CHARS( 0x7FFFFFFFFFFFFFFF ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x2000000000000000 ), + LONG2CHARS( 0x3000000000000000 ), + LONG2CHARS( 0x3800000000000000 ), + LONG2CHARS( 0x3C00000000000000 ), + LONG2CHARS( 0x3E00000000000000 ), + LONG2CHARS( 0x3F00000000000000 ), + LONG2CHARS( 0x3F80000000000000 ), + LONG2CHARS( 0x3FC0000000000000 ), + LONG2CHARS( 0x3FE0000000000000 ), + LONG2CHARS( 0x3FF0000000000000 ), + LONG2CHARS( 0x3FF8000000000000 ), + LONG2CHARS( 0x3FFC000000000000 ), + LONG2CHARS( 0x3FFE000000000000 ), + LONG2CHARS( 0x3FFF000000000000 ), + LONG2CHARS( 0x3FFF800000000000 ), + LONG2CHARS( 0x3FFFC00000000000 ), + LONG2CHARS( 0x3FFFE00000000000 ), + LONG2CHARS( 0x3FFFF00000000000 ), + LONG2CHARS( 0x3FFFF80000000000 ), + LONG2CHARS( 0x3FFFFC0000000000 ), + LONG2CHARS( 0x3FFFFE0000000000 ), + LONG2CHARS( 0x3FFFFF0000000000 ), + LONG2CHARS( 0x3FFFFF8000000000 ), + LONG2CHARS( 0x3FFFFFC000000000 ), + LONG2CHARS( 0x3FFFFFE000000000 ), + LONG2CHARS( 0x3FFFFFF000000000 ), + LONG2CHARS( 0x3FFFFFF800000000 ), + LONG2CHARS( 0x3FFFFFFC00000000 ), + LONG2CHARS( 0x3FFFFFFE00000000 ), + LONG2CHARS( 0x3FFFFFFF00000000 ), + LONG2CHARS( 0x3FFFFFFF80000000 ), + LONG2CHARS( 0x3FFFFFFFC0000000 ), + LONG2CHARS( 0x3FFFFFFFE0000000 ), + LONG2CHARS( 0x3FFFFFFFF0000000 ), + LONG2CHARS( 0x3FFFFFFFF8000000 ), + LONG2CHARS( 0x3FFFFFFFFC000000 ), + LONG2CHARS( 0x3FFFFFFFFE000000 ), + LONG2CHARS( 0x3FFFFFFFFF000000 ), + LONG2CHARS( 0x3FFFFFFFFF800000 ), + LONG2CHARS( 0x3FFFFFFFFFC00000 ), + LONG2CHARS( 0x3FFFFFFFFFE00000 ), + LONG2CHARS( 0x3FFFFFFFFFF00000 ), + LONG2CHARS( 0x3FFFFFFFFFF80000 ), + LONG2CHARS( 0x3FFFFFFFFFFC0000 ), + LONG2CHARS( 0x3FFFFFFFFFFE0000 ), + LONG2CHARS( 0x3FFFFFFFFFFF0000 ), + LONG2CHARS( 0x3FFFFFFFFFFF8000 ), + LONG2CHARS( 0x3FFFFFFFFFFFC000 ), + LONG2CHARS( 0x3FFFFFFFFFFFE000 ), + LONG2CHARS( 0x3FFFFFFFFFFFF000 ), + LONG2CHARS( 0x3FFFFFFFFFFFF800 ), + LONG2CHARS( 0x3FFFFFFFFFFFFC00 ), + LONG2CHARS( 0x3FFFFFFFFFFFFE00 ), + LONG2CHARS( 0x3FFFFFFFFFFFFF00 ), + LONG2CHARS( 0x3FFFFFFFFFFFFF80 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFC ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFE ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x1000000000000000 ), + LONG2CHARS( 0x1800000000000000 ), + LONG2CHARS( 0x1C00000000000000 ), + LONG2CHARS( 0x1E00000000000000 ), + LONG2CHARS( 0x1F00000000000000 ), + LONG2CHARS( 0x1F80000000000000 ), + LONG2CHARS( 0x1FC0000000000000 ), + LONG2CHARS( 0x1FE0000000000000 ), + LONG2CHARS( 0x1FF0000000000000 ), + LONG2CHARS( 0x1FF8000000000000 ), + LONG2CHARS( 0x1FFC000000000000 ), + LONG2CHARS( 0x1FFE000000000000 ), + LONG2CHARS( 0x1FFF000000000000 ), + LONG2CHARS( 0x1FFF800000000000 ), + LONG2CHARS( 0x1FFFC00000000000 ), + LONG2CHARS( 0x1FFFE00000000000 ), + LONG2CHARS( 0x1FFFF00000000000 ), + LONG2CHARS( 0x1FFFF80000000000 ), + LONG2CHARS( 0x1FFFFC0000000000 ), + LONG2CHARS( 0x1FFFFE0000000000 ), + LONG2CHARS( 0x1FFFFF0000000000 ), + LONG2CHARS( 0x1FFFFF8000000000 ), + LONG2CHARS( 0x1FFFFFC000000000 ), + LONG2CHARS( 0x1FFFFFE000000000 ), + LONG2CHARS( 0x1FFFFFF000000000 ), + LONG2CHARS( 0x1FFFFFF800000000 ), + LONG2CHARS( 0x1FFFFFFC00000000 ), + LONG2CHARS( 0x1FFFFFFE00000000 ), + LONG2CHARS( 0x1FFFFFFF00000000 ), + LONG2CHARS( 0x1FFFFFFF80000000 ), + LONG2CHARS( 0x1FFFFFFFC0000000 ), + LONG2CHARS( 0x1FFFFFFFE0000000 ), + LONG2CHARS( 0x1FFFFFFFF0000000 ), + LONG2CHARS( 0x1FFFFFFFF8000000 ), + LONG2CHARS( 0x1FFFFFFFFC000000 ), + LONG2CHARS( 0x1FFFFFFFFE000000 ), + LONG2CHARS( 0x1FFFFFFFFF000000 ), + LONG2CHARS( 0x1FFFFFFFFF800000 ), + LONG2CHARS( 0x1FFFFFFFFFC00000 ), + LONG2CHARS( 0x1FFFFFFFFFE00000 ), + LONG2CHARS( 0x1FFFFFFFFFF00000 ), + LONG2CHARS( 0x1FFFFFFFFFF80000 ), + LONG2CHARS( 0x1FFFFFFFFFFC0000 ), + LONG2CHARS( 0x1FFFFFFFFFFE0000 ), + LONG2CHARS( 0x1FFFFFFFFFFF0000 ), + LONG2CHARS( 0x1FFFFFFFFFFF8000 ), + LONG2CHARS( 0x1FFFFFFFFFFFC000 ), + LONG2CHARS( 0x1FFFFFFFFFFFE000 ), + LONG2CHARS( 0x1FFFFFFFFFFFF000 ), + LONG2CHARS( 0x1FFFFFFFFFFFF800 ), + LONG2CHARS( 0x1FFFFFFFFFFFFC00 ), + LONG2CHARS( 0x1FFFFFFFFFFFFE00 ), + LONG2CHARS( 0x1FFFFFFFFFFFFF00 ), + LONG2CHARS( 0x1FFFFFFFFFFFFF80 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFC ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFE ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0800000000000000 ), + LONG2CHARS( 0x0C00000000000000 ), + LONG2CHARS( 0x0E00000000000000 ), + LONG2CHARS( 0x0F00000000000000 ), + LONG2CHARS( 0x0F80000000000000 ), + LONG2CHARS( 0x0FC0000000000000 ), + LONG2CHARS( 0x0FE0000000000000 ), + LONG2CHARS( 0x0FF0000000000000 ), + LONG2CHARS( 0x0FF8000000000000 ), + LONG2CHARS( 0x0FFC000000000000 ), + LONG2CHARS( 0x0FFE000000000000 ), + LONG2CHARS( 0x0FFF000000000000 ), + LONG2CHARS( 0x0FFF800000000000 ), + LONG2CHARS( 0x0FFFC00000000000 ), + LONG2CHARS( 0x0FFFE00000000000 ), + LONG2CHARS( 0x0FFFF00000000000 ), + LONG2CHARS( 0x0FFFF80000000000 ), + LONG2CHARS( 0x0FFFFC0000000000 ), + LONG2CHARS( 0x0FFFFE0000000000 ), + LONG2CHARS( 0x0FFFFF0000000000 ), + LONG2CHARS( 0x0FFFFF8000000000 ), + LONG2CHARS( 0x0FFFFFC000000000 ), + LONG2CHARS( 0x0FFFFFE000000000 ), + LONG2CHARS( 0x0FFFFFF000000000 ), + LONG2CHARS( 0x0FFFFFF800000000 ), + LONG2CHARS( 0x0FFFFFFC00000000 ), + LONG2CHARS( 0x0FFFFFFE00000000 ), + LONG2CHARS( 0x0FFFFFFF00000000 ), + LONG2CHARS( 0x0FFFFFFF80000000 ), + LONG2CHARS( 0x0FFFFFFFC0000000 ), + LONG2CHARS( 0x0FFFFFFFE0000000 ), + LONG2CHARS( 0x0FFFFFFFF0000000 ), + LONG2CHARS( 0x0FFFFFFFF8000000 ), + LONG2CHARS( 0x0FFFFFFFFC000000 ), + LONG2CHARS( 0x0FFFFFFFFE000000 ), + LONG2CHARS( 0x0FFFFFFFFF000000 ), + LONG2CHARS( 0x0FFFFFFFFF800000 ), + LONG2CHARS( 0x0FFFFFFFFFC00000 ), + LONG2CHARS( 0x0FFFFFFFFFE00000 ), + LONG2CHARS( 0x0FFFFFFFFFF00000 ), + LONG2CHARS( 0x0FFFFFFFFFF80000 ), + LONG2CHARS( 0x0FFFFFFFFFFC0000 ), + LONG2CHARS( 0x0FFFFFFFFFFE0000 ), + LONG2CHARS( 0x0FFFFFFFFFFF0000 ), + LONG2CHARS( 0x0FFFFFFFFFFF8000 ), + LONG2CHARS( 0x0FFFFFFFFFFFC000 ), + LONG2CHARS( 0x0FFFFFFFFFFFE000 ), + LONG2CHARS( 0x0FFFFFFFFFFFF000 ), + LONG2CHARS( 0x0FFFFFFFFFFFF800 ), + LONG2CHARS( 0x0FFFFFFFFFFFFC00 ), + LONG2CHARS( 0x0FFFFFFFFFFFFE00 ), + LONG2CHARS( 0x0FFFFFFFFFFFFF00 ), + LONG2CHARS( 0x0FFFFFFFFFFFFF80 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFC ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFE ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0400000000000000 ), + LONG2CHARS( 0x0600000000000000 ), + LONG2CHARS( 0x0700000000000000 ), + LONG2CHARS( 0x0780000000000000 ), + LONG2CHARS( 0x07C0000000000000 ), + LONG2CHARS( 0x07E0000000000000 ), + LONG2CHARS( 0x07F0000000000000 ), + LONG2CHARS( 0x07F8000000000000 ), + LONG2CHARS( 0x07FC000000000000 ), + LONG2CHARS( 0x07FE000000000000 ), + LONG2CHARS( 0x07FF000000000000 ), + LONG2CHARS( 0x07FF800000000000 ), + LONG2CHARS( 0x07FFC00000000000 ), + LONG2CHARS( 0x07FFE00000000000 ), + LONG2CHARS( 0x07FFF00000000000 ), + LONG2CHARS( 0x07FFF80000000000 ), + LONG2CHARS( 0x07FFFC0000000000 ), + LONG2CHARS( 0x07FFFE0000000000 ), + LONG2CHARS( 0x07FFFF0000000000 ), + LONG2CHARS( 0x07FFFF8000000000 ), + LONG2CHARS( 0x07FFFFC000000000 ), + LONG2CHARS( 0x07FFFFE000000000 ), + LONG2CHARS( 0x07FFFFF000000000 ), + LONG2CHARS( 0x07FFFFF800000000 ), + LONG2CHARS( 0x07FFFFFC00000000 ), + LONG2CHARS( 0x07FFFFFE00000000 ), + LONG2CHARS( 0x07FFFFFF00000000 ), + LONG2CHARS( 0x07FFFFFF80000000 ), + LONG2CHARS( 0x07FFFFFFC0000000 ), + LONG2CHARS( 0x07FFFFFFE0000000 ), + LONG2CHARS( 0x07FFFFFFF0000000 ), + LONG2CHARS( 0x07FFFFFFF8000000 ), + LONG2CHARS( 0x07FFFFFFFC000000 ), + LONG2CHARS( 0x07FFFFFFFE000000 ), + LONG2CHARS( 0x07FFFFFFFF000000 ), + LONG2CHARS( 0x07FFFFFFFF800000 ), + LONG2CHARS( 0x07FFFFFFFFC00000 ), + LONG2CHARS( 0x07FFFFFFFFE00000 ), + LONG2CHARS( 0x07FFFFFFFFF00000 ), + LONG2CHARS( 0x07FFFFFFFFF80000 ), + LONG2CHARS( 0x07FFFFFFFFFC0000 ), + LONG2CHARS( 0x07FFFFFFFFFE0000 ), + LONG2CHARS( 0x07FFFFFFFFFF0000 ), + LONG2CHARS( 0x07FFFFFFFFFF8000 ), + LONG2CHARS( 0x07FFFFFFFFFFC000 ), + LONG2CHARS( 0x07FFFFFFFFFFE000 ), + LONG2CHARS( 0x07FFFFFFFFFFF000 ), + LONG2CHARS( 0x07FFFFFFFFFFF800 ), + LONG2CHARS( 0x07FFFFFFFFFFFC00 ), + LONG2CHARS( 0x07FFFFFFFFFFFE00 ), + LONG2CHARS( 0x07FFFFFFFFFFFF00 ), + LONG2CHARS( 0x07FFFFFFFFFFFF80 ), + LONG2CHARS( 0x07FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x07FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x07FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x07FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x07FFFFFFFFFFFFFC ), + LONG2CHARS( 0x07FFFFFFFFFFFFFE ), + LONG2CHARS( 0x07FFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0200000000000000 ), + LONG2CHARS( 0x0300000000000000 ), + LONG2CHARS( 0x0380000000000000 ), + LONG2CHARS( 0x03C0000000000000 ), + LONG2CHARS( 0x03E0000000000000 ), + LONG2CHARS( 0x03F0000000000000 ), + LONG2CHARS( 0x03F8000000000000 ), + LONG2CHARS( 0x03FC000000000000 ), + LONG2CHARS( 0x03FE000000000000 ), + LONG2CHARS( 0x03FF000000000000 ), + LONG2CHARS( 0x03FF800000000000 ), + LONG2CHARS( 0x03FFC00000000000 ), + LONG2CHARS( 0x03FFE00000000000 ), + LONG2CHARS( 0x03FFF00000000000 ), + LONG2CHARS( 0x03FFF80000000000 ), + LONG2CHARS( 0x03FFFC0000000000 ), + LONG2CHARS( 0x03FFFE0000000000 ), + LONG2CHARS( 0x03FFFF0000000000 ), + LONG2CHARS( 0x03FFFF8000000000 ), + LONG2CHARS( 0x03FFFFC000000000 ), + LONG2CHARS( 0x03FFFFE000000000 ), + LONG2CHARS( 0x03FFFFF000000000 ), + LONG2CHARS( 0x03FFFFF800000000 ), + LONG2CHARS( 0x03FFFFFC00000000 ), + LONG2CHARS( 0x03FFFFFE00000000 ), + LONG2CHARS( 0x03FFFFFF00000000 ), + LONG2CHARS( 0x03FFFFFF80000000 ), + LONG2CHARS( 0x03FFFFFFC0000000 ), + LONG2CHARS( 0x03FFFFFFE0000000 ), + LONG2CHARS( 0x03FFFFFFF0000000 ), + LONG2CHARS( 0x03FFFFFFF8000000 ), + LONG2CHARS( 0x03FFFFFFFC000000 ), + LONG2CHARS( 0x03FFFFFFFE000000 ), + LONG2CHARS( 0x03FFFFFFFF000000 ), + LONG2CHARS( 0x03FFFFFFFF800000 ), + LONG2CHARS( 0x03FFFFFFFFC00000 ), + LONG2CHARS( 0x03FFFFFFFFE00000 ), + LONG2CHARS( 0x03FFFFFFFFF00000 ), + LONG2CHARS( 0x03FFFFFFFFF80000 ), + LONG2CHARS( 0x03FFFFFFFFFC0000 ), + LONG2CHARS( 0x03FFFFFFFFFE0000 ), + LONG2CHARS( 0x03FFFFFFFFFF0000 ), + LONG2CHARS( 0x03FFFFFFFFFF8000 ), + LONG2CHARS( 0x03FFFFFFFFFFC000 ), + LONG2CHARS( 0x03FFFFFFFFFFE000 ), + LONG2CHARS( 0x03FFFFFFFFFFF000 ), + LONG2CHARS( 0x03FFFFFFFFFFF800 ), + LONG2CHARS( 0x03FFFFFFFFFFFC00 ), + LONG2CHARS( 0x03FFFFFFFFFFFE00 ), + LONG2CHARS( 0x03FFFFFFFFFFFF00 ), + LONG2CHARS( 0x03FFFFFFFFFFFF80 ), + LONG2CHARS( 0x03FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x03FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x03FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x03FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x03FFFFFFFFFFFFFC ), + LONG2CHARS( 0x03FFFFFFFFFFFFFE ), + LONG2CHARS( 0x03FFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0100000000000000 ), + LONG2CHARS( 0x0180000000000000 ), + LONG2CHARS( 0x01C0000000000000 ), + LONG2CHARS( 0x01E0000000000000 ), + LONG2CHARS( 0x01F0000000000000 ), + LONG2CHARS( 0x01F8000000000000 ), + LONG2CHARS( 0x01FC000000000000 ), + LONG2CHARS( 0x01FE000000000000 ), + LONG2CHARS( 0x01FF000000000000 ), + LONG2CHARS( 0x01FF800000000000 ), + LONG2CHARS( 0x01FFC00000000000 ), + LONG2CHARS( 0x01FFE00000000000 ), + LONG2CHARS( 0x01FFF00000000000 ), + LONG2CHARS( 0x01FFF80000000000 ), + LONG2CHARS( 0x01FFFC0000000000 ), + LONG2CHARS( 0x01FFFE0000000000 ), + LONG2CHARS( 0x01FFFF0000000000 ), + LONG2CHARS( 0x01FFFF8000000000 ), + LONG2CHARS( 0x01FFFFC000000000 ), + LONG2CHARS( 0x01FFFFE000000000 ), + LONG2CHARS( 0x01FFFFF000000000 ), + LONG2CHARS( 0x01FFFFF800000000 ), + LONG2CHARS( 0x01FFFFFC00000000 ), + LONG2CHARS( 0x01FFFFFE00000000 ), + LONG2CHARS( 0x01FFFFFF00000000 ), + LONG2CHARS( 0x01FFFFFF80000000 ), + LONG2CHARS( 0x01FFFFFFC0000000 ), + LONG2CHARS( 0x01FFFFFFE0000000 ), + LONG2CHARS( 0x01FFFFFFF0000000 ), + LONG2CHARS( 0x01FFFFFFF8000000 ), + LONG2CHARS( 0x01FFFFFFFC000000 ), + LONG2CHARS( 0x01FFFFFFFE000000 ), + LONG2CHARS( 0x01FFFFFFFF000000 ), + LONG2CHARS( 0x01FFFFFFFF800000 ), + LONG2CHARS( 0x01FFFFFFFFC00000 ), + LONG2CHARS( 0x01FFFFFFFFE00000 ), + LONG2CHARS( 0x01FFFFFFFFF00000 ), + LONG2CHARS( 0x01FFFFFFFFF80000 ), + LONG2CHARS( 0x01FFFFFFFFFC0000 ), + LONG2CHARS( 0x01FFFFFFFFFE0000 ), + LONG2CHARS( 0x01FFFFFFFFFF0000 ), + LONG2CHARS( 0x01FFFFFFFFFF8000 ), + LONG2CHARS( 0x01FFFFFFFFFFC000 ), + LONG2CHARS( 0x01FFFFFFFFFFE000 ), + LONG2CHARS( 0x01FFFFFFFFFFF000 ), + LONG2CHARS( 0x01FFFFFFFFFFF800 ), + LONG2CHARS( 0x01FFFFFFFFFFFC00 ), + LONG2CHARS( 0x01FFFFFFFFFFFE00 ), + LONG2CHARS( 0x01FFFFFFFFFFFF00 ), + LONG2CHARS( 0x01FFFFFFFFFFFF80 ), + LONG2CHARS( 0x01FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x01FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x01FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x01FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x01FFFFFFFFFFFFFC ), + LONG2CHARS( 0x01FFFFFFFFFFFFFE ), + LONG2CHARS( 0x01FFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0080000000000000 ), + LONG2CHARS( 0x00C0000000000000 ), + LONG2CHARS( 0x00E0000000000000 ), + LONG2CHARS( 0x00F0000000000000 ), + LONG2CHARS( 0x00F8000000000000 ), + LONG2CHARS( 0x00FC000000000000 ), + LONG2CHARS( 0x00FE000000000000 ), + LONG2CHARS( 0x00FF000000000000 ), + LONG2CHARS( 0x00FF800000000000 ), + LONG2CHARS( 0x00FFC00000000000 ), + LONG2CHARS( 0x00FFE00000000000 ), + LONG2CHARS( 0x00FFF00000000000 ), + LONG2CHARS( 0x00FFF80000000000 ), + LONG2CHARS( 0x00FFFC0000000000 ), + LONG2CHARS( 0x00FFFE0000000000 ), + LONG2CHARS( 0x00FFFF0000000000 ), + LONG2CHARS( 0x00FFFF8000000000 ), + LONG2CHARS( 0x00FFFFC000000000 ), + LONG2CHARS( 0x00FFFFE000000000 ), + LONG2CHARS( 0x00FFFFF000000000 ), + LONG2CHARS( 0x00FFFFF800000000 ), + LONG2CHARS( 0x00FFFFFC00000000 ), + LONG2CHARS( 0x00FFFFFE00000000 ), + LONG2CHARS( 0x00FFFFFF00000000 ), + LONG2CHARS( 0x00FFFFFF80000000 ), + LONG2CHARS( 0x00FFFFFFC0000000 ), + LONG2CHARS( 0x00FFFFFFE0000000 ), + LONG2CHARS( 0x00FFFFFFF0000000 ), + LONG2CHARS( 0x00FFFFFFF8000000 ), + LONG2CHARS( 0x00FFFFFFFC000000 ), + LONG2CHARS( 0x00FFFFFFFE000000 ), + LONG2CHARS( 0x00FFFFFFFF000000 ), + LONG2CHARS( 0x00FFFFFFFF800000 ), + LONG2CHARS( 0x00FFFFFFFFC00000 ), + LONG2CHARS( 0x00FFFFFFFFE00000 ), + LONG2CHARS( 0x00FFFFFFFFF00000 ), + LONG2CHARS( 0x00FFFFFFFFF80000 ), + LONG2CHARS( 0x00FFFFFFFFFC0000 ), + LONG2CHARS( 0x00FFFFFFFFFE0000 ), + LONG2CHARS( 0x00FFFFFFFFFF0000 ), + LONG2CHARS( 0x00FFFFFFFFFF8000 ), + LONG2CHARS( 0x00FFFFFFFFFFC000 ), + LONG2CHARS( 0x00FFFFFFFFFFE000 ), + LONG2CHARS( 0x00FFFFFFFFFFF000 ), + LONG2CHARS( 0x00FFFFFFFFFFF800 ), + LONG2CHARS( 0x00FFFFFFFFFFFC00 ), + LONG2CHARS( 0x00FFFFFFFFFFFE00 ), + LONG2CHARS( 0x00FFFFFFFFFFFF00 ), + LONG2CHARS( 0x00FFFFFFFFFFFF80 ), + LONG2CHARS( 0x00FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x00FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x00FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x00FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x00FFFFFFFFFFFFFC ), + LONG2CHARS( 0x00FFFFFFFFFFFFFE ), + LONG2CHARS( 0x00FFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0040000000000000 ), + LONG2CHARS( 0x0060000000000000 ), + LONG2CHARS( 0x0070000000000000 ), + LONG2CHARS( 0x0078000000000000 ), + LONG2CHARS( 0x007C000000000000 ), + LONG2CHARS( 0x007E000000000000 ), + LONG2CHARS( 0x007F000000000000 ), + LONG2CHARS( 0x007F800000000000 ), + LONG2CHARS( 0x007FC00000000000 ), + LONG2CHARS( 0x007FE00000000000 ), + LONG2CHARS( 0x007FF00000000000 ), + LONG2CHARS( 0x007FF80000000000 ), + LONG2CHARS( 0x007FFC0000000000 ), + LONG2CHARS( 0x007FFE0000000000 ), + LONG2CHARS( 0x007FFF0000000000 ), + LONG2CHARS( 0x007FFF8000000000 ), + LONG2CHARS( 0x007FFFC000000000 ), + LONG2CHARS( 0x007FFFE000000000 ), + LONG2CHARS( 0x007FFFF000000000 ), + LONG2CHARS( 0x007FFFF800000000 ), + LONG2CHARS( 0x007FFFFC00000000 ), + LONG2CHARS( 0x007FFFFE00000000 ), + LONG2CHARS( 0x007FFFFF00000000 ), + LONG2CHARS( 0x007FFFFF80000000 ), + LONG2CHARS( 0x007FFFFFC0000000 ), + LONG2CHARS( 0x007FFFFFE0000000 ), + LONG2CHARS( 0x007FFFFFF0000000 ), + LONG2CHARS( 0x007FFFFFF8000000 ), + LONG2CHARS( 0x007FFFFFFC000000 ), + LONG2CHARS( 0x007FFFFFFE000000 ), + LONG2CHARS( 0x007FFFFFFF000000 ), + LONG2CHARS( 0x007FFFFFFF800000 ), + LONG2CHARS( 0x007FFFFFFFC00000 ), + LONG2CHARS( 0x007FFFFFFFE00000 ), + LONG2CHARS( 0x007FFFFFFFF00000 ), + LONG2CHARS( 0x007FFFFFFFF80000 ), + LONG2CHARS( 0x007FFFFFFFFC0000 ), + LONG2CHARS( 0x007FFFFFFFFE0000 ), + LONG2CHARS( 0x007FFFFFFFFF0000 ), + LONG2CHARS( 0x007FFFFFFFFF8000 ), + LONG2CHARS( 0x007FFFFFFFFFC000 ), + LONG2CHARS( 0x007FFFFFFFFFE000 ), + LONG2CHARS( 0x007FFFFFFFFFF000 ), + LONG2CHARS( 0x007FFFFFFFFFF800 ), + LONG2CHARS( 0x007FFFFFFFFFFC00 ), + LONG2CHARS( 0x007FFFFFFFFFFE00 ), + LONG2CHARS( 0x007FFFFFFFFFFF00 ), + LONG2CHARS( 0x007FFFFFFFFFFF80 ), + LONG2CHARS( 0x007FFFFFFFFFFFC0 ), + LONG2CHARS( 0x007FFFFFFFFFFFE0 ), + LONG2CHARS( 0x007FFFFFFFFFFFF0 ), + LONG2CHARS( 0x007FFFFFFFFFFFF8 ), + LONG2CHARS( 0x007FFFFFFFFFFFFC ), + LONG2CHARS( 0x007FFFFFFFFFFFFE ), + LONG2CHARS( 0x007FFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0020000000000000 ), + LONG2CHARS( 0x0030000000000000 ), + LONG2CHARS( 0x0038000000000000 ), + LONG2CHARS( 0x003C000000000000 ), + LONG2CHARS( 0x003E000000000000 ), + LONG2CHARS( 0x003F000000000000 ), + LONG2CHARS( 0x003F800000000000 ), + LONG2CHARS( 0x003FC00000000000 ), + LONG2CHARS( 0x003FE00000000000 ), + LONG2CHARS( 0x003FF00000000000 ), + LONG2CHARS( 0x003FF80000000000 ), + LONG2CHARS( 0x003FFC0000000000 ), + LONG2CHARS( 0x003FFE0000000000 ), + LONG2CHARS( 0x003FFF0000000000 ), + LONG2CHARS( 0x003FFF8000000000 ), + LONG2CHARS( 0x003FFFC000000000 ), + LONG2CHARS( 0x003FFFE000000000 ), + LONG2CHARS( 0x003FFFF000000000 ), + LONG2CHARS( 0x003FFFF800000000 ), + LONG2CHARS( 0x003FFFFC00000000 ), + LONG2CHARS( 0x003FFFFE00000000 ), + LONG2CHARS( 0x003FFFFF00000000 ), + LONG2CHARS( 0x003FFFFF80000000 ), + LONG2CHARS( 0x003FFFFFC0000000 ), + LONG2CHARS( 0x003FFFFFE0000000 ), + LONG2CHARS( 0x003FFFFFF0000000 ), + LONG2CHARS( 0x003FFFFFF8000000 ), + LONG2CHARS( 0x003FFFFFFC000000 ), + LONG2CHARS( 0x003FFFFFFE000000 ), + LONG2CHARS( 0x003FFFFFFF000000 ), + LONG2CHARS( 0x003FFFFFFF800000 ), + LONG2CHARS( 0x003FFFFFFFC00000 ), + LONG2CHARS( 0x003FFFFFFFE00000 ), + LONG2CHARS( 0x003FFFFFFFF00000 ), + LONG2CHARS( 0x003FFFFFFFF80000 ), + LONG2CHARS( 0x003FFFFFFFFC0000 ), + LONG2CHARS( 0x003FFFFFFFFE0000 ), + LONG2CHARS( 0x003FFFFFFFFF0000 ), + LONG2CHARS( 0x003FFFFFFFFF8000 ), + LONG2CHARS( 0x003FFFFFFFFFC000 ), + LONG2CHARS( 0x003FFFFFFFFFE000 ), + LONG2CHARS( 0x003FFFFFFFFFF000 ), + LONG2CHARS( 0x003FFFFFFFFFF800 ), + LONG2CHARS( 0x003FFFFFFFFFFC00 ), + LONG2CHARS( 0x003FFFFFFFFFFE00 ), + LONG2CHARS( 0x003FFFFFFFFFFF00 ), + LONG2CHARS( 0x003FFFFFFFFFFF80 ), + LONG2CHARS( 0x003FFFFFFFFFFFC0 ), + LONG2CHARS( 0x003FFFFFFFFFFFE0 ), + LONG2CHARS( 0x003FFFFFFFFFFFF0 ), + LONG2CHARS( 0x003FFFFFFFFFFFF8 ), + LONG2CHARS( 0x003FFFFFFFFFFFFC ), + LONG2CHARS( 0x003FFFFFFFFFFFFE ), + LONG2CHARS( 0x003FFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0010000000000000 ), + LONG2CHARS( 0x0018000000000000 ), + LONG2CHARS( 0x001C000000000000 ), + LONG2CHARS( 0x001E000000000000 ), + LONG2CHARS( 0x001F000000000000 ), + LONG2CHARS( 0x001F800000000000 ), + LONG2CHARS( 0x001FC00000000000 ), + LONG2CHARS( 0x001FE00000000000 ), + LONG2CHARS( 0x001FF00000000000 ), + LONG2CHARS( 0x001FF80000000000 ), + LONG2CHARS( 0x001FFC0000000000 ), + LONG2CHARS( 0x001FFE0000000000 ), + LONG2CHARS( 0x001FFF0000000000 ), + LONG2CHARS( 0x001FFF8000000000 ), + LONG2CHARS( 0x001FFFC000000000 ), + LONG2CHARS( 0x001FFFE000000000 ), + LONG2CHARS( 0x001FFFF000000000 ), + LONG2CHARS( 0x001FFFF800000000 ), + LONG2CHARS( 0x001FFFFC00000000 ), + LONG2CHARS( 0x001FFFFE00000000 ), + LONG2CHARS( 0x001FFFFF00000000 ), + LONG2CHARS( 0x001FFFFF80000000 ), + LONG2CHARS( 0x001FFFFFC0000000 ), + LONG2CHARS( 0x001FFFFFE0000000 ), + LONG2CHARS( 0x001FFFFFF0000000 ), + LONG2CHARS( 0x001FFFFFF8000000 ), + LONG2CHARS( 0x001FFFFFFC000000 ), + LONG2CHARS( 0x001FFFFFFE000000 ), + LONG2CHARS( 0x001FFFFFFF000000 ), + LONG2CHARS( 0x001FFFFFFF800000 ), + LONG2CHARS( 0x001FFFFFFFC00000 ), + LONG2CHARS( 0x001FFFFFFFE00000 ), + LONG2CHARS( 0x001FFFFFFFF00000 ), + LONG2CHARS( 0x001FFFFFFFF80000 ), + LONG2CHARS( 0x001FFFFFFFFC0000 ), + LONG2CHARS( 0x001FFFFFFFFE0000 ), + LONG2CHARS( 0x001FFFFFFFFF0000 ), + LONG2CHARS( 0x001FFFFFFFFF8000 ), + LONG2CHARS( 0x001FFFFFFFFFC000 ), + LONG2CHARS( 0x001FFFFFFFFFE000 ), + LONG2CHARS( 0x001FFFFFFFFFF000 ), + LONG2CHARS( 0x001FFFFFFFFFF800 ), + LONG2CHARS( 0x001FFFFFFFFFFC00 ), + LONG2CHARS( 0x001FFFFFFFFFFE00 ), + LONG2CHARS( 0x001FFFFFFFFFFF00 ), + LONG2CHARS( 0x001FFFFFFFFFFF80 ), + LONG2CHARS( 0x001FFFFFFFFFFFC0 ), + LONG2CHARS( 0x001FFFFFFFFFFFE0 ), + LONG2CHARS( 0x001FFFFFFFFFFFF0 ), + LONG2CHARS( 0x001FFFFFFFFFFFF8 ), + LONG2CHARS( 0x001FFFFFFFFFFFFC ), + LONG2CHARS( 0x001FFFFFFFFFFFFE ), + LONG2CHARS( 0x001FFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0008000000000000 ), + LONG2CHARS( 0x000C000000000000 ), + LONG2CHARS( 0x000E000000000000 ), + LONG2CHARS( 0x000F000000000000 ), + LONG2CHARS( 0x000F800000000000 ), + LONG2CHARS( 0x000FC00000000000 ), + LONG2CHARS( 0x000FE00000000000 ), + LONG2CHARS( 0x000FF00000000000 ), + LONG2CHARS( 0x000FF80000000000 ), + LONG2CHARS( 0x000FFC0000000000 ), + LONG2CHARS( 0x000FFE0000000000 ), + LONG2CHARS( 0x000FFF0000000000 ), + LONG2CHARS( 0x000FFF8000000000 ), + LONG2CHARS( 0x000FFFC000000000 ), + LONG2CHARS( 0x000FFFE000000000 ), + LONG2CHARS( 0x000FFFF000000000 ), + LONG2CHARS( 0x000FFFF800000000 ), + LONG2CHARS( 0x000FFFFC00000000 ), + LONG2CHARS( 0x000FFFFE00000000 ), + LONG2CHARS( 0x000FFFFF00000000 ), + LONG2CHARS( 0x000FFFFF80000000 ), + LONG2CHARS( 0x000FFFFFC0000000 ), + LONG2CHARS( 0x000FFFFFE0000000 ), + LONG2CHARS( 0x000FFFFFF0000000 ), + LONG2CHARS( 0x000FFFFFF8000000 ), + LONG2CHARS( 0x000FFFFFFC000000 ), + LONG2CHARS( 0x000FFFFFFE000000 ), + LONG2CHARS( 0x000FFFFFFF000000 ), + LONG2CHARS( 0x000FFFFFFF800000 ), + LONG2CHARS( 0x000FFFFFFFC00000 ), + LONG2CHARS( 0x000FFFFFFFE00000 ), + LONG2CHARS( 0x000FFFFFFFF00000 ), + LONG2CHARS( 0x000FFFFFFFF80000 ), + LONG2CHARS( 0x000FFFFFFFFC0000 ), + LONG2CHARS( 0x000FFFFFFFFE0000 ), + LONG2CHARS( 0x000FFFFFFFFF0000 ), + LONG2CHARS( 0x000FFFFFFFFF8000 ), + LONG2CHARS( 0x000FFFFFFFFFC000 ), + LONG2CHARS( 0x000FFFFFFFFFE000 ), + LONG2CHARS( 0x000FFFFFFFFFF000 ), + LONG2CHARS( 0x000FFFFFFFFFF800 ), + LONG2CHARS( 0x000FFFFFFFFFFC00 ), + LONG2CHARS( 0x000FFFFFFFFFFE00 ), + LONG2CHARS( 0x000FFFFFFFFFFF00 ), + LONG2CHARS( 0x000FFFFFFFFFFF80 ), + LONG2CHARS( 0x000FFFFFFFFFFFC0 ), + LONG2CHARS( 0x000FFFFFFFFFFFE0 ), + LONG2CHARS( 0x000FFFFFFFFFFFF0 ), + LONG2CHARS( 0x000FFFFFFFFFFFF8 ), + LONG2CHARS( 0x000FFFFFFFFFFFFC ), + LONG2CHARS( 0x000FFFFFFFFFFFFE ), + LONG2CHARS( 0x000FFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0004000000000000 ), + LONG2CHARS( 0x0006000000000000 ), + LONG2CHARS( 0x0007000000000000 ), + LONG2CHARS( 0x0007800000000000 ), + LONG2CHARS( 0x0007C00000000000 ), + LONG2CHARS( 0x0007E00000000000 ), + LONG2CHARS( 0x0007F00000000000 ), + LONG2CHARS( 0x0007F80000000000 ), + LONG2CHARS( 0x0007FC0000000000 ), + LONG2CHARS( 0x0007FE0000000000 ), + LONG2CHARS( 0x0007FF0000000000 ), + LONG2CHARS( 0x0007FF8000000000 ), + LONG2CHARS( 0x0007FFC000000000 ), + LONG2CHARS( 0x0007FFE000000000 ), + LONG2CHARS( 0x0007FFF000000000 ), + LONG2CHARS( 0x0007FFF800000000 ), + LONG2CHARS( 0x0007FFFC00000000 ), + LONG2CHARS( 0x0007FFFE00000000 ), + LONG2CHARS( 0x0007FFFF00000000 ), + LONG2CHARS( 0x0007FFFF80000000 ), + LONG2CHARS( 0x0007FFFFC0000000 ), + LONG2CHARS( 0x0007FFFFE0000000 ), + LONG2CHARS( 0x0007FFFFF0000000 ), + LONG2CHARS( 0x0007FFFFF8000000 ), + LONG2CHARS( 0x0007FFFFFC000000 ), + LONG2CHARS( 0x0007FFFFFE000000 ), + LONG2CHARS( 0x0007FFFFFF000000 ), + LONG2CHARS( 0x0007FFFFFF800000 ), + LONG2CHARS( 0x0007FFFFFFC00000 ), + LONG2CHARS( 0x0007FFFFFFE00000 ), + LONG2CHARS( 0x0007FFFFFFF00000 ), + LONG2CHARS( 0x0007FFFFFFF80000 ), + LONG2CHARS( 0x0007FFFFFFFC0000 ), + LONG2CHARS( 0x0007FFFFFFFE0000 ), + LONG2CHARS( 0x0007FFFFFFFF0000 ), + LONG2CHARS( 0x0007FFFFFFFF8000 ), + LONG2CHARS( 0x0007FFFFFFFFC000 ), + LONG2CHARS( 0x0007FFFFFFFFE000 ), + LONG2CHARS( 0x0007FFFFFFFFF000 ), + LONG2CHARS( 0x0007FFFFFFFFF800 ), + LONG2CHARS( 0x0007FFFFFFFFFC00 ), + LONG2CHARS( 0x0007FFFFFFFFFE00 ), + LONG2CHARS( 0x0007FFFFFFFFFF00 ), + LONG2CHARS( 0x0007FFFFFFFFFF80 ), + LONG2CHARS( 0x0007FFFFFFFFFFC0 ), + LONG2CHARS( 0x0007FFFFFFFFFFE0 ), + LONG2CHARS( 0x0007FFFFFFFFFFF0 ), + LONG2CHARS( 0x0007FFFFFFFFFFF8 ), + LONG2CHARS( 0x0007FFFFFFFFFFFC ), + LONG2CHARS( 0x0007FFFFFFFFFFFE ), + LONG2CHARS( 0x0007FFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0002000000000000 ), + LONG2CHARS( 0x0003000000000000 ), + LONG2CHARS( 0x0003800000000000 ), + LONG2CHARS( 0x0003C00000000000 ), + LONG2CHARS( 0x0003E00000000000 ), + LONG2CHARS( 0x0003F00000000000 ), + LONG2CHARS( 0x0003F80000000000 ), + LONG2CHARS( 0x0003FC0000000000 ), + LONG2CHARS( 0x0003FE0000000000 ), + LONG2CHARS( 0x0003FF0000000000 ), + LONG2CHARS( 0x0003FF8000000000 ), + LONG2CHARS( 0x0003FFC000000000 ), + LONG2CHARS( 0x0003FFE000000000 ), + LONG2CHARS( 0x0003FFF000000000 ), + LONG2CHARS( 0x0003FFF800000000 ), + LONG2CHARS( 0x0003FFFC00000000 ), + LONG2CHARS( 0x0003FFFE00000000 ), + LONG2CHARS( 0x0003FFFF00000000 ), + LONG2CHARS( 0x0003FFFF80000000 ), + LONG2CHARS( 0x0003FFFFC0000000 ), + LONG2CHARS( 0x0003FFFFE0000000 ), + LONG2CHARS( 0x0003FFFFF0000000 ), + LONG2CHARS( 0x0003FFFFF8000000 ), + LONG2CHARS( 0x0003FFFFFC000000 ), + LONG2CHARS( 0x0003FFFFFE000000 ), + LONG2CHARS( 0x0003FFFFFF000000 ), + LONG2CHARS( 0x0003FFFFFF800000 ), + LONG2CHARS( 0x0003FFFFFFC00000 ), + LONG2CHARS( 0x0003FFFFFFE00000 ), + LONG2CHARS( 0x0003FFFFFFF00000 ), + LONG2CHARS( 0x0003FFFFFFF80000 ), + LONG2CHARS( 0x0003FFFFFFFC0000 ), + LONG2CHARS( 0x0003FFFFFFFE0000 ), + LONG2CHARS( 0x0003FFFFFFFF0000 ), + LONG2CHARS( 0x0003FFFFFFFF8000 ), + LONG2CHARS( 0x0003FFFFFFFFC000 ), + LONG2CHARS( 0x0003FFFFFFFFE000 ), + LONG2CHARS( 0x0003FFFFFFFFF000 ), + LONG2CHARS( 0x0003FFFFFFFFF800 ), + LONG2CHARS( 0x0003FFFFFFFFFC00 ), + LONG2CHARS( 0x0003FFFFFFFFFE00 ), + LONG2CHARS( 0x0003FFFFFFFFFF00 ), + LONG2CHARS( 0x0003FFFFFFFFFF80 ), + LONG2CHARS( 0x0003FFFFFFFFFFC0 ), + LONG2CHARS( 0x0003FFFFFFFFFFE0 ), + LONG2CHARS( 0x0003FFFFFFFFFFF0 ), + LONG2CHARS( 0x0003FFFFFFFFFFF8 ), + LONG2CHARS( 0x0003FFFFFFFFFFFC ), + LONG2CHARS( 0x0003FFFFFFFFFFFE ), + LONG2CHARS( 0x0003FFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0001000000000000 ), + LONG2CHARS( 0x0001800000000000 ), + LONG2CHARS( 0x0001C00000000000 ), + LONG2CHARS( 0x0001E00000000000 ), + LONG2CHARS( 0x0001F00000000000 ), + LONG2CHARS( 0x0001F80000000000 ), + LONG2CHARS( 0x0001FC0000000000 ), + LONG2CHARS( 0x0001FE0000000000 ), + LONG2CHARS( 0x0001FF0000000000 ), + LONG2CHARS( 0x0001FF8000000000 ), + LONG2CHARS( 0x0001FFC000000000 ), + LONG2CHARS( 0x0001FFE000000000 ), + LONG2CHARS( 0x0001FFF000000000 ), + LONG2CHARS( 0x0001FFF800000000 ), + LONG2CHARS( 0x0001FFFC00000000 ), + LONG2CHARS( 0x0001FFFE00000000 ), + LONG2CHARS( 0x0001FFFF00000000 ), + LONG2CHARS( 0x0001FFFF80000000 ), + LONG2CHARS( 0x0001FFFFC0000000 ), + LONG2CHARS( 0x0001FFFFE0000000 ), + LONG2CHARS( 0x0001FFFFF0000000 ), + LONG2CHARS( 0x0001FFFFF8000000 ), + LONG2CHARS( 0x0001FFFFFC000000 ), + LONG2CHARS( 0x0001FFFFFE000000 ), + LONG2CHARS( 0x0001FFFFFF000000 ), + LONG2CHARS( 0x0001FFFFFF800000 ), + LONG2CHARS( 0x0001FFFFFFC00000 ), + LONG2CHARS( 0x0001FFFFFFE00000 ), + LONG2CHARS( 0x0001FFFFFFF00000 ), + LONG2CHARS( 0x0001FFFFFFF80000 ), + LONG2CHARS( 0x0001FFFFFFFC0000 ), + LONG2CHARS( 0x0001FFFFFFFE0000 ), + LONG2CHARS( 0x0001FFFFFFFF0000 ), + LONG2CHARS( 0x0001FFFFFFFF8000 ), + LONG2CHARS( 0x0001FFFFFFFFC000 ), + LONG2CHARS( 0x0001FFFFFFFFE000 ), + LONG2CHARS( 0x0001FFFFFFFFF000 ), + LONG2CHARS( 0x0001FFFFFFFFF800 ), + LONG2CHARS( 0x0001FFFFFFFFFC00 ), + LONG2CHARS( 0x0001FFFFFFFFFE00 ), + LONG2CHARS( 0x0001FFFFFFFFFF00 ), + LONG2CHARS( 0x0001FFFFFFFFFF80 ), + LONG2CHARS( 0x0001FFFFFFFFFFC0 ), + LONG2CHARS( 0x0001FFFFFFFFFFE0 ), + LONG2CHARS( 0x0001FFFFFFFFFFF0 ), + LONG2CHARS( 0x0001FFFFFFFFFFF8 ), + LONG2CHARS( 0x0001FFFFFFFFFFFC ), + LONG2CHARS( 0x0001FFFFFFFFFFFE ), + LONG2CHARS( 0x0001FFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000800000000000 ), + LONG2CHARS( 0x0000C00000000000 ), + LONG2CHARS( 0x0000E00000000000 ), + LONG2CHARS( 0x0000F00000000000 ), + LONG2CHARS( 0x0000F80000000000 ), + LONG2CHARS( 0x0000FC0000000000 ), + LONG2CHARS( 0x0000FE0000000000 ), + LONG2CHARS( 0x0000FF0000000000 ), + LONG2CHARS( 0x0000FF8000000000 ), + LONG2CHARS( 0x0000FFC000000000 ), + LONG2CHARS( 0x0000FFE000000000 ), + LONG2CHARS( 0x0000FFF000000000 ), + LONG2CHARS( 0x0000FFF800000000 ), + LONG2CHARS( 0x0000FFFC00000000 ), + LONG2CHARS( 0x0000FFFE00000000 ), + LONG2CHARS( 0x0000FFFF00000000 ), + LONG2CHARS( 0x0000FFFF80000000 ), + LONG2CHARS( 0x0000FFFFC0000000 ), + LONG2CHARS( 0x0000FFFFE0000000 ), + LONG2CHARS( 0x0000FFFFF0000000 ), + LONG2CHARS( 0x0000FFFFF8000000 ), + LONG2CHARS( 0x0000FFFFFC000000 ), + LONG2CHARS( 0x0000FFFFFE000000 ), + LONG2CHARS( 0x0000FFFFFF000000 ), + LONG2CHARS( 0x0000FFFFFF800000 ), + LONG2CHARS( 0x0000FFFFFFC00000 ), + LONG2CHARS( 0x0000FFFFFFE00000 ), + LONG2CHARS( 0x0000FFFFFFF00000 ), + LONG2CHARS( 0x0000FFFFFFF80000 ), + LONG2CHARS( 0x0000FFFFFFFC0000 ), + LONG2CHARS( 0x0000FFFFFFFE0000 ), + LONG2CHARS( 0x0000FFFFFFFF0000 ), + LONG2CHARS( 0x0000FFFFFFFF8000 ), + LONG2CHARS( 0x0000FFFFFFFFC000 ), + LONG2CHARS( 0x0000FFFFFFFFE000 ), + LONG2CHARS( 0x0000FFFFFFFFF000 ), + LONG2CHARS( 0x0000FFFFFFFFF800 ), + LONG2CHARS( 0x0000FFFFFFFFFC00 ), + LONG2CHARS( 0x0000FFFFFFFFFE00 ), + LONG2CHARS( 0x0000FFFFFFFFFF00 ), + LONG2CHARS( 0x0000FFFFFFFFFF80 ), + LONG2CHARS( 0x0000FFFFFFFFFFC0 ), + LONG2CHARS( 0x0000FFFFFFFFFFE0 ), + LONG2CHARS( 0x0000FFFFFFFFFFF0 ), + LONG2CHARS( 0x0000FFFFFFFFFFF8 ), + LONG2CHARS( 0x0000FFFFFFFFFFFC ), + LONG2CHARS( 0x0000FFFFFFFFFFFE ), + LONG2CHARS( 0x0000FFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000400000000000 ), + LONG2CHARS( 0x0000600000000000 ), + LONG2CHARS( 0x0000700000000000 ), + LONG2CHARS( 0x0000780000000000 ), + LONG2CHARS( 0x00007C0000000000 ), + LONG2CHARS( 0x00007E0000000000 ), + LONG2CHARS( 0x00007F0000000000 ), + LONG2CHARS( 0x00007F8000000000 ), + LONG2CHARS( 0x00007FC000000000 ), + LONG2CHARS( 0x00007FE000000000 ), + LONG2CHARS( 0x00007FF000000000 ), + LONG2CHARS( 0x00007FF800000000 ), + LONG2CHARS( 0x00007FFC00000000 ), + LONG2CHARS( 0x00007FFE00000000 ), + LONG2CHARS( 0x00007FFF00000000 ), + LONG2CHARS( 0x00007FFF80000000 ), + LONG2CHARS( 0x00007FFFC0000000 ), + LONG2CHARS( 0x00007FFFE0000000 ), + LONG2CHARS( 0x00007FFFF0000000 ), + LONG2CHARS( 0x00007FFFF8000000 ), + LONG2CHARS( 0x00007FFFFC000000 ), + LONG2CHARS( 0x00007FFFFE000000 ), + LONG2CHARS( 0x00007FFFFF000000 ), + LONG2CHARS( 0x00007FFFFF800000 ), + LONG2CHARS( 0x00007FFFFFC00000 ), + LONG2CHARS( 0x00007FFFFFE00000 ), + LONG2CHARS( 0x00007FFFFFF00000 ), + LONG2CHARS( 0x00007FFFFFF80000 ), + LONG2CHARS( 0x00007FFFFFFC0000 ), + LONG2CHARS( 0x00007FFFFFFE0000 ), + LONG2CHARS( 0x00007FFFFFFF0000 ), + LONG2CHARS( 0x00007FFFFFFF8000 ), + LONG2CHARS( 0x00007FFFFFFFC000 ), + LONG2CHARS( 0x00007FFFFFFFE000 ), + LONG2CHARS( 0x00007FFFFFFFF000 ), + LONG2CHARS( 0x00007FFFFFFFF800 ), + LONG2CHARS( 0x00007FFFFFFFFC00 ), + LONG2CHARS( 0x00007FFFFFFFFE00 ), + LONG2CHARS( 0x00007FFFFFFFFF00 ), + LONG2CHARS( 0x00007FFFFFFFFF80 ), + LONG2CHARS( 0x00007FFFFFFFFFC0 ), + LONG2CHARS( 0x00007FFFFFFFFFE0 ), + LONG2CHARS( 0x00007FFFFFFFFFF0 ), + LONG2CHARS( 0x00007FFFFFFFFFF8 ), + LONG2CHARS( 0x00007FFFFFFFFFFC ), + LONG2CHARS( 0x00007FFFFFFFFFFE ), + LONG2CHARS( 0x00007FFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000200000000000 ), + LONG2CHARS( 0x0000300000000000 ), + LONG2CHARS( 0x0000380000000000 ), + LONG2CHARS( 0x00003C0000000000 ), + LONG2CHARS( 0x00003E0000000000 ), + LONG2CHARS( 0x00003F0000000000 ), + LONG2CHARS( 0x00003F8000000000 ), + LONG2CHARS( 0x00003FC000000000 ), + LONG2CHARS( 0x00003FE000000000 ), + LONG2CHARS( 0x00003FF000000000 ), + LONG2CHARS( 0x00003FF800000000 ), + LONG2CHARS( 0x00003FFC00000000 ), + LONG2CHARS( 0x00003FFE00000000 ), + LONG2CHARS( 0x00003FFF00000000 ), + LONG2CHARS( 0x00003FFF80000000 ), + LONG2CHARS( 0x00003FFFC0000000 ), + LONG2CHARS( 0x00003FFFE0000000 ), + LONG2CHARS( 0x00003FFFF0000000 ), + LONG2CHARS( 0x00003FFFF8000000 ), + LONG2CHARS( 0x00003FFFFC000000 ), + LONG2CHARS( 0x00003FFFFE000000 ), + LONG2CHARS( 0x00003FFFFF000000 ), + LONG2CHARS( 0x00003FFFFF800000 ), + LONG2CHARS( 0x00003FFFFFC00000 ), + LONG2CHARS( 0x00003FFFFFE00000 ), + LONG2CHARS( 0x00003FFFFFF00000 ), + LONG2CHARS( 0x00003FFFFFF80000 ), + LONG2CHARS( 0x00003FFFFFFC0000 ), + LONG2CHARS( 0x00003FFFFFFE0000 ), + LONG2CHARS( 0x00003FFFFFFF0000 ), + LONG2CHARS( 0x00003FFFFFFF8000 ), + LONG2CHARS( 0x00003FFFFFFFC000 ), + LONG2CHARS( 0x00003FFFFFFFE000 ), + LONG2CHARS( 0x00003FFFFFFFF000 ), + LONG2CHARS( 0x00003FFFFFFFF800 ), + LONG2CHARS( 0x00003FFFFFFFFC00 ), + LONG2CHARS( 0x00003FFFFFFFFE00 ), + LONG2CHARS( 0x00003FFFFFFFFF00 ), + LONG2CHARS( 0x00003FFFFFFFFF80 ), + LONG2CHARS( 0x00003FFFFFFFFFC0 ), + LONG2CHARS( 0x00003FFFFFFFFFE0 ), + LONG2CHARS( 0x00003FFFFFFFFFF0 ), + LONG2CHARS( 0x00003FFFFFFFFFF8 ), + LONG2CHARS( 0x00003FFFFFFFFFFC ), + LONG2CHARS( 0x00003FFFFFFFFFFE ), + LONG2CHARS( 0x00003FFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000100000000000 ), + LONG2CHARS( 0x0000180000000000 ), + LONG2CHARS( 0x00001C0000000000 ), + LONG2CHARS( 0x00001E0000000000 ), + LONG2CHARS( 0x00001F0000000000 ), + LONG2CHARS( 0x00001F8000000000 ), + LONG2CHARS( 0x00001FC000000000 ), + LONG2CHARS( 0x00001FE000000000 ), + LONG2CHARS( 0x00001FF000000000 ), + LONG2CHARS( 0x00001FF800000000 ), + LONG2CHARS( 0x00001FFC00000000 ), + LONG2CHARS( 0x00001FFE00000000 ), + LONG2CHARS( 0x00001FFF00000000 ), + LONG2CHARS( 0x00001FFF80000000 ), + LONG2CHARS( 0x00001FFFC0000000 ), + LONG2CHARS( 0x00001FFFE0000000 ), + LONG2CHARS( 0x00001FFFF0000000 ), + LONG2CHARS( 0x00001FFFF8000000 ), + LONG2CHARS( 0x00001FFFFC000000 ), + LONG2CHARS( 0x00001FFFFE000000 ), + LONG2CHARS( 0x00001FFFFF000000 ), + LONG2CHARS( 0x00001FFFFF800000 ), + LONG2CHARS( 0x00001FFFFFC00000 ), + LONG2CHARS( 0x00001FFFFFE00000 ), + LONG2CHARS( 0x00001FFFFFF00000 ), + LONG2CHARS( 0x00001FFFFFF80000 ), + LONG2CHARS( 0x00001FFFFFFC0000 ), + LONG2CHARS( 0x00001FFFFFFE0000 ), + LONG2CHARS( 0x00001FFFFFFF0000 ), + LONG2CHARS( 0x00001FFFFFFF8000 ), + LONG2CHARS( 0x00001FFFFFFFC000 ), + LONG2CHARS( 0x00001FFFFFFFE000 ), + LONG2CHARS( 0x00001FFFFFFFF000 ), + LONG2CHARS( 0x00001FFFFFFFF800 ), + LONG2CHARS( 0x00001FFFFFFFFC00 ), + LONG2CHARS( 0x00001FFFFFFFFE00 ), + LONG2CHARS( 0x00001FFFFFFFFF00 ), + LONG2CHARS( 0x00001FFFFFFFFF80 ), + LONG2CHARS( 0x00001FFFFFFFFFC0 ), + LONG2CHARS( 0x00001FFFFFFFFFE0 ), + LONG2CHARS( 0x00001FFFFFFFFFF0 ), + LONG2CHARS( 0x00001FFFFFFFFFF8 ), + LONG2CHARS( 0x00001FFFFFFFFFFC ), + LONG2CHARS( 0x00001FFFFFFFFFFE ), + LONG2CHARS( 0x00001FFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000080000000000 ), + LONG2CHARS( 0x00000C0000000000 ), + LONG2CHARS( 0x00000E0000000000 ), + LONG2CHARS( 0x00000F0000000000 ), + LONG2CHARS( 0x00000F8000000000 ), + LONG2CHARS( 0x00000FC000000000 ), + LONG2CHARS( 0x00000FE000000000 ), + LONG2CHARS( 0x00000FF000000000 ), + LONG2CHARS( 0x00000FF800000000 ), + LONG2CHARS( 0x00000FFC00000000 ), + LONG2CHARS( 0x00000FFE00000000 ), + LONG2CHARS( 0x00000FFF00000000 ), + LONG2CHARS( 0x00000FFF80000000 ), + LONG2CHARS( 0x00000FFFC0000000 ), + LONG2CHARS( 0x00000FFFE0000000 ), + LONG2CHARS( 0x00000FFFF0000000 ), + LONG2CHARS( 0x00000FFFF8000000 ), + LONG2CHARS( 0x00000FFFFC000000 ), + LONG2CHARS( 0x00000FFFFE000000 ), + LONG2CHARS( 0x00000FFFFF000000 ), + LONG2CHARS( 0x00000FFFFF800000 ), + LONG2CHARS( 0x00000FFFFFC00000 ), + LONG2CHARS( 0x00000FFFFFE00000 ), + LONG2CHARS( 0x00000FFFFFF00000 ), + LONG2CHARS( 0x00000FFFFFF80000 ), + LONG2CHARS( 0x00000FFFFFFC0000 ), + LONG2CHARS( 0x00000FFFFFFE0000 ), + LONG2CHARS( 0x00000FFFFFFF0000 ), + LONG2CHARS( 0x00000FFFFFFF8000 ), + LONG2CHARS( 0x00000FFFFFFFC000 ), + LONG2CHARS( 0x00000FFFFFFFE000 ), + LONG2CHARS( 0x00000FFFFFFFF000 ), + LONG2CHARS( 0x00000FFFFFFFF800 ), + LONG2CHARS( 0x00000FFFFFFFFC00 ), + LONG2CHARS( 0x00000FFFFFFFFE00 ), + LONG2CHARS( 0x00000FFFFFFFFF00 ), + LONG2CHARS( 0x00000FFFFFFFFF80 ), + LONG2CHARS( 0x00000FFFFFFFFFC0 ), + LONG2CHARS( 0x00000FFFFFFFFFE0 ), + LONG2CHARS( 0x00000FFFFFFFFFF0 ), + LONG2CHARS( 0x00000FFFFFFFFFF8 ), + LONG2CHARS( 0x00000FFFFFFFFFFC ), + LONG2CHARS( 0x00000FFFFFFFFFFE ), + LONG2CHARS( 0x00000FFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000040000000000 ), + LONG2CHARS( 0x0000060000000000 ), + LONG2CHARS( 0x0000070000000000 ), + LONG2CHARS( 0x0000078000000000 ), + LONG2CHARS( 0x000007C000000000 ), + LONG2CHARS( 0x000007E000000000 ), + LONG2CHARS( 0x000007F000000000 ), + LONG2CHARS( 0x000007F800000000 ), + LONG2CHARS( 0x000007FC00000000 ), + LONG2CHARS( 0x000007FE00000000 ), + LONG2CHARS( 0x000007FF00000000 ), + LONG2CHARS( 0x000007FF80000000 ), + LONG2CHARS( 0x000007FFC0000000 ), + LONG2CHARS( 0x000007FFE0000000 ), + LONG2CHARS( 0x000007FFF0000000 ), + LONG2CHARS( 0x000007FFF8000000 ), + LONG2CHARS( 0x000007FFFC000000 ), + LONG2CHARS( 0x000007FFFE000000 ), + LONG2CHARS( 0x000007FFFF000000 ), + LONG2CHARS( 0x000007FFFF800000 ), + LONG2CHARS( 0x000007FFFFC00000 ), + LONG2CHARS( 0x000007FFFFE00000 ), + LONG2CHARS( 0x000007FFFFF00000 ), + LONG2CHARS( 0x000007FFFFF80000 ), + LONG2CHARS( 0x000007FFFFFC0000 ), + LONG2CHARS( 0x000007FFFFFE0000 ), + LONG2CHARS( 0x000007FFFFFF0000 ), + LONG2CHARS( 0x000007FFFFFF8000 ), + LONG2CHARS( 0x000007FFFFFFC000 ), + LONG2CHARS( 0x000007FFFFFFE000 ), + LONG2CHARS( 0x000007FFFFFFF000 ), + LONG2CHARS( 0x000007FFFFFFF800 ), + LONG2CHARS( 0x000007FFFFFFFC00 ), + LONG2CHARS( 0x000007FFFFFFFE00 ), + LONG2CHARS( 0x000007FFFFFFFF00 ), + LONG2CHARS( 0x000007FFFFFFFF80 ), + LONG2CHARS( 0x000007FFFFFFFFC0 ), + LONG2CHARS( 0x000007FFFFFFFFE0 ), + LONG2CHARS( 0x000007FFFFFFFFF0 ), + LONG2CHARS( 0x000007FFFFFFFFF8 ), + LONG2CHARS( 0x000007FFFFFFFFFC ), + LONG2CHARS( 0x000007FFFFFFFFFE ), + LONG2CHARS( 0x000007FFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000020000000000 ), + LONG2CHARS( 0x0000030000000000 ), + LONG2CHARS( 0x0000038000000000 ), + LONG2CHARS( 0x000003C000000000 ), + LONG2CHARS( 0x000003E000000000 ), + LONG2CHARS( 0x000003F000000000 ), + LONG2CHARS( 0x000003F800000000 ), + LONG2CHARS( 0x000003FC00000000 ), + LONG2CHARS( 0x000003FE00000000 ), + LONG2CHARS( 0x000003FF00000000 ), + LONG2CHARS( 0x000003FF80000000 ), + LONG2CHARS( 0x000003FFC0000000 ), + LONG2CHARS( 0x000003FFE0000000 ), + LONG2CHARS( 0x000003FFF0000000 ), + LONG2CHARS( 0x000003FFF8000000 ), + LONG2CHARS( 0x000003FFFC000000 ), + LONG2CHARS( 0x000003FFFE000000 ), + LONG2CHARS( 0x000003FFFF000000 ), + LONG2CHARS( 0x000003FFFF800000 ), + LONG2CHARS( 0x000003FFFFC00000 ), + LONG2CHARS( 0x000003FFFFE00000 ), + LONG2CHARS( 0x000003FFFFF00000 ), + LONG2CHARS( 0x000003FFFFF80000 ), + LONG2CHARS( 0x000003FFFFFC0000 ), + LONG2CHARS( 0x000003FFFFFE0000 ), + LONG2CHARS( 0x000003FFFFFF0000 ), + LONG2CHARS( 0x000003FFFFFF8000 ), + LONG2CHARS( 0x000003FFFFFFC000 ), + LONG2CHARS( 0x000003FFFFFFE000 ), + LONG2CHARS( 0x000003FFFFFFF000 ), + LONG2CHARS( 0x000003FFFFFFF800 ), + LONG2CHARS( 0x000003FFFFFFFC00 ), + LONG2CHARS( 0x000003FFFFFFFE00 ), + LONG2CHARS( 0x000003FFFFFFFF00 ), + LONG2CHARS( 0x000003FFFFFFFF80 ), + LONG2CHARS( 0x000003FFFFFFFFC0 ), + LONG2CHARS( 0x000003FFFFFFFFE0 ), + LONG2CHARS( 0x000003FFFFFFFFF0 ), + LONG2CHARS( 0x000003FFFFFFFFF8 ), + LONG2CHARS( 0x000003FFFFFFFFFC ), + LONG2CHARS( 0x000003FFFFFFFFFE ), + LONG2CHARS( 0x000003FFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000010000000000 ), + LONG2CHARS( 0x0000018000000000 ), + LONG2CHARS( 0x000001C000000000 ), + LONG2CHARS( 0x000001E000000000 ), + LONG2CHARS( 0x000001F000000000 ), + LONG2CHARS( 0x000001F800000000 ), + LONG2CHARS( 0x000001FC00000000 ), + LONG2CHARS( 0x000001FE00000000 ), + LONG2CHARS( 0x000001FF00000000 ), + LONG2CHARS( 0x000001FF80000000 ), + LONG2CHARS( 0x000001FFC0000000 ), + LONG2CHARS( 0x000001FFE0000000 ), + LONG2CHARS( 0x000001FFF0000000 ), + LONG2CHARS( 0x000001FFF8000000 ), + LONG2CHARS( 0x000001FFFC000000 ), + LONG2CHARS( 0x000001FFFE000000 ), + LONG2CHARS( 0x000001FFFF000000 ), + LONG2CHARS( 0x000001FFFF800000 ), + LONG2CHARS( 0x000001FFFFC00000 ), + LONG2CHARS( 0x000001FFFFE00000 ), + LONG2CHARS( 0x000001FFFFF00000 ), + LONG2CHARS( 0x000001FFFFF80000 ), + LONG2CHARS( 0x000001FFFFFC0000 ), + LONG2CHARS( 0x000001FFFFFE0000 ), + LONG2CHARS( 0x000001FFFFFF0000 ), + LONG2CHARS( 0x000001FFFFFF8000 ), + LONG2CHARS( 0x000001FFFFFFC000 ), + LONG2CHARS( 0x000001FFFFFFE000 ), + LONG2CHARS( 0x000001FFFFFFF000 ), + LONG2CHARS( 0x000001FFFFFFF800 ), + LONG2CHARS( 0x000001FFFFFFFC00 ), + LONG2CHARS( 0x000001FFFFFFFE00 ), + LONG2CHARS( 0x000001FFFFFFFF00 ), + LONG2CHARS( 0x000001FFFFFFFF80 ), + LONG2CHARS( 0x000001FFFFFFFFC0 ), + LONG2CHARS( 0x000001FFFFFFFFE0 ), + LONG2CHARS( 0x000001FFFFFFFFF0 ), + LONG2CHARS( 0x000001FFFFFFFFF8 ), + LONG2CHARS( 0x000001FFFFFFFFFC ), + LONG2CHARS( 0x000001FFFFFFFFFE ), + LONG2CHARS( 0x000001FFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000008000000000 ), + LONG2CHARS( 0x000000C000000000 ), + LONG2CHARS( 0x000000E000000000 ), + LONG2CHARS( 0x000000F000000000 ), + LONG2CHARS( 0x000000F800000000 ), + LONG2CHARS( 0x000000FC00000000 ), + LONG2CHARS( 0x000000FE00000000 ), + LONG2CHARS( 0x000000FF00000000 ), + LONG2CHARS( 0x000000FF80000000 ), + LONG2CHARS( 0x000000FFC0000000 ), + LONG2CHARS( 0x000000FFE0000000 ), + LONG2CHARS( 0x000000FFF0000000 ), + LONG2CHARS( 0x000000FFF8000000 ), + LONG2CHARS( 0x000000FFFC000000 ), + LONG2CHARS( 0x000000FFFE000000 ), + LONG2CHARS( 0x000000FFFF000000 ), + LONG2CHARS( 0x000000FFFF800000 ), + LONG2CHARS( 0x000000FFFFC00000 ), + LONG2CHARS( 0x000000FFFFE00000 ), + LONG2CHARS( 0x000000FFFFF00000 ), + LONG2CHARS( 0x000000FFFFF80000 ), + LONG2CHARS( 0x000000FFFFFC0000 ), + LONG2CHARS( 0x000000FFFFFE0000 ), + LONG2CHARS( 0x000000FFFFFF0000 ), + LONG2CHARS( 0x000000FFFFFF8000 ), + LONG2CHARS( 0x000000FFFFFFC000 ), + LONG2CHARS( 0x000000FFFFFFE000 ), + LONG2CHARS( 0x000000FFFFFFF000 ), + LONG2CHARS( 0x000000FFFFFFF800 ), + LONG2CHARS( 0x000000FFFFFFFC00 ), + LONG2CHARS( 0x000000FFFFFFFE00 ), + LONG2CHARS( 0x000000FFFFFFFF00 ), + LONG2CHARS( 0x000000FFFFFFFF80 ), + LONG2CHARS( 0x000000FFFFFFFFC0 ), + LONG2CHARS( 0x000000FFFFFFFFE0 ), + LONG2CHARS( 0x000000FFFFFFFFF0 ), + LONG2CHARS( 0x000000FFFFFFFFF8 ), + LONG2CHARS( 0x000000FFFFFFFFFC ), + LONG2CHARS( 0x000000FFFFFFFFFE ), + LONG2CHARS( 0x000000FFFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000004000000000 ), + LONG2CHARS( 0x0000006000000000 ), + LONG2CHARS( 0x0000007000000000 ), + LONG2CHARS( 0x0000007800000000 ), + LONG2CHARS( 0x0000007C00000000 ), + LONG2CHARS( 0x0000007E00000000 ), + LONG2CHARS( 0x0000007F00000000 ), + LONG2CHARS( 0x0000007F80000000 ), + LONG2CHARS( 0x0000007FC0000000 ), + LONG2CHARS( 0x0000007FE0000000 ), + LONG2CHARS( 0x0000007FF0000000 ), + LONG2CHARS( 0x0000007FF8000000 ), + LONG2CHARS( 0x0000007FFC000000 ), + LONG2CHARS( 0x0000007FFE000000 ), + LONG2CHARS( 0x0000007FFF000000 ), + LONG2CHARS( 0x0000007FFF800000 ), + LONG2CHARS( 0x0000007FFFC00000 ), + LONG2CHARS( 0x0000007FFFE00000 ), + LONG2CHARS( 0x0000007FFFF00000 ), + LONG2CHARS( 0x0000007FFFF80000 ), + LONG2CHARS( 0x0000007FFFFC0000 ), + LONG2CHARS( 0x0000007FFFFE0000 ), + LONG2CHARS( 0x0000007FFFFF0000 ), + LONG2CHARS( 0x0000007FFFFF8000 ), + LONG2CHARS( 0x0000007FFFFFC000 ), + LONG2CHARS( 0x0000007FFFFFE000 ), + LONG2CHARS( 0x0000007FFFFFF000 ), + LONG2CHARS( 0x0000007FFFFFF800 ), + LONG2CHARS( 0x0000007FFFFFFC00 ), + LONG2CHARS( 0x0000007FFFFFFE00 ), + LONG2CHARS( 0x0000007FFFFFFF00 ), + LONG2CHARS( 0x0000007FFFFFFF80 ), + LONG2CHARS( 0x0000007FFFFFFFC0 ), + LONG2CHARS( 0x0000007FFFFFFFE0 ), + LONG2CHARS( 0x0000007FFFFFFFF0 ), + LONG2CHARS( 0x0000007FFFFFFFF8 ), + LONG2CHARS( 0x0000007FFFFFFFFC ), + LONG2CHARS( 0x0000007FFFFFFFFE ), + LONG2CHARS( 0x0000007FFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000002000000000 ), + LONG2CHARS( 0x0000003000000000 ), + LONG2CHARS( 0x0000003800000000 ), + LONG2CHARS( 0x0000003C00000000 ), + LONG2CHARS( 0x0000003E00000000 ), + LONG2CHARS( 0x0000003F00000000 ), + LONG2CHARS( 0x0000003F80000000 ), + LONG2CHARS( 0x0000003FC0000000 ), + LONG2CHARS( 0x0000003FE0000000 ), + LONG2CHARS( 0x0000003FF0000000 ), + LONG2CHARS( 0x0000003FF8000000 ), + LONG2CHARS( 0x0000003FFC000000 ), + LONG2CHARS( 0x0000003FFE000000 ), + LONG2CHARS( 0x0000003FFF000000 ), + LONG2CHARS( 0x0000003FFF800000 ), + LONG2CHARS( 0x0000003FFFC00000 ), + LONG2CHARS( 0x0000003FFFE00000 ), + LONG2CHARS( 0x0000003FFFF00000 ), + LONG2CHARS( 0x0000003FFFF80000 ), + LONG2CHARS( 0x0000003FFFFC0000 ), + LONG2CHARS( 0x0000003FFFFE0000 ), + LONG2CHARS( 0x0000003FFFFF0000 ), + LONG2CHARS( 0x0000003FFFFF8000 ), + LONG2CHARS( 0x0000003FFFFFC000 ), + LONG2CHARS( 0x0000003FFFFFE000 ), + LONG2CHARS( 0x0000003FFFFFF000 ), + LONG2CHARS( 0x0000003FFFFFF800 ), + LONG2CHARS( 0x0000003FFFFFFC00 ), + LONG2CHARS( 0x0000003FFFFFFE00 ), + LONG2CHARS( 0x0000003FFFFFFF00 ), + LONG2CHARS( 0x0000003FFFFFFF80 ), + LONG2CHARS( 0x0000003FFFFFFFC0 ), + LONG2CHARS( 0x0000003FFFFFFFE0 ), + LONG2CHARS( 0x0000003FFFFFFFF0 ), + LONG2CHARS( 0x0000003FFFFFFFF8 ), + LONG2CHARS( 0x0000003FFFFFFFFC ), + LONG2CHARS( 0x0000003FFFFFFFFE ), + LONG2CHARS( 0x0000003FFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000001000000000 ), + LONG2CHARS( 0x0000001800000000 ), + LONG2CHARS( 0x0000001C00000000 ), + LONG2CHARS( 0x0000001E00000000 ), + LONG2CHARS( 0x0000001F00000000 ), + LONG2CHARS( 0x0000001F80000000 ), + LONG2CHARS( 0x0000001FC0000000 ), + LONG2CHARS( 0x0000001FE0000000 ), + LONG2CHARS( 0x0000001FF0000000 ), + LONG2CHARS( 0x0000001FF8000000 ), + LONG2CHARS( 0x0000001FFC000000 ), + LONG2CHARS( 0x0000001FFE000000 ), + LONG2CHARS( 0x0000001FFF000000 ), + LONG2CHARS( 0x0000001FFF800000 ), + LONG2CHARS( 0x0000001FFFC00000 ), + LONG2CHARS( 0x0000001FFFE00000 ), + LONG2CHARS( 0x0000001FFFF00000 ), + LONG2CHARS( 0x0000001FFFF80000 ), + LONG2CHARS( 0x0000001FFFFC0000 ), + LONG2CHARS( 0x0000001FFFFE0000 ), + LONG2CHARS( 0x0000001FFFFF0000 ), + LONG2CHARS( 0x0000001FFFFF8000 ), + LONG2CHARS( 0x0000001FFFFFC000 ), + LONG2CHARS( 0x0000001FFFFFE000 ), + LONG2CHARS( 0x0000001FFFFFF000 ), + LONG2CHARS( 0x0000001FFFFFF800 ), + LONG2CHARS( 0x0000001FFFFFFC00 ), + LONG2CHARS( 0x0000001FFFFFFE00 ), + LONG2CHARS( 0x0000001FFFFFFF00 ), + LONG2CHARS( 0x0000001FFFFFFF80 ), + LONG2CHARS( 0x0000001FFFFFFFC0 ), + LONG2CHARS( 0x0000001FFFFFFFE0 ), + LONG2CHARS( 0x0000001FFFFFFFF0 ), + LONG2CHARS( 0x0000001FFFFFFFF8 ), + LONG2CHARS( 0x0000001FFFFFFFFC ), + LONG2CHARS( 0x0000001FFFFFFFFE ), + LONG2CHARS( 0x0000001FFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000800000000 ), + LONG2CHARS( 0x0000000C00000000 ), + LONG2CHARS( 0x0000000E00000000 ), + LONG2CHARS( 0x0000000F00000000 ), + LONG2CHARS( 0x0000000F80000000 ), + LONG2CHARS( 0x0000000FC0000000 ), + LONG2CHARS( 0x0000000FE0000000 ), + LONG2CHARS( 0x0000000FF0000000 ), + LONG2CHARS( 0x0000000FF8000000 ), + LONG2CHARS( 0x0000000FFC000000 ), + LONG2CHARS( 0x0000000FFE000000 ), + LONG2CHARS( 0x0000000FFF000000 ), + LONG2CHARS( 0x0000000FFF800000 ), + LONG2CHARS( 0x0000000FFFC00000 ), + LONG2CHARS( 0x0000000FFFE00000 ), + LONG2CHARS( 0x0000000FFFF00000 ), + LONG2CHARS( 0x0000000FFFF80000 ), + LONG2CHARS( 0x0000000FFFFC0000 ), + LONG2CHARS( 0x0000000FFFFE0000 ), + LONG2CHARS( 0x0000000FFFFF0000 ), + LONG2CHARS( 0x0000000FFFFF8000 ), + LONG2CHARS( 0x0000000FFFFFC000 ), + LONG2CHARS( 0x0000000FFFFFE000 ), + LONG2CHARS( 0x0000000FFFFFF000 ), + LONG2CHARS( 0x0000000FFFFFF800 ), + LONG2CHARS( 0x0000000FFFFFFC00 ), + LONG2CHARS( 0x0000000FFFFFFE00 ), + LONG2CHARS( 0x0000000FFFFFFF00 ), + LONG2CHARS( 0x0000000FFFFFFF80 ), + LONG2CHARS( 0x0000000FFFFFFFC0 ), + LONG2CHARS( 0x0000000FFFFFFFE0 ), + LONG2CHARS( 0x0000000FFFFFFFF0 ), + LONG2CHARS( 0x0000000FFFFFFFF8 ), + LONG2CHARS( 0x0000000FFFFFFFFC ), + LONG2CHARS( 0x0000000FFFFFFFFE ), + LONG2CHARS( 0x0000000FFFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000400000000 ), + LONG2CHARS( 0x0000000600000000 ), + LONG2CHARS( 0x0000000700000000 ), + LONG2CHARS( 0x0000000780000000 ), + LONG2CHARS( 0x00000007C0000000 ), + LONG2CHARS( 0x00000007E0000000 ), + LONG2CHARS( 0x00000007F0000000 ), + LONG2CHARS( 0x00000007F8000000 ), + LONG2CHARS( 0x00000007FC000000 ), + LONG2CHARS( 0x00000007FE000000 ), + LONG2CHARS( 0x00000007FF000000 ), + LONG2CHARS( 0x00000007FF800000 ), + LONG2CHARS( 0x00000007FFC00000 ), + LONG2CHARS( 0x00000007FFE00000 ), + LONG2CHARS( 0x00000007FFF00000 ), + LONG2CHARS( 0x00000007FFF80000 ), + LONG2CHARS( 0x00000007FFFC0000 ), + LONG2CHARS( 0x00000007FFFE0000 ), + LONG2CHARS( 0x00000007FFFF0000 ), + LONG2CHARS( 0x00000007FFFF8000 ), + LONG2CHARS( 0x00000007FFFFC000 ), + LONG2CHARS( 0x00000007FFFFE000 ), + LONG2CHARS( 0x00000007FFFFF000 ), + LONG2CHARS( 0x00000007FFFFF800 ), + LONG2CHARS( 0x00000007FFFFFC00 ), + LONG2CHARS( 0x00000007FFFFFE00 ), + LONG2CHARS( 0x00000007FFFFFF00 ), + LONG2CHARS( 0x00000007FFFFFF80 ), + LONG2CHARS( 0x00000007FFFFFFC0 ), + LONG2CHARS( 0x00000007FFFFFFE0 ), + LONG2CHARS( 0x00000007FFFFFFF0 ), + LONG2CHARS( 0x00000007FFFFFFF8 ), + LONG2CHARS( 0x00000007FFFFFFFC ), + LONG2CHARS( 0x00000007FFFFFFFE ), + LONG2CHARS( 0x00000007FFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000200000000 ), + LONG2CHARS( 0x0000000300000000 ), + LONG2CHARS( 0x0000000380000000 ), + LONG2CHARS( 0x00000003C0000000 ), + LONG2CHARS( 0x00000003E0000000 ), + LONG2CHARS( 0x00000003F0000000 ), + LONG2CHARS( 0x00000003F8000000 ), + LONG2CHARS( 0x00000003FC000000 ), + LONG2CHARS( 0x00000003FE000000 ), + LONG2CHARS( 0x00000003FF000000 ), + LONG2CHARS( 0x00000003FF800000 ), + LONG2CHARS( 0x00000003FFC00000 ), + LONG2CHARS( 0x00000003FFE00000 ), + LONG2CHARS( 0x00000003FFF00000 ), + LONG2CHARS( 0x00000003FFF80000 ), + LONG2CHARS( 0x00000003FFFC0000 ), + LONG2CHARS( 0x00000003FFFE0000 ), + LONG2CHARS( 0x00000003FFFF0000 ), + LONG2CHARS( 0x00000003FFFF8000 ), + LONG2CHARS( 0x00000003FFFFC000 ), + LONG2CHARS( 0x00000003FFFFE000 ), + LONG2CHARS( 0x00000003FFFFF000 ), + LONG2CHARS( 0x00000003FFFFF800 ), + LONG2CHARS( 0x00000003FFFFFC00 ), + LONG2CHARS( 0x00000003FFFFFE00 ), + LONG2CHARS( 0x00000003FFFFFF00 ), + LONG2CHARS( 0x00000003FFFFFF80 ), + LONG2CHARS( 0x00000003FFFFFFC0 ), + LONG2CHARS( 0x00000003FFFFFFE0 ), + LONG2CHARS( 0x00000003FFFFFFF0 ), + LONG2CHARS( 0x00000003FFFFFFF8 ), + LONG2CHARS( 0x00000003FFFFFFFC ), + LONG2CHARS( 0x00000003FFFFFFFE ), + LONG2CHARS( 0x00000003FFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000100000000 ), + LONG2CHARS( 0x0000000180000000 ), + LONG2CHARS( 0x00000001C0000000 ), + LONG2CHARS( 0x00000001E0000000 ), + LONG2CHARS( 0x00000001F0000000 ), + LONG2CHARS( 0x00000001F8000000 ), + LONG2CHARS( 0x00000001FC000000 ), + LONG2CHARS( 0x00000001FE000000 ), + LONG2CHARS( 0x00000001FF000000 ), + LONG2CHARS( 0x00000001FF800000 ), + LONG2CHARS( 0x00000001FFC00000 ), + LONG2CHARS( 0x00000001FFE00000 ), + LONG2CHARS( 0x00000001FFF00000 ), + LONG2CHARS( 0x00000001FFF80000 ), + LONG2CHARS( 0x00000001FFFC0000 ), + LONG2CHARS( 0x00000001FFFE0000 ), + LONG2CHARS( 0x00000001FFFF0000 ), + LONG2CHARS( 0x00000001FFFF8000 ), + LONG2CHARS( 0x00000001FFFFC000 ), + LONG2CHARS( 0x00000001FFFFE000 ), + LONG2CHARS( 0x00000001FFFFF000 ), + LONG2CHARS( 0x00000001FFFFF800 ), + LONG2CHARS( 0x00000001FFFFFC00 ), + LONG2CHARS( 0x00000001FFFFFE00 ), + LONG2CHARS( 0x00000001FFFFFF00 ), + LONG2CHARS( 0x00000001FFFFFF80 ), + LONG2CHARS( 0x00000001FFFFFFC0 ), + LONG2CHARS( 0x00000001FFFFFFE0 ), + LONG2CHARS( 0x00000001FFFFFFF0 ), + LONG2CHARS( 0x00000001FFFFFFF8 ), + LONG2CHARS( 0x00000001FFFFFFFC ), + LONG2CHARS( 0x00000001FFFFFFFE ), + LONG2CHARS( 0x00000001FFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000080000000 ), + LONG2CHARS( 0x00000000C0000000 ), + LONG2CHARS( 0x00000000E0000000 ), + LONG2CHARS( 0x00000000F0000000 ), + LONG2CHARS( 0x00000000F8000000 ), + LONG2CHARS( 0x00000000FC000000 ), + LONG2CHARS( 0x00000000FE000000 ), + LONG2CHARS( 0x00000000FF000000 ), + LONG2CHARS( 0x00000000FF800000 ), + LONG2CHARS( 0x00000000FFC00000 ), + LONG2CHARS( 0x00000000FFE00000 ), + LONG2CHARS( 0x00000000FFF00000 ), + LONG2CHARS( 0x00000000FFF80000 ), + LONG2CHARS( 0x00000000FFFC0000 ), + LONG2CHARS( 0x00000000FFFE0000 ), + LONG2CHARS( 0x00000000FFFF0000 ), + LONG2CHARS( 0x00000000FFFF8000 ), + LONG2CHARS( 0x00000000FFFFC000 ), + LONG2CHARS( 0x00000000FFFFE000 ), + LONG2CHARS( 0x00000000FFFFF000 ), + LONG2CHARS( 0x00000000FFFFF800 ), + LONG2CHARS( 0x00000000FFFFFC00 ), + LONG2CHARS( 0x00000000FFFFFE00 ), + LONG2CHARS( 0x00000000FFFFFF00 ), + LONG2CHARS( 0x00000000FFFFFF80 ), + LONG2CHARS( 0x00000000FFFFFFC0 ), + LONG2CHARS( 0x00000000FFFFFFE0 ), + LONG2CHARS( 0x00000000FFFFFFF0 ), + LONG2CHARS( 0x00000000FFFFFFF8 ), + LONG2CHARS( 0x00000000FFFFFFFC ), + LONG2CHARS( 0x00000000FFFFFFFE ), + LONG2CHARS( 0x00000000FFFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000040000000 ), + LONG2CHARS( 0x0000000060000000 ), + LONG2CHARS( 0x0000000070000000 ), + LONG2CHARS( 0x0000000078000000 ), + LONG2CHARS( 0x000000007C000000 ), + LONG2CHARS( 0x000000007E000000 ), + LONG2CHARS( 0x000000007F000000 ), + LONG2CHARS( 0x000000007F800000 ), + LONG2CHARS( 0x000000007FC00000 ), + LONG2CHARS( 0x000000007FE00000 ), + LONG2CHARS( 0x000000007FF00000 ), + LONG2CHARS( 0x000000007FF80000 ), + LONG2CHARS( 0x000000007FFC0000 ), + LONG2CHARS( 0x000000007FFE0000 ), + LONG2CHARS( 0x000000007FFF0000 ), + LONG2CHARS( 0x000000007FFF8000 ), + LONG2CHARS( 0x000000007FFFC000 ), + LONG2CHARS( 0x000000007FFFE000 ), + LONG2CHARS( 0x000000007FFFF000 ), + LONG2CHARS( 0x000000007FFFF800 ), + LONG2CHARS( 0x000000007FFFFC00 ), + LONG2CHARS( 0x000000007FFFFE00 ), + LONG2CHARS( 0x000000007FFFFF00 ), + LONG2CHARS( 0x000000007FFFFF80 ), + LONG2CHARS( 0x000000007FFFFFC0 ), + LONG2CHARS( 0x000000007FFFFFE0 ), + LONG2CHARS( 0x000000007FFFFFF0 ), + LONG2CHARS( 0x000000007FFFFFF8 ), + LONG2CHARS( 0x000000007FFFFFFC ), + LONG2CHARS( 0x000000007FFFFFFE ), + LONG2CHARS( 0x000000007FFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000020000000 ), + LONG2CHARS( 0x0000000030000000 ), + LONG2CHARS( 0x0000000038000000 ), + LONG2CHARS( 0x000000003C000000 ), + LONG2CHARS( 0x000000003E000000 ), + LONG2CHARS( 0x000000003F000000 ), + LONG2CHARS( 0x000000003F800000 ), + LONG2CHARS( 0x000000003FC00000 ), + LONG2CHARS( 0x000000003FE00000 ), + LONG2CHARS( 0x000000003FF00000 ), + LONG2CHARS( 0x000000003FF80000 ), + LONG2CHARS( 0x000000003FFC0000 ), + LONG2CHARS( 0x000000003FFE0000 ), + LONG2CHARS( 0x000000003FFF0000 ), + LONG2CHARS( 0x000000003FFF8000 ), + LONG2CHARS( 0x000000003FFFC000 ), + LONG2CHARS( 0x000000003FFFE000 ), + LONG2CHARS( 0x000000003FFFF000 ), + LONG2CHARS( 0x000000003FFFF800 ), + LONG2CHARS( 0x000000003FFFFC00 ), + LONG2CHARS( 0x000000003FFFFE00 ), + LONG2CHARS( 0x000000003FFFFF00 ), + LONG2CHARS( 0x000000003FFFFF80 ), + LONG2CHARS( 0x000000003FFFFFC0 ), + LONG2CHARS( 0x000000003FFFFFE0 ), + LONG2CHARS( 0x000000003FFFFFF0 ), + LONG2CHARS( 0x000000003FFFFFF8 ), + LONG2CHARS( 0x000000003FFFFFFC ), + LONG2CHARS( 0x000000003FFFFFFE ), + LONG2CHARS( 0x000000003FFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000010000000 ), + LONG2CHARS( 0x0000000018000000 ), + LONG2CHARS( 0x000000001C000000 ), + LONG2CHARS( 0x000000001E000000 ), + LONG2CHARS( 0x000000001F000000 ), + LONG2CHARS( 0x000000001F800000 ), + LONG2CHARS( 0x000000001FC00000 ), + LONG2CHARS( 0x000000001FE00000 ), + LONG2CHARS( 0x000000001FF00000 ), + LONG2CHARS( 0x000000001FF80000 ), + LONG2CHARS( 0x000000001FFC0000 ), + LONG2CHARS( 0x000000001FFE0000 ), + LONG2CHARS( 0x000000001FFF0000 ), + LONG2CHARS( 0x000000001FFF8000 ), + LONG2CHARS( 0x000000001FFFC000 ), + LONG2CHARS( 0x000000001FFFE000 ), + LONG2CHARS( 0x000000001FFFF000 ), + LONG2CHARS( 0x000000001FFFF800 ), + LONG2CHARS( 0x000000001FFFFC00 ), + LONG2CHARS( 0x000000001FFFFE00 ), + LONG2CHARS( 0x000000001FFFFF00 ), + LONG2CHARS( 0x000000001FFFFF80 ), + LONG2CHARS( 0x000000001FFFFFC0 ), + LONG2CHARS( 0x000000001FFFFFE0 ), + LONG2CHARS( 0x000000001FFFFFF0 ), + LONG2CHARS( 0x000000001FFFFFF8 ), + LONG2CHARS( 0x000000001FFFFFFC ), + LONG2CHARS( 0x000000001FFFFFFE ), + LONG2CHARS( 0x000000001FFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000008000000 ), + LONG2CHARS( 0x000000000C000000 ), + LONG2CHARS( 0x000000000E000000 ), + LONG2CHARS( 0x000000000F000000 ), + LONG2CHARS( 0x000000000F800000 ), + LONG2CHARS( 0x000000000FC00000 ), + LONG2CHARS( 0x000000000FE00000 ), + LONG2CHARS( 0x000000000FF00000 ), + LONG2CHARS( 0x000000000FF80000 ), + LONG2CHARS( 0x000000000FFC0000 ), + LONG2CHARS( 0x000000000FFE0000 ), + LONG2CHARS( 0x000000000FFF0000 ), + LONG2CHARS( 0x000000000FFF8000 ), + LONG2CHARS( 0x000000000FFFC000 ), + LONG2CHARS( 0x000000000FFFE000 ), + LONG2CHARS( 0x000000000FFFF000 ), + LONG2CHARS( 0x000000000FFFF800 ), + LONG2CHARS( 0x000000000FFFFC00 ), + LONG2CHARS( 0x000000000FFFFE00 ), + LONG2CHARS( 0x000000000FFFFF00 ), + LONG2CHARS( 0x000000000FFFFF80 ), + LONG2CHARS( 0x000000000FFFFFC0 ), + LONG2CHARS( 0x000000000FFFFFE0 ), + LONG2CHARS( 0x000000000FFFFFF0 ), + LONG2CHARS( 0x000000000FFFFFF8 ), + LONG2CHARS( 0x000000000FFFFFFC ), + LONG2CHARS( 0x000000000FFFFFFE ), + LONG2CHARS( 0x000000000FFFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000004000000 ), + LONG2CHARS( 0x0000000006000000 ), + LONG2CHARS( 0x0000000007000000 ), + LONG2CHARS( 0x0000000007800000 ), + LONG2CHARS( 0x0000000007C00000 ), + LONG2CHARS( 0x0000000007E00000 ), + LONG2CHARS( 0x0000000007F00000 ), + LONG2CHARS( 0x0000000007F80000 ), + LONG2CHARS( 0x0000000007FC0000 ), + LONG2CHARS( 0x0000000007FE0000 ), + LONG2CHARS( 0x0000000007FF0000 ), + LONG2CHARS( 0x0000000007FF8000 ), + LONG2CHARS( 0x0000000007FFC000 ), + LONG2CHARS( 0x0000000007FFE000 ), + LONG2CHARS( 0x0000000007FFF000 ), + LONG2CHARS( 0x0000000007FFF800 ), + LONG2CHARS( 0x0000000007FFFC00 ), + LONG2CHARS( 0x0000000007FFFE00 ), + LONG2CHARS( 0x0000000007FFFF00 ), + LONG2CHARS( 0x0000000007FFFF80 ), + LONG2CHARS( 0x0000000007FFFFC0 ), + LONG2CHARS( 0x0000000007FFFFE0 ), + LONG2CHARS( 0x0000000007FFFFF0 ), + LONG2CHARS( 0x0000000007FFFFF8 ), + LONG2CHARS( 0x0000000007FFFFFC ), + LONG2CHARS( 0x0000000007FFFFFE ), + LONG2CHARS( 0x0000000007FFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000002000000 ), + LONG2CHARS( 0x0000000003000000 ), + LONG2CHARS( 0x0000000003800000 ), + LONG2CHARS( 0x0000000003C00000 ), + LONG2CHARS( 0x0000000003E00000 ), + LONG2CHARS( 0x0000000003F00000 ), + LONG2CHARS( 0x0000000003F80000 ), + LONG2CHARS( 0x0000000003FC0000 ), + LONG2CHARS( 0x0000000003FE0000 ), + LONG2CHARS( 0x0000000003FF0000 ), + LONG2CHARS( 0x0000000003FF8000 ), + LONG2CHARS( 0x0000000003FFC000 ), + LONG2CHARS( 0x0000000003FFE000 ), + LONG2CHARS( 0x0000000003FFF000 ), + LONG2CHARS( 0x0000000003FFF800 ), + LONG2CHARS( 0x0000000003FFFC00 ), + LONG2CHARS( 0x0000000003FFFE00 ), + LONG2CHARS( 0x0000000003FFFF00 ), + LONG2CHARS( 0x0000000003FFFF80 ), + LONG2CHARS( 0x0000000003FFFFC0 ), + LONG2CHARS( 0x0000000003FFFFE0 ), + LONG2CHARS( 0x0000000003FFFFF0 ), + LONG2CHARS( 0x0000000003FFFFF8 ), + LONG2CHARS( 0x0000000003FFFFFC ), + LONG2CHARS( 0x0000000003FFFFFE ), + LONG2CHARS( 0x0000000003FFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000001000000 ), + LONG2CHARS( 0x0000000001800000 ), + LONG2CHARS( 0x0000000001C00000 ), + LONG2CHARS( 0x0000000001E00000 ), + LONG2CHARS( 0x0000000001F00000 ), + LONG2CHARS( 0x0000000001F80000 ), + LONG2CHARS( 0x0000000001FC0000 ), + LONG2CHARS( 0x0000000001FE0000 ), + LONG2CHARS( 0x0000000001FF0000 ), + LONG2CHARS( 0x0000000001FF8000 ), + LONG2CHARS( 0x0000000001FFC000 ), + LONG2CHARS( 0x0000000001FFE000 ), + LONG2CHARS( 0x0000000001FFF000 ), + LONG2CHARS( 0x0000000001FFF800 ), + LONG2CHARS( 0x0000000001FFFC00 ), + LONG2CHARS( 0x0000000001FFFE00 ), + LONG2CHARS( 0x0000000001FFFF00 ), + LONG2CHARS( 0x0000000001FFFF80 ), + LONG2CHARS( 0x0000000001FFFFC0 ), + LONG2CHARS( 0x0000000001FFFFE0 ), + LONG2CHARS( 0x0000000001FFFFF0 ), + LONG2CHARS( 0x0000000001FFFFF8 ), + LONG2CHARS( 0x0000000001FFFFFC ), + LONG2CHARS( 0x0000000001FFFFFE ), + LONG2CHARS( 0x0000000001FFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000800000 ), + LONG2CHARS( 0x0000000000C00000 ), + LONG2CHARS( 0x0000000000E00000 ), + LONG2CHARS( 0x0000000000F00000 ), + LONG2CHARS( 0x0000000000F80000 ), + LONG2CHARS( 0x0000000000FC0000 ), + LONG2CHARS( 0x0000000000FE0000 ), + LONG2CHARS( 0x0000000000FF0000 ), + LONG2CHARS( 0x0000000000FF8000 ), + LONG2CHARS( 0x0000000000FFC000 ), + LONG2CHARS( 0x0000000000FFE000 ), + LONG2CHARS( 0x0000000000FFF000 ), + LONG2CHARS( 0x0000000000FFF800 ), + LONG2CHARS( 0x0000000000FFFC00 ), + LONG2CHARS( 0x0000000000FFFE00 ), + LONG2CHARS( 0x0000000000FFFF00 ), + LONG2CHARS( 0x0000000000FFFF80 ), + LONG2CHARS( 0x0000000000FFFFC0 ), + LONG2CHARS( 0x0000000000FFFFE0 ), + LONG2CHARS( 0x0000000000FFFFF0 ), + LONG2CHARS( 0x0000000000FFFFF8 ), + LONG2CHARS( 0x0000000000FFFFFC ), + LONG2CHARS( 0x0000000000FFFFFE ), + LONG2CHARS( 0x0000000000FFFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000400000 ), + LONG2CHARS( 0x0000000000600000 ), + LONG2CHARS( 0x0000000000700000 ), + LONG2CHARS( 0x0000000000780000 ), + LONG2CHARS( 0x00000000007C0000 ), + LONG2CHARS( 0x00000000007E0000 ), + LONG2CHARS( 0x00000000007F0000 ), + LONG2CHARS( 0x00000000007F8000 ), + LONG2CHARS( 0x00000000007FC000 ), + LONG2CHARS( 0x00000000007FE000 ), + LONG2CHARS( 0x00000000007FF000 ), + LONG2CHARS( 0x00000000007FF800 ), + LONG2CHARS( 0x00000000007FFC00 ), + LONG2CHARS( 0x00000000007FFE00 ), + LONG2CHARS( 0x00000000007FFF00 ), + LONG2CHARS( 0x00000000007FFF80 ), + LONG2CHARS( 0x00000000007FFFC0 ), + LONG2CHARS( 0x00000000007FFFE0 ), + LONG2CHARS( 0x00000000007FFFF0 ), + LONG2CHARS( 0x00000000007FFFF8 ), + LONG2CHARS( 0x00000000007FFFFC ), + LONG2CHARS( 0x00000000007FFFFE ), + LONG2CHARS( 0x00000000007FFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000200000 ), + LONG2CHARS( 0x0000000000300000 ), + LONG2CHARS( 0x0000000000380000 ), + LONG2CHARS( 0x00000000003C0000 ), + LONG2CHARS( 0x00000000003E0000 ), + LONG2CHARS( 0x00000000003F0000 ), + LONG2CHARS( 0x00000000003F8000 ), + LONG2CHARS( 0x00000000003FC000 ), + LONG2CHARS( 0x00000000003FE000 ), + LONG2CHARS( 0x00000000003FF000 ), + LONG2CHARS( 0x00000000003FF800 ), + LONG2CHARS( 0x00000000003FFC00 ), + LONG2CHARS( 0x00000000003FFE00 ), + LONG2CHARS( 0x00000000003FFF00 ), + LONG2CHARS( 0x00000000003FFF80 ), + LONG2CHARS( 0x00000000003FFFC0 ), + LONG2CHARS( 0x00000000003FFFE0 ), + LONG2CHARS( 0x00000000003FFFF0 ), + LONG2CHARS( 0x00000000003FFFF8 ), + LONG2CHARS( 0x00000000003FFFFC ), + LONG2CHARS( 0x00000000003FFFFE ), + LONG2CHARS( 0x00000000003FFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000100000 ), + LONG2CHARS( 0x0000000000180000 ), + LONG2CHARS( 0x00000000001C0000 ), + LONG2CHARS( 0x00000000001E0000 ), + LONG2CHARS( 0x00000000001F0000 ), + LONG2CHARS( 0x00000000001F8000 ), + LONG2CHARS( 0x00000000001FC000 ), + LONG2CHARS( 0x00000000001FE000 ), + LONG2CHARS( 0x00000000001FF000 ), + LONG2CHARS( 0x00000000001FF800 ), + LONG2CHARS( 0x00000000001FFC00 ), + LONG2CHARS( 0x00000000001FFE00 ), + LONG2CHARS( 0x00000000001FFF00 ), + LONG2CHARS( 0x00000000001FFF80 ), + LONG2CHARS( 0x00000000001FFFC0 ), + LONG2CHARS( 0x00000000001FFFE0 ), + LONG2CHARS( 0x00000000001FFFF0 ), + LONG2CHARS( 0x00000000001FFFF8 ), + LONG2CHARS( 0x00000000001FFFFC ), + LONG2CHARS( 0x00000000001FFFFE ), + LONG2CHARS( 0x00000000001FFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000080000 ), + LONG2CHARS( 0x00000000000C0000 ), + LONG2CHARS( 0x00000000000E0000 ), + LONG2CHARS( 0x00000000000F0000 ), + LONG2CHARS( 0x00000000000F8000 ), + LONG2CHARS( 0x00000000000FC000 ), + LONG2CHARS( 0x00000000000FE000 ), + LONG2CHARS( 0x00000000000FF000 ), + LONG2CHARS( 0x00000000000FF800 ), + LONG2CHARS( 0x00000000000FFC00 ), + LONG2CHARS( 0x00000000000FFE00 ), + LONG2CHARS( 0x00000000000FFF00 ), + LONG2CHARS( 0x00000000000FFF80 ), + LONG2CHARS( 0x00000000000FFFC0 ), + LONG2CHARS( 0x00000000000FFFE0 ), + LONG2CHARS( 0x00000000000FFFF0 ), + LONG2CHARS( 0x00000000000FFFF8 ), + LONG2CHARS( 0x00000000000FFFFC ), + LONG2CHARS( 0x00000000000FFFFE ), + LONG2CHARS( 0x00000000000FFFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000040000 ), + LONG2CHARS( 0x0000000000060000 ), + LONG2CHARS( 0x0000000000070000 ), + LONG2CHARS( 0x0000000000078000 ), + LONG2CHARS( 0x000000000007C000 ), + LONG2CHARS( 0x000000000007E000 ), + LONG2CHARS( 0x000000000007F000 ), + LONG2CHARS( 0x000000000007F800 ), + LONG2CHARS( 0x000000000007FC00 ), + LONG2CHARS( 0x000000000007FE00 ), + LONG2CHARS( 0x000000000007FF00 ), + LONG2CHARS( 0x000000000007FF80 ), + LONG2CHARS( 0x000000000007FFC0 ), + LONG2CHARS( 0x000000000007FFE0 ), + LONG2CHARS( 0x000000000007FFF0 ), + LONG2CHARS( 0x000000000007FFF8 ), + LONG2CHARS( 0x000000000007FFFC ), + LONG2CHARS( 0x000000000007FFFE ), + LONG2CHARS( 0x000000000007FFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000020000 ), + LONG2CHARS( 0x0000000000030000 ), + LONG2CHARS( 0x0000000000038000 ), + LONG2CHARS( 0x000000000003C000 ), + LONG2CHARS( 0x000000000003E000 ), + LONG2CHARS( 0x000000000003F000 ), + LONG2CHARS( 0x000000000003F800 ), + LONG2CHARS( 0x000000000003FC00 ), + LONG2CHARS( 0x000000000003FE00 ), + LONG2CHARS( 0x000000000003FF00 ), + LONG2CHARS( 0x000000000003FF80 ), + LONG2CHARS( 0x000000000003FFC0 ), + LONG2CHARS( 0x000000000003FFE0 ), + LONG2CHARS( 0x000000000003FFF0 ), + LONG2CHARS( 0x000000000003FFF8 ), + LONG2CHARS( 0x000000000003FFFC ), + LONG2CHARS( 0x000000000003FFFE ), + LONG2CHARS( 0x000000000003FFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000010000 ), + LONG2CHARS( 0x0000000000018000 ), + LONG2CHARS( 0x000000000001C000 ), + LONG2CHARS( 0x000000000001E000 ), + LONG2CHARS( 0x000000000001F000 ), + LONG2CHARS( 0x000000000001F800 ), + LONG2CHARS( 0x000000000001FC00 ), + LONG2CHARS( 0x000000000001FE00 ), + LONG2CHARS( 0x000000000001FF00 ), + LONG2CHARS( 0x000000000001FF80 ), + LONG2CHARS( 0x000000000001FFC0 ), + LONG2CHARS( 0x000000000001FFE0 ), + LONG2CHARS( 0x000000000001FFF0 ), + LONG2CHARS( 0x000000000001FFF8 ), + LONG2CHARS( 0x000000000001FFFC ), + LONG2CHARS( 0x000000000001FFFE ), + LONG2CHARS( 0x000000000001FFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000008000 ), + LONG2CHARS( 0x000000000000C000 ), + LONG2CHARS( 0x000000000000E000 ), + LONG2CHARS( 0x000000000000F000 ), + LONG2CHARS( 0x000000000000F800 ), + LONG2CHARS( 0x000000000000FC00 ), + LONG2CHARS( 0x000000000000FE00 ), + LONG2CHARS( 0x000000000000FF00 ), + LONG2CHARS( 0x000000000000FF80 ), + LONG2CHARS( 0x000000000000FFC0 ), + LONG2CHARS( 0x000000000000FFE0 ), + LONG2CHARS( 0x000000000000FFF0 ), + LONG2CHARS( 0x000000000000FFF8 ), + LONG2CHARS( 0x000000000000FFFC ), + LONG2CHARS( 0x000000000000FFFE ), + LONG2CHARS( 0x000000000000FFFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000004000 ), + LONG2CHARS( 0x0000000000006000 ), + LONG2CHARS( 0x0000000000007000 ), + LONG2CHARS( 0x0000000000007800 ), + LONG2CHARS( 0x0000000000007C00 ), + LONG2CHARS( 0x0000000000007E00 ), + LONG2CHARS( 0x0000000000007F00 ), + LONG2CHARS( 0x0000000000007F80 ), + LONG2CHARS( 0x0000000000007FC0 ), + LONG2CHARS( 0x0000000000007FE0 ), + LONG2CHARS( 0x0000000000007FF0 ), + LONG2CHARS( 0x0000000000007FF8 ), + LONG2CHARS( 0x0000000000007FFC ), + LONG2CHARS( 0x0000000000007FFE ), + LONG2CHARS( 0x0000000000007FFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000002000 ), + LONG2CHARS( 0x0000000000003000 ), + LONG2CHARS( 0x0000000000003800 ), + LONG2CHARS( 0x0000000000003C00 ), + LONG2CHARS( 0x0000000000003E00 ), + LONG2CHARS( 0x0000000000003F00 ), + LONG2CHARS( 0x0000000000003F80 ), + LONG2CHARS( 0x0000000000003FC0 ), + LONG2CHARS( 0x0000000000003FE0 ), + LONG2CHARS( 0x0000000000003FF0 ), + LONG2CHARS( 0x0000000000003FF8 ), + LONG2CHARS( 0x0000000000003FFC ), + LONG2CHARS( 0x0000000000003FFE ), + LONG2CHARS( 0x0000000000003FFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000001000 ), + LONG2CHARS( 0x0000000000001800 ), + LONG2CHARS( 0x0000000000001C00 ), + LONG2CHARS( 0x0000000000001E00 ), + LONG2CHARS( 0x0000000000001F00 ), + LONG2CHARS( 0x0000000000001F80 ), + LONG2CHARS( 0x0000000000001FC0 ), + LONG2CHARS( 0x0000000000001FE0 ), + LONG2CHARS( 0x0000000000001FF0 ), + LONG2CHARS( 0x0000000000001FF8 ), + LONG2CHARS( 0x0000000000001FFC ), + LONG2CHARS( 0x0000000000001FFE ), + LONG2CHARS( 0x0000000000001FFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000800 ), + LONG2CHARS( 0x0000000000000C00 ), + LONG2CHARS( 0x0000000000000E00 ), + LONG2CHARS( 0x0000000000000F00 ), + LONG2CHARS( 0x0000000000000F80 ), + LONG2CHARS( 0x0000000000000FC0 ), + LONG2CHARS( 0x0000000000000FE0 ), + LONG2CHARS( 0x0000000000000FF0 ), + LONG2CHARS( 0x0000000000000FF8 ), + LONG2CHARS( 0x0000000000000FFC ), + LONG2CHARS( 0x0000000000000FFE ), + LONG2CHARS( 0x0000000000000FFF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000400 ), + LONG2CHARS( 0x0000000000000600 ), + LONG2CHARS( 0x0000000000000700 ), + LONG2CHARS( 0x0000000000000780 ), + LONG2CHARS( 0x00000000000007C0 ), + LONG2CHARS( 0x00000000000007E0 ), + LONG2CHARS( 0x00000000000007F0 ), + LONG2CHARS( 0x00000000000007F8 ), + LONG2CHARS( 0x00000000000007FC ), + LONG2CHARS( 0x00000000000007FE ), + LONG2CHARS( 0x00000000000007FF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000200 ), + LONG2CHARS( 0x0000000000000300 ), + LONG2CHARS( 0x0000000000000380 ), + LONG2CHARS( 0x00000000000003C0 ), + LONG2CHARS( 0x00000000000003E0 ), + LONG2CHARS( 0x00000000000003F0 ), + LONG2CHARS( 0x00000000000003F8 ), + LONG2CHARS( 0x00000000000003FC ), + LONG2CHARS( 0x00000000000003FE ), + LONG2CHARS( 0x00000000000003FF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000100 ), + LONG2CHARS( 0x0000000000000180 ), + LONG2CHARS( 0x00000000000001C0 ), + LONG2CHARS( 0x00000000000001E0 ), + LONG2CHARS( 0x00000000000001F0 ), + LONG2CHARS( 0x00000000000001F8 ), + LONG2CHARS( 0x00000000000001FC ), + LONG2CHARS( 0x00000000000001FE ), + LONG2CHARS( 0x00000000000001FF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000080 ), + LONG2CHARS( 0x00000000000000C0 ), + LONG2CHARS( 0x00000000000000E0 ), + LONG2CHARS( 0x00000000000000F0 ), + LONG2CHARS( 0x00000000000000F8 ), + LONG2CHARS( 0x00000000000000FC ), + LONG2CHARS( 0x00000000000000FE ), + LONG2CHARS( 0x00000000000000FF ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000040 ), + LONG2CHARS( 0x0000000000000060 ), + LONG2CHARS( 0x0000000000000070 ), + LONG2CHARS( 0x0000000000000078 ), + LONG2CHARS( 0x000000000000007C ), + LONG2CHARS( 0x000000000000007E ), + LONG2CHARS( 0x000000000000007F ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000020 ), + LONG2CHARS( 0x0000000000000030 ), + LONG2CHARS( 0x0000000000000038 ), + LONG2CHARS( 0x000000000000003C ), + LONG2CHARS( 0x000000000000003E ), + LONG2CHARS( 0x000000000000003F ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000010 ), + LONG2CHARS( 0x0000000000000018 ), + LONG2CHARS( 0x000000000000001C ), + LONG2CHARS( 0x000000000000001E ), + LONG2CHARS( 0x000000000000001F ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000008 ), + LONG2CHARS( 0x000000000000000C ), + LONG2CHARS( 0x000000000000000E ), + LONG2CHARS( 0x000000000000000F ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000004 ), + LONG2CHARS( 0x0000000000000006 ), + LONG2CHARS( 0x0000000000000007 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000002 ), + LONG2CHARS( 0x0000000000000003 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000001 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, +}; +#endif /* PPW */ + +#else /* LSBFirst */ +/* NOTE: +the first element in starttab could be LONG2CHARS( 0xffffffff. making it 0 +lets us deal with a full first word in the middle loop ), rather +than having to do the multiple reads and masks that we'd +have to do if we thought it was partial. +*/ +PixelType starttab[PPW+1] = + { +#if PPW == 32 + LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0xFFFFFFFE ), + LONG2CHARS( 0xFFFFFFFC ), + LONG2CHARS( 0xFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFC0 ), + LONG2CHARS( 0xFFFFFF80 ), + LONG2CHARS( 0xFFFFFF00 ), + LONG2CHARS( 0xFFFFFE00 ), + LONG2CHARS( 0xFFFFFC00 ), + LONG2CHARS( 0xFFFFF800 ), + LONG2CHARS( 0xFFFFF000 ), + LONG2CHARS( 0xFFFFE000 ), + LONG2CHARS( 0xFFFFC000 ), + LONG2CHARS( 0xFFFF8000 ), + LONG2CHARS( 0xFFFF0000 ), + LONG2CHARS( 0xFFFE0000 ), + LONG2CHARS( 0xFFFC0000 ), + LONG2CHARS( 0xFFF80000 ), + LONG2CHARS( 0xFFF00000 ), + LONG2CHARS( 0xFFE00000 ), + LONG2CHARS( 0xFFC00000 ), + LONG2CHARS( 0xFF800000 ), + LONG2CHARS( 0xFF000000 ), + LONG2CHARS( 0xFE000000 ), + LONG2CHARS( 0xFC000000 ), + LONG2CHARS( 0xF8000000 ), + LONG2CHARS( 0xF0000000 ), + LONG2CHARS( 0xE0000000 ), + LONG2CHARS( 0xC0000000 ), + LONG2CHARS( 0x80000000 ), + LONG2CHARS( 0x00000000 ) +#else /* PPW == 64 */ + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFE ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFC ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFC0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF80 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFE00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFC00 ), + LONG2CHARS( 0xFFFFFFFFFFFFF800 ), + LONG2CHARS( 0xFFFFFFFFFFFFF000 ), + LONG2CHARS( 0xFFFFFFFFFFFFE000 ), + LONG2CHARS( 0xFFFFFFFFFFFFC000 ), + LONG2CHARS( 0xFFFFFFFFFFFF8000 ), + LONG2CHARS( 0xFFFFFFFFFFFF0000 ), + LONG2CHARS( 0xFFFFFFFFFFFE0000 ), + LONG2CHARS( 0xFFFFFFFFFFFC0000 ), + LONG2CHARS( 0xFFFFFFFFFFF80000 ), + LONG2CHARS( 0xFFFFFFFFFFF00000 ), + LONG2CHARS( 0xFFFFFFFFFFE00000 ), + LONG2CHARS( 0xFFFFFFFFFFC00000 ), + LONG2CHARS( 0xFFFFFFFFFF800000 ), + LONG2CHARS( 0xFFFFFFFFFF000000 ), + LONG2CHARS( 0xFFFFFFFFFE000000 ), + LONG2CHARS( 0xFFFFFFFFFC000000 ), + LONG2CHARS( 0xFFFFFFFFF8000000 ), + LONG2CHARS( 0xFFFFFFFFF0000000 ), + LONG2CHARS( 0xFFFFFFFFE0000000 ), + LONG2CHARS( 0xFFFFFFFFC0000000 ), + LONG2CHARS( 0xFFFFFFFF80000000 ), + LONG2CHARS( 0xFFFFFFFF00000000 ), + LONG2CHARS( 0xFFFFFFFE00000000 ), + LONG2CHARS( 0xFFFFFFFC00000000 ), + LONG2CHARS( 0xFFFFFFF800000000 ), + LONG2CHARS( 0xFFFFFFF000000000 ), + LONG2CHARS( 0xFFFFFFE000000000 ), + LONG2CHARS( 0xFFFFFFC000000000 ), + LONG2CHARS( 0xFFFFFF8000000000 ), + LONG2CHARS( 0xFFFFFF0000000000 ), + LONG2CHARS( 0xFFFFFE0000000000 ), + LONG2CHARS( 0xFFFFFC0000000000 ), + LONG2CHARS( 0xFFFFF80000000000 ), + LONG2CHARS( 0xFFFFF00000000000 ), + LONG2CHARS( 0xFFFFE00000000000 ), + LONG2CHARS( 0xFFFFC00000000000 ), + LONG2CHARS( 0xFFFF800000000000 ), + LONG2CHARS( 0xFFFF000000000000 ), + LONG2CHARS( 0xFFFE000000000000 ), + LONG2CHARS( 0xFFFC000000000000 ), + LONG2CHARS( 0xFFF8000000000000 ), + LONG2CHARS( 0xFFF0000000000000 ), + LONG2CHARS( 0xFFE0000000000000 ), + LONG2CHARS( 0xFFC0000000000000 ), + LONG2CHARS( 0xFF80000000000000 ), + LONG2CHARS( 0xFF00000000000000 ), + LONG2CHARS( 0xFE00000000000000 ), + LONG2CHARS( 0xFC00000000000000 ), + LONG2CHARS( 0xF800000000000000 ), + LONG2CHARS( 0xF000000000000000 ), + LONG2CHARS( 0xE000000000000000 ), + LONG2CHARS( 0xC000000000000000 ), + LONG2CHARS( 0x8000000000000000 ), + LONG2CHARS( 0x0000000000000000 ) +#endif /* PPW */ + }; + +PixelType endtab[PPW+1] = + { + LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0x00000001 ), + LONG2CHARS( 0x00000003 ), + LONG2CHARS( 0x00000007 ), + LONG2CHARS( 0x0000000F ), + LONG2CHARS( 0x0000001F ), + LONG2CHARS( 0x0000003F ), + LONG2CHARS( 0x0000007F ), + LONG2CHARS( 0x000000FF ), + LONG2CHARS( 0x000001FF ), + LONG2CHARS( 0x000003FF ), + LONG2CHARS( 0x000007FF ), + LONG2CHARS( 0x00000FFF ), + LONG2CHARS( 0x00001FFF ), + LONG2CHARS( 0x00003FFF ), + LONG2CHARS( 0x00007FFF ), + LONG2CHARS( 0x0000FFFF ), + LONG2CHARS( 0x0001FFFF ), + LONG2CHARS( 0x0003FFFF ), + LONG2CHARS( 0x0007FFFF ), + LONG2CHARS( 0x000FFFFF ), + LONG2CHARS( 0x001FFFFF ), + LONG2CHARS( 0x003FFFFF ), + LONG2CHARS( 0x007FFFFF ), + LONG2CHARS( 0x00FFFFFF ), + LONG2CHARS( 0x01FFFFFF ), + LONG2CHARS( 0x03FFFFFF ), + LONG2CHARS( 0x07FFFFFF ), + LONG2CHARS( 0x0FFFFFFF ), + LONG2CHARS( 0x1FFFFFFF ), + LONG2CHARS( 0x3FFFFFFF ), + LONG2CHARS( 0x7FFFFFFF ), + LONG2CHARS( 0xFFFFFFFF ) +#if PPW == 64 + , + LONG2CHARS( 0x00000001FFFFFFFF ), + LONG2CHARS( 0x00000003FFFFFFFF ), + LONG2CHARS( 0x00000007FFFFFFFF ), + LONG2CHARS( 0x0000000FFFFFFFFF ), + LONG2CHARS( 0x0000001FFFFFFFFF ), + LONG2CHARS( 0x0000003FFFFFFFFF ), + LONG2CHARS( 0x0000007FFFFFFFFF ), + LONG2CHARS( 0x000000FFFFFFFFFF ), + LONG2CHARS( 0x000001FFFFFFFFFF ), + LONG2CHARS( 0x000003FFFFFFFFFF ), + LONG2CHARS( 0x000007FFFFFFFFFF ), + LONG2CHARS( 0x00000FFFFFFFFFFF ), + LONG2CHARS( 0x00001FFFFFFFFFFF ), + LONG2CHARS( 0x00003FFFFFFFFFFF ), + LONG2CHARS( 0x00007FFFFFFFFFFF ), + LONG2CHARS( 0x0000FFFFFFFFFFFF ), + LONG2CHARS( 0x0001FFFFFFFFFFFF ), + LONG2CHARS( 0x0003FFFFFFFFFFFF ), + LONG2CHARS( 0x0007FFFFFFFFFFFF ), + LONG2CHARS( 0x000FFFFFFFFFFFFF ), + LONG2CHARS( 0x001FFFFFFFFFFFFF ), + LONG2CHARS( 0x003FFFFFFFFFFFFF ), + LONG2CHARS( 0x007FFFFFFFFFFFFF ), + LONG2CHARS( 0x00FFFFFFFFFFFFFF ), + LONG2CHARS( 0x01FFFFFFFFFFFFFF ), + LONG2CHARS( 0x03FFFFFFFFFFFFFF ), + LONG2CHARS( 0x07FFFFFFFFFFFFFF ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x7FFFFFFFFFFFFFFF ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFF ) +#endif /* PPW */ + }; + +#ifndef LOWMEMFTPT + +#ifdef NEED_OLD_MFB_MASKS +/* a hack ), for now, since the entries for 0 need to be all + 1 bits ), not all zeros. + this means the code DOES NOT WORK for segments of length + 0 (which is only a problem in the horizontal line code.) +*/ +PixelType startpartial[33] = + { + LONG2CHARS( 0xFFFFFFFF ), + LONG2CHARS( 0xFFFFFFFE ), + LONG2CHARS( 0xFFFFFFFC ), + LONG2CHARS( 0xFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFC0 ), + LONG2CHARS( 0xFFFFFF80 ), + LONG2CHARS( 0xFFFFFF00 ), + LONG2CHARS( 0xFFFFFE00 ), + LONG2CHARS( 0xFFFFFC00 ), + LONG2CHARS( 0xFFFFF800 ), + LONG2CHARS( 0xFFFFF000 ), + LONG2CHARS( 0xFFFFE000 ), + LONG2CHARS( 0xFFFFC000 ), + LONG2CHARS( 0xFFFF8000 ), + LONG2CHARS( 0xFFFF0000 ), + LONG2CHARS( 0xFFFE0000 ), + LONG2CHARS( 0xFFFC0000 ), + LONG2CHARS( 0xFFF80000 ), + LONG2CHARS( 0xFFF00000 ), + LONG2CHARS( 0xFFE00000 ), + LONG2CHARS( 0xFFC00000 ), + LONG2CHARS( 0xFF800000 ), + LONG2CHARS( 0xFF000000 ), + LONG2CHARS( 0xFE000000 ), + LONG2CHARS( 0xFC000000 ), + LONG2CHARS( 0xF8000000 ), + LONG2CHARS( 0xF0000000 ), + LONG2CHARS( 0xE0000000 ), + LONG2CHARS( 0xC0000000 ), + LONG2CHARS( 0x80000000 ), + LONG2CHARS( 0x00000000 ) + }; + +PixelType endpartial[33] = + { + LONG2CHARS( 0xFFFFFFFF ), + LONG2CHARS( 0x00000001 ), + LONG2CHARS( 0x00000003 ), + LONG2CHARS( 0x00000007 ), + LONG2CHARS( 0x0000000F ), + LONG2CHARS( 0x0000001F ), + LONG2CHARS( 0x0000003F ), + LONG2CHARS( 0x0000007F ), + LONG2CHARS( 0x000000FF ), + LONG2CHARS( 0x000001FF ), + LONG2CHARS( 0x000003FF ), + LONG2CHARS( 0x000007FF ), + LONG2CHARS( 0x00000FFF ), + LONG2CHARS( 0x00001FFF ), + LONG2CHARS( 0x00003FFF ), + LONG2CHARS( 0x00007FFF ), + LONG2CHARS( 0x0000FFFF ), + LONG2CHARS( 0x0001FFFF ), + LONG2CHARS( 0x0003FFFF ), + LONG2CHARS( 0x0007FFFF ), + LONG2CHARS( 0x000FFFFF ), + LONG2CHARS( 0x001FFFFF ), + LONG2CHARS( 0x003FFFFF ), + LONG2CHARS( 0x007FFFFF ), + LONG2CHARS( 0x00FFFFFF ), + LONG2CHARS( 0x01FFFFFF ), + LONG2CHARS( 0x03FFFFFF ), + LONG2CHARS( 0x07FFFFFF ), + LONG2CHARS( 0x0FFFFFFF ), + LONG2CHARS( 0x1FFFFFFF ), + LONG2CHARS( 0x3FFFFFFF ), + LONG2CHARS( 0x7FFFFFFF ), + LONG2CHARS( 0xFFFFFFFF ) + }; +#endif + +#endif /* ifndef LOWMEMFTPT */ + +#if PPW == 32 +PixelType partmasks[PPW][PPW] = { + {LONG2CHARS( 0xFFFFFFFF ), LONG2CHARS( 0x00000001 ), LONG2CHARS( 0x00000003 ), LONG2CHARS( 0x00000007 ), + LONG2CHARS( 0x0000000F ), LONG2CHARS( 0x0000001F ), LONG2CHARS( 0x0000003F ), LONG2CHARS( 0x0000007F ), + LONG2CHARS( 0x000000FF ), LONG2CHARS( 0x000001FF ), LONG2CHARS( 0x000003FF ), LONG2CHARS( 0x000007FF ), + LONG2CHARS( 0x00000FFF ), LONG2CHARS( 0x00001FFF ), LONG2CHARS( 0x00003FFF ), LONG2CHARS( 0x00007FFF ), + LONG2CHARS( 0x0000FFFF ), LONG2CHARS( 0x0001FFFF ), LONG2CHARS( 0x0003FFFF ), LONG2CHARS( 0x0007FFFF ), + LONG2CHARS( 0x000FFFFF ), LONG2CHARS( 0x001FFFFF ), LONG2CHARS( 0x003FFFFF ), LONG2CHARS( 0x007FFFFF ), + LONG2CHARS( 0x00FFFFFF ), LONG2CHARS( 0x01FFFFFF ), LONG2CHARS( 0x03FFFFFF ), LONG2CHARS( 0x07FFFFFF ), + LONG2CHARS( 0x0FFFFFFF ), LONG2CHARS( 0x1FFFFFFF ), LONG2CHARS( 0x3FFFFFFF ), LONG2CHARS( 0x7FFFFFFF )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000002 ), LONG2CHARS( 0x00000006 ), LONG2CHARS( 0x0000000E ), + LONG2CHARS( 0x0000001E ), LONG2CHARS( 0x0000003E ), LONG2CHARS( 0x0000007E ), LONG2CHARS( 0x000000FE ), + LONG2CHARS( 0x000001FE ), LONG2CHARS( 0x000003FE ), LONG2CHARS( 0x000007FE ), LONG2CHARS( 0x00000FFE ), + LONG2CHARS( 0x00001FFE ), LONG2CHARS( 0x00003FFE ), LONG2CHARS( 0x00007FFE ), LONG2CHARS( 0x0000FFFE ), + LONG2CHARS( 0x0001FFFE ), LONG2CHARS( 0x0003FFFE ), LONG2CHARS( 0x0007FFFE ), LONG2CHARS( 0x000FFFFE ), + LONG2CHARS( 0x001FFFFE ), LONG2CHARS( 0x003FFFFE ), LONG2CHARS( 0x007FFFFE ), LONG2CHARS( 0x00FFFFFE ), + LONG2CHARS( 0x01FFFFFE ), LONG2CHARS( 0x03FFFFFE ), LONG2CHARS( 0x07FFFFFE ), LONG2CHARS( 0x0FFFFFFE ), + LONG2CHARS( 0x1FFFFFFE ), LONG2CHARS( 0x3FFFFFFE ), LONG2CHARS( 0x7FFFFFFE ), LONG2CHARS( 0xFFFFFFFE )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000004 ), LONG2CHARS( 0x0000000C ), LONG2CHARS( 0x0000001C ), + LONG2CHARS( 0x0000003C ), LONG2CHARS( 0x0000007C ), LONG2CHARS( 0x000000FC ), LONG2CHARS( 0x000001FC ), + LONG2CHARS( 0x000003FC ), LONG2CHARS( 0x000007FC ), LONG2CHARS( 0x00000FFC ), LONG2CHARS( 0x00001FFC ), + LONG2CHARS( 0x00003FFC ), LONG2CHARS( 0x00007FFC ), LONG2CHARS( 0x0000FFFC ), LONG2CHARS( 0x0001FFFC ), + LONG2CHARS( 0x0003FFFC ), LONG2CHARS( 0x0007FFFC ), LONG2CHARS( 0x000FFFFC ), LONG2CHARS( 0x001FFFFC ), + LONG2CHARS( 0x003FFFFC ), LONG2CHARS( 0x007FFFFC ), LONG2CHARS( 0x00FFFFFC ), LONG2CHARS( 0x01FFFFFC ), + LONG2CHARS( 0x03FFFFFC ), LONG2CHARS( 0x07FFFFFC ), LONG2CHARS( 0x0FFFFFFC ), LONG2CHARS( 0x1FFFFFFC ), + LONG2CHARS( 0x3FFFFFFC ), LONG2CHARS( 0x7FFFFFFC ), LONG2CHARS( 0xFFFFFFFC ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000008 ), LONG2CHARS( 0x00000018 ), LONG2CHARS( 0x00000038 ), + LONG2CHARS( 0x00000078 ), LONG2CHARS( 0x000000F8 ), LONG2CHARS( 0x000001F8 ), LONG2CHARS( 0x000003F8 ), + LONG2CHARS( 0x000007F8 ), LONG2CHARS( 0x00000FF8 ), LONG2CHARS( 0x00001FF8 ), LONG2CHARS( 0x00003FF8 ), + LONG2CHARS( 0X00007FF8 ), LONG2CHARS( 0x0000FFF8 ), LONG2CHARS( 0x0001FFF8 ), LONG2CHARS( 0x0003FFF8 ), + LONG2CHARS( 0X0007FFF8 ), LONG2CHARS( 0x000FFFF8 ), LONG2CHARS( 0x001FFFF8 ), LONG2CHARS( 0x003FFFF8 ), + LONG2CHARS( 0X007FFFF8 ), LONG2CHARS( 0x00FFFFF8 ), LONG2CHARS( 0x01FFFFF8 ), LONG2CHARS( 0x03FFFFF8 ), + LONG2CHARS( 0X07FFFFF8 ), LONG2CHARS( 0x0FFFFFF8 ), LONG2CHARS( 0x1FFFFFF8 ), LONG2CHARS( 0x3FFFFFF8 ), + LONG2CHARS( 0X7FFFFFF8 ), LONG2CHARS( 0xFFFFFFF8 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000010 ), LONG2CHARS( 0x00000030 ), LONG2CHARS( 0x00000070 ), + LONG2CHARS( 0X000000F0 ), LONG2CHARS( 0x000001F0 ), LONG2CHARS( 0x000003F0 ), LONG2CHARS( 0x000007F0 ), + LONG2CHARS( 0X00000FF0 ), LONG2CHARS( 0x00001FF0 ), LONG2CHARS( 0x00003FF0 ), LONG2CHARS( 0x00007FF0 ), + LONG2CHARS( 0X0000FFF0 ), LONG2CHARS( 0x0001FFF0 ), LONG2CHARS( 0x0003FFF0 ), LONG2CHARS( 0x0007FFF0 ), + LONG2CHARS( 0X000FFFF0 ), LONG2CHARS( 0x001FFFF0 ), LONG2CHARS( 0x003FFFF0 ), LONG2CHARS( 0x007FFFF0 ), + LONG2CHARS( 0X00FFFFF0 ), LONG2CHARS( 0x01FFFFF0 ), LONG2CHARS( 0x03FFFFF0 ), LONG2CHARS( 0x07FFFFF0 ), + LONG2CHARS( 0X0FFFFFF0 ), LONG2CHARS( 0x1FFFFFF0 ), LONG2CHARS( 0x3FFFFFF0 ), LONG2CHARS( 0x7FFFFFF0 ), + LONG2CHARS( 0XFFFFFFF0 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000020 ), LONG2CHARS( 0x00000060 ), LONG2CHARS( 0x000000E0 ), + LONG2CHARS( 0X000001E0 ), LONG2CHARS( 0x000003E0 ), LONG2CHARS( 0x000007E0 ), LONG2CHARS( 0x00000FE0 ), + LONG2CHARS( 0X00001FE0 ), LONG2CHARS( 0x00003FE0 ), LONG2CHARS( 0x00007FE0 ), LONG2CHARS( 0x0000FFE0 ), + LONG2CHARS( 0X0001FFE0 ), LONG2CHARS( 0x0003FFE0 ), LONG2CHARS( 0x0007FFE0 ), LONG2CHARS( 0x000FFFE0 ), + LONG2CHARS( 0X001FFFE0 ), LONG2CHARS( 0x003FFFE0 ), LONG2CHARS( 0x007FFFE0 ), LONG2CHARS( 0x00FFFFE0 ), + LONG2CHARS( 0X01FFFFE0 ), LONG2CHARS( 0x03FFFFE0 ), LONG2CHARS( 0x07FFFFE0 ), LONG2CHARS( 0x0FFFFFE0 ), + LONG2CHARS( 0X1FFFFFE0 ), LONG2CHARS( 0x3FFFFFE0 ), LONG2CHARS( 0x7FFFFFE0 ), LONG2CHARS( 0xFFFFFFE0 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000040 ), LONG2CHARS( 0x000000C0 ), LONG2CHARS( 0x000001C0 ), + LONG2CHARS( 0X000003C0 ), LONG2CHARS( 0x000007C0 ), LONG2CHARS( 0x00000FC0 ), LONG2CHARS( 0x00001FC0 ), + LONG2CHARS( 0X00003FC0 ), LONG2CHARS( 0x00007FC0 ), LONG2CHARS( 0x0000FFC0 ), LONG2CHARS( 0x0001FFC0 ), + LONG2CHARS( 0X0003FFC0 ), LONG2CHARS( 0x0007FFC0 ), LONG2CHARS( 0x000FFFC0 ), LONG2CHARS( 0x001FFFC0 ), + LONG2CHARS( 0X003FFFC0 ), LONG2CHARS( 0x007FFFC0 ), LONG2CHARS( 0x00FFFFC0 ), LONG2CHARS( 0x01FFFFC0 ), + LONG2CHARS( 0X03FFFFC0 ), LONG2CHARS( 0x07FFFFC0 ), LONG2CHARS( 0x0FFFFFC0 ), LONG2CHARS( 0x1FFFFFC0 ), + LONG2CHARS( 0X3FFFFFC0 ), LONG2CHARS( 0x7FFFFFC0 ), LONG2CHARS( 0xFFFFFFC0 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000080 ), LONG2CHARS( 0x00000180 ), LONG2CHARS( 0x00000380 ), + LONG2CHARS( 0X00000780 ), LONG2CHARS( 0x00000F80 ), LONG2CHARS( 0x00001F80 ), LONG2CHARS( 0x00003F80 ), + LONG2CHARS( 0X00007F80 ), LONG2CHARS( 0x0000FF80 ), LONG2CHARS( 0x0001FF80 ), LONG2CHARS( 0x0003FF80 ), + LONG2CHARS( 0X0007FF80 ), LONG2CHARS( 0x000FFF80 ), LONG2CHARS( 0x001FFF80 ), LONG2CHARS( 0x003FFF80 ), + LONG2CHARS( 0X007FFF80 ), LONG2CHARS( 0x00FFFF80 ), LONG2CHARS( 0x01FFFF80 ), LONG2CHARS( 0x03FFFF80 ), + LONG2CHARS( 0X07FFFF80 ), LONG2CHARS( 0x0FFFFF80 ), LONG2CHARS( 0x1FFFFF80 ), LONG2CHARS( 0x3FFFFF80 ), + LONG2CHARS( 0X7FFFFF80 ), LONG2CHARS( 0xFFFFFF80 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000100 ), LONG2CHARS( 0x00000300 ), LONG2CHARS( 0x00000700 ), + LONG2CHARS( 0X00000F00 ), LONG2CHARS( 0x00001F00 ), LONG2CHARS( 0x00003F00 ), LONG2CHARS( 0x00007F00 ), + LONG2CHARS( 0X0000FF00 ), LONG2CHARS( 0x0001FF00 ), LONG2CHARS( 0x0003FF00 ), LONG2CHARS( 0x0007FF00 ), + LONG2CHARS( 0X000FFF00 ), LONG2CHARS( 0x001FFF00 ), LONG2CHARS( 0x003FFF00 ), LONG2CHARS( 0x007FFF00 ), + LONG2CHARS( 0X00FFFF00 ), LONG2CHARS( 0x01FFFF00 ), LONG2CHARS( 0x03FFFF00 ), LONG2CHARS( 0x07FFFF00 ), + LONG2CHARS( 0X0FFFFF00 ), LONG2CHARS( 0x1FFFFF00 ), LONG2CHARS( 0x3FFFFF00 ), LONG2CHARS( 0x7FFFFF00 ), + LONG2CHARS( 0XFFFFFF00 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000200 ), LONG2CHARS( 0x00000600 ), LONG2CHARS( 0x00000E00 ), + LONG2CHARS( 0X00001E00 ), LONG2CHARS( 0x00003E00 ), LONG2CHARS( 0x00007E00 ), LONG2CHARS( 0x0000FE00 ), + LONG2CHARS( 0X0001FE00 ), LONG2CHARS( 0x0003FE00 ), LONG2CHARS( 0x0007FE00 ), LONG2CHARS( 0x000FFE00 ), + LONG2CHARS( 0X001FFE00 ), LONG2CHARS( 0x003FFE00 ), LONG2CHARS( 0x007FFE00 ), LONG2CHARS( 0x00FFFE00 ), + LONG2CHARS( 0X01FFFE00 ), LONG2CHARS( 0x03FFFE00 ), LONG2CHARS( 0x07FFFE00 ), LONG2CHARS( 0x0FFFFE00 ), + LONG2CHARS( 0X1FFFFE00 ), LONG2CHARS( 0x3FFFFE00 ), LONG2CHARS( 0x7FFFFE00 ), LONG2CHARS( 0xFFFFFE00 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000400 ), LONG2CHARS( 0x00000C00 ), LONG2CHARS( 0x00001C00 ), + LONG2CHARS( 0X00003C00 ), LONG2CHARS( 0x00007C00 ), LONG2CHARS( 0x0000FC00 ), LONG2CHARS( 0x0001FC00 ), + LONG2CHARS( 0X0003FC00 ), LONG2CHARS( 0x0007FC00 ), LONG2CHARS( 0x000FFC00 ), LONG2CHARS( 0x001FFC00 ), + LONG2CHARS( 0X003FFC00 ), LONG2CHARS( 0x007FFC00 ), LONG2CHARS( 0x00FFFC00 ), LONG2CHARS( 0x01FFFC00 ), + LONG2CHARS( 0X03FFFC00 ), LONG2CHARS( 0x07FFFC00 ), LONG2CHARS( 0x0FFFFC00 ), LONG2CHARS( 0x1FFFFC00 ), + LONG2CHARS( 0X3FFFFC00 ), LONG2CHARS( 0x7FFFFC00 ), LONG2CHARS( 0xFFFFFC00 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000800 ), LONG2CHARS( 0x00001800 ), LONG2CHARS( 0x00003800 ), + LONG2CHARS( 0X00007800 ), LONG2CHARS( 0x0000F800 ), LONG2CHARS( 0x0001F800 ), LONG2CHARS( 0x0003F800 ), + LONG2CHARS( 0X0007F800 ), LONG2CHARS( 0x000FF800 ), LONG2CHARS( 0x001FF800 ), LONG2CHARS( 0x003FF800 ), + LONG2CHARS( 0X007FF800 ), LONG2CHARS( 0x00FFF800 ), LONG2CHARS( 0x01FFF800 ), LONG2CHARS( 0x03FFF800 ), + LONG2CHARS( 0X07FFF800 ), LONG2CHARS( 0x0FFFF800 ), LONG2CHARS( 0x1FFFF800 ), LONG2CHARS( 0x3FFFF800 ), + LONG2CHARS( 0X7FFFF800 ), LONG2CHARS( 0xFFFFF800 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00001000 ), LONG2CHARS( 0x00003000 ), LONG2CHARS( 0x00007000 ), + LONG2CHARS( 0X0000F000 ), LONG2CHARS( 0x0001F000 ), LONG2CHARS( 0x0003F000 ), LONG2CHARS( 0x0007F000 ), + LONG2CHARS( 0X000FF000 ), LONG2CHARS( 0x001FF000 ), LONG2CHARS( 0x003FF000 ), LONG2CHARS( 0x007FF000 ), + LONG2CHARS( 0X00FFF000 ), LONG2CHARS( 0x01FFF000 ), LONG2CHARS( 0x03FFF000 ), LONG2CHARS( 0x07FFF000 ), + LONG2CHARS( 0X0FFFF000 ), LONG2CHARS( 0x1FFFF000 ), LONG2CHARS( 0x3FFFF000 ), LONG2CHARS( 0x7FFFF000 ), + LONG2CHARS( 0XFFFFF000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00002000 ), LONG2CHARS( 0x00006000 ), LONG2CHARS( 0x0000E000 ), + LONG2CHARS( 0X0001E000 ), LONG2CHARS( 0x0003E000 ), LONG2CHARS( 0x0007E000 ), LONG2CHARS( 0x000FE000 ), + LONG2CHARS( 0X001FE000 ), LONG2CHARS( 0x003FE000 ), LONG2CHARS( 0x007FE000 ), LONG2CHARS( 0x00FFE000 ), + LONG2CHARS( 0X01FFE000 ), LONG2CHARS( 0x03FFE000 ), LONG2CHARS( 0x07FFE000 ), LONG2CHARS( 0x0FFFE000 ), + LONG2CHARS( 0X1FFFE000 ), LONG2CHARS( 0x3FFFE000 ), LONG2CHARS( 0x7FFFE000 ), LONG2CHARS( 0xFFFFE000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00004000 ), LONG2CHARS( 0x0000C000 ), LONG2CHARS( 0x0001C000 ), + LONG2CHARS( 0X0003C000 ), LONG2CHARS( 0x0007C000 ), LONG2CHARS( 0x000FC000 ), LONG2CHARS( 0x001FC000 ), + LONG2CHARS( 0X003FC000 ), LONG2CHARS( 0x007FC000 ), LONG2CHARS( 0x00FFC000 ), LONG2CHARS( 0x01FFC000 ), + LONG2CHARS( 0X03FFC000 ), LONG2CHARS( 0x07FFC000 ), LONG2CHARS( 0x0FFFC000 ), LONG2CHARS( 0x1FFFC000 ), + LONG2CHARS( 0X3FFFC000 ), LONG2CHARS( 0x7FFFC000 ), LONG2CHARS( 0xFFFFC000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00008000 ), LONG2CHARS( 0x00018000 ), LONG2CHARS( 0x00038000 ), + LONG2CHARS( 0X00078000 ), LONG2CHARS( 0x000F8000 ), LONG2CHARS( 0x001F8000 ), LONG2CHARS( 0x003F8000 ), + LONG2CHARS( 0X007F8000 ), LONG2CHARS( 0x00FF8000 ), LONG2CHARS( 0x01FF8000 ), LONG2CHARS( 0x03FF8000 ), + LONG2CHARS( 0X07FF8000 ), LONG2CHARS( 0x0FFF8000 ), LONG2CHARS( 0x1FFF8000 ), LONG2CHARS( 0x3FFF8000 ), + LONG2CHARS( 0X7FFF8000 ), LONG2CHARS( 0xFFFF8000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00010000 ), LONG2CHARS( 0x00030000 ), LONG2CHARS( 0x00070000 ), + LONG2CHARS( 0X000F0000 ), LONG2CHARS( 0x001F0000 ), LONG2CHARS( 0x003F0000 ), LONG2CHARS( 0x007F0000 ), + LONG2CHARS( 0X00FF0000 ), LONG2CHARS( 0x01FF0000 ), LONG2CHARS( 0x03FF0000 ), LONG2CHARS( 0x07FF0000 ), + LONG2CHARS( 0X0FFF0000 ), LONG2CHARS( 0x1FFF0000 ), LONG2CHARS( 0x3FFF0000 ), LONG2CHARS( 0x7FFF0000 ), + LONG2CHARS( 0XFFFF0000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00020000 ), LONG2CHARS( 0x00060000 ), LONG2CHARS( 0x000E0000 ), + LONG2CHARS( 0X001E0000 ), LONG2CHARS( 0x003E0000 ), LONG2CHARS( 0x007E0000 ), LONG2CHARS( 0x00FE0000 ), + LONG2CHARS( 0X01FE0000 ), LONG2CHARS( 0x03FE0000 ), LONG2CHARS( 0x07FE0000 ), LONG2CHARS( 0x0FFE0000 ), + LONG2CHARS( 0X1FFE0000 ), LONG2CHARS( 0x3FFE0000 ), LONG2CHARS( 0x7FFE0000 ), LONG2CHARS( 0xFFFE0000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00040000 ), LONG2CHARS( 0x000C0000 ), LONG2CHARS( 0x001C0000 ), + LONG2CHARS( 0X003C0000 ), LONG2CHARS( 0x007C0000 ), LONG2CHARS( 0x00FC0000 ), LONG2CHARS( 0x01FC0000 ), + LONG2CHARS( 0X03FC0000 ), LONG2CHARS( 0x07FC0000 ), LONG2CHARS( 0x0FFC0000 ), LONG2CHARS( 0x1FFC0000 ), + LONG2CHARS( 0X3FFC0000 ), LONG2CHARS( 0x7FFC0000 ), LONG2CHARS( 0xFFFC0000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00080000 ), LONG2CHARS( 0x00180000 ), LONG2CHARS( 0x00380000 ), + LONG2CHARS( 0X00780000 ), LONG2CHARS( 0x00F80000 ), LONG2CHARS( 0x01F80000 ), LONG2CHARS( 0x03F80000 ), + LONG2CHARS( 0X07F80000 ), LONG2CHARS( 0x0FF80000 ), LONG2CHARS( 0x1FF80000 ), LONG2CHARS( 0x3FF80000 ), + LONG2CHARS( 0X7FF80000 ), LONG2CHARS( 0xFFF80000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00100000 ), LONG2CHARS( 0x00300000 ), LONG2CHARS( 0x00700000 ), + LONG2CHARS( 0X00F00000 ), LONG2CHARS( 0x01F00000 ), LONG2CHARS( 0x03F00000 ), LONG2CHARS( 0x07F00000 ), + LONG2CHARS( 0X0FF00000 ), LONG2CHARS( 0x1FF00000 ), LONG2CHARS( 0x3FF00000 ), LONG2CHARS( 0x7FF00000 ), + LONG2CHARS( 0XFFF00000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00200000 ), LONG2CHARS( 0x00600000 ), LONG2CHARS( 0x00E00000 ), + LONG2CHARS( 0X01E00000 ), LONG2CHARS( 0x03E00000 ), LONG2CHARS( 0x07E00000 ), LONG2CHARS( 0x0FE00000 ), + LONG2CHARS( 0X1FE00000 ), LONG2CHARS( 0x3FE00000 ), LONG2CHARS( 0x7FE00000 ), LONG2CHARS( 0xFFE00000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00400000 ), LONG2CHARS( 0x00C00000 ), LONG2CHARS( 0x01C00000 ), + LONG2CHARS( 0X03C00000 ), LONG2CHARS( 0x07C00000 ), LONG2CHARS( 0x0FC00000 ), LONG2CHARS( 0x1FC00000 ), + LONG2CHARS( 0X3FC00000 ), LONG2CHARS( 0x7FC00000 ), LONG2CHARS( 0xFFC00000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00800000 ), LONG2CHARS( 0x01800000 ), LONG2CHARS( 0x03800000 ), + LONG2CHARS( 0X07800000 ), LONG2CHARS( 0x0F800000 ), LONG2CHARS( 0x1F800000 ), LONG2CHARS( 0x3F800000 ), + LONG2CHARS( 0X7F800000 ), LONG2CHARS( 0xFF800000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x01000000 ), LONG2CHARS( 0x03000000 ), LONG2CHARS( 0x07000000 ), + LONG2CHARS( 0X0F000000 ), LONG2CHARS( 0x1F000000 ), LONG2CHARS( 0x3F000000 ), LONG2CHARS( 0x7F000000 ), + LONG2CHARS( 0XFF000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x02000000 ), LONG2CHARS( 0x06000000 ), LONG2CHARS( 0x0E000000 ), + LONG2CHARS( 0X1E000000 ), LONG2CHARS( 0x3E000000 ), LONG2CHARS( 0x7E000000 ), LONG2CHARS( 0xFE000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x04000000 ), LONG2CHARS( 0x0C000000 ), LONG2CHARS( 0x1C000000 ), + LONG2CHARS( 0X3C000000 ), LONG2CHARS( 0x7C000000 ), LONG2CHARS( 0xFC000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x08000000 ), LONG2CHARS( 0x18000000 ), LONG2CHARS( 0x38000000 ), + LONG2CHARS( 0X78000000 ), LONG2CHARS( 0xF8000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x10000000 ), LONG2CHARS( 0x30000000 ), LONG2CHARS( 0x70000000 ), + LONG2CHARS( 0XF0000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x20000000 ), LONG2CHARS( 0x60000000 ), LONG2CHARS( 0xE0000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x40000000 ), LONG2CHARS( 0xC0000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, + {LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x80000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), + LONG2CHARS( 0X00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 ), LONG2CHARS( 0x00000000 )}, +}; +#else /* PPW == 64 */ +unsigned long partmasks[PPW][PPW] = { + { + LONG2CHARS( 0xFFFFFFFFFFFFFFFF ), + LONG2CHARS( 0x0000000000000001 ), + LONG2CHARS( 0x0000000000000003 ), + LONG2CHARS( 0x0000000000000007 ), + LONG2CHARS( 0x000000000000000F ), + LONG2CHARS( 0x000000000000001F ), + LONG2CHARS( 0x000000000000003F ), + LONG2CHARS( 0x000000000000007F ), + LONG2CHARS( 0x00000000000000FF ), + LONG2CHARS( 0x00000000000001FF ), + LONG2CHARS( 0x00000000000003FF ), + LONG2CHARS( 0x00000000000007FF ), + LONG2CHARS( 0x0000000000000FFF ), + LONG2CHARS( 0x0000000000001FFF ), + LONG2CHARS( 0x0000000000003FFF ), + LONG2CHARS( 0x0000000000007FFF ), + LONG2CHARS( 0x000000000000FFFF ), + LONG2CHARS( 0x000000000001FFFF ), + LONG2CHARS( 0x000000000003FFFF ), + LONG2CHARS( 0x000000000007FFFF ), + LONG2CHARS( 0x00000000000FFFFF ), + LONG2CHARS( 0x00000000001FFFFF ), + LONG2CHARS( 0x00000000003FFFFF ), + LONG2CHARS( 0x00000000007FFFFF ), + LONG2CHARS( 0x0000000000FFFFFF ), + LONG2CHARS( 0x0000000001FFFFFF ), + LONG2CHARS( 0x0000000003FFFFFF ), + LONG2CHARS( 0x0000000007FFFFFF ), + LONG2CHARS( 0x000000000FFFFFFF ), + LONG2CHARS( 0x000000001FFFFFFF ), + LONG2CHARS( 0x000000003FFFFFFF ), + LONG2CHARS( 0x000000007FFFFFFF ), + LONG2CHARS( 0x00000000FFFFFFFF ), + LONG2CHARS( 0x00000001FFFFFFFF ), + LONG2CHARS( 0x00000003FFFFFFFF ), + LONG2CHARS( 0x00000007FFFFFFFF ), + LONG2CHARS( 0x0000000FFFFFFFFF ), + LONG2CHARS( 0x0000001FFFFFFFFF ), + LONG2CHARS( 0x0000003FFFFFFFFF ), + LONG2CHARS( 0x0000007FFFFFFFFF ), + LONG2CHARS( 0x000000FFFFFFFFFF ), + LONG2CHARS( 0x000001FFFFFFFFFF ), + LONG2CHARS( 0x000003FFFFFFFFFF ), + LONG2CHARS( 0x000007FFFFFFFFFF ), + LONG2CHARS( 0x00000FFFFFFFFFFF ), + LONG2CHARS( 0x00001FFFFFFFFFFF ), + LONG2CHARS( 0x00003FFFFFFFFFFF ), + LONG2CHARS( 0x00007FFFFFFFFFFF ), + LONG2CHARS( 0x0000FFFFFFFFFFFF ), + LONG2CHARS( 0x0001FFFFFFFFFFFF ), + LONG2CHARS( 0x0003FFFFFFFFFFFF ), + LONG2CHARS( 0x0007FFFFFFFFFFFF ), + LONG2CHARS( 0x000FFFFFFFFFFFFF ), + LONG2CHARS( 0x001FFFFFFFFFFFFF ), + LONG2CHARS( 0x003FFFFFFFFFFFFF ), + LONG2CHARS( 0x007FFFFFFFFFFFFF ), + LONG2CHARS( 0x00FFFFFFFFFFFFFF ), + LONG2CHARS( 0x01FFFFFFFFFFFFFF ), + LONG2CHARS( 0x03FFFFFFFFFFFFFF ), + LONG2CHARS( 0x07FFFFFFFFFFFFFF ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFF ), + LONG2CHARS( 0x7FFFFFFFFFFFFFFF ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000002 ), + LONG2CHARS( 0x0000000000000006 ), + LONG2CHARS( 0x000000000000000E ), + LONG2CHARS( 0x000000000000001E ), + LONG2CHARS( 0x000000000000003E ), + LONG2CHARS( 0x000000000000007E ), + LONG2CHARS( 0x00000000000000FE ), + LONG2CHARS( 0x00000000000001FE ), + LONG2CHARS( 0x00000000000003FE ), + LONG2CHARS( 0x00000000000007FE ), + LONG2CHARS( 0x0000000000000FFE ), + LONG2CHARS( 0x0000000000001FFE ), + LONG2CHARS( 0x0000000000003FFE ), + LONG2CHARS( 0x0000000000007FFE ), + LONG2CHARS( 0x000000000000FFFE ), + LONG2CHARS( 0x000000000001FFFE ), + LONG2CHARS( 0x000000000003FFFE ), + LONG2CHARS( 0x000000000007FFFE ), + LONG2CHARS( 0x00000000000FFFFE ), + LONG2CHARS( 0x00000000001FFFFE ), + LONG2CHARS( 0x00000000003FFFFE ), + LONG2CHARS( 0x00000000007FFFFE ), + LONG2CHARS( 0x0000000000FFFFFE ), + LONG2CHARS( 0x0000000001FFFFFE ), + LONG2CHARS( 0x0000000003FFFFFE ), + LONG2CHARS( 0x0000000007FFFFFE ), + LONG2CHARS( 0x000000000FFFFFFE ), + LONG2CHARS( 0x000000001FFFFFFE ), + LONG2CHARS( 0x000000003FFFFFFE ), + LONG2CHARS( 0x000000007FFFFFFE ), + LONG2CHARS( 0x00000000FFFFFFFE ), + LONG2CHARS( 0x00000001FFFFFFFE ), + LONG2CHARS( 0x00000003FFFFFFFE ), + LONG2CHARS( 0x00000007FFFFFFFE ), + LONG2CHARS( 0x0000000FFFFFFFFE ), + LONG2CHARS( 0x0000001FFFFFFFFE ), + LONG2CHARS( 0x0000003FFFFFFFFE ), + LONG2CHARS( 0x0000007FFFFFFFFE ), + LONG2CHARS( 0x000000FFFFFFFFFE ), + LONG2CHARS( 0x000001FFFFFFFFFE ), + LONG2CHARS( 0x000003FFFFFFFFFE ), + LONG2CHARS( 0x000007FFFFFFFFFE ), + LONG2CHARS( 0x00000FFFFFFFFFFE ), + LONG2CHARS( 0x00001FFFFFFFFFFE ), + LONG2CHARS( 0x00003FFFFFFFFFFE ), + LONG2CHARS( 0x00007FFFFFFFFFFE ), + LONG2CHARS( 0x0000FFFFFFFFFFFE ), + LONG2CHARS( 0x0001FFFFFFFFFFFE ), + LONG2CHARS( 0x0003FFFFFFFFFFFE ), + LONG2CHARS( 0x0007FFFFFFFFFFFE ), + LONG2CHARS( 0x000FFFFFFFFFFFFE ), + LONG2CHARS( 0x001FFFFFFFFFFFFE ), + LONG2CHARS( 0x003FFFFFFFFFFFFE ), + LONG2CHARS( 0x007FFFFFFFFFFFFE ), + LONG2CHARS( 0x00FFFFFFFFFFFFFE ), + LONG2CHARS( 0x01FFFFFFFFFFFFFE ), + LONG2CHARS( 0x03FFFFFFFFFFFFFE ), + LONG2CHARS( 0x07FFFFFFFFFFFFFE ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFE ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFE ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFE ), + LONG2CHARS( 0x7FFFFFFFFFFFFFFE ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFE ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000004 ), + LONG2CHARS( 0x000000000000000C ), + LONG2CHARS( 0x000000000000001C ), + LONG2CHARS( 0x000000000000003C ), + LONG2CHARS( 0x000000000000007C ), + LONG2CHARS( 0x00000000000000FC ), + LONG2CHARS( 0x00000000000001FC ), + LONG2CHARS( 0x00000000000003FC ), + LONG2CHARS( 0x00000000000007FC ), + LONG2CHARS( 0x0000000000000FFC ), + LONG2CHARS( 0x0000000000001FFC ), + LONG2CHARS( 0x0000000000003FFC ), + LONG2CHARS( 0x0000000000007FFC ), + LONG2CHARS( 0x000000000000FFFC ), + LONG2CHARS( 0x000000000001FFFC ), + LONG2CHARS( 0x000000000003FFFC ), + LONG2CHARS( 0x000000000007FFFC ), + LONG2CHARS( 0x00000000000FFFFC ), + LONG2CHARS( 0x00000000001FFFFC ), + LONG2CHARS( 0x00000000003FFFFC ), + LONG2CHARS( 0x00000000007FFFFC ), + LONG2CHARS( 0x0000000000FFFFFC ), + LONG2CHARS( 0x0000000001FFFFFC ), + LONG2CHARS( 0x0000000003FFFFFC ), + LONG2CHARS( 0x0000000007FFFFFC ), + LONG2CHARS( 0x000000000FFFFFFC ), + LONG2CHARS( 0x000000001FFFFFFC ), + LONG2CHARS( 0x000000003FFFFFFC ), + LONG2CHARS( 0x000000007FFFFFFC ), + LONG2CHARS( 0x00000000FFFFFFFC ), + LONG2CHARS( 0x00000001FFFFFFFC ), + LONG2CHARS( 0x00000003FFFFFFFC ), + LONG2CHARS( 0x00000007FFFFFFFC ), + LONG2CHARS( 0x0000000FFFFFFFFC ), + LONG2CHARS( 0x0000001FFFFFFFFC ), + LONG2CHARS( 0x0000003FFFFFFFFC ), + LONG2CHARS( 0x0000007FFFFFFFFC ), + LONG2CHARS( 0x000000FFFFFFFFFC ), + LONG2CHARS( 0x000001FFFFFFFFFC ), + LONG2CHARS( 0x000003FFFFFFFFFC ), + LONG2CHARS( 0x000007FFFFFFFFFC ), + LONG2CHARS( 0x00000FFFFFFFFFFC ), + LONG2CHARS( 0x00001FFFFFFFFFFC ), + LONG2CHARS( 0x00003FFFFFFFFFFC ), + LONG2CHARS( 0x00007FFFFFFFFFFC ), + LONG2CHARS( 0x0000FFFFFFFFFFFC ), + LONG2CHARS( 0x0001FFFFFFFFFFFC ), + LONG2CHARS( 0x0003FFFFFFFFFFFC ), + LONG2CHARS( 0x0007FFFFFFFFFFFC ), + LONG2CHARS( 0x000FFFFFFFFFFFFC ), + LONG2CHARS( 0x001FFFFFFFFFFFFC ), + LONG2CHARS( 0x003FFFFFFFFFFFFC ), + LONG2CHARS( 0x007FFFFFFFFFFFFC ), + LONG2CHARS( 0x00FFFFFFFFFFFFFC ), + LONG2CHARS( 0x01FFFFFFFFFFFFFC ), + LONG2CHARS( 0x03FFFFFFFFFFFFFC ), + LONG2CHARS( 0x07FFFFFFFFFFFFFC ), + LONG2CHARS( 0x0FFFFFFFFFFFFFFC ), + LONG2CHARS( 0x1FFFFFFFFFFFFFFC ), + LONG2CHARS( 0x3FFFFFFFFFFFFFFC ), + LONG2CHARS( 0x7FFFFFFFFFFFFFFC ), + LONG2CHARS( 0xFFFFFFFFFFFFFFFC ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000008 ), + LONG2CHARS( 0x0000000000000018 ), + LONG2CHARS( 0x0000000000000038 ), + LONG2CHARS( 0x0000000000000078 ), + LONG2CHARS( 0x00000000000000F8 ), + LONG2CHARS( 0x00000000000001F8 ), + LONG2CHARS( 0x00000000000003F8 ), + LONG2CHARS( 0x00000000000007F8 ), + LONG2CHARS( 0x0000000000000FF8 ), + LONG2CHARS( 0x0000000000001FF8 ), + LONG2CHARS( 0x0000000000003FF8 ), + LONG2CHARS( 0x0000000000007FF8 ), + LONG2CHARS( 0x000000000000FFF8 ), + LONG2CHARS( 0x000000000001FFF8 ), + LONG2CHARS( 0x000000000003FFF8 ), + LONG2CHARS( 0x000000000007FFF8 ), + LONG2CHARS( 0x00000000000FFFF8 ), + LONG2CHARS( 0x00000000001FFFF8 ), + LONG2CHARS( 0x00000000003FFFF8 ), + LONG2CHARS( 0x00000000007FFFF8 ), + LONG2CHARS( 0x0000000000FFFFF8 ), + LONG2CHARS( 0x0000000001FFFFF8 ), + LONG2CHARS( 0x0000000003FFFFF8 ), + LONG2CHARS( 0x0000000007FFFFF8 ), + LONG2CHARS( 0x000000000FFFFFF8 ), + LONG2CHARS( 0x000000001FFFFFF8 ), + LONG2CHARS( 0x000000003FFFFFF8 ), + LONG2CHARS( 0x000000007FFFFFF8 ), + LONG2CHARS( 0x00000000FFFFFFF8 ), + LONG2CHARS( 0x00000001FFFFFFF8 ), + LONG2CHARS( 0x00000003FFFFFFF8 ), + LONG2CHARS( 0x00000007FFFFFFF8 ), + LONG2CHARS( 0x0000000FFFFFFFF8 ), + LONG2CHARS( 0x0000001FFFFFFFF8 ), + LONG2CHARS( 0x0000003FFFFFFFF8 ), + LONG2CHARS( 0x0000007FFFFFFFF8 ), + LONG2CHARS( 0x000000FFFFFFFFF8 ), + LONG2CHARS( 0x000001FFFFFFFFF8 ), + LONG2CHARS( 0x000003FFFFFFFFF8 ), + LONG2CHARS( 0x000007FFFFFFFFF8 ), + LONG2CHARS( 0x00000FFFFFFFFFF8 ), + LONG2CHARS( 0x00001FFFFFFFFFF8 ), + LONG2CHARS( 0x00003FFFFFFFFFF8 ), + LONG2CHARS( 0x00007FFFFFFFFFF8 ), + LONG2CHARS( 0x0000FFFFFFFFFFF8 ), + LONG2CHARS( 0x0001FFFFFFFFFFF8 ), + LONG2CHARS( 0x0003FFFFFFFFFFF8 ), + LONG2CHARS( 0x0007FFFFFFFFFFF8 ), + LONG2CHARS( 0x000FFFFFFFFFFFF8 ), + LONG2CHARS( 0x001FFFFFFFFFFFF8 ), + LONG2CHARS( 0x003FFFFFFFFFFFF8 ), + LONG2CHARS( 0x007FFFFFFFFFFFF8 ), + LONG2CHARS( 0x00FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x01FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x03FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x07FFFFFFFFFFFFF8 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFF8 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF8 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000010 ), + LONG2CHARS( 0x0000000000000030 ), + LONG2CHARS( 0x0000000000000070 ), + LONG2CHARS( 0x00000000000000F0 ), + LONG2CHARS( 0x00000000000001F0 ), + LONG2CHARS( 0x00000000000003F0 ), + LONG2CHARS( 0x00000000000007F0 ), + LONG2CHARS( 0x0000000000000FF0 ), + LONG2CHARS( 0x0000000000001FF0 ), + LONG2CHARS( 0x0000000000003FF0 ), + LONG2CHARS( 0x0000000000007FF0 ), + LONG2CHARS( 0x000000000000FFF0 ), + LONG2CHARS( 0x000000000001FFF0 ), + LONG2CHARS( 0x000000000003FFF0 ), + LONG2CHARS( 0x000000000007FFF0 ), + LONG2CHARS( 0x00000000000FFFF0 ), + LONG2CHARS( 0x00000000001FFFF0 ), + LONG2CHARS( 0x00000000003FFFF0 ), + LONG2CHARS( 0x00000000007FFFF0 ), + LONG2CHARS( 0x0000000000FFFFF0 ), + LONG2CHARS( 0x0000000001FFFFF0 ), + LONG2CHARS( 0x0000000003FFFFF0 ), + LONG2CHARS( 0x0000000007FFFFF0 ), + LONG2CHARS( 0x000000000FFFFFF0 ), + LONG2CHARS( 0x000000001FFFFFF0 ), + LONG2CHARS( 0x000000003FFFFFF0 ), + LONG2CHARS( 0x000000007FFFFFF0 ), + LONG2CHARS( 0x00000000FFFFFFF0 ), + LONG2CHARS( 0x00000001FFFFFFF0 ), + LONG2CHARS( 0x00000003FFFFFFF0 ), + LONG2CHARS( 0x00000007FFFFFFF0 ), + LONG2CHARS( 0x0000000FFFFFFFF0 ), + LONG2CHARS( 0x0000001FFFFFFFF0 ), + LONG2CHARS( 0x0000003FFFFFFFF0 ), + LONG2CHARS( 0x0000007FFFFFFFF0 ), + LONG2CHARS( 0x000000FFFFFFFFF0 ), + LONG2CHARS( 0x000001FFFFFFFFF0 ), + LONG2CHARS( 0x000003FFFFFFFFF0 ), + LONG2CHARS( 0x000007FFFFFFFFF0 ), + LONG2CHARS( 0x00000FFFFFFFFFF0 ), + LONG2CHARS( 0x00001FFFFFFFFFF0 ), + LONG2CHARS( 0x00003FFFFFFFFFF0 ), + LONG2CHARS( 0x00007FFFFFFFFFF0 ), + LONG2CHARS( 0x0000FFFFFFFFFFF0 ), + LONG2CHARS( 0x0001FFFFFFFFFFF0 ), + LONG2CHARS( 0x0003FFFFFFFFFFF0 ), + LONG2CHARS( 0x0007FFFFFFFFFFF0 ), + LONG2CHARS( 0x000FFFFFFFFFFFF0 ), + LONG2CHARS( 0x001FFFFFFFFFFFF0 ), + LONG2CHARS( 0x003FFFFFFFFFFFF0 ), + LONG2CHARS( 0x007FFFFFFFFFFFF0 ), + LONG2CHARS( 0x00FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x01FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x03FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x07FFFFFFFFFFFFF0 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFF0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFF0 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000020 ), + LONG2CHARS( 0x0000000000000060 ), + LONG2CHARS( 0x00000000000000E0 ), + LONG2CHARS( 0x00000000000001E0 ), + LONG2CHARS( 0x00000000000003E0 ), + LONG2CHARS( 0x00000000000007E0 ), + LONG2CHARS( 0x0000000000000FE0 ), + LONG2CHARS( 0x0000000000001FE0 ), + LONG2CHARS( 0x0000000000003FE0 ), + LONG2CHARS( 0x0000000000007FE0 ), + LONG2CHARS( 0x000000000000FFE0 ), + LONG2CHARS( 0x000000000001FFE0 ), + LONG2CHARS( 0x000000000003FFE0 ), + LONG2CHARS( 0x000000000007FFE0 ), + LONG2CHARS( 0x00000000000FFFE0 ), + LONG2CHARS( 0x00000000001FFFE0 ), + LONG2CHARS( 0x00000000003FFFE0 ), + LONG2CHARS( 0x00000000007FFFE0 ), + LONG2CHARS( 0x0000000000FFFFE0 ), + LONG2CHARS( 0x0000000001FFFFE0 ), + LONG2CHARS( 0x0000000003FFFFE0 ), + LONG2CHARS( 0x0000000007FFFFE0 ), + LONG2CHARS( 0x000000000FFFFFE0 ), + LONG2CHARS( 0x000000001FFFFFE0 ), + LONG2CHARS( 0x000000003FFFFFE0 ), + LONG2CHARS( 0x000000007FFFFFE0 ), + LONG2CHARS( 0x00000000FFFFFFE0 ), + LONG2CHARS( 0x00000001FFFFFFE0 ), + LONG2CHARS( 0x00000003FFFFFFE0 ), + LONG2CHARS( 0x00000007FFFFFFE0 ), + LONG2CHARS( 0x0000000FFFFFFFE0 ), + LONG2CHARS( 0x0000001FFFFFFFE0 ), + LONG2CHARS( 0x0000003FFFFFFFE0 ), + LONG2CHARS( 0x0000007FFFFFFFE0 ), + LONG2CHARS( 0x000000FFFFFFFFE0 ), + LONG2CHARS( 0x000001FFFFFFFFE0 ), + LONG2CHARS( 0x000003FFFFFFFFE0 ), + LONG2CHARS( 0x000007FFFFFFFFE0 ), + LONG2CHARS( 0x00000FFFFFFFFFE0 ), + LONG2CHARS( 0x00001FFFFFFFFFE0 ), + LONG2CHARS( 0x00003FFFFFFFFFE0 ), + LONG2CHARS( 0x00007FFFFFFFFFE0 ), + LONG2CHARS( 0x0000FFFFFFFFFFE0 ), + LONG2CHARS( 0x0001FFFFFFFFFFE0 ), + LONG2CHARS( 0x0003FFFFFFFFFFE0 ), + LONG2CHARS( 0x0007FFFFFFFFFFE0 ), + LONG2CHARS( 0x000FFFFFFFFFFFE0 ), + LONG2CHARS( 0x001FFFFFFFFFFFE0 ), + LONG2CHARS( 0x003FFFFFFFFFFFE0 ), + LONG2CHARS( 0x007FFFFFFFFFFFE0 ), + LONG2CHARS( 0x00FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x01FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x03FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x07FFFFFFFFFFFFE0 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFE0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFE0 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000040 ), + LONG2CHARS( 0x00000000000000C0 ), + LONG2CHARS( 0x00000000000001C0 ), + LONG2CHARS( 0x00000000000003C0 ), + LONG2CHARS( 0x00000000000007C0 ), + LONG2CHARS( 0x0000000000000FC0 ), + LONG2CHARS( 0x0000000000001FC0 ), + LONG2CHARS( 0x0000000000003FC0 ), + LONG2CHARS( 0x0000000000007FC0 ), + LONG2CHARS( 0x000000000000FFC0 ), + LONG2CHARS( 0x000000000001FFC0 ), + LONG2CHARS( 0x000000000003FFC0 ), + LONG2CHARS( 0x000000000007FFC0 ), + LONG2CHARS( 0x00000000000FFFC0 ), + LONG2CHARS( 0x00000000001FFFC0 ), + LONG2CHARS( 0x00000000003FFFC0 ), + LONG2CHARS( 0x00000000007FFFC0 ), + LONG2CHARS( 0x0000000000FFFFC0 ), + LONG2CHARS( 0x0000000001FFFFC0 ), + LONG2CHARS( 0x0000000003FFFFC0 ), + LONG2CHARS( 0x0000000007FFFFC0 ), + LONG2CHARS( 0x000000000FFFFFC0 ), + LONG2CHARS( 0x000000001FFFFFC0 ), + LONG2CHARS( 0x000000003FFFFFC0 ), + LONG2CHARS( 0x000000007FFFFFC0 ), + LONG2CHARS( 0x00000000FFFFFFC0 ), + LONG2CHARS( 0x00000001FFFFFFC0 ), + LONG2CHARS( 0x00000003FFFFFFC0 ), + LONG2CHARS( 0x00000007FFFFFFC0 ), + LONG2CHARS( 0x0000000FFFFFFFC0 ), + LONG2CHARS( 0x0000001FFFFFFFC0 ), + LONG2CHARS( 0x0000003FFFFFFFC0 ), + LONG2CHARS( 0x0000007FFFFFFFC0 ), + LONG2CHARS( 0x000000FFFFFFFFC0 ), + LONG2CHARS( 0x000001FFFFFFFFC0 ), + LONG2CHARS( 0x000003FFFFFFFFC0 ), + LONG2CHARS( 0x000007FFFFFFFFC0 ), + LONG2CHARS( 0x00000FFFFFFFFFC0 ), + LONG2CHARS( 0x00001FFFFFFFFFC0 ), + LONG2CHARS( 0x00003FFFFFFFFFC0 ), + LONG2CHARS( 0x00007FFFFFFFFFC0 ), + LONG2CHARS( 0x0000FFFFFFFFFFC0 ), + LONG2CHARS( 0x0001FFFFFFFFFFC0 ), + LONG2CHARS( 0x0003FFFFFFFFFFC0 ), + LONG2CHARS( 0x0007FFFFFFFFFFC0 ), + LONG2CHARS( 0x000FFFFFFFFFFFC0 ), + LONG2CHARS( 0x001FFFFFFFFFFFC0 ), + LONG2CHARS( 0x003FFFFFFFFFFFC0 ), + LONG2CHARS( 0x007FFFFFFFFFFFC0 ), + LONG2CHARS( 0x00FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x01FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x03FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x07FFFFFFFFFFFFC0 ), + LONG2CHARS( 0x0FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x1FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x3FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x7FFFFFFFFFFFFFC0 ), + LONG2CHARS( 0xFFFFFFFFFFFFFFC0 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000080 ), + LONG2CHARS( 0x0000000000000180 ), + LONG2CHARS( 0x0000000000000380 ), + LONG2CHARS( 0x0000000000000780 ), + LONG2CHARS( 0x0000000000000F80 ), + LONG2CHARS( 0x0000000000001F80 ), + LONG2CHARS( 0x0000000000003F80 ), + LONG2CHARS( 0x0000000000007F80 ), + LONG2CHARS( 0x000000000000FF80 ), + LONG2CHARS( 0x000000000001FF80 ), + LONG2CHARS( 0x000000000003FF80 ), + LONG2CHARS( 0x000000000007FF80 ), + LONG2CHARS( 0x00000000000FFF80 ), + LONG2CHARS( 0x00000000001FFF80 ), + LONG2CHARS( 0x00000000003FFF80 ), + LONG2CHARS( 0x00000000007FFF80 ), + LONG2CHARS( 0x0000000000FFFF80 ), + LONG2CHARS( 0x0000000001FFFF80 ), + LONG2CHARS( 0x0000000003FFFF80 ), + LONG2CHARS( 0x0000000007FFFF80 ), + LONG2CHARS( 0x000000000FFFFF80 ), + LONG2CHARS( 0x000000001FFFFF80 ), + LONG2CHARS( 0x000000003FFFFF80 ), + LONG2CHARS( 0x000000007FFFFF80 ), + LONG2CHARS( 0x00000000FFFFFF80 ), + LONG2CHARS( 0x00000001FFFFFF80 ), + LONG2CHARS( 0x00000003FFFFFF80 ), + LONG2CHARS( 0x00000007FFFFFF80 ), + LONG2CHARS( 0x0000000FFFFFFF80 ), + LONG2CHARS( 0x0000001FFFFFFF80 ), + LONG2CHARS( 0x0000003FFFFFFF80 ), + LONG2CHARS( 0x0000007FFFFFFF80 ), + LONG2CHARS( 0x000000FFFFFFFF80 ), + LONG2CHARS( 0x000001FFFFFFFF80 ), + LONG2CHARS( 0x000003FFFFFFFF80 ), + LONG2CHARS( 0x000007FFFFFFFF80 ), + LONG2CHARS( 0x00000FFFFFFFFF80 ), + LONG2CHARS( 0x00001FFFFFFFFF80 ), + LONG2CHARS( 0x00003FFFFFFFFF80 ), + LONG2CHARS( 0x00007FFFFFFFFF80 ), + LONG2CHARS( 0x0000FFFFFFFFFF80 ), + LONG2CHARS( 0x0001FFFFFFFFFF80 ), + LONG2CHARS( 0x0003FFFFFFFFFF80 ), + LONG2CHARS( 0x0007FFFFFFFFFF80 ), + LONG2CHARS( 0x000FFFFFFFFFFF80 ), + LONG2CHARS( 0x001FFFFFFFFFFF80 ), + LONG2CHARS( 0x003FFFFFFFFFFF80 ), + LONG2CHARS( 0x007FFFFFFFFFFF80 ), + LONG2CHARS( 0x00FFFFFFFFFFFF80 ), + LONG2CHARS( 0x01FFFFFFFFFFFF80 ), + LONG2CHARS( 0x03FFFFFFFFFFFF80 ), + LONG2CHARS( 0x07FFFFFFFFFFFF80 ), + LONG2CHARS( 0x0FFFFFFFFFFFFF80 ), + LONG2CHARS( 0x1FFFFFFFFFFFFF80 ), + LONG2CHARS( 0x3FFFFFFFFFFFFF80 ), + LONG2CHARS( 0x7FFFFFFFFFFFFF80 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF80 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000100 ), + LONG2CHARS( 0x0000000000000300 ), + LONG2CHARS( 0x0000000000000700 ), + LONG2CHARS( 0x0000000000000F00 ), + LONG2CHARS( 0x0000000000001F00 ), + LONG2CHARS( 0x0000000000003F00 ), + LONG2CHARS( 0x0000000000007F00 ), + LONG2CHARS( 0x000000000000FF00 ), + LONG2CHARS( 0x000000000001FF00 ), + LONG2CHARS( 0x000000000003FF00 ), + LONG2CHARS( 0x000000000007FF00 ), + LONG2CHARS( 0x00000000000FFF00 ), + LONG2CHARS( 0x00000000001FFF00 ), + LONG2CHARS( 0x00000000003FFF00 ), + LONG2CHARS( 0x00000000007FFF00 ), + LONG2CHARS( 0x0000000000FFFF00 ), + LONG2CHARS( 0x0000000001FFFF00 ), + LONG2CHARS( 0x0000000003FFFF00 ), + LONG2CHARS( 0x0000000007FFFF00 ), + LONG2CHARS( 0x000000000FFFFF00 ), + LONG2CHARS( 0x000000001FFFFF00 ), + LONG2CHARS( 0x000000003FFFFF00 ), + LONG2CHARS( 0x000000007FFFFF00 ), + LONG2CHARS( 0x00000000FFFFFF00 ), + LONG2CHARS( 0x00000001FFFFFF00 ), + LONG2CHARS( 0x00000003FFFFFF00 ), + LONG2CHARS( 0x00000007FFFFFF00 ), + LONG2CHARS( 0x0000000FFFFFFF00 ), + LONG2CHARS( 0x0000001FFFFFFF00 ), + LONG2CHARS( 0x0000003FFFFFFF00 ), + LONG2CHARS( 0x0000007FFFFFFF00 ), + LONG2CHARS( 0x000000FFFFFFFF00 ), + LONG2CHARS( 0x000001FFFFFFFF00 ), + LONG2CHARS( 0x000003FFFFFFFF00 ), + LONG2CHARS( 0x000007FFFFFFFF00 ), + LONG2CHARS( 0x00000FFFFFFFFF00 ), + LONG2CHARS( 0x00001FFFFFFFFF00 ), + LONG2CHARS( 0x00003FFFFFFFFF00 ), + LONG2CHARS( 0x00007FFFFFFFFF00 ), + LONG2CHARS( 0x0000FFFFFFFFFF00 ), + LONG2CHARS( 0x0001FFFFFFFFFF00 ), + LONG2CHARS( 0x0003FFFFFFFFFF00 ), + LONG2CHARS( 0x0007FFFFFFFFFF00 ), + LONG2CHARS( 0x000FFFFFFFFFFF00 ), + LONG2CHARS( 0x001FFFFFFFFFFF00 ), + LONG2CHARS( 0x003FFFFFFFFFFF00 ), + LONG2CHARS( 0x007FFFFFFFFFFF00 ), + LONG2CHARS( 0x00FFFFFFFFFFFF00 ), + LONG2CHARS( 0x01FFFFFFFFFFFF00 ), + LONG2CHARS( 0x03FFFFFFFFFFFF00 ), + LONG2CHARS( 0x07FFFFFFFFFFFF00 ), + LONG2CHARS( 0x0FFFFFFFFFFFFF00 ), + LONG2CHARS( 0x1FFFFFFFFFFFFF00 ), + LONG2CHARS( 0x3FFFFFFFFFFFFF00 ), + LONG2CHARS( 0x7FFFFFFFFFFFFF00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFF00 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000200 ), + LONG2CHARS( 0x0000000000000600 ), + LONG2CHARS( 0x0000000000000E00 ), + LONG2CHARS( 0x0000000000001E00 ), + LONG2CHARS( 0x0000000000003E00 ), + LONG2CHARS( 0x0000000000007E00 ), + LONG2CHARS( 0x000000000000FE00 ), + LONG2CHARS( 0x000000000001FE00 ), + LONG2CHARS( 0x000000000003FE00 ), + LONG2CHARS( 0x000000000007FE00 ), + LONG2CHARS( 0x00000000000FFE00 ), + LONG2CHARS( 0x00000000001FFE00 ), + LONG2CHARS( 0x00000000003FFE00 ), + LONG2CHARS( 0x00000000007FFE00 ), + LONG2CHARS( 0x0000000000FFFE00 ), + LONG2CHARS( 0x0000000001FFFE00 ), + LONG2CHARS( 0x0000000003FFFE00 ), + LONG2CHARS( 0x0000000007FFFE00 ), + LONG2CHARS( 0x000000000FFFFE00 ), + LONG2CHARS( 0x000000001FFFFE00 ), + LONG2CHARS( 0x000000003FFFFE00 ), + LONG2CHARS( 0x000000007FFFFE00 ), + LONG2CHARS( 0x00000000FFFFFE00 ), + LONG2CHARS( 0x00000001FFFFFE00 ), + LONG2CHARS( 0x00000003FFFFFE00 ), + LONG2CHARS( 0x00000007FFFFFE00 ), + LONG2CHARS( 0x0000000FFFFFFE00 ), + LONG2CHARS( 0x0000001FFFFFFE00 ), + LONG2CHARS( 0x0000003FFFFFFE00 ), + LONG2CHARS( 0x0000007FFFFFFE00 ), + LONG2CHARS( 0x000000FFFFFFFE00 ), + LONG2CHARS( 0x000001FFFFFFFE00 ), + LONG2CHARS( 0x000003FFFFFFFE00 ), + LONG2CHARS( 0x000007FFFFFFFE00 ), + LONG2CHARS( 0x00000FFFFFFFFE00 ), + LONG2CHARS( 0x00001FFFFFFFFE00 ), + LONG2CHARS( 0x00003FFFFFFFFE00 ), + LONG2CHARS( 0x00007FFFFFFFFE00 ), + LONG2CHARS( 0x0000FFFFFFFFFE00 ), + LONG2CHARS( 0x0001FFFFFFFFFE00 ), + LONG2CHARS( 0x0003FFFFFFFFFE00 ), + LONG2CHARS( 0x0007FFFFFFFFFE00 ), + LONG2CHARS( 0x000FFFFFFFFFFE00 ), + LONG2CHARS( 0x001FFFFFFFFFFE00 ), + LONG2CHARS( 0x003FFFFFFFFFFE00 ), + LONG2CHARS( 0x007FFFFFFFFFFE00 ), + LONG2CHARS( 0x00FFFFFFFFFFFE00 ), + LONG2CHARS( 0x01FFFFFFFFFFFE00 ), + LONG2CHARS( 0x03FFFFFFFFFFFE00 ), + LONG2CHARS( 0x07FFFFFFFFFFFE00 ), + LONG2CHARS( 0x0FFFFFFFFFFFFE00 ), + LONG2CHARS( 0x1FFFFFFFFFFFFE00 ), + LONG2CHARS( 0x3FFFFFFFFFFFFE00 ), + LONG2CHARS( 0x7FFFFFFFFFFFFE00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFE00 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000400 ), + LONG2CHARS( 0x0000000000000C00 ), + LONG2CHARS( 0x0000000000001C00 ), + LONG2CHARS( 0x0000000000003C00 ), + LONG2CHARS( 0x0000000000007C00 ), + LONG2CHARS( 0x000000000000FC00 ), + LONG2CHARS( 0x000000000001FC00 ), + LONG2CHARS( 0x000000000003FC00 ), + LONG2CHARS( 0x000000000007FC00 ), + LONG2CHARS( 0x00000000000FFC00 ), + LONG2CHARS( 0x00000000001FFC00 ), + LONG2CHARS( 0x00000000003FFC00 ), + LONG2CHARS( 0x00000000007FFC00 ), + LONG2CHARS( 0x0000000000FFFC00 ), + LONG2CHARS( 0x0000000001FFFC00 ), + LONG2CHARS( 0x0000000003FFFC00 ), + LONG2CHARS( 0x0000000007FFFC00 ), + LONG2CHARS( 0x000000000FFFFC00 ), + LONG2CHARS( 0x000000001FFFFC00 ), + LONG2CHARS( 0x000000003FFFFC00 ), + LONG2CHARS( 0x000000007FFFFC00 ), + LONG2CHARS( 0x00000000FFFFFC00 ), + LONG2CHARS( 0x00000001FFFFFC00 ), + LONG2CHARS( 0x00000003FFFFFC00 ), + LONG2CHARS( 0x00000007FFFFFC00 ), + LONG2CHARS( 0x0000000FFFFFFC00 ), + LONG2CHARS( 0x0000001FFFFFFC00 ), + LONG2CHARS( 0x0000003FFFFFFC00 ), + LONG2CHARS( 0x0000007FFFFFFC00 ), + LONG2CHARS( 0x000000FFFFFFFC00 ), + LONG2CHARS( 0x000001FFFFFFFC00 ), + LONG2CHARS( 0x000003FFFFFFFC00 ), + LONG2CHARS( 0x000007FFFFFFFC00 ), + LONG2CHARS( 0x00000FFFFFFFFC00 ), + LONG2CHARS( 0x00001FFFFFFFFC00 ), + LONG2CHARS( 0x00003FFFFFFFFC00 ), + LONG2CHARS( 0x00007FFFFFFFFC00 ), + LONG2CHARS( 0x0000FFFFFFFFFC00 ), + LONG2CHARS( 0x0001FFFFFFFFFC00 ), + LONG2CHARS( 0x0003FFFFFFFFFC00 ), + LONG2CHARS( 0x0007FFFFFFFFFC00 ), + LONG2CHARS( 0x000FFFFFFFFFFC00 ), + LONG2CHARS( 0x001FFFFFFFFFFC00 ), + LONG2CHARS( 0x003FFFFFFFFFFC00 ), + LONG2CHARS( 0x007FFFFFFFFFFC00 ), + LONG2CHARS( 0x00FFFFFFFFFFFC00 ), + LONG2CHARS( 0x01FFFFFFFFFFFC00 ), + LONG2CHARS( 0x03FFFFFFFFFFFC00 ), + LONG2CHARS( 0x07FFFFFFFFFFFC00 ), + LONG2CHARS( 0x0FFFFFFFFFFFFC00 ), + LONG2CHARS( 0x1FFFFFFFFFFFFC00 ), + LONG2CHARS( 0x3FFFFFFFFFFFFC00 ), + LONG2CHARS( 0x7FFFFFFFFFFFFC00 ), + LONG2CHARS( 0xFFFFFFFFFFFFFC00 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000800 ), + LONG2CHARS( 0x0000000000001800 ), + LONG2CHARS( 0x0000000000003800 ), + LONG2CHARS( 0x0000000000007800 ), + LONG2CHARS( 0x000000000000F800 ), + LONG2CHARS( 0x000000000001F800 ), + LONG2CHARS( 0x000000000003F800 ), + LONG2CHARS( 0x000000000007F800 ), + LONG2CHARS( 0x00000000000FF800 ), + LONG2CHARS( 0x00000000001FF800 ), + LONG2CHARS( 0x00000000003FF800 ), + LONG2CHARS( 0x00000000007FF800 ), + LONG2CHARS( 0x0000000000FFF800 ), + LONG2CHARS( 0x0000000001FFF800 ), + LONG2CHARS( 0x0000000003FFF800 ), + LONG2CHARS( 0x0000000007FFF800 ), + LONG2CHARS( 0x000000000FFFF800 ), + LONG2CHARS( 0x000000001FFFF800 ), + LONG2CHARS( 0x000000003FFFF800 ), + LONG2CHARS( 0x000000007FFFF800 ), + LONG2CHARS( 0x00000000FFFFF800 ), + LONG2CHARS( 0x00000001FFFFF800 ), + LONG2CHARS( 0x00000003FFFFF800 ), + LONG2CHARS( 0x00000007FFFFF800 ), + LONG2CHARS( 0x0000000FFFFFF800 ), + LONG2CHARS( 0x0000001FFFFFF800 ), + LONG2CHARS( 0x0000003FFFFFF800 ), + LONG2CHARS( 0x0000007FFFFFF800 ), + LONG2CHARS( 0x000000FFFFFFF800 ), + LONG2CHARS( 0x000001FFFFFFF800 ), + LONG2CHARS( 0x000003FFFFFFF800 ), + LONG2CHARS( 0x000007FFFFFFF800 ), + LONG2CHARS( 0x00000FFFFFFFF800 ), + LONG2CHARS( 0x00001FFFFFFFF800 ), + LONG2CHARS( 0x00003FFFFFFFF800 ), + LONG2CHARS( 0x00007FFFFFFFF800 ), + LONG2CHARS( 0x0000FFFFFFFFF800 ), + LONG2CHARS( 0x0001FFFFFFFFF800 ), + LONG2CHARS( 0x0003FFFFFFFFF800 ), + LONG2CHARS( 0x0007FFFFFFFFF800 ), + LONG2CHARS( 0x000FFFFFFFFFF800 ), + LONG2CHARS( 0x001FFFFFFFFFF800 ), + LONG2CHARS( 0x003FFFFFFFFFF800 ), + LONG2CHARS( 0x007FFFFFFFFFF800 ), + LONG2CHARS( 0x00FFFFFFFFFFF800 ), + LONG2CHARS( 0x01FFFFFFFFFFF800 ), + LONG2CHARS( 0x03FFFFFFFFFFF800 ), + LONG2CHARS( 0x07FFFFFFFFFFF800 ), + LONG2CHARS( 0x0FFFFFFFFFFFF800 ), + LONG2CHARS( 0x1FFFFFFFFFFFF800 ), + LONG2CHARS( 0x3FFFFFFFFFFFF800 ), + LONG2CHARS( 0x7FFFFFFFFFFFF800 ), + LONG2CHARS( 0xFFFFFFFFFFFFF800 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000001000 ), + LONG2CHARS( 0x0000000000003000 ), + LONG2CHARS( 0x0000000000007000 ), + LONG2CHARS( 0x000000000000F000 ), + LONG2CHARS( 0x000000000001F000 ), + LONG2CHARS( 0x000000000003F000 ), + LONG2CHARS( 0x000000000007F000 ), + LONG2CHARS( 0x00000000000FF000 ), + LONG2CHARS( 0x00000000001FF000 ), + LONG2CHARS( 0x00000000003FF000 ), + LONG2CHARS( 0x00000000007FF000 ), + LONG2CHARS( 0x0000000000FFF000 ), + LONG2CHARS( 0x0000000001FFF000 ), + LONG2CHARS( 0x0000000003FFF000 ), + LONG2CHARS( 0x0000000007FFF000 ), + LONG2CHARS( 0x000000000FFFF000 ), + LONG2CHARS( 0x000000001FFFF000 ), + LONG2CHARS( 0x000000003FFFF000 ), + LONG2CHARS( 0x000000007FFFF000 ), + LONG2CHARS( 0x00000000FFFFF000 ), + LONG2CHARS( 0x00000001FFFFF000 ), + LONG2CHARS( 0x00000003FFFFF000 ), + LONG2CHARS( 0x00000007FFFFF000 ), + LONG2CHARS( 0x0000000FFFFFF000 ), + LONG2CHARS( 0x0000001FFFFFF000 ), + LONG2CHARS( 0x0000003FFFFFF000 ), + LONG2CHARS( 0x0000007FFFFFF000 ), + LONG2CHARS( 0x000000FFFFFFF000 ), + LONG2CHARS( 0x000001FFFFFFF000 ), + LONG2CHARS( 0x000003FFFFFFF000 ), + LONG2CHARS( 0x000007FFFFFFF000 ), + LONG2CHARS( 0x00000FFFFFFFF000 ), + LONG2CHARS( 0x00001FFFFFFFF000 ), + LONG2CHARS( 0x00003FFFFFFFF000 ), + LONG2CHARS( 0x00007FFFFFFFF000 ), + LONG2CHARS( 0x0000FFFFFFFFF000 ), + LONG2CHARS( 0x0001FFFFFFFFF000 ), + LONG2CHARS( 0x0003FFFFFFFFF000 ), + LONG2CHARS( 0x0007FFFFFFFFF000 ), + LONG2CHARS( 0x000FFFFFFFFFF000 ), + LONG2CHARS( 0x001FFFFFFFFFF000 ), + LONG2CHARS( 0x003FFFFFFFFFF000 ), + LONG2CHARS( 0x007FFFFFFFFFF000 ), + LONG2CHARS( 0x00FFFFFFFFFFF000 ), + LONG2CHARS( 0x01FFFFFFFFFFF000 ), + LONG2CHARS( 0x03FFFFFFFFFFF000 ), + LONG2CHARS( 0x07FFFFFFFFFFF000 ), + LONG2CHARS( 0x0FFFFFFFFFFFF000 ), + LONG2CHARS( 0x1FFFFFFFFFFFF000 ), + LONG2CHARS( 0x3FFFFFFFFFFFF000 ), + LONG2CHARS( 0x7FFFFFFFFFFFF000 ), + LONG2CHARS( 0xFFFFFFFFFFFFF000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000002000 ), + LONG2CHARS( 0x0000000000006000 ), + LONG2CHARS( 0x000000000000E000 ), + LONG2CHARS( 0x000000000001E000 ), + LONG2CHARS( 0x000000000003E000 ), + LONG2CHARS( 0x000000000007E000 ), + LONG2CHARS( 0x00000000000FE000 ), + LONG2CHARS( 0x00000000001FE000 ), + LONG2CHARS( 0x00000000003FE000 ), + LONG2CHARS( 0x00000000007FE000 ), + LONG2CHARS( 0x0000000000FFE000 ), + LONG2CHARS( 0x0000000001FFE000 ), + LONG2CHARS( 0x0000000003FFE000 ), + LONG2CHARS( 0x0000000007FFE000 ), + LONG2CHARS( 0x000000000FFFE000 ), + LONG2CHARS( 0x000000001FFFE000 ), + LONG2CHARS( 0x000000003FFFE000 ), + LONG2CHARS( 0x000000007FFFE000 ), + LONG2CHARS( 0x00000000FFFFE000 ), + LONG2CHARS( 0x00000001FFFFE000 ), + LONG2CHARS( 0x00000003FFFFE000 ), + LONG2CHARS( 0x00000007FFFFE000 ), + LONG2CHARS( 0x0000000FFFFFE000 ), + LONG2CHARS( 0x0000001FFFFFE000 ), + LONG2CHARS( 0x0000003FFFFFE000 ), + LONG2CHARS( 0x0000007FFFFFE000 ), + LONG2CHARS( 0x000000FFFFFFE000 ), + LONG2CHARS( 0x000001FFFFFFE000 ), + LONG2CHARS( 0x000003FFFFFFE000 ), + LONG2CHARS( 0x000007FFFFFFE000 ), + LONG2CHARS( 0x00000FFFFFFFE000 ), + LONG2CHARS( 0x00001FFFFFFFE000 ), + LONG2CHARS( 0x00003FFFFFFFE000 ), + LONG2CHARS( 0x00007FFFFFFFE000 ), + LONG2CHARS( 0x0000FFFFFFFFE000 ), + LONG2CHARS( 0x0001FFFFFFFFE000 ), + LONG2CHARS( 0x0003FFFFFFFFE000 ), + LONG2CHARS( 0x0007FFFFFFFFE000 ), + LONG2CHARS( 0x000FFFFFFFFFE000 ), + LONG2CHARS( 0x001FFFFFFFFFE000 ), + LONG2CHARS( 0x003FFFFFFFFFE000 ), + LONG2CHARS( 0x007FFFFFFFFFE000 ), + LONG2CHARS( 0x00FFFFFFFFFFE000 ), + LONG2CHARS( 0x01FFFFFFFFFFE000 ), + LONG2CHARS( 0x03FFFFFFFFFFE000 ), + LONG2CHARS( 0x07FFFFFFFFFFE000 ), + LONG2CHARS( 0x0FFFFFFFFFFFE000 ), + LONG2CHARS( 0x1FFFFFFFFFFFE000 ), + LONG2CHARS( 0x3FFFFFFFFFFFE000 ), + LONG2CHARS( 0x7FFFFFFFFFFFE000 ), + LONG2CHARS( 0xFFFFFFFFFFFFE000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000004000 ), + LONG2CHARS( 0x000000000000C000 ), + LONG2CHARS( 0x000000000001C000 ), + LONG2CHARS( 0x000000000003C000 ), + LONG2CHARS( 0x000000000007C000 ), + LONG2CHARS( 0x00000000000FC000 ), + LONG2CHARS( 0x00000000001FC000 ), + LONG2CHARS( 0x00000000003FC000 ), + LONG2CHARS( 0x00000000007FC000 ), + LONG2CHARS( 0x0000000000FFC000 ), + LONG2CHARS( 0x0000000001FFC000 ), + LONG2CHARS( 0x0000000003FFC000 ), + LONG2CHARS( 0x0000000007FFC000 ), + LONG2CHARS( 0x000000000FFFC000 ), + LONG2CHARS( 0x000000001FFFC000 ), + LONG2CHARS( 0x000000003FFFC000 ), + LONG2CHARS( 0x000000007FFFC000 ), + LONG2CHARS( 0x00000000FFFFC000 ), + LONG2CHARS( 0x00000001FFFFC000 ), + LONG2CHARS( 0x00000003FFFFC000 ), + LONG2CHARS( 0x00000007FFFFC000 ), + LONG2CHARS( 0x0000000FFFFFC000 ), + LONG2CHARS( 0x0000001FFFFFC000 ), + LONG2CHARS( 0x0000003FFFFFC000 ), + LONG2CHARS( 0x0000007FFFFFC000 ), + LONG2CHARS( 0x000000FFFFFFC000 ), + LONG2CHARS( 0x000001FFFFFFC000 ), + LONG2CHARS( 0x000003FFFFFFC000 ), + LONG2CHARS( 0x000007FFFFFFC000 ), + LONG2CHARS( 0x00000FFFFFFFC000 ), + LONG2CHARS( 0x00001FFFFFFFC000 ), + LONG2CHARS( 0x00003FFFFFFFC000 ), + LONG2CHARS( 0x00007FFFFFFFC000 ), + LONG2CHARS( 0x0000FFFFFFFFC000 ), + LONG2CHARS( 0x0001FFFFFFFFC000 ), + LONG2CHARS( 0x0003FFFFFFFFC000 ), + LONG2CHARS( 0x0007FFFFFFFFC000 ), + LONG2CHARS( 0x000FFFFFFFFFC000 ), + LONG2CHARS( 0x001FFFFFFFFFC000 ), + LONG2CHARS( 0x003FFFFFFFFFC000 ), + LONG2CHARS( 0x007FFFFFFFFFC000 ), + LONG2CHARS( 0x00FFFFFFFFFFC000 ), + LONG2CHARS( 0x01FFFFFFFFFFC000 ), + LONG2CHARS( 0x03FFFFFFFFFFC000 ), + LONG2CHARS( 0x07FFFFFFFFFFC000 ), + LONG2CHARS( 0x0FFFFFFFFFFFC000 ), + LONG2CHARS( 0x1FFFFFFFFFFFC000 ), + LONG2CHARS( 0x3FFFFFFFFFFFC000 ), + LONG2CHARS( 0x7FFFFFFFFFFFC000 ), + LONG2CHARS( 0xFFFFFFFFFFFFC000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000008000 ), + LONG2CHARS( 0x0000000000018000 ), + LONG2CHARS( 0x0000000000038000 ), + LONG2CHARS( 0x0000000000078000 ), + LONG2CHARS( 0x00000000000F8000 ), + LONG2CHARS( 0x00000000001F8000 ), + LONG2CHARS( 0x00000000003F8000 ), + LONG2CHARS( 0x00000000007F8000 ), + LONG2CHARS( 0x0000000000FF8000 ), + LONG2CHARS( 0x0000000001FF8000 ), + LONG2CHARS( 0x0000000003FF8000 ), + LONG2CHARS( 0x0000000007FF8000 ), + LONG2CHARS( 0x000000000FFF8000 ), + LONG2CHARS( 0x000000001FFF8000 ), + LONG2CHARS( 0x000000003FFF8000 ), + LONG2CHARS( 0x000000007FFF8000 ), + LONG2CHARS( 0x00000000FFFF8000 ), + LONG2CHARS( 0x00000001FFFF8000 ), + LONG2CHARS( 0x00000003FFFF8000 ), + LONG2CHARS( 0x00000007FFFF8000 ), + LONG2CHARS( 0x0000000FFFFF8000 ), + LONG2CHARS( 0x0000001FFFFF8000 ), + LONG2CHARS( 0x0000003FFFFF8000 ), + LONG2CHARS( 0x0000007FFFFF8000 ), + LONG2CHARS( 0x000000FFFFFF8000 ), + LONG2CHARS( 0x000001FFFFFF8000 ), + LONG2CHARS( 0x000003FFFFFF8000 ), + LONG2CHARS( 0x000007FFFFFF8000 ), + LONG2CHARS( 0x00000FFFFFFF8000 ), + LONG2CHARS( 0x00001FFFFFFF8000 ), + LONG2CHARS( 0x00003FFFFFFF8000 ), + LONG2CHARS( 0x00007FFFFFFF8000 ), + LONG2CHARS( 0x0000FFFFFFFF8000 ), + LONG2CHARS( 0x0001FFFFFFFF8000 ), + LONG2CHARS( 0x0003FFFFFFFF8000 ), + LONG2CHARS( 0x0007FFFFFFFF8000 ), + LONG2CHARS( 0x000FFFFFFFFF8000 ), + LONG2CHARS( 0x001FFFFFFFFF8000 ), + LONG2CHARS( 0x003FFFFFFFFF8000 ), + LONG2CHARS( 0x007FFFFFFFFF8000 ), + LONG2CHARS( 0x00FFFFFFFFFF8000 ), + LONG2CHARS( 0x01FFFFFFFFFF8000 ), + LONG2CHARS( 0x03FFFFFFFFFF8000 ), + LONG2CHARS( 0x07FFFFFFFFFF8000 ), + LONG2CHARS( 0x0FFFFFFFFFFF8000 ), + LONG2CHARS( 0x1FFFFFFFFFFF8000 ), + LONG2CHARS( 0x3FFFFFFFFFFF8000 ), + LONG2CHARS( 0x7FFFFFFFFFFF8000 ), + LONG2CHARS( 0xFFFFFFFFFFFF8000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000010000 ), + LONG2CHARS( 0x0000000000030000 ), + LONG2CHARS( 0x0000000000070000 ), + LONG2CHARS( 0x00000000000F0000 ), + LONG2CHARS( 0x00000000001F0000 ), + LONG2CHARS( 0x00000000003F0000 ), + LONG2CHARS( 0x00000000007F0000 ), + LONG2CHARS( 0x0000000000FF0000 ), + LONG2CHARS( 0x0000000001FF0000 ), + LONG2CHARS( 0x0000000003FF0000 ), + LONG2CHARS( 0x0000000007FF0000 ), + LONG2CHARS( 0x000000000FFF0000 ), + LONG2CHARS( 0x000000001FFF0000 ), + LONG2CHARS( 0x000000003FFF0000 ), + LONG2CHARS( 0x000000007FFF0000 ), + LONG2CHARS( 0x00000000FFFF0000 ), + LONG2CHARS( 0x00000001FFFF0000 ), + LONG2CHARS( 0x00000003FFFF0000 ), + LONG2CHARS( 0x00000007FFFF0000 ), + LONG2CHARS( 0x0000000FFFFF0000 ), + LONG2CHARS( 0x0000001FFFFF0000 ), + LONG2CHARS( 0x0000003FFFFF0000 ), + LONG2CHARS( 0x0000007FFFFF0000 ), + LONG2CHARS( 0x000000FFFFFF0000 ), + LONG2CHARS( 0x000001FFFFFF0000 ), + LONG2CHARS( 0x000003FFFFFF0000 ), + LONG2CHARS( 0x000007FFFFFF0000 ), + LONG2CHARS( 0x00000FFFFFFF0000 ), + LONG2CHARS( 0x00001FFFFFFF0000 ), + LONG2CHARS( 0x00003FFFFFFF0000 ), + LONG2CHARS( 0x00007FFFFFFF0000 ), + LONG2CHARS( 0x0000FFFFFFFF0000 ), + LONG2CHARS( 0x0001FFFFFFFF0000 ), + LONG2CHARS( 0x0003FFFFFFFF0000 ), + LONG2CHARS( 0x0007FFFFFFFF0000 ), + LONG2CHARS( 0x000FFFFFFFFF0000 ), + LONG2CHARS( 0x001FFFFFFFFF0000 ), + LONG2CHARS( 0x003FFFFFFFFF0000 ), + LONG2CHARS( 0x007FFFFFFFFF0000 ), + LONG2CHARS( 0x00FFFFFFFFFF0000 ), + LONG2CHARS( 0x01FFFFFFFFFF0000 ), + LONG2CHARS( 0x03FFFFFFFFFF0000 ), + LONG2CHARS( 0x07FFFFFFFFFF0000 ), + LONG2CHARS( 0x0FFFFFFFFFFF0000 ), + LONG2CHARS( 0x1FFFFFFFFFFF0000 ), + LONG2CHARS( 0x3FFFFFFFFFFF0000 ), + LONG2CHARS( 0x7FFFFFFFFFFF0000 ), + LONG2CHARS( 0xFFFFFFFFFFFF0000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000020000 ), + LONG2CHARS( 0x0000000000060000 ), + LONG2CHARS( 0x00000000000E0000 ), + LONG2CHARS( 0x00000000001E0000 ), + LONG2CHARS( 0x00000000003E0000 ), + LONG2CHARS( 0x00000000007E0000 ), + LONG2CHARS( 0x0000000000FE0000 ), + LONG2CHARS( 0x0000000001FE0000 ), + LONG2CHARS( 0x0000000003FE0000 ), + LONG2CHARS( 0x0000000007FE0000 ), + LONG2CHARS( 0x000000000FFE0000 ), + LONG2CHARS( 0x000000001FFE0000 ), + LONG2CHARS( 0x000000003FFE0000 ), + LONG2CHARS( 0x000000007FFE0000 ), + LONG2CHARS( 0x00000000FFFE0000 ), + LONG2CHARS( 0x00000001FFFE0000 ), + LONG2CHARS( 0x00000003FFFE0000 ), + LONG2CHARS( 0x00000007FFFE0000 ), + LONG2CHARS( 0x0000000FFFFE0000 ), + LONG2CHARS( 0x0000001FFFFE0000 ), + LONG2CHARS( 0x0000003FFFFE0000 ), + LONG2CHARS( 0x0000007FFFFE0000 ), + LONG2CHARS( 0x000000FFFFFE0000 ), + LONG2CHARS( 0x000001FFFFFE0000 ), + LONG2CHARS( 0x000003FFFFFE0000 ), + LONG2CHARS( 0x000007FFFFFE0000 ), + LONG2CHARS( 0x00000FFFFFFE0000 ), + LONG2CHARS( 0x00001FFFFFFE0000 ), + LONG2CHARS( 0x00003FFFFFFE0000 ), + LONG2CHARS( 0x00007FFFFFFE0000 ), + LONG2CHARS( 0x0000FFFFFFFE0000 ), + LONG2CHARS( 0x0001FFFFFFFE0000 ), + LONG2CHARS( 0x0003FFFFFFFE0000 ), + LONG2CHARS( 0x0007FFFFFFFE0000 ), + LONG2CHARS( 0x000FFFFFFFFE0000 ), + LONG2CHARS( 0x001FFFFFFFFE0000 ), + LONG2CHARS( 0x003FFFFFFFFE0000 ), + LONG2CHARS( 0x007FFFFFFFFE0000 ), + LONG2CHARS( 0x00FFFFFFFFFE0000 ), + LONG2CHARS( 0x01FFFFFFFFFE0000 ), + LONG2CHARS( 0x03FFFFFFFFFE0000 ), + LONG2CHARS( 0x07FFFFFFFFFE0000 ), + LONG2CHARS( 0x0FFFFFFFFFFE0000 ), + LONG2CHARS( 0x1FFFFFFFFFFE0000 ), + LONG2CHARS( 0x3FFFFFFFFFFE0000 ), + LONG2CHARS( 0x7FFFFFFFFFFE0000 ), + LONG2CHARS( 0xFFFFFFFFFFFE0000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000040000 ), + LONG2CHARS( 0x00000000000C0000 ), + LONG2CHARS( 0x00000000001C0000 ), + LONG2CHARS( 0x00000000003C0000 ), + LONG2CHARS( 0x00000000007C0000 ), + LONG2CHARS( 0x0000000000FC0000 ), + LONG2CHARS( 0x0000000001FC0000 ), + LONG2CHARS( 0x0000000003FC0000 ), + LONG2CHARS( 0x0000000007FC0000 ), + LONG2CHARS( 0x000000000FFC0000 ), + LONG2CHARS( 0x000000001FFC0000 ), + LONG2CHARS( 0x000000003FFC0000 ), + LONG2CHARS( 0x000000007FFC0000 ), + LONG2CHARS( 0x00000000FFFC0000 ), + LONG2CHARS( 0x00000001FFFC0000 ), + LONG2CHARS( 0x00000003FFFC0000 ), + LONG2CHARS( 0x00000007FFFC0000 ), + LONG2CHARS( 0x0000000FFFFC0000 ), + LONG2CHARS( 0x0000001FFFFC0000 ), + LONG2CHARS( 0x0000003FFFFC0000 ), + LONG2CHARS( 0x0000007FFFFC0000 ), + LONG2CHARS( 0x000000FFFFFC0000 ), + LONG2CHARS( 0x000001FFFFFC0000 ), + LONG2CHARS( 0x000003FFFFFC0000 ), + LONG2CHARS( 0x000007FFFFFC0000 ), + LONG2CHARS( 0x00000FFFFFFC0000 ), + LONG2CHARS( 0x00001FFFFFFC0000 ), + LONG2CHARS( 0x00003FFFFFFC0000 ), + LONG2CHARS( 0x00007FFFFFFC0000 ), + LONG2CHARS( 0x0000FFFFFFFC0000 ), + LONG2CHARS( 0x0001FFFFFFFC0000 ), + LONG2CHARS( 0x0003FFFFFFFC0000 ), + LONG2CHARS( 0x0007FFFFFFFC0000 ), + LONG2CHARS( 0x000FFFFFFFFC0000 ), + LONG2CHARS( 0x001FFFFFFFFC0000 ), + LONG2CHARS( 0x003FFFFFFFFC0000 ), + LONG2CHARS( 0x007FFFFFFFFC0000 ), + LONG2CHARS( 0x00FFFFFFFFFC0000 ), + LONG2CHARS( 0x01FFFFFFFFFC0000 ), + LONG2CHARS( 0x03FFFFFFFFFC0000 ), + LONG2CHARS( 0x07FFFFFFFFFC0000 ), + LONG2CHARS( 0x0FFFFFFFFFFC0000 ), + LONG2CHARS( 0x1FFFFFFFFFFC0000 ), + LONG2CHARS( 0x3FFFFFFFFFFC0000 ), + LONG2CHARS( 0x7FFFFFFFFFFC0000 ), + LONG2CHARS( 0xFFFFFFFFFFFC0000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000080000 ), + LONG2CHARS( 0x0000000000180000 ), + LONG2CHARS( 0x0000000000380000 ), + LONG2CHARS( 0x0000000000780000 ), + LONG2CHARS( 0x0000000000F80000 ), + LONG2CHARS( 0x0000000001F80000 ), + LONG2CHARS( 0x0000000003F80000 ), + LONG2CHARS( 0x0000000007F80000 ), + LONG2CHARS( 0x000000000FF80000 ), + LONG2CHARS( 0x000000001FF80000 ), + LONG2CHARS( 0x000000003FF80000 ), + LONG2CHARS( 0x000000007FF80000 ), + LONG2CHARS( 0x00000000FFF80000 ), + LONG2CHARS( 0x00000001FFF80000 ), + LONG2CHARS( 0x00000003FFF80000 ), + LONG2CHARS( 0x00000007FFF80000 ), + LONG2CHARS( 0x0000000FFFF80000 ), + LONG2CHARS( 0x0000001FFFF80000 ), + LONG2CHARS( 0x0000003FFFF80000 ), + LONG2CHARS( 0x0000007FFFF80000 ), + LONG2CHARS( 0x000000FFFFF80000 ), + LONG2CHARS( 0x000001FFFFF80000 ), + LONG2CHARS( 0x000003FFFFF80000 ), + LONG2CHARS( 0x000007FFFFF80000 ), + LONG2CHARS( 0x00000FFFFFF80000 ), + LONG2CHARS( 0x00001FFFFFF80000 ), + LONG2CHARS( 0x00003FFFFFF80000 ), + LONG2CHARS( 0x00007FFFFFF80000 ), + LONG2CHARS( 0x0000FFFFFFF80000 ), + LONG2CHARS( 0x0001FFFFFFF80000 ), + LONG2CHARS( 0x0003FFFFFFF80000 ), + LONG2CHARS( 0x0007FFFFFFF80000 ), + LONG2CHARS( 0x000FFFFFFFF80000 ), + LONG2CHARS( 0x001FFFFFFFF80000 ), + LONG2CHARS( 0x003FFFFFFFF80000 ), + LONG2CHARS( 0x007FFFFFFFF80000 ), + LONG2CHARS( 0x00FFFFFFFFF80000 ), + LONG2CHARS( 0x01FFFFFFFFF80000 ), + LONG2CHARS( 0x03FFFFFFFFF80000 ), + LONG2CHARS( 0x07FFFFFFFFF80000 ), + LONG2CHARS( 0x0FFFFFFFFFF80000 ), + LONG2CHARS( 0x1FFFFFFFFFF80000 ), + LONG2CHARS( 0x3FFFFFFFFFF80000 ), + LONG2CHARS( 0x7FFFFFFFFFF80000 ), + LONG2CHARS( 0xFFFFFFFFFFF80000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000100000 ), + LONG2CHARS( 0x0000000000300000 ), + LONG2CHARS( 0x0000000000700000 ), + LONG2CHARS( 0x0000000000F00000 ), + LONG2CHARS( 0x0000000001F00000 ), + LONG2CHARS( 0x0000000003F00000 ), + LONG2CHARS( 0x0000000007F00000 ), + LONG2CHARS( 0x000000000FF00000 ), + LONG2CHARS( 0x000000001FF00000 ), + LONG2CHARS( 0x000000003FF00000 ), + LONG2CHARS( 0x000000007FF00000 ), + LONG2CHARS( 0x00000000FFF00000 ), + LONG2CHARS( 0x00000001FFF00000 ), + LONG2CHARS( 0x00000003FFF00000 ), + LONG2CHARS( 0x00000007FFF00000 ), + LONG2CHARS( 0x0000000FFFF00000 ), + LONG2CHARS( 0x0000001FFFF00000 ), + LONG2CHARS( 0x0000003FFFF00000 ), + LONG2CHARS( 0x0000007FFFF00000 ), + LONG2CHARS( 0x000000FFFFF00000 ), + LONG2CHARS( 0x000001FFFFF00000 ), + LONG2CHARS( 0x000003FFFFF00000 ), + LONG2CHARS( 0x000007FFFFF00000 ), + LONG2CHARS( 0x00000FFFFFF00000 ), + LONG2CHARS( 0x00001FFFFFF00000 ), + LONG2CHARS( 0x00003FFFFFF00000 ), + LONG2CHARS( 0x00007FFFFFF00000 ), + LONG2CHARS( 0x0000FFFFFFF00000 ), + LONG2CHARS( 0x0001FFFFFFF00000 ), + LONG2CHARS( 0x0003FFFFFFF00000 ), + LONG2CHARS( 0x0007FFFFFFF00000 ), + LONG2CHARS( 0x000FFFFFFFF00000 ), + LONG2CHARS( 0x001FFFFFFFF00000 ), + LONG2CHARS( 0x003FFFFFFFF00000 ), + LONG2CHARS( 0x007FFFFFFFF00000 ), + LONG2CHARS( 0x00FFFFFFFFF00000 ), + LONG2CHARS( 0x01FFFFFFFFF00000 ), + LONG2CHARS( 0x03FFFFFFFFF00000 ), + LONG2CHARS( 0x07FFFFFFFFF00000 ), + LONG2CHARS( 0x0FFFFFFFFFF00000 ), + LONG2CHARS( 0x1FFFFFFFFFF00000 ), + LONG2CHARS( 0x3FFFFFFFFFF00000 ), + LONG2CHARS( 0x7FFFFFFFFFF00000 ), + LONG2CHARS( 0xFFFFFFFFFFF00000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000200000 ), + LONG2CHARS( 0x0000000000600000 ), + LONG2CHARS( 0x0000000000E00000 ), + LONG2CHARS( 0x0000000001E00000 ), + LONG2CHARS( 0x0000000003E00000 ), + LONG2CHARS( 0x0000000007E00000 ), + LONG2CHARS( 0x000000000FE00000 ), + LONG2CHARS( 0x000000001FE00000 ), + LONG2CHARS( 0x000000003FE00000 ), + LONG2CHARS( 0x000000007FE00000 ), + LONG2CHARS( 0x00000000FFE00000 ), + LONG2CHARS( 0x00000001FFE00000 ), + LONG2CHARS( 0x00000003FFE00000 ), + LONG2CHARS( 0x00000007FFE00000 ), + LONG2CHARS( 0x0000000FFFE00000 ), + LONG2CHARS( 0x0000001FFFE00000 ), + LONG2CHARS( 0x0000003FFFE00000 ), + LONG2CHARS( 0x0000007FFFE00000 ), + LONG2CHARS( 0x000000FFFFE00000 ), + LONG2CHARS( 0x000001FFFFE00000 ), + LONG2CHARS( 0x000003FFFFE00000 ), + LONG2CHARS( 0x000007FFFFE00000 ), + LONG2CHARS( 0x00000FFFFFE00000 ), + LONG2CHARS( 0x00001FFFFFE00000 ), + LONG2CHARS( 0x00003FFFFFE00000 ), + LONG2CHARS( 0x00007FFFFFE00000 ), + LONG2CHARS( 0x0000FFFFFFE00000 ), + LONG2CHARS( 0x0001FFFFFFE00000 ), + LONG2CHARS( 0x0003FFFFFFE00000 ), + LONG2CHARS( 0x0007FFFFFFE00000 ), + LONG2CHARS( 0x000FFFFFFFE00000 ), + LONG2CHARS( 0x001FFFFFFFE00000 ), + LONG2CHARS( 0x003FFFFFFFE00000 ), + LONG2CHARS( 0x007FFFFFFFE00000 ), + LONG2CHARS( 0x00FFFFFFFFE00000 ), + LONG2CHARS( 0x01FFFFFFFFE00000 ), + LONG2CHARS( 0x03FFFFFFFFE00000 ), + LONG2CHARS( 0x07FFFFFFFFE00000 ), + LONG2CHARS( 0x0FFFFFFFFFE00000 ), + LONG2CHARS( 0x1FFFFFFFFFE00000 ), + LONG2CHARS( 0x3FFFFFFFFFE00000 ), + LONG2CHARS( 0x7FFFFFFFFFE00000 ), + LONG2CHARS( 0xFFFFFFFFFFE00000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000400000 ), + LONG2CHARS( 0x0000000000C00000 ), + LONG2CHARS( 0x0000000001C00000 ), + LONG2CHARS( 0x0000000003C00000 ), + LONG2CHARS( 0x0000000007C00000 ), + LONG2CHARS( 0x000000000FC00000 ), + LONG2CHARS( 0x000000001FC00000 ), + LONG2CHARS( 0x000000003FC00000 ), + LONG2CHARS( 0x000000007FC00000 ), + LONG2CHARS( 0x00000000FFC00000 ), + LONG2CHARS( 0x00000001FFC00000 ), + LONG2CHARS( 0x00000003FFC00000 ), + LONG2CHARS( 0x00000007FFC00000 ), + LONG2CHARS( 0x0000000FFFC00000 ), + LONG2CHARS( 0x0000001FFFC00000 ), + LONG2CHARS( 0x0000003FFFC00000 ), + LONG2CHARS( 0x0000007FFFC00000 ), + LONG2CHARS( 0x000000FFFFC00000 ), + LONG2CHARS( 0x000001FFFFC00000 ), + LONG2CHARS( 0x000003FFFFC00000 ), + LONG2CHARS( 0x000007FFFFC00000 ), + LONG2CHARS( 0x00000FFFFFC00000 ), + LONG2CHARS( 0x00001FFFFFC00000 ), + LONG2CHARS( 0x00003FFFFFC00000 ), + LONG2CHARS( 0x00007FFFFFC00000 ), + LONG2CHARS( 0x0000FFFFFFC00000 ), + LONG2CHARS( 0x0001FFFFFFC00000 ), + LONG2CHARS( 0x0003FFFFFFC00000 ), + LONG2CHARS( 0x0007FFFFFFC00000 ), + LONG2CHARS( 0x000FFFFFFFC00000 ), + LONG2CHARS( 0x001FFFFFFFC00000 ), + LONG2CHARS( 0x003FFFFFFFC00000 ), + LONG2CHARS( 0x007FFFFFFFC00000 ), + LONG2CHARS( 0x00FFFFFFFFC00000 ), + LONG2CHARS( 0x01FFFFFFFFC00000 ), + LONG2CHARS( 0x03FFFFFFFFC00000 ), + LONG2CHARS( 0x07FFFFFFFFC00000 ), + LONG2CHARS( 0x0FFFFFFFFFC00000 ), + LONG2CHARS( 0x1FFFFFFFFFC00000 ), + LONG2CHARS( 0x3FFFFFFFFFC00000 ), + LONG2CHARS( 0x7FFFFFFFFFC00000 ), + LONG2CHARS( 0xFFFFFFFFFFC00000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000800000 ), + LONG2CHARS( 0x0000000001800000 ), + LONG2CHARS( 0x0000000003800000 ), + LONG2CHARS( 0x0000000007800000 ), + LONG2CHARS( 0x000000000F800000 ), + LONG2CHARS( 0x000000001F800000 ), + LONG2CHARS( 0x000000003F800000 ), + LONG2CHARS( 0x000000007F800000 ), + LONG2CHARS( 0x00000000FF800000 ), + LONG2CHARS( 0x00000001FF800000 ), + LONG2CHARS( 0x00000003FF800000 ), + LONG2CHARS( 0x00000007FF800000 ), + LONG2CHARS( 0x0000000FFF800000 ), + LONG2CHARS( 0x0000001FFF800000 ), + LONG2CHARS( 0x0000003FFF800000 ), + LONG2CHARS( 0x0000007FFF800000 ), + LONG2CHARS( 0x000000FFFF800000 ), + LONG2CHARS( 0x000001FFFF800000 ), + LONG2CHARS( 0x000003FFFF800000 ), + LONG2CHARS( 0x000007FFFF800000 ), + LONG2CHARS( 0x00000FFFFF800000 ), + LONG2CHARS( 0x00001FFFFF800000 ), + LONG2CHARS( 0x00003FFFFF800000 ), + LONG2CHARS( 0x00007FFFFF800000 ), + LONG2CHARS( 0x0000FFFFFF800000 ), + LONG2CHARS( 0x0001FFFFFF800000 ), + LONG2CHARS( 0x0003FFFFFF800000 ), + LONG2CHARS( 0x0007FFFFFF800000 ), + LONG2CHARS( 0x000FFFFFFF800000 ), + LONG2CHARS( 0x001FFFFFFF800000 ), + LONG2CHARS( 0x003FFFFFFF800000 ), + LONG2CHARS( 0x007FFFFFFF800000 ), + LONG2CHARS( 0x00FFFFFFFF800000 ), + LONG2CHARS( 0x01FFFFFFFF800000 ), + LONG2CHARS( 0x03FFFFFFFF800000 ), + LONG2CHARS( 0x07FFFFFFFF800000 ), + LONG2CHARS( 0x0FFFFFFFFF800000 ), + LONG2CHARS( 0x1FFFFFFFFF800000 ), + LONG2CHARS( 0x3FFFFFFFFF800000 ), + LONG2CHARS( 0x7FFFFFFFFF800000 ), + LONG2CHARS( 0xFFFFFFFFFF800000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000001000000 ), + LONG2CHARS( 0x0000000003000000 ), + LONG2CHARS( 0x0000000007000000 ), + LONG2CHARS( 0x000000000F000000 ), + LONG2CHARS( 0x000000001F000000 ), + LONG2CHARS( 0x000000003F000000 ), + LONG2CHARS( 0x000000007F000000 ), + LONG2CHARS( 0x00000000FF000000 ), + LONG2CHARS( 0x00000001FF000000 ), + LONG2CHARS( 0x00000003FF000000 ), + LONG2CHARS( 0x00000007FF000000 ), + LONG2CHARS( 0x0000000FFF000000 ), + LONG2CHARS( 0x0000001FFF000000 ), + LONG2CHARS( 0x0000003FFF000000 ), + LONG2CHARS( 0x0000007FFF000000 ), + LONG2CHARS( 0x000000FFFF000000 ), + LONG2CHARS( 0x000001FFFF000000 ), + LONG2CHARS( 0x000003FFFF000000 ), + LONG2CHARS( 0x000007FFFF000000 ), + LONG2CHARS( 0x00000FFFFF000000 ), + LONG2CHARS( 0x00001FFFFF000000 ), + LONG2CHARS( 0x00003FFFFF000000 ), + LONG2CHARS( 0x00007FFFFF000000 ), + LONG2CHARS( 0x0000FFFFFF000000 ), + LONG2CHARS( 0x0001FFFFFF000000 ), + LONG2CHARS( 0x0003FFFFFF000000 ), + LONG2CHARS( 0x0007FFFFFF000000 ), + LONG2CHARS( 0x000FFFFFFF000000 ), + LONG2CHARS( 0x001FFFFFFF000000 ), + LONG2CHARS( 0x003FFFFFFF000000 ), + LONG2CHARS( 0x007FFFFFFF000000 ), + LONG2CHARS( 0x00FFFFFFFF000000 ), + LONG2CHARS( 0x01FFFFFFFF000000 ), + LONG2CHARS( 0x03FFFFFFFF000000 ), + LONG2CHARS( 0x07FFFFFFFF000000 ), + LONG2CHARS( 0x0FFFFFFFFF000000 ), + LONG2CHARS( 0x1FFFFFFFFF000000 ), + LONG2CHARS( 0x3FFFFFFFFF000000 ), + LONG2CHARS( 0x7FFFFFFFFF000000 ), + LONG2CHARS( 0xFFFFFFFFFF000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000002000000 ), + LONG2CHARS( 0x0000000006000000 ), + LONG2CHARS( 0x000000000E000000 ), + LONG2CHARS( 0x000000001E000000 ), + LONG2CHARS( 0x000000003E000000 ), + LONG2CHARS( 0x000000007E000000 ), + LONG2CHARS( 0x00000000FE000000 ), + LONG2CHARS( 0x00000001FE000000 ), + LONG2CHARS( 0x00000003FE000000 ), + LONG2CHARS( 0x00000007FE000000 ), + LONG2CHARS( 0x0000000FFE000000 ), + LONG2CHARS( 0x0000001FFE000000 ), + LONG2CHARS( 0x0000003FFE000000 ), + LONG2CHARS( 0x0000007FFE000000 ), + LONG2CHARS( 0x000000FFFE000000 ), + LONG2CHARS( 0x000001FFFE000000 ), + LONG2CHARS( 0x000003FFFE000000 ), + LONG2CHARS( 0x000007FFFE000000 ), + LONG2CHARS( 0x00000FFFFE000000 ), + LONG2CHARS( 0x00001FFFFE000000 ), + LONG2CHARS( 0x00003FFFFE000000 ), + LONG2CHARS( 0x00007FFFFE000000 ), + LONG2CHARS( 0x0000FFFFFE000000 ), + LONG2CHARS( 0x0001FFFFFE000000 ), + LONG2CHARS( 0x0003FFFFFE000000 ), + LONG2CHARS( 0x0007FFFFFE000000 ), + LONG2CHARS( 0x000FFFFFFE000000 ), + LONG2CHARS( 0x001FFFFFFE000000 ), + LONG2CHARS( 0x003FFFFFFE000000 ), + LONG2CHARS( 0x007FFFFFFE000000 ), + LONG2CHARS( 0x00FFFFFFFE000000 ), + LONG2CHARS( 0x01FFFFFFFE000000 ), + LONG2CHARS( 0x03FFFFFFFE000000 ), + LONG2CHARS( 0x07FFFFFFFE000000 ), + LONG2CHARS( 0x0FFFFFFFFE000000 ), + LONG2CHARS( 0x1FFFFFFFFE000000 ), + LONG2CHARS( 0x3FFFFFFFFE000000 ), + LONG2CHARS( 0x7FFFFFFFFE000000 ), + LONG2CHARS( 0xFFFFFFFFFE000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000004000000 ), + LONG2CHARS( 0x000000000C000000 ), + LONG2CHARS( 0x000000001C000000 ), + LONG2CHARS( 0x000000003C000000 ), + LONG2CHARS( 0x000000007C000000 ), + LONG2CHARS( 0x00000000FC000000 ), + LONG2CHARS( 0x00000001FC000000 ), + LONG2CHARS( 0x00000003FC000000 ), + LONG2CHARS( 0x00000007FC000000 ), + LONG2CHARS( 0x0000000FFC000000 ), + LONG2CHARS( 0x0000001FFC000000 ), + LONG2CHARS( 0x0000003FFC000000 ), + LONG2CHARS( 0x0000007FFC000000 ), + LONG2CHARS( 0x000000FFFC000000 ), + LONG2CHARS( 0x000001FFFC000000 ), + LONG2CHARS( 0x000003FFFC000000 ), + LONG2CHARS( 0x000007FFFC000000 ), + LONG2CHARS( 0x00000FFFFC000000 ), + LONG2CHARS( 0x00001FFFFC000000 ), + LONG2CHARS( 0x00003FFFFC000000 ), + LONG2CHARS( 0x00007FFFFC000000 ), + LONG2CHARS( 0x0000FFFFFC000000 ), + LONG2CHARS( 0x0001FFFFFC000000 ), + LONG2CHARS( 0x0003FFFFFC000000 ), + LONG2CHARS( 0x0007FFFFFC000000 ), + LONG2CHARS( 0x000FFFFFFC000000 ), + LONG2CHARS( 0x001FFFFFFC000000 ), + LONG2CHARS( 0x003FFFFFFC000000 ), + LONG2CHARS( 0x007FFFFFFC000000 ), + LONG2CHARS( 0x00FFFFFFFC000000 ), + LONG2CHARS( 0x01FFFFFFFC000000 ), + LONG2CHARS( 0x03FFFFFFFC000000 ), + LONG2CHARS( 0x07FFFFFFFC000000 ), + LONG2CHARS( 0x0FFFFFFFFC000000 ), + LONG2CHARS( 0x1FFFFFFFFC000000 ), + LONG2CHARS( 0x3FFFFFFFFC000000 ), + LONG2CHARS( 0x7FFFFFFFFC000000 ), + LONG2CHARS( 0xFFFFFFFFFC000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000008000000 ), + LONG2CHARS( 0x0000000018000000 ), + LONG2CHARS( 0x0000000038000000 ), + LONG2CHARS( 0x0000000078000000 ), + LONG2CHARS( 0x00000000F8000000 ), + LONG2CHARS( 0x00000001F8000000 ), + LONG2CHARS( 0x00000003F8000000 ), + LONG2CHARS( 0x00000007F8000000 ), + LONG2CHARS( 0x0000000FF8000000 ), + LONG2CHARS( 0x0000001FF8000000 ), + LONG2CHARS( 0x0000003FF8000000 ), + LONG2CHARS( 0x0000007FF8000000 ), + LONG2CHARS( 0x000000FFF8000000 ), + LONG2CHARS( 0x000001FFF8000000 ), + LONG2CHARS( 0x000003FFF8000000 ), + LONG2CHARS( 0x000007FFF8000000 ), + LONG2CHARS( 0x00000FFFF8000000 ), + LONG2CHARS( 0x00001FFFF8000000 ), + LONG2CHARS( 0x00003FFFF8000000 ), + LONG2CHARS( 0x00007FFFF8000000 ), + LONG2CHARS( 0x0000FFFFF8000000 ), + LONG2CHARS( 0x0001FFFFF8000000 ), + LONG2CHARS( 0x0003FFFFF8000000 ), + LONG2CHARS( 0x0007FFFFF8000000 ), + LONG2CHARS( 0x000FFFFFF8000000 ), + LONG2CHARS( 0x001FFFFFF8000000 ), + LONG2CHARS( 0x003FFFFFF8000000 ), + LONG2CHARS( 0x007FFFFFF8000000 ), + LONG2CHARS( 0x00FFFFFFF8000000 ), + LONG2CHARS( 0x01FFFFFFF8000000 ), + LONG2CHARS( 0x03FFFFFFF8000000 ), + LONG2CHARS( 0x07FFFFFFF8000000 ), + LONG2CHARS( 0x0FFFFFFFF8000000 ), + LONG2CHARS( 0x1FFFFFFFF8000000 ), + LONG2CHARS( 0x3FFFFFFFF8000000 ), + LONG2CHARS( 0x7FFFFFFFF8000000 ), + LONG2CHARS( 0xFFFFFFFFF8000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000010000000 ), + LONG2CHARS( 0x0000000030000000 ), + LONG2CHARS( 0x0000000070000000 ), + LONG2CHARS( 0x00000000F0000000 ), + LONG2CHARS( 0x00000001F0000000 ), + LONG2CHARS( 0x00000003F0000000 ), + LONG2CHARS( 0x00000007F0000000 ), + LONG2CHARS( 0x0000000FF0000000 ), + LONG2CHARS( 0x0000001FF0000000 ), + LONG2CHARS( 0x0000003FF0000000 ), + LONG2CHARS( 0x0000007FF0000000 ), + LONG2CHARS( 0x000000FFF0000000 ), + LONG2CHARS( 0x000001FFF0000000 ), + LONG2CHARS( 0x000003FFF0000000 ), + LONG2CHARS( 0x000007FFF0000000 ), + LONG2CHARS( 0x00000FFFF0000000 ), + LONG2CHARS( 0x00001FFFF0000000 ), + LONG2CHARS( 0x00003FFFF0000000 ), + LONG2CHARS( 0x00007FFFF0000000 ), + LONG2CHARS( 0x0000FFFFF0000000 ), + LONG2CHARS( 0x0001FFFFF0000000 ), + LONG2CHARS( 0x0003FFFFF0000000 ), + LONG2CHARS( 0x0007FFFFF0000000 ), + LONG2CHARS( 0x000FFFFFF0000000 ), + LONG2CHARS( 0x001FFFFFF0000000 ), + LONG2CHARS( 0x003FFFFFF0000000 ), + LONG2CHARS( 0x007FFFFFF0000000 ), + LONG2CHARS( 0x00FFFFFFF0000000 ), + LONG2CHARS( 0x01FFFFFFF0000000 ), + LONG2CHARS( 0x03FFFFFFF0000000 ), + LONG2CHARS( 0x07FFFFFFF0000000 ), + LONG2CHARS( 0x0FFFFFFFF0000000 ), + LONG2CHARS( 0x1FFFFFFFF0000000 ), + LONG2CHARS( 0x3FFFFFFFF0000000 ), + LONG2CHARS( 0x7FFFFFFFF0000000 ), + LONG2CHARS( 0xFFFFFFFFF0000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000020000000 ), + LONG2CHARS( 0x0000000060000000 ), + LONG2CHARS( 0x00000000E0000000 ), + LONG2CHARS( 0x00000001E0000000 ), + LONG2CHARS( 0x00000003E0000000 ), + LONG2CHARS( 0x00000007E0000000 ), + LONG2CHARS( 0x0000000FE0000000 ), + LONG2CHARS( 0x0000001FE0000000 ), + LONG2CHARS( 0x0000003FE0000000 ), + LONG2CHARS( 0x0000007FE0000000 ), + LONG2CHARS( 0x000000FFE0000000 ), + LONG2CHARS( 0x000001FFE0000000 ), + LONG2CHARS( 0x000003FFE0000000 ), + LONG2CHARS( 0x000007FFE0000000 ), + LONG2CHARS( 0x00000FFFE0000000 ), + LONG2CHARS( 0x00001FFFE0000000 ), + LONG2CHARS( 0x00003FFFE0000000 ), + LONG2CHARS( 0x00007FFFE0000000 ), + LONG2CHARS( 0x0000FFFFE0000000 ), + LONG2CHARS( 0x0001FFFFE0000000 ), + LONG2CHARS( 0x0003FFFFE0000000 ), + LONG2CHARS( 0x0007FFFFE0000000 ), + LONG2CHARS( 0x000FFFFFE0000000 ), + LONG2CHARS( 0x001FFFFFE0000000 ), + LONG2CHARS( 0x003FFFFFE0000000 ), + LONG2CHARS( 0x007FFFFFE0000000 ), + LONG2CHARS( 0x00FFFFFFE0000000 ), + LONG2CHARS( 0x01FFFFFFE0000000 ), + LONG2CHARS( 0x03FFFFFFE0000000 ), + LONG2CHARS( 0x07FFFFFFE0000000 ), + LONG2CHARS( 0x0FFFFFFFE0000000 ), + LONG2CHARS( 0x1FFFFFFFE0000000 ), + LONG2CHARS( 0x3FFFFFFFE0000000 ), + LONG2CHARS( 0x7FFFFFFFE0000000 ), + LONG2CHARS( 0xFFFFFFFFE0000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000040000000 ), + LONG2CHARS( 0x00000000C0000000 ), + LONG2CHARS( 0x00000001C0000000 ), + LONG2CHARS( 0x00000003C0000000 ), + LONG2CHARS( 0x00000007C0000000 ), + LONG2CHARS( 0x0000000FC0000000 ), + LONG2CHARS( 0x0000001FC0000000 ), + LONG2CHARS( 0x0000003FC0000000 ), + LONG2CHARS( 0x0000007FC0000000 ), + LONG2CHARS( 0x000000FFC0000000 ), + LONG2CHARS( 0x000001FFC0000000 ), + LONG2CHARS( 0x000003FFC0000000 ), + LONG2CHARS( 0x000007FFC0000000 ), + LONG2CHARS( 0x00000FFFC0000000 ), + LONG2CHARS( 0x00001FFFC0000000 ), + LONG2CHARS( 0x00003FFFC0000000 ), + LONG2CHARS( 0x00007FFFC0000000 ), + LONG2CHARS( 0x0000FFFFC0000000 ), + LONG2CHARS( 0x0001FFFFC0000000 ), + LONG2CHARS( 0x0003FFFFC0000000 ), + LONG2CHARS( 0x0007FFFFC0000000 ), + LONG2CHARS( 0x000FFFFFC0000000 ), + LONG2CHARS( 0x001FFFFFC0000000 ), + LONG2CHARS( 0x003FFFFFC0000000 ), + LONG2CHARS( 0x007FFFFFC0000000 ), + LONG2CHARS( 0x00FFFFFFC0000000 ), + LONG2CHARS( 0x01FFFFFFC0000000 ), + LONG2CHARS( 0x03FFFFFFC0000000 ), + LONG2CHARS( 0x07FFFFFFC0000000 ), + LONG2CHARS( 0x0FFFFFFFC0000000 ), + LONG2CHARS( 0x1FFFFFFFC0000000 ), + LONG2CHARS( 0x3FFFFFFFC0000000 ), + LONG2CHARS( 0x7FFFFFFFC0000000 ), + LONG2CHARS( 0xFFFFFFFFC0000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000080000000 ), + LONG2CHARS( 0x0000000180000000 ), + LONG2CHARS( 0x0000000380000000 ), + LONG2CHARS( 0x0000000780000000 ), + LONG2CHARS( 0x0000000F80000000 ), + LONG2CHARS( 0x0000001F80000000 ), + LONG2CHARS( 0x0000003F80000000 ), + LONG2CHARS( 0x0000007F80000000 ), + LONG2CHARS( 0x000000FF80000000 ), + LONG2CHARS( 0x000001FF80000000 ), + LONG2CHARS( 0x000003FF80000000 ), + LONG2CHARS( 0x000007FF80000000 ), + LONG2CHARS( 0x00000FFF80000000 ), + LONG2CHARS( 0x00001FFF80000000 ), + LONG2CHARS( 0x00003FFF80000000 ), + LONG2CHARS( 0x00007FFF80000000 ), + LONG2CHARS( 0x0000FFFF80000000 ), + LONG2CHARS( 0x0001FFFF80000000 ), + LONG2CHARS( 0x0003FFFF80000000 ), + LONG2CHARS( 0x0007FFFF80000000 ), + LONG2CHARS( 0x000FFFFF80000000 ), + LONG2CHARS( 0x001FFFFF80000000 ), + LONG2CHARS( 0x003FFFFF80000000 ), + LONG2CHARS( 0x007FFFFF80000000 ), + LONG2CHARS( 0x00FFFFFF80000000 ), + LONG2CHARS( 0x01FFFFFF80000000 ), + LONG2CHARS( 0x03FFFFFF80000000 ), + LONG2CHARS( 0x07FFFFFF80000000 ), + LONG2CHARS( 0x0FFFFFFF80000000 ), + LONG2CHARS( 0x1FFFFFFF80000000 ), + LONG2CHARS( 0x3FFFFFFF80000000 ), + LONG2CHARS( 0x7FFFFFFF80000000 ), + LONG2CHARS( 0xFFFFFFFF80000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000100000000 ), + LONG2CHARS( 0x0000000300000000 ), + LONG2CHARS( 0x0000000700000000 ), + LONG2CHARS( 0x0000000F00000000 ), + LONG2CHARS( 0x0000001F00000000 ), + LONG2CHARS( 0x0000003F00000000 ), + LONG2CHARS( 0x0000007F00000000 ), + LONG2CHARS( 0x000000FF00000000 ), + LONG2CHARS( 0x000001FF00000000 ), + LONG2CHARS( 0x000003FF00000000 ), + LONG2CHARS( 0x000007FF00000000 ), + LONG2CHARS( 0x00000FFF00000000 ), + LONG2CHARS( 0x00001FFF00000000 ), + LONG2CHARS( 0x00003FFF00000000 ), + LONG2CHARS( 0x00007FFF00000000 ), + LONG2CHARS( 0x0000FFFF00000000 ), + LONG2CHARS( 0x0001FFFF00000000 ), + LONG2CHARS( 0x0003FFFF00000000 ), + LONG2CHARS( 0x0007FFFF00000000 ), + LONG2CHARS( 0x000FFFFF00000000 ), + LONG2CHARS( 0x001FFFFF00000000 ), + LONG2CHARS( 0x003FFFFF00000000 ), + LONG2CHARS( 0x007FFFFF00000000 ), + LONG2CHARS( 0x00FFFFFF00000000 ), + LONG2CHARS( 0x01FFFFFF00000000 ), + LONG2CHARS( 0x03FFFFFF00000000 ), + LONG2CHARS( 0x07FFFFFF00000000 ), + LONG2CHARS( 0x0FFFFFFF00000000 ), + LONG2CHARS( 0x1FFFFFFF00000000 ), + LONG2CHARS( 0x3FFFFFFF00000000 ), + LONG2CHARS( 0x7FFFFFFF00000000 ), + LONG2CHARS( 0xFFFFFFFF00000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000200000000 ), + LONG2CHARS( 0x0000000600000000 ), + LONG2CHARS( 0x0000000E00000000 ), + LONG2CHARS( 0x0000001E00000000 ), + LONG2CHARS( 0x0000003E00000000 ), + LONG2CHARS( 0x0000007E00000000 ), + LONG2CHARS( 0x000000FE00000000 ), + LONG2CHARS( 0x000001FE00000000 ), + LONG2CHARS( 0x000003FE00000000 ), + LONG2CHARS( 0x000007FE00000000 ), + LONG2CHARS( 0x00000FFE00000000 ), + LONG2CHARS( 0x00001FFE00000000 ), + LONG2CHARS( 0x00003FFE00000000 ), + LONG2CHARS( 0x00007FFE00000000 ), + LONG2CHARS( 0x0000FFFE00000000 ), + LONG2CHARS( 0x0001FFFE00000000 ), + LONG2CHARS( 0x0003FFFE00000000 ), + LONG2CHARS( 0x0007FFFE00000000 ), + LONG2CHARS( 0x000FFFFE00000000 ), + LONG2CHARS( 0x001FFFFE00000000 ), + LONG2CHARS( 0x003FFFFE00000000 ), + LONG2CHARS( 0x007FFFFE00000000 ), + LONG2CHARS( 0x00FFFFFE00000000 ), + LONG2CHARS( 0x01FFFFFE00000000 ), + LONG2CHARS( 0x03FFFFFE00000000 ), + LONG2CHARS( 0x07FFFFFE00000000 ), + LONG2CHARS( 0x0FFFFFFE00000000 ), + LONG2CHARS( 0x1FFFFFFE00000000 ), + LONG2CHARS( 0x3FFFFFFE00000000 ), + LONG2CHARS( 0x7FFFFFFE00000000 ), + LONG2CHARS( 0xFFFFFFFE00000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000400000000 ), + LONG2CHARS( 0x0000000C00000000 ), + LONG2CHARS( 0x0000001C00000000 ), + LONG2CHARS( 0x0000003C00000000 ), + LONG2CHARS( 0x0000007C00000000 ), + LONG2CHARS( 0x000000FC00000000 ), + LONG2CHARS( 0x000001FC00000000 ), + LONG2CHARS( 0x000003FC00000000 ), + LONG2CHARS( 0x000007FC00000000 ), + LONG2CHARS( 0x00000FFC00000000 ), + LONG2CHARS( 0x00001FFC00000000 ), + LONG2CHARS( 0x00003FFC00000000 ), + LONG2CHARS( 0x00007FFC00000000 ), + LONG2CHARS( 0x0000FFFC00000000 ), + LONG2CHARS( 0x0001FFFC00000000 ), + LONG2CHARS( 0x0003FFFC00000000 ), + LONG2CHARS( 0x0007FFFC00000000 ), + LONG2CHARS( 0x000FFFFC00000000 ), + LONG2CHARS( 0x001FFFFC00000000 ), + LONG2CHARS( 0x003FFFFC00000000 ), + LONG2CHARS( 0x007FFFFC00000000 ), + LONG2CHARS( 0x00FFFFFC00000000 ), + LONG2CHARS( 0x01FFFFFC00000000 ), + LONG2CHARS( 0x03FFFFFC00000000 ), + LONG2CHARS( 0x07FFFFFC00000000 ), + LONG2CHARS( 0x0FFFFFFC00000000 ), + LONG2CHARS( 0x1FFFFFFC00000000 ), + LONG2CHARS( 0x3FFFFFFC00000000 ), + LONG2CHARS( 0x7FFFFFFC00000000 ), + LONG2CHARS( 0xFFFFFFFC00000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000800000000 ), + LONG2CHARS( 0x0000001800000000 ), + LONG2CHARS( 0x0000003800000000 ), + LONG2CHARS( 0x0000007800000000 ), + LONG2CHARS( 0x000000F800000000 ), + LONG2CHARS( 0x000001F800000000 ), + LONG2CHARS( 0x000003F800000000 ), + LONG2CHARS( 0x000007F800000000 ), + LONG2CHARS( 0x00000FF800000000 ), + LONG2CHARS( 0x00001FF800000000 ), + LONG2CHARS( 0x00003FF800000000 ), + LONG2CHARS( 0x00007FF800000000 ), + LONG2CHARS( 0x0000FFF800000000 ), + LONG2CHARS( 0x0001FFF800000000 ), + LONG2CHARS( 0x0003FFF800000000 ), + LONG2CHARS( 0x0007FFF800000000 ), + LONG2CHARS( 0x000FFFF800000000 ), + LONG2CHARS( 0x001FFFF800000000 ), + LONG2CHARS( 0x003FFFF800000000 ), + LONG2CHARS( 0x007FFFF800000000 ), + LONG2CHARS( 0x00FFFFF800000000 ), + LONG2CHARS( 0x01FFFFF800000000 ), + LONG2CHARS( 0x03FFFFF800000000 ), + LONG2CHARS( 0x07FFFFF800000000 ), + LONG2CHARS( 0x0FFFFFF800000000 ), + LONG2CHARS( 0x1FFFFFF800000000 ), + LONG2CHARS( 0x3FFFFFF800000000 ), + LONG2CHARS( 0x7FFFFFF800000000 ), + LONG2CHARS( 0xFFFFFFF800000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000001000000000 ), + LONG2CHARS( 0x0000003000000000 ), + LONG2CHARS( 0x0000007000000000 ), + LONG2CHARS( 0x000000F000000000 ), + LONG2CHARS( 0x000001F000000000 ), + LONG2CHARS( 0x000003F000000000 ), + LONG2CHARS( 0x000007F000000000 ), + LONG2CHARS( 0x00000FF000000000 ), + LONG2CHARS( 0x00001FF000000000 ), + LONG2CHARS( 0x00003FF000000000 ), + LONG2CHARS( 0x00007FF000000000 ), + LONG2CHARS( 0x0000FFF000000000 ), + LONG2CHARS( 0x0001FFF000000000 ), + LONG2CHARS( 0x0003FFF000000000 ), + LONG2CHARS( 0x0007FFF000000000 ), + LONG2CHARS( 0x000FFFF000000000 ), + LONG2CHARS( 0x001FFFF000000000 ), + LONG2CHARS( 0x003FFFF000000000 ), + LONG2CHARS( 0x007FFFF000000000 ), + LONG2CHARS( 0x00FFFFF000000000 ), + LONG2CHARS( 0x01FFFFF000000000 ), + LONG2CHARS( 0x03FFFFF000000000 ), + LONG2CHARS( 0x07FFFFF000000000 ), + LONG2CHARS( 0x0FFFFFF000000000 ), + LONG2CHARS( 0x1FFFFFF000000000 ), + LONG2CHARS( 0x3FFFFFF000000000 ), + LONG2CHARS( 0x7FFFFFF000000000 ), + LONG2CHARS( 0xFFFFFFF000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000002000000000 ), + LONG2CHARS( 0x0000006000000000 ), + LONG2CHARS( 0x000000E000000000 ), + LONG2CHARS( 0x000001E000000000 ), + LONG2CHARS( 0x000003E000000000 ), + LONG2CHARS( 0x000007E000000000 ), + LONG2CHARS( 0x00000FE000000000 ), + LONG2CHARS( 0x00001FE000000000 ), + LONG2CHARS( 0x00003FE000000000 ), + LONG2CHARS( 0x00007FE000000000 ), + LONG2CHARS( 0x0000FFE000000000 ), + LONG2CHARS( 0x0001FFE000000000 ), + LONG2CHARS( 0x0003FFE000000000 ), + LONG2CHARS( 0x0007FFE000000000 ), + LONG2CHARS( 0x000FFFE000000000 ), + LONG2CHARS( 0x001FFFE000000000 ), + LONG2CHARS( 0x003FFFE000000000 ), + LONG2CHARS( 0x007FFFE000000000 ), + LONG2CHARS( 0x00FFFFE000000000 ), + LONG2CHARS( 0x01FFFFE000000000 ), + LONG2CHARS( 0x03FFFFE000000000 ), + LONG2CHARS( 0x07FFFFE000000000 ), + LONG2CHARS( 0x0FFFFFE000000000 ), + LONG2CHARS( 0x1FFFFFE000000000 ), + LONG2CHARS( 0x3FFFFFE000000000 ), + LONG2CHARS( 0x7FFFFFE000000000 ), + LONG2CHARS( 0xFFFFFFE000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000004000000000 ), + LONG2CHARS( 0x000000C000000000 ), + LONG2CHARS( 0x000001C000000000 ), + LONG2CHARS( 0x000003C000000000 ), + LONG2CHARS( 0x000007C000000000 ), + LONG2CHARS( 0x00000FC000000000 ), + LONG2CHARS( 0x00001FC000000000 ), + LONG2CHARS( 0x00003FC000000000 ), + LONG2CHARS( 0x00007FC000000000 ), + LONG2CHARS( 0x0000FFC000000000 ), + LONG2CHARS( 0x0001FFC000000000 ), + LONG2CHARS( 0x0003FFC000000000 ), + LONG2CHARS( 0x0007FFC000000000 ), + LONG2CHARS( 0x000FFFC000000000 ), + LONG2CHARS( 0x001FFFC000000000 ), + LONG2CHARS( 0x003FFFC000000000 ), + LONG2CHARS( 0x007FFFC000000000 ), + LONG2CHARS( 0x00FFFFC000000000 ), + LONG2CHARS( 0x01FFFFC000000000 ), + LONG2CHARS( 0x03FFFFC000000000 ), + LONG2CHARS( 0x07FFFFC000000000 ), + LONG2CHARS( 0x0FFFFFC000000000 ), + LONG2CHARS( 0x1FFFFFC000000000 ), + LONG2CHARS( 0x3FFFFFC000000000 ), + LONG2CHARS( 0x7FFFFFC000000000 ), + LONG2CHARS( 0xFFFFFFC000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000008000000000 ), + LONG2CHARS( 0x0000018000000000 ), + LONG2CHARS( 0x0000038000000000 ), + LONG2CHARS( 0x0000078000000000 ), + LONG2CHARS( 0x00000F8000000000 ), + LONG2CHARS( 0x00001F8000000000 ), + LONG2CHARS( 0x00003F8000000000 ), + LONG2CHARS( 0x00007F8000000000 ), + LONG2CHARS( 0x0000FF8000000000 ), + LONG2CHARS( 0x0001FF8000000000 ), + LONG2CHARS( 0x0003FF8000000000 ), + LONG2CHARS( 0x0007FF8000000000 ), + LONG2CHARS( 0x000FFF8000000000 ), + LONG2CHARS( 0x001FFF8000000000 ), + LONG2CHARS( 0x003FFF8000000000 ), + LONG2CHARS( 0x007FFF8000000000 ), + LONG2CHARS( 0x00FFFF8000000000 ), + LONG2CHARS( 0x01FFFF8000000000 ), + LONG2CHARS( 0x03FFFF8000000000 ), + LONG2CHARS( 0x07FFFF8000000000 ), + LONG2CHARS( 0x0FFFFF8000000000 ), + LONG2CHARS( 0x1FFFFF8000000000 ), + LONG2CHARS( 0x3FFFFF8000000000 ), + LONG2CHARS( 0x7FFFFF8000000000 ), + LONG2CHARS( 0xFFFFFF8000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000010000000000 ), + LONG2CHARS( 0x0000030000000000 ), + LONG2CHARS( 0x0000070000000000 ), + LONG2CHARS( 0x00000F0000000000 ), + LONG2CHARS( 0x00001F0000000000 ), + LONG2CHARS( 0x00003F0000000000 ), + LONG2CHARS( 0x00007F0000000000 ), + LONG2CHARS( 0x0000FF0000000000 ), + LONG2CHARS( 0x0001FF0000000000 ), + LONG2CHARS( 0x0003FF0000000000 ), + LONG2CHARS( 0x0007FF0000000000 ), + LONG2CHARS( 0x000FFF0000000000 ), + LONG2CHARS( 0x001FFF0000000000 ), + LONG2CHARS( 0x003FFF0000000000 ), + LONG2CHARS( 0x007FFF0000000000 ), + LONG2CHARS( 0x00FFFF0000000000 ), + LONG2CHARS( 0x01FFFF0000000000 ), + LONG2CHARS( 0x03FFFF0000000000 ), + LONG2CHARS( 0x07FFFF0000000000 ), + LONG2CHARS( 0x0FFFFF0000000000 ), + LONG2CHARS( 0x1FFFFF0000000000 ), + LONG2CHARS( 0x3FFFFF0000000000 ), + LONG2CHARS( 0x7FFFFF0000000000 ), + LONG2CHARS( 0xFFFFFF0000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000020000000000 ), + LONG2CHARS( 0x0000060000000000 ), + LONG2CHARS( 0x00000E0000000000 ), + LONG2CHARS( 0x00001E0000000000 ), + LONG2CHARS( 0x00003E0000000000 ), + LONG2CHARS( 0x00007E0000000000 ), + LONG2CHARS( 0x0000FE0000000000 ), + LONG2CHARS( 0x0001FE0000000000 ), + LONG2CHARS( 0x0003FE0000000000 ), + LONG2CHARS( 0x0007FE0000000000 ), + LONG2CHARS( 0x000FFE0000000000 ), + LONG2CHARS( 0x001FFE0000000000 ), + LONG2CHARS( 0x003FFE0000000000 ), + LONG2CHARS( 0x007FFE0000000000 ), + LONG2CHARS( 0x00FFFE0000000000 ), + LONG2CHARS( 0x01FFFE0000000000 ), + LONG2CHARS( 0x03FFFE0000000000 ), + LONG2CHARS( 0x07FFFE0000000000 ), + LONG2CHARS( 0x0FFFFE0000000000 ), + LONG2CHARS( 0x1FFFFE0000000000 ), + LONG2CHARS( 0x3FFFFE0000000000 ), + LONG2CHARS( 0x7FFFFE0000000000 ), + LONG2CHARS( 0xFFFFFE0000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000040000000000 ), + LONG2CHARS( 0x00000C0000000000 ), + LONG2CHARS( 0x00001C0000000000 ), + LONG2CHARS( 0x00003C0000000000 ), + LONG2CHARS( 0x00007C0000000000 ), + LONG2CHARS( 0x0000FC0000000000 ), + LONG2CHARS( 0x0001FC0000000000 ), + LONG2CHARS( 0x0003FC0000000000 ), + LONG2CHARS( 0x0007FC0000000000 ), + LONG2CHARS( 0x000FFC0000000000 ), + LONG2CHARS( 0x001FFC0000000000 ), + LONG2CHARS( 0x003FFC0000000000 ), + LONG2CHARS( 0x007FFC0000000000 ), + LONG2CHARS( 0x00FFFC0000000000 ), + LONG2CHARS( 0x01FFFC0000000000 ), + LONG2CHARS( 0x03FFFC0000000000 ), + LONG2CHARS( 0x07FFFC0000000000 ), + LONG2CHARS( 0x0FFFFC0000000000 ), + LONG2CHARS( 0x1FFFFC0000000000 ), + LONG2CHARS( 0x3FFFFC0000000000 ), + LONG2CHARS( 0x7FFFFC0000000000 ), + LONG2CHARS( 0xFFFFFC0000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000080000000000 ), + LONG2CHARS( 0x0000180000000000 ), + LONG2CHARS( 0x0000380000000000 ), + LONG2CHARS( 0x0000780000000000 ), + LONG2CHARS( 0x0000F80000000000 ), + LONG2CHARS( 0x0001F80000000000 ), + LONG2CHARS( 0x0003F80000000000 ), + LONG2CHARS( 0x0007F80000000000 ), + LONG2CHARS( 0x000FF80000000000 ), + LONG2CHARS( 0x001FF80000000000 ), + LONG2CHARS( 0x003FF80000000000 ), + LONG2CHARS( 0x007FF80000000000 ), + LONG2CHARS( 0x00FFF80000000000 ), + LONG2CHARS( 0x01FFF80000000000 ), + LONG2CHARS( 0x03FFF80000000000 ), + LONG2CHARS( 0x07FFF80000000000 ), + LONG2CHARS( 0x0FFFF80000000000 ), + LONG2CHARS( 0x1FFFF80000000000 ), + LONG2CHARS( 0x3FFFF80000000000 ), + LONG2CHARS( 0x7FFFF80000000000 ), + LONG2CHARS( 0xFFFFF80000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000100000000000 ), + LONG2CHARS( 0x0000300000000000 ), + LONG2CHARS( 0x0000700000000000 ), + LONG2CHARS( 0x0000F00000000000 ), + LONG2CHARS( 0x0001F00000000000 ), + LONG2CHARS( 0x0003F00000000000 ), + LONG2CHARS( 0x0007F00000000000 ), + LONG2CHARS( 0x000FF00000000000 ), + LONG2CHARS( 0x001FF00000000000 ), + LONG2CHARS( 0x003FF00000000000 ), + LONG2CHARS( 0x007FF00000000000 ), + LONG2CHARS( 0x00FFF00000000000 ), + LONG2CHARS( 0x01FFF00000000000 ), + LONG2CHARS( 0x03FFF00000000000 ), + LONG2CHARS( 0x07FFF00000000000 ), + LONG2CHARS( 0x0FFFF00000000000 ), + LONG2CHARS( 0x1FFFF00000000000 ), + LONG2CHARS( 0x3FFFF00000000000 ), + LONG2CHARS( 0x7FFFF00000000000 ), + LONG2CHARS( 0xFFFFF00000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000200000000000 ), + LONG2CHARS( 0x0000600000000000 ), + LONG2CHARS( 0x0000E00000000000 ), + LONG2CHARS( 0x0001E00000000000 ), + LONG2CHARS( 0x0003E00000000000 ), + LONG2CHARS( 0x0007E00000000000 ), + LONG2CHARS( 0x000FE00000000000 ), + LONG2CHARS( 0x001FE00000000000 ), + LONG2CHARS( 0x003FE00000000000 ), + LONG2CHARS( 0x007FE00000000000 ), + LONG2CHARS( 0x00FFE00000000000 ), + LONG2CHARS( 0x01FFE00000000000 ), + LONG2CHARS( 0x03FFE00000000000 ), + LONG2CHARS( 0x07FFE00000000000 ), + LONG2CHARS( 0x0FFFE00000000000 ), + LONG2CHARS( 0x1FFFE00000000000 ), + LONG2CHARS( 0x3FFFE00000000000 ), + LONG2CHARS( 0x7FFFE00000000000 ), + LONG2CHARS( 0xFFFFE00000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000400000000000 ), + LONG2CHARS( 0x0000C00000000000 ), + LONG2CHARS( 0x0001C00000000000 ), + LONG2CHARS( 0x0003C00000000000 ), + LONG2CHARS( 0x0007C00000000000 ), + LONG2CHARS( 0x000FC00000000000 ), + LONG2CHARS( 0x001FC00000000000 ), + LONG2CHARS( 0x003FC00000000000 ), + LONG2CHARS( 0x007FC00000000000 ), + LONG2CHARS( 0x00FFC00000000000 ), + LONG2CHARS( 0x01FFC00000000000 ), + LONG2CHARS( 0x03FFC00000000000 ), + LONG2CHARS( 0x07FFC00000000000 ), + LONG2CHARS( 0x0FFFC00000000000 ), + LONG2CHARS( 0x1FFFC00000000000 ), + LONG2CHARS( 0x3FFFC00000000000 ), + LONG2CHARS( 0x7FFFC00000000000 ), + LONG2CHARS( 0xFFFFC00000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000800000000000 ), + LONG2CHARS( 0x0001800000000000 ), + LONG2CHARS( 0x0003800000000000 ), + LONG2CHARS( 0x0007800000000000 ), + LONG2CHARS( 0x000F800000000000 ), + LONG2CHARS( 0x001F800000000000 ), + LONG2CHARS( 0x003F800000000000 ), + LONG2CHARS( 0x007F800000000000 ), + LONG2CHARS( 0x00FF800000000000 ), + LONG2CHARS( 0x01FF800000000000 ), + LONG2CHARS( 0x03FF800000000000 ), + LONG2CHARS( 0x07FF800000000000 ), + LONG2CHARS( 0x0FFF800000000000 ), + LONG2CHARS( 0x1FFF800000000000 ), + LONG2CHARS( 0x3FFF800000000000 ), + LONG2CHARS( 0x7FFF800000000000 ), + LONG2CHARS( 0xFFFF800000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0001000000000000 ), + LONG2CHARS( 0x0003000000000000 ), + LONG2CHARS( 0x0007000000000000 ), + LONG2CHARS( 0x000F000000000000 ), + LONG2CHARS( 0x001F000000000000 ), + LONG2CHARS( 0x003F000000000000 ), + LONG2CHARS( 0x007F000000000000 ), + LONG2CHARS( 0x00FF000000000000 ), + LONG2CHARS( 0x01FF000000000000 ), + LONG2CHARS( 0x03FF000000000000 ), + LONG2CHARS( 0x07FF000000000000 ), + LONG2CHARS( 0x0FFF000000000000 ), + LONG2CHARS( 0x1FFF000000000000 ), + LONG2CHARS( 0x3FFF000000000000 ), + LONG2CHARS( 0x7FFF000000000000 ), + LONG2CHARS( 0xFFFF000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0002000000000000 ), + LONG2CHARS( 0x0006000000000000 ), + LONG2CHARS( 0x000E000000000000 ), + LONG2CHARS( 0x001E000000000000 ), + LONG2CHARS( 0x003E000000000000 ), + LONG2CHARS( 0x007E000000000000 ), + LONG2CHARS( 0x00FE000000000000 ), + LONG2CHARS( 0x01FE000000000000 ), + LONG2CHARS( 0x03FE000000000000 ), + LONG2CHARS( 0x07FE000000000000 ), + LONG2CHARS( 0x0FFE000000000000 ), + LONG2CHARS( 0x1FFE000000000000 ), + LONG2CHARS( 0x3FFE000000000000 ), + LONG2CHARS( 0x7FFE000000000000 ), + LONG2CHARS( 0xFFFE000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0004000000000000 ), + LONG2CHARS( 0x000C000000000000 ), + LONG2CHARS( 0x001C000000000000 ), + LONG2CHARS( 0x003C000000000000 ), + LONG2CHARS( 0x007C000000000000 ), + LONG2CHARS( 0x00FC000000000000 ), + LONG2CHARS( 0x01FC000000000000 ), + LONG2CHARS( 0x03FC000000000000 ), + LONG2CHARS( 0x07FC000000000000 ), + LONG2CHARS( 0x0FFC000000000000 ), + LONG2CHARS( 0x1FFC000000000000 ), + LONG2CHARS( 0x3FFC000000000000 ), + LONG2CHARS( 0x7FFC000000000000 ), + LONG2CHARS( 0xFFFC000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0008000000000000 ), + LONG2CHARS( 0x0018000000000000 ), + LONG2CHARS( 0x0038000000000000 ), + LONG2CHARS( 0x0078000000000000 ), + LONG2CHARS( 0x00F8000000000000 ), + LONG2CHARS( 0x01F8000000000000 ), + LONG2CHARS( 0x03F8000000000000 ), + LONG2CHARS( 0x07F8000000000000 ), + LONG2CHARS( 0x0FF8000000000000 ), + LONG2CHARS( 0x1FF8000000000000 ), + LONG2CHARS( 0x3FF8000000000000 ), + LONG2CHARS( 0x7FF8000000000000 ), + LONG2CHARS( 0xFFF8000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0010000000000000 ), + LONG2CHARS( 0x0030000000000000 ), + LONG2CHARS( 0x0070000000000000 ), + LONG2CHARS( 0x00F0000000000000 ), + LONG2CHARS( 0x01F0000000000000 ), + LONG2CHARS( 0x03F0000000000000 ), + LONG2CHARS( 0x07F0000000000000 ), + LONG2CHARS( 0x0FF0000000000000 ), + LONG2CHARS( 0x1FF0000000000000 ), + LONG2CHARS( 0x3FF0000000000000 ), + LONG2CHARS( 0x7FF0000000000000 ), + LONG2CHARS( 0xFFF0000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0020000000000000 ), + LONG2CHARS( 0x0060000000000000 ), + LONG2CHARS( 0x00E0000000000000 ), + LONG2CHARS( 0x01E0000000000000 ), + LONG2CHARS( 0x03E0000000000000 ), + LONG2CHARS( 0x07E0000000000000 ), + LONG2CHARS( 0x0FE0000000000000 ), + LONG2CHARS( 0x1FE0000000000000 ), + LONG2CHARS( 0x3FE0000000000000 ), + LONG2CHARS( 0x7FE0000000000000 ), + LONG2CHARS( 0xFFE0000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0040000000000000 ), + LONG2CHARS( 0x00C0000000000000 ), + LONG2CHARS( 0x01C0000000000000 ), + LONG2CHARS( 0x03C0000000000000 ), + LONG2CHARS( 0x07C0000000000000 ), + LONG2CHARS( 0x0FC0000000000000 ), + LONG2CHARS( 0x1FC0000000000000 ), + LONG2CHARS( 0x3FC0000000000000 ), + LONG2CHARS( 0x7FC0000000000000 ), + LONG2CHARS( 0xFFC0000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0080000000000000 ), + LONG2CHARS( 0x0180000000000000 ), + LONG2CHARS( 0x0380000000000000 ), + LONG2CHARS( 0x0780000000000000 ), + LONG2CHARS( 0x0F80000000000000 ), + LONG2CHARS( 0x1F80000000000000 ), + LONG2CHARS( 0x3F80000000000000 ), + LONG2CHARS( 0x7F80000000000000 ), + LONG2CHARS( 0xFF80000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0100000000000000 ), + LONG2CHARS( 0x0300000000000000 ), + LONG2CHARS( 0x0700000000000000 ), + LONG2CHARS( 0x0F00000000000000 ), + LONG2CHARS( 0x1F00000000000000 ), + LONG2CHARS( 0x3F00000000000000 ), + LONG2CHARS( 0x7F00000000000000 ), + LONG2CHARS( 0xFF00000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0200000000000000 ), + LONG2CHARS( 0x0600000000000000 ), + LONG2CHARS( 0x0E00000000000000 ), + LONG2CHARS( 0x1E00000000000000 ), + LONG2CHARS( 0x3E00000000000000 ), + LONG2CHARS( 0x7E00000000000000 ), + LONG2CHARS( 0xFE00000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0400000000000000 ), + LONG2CHARS( 0x0C00000000000000 ), + LONG2CHARS( 0x1C00000000000000 ), + LONG2CHARS( 0x3C00000000000000 ), + LONG2CHARS( 0x7C00000000000000 ), + LONG2CHARS( 0xFC00000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0800000000000000 ), + LONG2CHARS( 0x1800000000000000 ), + LONG2CHARS( 0x3800000000000000 ), + LONG2CHARS( 0x7800000000000000 ), + LONG2CHARS( 0xF800000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x1000000000000000 ), + LONG2CHARS( 0x3000000000000000 ), + LONG2CHARS( 0x7000000000000000 ), + LONG2CHARS( 0xF000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x2000000000000000 ), + LONG2CHARS( 0x6000000000000000 ), + LONG2CHARS( 0xE000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x4000000000000000 ), + LONG2CHARS( 0xC000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, + { + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x8000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + LONG2CHARS( 0x0000000000000000 ), + }, +}; +#endif /* PPW */ +#endif + + +/* used for masking bits in bresenham lines + mask[n] is used to mask out all but bit n in a longword (n is a +screen position). + rmask[n] is used to mask out the single bit at position n (n +is a screen posiotion.) +*/ + +#define _1_ ((PixelType)1) + +#if (BITMAP_BIT_ORDER == MSBFirst) +PixelType mask[PPW] = + { +#if PPW == 64 + LONG2CHARS( _1_<<63 ), LONG2CHARS( 1L<<62 ), LONG2CHARS( 1L<<61 ), + LONG2CHARS( 1L<<60 ), LONG2CHARS( 1L<<59 ), + LONG2CHARS( 1L<<58 ), LONG2CHARS( 1L<<57 ), LONG2CHARS( 1L<<56 ), + LONG2CHARS( 1L<<55 ), LONG2CHARS( 1L<<54 ), LONG2CHARS( 1L<<53 ), + LONG2CHARS( 1L<<52 ), LONG2CHARS( 1L<<51 ), LONG2CHARS( 1L<<50 ), + LONG2CHARS( 1L<<49 ), LONG2CHARS( 1L<<48 ), LONG2CHARS( 1L<<47 ), + LONG2CHARS( 1L<<46 ), LONG2CHARS( 1L<<45 ), LONG2CHARS( 1L<<44 ), + LONG2CHARS( 1L<<43 ), LONG2CHARS( 1L<<42 ), LONG2CHARS( 1L<<41 ), + LONG2CHARS( 1L<<40 ), LONG2CHARS( 1L<<39 ), LONG2CHARS( 1L<<38 ), + LONG2CHARS( 1L<<37 ), LONG2CHARS( 1L<<36 ), LONG2CHARS( 1L<<35 ), + LONG2CHARS( 1L<<34 ), LONG2CHARS( 1L<<33 ), LONG2CHARS( 1L<<32 ), +#endif /* PPW */ + LONG2CHARS( _1_<<31 ), LONG2CHARS( 1<<30 ), LONG2CHARS( 1<<29 ), + LONG2CHARS( 1<<28 ), LONG2CHARS( 1<<27 ), LONG2CHARS( 1<<26 ), + LONG2CHARS( 1<<25 ), LONG2CHARS( 1<<24 ), LONG2CHARS( 1<<23 ), + LONG2CHARS( 1<<22 ), LONG2CHARS( 1<<21 ), LONG2CHARS( 1<<20 ), + LONG2CHARS( 1<<19 ), LONG2CHARS( 1<<18 ), LONG2CHARS( 1<<17 ), + LONG2CHARS( 1<<16 ), LONG2CHARS( 1<<15 ), LONG2CHARS( 1<<14 ), + LONG2CHARS( 1<<13 ), LONG2CHARS( 1<<12 ), LONG2CHARS( 1<<11 ), + LONG2CHARS( 1<<10 ), LONG2CHARS( 1<<9 ), LONG2CHARS( 1<<8 ), + LONG2CHARS( 1<<7 ), LONG2CHARS( 1<<6 ), LONG2CHARS( 1<<5 ), + LONG2CHARS( 1<<4 ), LONG2CHARS( 1<<3 ), LONG2CHARS( 1<<2 ), + LONG2CHARS( 1<<1 ), LONG2CHARS( 1<<0 ) + }; + +PixelType rmask[] = + { +#if PPW == 64 + 0xffffffffffffffff ^ LONG2CHARS( _1_<<63 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<62 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<61 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<60 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<59 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<58 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<57 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<56 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<55 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<54 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<53 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<52 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<51 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<50 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<49 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<48 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<47 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<46 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<45 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<44 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<43 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<42 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<41 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<40 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<39 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<38 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<37 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<36 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<35 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<34 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<33 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<32 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<31 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<30 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<29 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<28 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<27 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<26 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<25 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<24 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<23 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<22 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<21 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<20 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<19 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<18 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<17 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<16 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<15 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<14 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<13 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<12 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<11 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<10 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<9 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<8 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<7 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<6 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<5 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<4 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<3 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<2 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<1 ), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<0 ) +#else /* PPW */ + 0xffffffff ^ LONG2CHARS( _1_<<31 ), 0xffffffff ^ LONG2CHARS( 1<<30 ), + 0xffffffff ^ LONG2CHARS( 1<<29 ), 0xffffffff ^ LONG2CHARS( 1<<28), + 0xffffffff ^ LONG2CHARS( 1<<27 ), 0xffffffff ^ LONG2CHARS( 1<<26), + 0xffffffff ^ LONG2CHARS( 1<<25 ), 0xffffffff ^ LONG2CHARS( 1<<24 ), + 0xffffffff ^ LONG2CHARS( 1<<23 ), 0xffffffff ^ LONG2CHARS( 1<<22), + 0xffffffff ^ LONG2CHARS( 1<<21 ), 0xffffffff ^ LONG2CHARS( 1<<20), + 0xffffffff ^ LONG2CHARS( 1<<19 ), 0xffffffff ^ LONG2CHARS( 1<<18 ), + 0xffffffff ^ LONG2CHARS( 1<<17 ), 0xffffffff ^ LONG2CHARS( 1<<16), + 0xffffffff ^ LONG2CHARS( 1<<15 ), 0xffffffff ^ LONG2CHARS( 1<<14), + 0xffffffff ^ LONG2CHARS( 1<<13 ), 0xffffffff ^ LONG2CHARS( 1<<12 ), + 0xffffffff ^ LONG2CHARS( 1<<11 ), 0xffffffff ^ LONG2CHARS( 1<<10), + 0xffffffff ^ LONG2CHARS( 1<<9 ), 0xffffffff ^ LONG2CHARS( 1<<8), + 0xffffffff ^ LONG2CHARS( 1<<7 ), 0xffffffff ^ LONG2CHARS( 1<<6), + 0xffffffff ^ LONG2CHARS( 1<<5 ), 0xffffffff ^ LONG2CHARS( 1<<4), + 0xffffffff ^ LONG2CHARS( 1<<3 ), 0xffffffff ^ LONG2CHARS( 1<<2), + 0xffffffff ^ LONG2CHARS( 1<<1 ), 0xffffffff ^ LONG2CHARS( 1<<0) +#endif /* PPW */ + }; +#else /* LSBFirst */ +PixelType mask[] = + { + LONG2CHARS( 1<<0 ), LONG2CHARS( 1<<1 ), LONG2CHARS( 1<<2), + LONG2CHARS( 1<<3 ), LONG2CHARS( 1<<4 ), LONG2CHARS( 1<<5), + LONG2CHARS( 1<<6 ), LONG2CHARS( 1<<7 ), LONG2CHARS( 1<<8), + LONG2CHARS( 1<<9 ), LONG2CHARS( 1<<10 ), LONG2CHARS( 1<<11), + LONG2CHARS( 1<<12 ), LONG2CHARS( 1<<13 ), LONG2CHARS( 1<<14), + LONG2CHARS( 1<<15 ), LONG2CHARS( 1<<16 ), LONG2CHARS( 1<<17), + LONG2CHARS( 1<<18 ), LONG2CHARS( 1<<19 ), LONG2CHARS( 1<<20), + LONG2CHARS( 1<<21 ), LONG2CHARS( 1<<22 ), LONG2CHARS( 1<<23), + LONG2CHARS( 1<<24 ), LONG2CHARS( 1<<25 ), LONG2CHARS( 1<<26), + LONG2CHARS( 1<<27 ), LONG2CHARS( 1<<28 ), LONG2CHARS( 1<<29), + LONG2CHARS( 1<<30 ), LONG2CHARS( _1_<<31 ) +#if PPW == 64 + , + LONG2CHARS( 1L<<32), + LONG2CHARS( 1L<<33 ), LONG2CHARS( 1L<<34 ), LONG2CHARS( 1L<<35), + LONG2CHARS( 1L<<36 ), LONG2CHARS( 1L<<37 ), LONG2CHARS( 1L<<38), + LONG2CHARS( 1L<<39 ), LONG2CHARS( 1L<<40 ), LONG2CHARS( 1L<<41), + LONG2CHARS( 1L<<42 ), LONG2CHARS( 1L<<43 ), LONG2CHARS( 1L<<44), + LONG2CHARS( 1L<<45 ), LONG2CHARS( 1L<<46 ), LONG2CHARS( 1L<<47), + LONG2CHARS( 1L<<48 ), LONG2CHARS( 1L<<49 ), LONG2CHARS( 1L<<50), + LONG2CHARS( 1L<<51 ), LONG2CHARS( 1L<<52 ), LONG2CHARS( 1L<<53), + LONG2CHARS( 1L<<54 ), LONG2CHARS( 1L<<55 ), LONG2CHARS( 1L<<56), + LONG2CHARS( 1L<<57 ), LONG2CHARS( 1L<<58 ), LONG2CHARS( 1L<<59), + LONG2CHARS( 1L<<60 ), LONG2CHARS( 1L<<61 ), + LONG2CHARS( 1L<<62 ), LONG2CHARS( _1_<<63 ), +#endif /* PPW */ + }; +PixelType rmask[] = + { +#if PPW == 32 + 0xffffffff ^ LONG2CHARS( 1<<0), 0xffffffff ^ LONG2CHARS( 1<<1), + 0xffffffff ^ LONG2CHARS( 1<<2), 0xffffffff ^ LONG2CHARS( 1<<3), + 0xffffffff ^ LONG2CHARS( 1<<4), 0xffffffff ^ LONG2CHARS( 1<<5), + 0xffffffff ^ LONG2CHARS( 1<<6), 0xffffffff ^ LONG2CHARS( 1<<7), + 0xffffffff ^ LONG2CHARS( 1<<8), 0xffffffff ^ LONG2CHARS( 1<<9), + 0xffffffff ^ LONG2CHARS( 1<<10), 0xffffffff ^ LONG2CHARS( 1<<11), + 0xffffffff ^ LONG2CHARS( 1<<12), 0xffffffff ^ LONG2CHARS( 1<<13), + 0xffffffff ^ LONG2CHARS( 1<<14), 0xffffffff ^ LONG2CHARS( 1<<15), + 0xffffffff ^ LONG2CHARS( 1<<16), 0xffffffff ^ LONG2CHARS( 1<<17), + 0xffffffff ^ LONG2CHARS( 1<<18), 0xffffffff ^ LONG2CHARS( 1<<19), + 0xffffffff ^ LONG2CHARS( 1<<20), 0xffffffff ^ LONG2CHARS( 1<<21), + 0xffffffff ^ LONG2CHARS( 1<<22), 0xffffffff ^ LONG2CHARS( 1<<23), + 0xffffffff ^ LONG2CHARS( 1<<24), 0xffffffff ^ LONG2CHARS( 1<<25), + 0xffffffff ^ LONG2CHARS( 1<<26), 0xffffffff ^ LONG2CHARS( 1<<27), + 0xffffffff ^ LONG2CHARS( 1<<28), 0xffffffff ^ LONG2CHARS( 1<<29), + 0xffffffff ^ LONG2CHARS( 1<<30), 0xffffffff ^ LONG2CHARS( _1_<<31) +#else /* PPW */ + 0xffffffffffffffff ^ LONG2CHARS( 1L<<0), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<1), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<2), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<3), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<4), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<5), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<6), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<7), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<8), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<9), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<10), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<11), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<12), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<13), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<14), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<15), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<16), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<17), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<18), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<19), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<20), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<21), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<22), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<23), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<24), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<25), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<26), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<27), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<28), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<29), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<30), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<31), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<32), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<33), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<34), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<35), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<36), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<37), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<38), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<39), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<40), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<41), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<42), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<43), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<44), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<45), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<46), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<47), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<48), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<49), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<50), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<51), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<52), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<53), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<54), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<55), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<56), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<57), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<58), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<59), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<60), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<61), + 0xffffffffffffffff ^ LONG2CHARS( 1L<<62), + 0xffffffffffffffff ^ LONG2CHARS( _1_<<63), +#endif /* PPW */ + }; +#endif /* BITMAP_BIT_ORDER */ + +#undef _1_ + +/* + * Merge raster ops for full src + dest + plane mask + * + * More clever usage of boolean arithmetic to reduce the + * cost of complex raster ops. This is for bitblt and + * reduces all 16 raster ops + planemask to a single + * expression: + * + * dst = dst & (src & ca1 ^ cx1) ^ (src & ca2 ^ cx2) + * + * The array below contains the values for c?? for each + * raster op. Those values are further modified by + * planemasks on multi-plane displays as follows: + * + * ca1 &= pm; + * cx1 |= ~pm; + * ca2 &= pm; + * cx2 &= pm; + */ + +#include "mergerop.h" + +#define O 0 +#define I ~((unsigned long)0) + +mergeRopRec mergeRopBits[16] = { +O,O,O,O, /* clear 0x0 0 */ +I,O,O,O, /* and 0x1 src AND dst */ +I,O,I,O, /* andReverse 0x2 src AND NOT dst */ +O,O,I,O, /* copy 0x3 src */ +I,I,O,O, /* andInverted 0x4 NOT src AND dst */ +O,I,O,O, /* noop 0x5 dst */ +O,I,I,O, /* xor 0x6 src XOR dst */ +I,I,I,O, /* or 0x7 src OR dst */ +I,I,I,I, /* nor 0x8 NOT src AND NOT dst */ +O,I,I,I, /* equiv 0x9 NOT src XOR dst */ +O,I,O,I, /* invert 0xa NOT dst */ +I,I,O,I, /* orReverse 0xb src OR NOT dst */ +O,O,I,I, /* copyInverted 0xc NOT src */ +I,O,I,I, /* orInverted 0xd NOT src OR dst */ +I,O,O,I, /* nand 0xe NOT src OR NOT dst */ +O,O,O,I, /* set 0xf 1 */ +}; + +#undef O +#undef I diff --git a/mfb/maskbits.h b/mfb/maskbits.h new file mode 100644 index 000000000..e8a7faa90 --- /dev/null +++ b/mfb/maskbits.h @@ -0,0 +1,711 @@ +/* Combined Purdue/PurduePlus patches, level 2.1, 1/24/89 */ +/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: maskbits.h,v 1.3 2000/08/17 19:53:34 cpqbld Exp $ */ +#include "X.h" +#include "Xmd.h" +#include "servermd.h" + + +/* the following notes use the following conventions: +SCREEN LEFT SCREEN RIGHT +in this file and maskbits.c, left and right refer to screen coordinates, +NOT bit numbering in registers. + +starttab[n] + bits[0,n-1] = 0 bits[n,PLST] = 1 +endtab[n] = + bits[0,n-1] = 1 bits[n,PLST] = 0 + +startpartial[], endpartial[] + these are used as accelerators for doing putbits and masking out +bits that are all contained between longword boudaries. the extra +256 bytes of data seems a small price to pay -- code is smaller, +and narrow things (e.g. window borders) go faster. + +the names may seem misleading; they are derived not from which end +of the word the bits are turned on, but at which end of a scanline +the table tends to be used. + +look at the tables and macros to understand boundary conditions. +(careful readers will note that starttab[n] = ~endtab[n] for n != 0) + +----------------------------------------------------------------------- +these two macros depend on the screen's bit ordering. +in both of them x is a screen position. they are used to +combine bits collected from multiple longwords into a +single destination longword, and to unpack a single +source longword into multiple destinations. + +SCRLEFT(dst, x) + takes dst[x, PPW] and moves them to dst[0, PPW-x] + the contents of the rest of dst are 0. + this is a right shift on LSBFirst (forward-thinking) + machines like the VAX, and left shift on MSBFirst + (backwards) machines like the 680x0 and pc/rt. + +SCRRIGHT(dst, x) + takes dst[0,x] and moves them to dst[PPW-x, PPW] + the contents of the rest of dst are 0. + this is a left shift on LSBFirst, right shift + on MSBFirst. + + +the remaining macros are cpu-independent; all bit order dependencies +are built into the tables and the two macros above. + +maskbits(x, w, startmask, endmask, nlw) + for a span of width w starting at position x, returns +a mask for ragged bits at start, mask for ragged bits at end, +and the number of whole longwords between the ends. + +maskpartialbits(x, w, mask) + works like maskbits(), except all the bits are in the + same longword (i.e. (x&PIM + w) <= PPW) + +maskPPWbits(x, w, startmask, endmask, nlw) + as maskbits, but does not calculate nlw. it is used by + mfbGlyphBlt to put down glyphs <= PPW bits wide. + +------------------------------------------------------------------- + +NOTE + any pointers passed to the following 4 macros are + guranteed to be PPW-bit aligned. + The only non-PPW-bit-aligned references ever made are + to font glyphs, and those are made with getleftbits() + and getshiftedleftbits (qq.v.) + + For 64-bit server, it is assumed that we will never have font padding + of more than 4 bytes. The code uses int's to access the fonts + intead of longs. + +getbits(psrc, x, w, dst) + starting at position x in psrc (x < PPW), collect w + bits and put them in the screen left portion of dst. + psrc is a longword pointer. this may span longword boundaries. + it special-cases fetching all w bits from one longword. + + +--------+--------+ +--------+ + | | m |n| | ==> | m |n| | + +--------+--------+ +--------+ + x x+w 0 w + psrc psrc+1 dst + m = PPW - x + n = w - m + + implementation: + get m bits, move to screen-left of dst, zeroing rest of dst; + get n bits from next word, move screen-right by m, zeroing + lower m bits of word. + OR the two things together. + +putbits(src, x, w, pdst) + starting at position x in pdst, put down the screen-leftmost + w bits of src. pdst is a longword pointer. this may + span longword boundaries. + it special-cases putting all w bits into the same longword. + + +--------+ +--------+--------+ + | m |n| | ==> | | m |n| | + +--------+ +--------+--------+ + 0 w x x+w + dst pdst pdst+1 + m = PPW - x + n = w - m + + implementation: + get m bits, shift screen-right by x, zero screen-leftmost x + bits; zero rightmost m bits of *pdst and OR in stuff + from before the semicolon. + shift src screen-left by m, zero bits n-PPW; + zero leftmost n bits of *(pdst+1) and OR in the + stuff from before the semicolon. + +putbitsrop(src, x, w, pdst, ROP) + like putbits but calls DoRop with the rasterop ROP (see mfb.h for + DoRop) + +putbitsrrop(src, x, w, pdst, ROP) + like putbits but calls DoRRop with the reduced rasterop ROP + (see mfb.h for DoRRop) + +----------------------------------------------------------------------- + The two macros below are used only for getting bits from glyphs +in fonts, and glyphs in fonts are gotten only with the following two +mcros. + You should tune these macros toyour font format and cpu +byte ordering. + +NOTE +getleftbits(psrc, w, dst) + get the leftmost w (w<=32) bits from *psrc and put them + in dst. this is used by the mfbGlyphBlt code for glyphs + <=PPW bits wide. + psrc is declared (unsigned char *) + + psrc is NOT guaranteed to be PPW-bit aligned. on many + machines this will cause problems, so there are several + versions of this macro. + + this macro is called ONLY for getting bits from font glyphs, + and depends on the server-natural font padding. + + for blazing text performance, you want this macro + to touch memory as infrequently as possible (e.g. + fetch longwords) and as efficiently as possible + (e.g. don't fetch misaligned longwords) + +getshiftedleftbits(psrc, offset, w, dst) + used by the font code; like getleftbits, but shifts the + bits SCRLEFT by offset. + this is implemented portably, calling getleftbits() + and SCRLEFT(). + psrc is declared (unsigned char *). +*/ + +/* to match CFB and allow algorithm sharing ... + * name mfb32 mfb64 explanation + * ---- ------ ----- ----------- + * PGSZ 32 64 pixel group size (in bits; same as PPW for mfb) + * PGSZB 4 8 pixel group size (in bytes) + * PPW 32 64 pixels per word (pixels per pixel group) + * PLST 31 63 index of last pixel in a word (should be PPW-1) + * PIM 0x1f 0x3f pixel index mask (index within a pixel group) + * PWSH 5 6 pixel-to-word shift (should be log2(PPW)) + * + * The MFB_ versions are here so that cfb can include maskbits.h to get + * the bitmap constants without conflicting with its own P* constants. + */ + +/* warning: PixelType definition duplicated in mfb.h */ +#ifndef PixelType +#define PixelType unsigned long +#endif /* PixelType */ + +#ifdef LONG64 +#define MFB_PGSZB 8 +#else +#define MFB_PGSZB 4 +#endif /* LONG64 */ +#define MFB_PPW (MFB_PGSZB<<3) /* assuming 8 bits per byte */ +#define MFB_PGSZ MFB_PPW +#define MFB_PLST (MFB_PPW-1) +#define MFB_PIM MFB_PLST + +/* set PWSH = log2(PPW) using brute force */ + +#if MFB_PPW == 32 +#define MFB_PWSH 5 +#else +#if MFB_PPW == 64 +#define MFB_PWSH 6 +#endif /* MFB_PPW == 64 */ +#endif /* MFB_PPW == 32 */ + +extern PixelType starttab[]; +extern PixelType endtab[]; +extern PixelType partmasks[MFB_PPW][MFB_PPW]; +extern PixelType rmask[]; +extern PixelType mask[]; + +#ifndef MFB_CONSTS_ONLY + +#define PGSZB MFB_PGSZB +#define PPW MFB_PPW +#define PGSZ MFB_PGSZ +#define PLST MFB_PLST +#define PIM MFB_PIM +#define PWSH MFB_PWSH + +#define BitLeft(b,s) SCRLEFT(b,s) +#define BitRight(b,s) SCRRIGHT(b,s) + +#if (BITMAP_BIT_ORDER == IMAGE_BYTE_ORDER) +#define LONG2CHARS(x) (x) +#else +/* + * the unsigned case below is for compilers like + * the Danbury C and i386cc + */ +#if PPW == 32 +#define LONG2CHARS( x ) ( ( ( ( x ) & 0x000000FF ) << 0x18 ) \ + | ( ( ( x ) & 0x0000FF00 ) << 0x08 ) \ + | ( ( ( x ) & 0x00FF0000 ) >> 0x08 ) \ + | ( ( ( x ) & (unsigned long)0xFF000000 ) >> 0x18 ) ) +#else /* PPW == 64 */ +#define LONG2CHARS( x ) \ + ( ( ( ( x ) & 0x000000FF) << 0x18 ) \ + | ( ( ( x ) & 0x0000FF00) << 0x08 ) \ + | ( ( ( x ) & 0x00FF0000) >> 0x08 ) \ + | ( ( ( x ) & (unsigned long)0xFF000000) >> 0x18 ) \ + | ( ( ( x ) & 0x000000FF00000000) << 0x18 ) \ + | ( ( ( x ) & 0x0000FF0000000000) << 0x08 ) \ + | ( ( ( x ) & 0x00FF000000000000) >> 0x08 ) \ + | ( ( ( x ) & (unsigned long)0xFF00000000000000) >> 0x18 ) ) +#endif /* PPW */ +#endif /* BITMAP_BIT_ORDER */ + +#ifdef STRICT_ANSI_SHIFT +#define SHL(x,y) ((y) >= PPW ? 0 : LONG2CHARS(LONG2CHARS(x) << (y))) +#define SHR(x,y) ((y) >= PPW ? 0 : LONG2CHARS(LONG2CHARS(x) >> (y))) +#else +#define SHL(x,y) LONG2CHARS(LONG2CHARS(x) << (y)) +#define SHR(x,y) LONG2CHARS(LONG2CHARS(x) >> (y)) +#endif + +#if (BITMAP_BIT_ORDER == MSBFirst) /* pc/rt, 680x0 */ +#define SCRLEFT(lw, n) SHL((PixelType)(lw),(n)) +#define SCRRIGHT(lw, n) SHR((PixelType)(lw),(n)) +#else /* vax, intel */ +#define SCRLEFT(lw, n) SHR((PixelType)(lw),(n)) +#define SCRRIGHT(lw, n) SHL((PixelType)(lw),(n)) +#endif + +#define DoRRop(alu, src, dst) \ +(((alu) == RROP_BLACK) ? ((dst) & ~(src)) : \ + ((alu) == RROP_WHITE) ? ((dst) | (src)) : \ + ((alu) == RROP_INVERT) ? ((dst) ^ (src)) : \ + (dst)) + +#if PPW == 32 +/* A generalized form of a x4 Duff's Device */ +#define Duff(counter, block) { \ + while (counter >= 4) {\ + { block; } \ + { block; } \ + { block; } \ + { block; } \ + counter -= 4; \ + } \ + switch (counter & 3) { \ + case 3: { block; } \ + case 2: { block; } \ + case 1: { block; } \ + case 0: \ + counter = 0; \ + } \ +} +#else /* PPW == 64 */ +/* A generalized form of a x8 Duff's Device */ +#define Duff(counter, block) { \ + while (counter >= 8) {\ + { block; } \ + { block; } \ + { block; } \ + { block; } \ + { block; } \ + { block; } \ + { block; } \ + { block; } \ + counter -= 8; \ + } \ + switch (counter & 7) { \ + case 7: { block; } \ + case 6: { block; } \ + case 5: { block; } \ + case 4: { block; } \ + case 3: { block; } \ + case 2: { block; } \ + case 1: { block; } \ + case 0: \ + counter = 0; \ + } \ +} +#endif /* PPW */ + + +#define maskbits(x, w, startmask, endmask, nlw) \ + startmask = starttab[(x) & PIM]; \ + endmask = endtab[((x)+(w)) & PIM]; \ + if (startmask) \ + nlw = (((w) - (PPW - ((x) & PIM))) >> PWSH); \ + else \ + nlw = (w) >> PWSH; + +#define maskpartialbits(x, w, mask) \ + mask = partmasks[(x) & PIM][(w) & PIM]; + +#define maskPPWbits(x, w, startmask, endmask) \ + startmask = starttab[(x) & PIM]; \ + endmask = endtab[((x)+(w)) & PIM]; + +#ifdef __GNUC__ /* XXX don't want for Alpha? */ +#ifdef vax +#define FASTGETBITS(psrc,x,w,dst) \ + __asm ("extzv %1,%2,%3,%0" \ + : "=g" (dst) \ + : "g" (x), "g" (w), "m" (*(char *)(psrc))) +#define getbits(psrc,x,w,dst) FASTGETBITS(psrc,x,w,dst) + +#define FASTPUTBITS(src, x, w, pdst) \ + __asm ("insv %3,%1,%2,%0" \ + : "=m" (*(char *)(pdst)) \ + : "g" (x), "g" (w), "g" (src)) +#define putbits(src, x, w, pdst) FASTPUTBITS(src, x, w, pdst) +#endif /* vax */ +#ifdef mc68020 +#define FASTGETBITS(psrc, x, w, dst) \ + __asm ("bfextu %3{%1:%2},%0" \ + : "=d" (dst) : "di" (x), "di" (w), "o" (*(char *)(psrc))) + +#define getbits(psrc,x,w,dst) \ +{ \ + FASTGETBITS(psrc, x, w, dst);\ + dst = SHL(dst,(32-(w))); \ +} + +#define FASTPUTBITS(src, x, w, pdst) \ + __asm ("bfins %3,%0{%1:%2}" \ + : "=o" (*(char *)(pdst)) \ + : "di" (x), "di" (w), "d" (src), "0" (*(char *) (pdst))) + +#define putbits(src, x, w, pdst) FASTPUTBITS(SHR((src),32-(w)), x, w, pdst) + +#endif /* mc68020 */ +#endif /* __GNUC__ */ + +/* The following flag is used to override a bugfix for sun 3/60+CG4 machines, + */ + +/* We don't need to be careful about this unless we're dealing with sun3's + * We will default its usage for those who do not know anything, but will + * override its effect if the machine doesn't look like a sun3 + */ +#if !defined(mc68020) || !defined(sun) +#define NO_3_60_CG4 +#endif + +/* This is gross. We want to #define u_putbits as something which can be used + * in the case of the 3/60+CG4, but if we use /bin/cc or are on another + * machine type, we want nothing to do with u_putbits. What a hastle. Here + * I used slo_putbits as something which either u_putbits or putbits could be + * defined as. + * + * putbits gets it iff it is not already defined with FASTPUTBITS above. + * u_putbits gets it if we have FASTPUTBITS (putbits) from above and have not + * overridden the NO_3_60_CG4 flag. + */ + +#define slo_putbits(src, x, w, pdst) \ +{ \ + register int n = (x)+(w)-PPW; \ + \ + if (n <= 0) \ + { \ + register PixelType tmpmask; \ + maskpartialbits((x), (w), tmpmask); \ + *(pdst) = (*(pdst) & ~tmpmask) | \ + (SCRRIGHT(src, x) & tmpmask); \ + } \ + else \ + { \ + *(pdst) = (*(pdst) & endtab[x]) | (SCRRIGHT((src), x)); \ + (pdst)[1] = ((pdst)[1] & starttab[n]) | \ + (SCRLEFT(src, PPW-(x)) & endtab[n]); \ + } \ +} + +#if defined(putbits) && !defined(NO_3_60_CG4) +#define u_putbits(src, x, w, pdst) slo_putbits(src, x, w, pdst) +#else +#define u_putbits(src, x, w, pdst) putbits(src, x, w, pdst) +#endif + +#if !defined(putbits) +#define putbits(src, x, w, pdst) slo_putbits(src, x, w, pdst) +#endif + +/* Now if we have not gotten any really good bitfield macros, try some + * moderately fast macros. Alas, I don't know how to do asm instructions + * without gcc. + */ + +#ifndef getbits +#define getbits(psrc, x, w, dst) \ +{ \ + dst = SCRLEFT(*(psrc), (x)); \ + if ( ((x) + (w)) > PPW) \ + dst |= (SCRRIGHT(*((psrc)+1), PPW-(x))); \ +} +#endif + +/* We have to special-case putbitsrop because of 3/60+CG4 combos + */ + +#define u_putbitsrop(src, x, w, pdst, rop) \ +{\ + register PixelType t1, t2; \ + register int n = (x)+(w)-PPW; \ + \ + t1 = SCRRIGHT((src), (x)); \ + DoRop(t2, rop, t1, *(pdst)); \ + \ + if (n <= 0) \ + { \ + register PixelType tmpmask; \ + \ + maskpartialbits((x), (w), tmpmask); \ + *(pdst) = (*(pdst) & ~tmpmask) | (t2 & tmpmask); \ + } \ + else \ + { \ + int m = PPW-(x); \ + *(pdst) = (*(pdst) & endtab[x]) | (t2 & starttab[x]); \ + t1 = SCRLEFT((src), m); \ + DoRop(t2, rop, t1, (pdst)[1]); \ + (pdst)[1] = ((pdst)[1] & starttab[n]) | (t2 & endtab[n]); \ + } \ +} + +/* If our getbits and putbits are FAST enough, + * do this brute force, it's faster + */ + +#if defined(FASTPUTBITS) && defined(FASTGETBITS) && defined(NO_3_60_CG4) +#if (BITMAP_BIT_ORDER == MSBFirst) +#define putbitsrop(src, x, w, pdst, rop) \ +{ \ + register PixelType _tmp, _tmp2; \ + FASTGETBITS(pdst, x, w, _tmp); \ + _tmp2 = SCRRIGHT(src, PPW-(w)); \ + DoRop(_tmp, rop, _tmp2, _tmp) \ + FASTPUTBITS(_tmp, x, w, pdst); \ +} +#define putbitsrrop(src, x, w, pdst, rop) \ +{ \ + register PixelType _tmp, _tmp2; \ + \ + FASTGETBITS(pdst, x, w, _tmp); \ + _tmp2 = SCRRIGHT(src, PPW-(w)); \ + _tmp= DoRRop(rop, _tmp2, _tmp); \ + FASTPUTBITS(_tmp, x, w, pdst); \ +} +#undef u_putbitsrop +#else +#define putbitsrop(src, x, w, pdst, rop) \ +{ \ + register PixelType _tmp; \ + FASTGETBITS(pdst, x, w, _tmp); \ + DoRop(_tmp, rop, src, _tmp) \ + FASTPUTBITS(_tmp, x, w, pdst); \ +} +#define putbitsrrop(src, x, w, pdst, rop) \ +{ \ + register PixelType _tmp; \ + \ + FASTGETBITS(pdst, x, w, _tmp); \ + _tmp= DoRRop(rop, src, _tmp); \ + FASTPUTBITS(_tmp, x, w, pdst); \ +} +#undef u_putbitsrop +#endif +#endif + +#ifndef putbitsrop +#define putbitsrop(src, x, w, pdst, rop) u_putbitsrop(src, x, w, pdst, rop) +#endif + +#ifndef putbitsrrop +#define putbitsrrop(src, x, w, pdst, rop) \ +{\ + register PixelType t1, t2; \ + register int n = (x)+(w)-PPW; \ + \ + t1 = SCRRIGHT((src), (x)); \ + t2 = DoRRop(rop, t1, *(pdst)); \ + \ + if (n <= 0) \ + { \ + register PixelType tmpmask; \ + \ + maskpartialbits((x), (w), tmpmask); \ + *(pdst) = (*(pdst) & ~tmpmask) | (t2 & tmpmask); \ + } \ + else \ + { \ + int m = PPW-(x); \ + *(pdst) = (*(pdst) & endtab[x]) | (t2 & starttab[x]); \ + t1 = SCRLEFT((src), m); \ + t2 = DoRRop(rop, t1, (pdst)[1]); \ + (pdst)[1] = ((pdst)[1] & starttab[n]) | (t2 & endtab[n]); \ + } \ +} +#endif + +#if GETLEFTBITS_ALIGNMENT == 1 +#define getleftbits(psrc, w, dst) dst = *((CARD32 *) psrc) +#endif /* GETLEFTBITS_ALIGNMENT == 1 */ + +#if GETLEFTBITS_ALIGNMENT == 2 +#define getleftbits(psrc, w, dst) \ + { \ + if ( ((int)(psrc)) & 0x01 ) \ + getbits( ((CARD32 *)(((char *)(psrc))-1)), 8, (w), (dst) ); \ + else \ + getbits(psrc, 0, w, dst); \ + } +#endif /* GETLEFTBITS_ALIGNMENT == 2 */ + +#if GETLEFTBITS_ALIGNMENT == 4 +#define getleftbits(psrc, w, dst) \ + { \ + int off, off_b; \ + off_b = (off = ( ((int)(psrc)) & 0x03)) << 3; \ + getbits( \ + (CARD32 *)( ((char *)(psrc)) - off), \ + (off_b), (w), (dst) \ + ); \ + } +#endif /* GETLEFTBITS_ALIGNMENT == 4 */ + + +#define getshiftedleftbits(psrc, offset, w, dst) \ + getleftbits((psrc), (w), (dst)); \ + dst = SCRLEFT((dst), (offset)); + +/* FASTGETBITS and FASTPUTBITS are not necessarily correct implementations of + * getbits and putbits, but they work if used together. + * + * On a MSBFirst machine, a cpu bitfield extract instruction (like bfextu) + * could normally assign its result to a long word register in the screen + * right position. This saves canceling register shifts by not fighting the + * natural cpu byte order. + * + * Unfortunately, these fail on a 3/60+CG4 and cannot be used unmodified. Sigh. + */ +#if defined(FASTGETBITS) && defined(FASTPUTBITS) +#ifdef NO_3_60_CG4 +#define u_FASTPUT(aa, bb, cc, dd) FASTPUTBITS(aa, bb, cc, dd) +#else +#define u_FASTPUT(aa, bb, cc, dd) u_putbits(SCRLEFT(aa, PPW-(cc)), bb, cc, dd) +#endif + +#define getandputbits(psrc, srcbit, dstbit, width, pdst) \ +{ \ + register PixelType _tmpbits; \ + FASTGETBITS(psrc, srcbit, width, _tmpbits); \ + u_FASTPUT(_tmpbits, dstbit, width, pdst); \ +} + +#define getandputrop(psrc, srcbit, dstbit, width, pdst, rop) \ +{ \ + register PixelType _tmpsrc, _tmpdst; \ + FASTGETBITS(pdst, dstbit, width, _tmpdst); \ + FASTGETBITS(psrc, srcbit, width, _tmpsrc); \ + DoRop(_tmpdst, rop, _tmpsrc, _tmpdst); \ + u_FASTPUT(_tmpdst, dstbit, width, pdst); \ +} + +#define getandputrrop(psrc, srcbit, dstbit, width, pdst, rop) \ +{ \ + register PixelType _tmpsrc, _tmpdst; \ + FASTGETBITS(pdst, dstbit, width, _tmpdst); \ + FASTGETBITS(psrc, srcbit, width, _tmpsrc); \ + _tmpdst = DoRRop(rop, _tmpsrc, _tmpdst); \ + u_FASTPUT(_tmpdst, dstbit, width, pdst); \ +} + +#define getandputbits0(psrc, srcbit, width, pdst) \ + getandputbits(psrc, srcbit, 0, width, pdst) + +#define getandputrop0(psrc, srcbit, width, pdst, rop) \ + getandputrop(psrc, srcbit, 0, width, pdst, rop) + +#define getandputrrop0(psrc, srcbit, width, pdst, rop) \ + getandputrrop(psrc, srcbit, 0, width, pdst, rop) + + +#else /* Slow poke */ + +/* pairs of getbits/putbits happen frequently. Some of the code can + * be shared or avoided in a few specific instances. It gets us a + * small advantage, so we do it. The getandput...0 macros are the only ones + * which speed things here. The others are here for compatibility w/the above + * FAST ones + */ + +#define getandputbits(psrc, srcbit, dstbit, width, pdst) \ +{ \ + register PixelType _tmpbits; \ + getbits(psrc, srcbit, width, _tmpbits); \ + putbits(_tmpbits, dstbit, width, pdst); \ +} + +#define getandputrop(psrc, srcbit, dstbit, width, pdst, rop) \ +{ \ + register PixelType _tmpbits; \ + getbits(psrc, srcbit, width, _tmpbits) \ + putbitsrop(_tmpbits, dstbit, width, pdst, rop) \ +} + +#define getandputrrop(psrc, srcbit, dstbit, width, pdst, rop) \ +{ \ + register PixelType _tmpbits; \ + getbits(psrc, srcbit, width, _tmpbits) \ + putbitsrrop(_tmpbits, dstbit, width, pdst, rop) \ +} + + +#define getandputbits0(psrc, sbindex, width, pdst) \ +{ /* unroll the whole damn thing to see how it * behaves */ \ + register int _flag = PPW - (sbindex); \ + register PixelType _src; \ + \ + _src = SCRLEFT (*(psrc), (sbindex)); \ + if ((width) > _flag) \ + _src |= SCRRIGHT (*((psrc) + 1), _flag); \ + \ + *(pdst) = (*(pdst) & starttab[(width)]) | (_src & endtab[(width)]); \ +} + + +#define getandputrop0(psrc, sbindex, width, pdst, rop) \ +{ \ + register int _flag = PPW - (sbindex); \ + register PixelType _src; \ + \ + _src = SCRLEFT (*(psrc), (sbindex)); \ + if ((width) > _flag) \ + _src |= SCRRIGHT (*((psrc) + 1), _flag); \ + DoRop(_src, rop, _src, *(pdst)); \ + \ + *(pdst) = (*(pdst) & starttab[(width)]) | (_src & endtab[(width)]); \ +} + +#define getandputrrop0(psrc, sbindex, width, pdst, rop) \ +{ \ + int _flag = PPW - (sbindex); \ + register PixelType _src; \ + \ + _src = SCRLEFT (*(psrc), (sbindex)); \ + if ((width) > _flag) \ + _src |= SCRRIGHT (*((psrc) + 1), _flag); \ + _src = DoRRop(rop, _src, *(pdst)); \ + \ + *(pdst) = (*(pdst) & starttab[(width)]) | (_src & endtab[(width)]); \ +} + +#endif /* FASTGETBITS && FASTPUTBITS */ + +#endif /* MFB_CONSTS_ONLY */ diff --git a/mfb/mergerop.h b/mfb/mergerop.h new file mode 100644 index 000000000..b797c245a --- /dev/null +++ b/mfb/mergerop.h @@ -0,0 +1,186 @@ +/* + * $Xorg: mergerop.h,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _MERGEROP_H_ +#define _MERGEROP_H_ + +#ifndef GXcopy +#include "X.h" +#endif + +typedef struct _mergeRopBits { + unsigned long ca1, cx1, ca2, cx2; +} mergeRopRec, *mergeRopPtr; + +extern mergeRopRec mergeRopBits[16]; + +#define DeclareMergeRop() unsigned long _ca1, _cx1, _ca2, _cx2; +#define DeclarePrebuiltMergeRop() unsigned long _cca, _ccx; + +#if PPW != PGSZ /* cfb */ +#define InitializeMergeRop(alu,pm) {\ + unsigned long _pm; \ + mergeRopPtr _bits; \ + _pm = PFILL(pm); \ + _bits = &mergeRopBits[alu]; \ + _ca1 = _bits->ca1 & _pm; \ + _cx1 = _bits->cx1 | ~_pm; \ + _ca2 = _bits->ca2 & _pm; \ + _cx2 = _bits->cx2 & _pm; \ +} +#else /* mfb */ +#define InitializeMergeRop(alu,pm) {\ + mergeRopPtr _bits; \ + _bits = &mergeRopBits[alu]; \ + _ca1 = _bits->ca1; \ + _cx1 = _bits->cx1; \ + _ca2 = _bits->ca2; \ + _cx2 = _bits->cx2; \ +} +#endif + +/* AND has higher precedence than XOR */ + +#define DoMergeRop(src, dst) \ + ((dst) & ((src) & _ca1 ^ _cx1) ^ ((src) & _ca2 ^ _cx2)) + +#define DoPrebuiltMergeRop(dst) ((dst) & _cca ^ _ccx) + +#define DoMaskPrebuiltMergeRop(dst,mask) \ + ((dst) & (_cca | ~(mask)) ^ (_ccx & (mask))) + +#define PrebuildMergeRop(src) ((_cca = (src) & _ca1 ^ _cx1), \ + (_ccx = (src) & _ca2 ^ _cx2)) + +#define DoMaskMergeRop(src, dst, mask) \ + ((dst) & (((src) & _ca1 ^ _cx1) | ~(mask)) ^ (((src) & _ca2 ^ _cx2) & (mask))) + +#ifndef MROP +#define MROP 0 +#endif + +#define Mclear (1<ca1; \ + _cx1 = _bits->cx1; \ +} +#define MROP_SOLID(src,dst) \ + ((dst) & ((src) & _ca1 ^ _cx1) ^ (src)) +#define MROP_MASK(src,dst,mask) \ + ((dst) & (((src) & _ca1 ^ _cx1) | ~(mask)) ^ ((src) & (mask))) +#define MROP_NAME(prefix) MROP_NAME_CAT(prefix,CopyXorAndReverseOr) +#define MROP_PREBUILD(src) PrebuildMergeRop(src) +#define MROP_PREBUILT_DECLARE() DeclarePrebuiltMergeRop() +#define MROP_PREBUILT_SOLID(src,dst) DoPrebuiltMergeRop(dst) +#define MROP_PREBUILT_MASK(src,dst,mask) DoMaskPrebuiltMergeRop(dst,mask) +#endif + +#if (MROP) == 0 +#define MROP_DECLARE() DeclareMergeRop() +#define MROP_DECLARE_REG() register DeclareMergeRop() +#define MROP_INITIALIZE(alu,pm) InitializeMergeRop(alu,pm) +#define MROP_SOLID(src,dst) DoMergeRop(src,dst) +#define MROP_MASK(src,dst,mask) DoMaskMergeRop(src, dst, mask) +#define MROP_NAME(prefix) MROP_NAME_CAT(prefix,General) +#define MROP_PREBUILD(src) PrebuildMergeRop(src) +#define MROP_PREBUILT_DECLARE() DeclarePrebuiltMergeRop() +#define MROP_PREBUILT_SOLID(src,dst) DoPrebuiltMergeRop(dst) +#define MROP_PREBUILT_MASK(src,dst,mask) DoMaskPrebuiltMergeRop(dst,mask) +#endif + +#ifndef MROP_PREBUILD +#define MROP_PREBUILD(src) +#define MROP_PREBUILT_DECLARE() +#define MROP_PREBUILT_SOLID(src,dst) MROP_SOLID(src,dst) +#define MROP_PREBUILT_MASK(src,dst,mask) MROP_MASK(src,dst,mask) +#endif + +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define MROP_NAME_CAT(prefix,suffix) prefix##suffix +#else +#define MROP_NAME_CAT(prefix,suffix) prefix/**/suffix +#endif + +#endif diff --git a/mfb/mfb.h b/mfb/mfb.h new file mode 100644 index 000000000..56c0f9667 --- /dev/null +++ b/mfb/mfb.h @@ -0,0 +1,1250 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfb.h,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +/* Monochrome Frame Buffer definitions + written by drewry, september 1986 +*/ +#include "pixmap.h" +#include "region.h" +#include "gc.h" +#include "colormap.h" +#include "miscstruct.h" +#include "mibstore.h" + +extern int InverseAlu[]; + +/* warning: PixelType definition duplicated in maskbits.h */ +#ifndef PixelType +#define PixelType unsigned long +#endif /* PixelType */ + +/* mfbbitblt.c */ + +extern void mfbDoBitblt( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/ +#endif +); + +extern RegionPtr mfbCopyArea( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr/*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/ +#endif +); + +extern Bool mfbRegisterCopyPlaneProc( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + RegionPtr (* /*proc*/)() +#endif +); + +extern RegionPtr mfbCopyPlane( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr/*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/, + unsigned long /*plane*/ +#endif +); +/* mfbbltC.c */ + +extern void mfbDoBitbltCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/ +#endif +); +/* mfbbltCI.c */ + +extern void mfbDoBitbltCopyInverted( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/ +#endif +); +/* mfbbltG.c */ + +extern void mfbDoBitbltGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/ +#endif +); +/* mfbbltO.c */ + +extern void mfbDoBitbltOr( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/ +#endif +); +/* mfbbltX.c */ + +extern void mfbDoBitbltXor( +#if NeedFunctionPrototypes + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + int /*alu*/, + RegionPtr /*prgnDst*/, + DDXPointPtr /*pptSrc*/ +#endif +); +/* mfbbres.c */ + +extern void mfbBresS( +#if NeedFunctionPrototypes + int /*rop*/, + PixelType * /*addrl*/, + int /*nlwidth*/, + int /*signdx*/, + int /*signdy*/, + int /*axis*/, + int /*x1*/, + int /*y1*/, + int /*e*/, + int /*e1*/, + int /*e2*/, + int /*len*/ +#endif +); +/* mfbbresd.c */ + +extern void mfbBresD( +#if NeedFunctionPrototypes + int /*fgrop*/, + int /*bgrop*/, + int * /*pdashIndex*/, + unsigned char * /*pDash*/, + int /*numInDashList*/, + int * /*pdashOffset*/, + int /*isDoubleDash*/, + PixelType * /*addrl*/, + int /*nlwidth*/, + int /*signdx*/, + int /*signdy*/, + int /*axis*/, + int /*x1*/, + int /*y1*/, + int /*e*/, + int /*e1*/, + int /*e2*/, + int /*len*/ +#endif +); +/* mfbbstore.c */ + +extern void mfbSaveAreas( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/, + RegionPtr /*prgnSave*/, + int /*xorg*/, + int /*yorg*/, + WindowPtr /*pWin*/ +#endif +); + +extern void mfbRestoreAreas( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/, + RegionPtr /*prgnRestore*/, + int /*xorg*/, + int /*yorg*/, + WindowPtr /*pWin*/ +#endif +); +/* mfbclip.c */ + +extern RegionPtr mfbPixmapToRegion( +#if NeedFunctionPrototypes + PixmapPtr /*pPix*/ +#endif +); +/* mfbcmap.c */ + +extern int mfbListInstalledColormaps( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + Colormap * /*pmaps*/ +#endif +); + +extern void mfbInstallColormap( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/ +#endif +); + +extern void mfbUninstallColormap( +#if NeedFunctionPrototypes + ColormapPtr /*pmap*/ +#endif +); + +extern void mfbResolveColor( +#if NeedFunctionPrototypes + unsigned short * /*pred*/, + unsigned short * /*pgreen*/, + unsigned short * /*pblue*/, + VisualPtr /*pVisual*/ +#endif +); + +extern Bool mfbCreateColormap( +#if NeedFunctionPrototypes + ColormapPtr /*pMap*/ +#endif +); + +extern void mfbDestroyColormap( +#if NeedFunctionPrototypes + ColormapPtr /*pMap*/ +#endif +); + +extern Bool mfbCreateDefColormap( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/ +#endif +); +/* mfbfillarc.c */ + +extern void mfbPolyFillArcSolid( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); +/* mfbfillrct.c */ + +extern void mfbPolyFillRect( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nrectFill*/, + xRectangle * /*prectInit*/ +#endif +); +/* mfbfillsp.c */ + +extern void mfbBlackSolidFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbWhiteSolidFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbInvertSolidFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbWhiteStippleFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbBlackStippleFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbInvertStippleFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbTileFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbUnnaturalTileFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); + +extern void mfbUnnaturalStippleFS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/ +#endif +); +/* mfbfont.c */ + +extern Bool mfbRealizeFont( +#if NeedFunctionPrototypes + ScreenPtr /*pscr*/, + FontPtr /*pFont*/ +#endif +); + +extern Bool mfbUnrealizeFont( +#if NeedFunctionPrototypes + ScreenPtr /*pscr*/, + FontPtr /*pFont*/ +#endif +); +/* mfbgc.c */ + +extern Bool mfbCreateGC( +#if NeedFunctionPrototypes + GCPtr /*pGC*/ +#endif +); + +extern void mfbValidateGC( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + unsigned long /*changes*/, + DrawablePtr /*pDrawable*/ +#endif +); + +extern int mfbReduceRop( +#if NeedFunctionPrototypes + int /*alu*/, + Pixel /*src*/ +#endif +); + +/* mfbgetsp.c */ + +extern void mfbGetSpans( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*wMax*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + int /*nspans*/, + char * /*pdstStart*/ +#endif +); +/* mfbhrzvert.c */ + +extern int mfbHorzS( +#if NeedFunctionPrototypes + int /*rop*/, + PixelType * /*addrl*/, + int /*nlwidth*/, + int /*x1*/, + int /*y1*/, + int /*len*/ +#endif +); + +extern int mfbVertS( +#if NeedFunctionPrototypes + int /*rop*/, + PixelType * /*addrl*/, + int /*nlwidth*/, + int /*x1*/, + int /*y1*/, + int /*len*/ +#endif +); +/* mfbigbblak.c */ + +extern void mfbImageGlyphBltBlack( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* mfbigbwht.c */ + +extern void mfbImageGlyphBltWhite( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* mfbimage.c */ + +extern void mfbPutImage( +#if NeedFunctionPrototypes + DrawablePtr /*dst*/, + GCPtr /*pGC*/, + int /*depth*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*leftPad*/, + int /*format*/, + char * /*pImage*/ +#endif +); + +extern void mfbGetImage( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + int /*sx*/, + int /*sy*/, + int /*w*/, + int /*h*/, + unsigned int /*format*/, + unsigned long /*planeMask*/, + char * /*pdstLine*/ +#endif +); +/* mfbline.c */ + +extern void mfbLineSS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/ +#endif +); + +extern void mfbLineSD( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/ +#endif +); + +/* mfbmisc.c */ + +extern void mfbQueryBestSize( +#if NeedFunctionPrototypes + int /*class*/, + unsigned short * /*pwidth*/, + unsigned short * /*pheight*/, + ScreenPtr /*pScreen*/ +#endif +); +/* mfbpablack.c */ + +extern void mfbSolidBlackArea( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*nop*/ +#endif +); + +extern void mfbStippleBlackArea( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*pstipple*/ +#endif +); +/* mfbpainv.c */ + +extern void mfbSolidInvertArea( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*nop*/ +#endif +); + +extern void mfbStippleInvertArea( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*pstipple*/ +#endif +); +/* mfbpawhite.c */ + +extern void mfbSolidWhiteArea( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*nop*/ +#endif +); + +extern void mfbStippleWhiteArea( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*pstipple*/ +#endif +); +/* mfbpgbblak.c */ + +extern void mfbPolyGlyphBltBlack( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* mfbpgbinv.c */ + +extern void mfbPolyGlyphBltInvert( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* mfbpgbwht.c */ + +extern void mfbPolyGlyphBltWhite( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* mfbpixmap.c */ + +extern PixmapPtr mfbCreatePixmap( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int /*width*/, + int /*height*/, + int /*depth*/ +#endif +); + +extern Bool mfbDestroyPixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/ +#endif +); + +extern PixmapPtr mfbCopyPixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pSrc*/ +#endif +); + +extern void mfbPadPixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/ +#endif +); + +extern void mfbXRotatePixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPix*/, + int /*rw*/ +#endif +); + +extern void mfbYRotatePixmap( +#if NeedFunctionPrototypes + PixmapPtr /*pPix*/, + int /*rh*/ +#endif +); + +extern void mfbCopyRotatePixmap( +#if NeedFunctionPrototypes + PixmapPtr /*psrcPix*/, + PixmapPtr * /*ppdstPix*/, + int /*xrot*/, + int /*yrot*/ +#endif +); +/* mfbplyblack.c */ + +extern void mfbFillPolyBlack( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +#endif +); +/* mfbplyinv.c */ + +extern void mfbFillPolyInvert( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +#endif +); +/* mfbplywhite.c */ + +extern void mfbFillPolyWhite( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +#endif +); +/* mfbpntwin.c */ + +extern void mfbPaintWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + RegionPtr /*pRegion*/, + int /*what*/ +#endif +); +/* mfbpolypnt.c */ + +extern void mfbPolyPoint( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + xPoint * /*pptInit*/ +#endif +); +/* mfbpushpxl.c */ + +extern void mfbSolidPP( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + PixmapPtr /*pBitMap*/, + DrawablePtr /*pDrawable*/, + int /*dx*/, + int /*dy*/, + int /*xOrg*/, + int /*yOrg*/ +#endif +); + +extern void mfbPushPixels( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + PixmapPtr /*pBitMap*/, + DrawablePtr /*pDrawable*/, + int /*dx*/, + int /*dy*/, + int /*xOrg*/, + int /*yOrg*/ +#endif +); +/* mfbscrclse.c */ + +extern Bool mfbCloseScreen( +#if NeedFunctionPrototypes + int /*index*/, + ScreenPtr /*pScreen*/ +#endif +); +/* mfbscrinit.c */ + +extern Bool mfbAllocatePrivates( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int * /*pWinIndex*/, + int * /*pGCIndex*/ +#endif +); + +extern Bool mfbScreenInit( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + pointer /*pbits*/, + int /*xsize*/, + int /*ysize*/, + int /*dpix*/, + int /*dpiy*/, + int /*width*/ +#endif +); +/* mfbseg.c */ + +extern void mfbSegmentSS( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSeg*/ +#endif +); + +extern void mfbSegmentSD( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSeg*/ +#endif +); +/* mfbsetsp.c */ + +extern int mfbSetScanline( +#if NeedFunctionPrototypes + int /*y*/, + int /*xOrigin*/, + int /*xStart*/, + int /*xEnd*/, + PixelType * /*psrc*/, + int /*alu*/, + PixelType * /*pdstBase*/, + int /*widthDst*/ +#endif +); + +extern void mfbSetSpans( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + char * /*psrc*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + int /*nspans*/, + int /*fSorted*/ +#endif +); +/* mfbteblack.c */ + +extern void mfbTEGlyphBltBlack( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* mfbtewhite.c */ + +extern void mfbTEGlyphBltWhite( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr/*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); +/* mfbtileC.c */ + +extern void mfbTileAreaPPWCopy( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*ptile*/ +#endif +); +/* mfbtileG.c */ + +extern void mfbTileAreaPPWGeneral( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*ptile*/ +#endif +); + +extern void mfbTileAreaPPW( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*nbox*/, + BoxPtr /*pbox*/, + int /*alu*/, + PixmapPtr /*ptile*/ +#endif +); +/* mfbwindow.c */ + +extern Bool mfbCreateWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern Bool mfbDestroyWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern Bool mfbMapWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWindow*/ +#endif +); + +extern Bool mfbPositionWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/ +#endif +); + +extern Bool mfbUnmapWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWindow*/ +#endif +); + +extern void mfbCopyWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + DDXPointRec /*ptOldOrg*/, + RegionPtr /*prgnSrc*/ +#endif +); + +extern Bool mfbChangeWindowAttributes( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + unsigned long /*mask*/ +#endif +); +/* mfbzerarc.c */ + +extern void mfbZeroPolyArcSS( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); + +/* + private filed of pixmap + pixmap.devPrivate = (PixelType *)pointer_to_bits + pixmap.devKind = width_of_pixmap_in_bytes + + private field of screen + a pixmap, for which we allocate storage. devPrivate is a pointer to +the bits in the hardware framebuffer. note that devKind can be poked to +make the code work for framebuffers that are wider than their +displayable screen (e.g. the early vsII, which displayed 960 pixels +across, but was 1024 in the hardware.) + + private field of GC + Freeing pCompositeClip is done based on the value of +freeCompClip; if freeCompClip is not carefully maintained, we will end +up losing storage or freeing something that isn't ours. +*/ + +typedef struct { + unsigned char rop; /* reduction of rasterop to 1 of 3 */ + unsigned char ropOpStip; /* rop for opaque stipple */ + unsigned char ropFillArea; /* == alu, rop, or ropOpStip */ + unsigned fExpose:1; /* callexposure handling ? */ + unsigned freeCompClip:1; + PixmapPtr pRotatedPixmap; /* tile/stipple rotated to align */ + RegionPtr pCompositeClip; /* free this based on freeCompClip + flag rather than NULLness */ + void (* FillArea)(); /* fills regions; look at the code */ + } mfbPrivGC; +typedef mfbPrivGC *mfbPrivGCPtr; + +extern int mfbGCPrivateIndex; /* index into GC private array */ +extern int mfbWindowPrivateIndex; /* index into Window private array */ +#ifdef PIXMAP_PER_WINDOW +extern int frameWindowPrivateIndex; /* index into Window private array */ +#endif + +/* private field of window */ +typedef struct { + unsigned char fastBorder; /* non-zero if border tile is 32 bits wide */ + unsigned char fastBackground; + unsigned short unused; /* pad for alignment with Sun compiler */ + DDXPointRec oldRotate; + PixmapPtr pRotatedBackground; + PixmapPtr pRotatedBorder; + } mfbPrivWin; + +/* Common macros for extracting drawing information */ + +#define mfbGetTypedWidth(pDrawable,type) (\ + (((pDrawable)->type == DRAWABLE_WINDOW) ? \ + (int) (((PixmapPtr)((pDrawable)->pScreen->devPrivate))->devKind) : \ + (int)(((PixmapPtr)pDrawable)->devKind)) / sizeof (type)) + +#define mfbGetByteWidth(pDrawable) mfbGetTypedWidth(pDrawable, unsigned char) + +#define mfbGetPixelWidth(pDrawable) mfbGetTypedWidth(pDrawable, PixelType) + +#define mfbGetTypedWidthAndPointer(pDrawable, width, pointer, wtype, ptype) {\ + PixmapPtr _pPix; \ + if ((pDrawable)->type == DRAWABLE_WINDOW) \ + _pPix = (PixmapPtr) (pDrawable)->pScreen->devPrivate; \ + else \ + _pPix = (PixmapPtr) (pDrawable); \ + (pointer) = (ptype *) _pPix->devPrivate.ptr; \ + (width) = ((int) _pPix->devKind) / sizeof (wtype); \ +} + +#define mfbGetByteWidthAndPointer(pDrawable, width, pointer) \ + mfbGetTypedWidthAndPointer(pDrawable, width, pointer, unsigned char, unsigned char) + +#define mfbGetPixelWidthAndPointer(pDrawable, width, pointer) \ + mfbGetTypedWidthAndPointer(pDrawable, width, pointer, PixelType, PixelType) + +#define mfbGetWindowTypedWidthAndPointer(pWin, width, pointer, wtype, ptype) {\ + PixmapPtr _pPix = (PixmapPtr) (pWin)->drawable.pScreen->devPrivate; \ + (pointer) = (ptype *) _pPix->devPrivate.ptr; \ + (width) = ((int) _pPix->devKind) / sizeof (wtype); \ +} + +#define mfbGetWindowPixelWidthAndPointer(pWin, width, pointer) \ + mfbGetWindowTypedWidthAndPointer(pWin, width, pointer, PixelType, PixelType) + +#define mfbGetWindowByteWidthAndPointer(pWin, width, pointer) \ + mfbGetWindowTypedWidthAndPointer(pWin, width, pointer, char, char) + +/* mfb uses the following macros to calculate addresses in drawables. + * To support banked framebuffers, the macros come in four flavors. + * All four collapse into the same definition on unbanked devices. + * + * mfbScanlineFoo - calculate address and do bank switching + * mfbScanlineFooNoBankSwitch - calculate address, don't bank switch + * mfbScanlineFooSrc - calculate address, switch source bank + * mfbScanlineFooDst - calculate address, switch destination bank + */ + +/* The NoBankSwitch versions are the same for banked and unbanked cases */ + +#define mfbScanlineIncNoBankSwitch(_ptr, _off) _ptr += (_off) +#define mfbScanlineOffsetNoBankSwitch(_ptr, _off) ((_ptr) + (_off)) +#define mfbScanlineDeltaNoBankSwitch(_ptr, _y, _w) \ + mfbScanlineOffsetNoBankSwitch(_ptr, (_y) * (_w)) +#define mfbScanlineNoBankSwitch(_ptr, _x, _y, _w) \ + mfbScanlineOffsetNoBankSwitch(_ptr, (_y) * (_w) + ((_x) >> MFB_PWSH)) + +#ifdef MFB_LINE_BANK + +#include "mfblinebank.h" /* get macro definitions from this file */ + +#else /* !MFB_LINE_BANK - unbanked case */ + +#define mfbScanlineInc(_ptr, _off) mfbScanlineIncNoBankSwitch(_ptr, _off) +#define mfbScanlineIncSrc(_ptr, _off) mfbScanlineInc(_ptr, _off) +#define mfbScanlineIncDst(_ptr, _off) mfbScanlineInc(_ptr, _off) + +#define mfbScanlineOffset(_ptr, _off) mfbScanlineOffsetNoBankSwitch(_ptr, _off) +#define mfbScanlineOffsetSrc(_ptr, _off) mfbScanlineOffset(_ptr, _off) +#define mfbScanlineOffsetDst(_ptr, _off) mfbScanlineOffset(_ptr, _off) + +#define mfbScanlineSrc(_ptr, _x, _y, _w) mfbScanline(_ptr, _x, _y, _w) +#define mfbScanlineDst(_ptr, _x, _y, _w) mfbScanline(_ptr, _x, _y, _w) + +#define mfbScanlineDeltaSrc(_ptr, _y, _w) mfbScanlineDelta(_ptr, _y, _w) +#define mfbScanlineDeltaDst(_ptr, _y, _w) mfbScanlineDelta(_ptr, _y, _w) + +#endif /* MFB_LINE_BANK */ + +#define mfbScanlineDelta(_ptr, _y, _w) \ + mfbScanlineOffset(_ptr, (_y) * (_w)) + +#define mfbScanline(_ptr, _x, _y, _w) \ + mfbScanlineOffset(_ptr, (_y) * (_w) + ((_x) >> MFB_PWSH)) + + +/* precomputed information about each glyph for GlyphBlt code. + this saves recalculating the per glyph information for each box. +*/ +typedef struct _pos{ + int xpos; /* xposition of glyph's origin */ + int xchar; /* x position mod 32 */ + int leftEdge; + int rightEdge; + int topEdge; + int bottomEdge; + PixelType *pdstBase; /* longword with character origin */ + int widthGlyph; /* width in bytes of this glyph */ +} TEXTPOS; + +/* reduced raster ops for mfb */ +#define RROP_BLACK GXclear +#define RROP_WHITE GXset +#define RROP_NOP GXnoop +#define RROP_INVERT GXinvert + +/* macros for mfbbitblt.c, mfbfillsp.c + these let the code do one switch on the rop per call, rather +than a switch on the rop per item (span or rectangle.) +*/ + +#define fnCLEAR(src, dst) (0) +#define fnAND(src, dst) (src & dst) +#define fnANDREVERSE(src, dst) (src & ~dst) +#define fnCOPY(src, dst) (src) +#define fnANDINVERTED(src, dst) (~src & dst) +#define fnNOOP(src, dst) (dst) +#define fnXOR(src, dst) (src ^ dst) +#define fnOR(src, dst) (src | dst) +#define fnNOR(src, dst) (~(src | dst)) +#define fnEQUIV(src, dst) (~src ^ dst) +#define fnINVERT(src, dst) (~dst) +#define fnORREVERSE(src, dst) (src | ~dst) +#define fnCOPYINVERTED(src, dst)(~src) +#define fnORINVERTED(src, dst) (~src | dst) +#define fnNAND(src, dst) (~(src & dst)) +#define fnSET(src, dst) (~0) + +/* Using a "switch" statement is much faster in most cases + * since the compiler can do a look-up table or multi-way branch + * instruction, depending on the architecture. The result on + * A Sun 3/50 is at least 2.5 times faster, assuming a uniform + * distribution of RasterOp operation types. + * + * However, doing some profiling on a running system reveals + * GXcopy is the operation over 99.5% of the time and + * GXxor is the next most frequent (about .4%), so we make special + * checks for those first. + * + * Note that this requires a change to the "calling sequence" + * since we can't engineer a "switch" statement to have an lvalue. + */ +#define DoRop(result, alu, src, dst) \ +{ \ + if (alu == GXcopy) \ + result = fnCOPY (src, dst); \ + else if (alu == GXxor) \ + result = fnXOR (src, dst); \ + else \ + switch (alu) \ + { \ + case GXclear: \ + result = fnCLEAR (src, dst); \ + break; \ + case GXand: \ + result = fnAND (src, dst); \ + break; \ + case GXandReverse: \ + result = fnANDREVERSE (src, dst); \ + break; \ + case GXandInverted: \ + result = fnANDINVERTED (src, dst); \ + break; \ + case GXnoop: \ + result = fnNOOP (src, dst); \ + break; \ + case GXor: \ + result = fnOR (src, dst); \ + break; \ + case GXnor: \ + result = fnNOR (src, dst); \ + break; \ + case GXequiv: \ + result = fnEQUIV (src, dst); \ + break; \ + case GXinvert: \ + result = fnINVERT (src, dst); \ + break; \ + case GXorReverse: \ + result = fnORREVERSE (src, dst); \ + break; \ + case GXcopyInverted: \ + result = fnCOPYINVERTED (src, dst); \ + break; \ + case GXorInverted: \ + result = fnORINVERTED (src, dst); \ + break; \ + case GXnand: \ + result = fnNAND (src, dst); \ + break; \ + case GXset: \ + result = fnSET (src, dst); \ + break; \ + } \ +} + + +/* C expression fragments for various operations. These get passed in + * as -D's on the compile command line. See mfb/Imakefile. This + * fixes XBUG 6319. + * + * This seems like a good place to point out that mfb's use of the + * words black and white is an unfortunate misnomer. In mfb code, black + * means zero, and white means one. + */ +#define MFB_OPEQ_WHITE |= +#define MFB_OPEQ_BLACK &=~ +#define MFB_OPEQ_INVERT ^= +#define MFB_EQWHOLEWORD_WHITE =~0 +#define MFB_EQWHOLEWORD_BLACK =0 +#define MFB_EQWHOLEWORD_INVERT ^=~0 +#define MFB_OP_WHITE /* nothing */ +#define MFB_OP_BLACK ~ diff --git a/mfb/mfbbitblt.c b/mfb/mfbbitblt.c new file mode 100644 index 000000000..7fe20aec2 --- /dev/null +++ b/mfb/mfbbitblt.c @@ -0,0 +1,485 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbbitblt.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "Xprotostr.h" + +#include "miscstruct.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "mi.h" + +#include "mfb.h" +#include "maskbits.h" + + +/* CopyArea and CopyPlane for a monchrome frame buffer + + + clip the source rectangle to the source's available bits. (this +avoids copying unnecessary pieces that will just get exposed anyway.) +this becomes the new shape of the destination. + clip the destination region to the composite clip in the +GC. this requires translating the destination region to (dstx, dsty). + build a list of source points, one for each rectangle in the +destination. this is a simple translation. + go do the multiple rectangle copies + do graphics exposures +*/ +/** Optimized for drawing pixmaps into windows, especially when drawing into + ** unobscured windows. Calls to the general-purpose region code were + ** replaced with rectangle-to-rectangle clipping comparisions. This is + ** possible, since the pixmap is a single rectangle. In an unobscured + ** window, the destination clip is also a single rectangle, and region + ** code can be avoided entirely. This is a big savings, since the region + ** code uses XAlloc() and makes many function calls. + ** + ** In addition, if source is a pixmap, there is no need to call the + ** expensive miHandleExposures() routine. Instead, we simply return NULL. + ** + ** Previously, drawing a pixmap into an unobscured window executed at least + ** 8 XAlloc()'s, 30 function calls, and hundreds of lines of code. + ** + ** Now, the same operation requires no XAlloc()'s, no region function calls, + ** and much less overhead. Nice for drawing lots of small pixmaps. + */ + +#ifndef LOWMEMFTPT + +void +mfbDoBitblt (pSrc, pDst, alu, prgnDst, pptSrc) + DrawablePtr pSrc, pDst; + int alu; + RegionPtr prgnDst; + DDXPointPtr pptSrc; +{ + switch (alu) + { + case GXcopy: + mfbDoBitbltCopy (pSrc, pDst, alu, prgnDst, pptSrc); + break; + case GXxor: + mfbDoBitbltXor (pSrc, pDst, alu, prgnDst, pptSrc); + break; + case GXcopyInverted: + mfbDoBitbltCopyInverted (pSrc, pDst, alu, prgnDst, pptSrc); + break; + case GXor: + mfbDoBitbltOr (pSrc, pDst, alu, prgnDst, pptSrc); + break; + default: + mfbDoBitbltGeneral (pSrc, pDst, alu, prgnDst, pptSrc); + break; + } +} + +RegionPtr +mfbCopyArea(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty) +register DrawablePtr pSrcDrawable; +register DrawablePtr pDstDrawable; +register GC *pGC; +int srcx, srcy; +int width, height; +int dstx, dsty; +{ + RegionPtr prgnSrcClip; /* may be a new region, or just a copy */ + Bool freeSrcClip = FALSE; + + RegionPtr prgnExposed; + RegionRec rgnDst; + DDXPointPtr pptSrc; + register DDXPointPtr ppt; + register BoxPtr pbox; + int i; + register int dx; + register int dy; + xRectangle origSource; + DDXPointRec origDest; + int numRects; + BoxRec fastBox; + int fastClip = 0; /* for fast clipping with pixmap source */ + int fastExpose = 0; /* for fast exposures with pixmap source */ + void (*localDoBitBlt)(); + + origSource.x = srcx; + origSource.y = srcy; + origSource.width = width; + origSource.height = height; + origDest.x = dstx; + origDest.y = dsty; + + if ((pSrcDrawable != pDstDrawable) && + pSrcDrawable->pScreen->SourceValidate) + { + (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height); + } + + switch (pGC->alu) { + case GXcopy: + localDoBitBlt = mfbDoBitbltCopy; + break; + case GXcopyInverted: + localDoBitBlt = mfbDoBitbltCopyInverted; + break; + case GXxor: + localDoBitBlt = mfbDoBitbltXor; + break; + case GXor: + localDoBitBlt = mfbDoBitbltOr; + break; + default: + localDoBitBlt = mfbDoBitbltGeneral; + break; + } + + srcx += pSrcDrawable->x; + srcy += pSrcDrawable->y; + + /* clip the source */ + + if (pSrcDrawable->type == DRAWABLE_PIXMAP) + { + if ((pSrcDrawable == pDstDrawable) && + (pGC->clientClipType == CT_NONE)) + { + prgnSrcClip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + } + else + { + fastClip = 1; + } + } + else + { + if (pGC->subWindowMode == IncludeInferiors) + { + if (!((WindowPtr) pSrcDrawable)->parent) + { + /* + * special case bitblt from root window in + * IncludeInferiors mode; just like from a pixmap + */ + fastClip = 1; + } + else if ((pSrcDrawable == pDstDrawable) && + (pGC->clientClipType == CT_NONE)) + { + prgnSrcClip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + } + else + { + prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); + freeSrcClip = TRUE; + } + } + else + { + prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; + } + } + + fastBox.x1 = srcx; + fastBox.y1 = srcy; + fastBox.x2 = srcx + width; + fastBox.y2 = srcy + height; + + /* Don't create a source region if we are doing a fast clip */ + if (fastClip) + { + fastExpose = 1; + /* + * clip the source; if regions extend beyond the source size, + * make sure exposure events get sent + */ + if (fastBox.x1 < pSrcDrawable->x) + { + fastBox.x1 = pSrcDrawable->x; + fastExpose = 0; + } + if (fastBox.y1 < pSrcDrawable->y) + { + fastBox.y1 = pSrcDrawable->y; + fastExpose = 0; + } + if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) + { + fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + fastExpose = 0; + } + if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) + { + fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + fastExpose = 0; + } + } + else + { + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); + } + + dstx += pDstDrawable->x; + dsty += pDstDrawable->y; + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + if (!((WindowPtr)pDstDrawable)->realized) + { + if (!fastClip) + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return NULL; + } + } + + dx = srcx - dstx; + dy = srcy - dsty; + + /* Translate and clip the dst to the destination composite clip */ + if (fastClip) + { + RegionPtr cclip; + + /* Translate the region directly */ + fastBox.x1 -= dx; + fastBox.x2 -= dx; + fastBox.y1 -= dy; + fastBox.y2 -= dy; + + /* If the destination composite clip is one rectangle we can + do the clip directly. Otherwise we have to create a full + blown region and call intersect */ + cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + if (REGION_NUM_RECTS(cclip) == 1) + { + BoxPtr pBox = REGION_RECTS(cclip); + + if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1; + if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2; + if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1; + if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2; + + /* Check to see if the region is empty */ + if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) + { + REGION_INIT(pGC->pScreen, &rgnDst, NullBox, 0); + } + else + { + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); + } + } + else + { + /* We must turn off fastClip now, since we must create + a full blown region. It is intersected with the + composite clip below. */ + fastClip = 0; + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1); + } + } + else + { + REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); + } + + if (!fastClip) + { + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + } + + /* Do bit blitting */ + numRects = REGION_NUM_RECTS(&rgnDst); + if (numRects && width && height) + { + if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects * + sizeof(DDXPointRec)))) + { + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return NULL; + } + pbox = REGION_RECTS(&rgnDst); + ppt = pptSrc; + for (i = numRects; --i >= 0; pbox++, ppt++) + { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + if (pGC->planemask & 1) + (*localDoBitBlt) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc); + + DEALLOCATE_LOCAL(pptSrc); + } + + prgnExposed = NULL; + if (((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->fExpose) + { + /* Pixmap sources generate a NoExposed (we return NULL to do this) */ + if (!fastExpose) + prgnExposed = + miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + origSource.x, origSource.y, + (int)origSource.width, + (int)origSource.height, + origDest.x, origDest.y, (unsigned long)0); + } + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return prgnExposed; +} + +#endif /* ifndef LOWMEMFTPT */ + +/* + * Devices which use mfb for 1-bit pixmap support + * must register a function for n-to-1 copy operations + */ + +static unsigned long copyPlaneGeneration; +static int copyPlaneScreenIndex = -1; + +Bool +mfbRegisterCopyPlaneProc (pScreen, proc) + ScreenPtr pScreen; + RegionPtr (*proc)(); +{ + if (copyPlaneGeneration != serverGeneration) + { + copyPlaneScreenIndex = AllocateScreenPrivateIndex(); + if (copyPlaneScreenIndex < 0) + return FALSE; + copyPlaneGeneration = serverGeneration; + } + pScreen->devPrivates[copyPlaneScreenIndex].fptr = (pointer (*)()) proc; + return TRUE; +} + +/* + if fg == 1 and bg ==0, we can do an ordinary CopyArea. + if fg == bg, we can do a CopyArea with alu = mfbReduceRop(alu, fg) + if fg == 0 and bg == 1, we use the same rasterop, with + source operand inverted. + + CopyArea deals with all of the graphics exposure events. + This code depends on knowing that we can change the +alu in the GC without having to call ValidateGC() before calling +CopyArea(). + +*/ + +#ifndef LOWMEMFTPT + +RegionPtr +mfbCopyPlane(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) +DrawablePtr pSrcDrawable, pDstDrawable; +register GC *pGC; +int srcx, srcy; +int width, height; +int dstx, dsty; +unsigned long plane; +{ + int alu; + RegionPtr prgnExposed; + RegionPtr (*copyPlane)(); + + if (pSrcDrawable->depth != 1) + { + if (copyPlaneScreenIndex >= 0 && + (copyPlane = (RegionPtr (*)()) + pSrcDrawable->pScreen->devPrivates[copyPlaneScreenIndex].fptr) + ) + { + return (*copyPlane) (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else + { + FatalError ("No copyPlane proc registered for depth %d\n", + pSrcDrawable->depth); + } + } + if (plane != 1) + return NULL; + + if ((pGC->fgPixel & 1) == 1 && (pGC->bgPixel & 1) == 0) + { + prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)) + { + alu = pGC->alu; + pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel); + prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + pGC->alu = alu; + } + else /* need to invert the src */ + { + alu = pGC->alu; + pGC->alu = InverseAlu[alu]; + prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + pGC->alu = alu; + } + return prgnExposed; +} + +#endif /* ifndef LOWMEMFTPT */ diff --git a/mfb/mfbblt.c b/mfb/mfbblt.c new file mode 100644 index 000000000..28f16febc --- /dev/null +++ b/mfb/mfbblt.c @@ -0,0 +1,587 @@ +/* + * mfb copy area + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Keith Packard + +*/ +/* $Xorg: mfbblt.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "mfb.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "maskbits.h" +#include "fastblt.h" +#include "mergerop.h" + +void +MROP_NAME(mfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc) + DrawablePtr pSrc, pDst; + int alu; + RegionPtr prgnDst; + DDXPointPtr pptSrc; +{ + PixelType *psrcBase, *pdstBase; + /* start of src and dst bitmaps */ + int widthSrc, widthDst; /* add to get to same position in next line */ + + BoxPtr pbox; + int nbox; + + BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; + /* temporaries for shuffling rectangles */ + DDXPointPtr pptTmp, pptNew1, pptNew2; + /* shuffling boxes entails shuffling the + source points too */ + int w, h; + int xdir; /* 1 = left right, -1 = right left/ */ + int ydir; /* 1 = top down, -1 = bottom up */ + + PixelType *psrcLine, *pdstLine; + /* pointers to line with current src and dst */ + register PixelType *psrc;/* pointer to current src longword */ + register PixelType *pdst;/* pointer to current dst longword */ + + MROP_DECLARE_REG() + + /* following used for looping through a line */ + PixelType startmask, endmask; /* masks for writing ends of dst */ + int nlMiddle; /* whole longwords in dst */ + int xoffSrc, xoffDst; + register int leftShift, rightShift; + register PixelType bits; + register PixelType bits1; + register int nl; /* temp copy of nlMiddle */ + + /* place to store full source word */ + int nstart; /* number of ragged bits at start of dst */ + int nend; /* number of ragged bits at end of dst */ + int srcStartOver; /* pulling nstart bits from src + overflows into the next word? */ + int careful; + int tmpSrc; + + MROP_INITIALIZE(alu,0); + + mfbGetPixelWidthAndPointer(pSrc, widthSrc, psrcBase); + + mfbGetPixelWidthAndPointer(pDst, widthDst, pdstBase); + + /* XXX we have to err on the side of safety when both are windows, + * because we don't know if IncludeInferiors is being used. + */ + careful = ((pSrc == pDst) || + ((pSrc->type == DRAWABLE_WINDOW) && + (pDst->type == DRAWABLE_WINDOW))); + + pbox = REGION_RECTS(prgnDst); + nbox = REGION_NUM_RECTS(prgnDst); + + pboxNew1 = NULL; + pptNew1 = NULL; + pboxNew2 = NULL; + pptNew2 = NULL; + if (careful && (pptSrc->y < pbox->y1)) + { + /* walk source botttom to top */ + ydir = -1; + widthSrc = -widthSrc; + widthDst = -widthDst; + + if (nbox > 1) + { + /* keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + if(!pboxNew1) + return; + pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); + if(!pptNew1) + { + DEALLOCATE_LOCAL(pboxNew1); + return; + } + pboxBase = pboxNext = pbox+nbox-1; + while (pboxBase >= pbox) + { + while ((pboxNext >= pbox) && + (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext+1; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp <= pboxBase) + { + *pboxNew1++ = *pboxTmp++; + *pptNew1++ = *pptTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + pptNew1 -= nbox; + pptSrc = pptNew1; + } + } + else + { + /* walk source top to bottom */ + ydir = 1; + } + + if (careful && (pptSrc->x < pbox->x1)) + { + /* walk source right to left */ + xdir = -1; + + if (nbox > 1) + { + /* reverse order of rects in each band */ + pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); + if(!pboxNew2 || !pptNew2) + { + if (pptNew2) DEALLOCATE_LOCAL(pptNew2); + if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2); + if (pboxNew1) + { + DEALLOCATE_LOCAL(pptNew1); + DEALLOCATE_LOCAL(pboxNew1); + } + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox+nbox) + { + while ((pboxNext < pbox+nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp != pboxBase) + { + *pboxNew2++ = *--pboxTmp; + *pptNew2++ = *--pptTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + pptNew2 -= nbox; + pptSrc = pptNew2; + } + } + else + { + /* walk source left to right */ + xdir = 1; + } + + while(nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + + if (ydir == -1) /* start at last scanline of rectangle */ + { + psrcLine = mfbScanlineDeltaSrc(psrcBase, -(pptSrc->y+h-1), widthSrc); + pdstLine = mfbScanlineDeltaDst(pdstBase, -(pbox->y2-1), widthDst); + } + else /* start at first scanline */ + { + psrcLine = mfbScanlineDeltaSrc(psrcBase, pptSrc->y, widthSrc); + pdstLine = mfbScanlineDeltaDst(pdstBase, pbox->y1, widthDst); + } + if ((pbox->x1 & PIM) + w <= PPW) + { + maskpartialbits (pbox->x1, w, startmask); + endmask = 0; + nlMiddle = 0; + } + else + { + maskbits(pbox->x1, w, startmask, endmask, nlMiddle); + } + if (xdir == 1) + { + xoffSrc = pptSrc->x & PIM; + xoffDst = pbox->x1 & PIM; + pdstLine += (pbox->x1 >> PWSH); + psrcLine += (pptSrc->x >> PWSH); +#ifdef DO_UNALIGNED_BITBLT + nl = xoffSrc - xoffDst; + psrcLine = (PixelType *) + (((unsigned char *) psrcLine) + nl); +#else + if (xoffSrc == xoffDst) +#endif + { + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + if (startmask) + { + *pdst = MROP_MASK(*psrc, *pdst, startmask); + psrc++; + pdst++; + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); +#define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); + +#define LoopReset \ +pdst += UNROLL; \ +psrc += UNROLL; + +#else + +#define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++; +#define BodyEven(n) BodyOdd(n) + +#define LoopReset ; + +#endif + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else +#ifdef NOTDEF + /* you'd think this would be faster -- + * a single instruction instead of 6 + * but measurements show it to be ~15% slower + */ + while ((nl -= 6) >= 0) + { + asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0" + : "=m" (*(char *)pdst) + : "m" (*(char *)psrc) + : "d0", "d1", "d2", "d3", + "a2", "a3"); + pdst += 6; + } + nl += 6; + while (nl--) + *pdst++ = *psrc++; +#endif + DuffL(nl, label1, + *pdst = MROP_SOLID (*psrc, *pdst); + pdst++; psrc++;) +#endif + + if (endmask) + *pdst = MROP_MASK(*psrc, *pdst, endmask); + mfbScanlineIncDst(pdstLine, widthDst); + mfbScanlineIncSrc(psrcLine, widthSrc); + } + } +#ifndef DO_UNALIGNED_BITBLT + else + { + if (xoffSrc > xoffDst) + { + leftShift = (xoffSrc - xoffDst); + rightShift = PPW - leftShift; + } + else + { + rightShift = (xoffDst - xoffSrc); + leftShift = PPW - rightShift; + } + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + bits = 0; + if (xoffSrc > xoffDst) + bits = *psrc++; + if (startmask) + { + bits1 = BitLeft(bits,leftShift); + bits = *psrc++; + bits1 |= BitRight(bits,rightShift); + *pdst = MROP_MASK(bits1, *pdst, startmask); + pdst++; + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE + bits1 = bits; + +#ifdef FAST_CONSTANT_OFFSET_MODE + + psrc += nl & (UNROLL-1); + pdst += nl & (UNROLL-1); + +#define BodyOdd(n) \ +bits = psrc[-n]; \ +pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]); + +#define BodyEven(n) \ +bits1 = psrc[-n]; \ +pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]); + +#define LoopReset \ +pdst += UNROLL; \ +psrc += UNROLL; + +#else + +#define BodyOdd(n) \ +bits = *psrc++; \ +*pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \ +pdst++; + +#define BodyEven(n) \ +bits1 = *psrc++; \ +*pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \ +pdst++; + +#define LoopReset ; + +#endif /* !FAST_CONSTANT_OFFSET_MODE */ + + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL (nl,label2, + bits1 = BitLeft(bits, leftShift); + bits = *psrc++; + *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst); + pdst++; + ) +#endif + + if (endmask) + { + bits1 = BitLeft(bits, leftShift); + if (BitLeft(endmask, rightShift)) + { + bits = *psrc; + bits1 |= BitRight(bits, rightShift); + } + *pdst = MROP_MASK (bits1, *pdst, endmask); + } + mfbScanlineIncDst(pdstLine, widthDst); + mfbScanlineIncSrc(psrcLine, widthSrc); + } + } +#endif /* DO_UNALIGNED_BITBLT */ + } + else /* xdir == -1 */ + { + xoffSrc = (pptSrc->x + w - 1) & PIM; + xoffDst = (pbox->x2 - 1) & PIM; + pdstLine += ((pbox->x2-1) >> PWSH) + 1; + psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1; +#ifdef DO_UNALIGNED_BITBLT + nl = xoffSrc - xoffDst; + psrcLine = (PixelType *) + (((unsigned char *) psrcLine) + nl); +#else + if (xoffSrc == xoffDst) +#endif + { + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + if (endmask) + { + pdst--; + psrc--; + *pdst = MROP_MASK (*psrc, *pdst, endmask); + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE +#ifdef FAST_CONSTANT_OFFSET_MODE + psrc -= nl & (UNROLL - 1); + pdst -= nl & (UNROLL - 1); + +#define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]); + +#define BodyEven(n) BodyOdd(n) + +#define LoopReset \ +pdst -= UNROLL;\ +psrc -= UNROLL; + +#else + +#define BodyOdd(n) --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst); +#define BodyEven(n) BodyOdd(n) +#define LoopReset ; + +#endif + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL(nl,label3, + --pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);) +#endif + + if (startmask) + { + --pdst; + --psrc; + *pdst = MROP_MASK(*psrc, *pdst, startmask); + } + mfbScanlineIncDst(pdstLine, widthDst); + mfbScanlineIncSrc(psrcLine, widthSrc); + } + } +#ifndef DO_UNALIGNED_BITBLT + else + { + if (xoffDst > xoffSrc) + { + rightShift = (xoffDst - xoffSrc); + leftShift = PPW - rightShift; + } + else + { + leftShift = (xoffSrc - xoffDst); + rightShift = PPW - leftShift; + } + while (h--) + { + psrc = psrcLine; + pdst = pdstLine; + bits = 0; + if (xoffDst > xoffSrc) + bits = *--psrc; + if (endmask) + { + bits1 = BitRight(bits, rightShift); + bits = *--psrc; + bits1 |= BitLeft(bits, leftShift); + pdst--; + *pdst = MROP_MASK(bits1, *pdst, endmask); + } + nl = nlMiddle; + +#ifdef LARGE_INSTRUCTION_CACHE + bits1 = bits; +#ifdef FAST_CONSTANT_OFFSET_MODE + psrc -= nl & (UNROLL - 1); + pdst -= nl & (UNROLL - 1); + +#define BodyOdd(n) \ +bits = psrc[n-1]; \ +pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]); + +#define BodyEven(n) \ +bits1 = psrc[n-1]; \ +pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]); + +#define LoopReset \ +pdst -= UNROLL; \ +psrc -= UNROLL; + +#else + +#define BodyOdd(n) \ +bits = *--psrc; --pdst; \ +*pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst); + +#define BodyEven(n) \ +bits1 = *--psrc; --pdst; \ +*pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst); + +#define LoopReset ; + +#endif + + PackedLoop + +#undef BodyOdd +#undef BodyEven +#undef LoopReset + +#else + DuffL (nl, label4, + bits1 = BitRight(bits, rightShift); + bits = *--psrc; + --pdst; + *pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst); + ) +#endif + + if (startmask) + { + bits1 = BitRight(bits, rightShift); + if (BitRight (startmask, leftShift)) + { + bits = *--psrc; + bits1 |= BitLeft(bits, leftShift); + } + --pdst; + *pdst = MROP_MASK(bits1, *pdst, startmask); + } + mfbScanlineIncDst(pdstLine, widthDst); + mfbScanlineIncSrc(psrcLine, widthSrc); + } + } +#endif + } + pbox++; + pptSrc++; + } + if (pboxNew2) + { + DEALLOCATE_LOCAL(pptNew2); + DEALLOCATE_LOCAL(pboxNew2); + } + if (pboxNew1) + { + DEALLOCATE_LOCAL(pptNew1); + DEALLOCATE_LOCAL(pboxNew1); + } +} diff --git a/mfb/mfbbres.c b/mfb/mfbbres.c new file mode 100644 index 000000000..6eb954281 --- /dev/null +++ b/mfb/mfbbres.c @@ -0,0 +1,365 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbbres.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "misc.h" +#include "mfb.h" +#include "maskbits.h" +#include "miline.h" + +/* Solid bresenham line */ +/* NOTES + e2 is used less often than e1, so it's not in a register +*/ + +void +mfbBresS(rop, addrlbase, nlwidth, signdx, signdy, axis, x1, y1, e, e1, e2, len) +int rop; /* a reduced rasterop */ +PixelType *addrlbase; /* pointer to base of bitmap */ +int nlwidth; /* width in longwords of bitmap */ +int signdx, signdy; /* signs of directions */ +int axis; /* major axis (Y_AXIS or X_AXIS) */ +int x1, y1; /* initial point */ +register int e; /* error accumulator */ +register int e1; /* bresenham increments */ +int e2; +int len; /* length of line */ +{ + register int yinc; /* increment to next scanline, in bytes */ + register PixelType *addrl; /* bitmask long pointer */ + register PixelType bit; /* current bit being set/cleared/etc. */ + PixelType leftbit = mask[0]; /* leftmost bit to process in new word */ + PixelType rightbit = mask[PPW-1]; /* rightmost bit to process in new word */ + + register int e3 = e2-e1; + PixelType tmp; + + /* point to longword containing first point */ + addrl = mfbScanline(addrlbase, x1, y1, nlwidth); + yinc = signdy * nlwidth; + e = e-e1; /* to make looping easier */ + bit = mask[x1 & PIM]; + + if (!len) + return; + if (rop == RROP_BLACK) + { + if (axis == X_AXIS) + { + if (signdx > 0) + { + tmp = *addrl; + for (;;) + { + tmp &= ~bit; + if (!--len) + break; + bit = SCRRIGHT(bit,1); + e += e1; + if (e >= 0) + { + *addrl = tmp; + mfbScanlineInc(addrl, yinc); + e += e3; + if (!bit) + { + bit = leftbit; + addrl ++; + } + tmp = *addrl; + } + else if (!bit) + { + *addrl = tmp; + bit = leftbit; + addrl ++; + tmp = *addrl; + } + } + *addrl = tmp; + } + else + { + tmp = *addrl; + for (;;) + { + tmp &= ~bit; + if (!--len) + break; + e += e1; + bit = SCRLEFT(bit,1); + if (e >= 0) + { + *addrl = tmp; + mfbScanlineInc(addrl, yinc); + e += e3; + if (!bit) + { + bit = rightbit; + addrl --; + } + tmp = *addrl; + } + else if (!bit) + { + *addrl = tmp; + bit = rightbit; + addrl --; + tmp = *addrl; + } + } + *addrl = tmp; + } + } /* if X_AXIS */ + else + { + if (signdx > 0) + { + while(len--) + { + *addrl &= ~bit; + e += e1; + if (e >= 0) + { + bit = SCRRIGHT(bit,1); + if (!bit) { bit = leftbit;addrl ++; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + } + } + else + { + while(len--) + { + *addrl &= ~bit; + e += e1; + if (e >= 0) + { + bit = SCRLEFT(bit,1); + if (!bit) { bit = rightbit;addrl --; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + } + } + } /* else Y_AXIS */ + } + else if (rop == RROP_WHITE) + { + if (axis == X_AXIS) + { + if (signdx > 0) + { + tmp = *addrl; + for (;;) + { + tmp |= bit; + if (!--len) + break; + e += e1; + bit = SCRRIGHT(bit,1); + if (e >= 0) + { + *addrl = tmp; + mfbScanlineInc(addrl, yinc); + e += e3; + if (!bit) + { + bit = leftbit; + addrl ++; + } + tmp = *addrl; + } + else if (!bit) + { + *addrl = tmp; + bit = leftbit; + addrl ++; + tmp = *addrl; + } + } + *addrl = tmp; + } + else + { + tmp = *addrl; + for (;;) + { + tmp |= bit; + if (!--len) + break; + e += e1; + bit = SCRLEFT(bit,1); + if (e >= 0) + { + *addrl = tmp; + mfbScanlineInc(addrl, yinc); + e += e3; + if (!bit) + { + bit = rightbit; + addrl --; + } + tmp = *addrl; + } + else if (!bit) + { + *addrl = tmp; + bit = rightbit; + addrl --; + tmp = *addrl; + } + } + *addrl = tmp; + } + } /* if X_AXIS */ + else + { + if (signdx > 0) + { + while(len--) + { + *addrl |= bit; + e += e1; + if (e >= 0) + { + bit = SCRRIGHT(bit,1); + if (!bit) { bit = leftbit;addrl ++; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + } + } + else + { + while(len--) + { + *addrl |= bit; + e += e1; + if (e >= 0) + { + bit = SCRLEFT(bit,1); + if (!bit) { bit = rightbit;addrl --; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + } + } + } /* else Y_AXIS */ + } + else if (rop == RROP_INVERT) + { + if (axis == X_AXIS) + { + if (signdx > 0) + { + while(len--) + { + *addrl ^= bit; + e += e1; + if (e >= 0) + { + mfbScanlineInc(addrl, yinc); + e += e3; + } + bit = SCRRIGHT(bit,1); + if (!bit) { bit = leftbit;addrl ++; } + } + } + else + { + while(len--) + { + *addrl ^= bit; + e += e1; + if (e >= 0) + { + mfbScanlineInc(addrl, yinc); + e += e3; + } + bit = SCRLEFT(bit,1); + if (!bit) { bit = rightbit;addrl --; } + } + } + } /* if X_AXIS */ + else + { + if (signdx > 0) + { + while(len--) + { + *addrl ^= bit; + e += e1; + if (e >= 0) + { + bit = SCRRIGHT(bit,1); + if (!bit) { bit = leftbit;addrl ++; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + } + } + else + { + while(len--) + { + *addrl ^= bit; + e += e1; + if (e >= 0) + { + bit = SCRLEFT(bit,1); + if (!bit) { bit = rightbit; addrl --; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + } + } + } /* else Y_AXIS */ + } +} diff --git a/mfb/mfbbresd.c b/mfb/mfbbresd.c new file mode 100644 index 000000000..f71070773 --- /dev/null +++ b/mfb/mfbbresd.c @@ -0,0 +1,204 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbbresd.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "misc.h" +#include "mfb.h" +#include "maskbits.h" +#include "miline.h" + +/* Dashed bresenham line */ + +#define StepDash\ + if (!--dashRemaining) { \ + if (++ dashIndex == numInDashList) \ + dashIndex = 0; \ + dashRemaining = pDash[dashIndex]; \ + rop = fgrop; \ + if (dashIndex & 1) \ + rop = bgrop; \ + } + +void +mfbBresD(fgrop, bgrop, + pdashIndex, pDash, numInDashList, pdashOffset, isDoubleDash, + addrlbase, nlwidth, + signdx, signdy, axis, x1, y1, e, e1, e2, len) +int fgrop, bgrop; +int *pdashIndex; /* current dash */ +unsigned char *pDash; /* dash list */ +int numInDashList; /* total length of dash list */ +int *pdashOffset; /* offset into current dash */ +int isDoubleDash; +PixelType *addrlbase; /* pointer to base of bitmap */ +int nlwidth; /* width in longwords of bitmap */ +int signdx, signdy; /* signs of directions */ +int axis; /* major axis (Y_AXIS or X_AXIS) */ +int x1, y1; /* initial point */ +register int e; /* error accumulator */ +register int e1; /* bresenham increments */ +int e2; +int len; /* length of line */ +{ + register int yinc; /* increment to next scanline, in bytes */ + register PixelType *addrl; + register int e3 = e2-e1; + register unsigned long bit; + PixelType leftbit = mask[0]; /* leftmost bit to process in new word */ + PixelType rightbit = mask[PPW-1]; /* rightmost bit to process in new word */ + int dashIndex; + int dashOffset; + int dashRemaining; + int rop; + + dashOffset = *pdashOffset; + dashIndex = *pdashIndex; + dashRemaining = pDash[dashIndex] - dashOffset; + rop = fgrop; + if (!isDoubleDash) + bgrop = -1; + if (dashIndex & 1) + rop = bgrop; + + /* point to longword containing first point */ + addrl = mfbScanline(addrlbase, x1, y1, nlwidth); + yinc = signdy * nlwidth; + e = e-e1; /* to make looping easier */ + bit = mask[x1 & PIM]; + if (axis == X_AXIS) + { + if (signdx > 0) + { + while(len--) + { + if (rop == RROP_BLACK) + *addrl &= ~bit; + else if (rop == RROP_WHITE) + *addrl |= bit; + else if (rop == RROP_INVERT) + *addrl ^= bit; + e += e1; + if (e >= 0) + { + mfbScanlineInc(addrl, yinc); + e += e3; + } + bit = SCRRIGHT(bit,1); + if (!bit) { bit = leftbit;addrl ++; } + StepDash + } + } + else + { + while(len--) + { + if (rop == RROP_BLACK) + *addrl &= ~bit; + else if (rop == RROP_WHITE) + *addrl |= bit; + else if (rop == RROP_INVERT) + *addrl ^= bit; + e += e1; + if (e >= 0) + { + mfbScanlineInc(addrl, yinc); + e += e3; + } + bit = SCRLEFT(bit,1); + if (!bit) { bit = rightbit;addrl --; } + StepDash + } + } + } /* if X_AXIS */ + else + { + if (signdx > 0) + { + while(len--) + { + if (rop == RROP_BLACK) + *addrl &= ~bit; + else if (rop == RROP_WHITE) + *addrl |= bit; + else if (rop == RROP_INVERT) + *addrl ^= bit; + e += e1; + if (e >= 0) + { + bit = SCRRIGHT(bit,1); + if (!bit) { bit = leftbit;addrl ++; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + StepDash + } + } + else + { + while(len--) + { + if (rop == RROP_BLACK) + *addrl &= ~bit; + else if (rop == RROP_WHITE) + *addrl |= bit; + else if (rop == RROP_INVERT) + *addrl ^= bit; + e += e1; + if (e >= 0) + { + bit = SCRLEFT(bit,1); + if (!bit) { bit = rightbit;addrl --; } + e += e3; + } + mfbScanlineInc(addrl, yinc); + StepDash + } + } + } /* else Y_AXIS */ + *pdashIndex = dashIndex; + *pdashOffset = pDash[dashIndex] - dashRemaining; +} diff --git a/mfb/mfbbstore.c b/mfb/mfbbstore.c new file mode 100644 index 000000000..661ed0827 --- /dev/null +++ b/mfb/mfbbstore.c @@ -0,0 +1,151 @@ +/* $Xorg: mfbbstore.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "mfb.h" +#include "X.h" +#include "mibstore.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" + +/*- + *----------------------------------------------------------------------- + * mfbSaveAreas -- + * Function called by miSaveAreas to actually fetch the areas to be + * saved into the backing pixmap. This is very simple to do, since + * mfbDoBitblt is designed for this very thing. The region to save is + * already destination-relative and we're given the offset to the + * window origin, so we have only to create an array of points of the + * u.l. corners of the boxes in the region translated to the screen + * coordinate system and fetch the screen pixmap out of its devPrivate + * field.... + * + * Results: + * None. + * + * Side Effects: + * Data are copied from the screen into the pixmap. + * + *----------------------------------------------------------------------- + */ +void +mfbSaveAreas(pPixmap, prgnSave, xorg, yorg, pWin) + PixmapPtr pPixmap; /* Backing pixmap */ + RegionPtr prgnSave; /* Region to save (pixmap-relative) */ + int xorg; /* X origin of region */ + int yorg; /* Y origin of region */ + WindowPtr pWin; +{ + register DDXPointPtr pPt; + DDXPointPtr pPtsInit; + register BoxPtr pBox; + register int numRects; + + numRects = REGION_NUM_RECTS(prgnSave); + pPtsInit = (DDXPointPtr)ALLOCATE_LOCAL(numRects * sizeof(DDXPointRec)); + if (!pPtsInit) + return; + + pBox = REGION_RECTS(prgnSave); + pPt = pPtsInit; + while (numRects--) + { + pPt->x = pBox->x1 + xorg; + pPt->y = pBox->y1 + yorg; + pPt++; + pBox++; + } + + mfbDoBitblt((DrawablePtr)pPixmap->drawable.pScreen->devPrivate, + (DrawablePtr)pPixmap, + GXcopy, + prgnSave, + pPtsInit); + + DEALLOCATE_LOCAL(pPtsInit); +} + +/*- + *----------------------------------------------------------------------- + * mfbRestoreAreas -- + * Function called by miRestoreAreas to actually fetch the areas to be + * restored from the backing pixmap. This is very simple to do, since + * mfbDoBitblt is designed for this very thing. The region to restore is + * already destination-relative and we're given the offset to the + * window origin, so we have only to create an array of points of the + * u.l. corners of the boxes in the region translated to the pixmap + * coordinate system and fetch the screen pixmap out of its devPrivate + * field.... + * + * Results: + * None. + * + * Side Effects: + * Data are copied from the pixmap into the screen. + * + *----------------------------------------------------------------------- + */ +void +mfbRestoreAreas(pPixmap, prgnRestore, xorg, yorg, pWin) + PixmapPtr pPixmap; /* Backing pixmap */ + RegionPtr prgnRestore; /* Region to restore (screen-relative)*/ + int xorg; /* X origin of window */ + int yorg; /* Y origin of window */ + WindowPtr pWin; +{ + register DDXPointPtr pPt; + DDXPointPtr pPtsInit; + register BoxPtr pBox; + register int numRects; + + numRects = REGION_NUM_RECTS(prgnRestore); + pPtsInit = (DDXPointPtr)ALLOCATE_LOCAL(numRects*sizeof(DDXPointRec)); + if (!pPtsInit) + return; + + pBox = REGION_RECTS(prgnRestore); + pPt = pPtsInit; + while (numRects--) + { + pPt->x = pBox->x1 - xorg; + pPt->y = pBox->y1 - yorg; + pPt++; + pBox++; + } + + mfbDoBitblt((DrawablePtr)pPixmap, + (DrawablePtr)pPixmap->drawable.pScreen->devPrivate, + GXcopy, + prgnRestore, + pPtsInit); + + DEALLOCATE_LOCAL(pPtsInit); +} diff --git a/mfb/mfbclip.c b/mfb/mfbclip.c new file mode 100644 index 000000000..65d902162 --- /dev/null +++ b/mfb/mfbclip.c @@ -0,0 +1,268 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbclip.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "miscstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "regionstr.h" +#include "gc.h" +#include "maskbits.h" +#include "mi.h" + +#define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \ +if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \ + (!((reg)->data->numRects && \ + ((r-1)->y1 == (ry1)) && \ + ((r-1)->y2 == (ry2)) && \ + ((r-1)->x1 <= (rx1)) && \ + ((r-1)->x2 >= (rx2))))) \ +{ \ + if ((reg)->data->numRects == (reg)->data->size) \ + { \ + miRectAlloc(reg, 1); \ + fr = REGION_BOXPTR(reg); \ + r = fr + (reg)->data->numRects; \ + } \ + r->x1 = (rx1); \ + r->y1 = (ry1); \ + r->x2 = (rx2); \ + r->y2 = (ry2); \ + (reg)->data->numRects++; \ + if(r->x1 < (reg)->extents.x1) \ + (reg)->extents.x1 = r->x1; \ + if(r->x2 > (reg)->extents.x2) \ + (reg)->extents.x2 = r->x2; \ + r++; \ +} + +/* Convert bitmap clip mask into clipping region. + * First, goes through each line and makes boxes by noting the transitions + * from 0 to 1 and 1 to 0. + * Then it coalesces the current line with the previous if they have boxes + * at the same X coordinates. + */ +RegionPtr +mfbPixmapToRegion(pPix) + PixmapPtr pPix; +{ + register RegionPtr pReg; + register PixelType *pw, w; + register int ib; + int width, h, base, rx1, crects; + PixelType *pwLineEnd; + int irectPrevStart, irectLineStart; + register BoxPtr prectO, prectN; + BoxPtr FirstRect, rects, prectLineStart; + Bool fInBox, fSame; + register PixelType mask0 = mask[0]; + PixelType *pwLine; + int nWidth; + + pReg = REGION_CREATE(pPix->drawable.pScreen, NULL, 1); + if(!pReg) + return NullRegion; + FirstRect = REGION_BOXPTR(pReg); + rects = FirstRect; + + pwLine = (PixelType *) pPix->devPrivate.ptr; + nWidth = pPix->devKind / PGSZB; + + width = pPix->drawable.width; + pReg->extents.x1 = width - 1; + pReg->extents.x2 = 0; + irectPrevStart = -1; + for(h = 0; h < pPix->drawable.height; h++) + { + pw = pwLine; + pwLine += nWidth; + irectLineStart = rects - FirstRect; + /* If the Screen left most bit of the word is set, we're starting in + * a box */ + if(*pw & mask0) + { + fInBox = TRUE; + rx1 = 0; + } + else + fInBox = FALSE; + /* Process all words which are fully in the pixmap */ + pwLineEnd = pw + (width >> PWSH); + for (base = 0; pw < pwLineEnd; base += PPW) + { + w = *pw++; + if (fInBox) + { + if (!~w) + continue; + } + else + { + if (!w) + continue; + } + for(ib = 0; ib < PPW; ib++) + { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if(w & mask0) + { + if(!fInBox) + { + rx1 = base + ib; + /* start new box */ + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + /* end box */ + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + ib, h + 1); + fInBox = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = SCRLEFT(w, 1); + } + } + if(width & PIM) + { + /* Process final partial word on line */ + w = *pw++; + for(ib = 0; ib < (width & PIM); ib++) + { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if(w & mask0) + { + if(!fInBox) + { + rx1 = base + ib; + /* start new box */ + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + /* end box */ + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + ib, h + 1); + fInBox = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = SCRLEFT(w, 1); + } + } + /* If scanline ended with last bit set, end the box */ + if(fInBox) + { + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + (width & PIM), h + 1); + } + /* if all rectangles on this line have the same x-coords as + * those on the previous line, then add 1 to all the previous y2s and + * throw away all the rectangles from this line + */ + fSame = FALSE; + if(irectPrevStart != -1) + { + crects = irectLineStart - irectPrevStart; + if(crects == ((rects - FirstRect) - irectLineStart)) + { + prectO = FirstRect + irectPrevStart; + prectN = prectLineStart = FirstRect + irectLineStart; + fSame = TRUE; + while(prectO < prectLineStart) + { + if((prectO->x1 != prectN->x1) || (prectO->x2 != prectN->x2)) + { + fSame = FALSE; + break; + } + prectO++; + prectN++; + } + if (fSame) + { + prectO = FirstRect + irectPrevStart; + while(prectO < prectLineStart) + { + prectO->y2 += 1; + prectO++; + } + rects -= crects; + pReg->data->numRects -= crects; + } + } + } + if(!fSame) + irectPrevStart = irectLineStart; + } + if (!pReg->data->numRects) + pReg->extents.x1 = pReg->extents.x2 = 0; + else + { + pReg->extents.y1 = REGION_BOXPTR(pReg)->y1; + pReg->extents.y2 = REGION_END(pReg)->y2; + if (pReg->data->numRects == 1) + { + xfree(pReg->data); + pReg->data = (RegDataPtr)NULL; + } + } +#ifdef DEBUG + if (!miValidRegion(pReg)) + FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); +#endif + return(pReg); +} diff --git a/mfb/mfbcmap.c b/mfb/mfbcmap.c new file mode 100644 index 000000000..656c9daf6 --- /dev/null +++ b/mfb/mfbcmap.c @@ -0,0 +1,198 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbcmap.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "scrnintstr.h" +#include "colormapst.h" +#include "resource.h" + +/* A monochrome frame buffer is a static gray colormap with two entries. + * We have a "required list" of length 1. Because we can only support 1 + * colormap, we never have to change it, but we may have to change the + * name we call it. If someone installs a new colormap, we know it must + * look just like the old one (because we've checked in dispatch that it was + * a valid colormap identifier, and all the colormap IDs for this device + * look the same). Nevertheless, we still have to uninstall the old colormap + * and install the new one. Similarly, if someone uninstalls a colormap, + * we have to install the default map, even though we know those two looked + * alike. + * The required list concept is pretty much irrelevant when you can only + * have one map installed at a time. + */ +static ColormapPtr InstalledMaps[MAXSCREENS]; + +int +mfbListInstalledColormaps(pScreen, pmaps) + ScreenPtr pScreen; + Colormap *pmaps; +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + *pmaps = InstalledMaps[pScreen->myNum]->mid; + return (1); +} + + +void +mfbInstallColormap(pmap) + ColormapPtr pmap; +{ + int index = pmap->pScreen->myNum; + ColormapPtr oldpmap = InstalledMaps[index]; + + if(pmap != oldpmap) + { + /* Uninstall pInstalledMap. No hardware changes required, just + * notify all interested parties. */ + if(oldpmap != (ColormapPtr)None) + WalkTree(pmap->pScreen, TellLostMap, (pointer)&oldpmap->mid); + /* Install pmap */ + InstalledMaps[index] = pmap; + WalkTree(pmap->pScreen, TellGainedMap, (pointer)&pmap->mid); + + } +} + +void +mfbUninstallColormap(pmap) + ColormapPtr pmap; +{ + int index = pmap->pScreen->myNum; + ColormapPtr curpmap = InstalledMaps[index]; + + if(pmap == curpmap) + { + if (pmap->mid != pmap->pScreen->defColormap) + { + curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, + RT_COLORMAP); + (*pmap->pScreen->InstallColormap)(curpmap); + } + } +} + +/*ARGSUSED*/ +void +mfbResolveColor (pred, pgreen, pblue, pVisual) + unsigned short *pred; + unsigned short *pgreen; + unsigned short *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 +mfbCreateColormap(pMap) + ColormapPtr pMap; +{ + ScreenPtr pScreen; + unsigned short red0, green0, blue0; + unsigned short red1, green1, blue1; + Pixel pix; + + pScreen = pMap->pScreen; + if (pScreen->whitePixel == 0) + { + red0 = green0 = blue0 = ~0; + red1 = green1 = blue1 = 0; + } + else + { + red0 = green0 = blue0 = 0; + red1 = green1 = blue1 = ~0; + } + + /* 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 */ + + /* this will be pixel 0 */ + pix = 0; + if (AllocColor(pMap, &red0, &green0, &blue0, &pix, 0) != Success) + return FALSE; + + /* this will be pixel 1 */ + if (AllocColor(pMap, &red1, &green1, &blue1, &pix, 0) != Success) + return FALSE; + return TRUE; +} + +/*ARGSUSED*/ +void +mfbDestroyColormap (pMap) + ColormapPtr pMap; +{ + return; +} + +Bool +mfbCreateDefColormap (pScreen) + ScreenPtr pScreen; +{ + VisualPtr pVisual; + ColormapPtr pColormap; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + if (CreateColormap (pScreen->defColormap, pScreen, pVisual, + &pColormap, AllocNone, 0) != Success) + { + return FALSE; + } + (*pScreen->InstallColormap) (pColormap); + return TRUE; +} diff --git a/mfb/mfbfillarc.c b/mfb/mfbfillarc.c new file mode 100644 index 000000000..0d78decf1 --- /dev/null +++ b/mfb/mfbfillarc.c @@ -0,0 +1,328 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mfbfillarc.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ + +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "mfb.h" +#include "maskbits.h" +#include "mifillarc.h" +#include "mi.h" + +static void +mfbFillEllipseSolid(pDraw, arc, rop) + DrawablePtr pDraw; + xArc *arc; + register int rop; +{ + int x, y, e; + int yk, xk, ym, xm, dx, dy, xorg, yorg; + register int slw; + miFillArcRec info; + PixelType *addrlt, *addrlb; + register PixelType *addrl; + register int n; + int nlwidth; + register int xpos; + PixelType startmask, endmask; + int nlmiddle; + + mfbGetPixelWidthAndPointer(pDraw, nlwidth, addrlt); + miFillArcSetup(arc, &info); + MIFILLARCSETUP(); + xorg += pDraw->x; + yorg += pDraw->y; + addrlb = addrlt; + addrlt += nlwidth * (yorg - y); + addrlb += nlwidth * (yorg + y + dy); + while (y) + { + addrlt += nlwidth; + addrlb -= nlwidth; + MIFILLARCSTEP(slw); + if (!slw) + continue; + xpos = xorg - x; + addrl = mfbScanlineOffset(addrlt, (xpos >> PWSH)); + if (((xpos & PIM) + slw) < PPW) + { + maskpartialbits(xpos, slw, startmask); + if (rop == RROP_BLACK) + *addrl &= ~startmask; + else if (rop == RROP_WHITE) + *addrl |= startmask; + else + *addrl ^= startmask; + if (miFillArcLower(slw)) + { + addrl = mfbScanlineOffset(addrlb, (xpos >> PWSH)); + if (rop == RROP_BLACK) + *addrl &= ~startmask; + else if (rop == RROP_WHITE) + *addrl |= startmask; + else + *addrl ^= startmask; + } + continue; + } + maskbits(xpos, slw, startmask, endmask, nlmiddle); + if (startmask) + { + if (rop == RROP_BLACK) + *addrl++ &= ~startmask; + else if (rop == RROP_WHITE) + *addrl++ |= startmask; + else + *addrl++ ^= startmask; + } + n = nlmiddle; + if (rop == RROP_BLACK) + while (n--) + *addrl++ = 0; + else if (rop == RROP_WHITE) + while (n--) + *addrl++ = ~0; + else + while (n--) + *addrl++ ^= ~0; + if (endmask) + { + if (rop == RROP_BLACK) + *addrl &= ~endmask; + else if (rop == RROP_WHITE) + *addrl |= endmask; + else + *addrl ^= endmask; + } + if (!miFillArcLower(slw)) + continue; + addrl = mfbScanlineOffset(addrlb, (xpos >> PWSH)); + if (startmask) + { + if (rop == RROP_BLACK) + *addrl++ &= ~startmask; + else if (rop == RROP_WHITE) + *addrl++ |= startmask; + else + *addrl++ ^= startmask; + } + n = nlmiddle; + if (rop == RROP_BLACK) + while (n--) + *addrl++ = 0; + else if (rop == RROP_WHITE) + while (n--) + *addrl++ = ~0; + else + while (n--) + *addrl++ ^= ~0; + if (endmask) + { + if (rop == RROP_BLACK) + *addrl &= ~endmask; + else if (rop == RROP_WHITE) + *addrl |= endmask; + else + *addrl ^= endmask; + } + } +} + +#define FILLSPAN(xl,xr,addr) \ + if (xr >= xl) \ + { \ + width = xr - xl + 1; \ + addrl = mfbScanlineOffset(addr, (xl >> PWSH)); \ + if (((xl & PIM) + width) < PPW) \ + { \ + maskpartialbits(xl, width, startmask); \ + if (rop == RROP_BLACK) \ + *addrl &= ~startmask; \ + else if (rop == RROP_WHITE) \ + *addrl |= startmask; \ + else \ + *addrl ^= startmask; \ + } \ + else \ + { \ + maskbits(xl, width, startmask, endmask, nlmiddle); \ + if (startmask) \ + { \ + if (rop == RROP_BLACK) \ + *addrl++ &= ~startmask; \ + else if (rop == RROP_WHITE) \ + *addrl++ |= startmask; \ + else \ + *addrl++ ^= startmask; \ + } \ + n = nlmiddle; \ + if (rop == RROP_BLACK) \ + while (n--) \ + *addrl++ = 0; \ + else if (rop == RROP_WHITE) \ + while (n--) \ + *addrl++ = ~0; \ + else \ + while (n--) \ + *addrl++ ^= ~0; \ + if (endmask) \ + { \ + if (rop == RROP_BLACK) \ + *addrl &= ~endmask; \ + else if (rop == RROP_WHITE) \ + *addrl |= endmask; \ + else \ + *addrl ^= endmask; \ + } \ + } \ + } + +#define FILLSLICESPANS(flip,addr) \ + if (!flip) \ + { \ + FILLSPAN(xl, xr, addr); \ + } \ + else \ + { \ + xc = xorg - x; \ + FILLSPAN(xc, xr, addr); \ + xc += slw - 1; \ + FILLSPAN(xl, xc, addr); \ + } + +static void +mfbFillArcSliceSolidCopy(pDraw, pGC, arc, rop) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; + register int rop; +{ + register PixelType *addrl; + register int n; + int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; + register int x, y, e; + miFillArcRec info; + miArcSliceRec slice; + int xl, xr, xc; + PixelType *addrlt, *addrlb; + int nlwidth; + int width; + PixelType startmask, endmask; + int nlmiddle; + + mfbGetPixelWidthAndPointer(pDraw, nlwidth, addrlt); + miFillArcSetup(arc, &info); + miFillArcSliceSetup(arc, &slice, pGC); + MIFILLARCSETUP(); + xorg += pDraw->x; + yorg += pDraw->y; + addrlb = addrlt; + addrlt = mfbScanlineDeltaNoBankSwitch(addrlt, yorg - y, nlwidth); + addrlb = mfbScanlineDeltaNoBankSwitch(addrlb, yorg + y + dy, nlwidth); + slice.edge1.x += pDraw->x; + slice.edge2.x += pDraw->x; + while (y > 0) + { + mfbScanlineIncNoBankSwitch(addrlt, nlwidth); + mfbScanlineIncNoBankSwitch(addrlb, -nlwidth); + MIFILLARCSTEP(slw); + MIARCSLICESTEP(slice.edge1); + MIARCSLICESTEP(slice.edge2); + if (miFillSliceUpper(slice)) + { + MIARCSLICEUPPER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_top, addrlt); + } + if (miFillSliceLower(slice)) + { + MIARCSLICELOWER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_bot, addrlb); + } + } +} + +void +mfbPolyFillArcSolid(pDraw, pGC, narcs, parcs) + register DrawablePtr pDraw; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + mfbPrivGC *priv; + register xArc *arc; + register int i; + BoxRec box; + int x2, y2; + RegionPtr cclip; + int rop; + + priv = (mfbPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr; + rop = priv->rop; + if ((rop == RROP_NOP) || !(pGC->planemask & 1)) + return; + cclip = priv->pCompositeClip; + for (arc = parcs, i = narcs; --i >= 0; arc++) + { + if (miFillArcEmpty(arc)) + continue; + if (miCanFillArc(arc)) + { + box.x1 = arc->x + pDraw->x; + box.y1 = arc->y + pDraw->y; + /* + * Because box.x2 and box.y2 get truncated to 16 bits, and the + * RECT_IN_REGION test treats the resulting number as a signed + * integer, the RECT_IN_REGION test alone can go the wrong way. + * This can result in a server crash because the rendering + * routines in this file deal directly with cpu addresses + * of pixels to be stored, and do not clip or otherwise check + * that all such addresses are within their respective pixmaps. + * So we only allow the RECT_IN_REGION test to be used for + * values that can be expressed correctly in a signed short. + */ + x2 = box.x1 + (int)arc->width + 1; + box.x2 = x2; + y2 = box.y1 + (int)arc->height + 1; + box.y2 = y2; + if ( (x2 <= MAXSHORT) && (y2 <= MAXSHORT) && + (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) ) + { + if ((arc->angle2 >= FULLCIRCLE) || + (arc->angle2 <= -FULLCIRCLE)) + mfbFillEllipseSolid(pDraw, arc, rop); + else + mfbFillArcSliceSolidCopy(pDraw, pGC, arc, rop); + continue; + } + } + miPolyFillArc(pDraw, pGC, 1, arc); + } +} diff --git a/mfb/mfbfillrct.c b/mfb/mfbfillrct.c new file mode 100644 index 000000000..1c4c2e617 --- /dev/null +++ b/mfb/mfbfillrct.c @@ -0,0 +1,224 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbfillrct.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "Xprotostr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "miscstruct.h" +#include "regionstr.h" +#include "scrnintstr.h" + +#include "mfb.h" +#include "maskbits.h" + +#define MODEQ(a, b) ((a) %= (b)) +void mfbPaintOddSize(); + +/* + filled rectangles. + translate the rectangles, clip them, and call the +helper function in the GC. +*/ + +#define NUM_STACK_RECTS 1024 + +void +mfbPolyFillRect(pDrawable, pGC, nrectFill, prectInit) + DrawablePtr pDrawable; + GCPtr pGC; + int nrectFill; /* number of rectangles to fill */ + xRectangle *prectInit; /* Pointer to first rectangle to fill */ +{ + xRectangle *prect; + RegionPtr prgnClip; + register BoxPtr pbox; + register BoxPtr pboxClipped; + BoxPtr pboxClippedBase; + BoxPtr pextent; + BoxRec stackRects[NUM_STACK_RECTS]; + int numRects; + int n; + int xorg, yorg; + mfbPrivGC *priv; + int alu; + void (* pfn) (); + PixmapPtr ppix; + + if (!(pGC->planemask & 1)) + return; + + priv = (mfbPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr; + alu = priv->ropFillArea; + pfn = priv->FillArea; + ppix = priv->pRotatedPixmap; + prgnClip = priv->pCompositeClip; + + prect = prectInit; + xorg = pDrawable->x; + yorg = pDrawable->y; + if (xorg || yorg) + { + prect = prectInit; + n = nrectFill; + Duff (n, prect->x += xorg; prect->y += yorg; prect++); + } + + + prect = prectInit; + + numRects = REGION_NUM_RECTS(prgnClip) * nrectFill; + if (numRects > NUM_STACK_RECTS) + { + pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec)); + if (!pboxClippedBase) + return; + } + else + pboxClippedBase = stackRects; + + pboxClipped = pboxClippedBase; + + if (REGION_NUM_RECTS(prgnClip) == 1) + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_RECTS(prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + if ((pboxClipped->x1 = prect->x) < x1) + pboxClipped->x1 = x1; + + if ((pboxClipped->y1 = prect->y) < y1) + pboxClipped->y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + pboxClipped->x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + pboxClipped->y2 = by2; + + prect++; + if ((pboxClipped->x1 < pboxClipped->x2) && + (pboxClipped->y1 < pboxClipped->y2)) + { + pboxClipped++; + } + } + } + else + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + BoxRec box; + + if ((box.x1 = prect->x) < x1) + box.x1 = x1; + + if ((box.y1 = prect->y) < y1) + box.y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + box.x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + box.y2 = by2; + + prect++; + + if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) + continue; + + n = REGION_NUM_RECTS (prgnClip); + pbox = REGION_RECTS(prgnClip); + + /* clip the rectangle to each box in the clip region + this is logically equivalent to calling Intersect() + */ + while(n--) + { + pboxClipped->x1 = max(box.x1, pbox->x1); + pboxClipped->y1 = max(box.y1, pbox->y1); + pboxClipped->x2 = min(box.x2, pbox->x2); + pboxClipped->y2 = min(box.y2, pbox->y2); + pbox++; + + /* see if clipping left anything */ + if(pboxClipped->x1 < pboxClipped->x2 && + pboxClipped->y1 < pboxClipped->y2) + { + pboxClipped++; + } + } + } + } + if (pboxClipped != pboxClippedBase) + (*pfn) (pDrawable,pboxClipped-pboxClippedBase, pboxClippedBase, alu, ppix); + if (pboxClippedBase != stackRects) + DEALLOCATE_LOCAL(pboxClippedBase); +} diff --git a/mfb/mfbfillsp.c b/mfb/mfbfillsp.c new file mode 100644 index 000000000..0ba5fc9a7 --- /dev/null +++ b/mfb/mfbfillsp.c @@ -0,0 +1,1024 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbfillsp.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "Xmd.h" +#include "gcstruct.h" +#include "window.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "mfb.h" +#include "maskbits.h" + +#include "mergerop.h" + +#include "servermd.h" +#include "mi.h" +#include "mispans.h" + +/* scanline filling for monochrome frame buffer + written by drewry, oct 1986 + + these routines all clip. they assume that anything that has called +them has already translated the points (i.e. pGC->miTranslate is +non-zero, which is howit gets set in mfbCreateGC().) + + the number of new scnalines created by clipping == +MaxRectsPerBand * nSpans. + + FillSolid is overloaded to be used for OpaqueStipple as well, +if fgPixel == bgPixel. + + + FillTiled is overloaded to be used for OpaqueStipple, if +fgPixel != bgPixel. based on the fill style, it uses +{RotatedPixmap, gc.alu} or {RotatedPixmap, PrivGC.ropOpStip} +*/ + + +void +mfbBlackSolidFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *addrl;/* pointer to current longword in bitmap */ + register int nlmiddle; + register PixelType startmask; + register PixelType endmask; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + while (n--) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + + if (*pwidth) + { + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + /* all bits inside same longword */ + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl &= ~startmask; + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + *addrl++ &= ~startmask; + Duff (nlmiddle, *addrl++ = 0x0); + if (endmask) + *addrl &= ~endmask; + } + } + pwidth++; + ppt++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + + +void +mfbWhiteSolidFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *addrl;/* pointer to current longword in bitmap */ + register int nlmiddle; + register PixelType startmask; + register PixelType endmask; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + while (n--) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + + if (*pwidth) + { + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + /* all bits inside same longword */ + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl |= startmask; + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + *addrl++ |= startmask; + Duff (nlmiddle, *addrl++ = ~0); + if (endmask) + *addrl |= endmask; + } + } + pwidth++; + ppt++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + + +void +mfbInvertSolidFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *addrl;/* pointer to current longword in bitmap */ + register int nlmiddle; + register PixelType startmask; + register PixelType endmask; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + while (n--) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + + if (*pwidth) + { + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + /* all bits inside same longword */ + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl ^= startmask; + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + *addrl++ ^= startmask; + Duff (nlmiddle, *addrl++ ^= ~0); + if (endmask) + *addrl ^= endmask; + } + } + pwidth++; + ppt++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + +void +mfbWhiteStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GC *pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *addrl;/* pointer to current longword in bitmap */ + register PixelType src; + register int nlmiddle; + register PixelType startmask; + register PixelType endmask; + PixmapPtr pStipple; + PixelType *psrc; + int tileHeight; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + pStipple = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap; + tileHeight = pStipple->drawable.height; + psrc = (PixelType *)(pStipple->devPrivate.ptr); + + while (n--) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + src = psrc[ppt->y % tileHeight]; + + /* all bits inside same longword */ + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl |= (src & startmask); + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + *addrl++ |= (src & startmask); + Duff (nlmiddle, *addrl++ |= src); + if (endmask) + *addrl |= (src & endmask); + } + pwidth++; + ppt++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + +void +mfbBlackStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GC *pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *addrl; /* pointer to current longword in bitmap */ + register PixelType src; + register int nlmiddle; + register PixelType startmask; + register PixelType endmask; + PixmapPtr pStipple; + PixelType *psrc; + int tileHeight; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + pStipple = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap; + tileHeight = pStipple->drawable.height; + psrc = (PixelType *)(pStipple->devPrivate.ptr); + + while (n--) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + src = psrc[ppt->y % tileHeight]; + + /* all bits inside same longword */ + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl &= ~(src & startmask); + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + *addrl++ &= ~(src & startmask); + Duff (nlmiddle, *addrl++ &= ~src); + if (endmask) + *addrl &= ~(src & endmask); + } + pwidth++; + ppt++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + +void +mfbInvertStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GC *pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *addrl; /* pointer to current longword in bitmap */ + register PixelType src; + register int nlmiddle; + register PixelType startmask; + register PixelType endmask; + PixmapPtr pStipple; + PixelType *psrc; + int tileHeight; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + pStipple = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap; + tileHeight = pStipple->drawable.height; + psrc = (PixelType *)(pStipple->devPrivate.ptr); + + while (n--) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + src = psrc[ppt->y % tileHeight]; + + /* all bits inside same longword */ + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl ^= (src & startmask); + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + *addrl++ ^= (src & startmask); + Duff(nlmiddle, *addrl++ ^= src); + if (endmask) + *addrl ^= (src & endmask); + } + pwidth++; + ppt++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + +/* this works with tiles of width == PPW */ +#define FILLSPANPPW(ROP) \ + while (n--) \ + { \ + if (*pwidth) \ + { \ + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); \ + src = psrc[ppt->y % tileHeight]; \ + if ( ((ppt->x & PIM) + *pwidth) < PPW) \ + { \ + maskpartialbits(ppt->x, *pwidth, startmask); \ + *addrl = (*addrl & ~startmask) | \ + (ROP(src, *addrl) & startmask); \ + } \ + else \ + { \ + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); \ + if (startmask) \ + { \ + *addrl = (*addrl & ~startmask) | \ + (ROP(src, *addrl) & startmask); \ + addrl++; \ + } \ + while (nlmiddle--) \ + { \ + *addrl = ROP(src, *addrl); \ + addrl++; \ + } \ + if (endmask) \ + *addrl = (*addrl & ~endmask) | \ + (ROP(src, *addrl) & endmask); \ + } \ + } \ + pwidth++; \ + ppt++; \ + } + + + +void +mfbTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GC *pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *addrl; /* pointer to current longword in bitmap */ + register PixelType src; + register int nlmiddle; + register PixelType startmask; + register PixelType endmask; + PixmapPtr pTile; + PixelType *psrc; + int tileHeight; + int rop; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + unsigned long flip; + + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + pTile = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap; + tileHeight = pTile->drawable.height; + psrc = (PixelType *)(pTile->devPrivate.ptr); + if (pGC->fillStyle == FillTiled) + rop = pGC->alu; + else + rop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->ropOpStip; + + flip = 0; + switch(rop) + { + case GXcopyInverted: /* for opaque stipples */ + flip = ~0; + case GXcopy: + { + +#define DoMaskCopyRop(src,dst,mask) ((dst) & ~(mask) | (src) & (mask)) + + while (n--) + { + if (*pwidth) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + src = psrc[ppt->y % tileHeight] ^ flip; + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl = DoMaskCopyRop (src, *addrl, startmask); + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + { + *addrl = DoMaskCopyRop (src, *addrl, startmask); + addrl++; + } + while (nlmiddle--) + { + *addrl = src; + addrl++; + } + if (endmask) + *addrl = DoMaskCopyRop (src, *addrl, endmask); + } + } + pwidth++; + ppt++; + } + } + break; + default: + { + register DeclareMergeRop (); + + InitializeMergeRop(rop,~0); + while (n--) + { + if (*pwidth) + { + addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + src = psrc[ppt->y % tileHeight]; + if ( ((ppt->x & PIM) + *pwidth) < PPW) + { + maskpartialbits(ppt->x, *pwidth, startmask); + *addrl = DoMaskMergeRop (src, *addrl, startmask); + } + else + { + maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); + if (startmask) + { + *addrl = DoMaskMergeRop (src, *addrl, startmask); + addrl++; + } + while (nlmiddle--) + { + *addrl = DoMergeRop (src, *addrl); + addrl++; + } + if (endmask) + *addrl = DoMaskMergeRop (src, *addrl, endmask); + } + } + pwidth++; + ppt++; + } + } + break; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + +/* Fill spans with tiles that aren't PPW bits wide */ +void +mfbUnnaturalTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GC *pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + int iline; /* first line of tile to use */ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *pdst;/* pointer to current word in bitmap */ + register PixelType *psrc;/* pointer to current word in tile */ + register int nlMiddle; + register int rop, nstart; + PixelType startmask; + PixmapPtr pTile; /* pointer to tile we want to fill with */ + int w, width, x, xSrc, ySrc, srcStartOver, nend; + int tlwidth, rem, tileWidth, tileHeight, endinc; + PixelType endmask, *psrcT; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + if (pGC->fillStyle == FillTiled) + { + pTile = pGC->tile.pixmap; + tlwidth = pTile->devKind / PGSZB; + rop = pGC->alu; + } + else + { + pTile = pGC->stipple; + tlwidth = pTile->devKind / PGSZB; + rop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->ropOpStip; + } + + xSrc = pDrawable->x; + ySrc = pDrawable->y; + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + /* this replaces rotating the tile. Instead we just adjust the offset + * at which we start grabbing bits from the tile. + * Ensure that ppt->x - xSrc >= 0 and ppt->y - ySrc >= 0, + * so that iline and rem always stay within the tile bounds. + */ + xSrc += (pGC->patOrg.x % tileWidth) - tileWidth; + ySrc += (pGC->patOrg.y % tileHeight) - tileHeight; + + while (n--) + { + iline = (ppt->y - ySrc) % tileHeight; + pdst = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + psrcT = (PixelType *) pTile->devPrivate.ptr + (iline * tlwidth); + x = ppt->x; + + if (*pwidth) + { + width = *pwidth; + while(width > 0) + { + psrc = psrcT; + w = min(tileWidth, width); + if((rem = (x - xSrc) % tileWidth) != 0) + { + /* if we're in the middle of the tile, get + as many bits as will finish the span, or + as many as will get to the left edge of the tile, + or a longword worth, starting at the appropriate + offset in the tile. + */ + w = min(min(tileWidth - rem, width), BITMAP_SCANLINE_PAD); + endinc = rem / BITMAP_SCANLINE_PAD; + getandputrop((psrc+endinc), (rem&PIM), (x & PIM), w, pdst, rop); + if((x & PIM) + w >= PPW) + pdst++; + } + else if(((x & PIM) + w) < PPW) + { + /* doing < PPW bits is easy, and worth special-casing */ + putbitsrop(*psrc, x & PIM, w, pdst, rop); + } + else + { + /* start at the left edge of the tile, + and put down as much as we can + */ + maskbits(x, w, startmask, endmask, nlMiddle); + + if (startmask) + nstart = PPW - (x & PIM); + else + nstart = 0; + if (endmask) + nend = (x + w) & PIM; + else + nend = 0; + + srcStartOver = nstart > PLST; + + if(startmask) + { + putbitsrop(*psrc, (x & PIM), nstart, pdst, rop); + pdst++; + if(srcStartOver) + psrc++; + } + + while(nlMiddle--) + { + getandputrop0(psrc, nstart, PPW, pdst, rop); + pdst++; + psrc++; + } + if(endmask) + { + getandputrop0(psrc, nstart, nend, pdst, rop); + } + } + x += w; + width -= w; + } + } + ppt++; + pwidth++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + + +/* Fill spans with stipples that aren't PPW bits wide */ +void +mfbUnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GC *pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + /* next three parameters are post-clip */ + int n; /* number of spans to fill */ + register DDXPointPtr ppt; /* pointer to list of start points */ + register int *pwidth; /* pointer to list of n widths */ + int iline; /* first line of tile to use */ + PixelType *addrlBase; /* pointer to start of bitmap */ + int nlwidth; /* width in longwords of bitmap */ + register PixelType *pdst; /* pointer to current word in bitmap */ + register PixelType *psrc; /* pointer to current word in tile */ + register int nlMiddle; + register int rop, nstart; + PixelType startmask; + PixmapPtr pTile; /* pointer to tile we want to fill with */ + int w, width, x, xSrc, ySrc, srcStartOver, nend; + PixelType endmask, *psrcT; + int tlwidth, rem, tileWidth, endinc; + int tileHeight; + int *pwidthFree; /* copies of the pointers to free */ + DDXPointPtr pptFree; + + if (!(pGC->planemask & 1)) + return; + + n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + pwidth = pwidthFree; + ppt = pptFree; + n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, + pptInit, pwidthInit, nInit, + ppt, pwidth, fSorted); + + pTile = pGC->stipple; + rop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop; + tlwidth = pTile->devKind / PGSZB; + xSrc = pDrawable->x; + ySrc = pDrawable->y; + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + /* this replaces rotating the stipple. Instead, we just adjust the offset + * at which we start grabbing bits from the stipple. + * Ensure that ppt->x - xSrc >= 0 and ppt->y - ySrc >= 0, + * so that iline and rem always stay within the tile bounds. + */ + xSrc += (pGC->patOrg.x % tileWidth) - tileWidth; + ySrc += (pGC->patOrg.y % tileHeight) - tileHeight; + while (n--) + { + iline = (ppt->y - ySrc) % tileHeight; + pdst = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); + psrcT = (PixelType *) pTile->devPrivate.ptr + (iline * tlwidth); + x = ppt->x; + + if (*pwidth) + { + width = *pwidth; + while(width > 0) + { + psrc = psrcT; + w = min(tileWidth, width); + if((rem = (x - xSrc) % tileWidth) != 0) + { + /* if we're in the middle of the tile, get + as many bits as will finish the span, or + as many as will get to the left edge of the tile, + or a longword worth, starting at the appropriate + offset in the tile. + */ + w = min(min(tileWidth - rem, width), BITMAP_SCANLINE_PAD); + endinc = rem / BITMAP_SCANLINE_PAD; + getandputrrop((psrc + endinc), (rem & PIM), (x & PIM), + w, pdst, rop) + if((x & PIM) + w >= PPW) + pdst++; + } + + else if(((x & PIM) + w) < PPW) + { + /* doing < PPW bits is easy, and worth special-casing */ + putbitsrrop(*psrc, x & PIM, w, pdst, rop); + } + else + { + /* start at the left edge of the tile, + and put down as much as we can + */ + maskbits(x, w, startmask, endmask, nlMiddle); + + if (startmask) + nstart = PPW - (x & PIM); + else + nstart = 0; + if (endmask) + nend = (x + w) & PIM; + else + nend = 0; + + srcStartOver = nstart > PLST; + + if(startmask) + { + putbitsrrop(*psrc, (x & PIM), nstart, pdst, rop); + pdst++; + if(srcStartOver) + psrc++; + } + + while(nlMiddle--) + { + getandputrrop0(psrc, nstart, PPW, pdst, rop); + pdst++; + psrc++; + } + if(endmask) + { + getandputrrop0(psrc, nstart, nend, pdst, rop); + } + } + x += w; + width -= w; + } + } + ppt++; + pwidth++; + } + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} diff --git a/mfb/mfbfont.c b/mfb/mfbfont.c new file mode 100644 index 000000000..499dac52a --- /dev/null +++ b/mfb/mfbfont.c @@ -0,0 +1,72 @@ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +*/ +/* $Xorg: mfbfont.c,v 1.4 2001/02/09 02:05:18 xorgcvs Exp $ */ +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "mfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "scrnintstr.h" + +/*ARGSUSED*/ +Bool +mfbRealizeFont( pscr, pFont) + ScreenPtr pscr; + FontPtr pFont; +{ + return (TRUE); +} + +/*ARGSUSED*/ +Bool +mfbUnrealizeFont( pscr, pFont) + ScreenPtr pscr; + FontPtr pFont; +{ + return (TRUE); +} diff --git a/mfb/mfbgc.c b/mfb/mfbgc.c new file mode 100644 index 000000000..8ab76ad37 --- /dev/null +++ b/mfb/mfbgc.c @@ -0,0 +1,1527 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbgc.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "mfb.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "region.h" + +#include "mistruct.h" +#include "migc.h" + +#include "maskbits.h" + +static GCFuncs mfbFuncs = { + mfbValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +#ifndef LOWMEMFTPT + +static GCOps whiteTECopyOps = { + mfbWhiteSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + mfbZeroPolyArcSS, + mfbFillPolyWhite, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltWhite, + mfbPolyGlyphBltWhite, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackTECopyOps = { + mfbBlackSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + mfbZeroPolyArcSS, + mfbFillPolyBlack, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltBlack, + mfbPolyGlyphBltBlack, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteTEInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + mfbPutImage, + miCopyArea, + miCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltWhite, + mfbPolyGlyphBltInvert, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackTEInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltBlack, + mfbPolyGlyphBltInvert, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteCopyOps = { + mfbWhiteSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + mfbZeroPolyArcSS, + mfbFillPolyWhite, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltWhite, + mfbPolyGlyphBltWhite, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackCopyOps = { + mfbBlackSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + mfbZeroPolyArcSS, + mfbFillPolyBlack, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltBlack, + mfbPolyGlyphBltBlack, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltWhite, + mfbPolyGlyphBltInvert, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltBlack, + mfbPolyGlyphBltInvert, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteWhiteCopyOps = { + mfbWhiteSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + mfbZeroPolyArcSS, + mfbFillPolyWhite, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + miImageGlyphBlt, + mfbPolyGlyphBltWhite, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackBlackCopyOps = { + mfbBlackSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + mfbZeroPolyArcSS, + mfbFillPolyBlack, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + miImageGlyphBlt, + mfbPolyGlyphBltBlack, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps fgEqBgInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + mfbPutImage, + mfbCopyArea, + mfbCopyPlane, + mfbPolyPoint, + mfbLineSS, + mfbSegmentSS, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + mfbPolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + miImageGlyphBlt, + mfbPolyGlyphBltInvert, + mfbSolidPP +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +#else + +static GCOps whiteTECopyOps = { + mfbWhiteSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyWhite, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltWhite, + mfbPolyGlyphBltWhite, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackTECopyOps = { + mfbBlackSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyBlack, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltBlack, + mfbPolyGlyphBltBlack, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteTEInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltWhite, + mfbPolyGlyphBltInvert, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackTEInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbTEGlyphBltBlack, + mfbPolyGlyphBltInvert, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteCopyOps = { + mfbWhiteSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyWhite, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltWhite, + mfbPolyGlyphBltWhite, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackCopyOps = { + mfbBlackSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyBlack, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltBlack, + mfbPolyGlyphBltBlack, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltWhite, + mfbPolyGlyphBltInvert, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + mfbImageGlyphBltBlack, + mfbPolyGlyphBltInvert, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps whiteWhiteCopyOps = { + mfbWhiteSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyWhite, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + miImageGlyphBlt, + mfbPolyGlyphBltWhite, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps blackBlackCopyOps = { + mfbBlackSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyBlack, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + miImageGlyphBlt, + mfbPolyGlyphBltBlack, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps fgEqBgInvertOps = { + mfbInvertSolidFS, + mfbSetSpans, + miPutImage, + miCopyArea, + miCopyPlane, + miPolyPoint, + miZeroLine, + miPolySegment, + miPolyRectangle, + miZeroPolyArc, + mfbFillPolyInvert, + mfbPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + miImageGlyphBlt, + mfbPolyGlyphBltInvert, + miPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +#endif /* ifndef LOWMEMFTPT */ + +struct commonOps { + int fg, bg; + int rrop; + int terminalFont; + GCOps *ops; + void (*fillArea)(); +}; + +static struct commonOps mfbCommonOps[] = { + { 1, 0, RROP_WHITE, 1, &whiteTECopyOps, mfbSolidWhiteArea }, + { 0, 1, RROP_BLACK, 1, &blackTECopyOps, mfbSolidBlackArea }, + { 1, 0, RROP_INVERT, 1, &whiteTEInvertOps, mfbSolidInvertArea }, + { 0, 1, RROP_INVERT, 1, &blackTEInvertOps, mfbSolidInvertArea }, + { 1, 0, RROP_WHITE, 0, &whiteCopyOps, mfbSolidWhiteArea }, + { 0, 1, RROP_BLACK, 0, &blackCopyOps, mfbSolidBlackArea }, + { 1, 0, RROP_INVERT, 0, &whiteInvertOps, mfbSolidInvertArea }, + { 0, 1, RROP_INVERT, 0, &blackInvertOps, mfbSolidInvertArea }, + { 1, 1, RROP_WHITE, 0, &whiteWhiteCopyOps, mfbSolidWhiteArea }, + { 0, 0, RROP_BLACK, 0, &blackBlackCopyOps, mfbSolidBlackArea }, + { 1, 1, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea }, + { 0, 0, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea }, +}; + +#define numberCommonOps (sizeof (mfbCommonOps) / sizeof (mfbCommonOps[0])) + +static GCOps * +matchCommon (pGC) + GCPtr pGC; +{ + int i; + struct commonOps *cop; + mfbPrivGC *priv; + + if (pGC->lineWidth != 0) + return 0; + if (pGC->lineStyle != LineSolid) + return 0; + if (pGC->fillStyle != FillSolid) + return 0; + if (!pGC->font || + FONTMAXBOUNDS(pGC->font,rightSideBearing) - + FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 || + FONTMINBOUNDS(pGC->font,characterWidth) < 0) + return 0; + priv = (mfbPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr; + for (i = 0; i < numberCommonOps; i++) { + cop = &mfbCommonOps[i]; + if ((pGC->fgPixel & 1) != cop->fg) + continue; + if ((pGC->bgPixel & 1) != cop->bg) + continue; + if (priv->rop != cop->rrop) + continue; + if (cop->terminalFont && !TERMINALFONT(pGC->font)) + continue; + priv->FillArea = cop->fillArea; + return cop->ops; + } + return 0; +} + + +Bool +mfbCreateGC(pGC) + register GCPtr pGC; +{ + mfbPrivGC *pPriv; + + pGC->clientClip = NULL; + pGC->clientClipType = CT_NONE; + + /* some of the output primitives aren't really necessary, since + they will be filled in ValidateGC because of dix/CreateGC() + setting all the change bits. Others are necessary because although + they depend on being a monochrome frame buffer, they don't change + */ + + pGC->ops = &whiteCopyOps; + pGC->funcs = &mfbFuncs; + + /* mfb wants to translate before scan convesion */ + pGC->miTranslate = 1; + + pPriv = (mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr); + pPriv->rop = mfbReduceRop(pGC->alu, pGC->fgPixel); + pPriv->fExpose = TRUE; + pPriv->pRotatedPixmap = NullPixmap; + pPriv->freeCompClip = FALSE; + pPriv->FillArea = mfbSolidWhiteArea; + return TRUE; +} + +/* Clipping conventions + if the drawable is a window + CT_REGION ==> pCompositeClip really is the composite + CT_other ==> pCompositeClip is the window clip region + if the drawable is a pixmap + CT_REGION ==> pCompositeClip is the translated client region + clipped to the pixmap boundary + CT_other ==> pCompositeClip is the pixmap bounding box +*/ + +/*ARGSUSED*/ +void +mfbValidateGC(pGC, changes, pDrawable) + register GCPtr pGC; + unsigned long changes; + DrawablePtr pDrawable; +{ + register mfbPrivGCPtr devPriv; + int mask; /* stateChanges */ + int index; /* used for stepping through bitfields */ + int xrot, yrot; /* rotations for tile and stipple pattern */ + int rrop; /* reduced rasterop */ + /* flags for changing the proc vector + and updating things in devPriv + */ + int new_rotate, new_rrop, new_line, new_text, new_fill; + DDXPointRec oldOrg; /* origin of thing GC was last used with */ + + oldOrg = pGC->lastWinOrg; + + pGC->lastWinOrg.x = pDrawable->x; + pGC->lastWinOrg.y = pDrawable->y; + + /* we need to re-rotate the tile if the previous window/pixmap + origin (oldOrg) differs from the new window/pixmap origin + (pGC->lastWinOrg) + */ + new_rotate = (oldOrg.x != pGC->lastWinOrg.x) || + (oldOrg.y != pGC->lastWinOrg.y); + + devPriv = ((mfbPrivGCPtr) (pGC->devPrivates[mfbGCPrivateIndex].ptr)); + + /* + if the client clip is different or moved OR + the subwindowMode has changed OR + the window's clip has changed since the last validation + we need to recompute the composite clip + */ + if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || + (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) + ) + { + miComputeCompositeClip(pGC, pDrawable); + } + + new_rrop = FALSE; + new_line = FALSE; + new_text = FALSE; + new_fill = FALSE; + + mask = changes; + while (mask) + { + index = lowbit (mask); + mask &= ~index; + + /* this switch acculmulates a list of which procedures + might have to change due to changes in the GC. in + some cases (e.g. changing one 16 bit tile for another) + we might not really need a change, but the code is + being paranoid. + this sort of batching wins if, for example, the alu + and the font have been changed, or any other pair + of items that both change the same thing. + */ + switch (index) + { + case GCFunction: + case GCForeground: + new_rrop = TRUE; + break; + case GCPlaneMask: + break; + case GCBackground: + new_rrop = TRUE; /* for opaque stipples */ + break; + case GCLineStyle: + case GCLineWidth: + case GCJoinStyle: + new_line = TRUE; + break; + case GCCapStyle: + break; + case GCFillStyle: + new_fill = TRUE; + break; + case GCFillRule: + break; + case GCTile: + if(pGC->tileIsPixel) + break; + new_rotate = TRUE; + new_fill = TRUE; + break; + + case GCStipple: + if(pGC->stipple == (PixmapPtr)NULL) + break; + new_rotate = TRUE; + new_fill = TRUE; + break; + + case GCTileStipXOrigin: + new_rotate = TRUE; + break; + + case GCTileStipYOrigin: + new_rotate = TRUE; + break; + + case GCFont: + new_text = TRUE; + break; + case GCSubwindowMode: + break; + case GCGraphicsExposures: + break; + case GCClipXOrigin: + break; + case GCClipYOrigin: + break; + case GCClipMask: + break; + case GCDashOffset: + break; + case GCDashList: + break; + case GCArcMode: + break; + default: + break; + } + } + + /* deal with the changes we've collected . + new_rrop must be done first because subsequent things + depend on it. + */ + + if(new_rotate || new_fill) + { + Bool new_pix = FALSE; + + /* figure out how much to rotate */ + xrot = pGC->patOrg.x; + yrot = pGC->patOrg.y; + xrot += pDrawable->x; + yrot += pDrawable->y; + + switch (pGC->fillStyle) + { + case FillTiled: + /* copy current tile and stipple */ + if (!pGC->tileIsPixel && (pGC->tile.pixmap->drawable.width <= PPW) && + !(pGC->tile.pixmap->drawable.width & (pGC->tile.pixmap->drawable.width - 1))) + { + mfbCopyRotatePixmap(pGC->tile.pixmap, + &devPriv->pRotatedPixmap, xrot, yrot); + new_pix = TRUE; + } + break; + case FillStippled: + case FillOpaqueStippled: + if (pGC->stipple && (pGC->stipple->drawable.width <= PPW) && + !(pGC->stipple->drawable.width & (pGC->stipple->drawable.width - 1))) + { + mfbCopyRotatePixmap(pGC->stipple, + &devPriv->pRotatedPixmap, xrot, yrot); + new_pix = TRUE; + } + } + /* destroy any previously rotated tile or stipple */ + if (!new_pix && devPriv->pRotatedPixmap) + { + (*pDrawable->pScreen->DestroyPixmap)(devPriv->pRotatedPixmap); + devPriv->pRotatedPixmap = (PixmapPtr)NULL; + } + } + + /* + * duck out here when the GC is unchanged + */ + + if (!changes) + return; + + if (new_rrop || new_fill) + { + rrop = mfbReduceRop(pGC->alu, pGC->fgPixel); + devPriv->rop = rrop; + new_fill = TRUE; + /* FillArea raster op is GC's for tile filling, + and the reduced rop for solid and stipple + */ + if (pGC->fillStyle == FillTiled) + devPriv->ropFillArea = pGC->alu; + else + devPriv->ropFillArea = rrop; + + /* opaque stipples: + fg bg ropOpStip fill style + 1 0 alu tile + 0 1 inverseAlu tile + 1 1 rrop(fg, alu) solid + 0 0 rrop(fg, alu) solid + Note that rrop(fg, alu) == mfbPrivGC.rop, so we don't really need to + compute it. + */ + if (pGC->fillStyle == FillOpaqueStippled) + { + if ((pGC->fgPixel & 1) != (pGC->bgPixel & 1)) + { + if (pGC->fgPixel & 1) + devPriv->ropOpStip = pGC->alu; + else + devPriv->ropOpStip = InverseAlu[pGC->alu]; + } + else + devPriv->ropOpStip = rrop; + devPriv->ropFillArea = devPriv->ropOpStip; + } + } + else + rrop = devPriv->rop; + + if (new_line || new_fill || new_text) + { + GCOps *newops; + + if (newops = matchCommon (pGC)) + { + if (pGC->ops->devPrivate.val) + miDestroyGCOps (pGC->ops); + pGC->ops = newops; + new_line = new_fill = new_text = 0; + } + else + { + if (!pGC->ops->devPrivate.val) + { + pGC->ops = miCreateGCOps (pGC->ops); + pGC->ops->devPrivate.val = 1; + } + } + } + + if (new_line || new_fill) + { + if (pGC->lineWidth == 0) + { +#ifndef LOWMEMFTPT + if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid) + && ((rrop == RROP_WHITE) || (rrop == RROP_BLACK))) + pGC->ops->PolyArc = mfbZeroPolyArcSS; + else +#endif /* ifndef LOWMEMFTPT */ + pGC->ops->PolyArc = miZeroPolyArc; + } + else + pGC->ops->PolyArc = miPolyArc; + if (pGC->lineStyle == LineSolid) + { + if(pGC->lineWidth == 0) + { +#ifndef LOWMEMFTPT + if (pGC->fillStyle == FillSolid) + { + pGC->ops->PolySegment = mfbSegmentSS; + pGC->ops->Polylines = mfbLineSS; + } + else +#endif /* ifndef LOWMEMFTPT */ + { + pGC->ops->PolySegment = miPolySegment; + pGC->ops->Polylines = miZeroLine; + } + } + else + { + pGC->ops->PolySegment = miPolySegment; + pGC->ops->Polylines = miWideLine; + } + } + else + { +#ifndef LOWMEMFTPT + if(pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) + { + pGC->ops->Polylines = mfbLineSD; + pGC->ops->PolySegment = mfbSegmentSD; + } + else +#endif /* ifndef LOWMEMFTPT */ + { + pGC->ops->Polylines = miWideDash; + pGC->ops->PolySegment = miPolySegment; + } + } + } + + if (new_text || new_fill) + { + if ((pGC->font) && + (FONTMAXBOUNDS(pGC->font,rightSideBearing) - + FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 || + FONTMINBOUNDS(pGC->font,characterWidth) < 0)) + { + pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; + pGC->ops->ImageGlyphBlt = miImageGlyphBlt; + } + else + { + /* special case ImageGlyphBlt for terminal emulator fonts */ + +#ifndef LOWMEMFTPT + + if ((pGC->font) && + TERMINALFONT(pGC->font) && + ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))) + { + /* pcc bug makes this not compile... + pGC->ops->ImageGlyphBlt = (pGC->fgPixel & 1) ? mfbTEGlyphBltWhite : + mfbTEGlyphBltBlack; + */ + if (pGC->fgPixel & 1) + pGC->ops->ImageGlyphBlt = mfbTEGlyphBltWhite; + else + pGC->ops->ImageGlyphBlt = mfbTEGlyphBltBlack; + } + else + +#endif /* ifndef LOWMEMFTPT */ + + { + if (pGC->fgPixel & 1) + pGC->ops->ImageGlyphBlt = mfbImageGlyphBltWhite; + else + pGC->ops->ImageGlyphBlt = mfbImageGlyphBltBlack; + } + + /* now do PolyGlyphBlt */ + if (pGC->fillStyle == FillSolid || + (pGC->fillStyle == FillOpaqueStippled && + (pGC->fgPixel & 1) == (pGC->bgPixel & 1) + ) + ) + { + if (rrop == RROP_WHITE) + pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltWhite; + else if (rrop == RROP_BLACK) + pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltBlack; + else if (rrop == RROP_INVERT) + pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltInvert; + else + pGC->ops->PolyGlyphBlt = (void (*)())NoopDDA; + } + else + { + pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; + } + } + } + + if (new_fill) + +#ifndef LOWMEMFTPT + + { + /* install a suitable fillspans and pushpixels */ + pGC->ops->PushPixels = mfbPushPixels; + pGC->ops->FillPolygon = miFillPolygon; + if ((pGC->fillStyle == FillSolid) || + ((pGC->fillStyle == FillOpaqueStippled) && + ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)))) + { + pGC->ops->PushPixels = mfbSolidPP; + switch(devPriv->rop) + { + case RROP_WHITE: + pGC->ops->FillSpans = mfbWhiteSolidFS; + pGC->ops->FillPolygon = mfbFillPolyWhite; + break; + case RROP_BLACK: + pGC->ops->FillSpans = mfbBlackSolidFS; + pGC->ops->FillPolygon = mfbFillPolyBlack; + break; + case RROP_INVERT: + pGC->ops->FillSpans = mfbInvertSolidFS; + pGC->ops->FillPolygon = mfbFillPolyInvert; + break; + case RROP_NOP: + pGC->ops->FillSpans = (void (*)())NoopDDA; + pGC->ops->FillPolygon = (void (*)())NoopDDA; + break; + } + } + /* beyond this point, opaqueStippled ==> fg != bg */ + else if (((pGC->fillStyle == FillTiled) || + (pGC->fillStyle == FillOpaqueStippled)) && + !devPriv->pRotatedPixmap) + { + pGC->ops->FillSpans = mfbUnnaturalTileFS; + } + else if ((pGC->fillStyle == FillStippled) && !devPriv->pRotatedPixmap) + { + pGC->ops->FillSpans = mfbUnnaturalStippleFS; + } + else if (pGC->fillStyle == FillStippled) + { + switch(devPriv->rop) + { + case RROP_WHITE: + pGC->ops->FillSpans = mfbWhiteStippleFS; + break; + case RROP_BLACK: + pGC->ops->FillSpans = mfbBlackStippleFS; + break; + case RROP_INVERT: + pGC->ops->FillSpans = mfbInvertStippleFS; + break; + case RROP_NOP: + pGC->ops->FillSpans = (void (*)())NoopDDA; + break; + } + } + else /* overload tiles to do parti-colored opaque stipples */ + { + pGC->ops->FillSpans = mfbTileFS; + } + if (pGC->fillStyle == FillSolid) + pGC->ops->PolyFillArc = mfbPolyFillArcSolid; + else + pGC->ops->PolyFillArc = miPolyFillArc; + /* the rectangle code doesn't deal with opaque stipples that + are two colors -- we can fool it for fg==bg, though + */ + if ((((pGC->fillStyle == FillTiled) || + (pGC->fillStyle == FillStippled)) && + !devPriv->pRotatedPixmap) || + ((pGC->fillStyle == FillOpaqueStippled) && + ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))) + ) + { + pGC->ops->PolyFillRect = miPolyFillRect; + } + else /* deal with solids and natural stipples and tiles */ + { + pGC->ops->PolyFillRect = mfbPolyFillRect; + + if ((pGC->fillStyle == FillSolid) || + ((pGC->fillStyle == FillOpaqueStippled) && + ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)))) + { + switch(devPriv->rop) + { + case RROP_WHITE: + devPriv->FillArea = mfbSolidWhiteArea; + break; + case RROP_BLACK: + devPriv->FillArea = mfbSolidBlackArea; + break; + case RROP_INVERT: + devPriv->FillArea = mfbSolidInvertArea; + break; + case RROP_NOP: + devPriv->FillArea = (void (*)())NoopDDA; + break; + } + } + else if (pGC->fillStyle == FillStippled) + { + switch(devPriv->rop) + { + case RROP_WHITE: + devPriv->FillArea = mfbStippleWhiteArea; + break; + case RROP_BLACK: + devPriv->FillArea = mfbStippleBlackArea; + break; + case RROP_INVERT: + devPriv->FillArea = mfbStippleInvertArea; + break; + case RROP_NOP: + devPriv->FillArea = (void (*)())NoopDDA; + break; + } + } + else /* deal with tiles */ + { + switch (pGC->alu) + { + case GXcopy: + devPriv->FillArea = mfbTileAreaPPWCopy; + break; + default: + devPriv->FillArea = mfbTileAreaPPWGeneral; + break; + } + } + } /* end of natural rectangles */ + } /* end of new_fill */ + +#else + + { + /* install a suitable fillspans and pushpixels */ + pGC->ops->PushPixels = miPushPixels; + pGC->ops->FillPolygon = miFillPolygon; + if ((pGC->fillStyle == FillSolid) || + ((pGC->fillStyle == FillOpaqueStippled) && + ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)))) + { + pGC->ops->PushPixels = miPushPixels; + switch(devPriv->rop) + { + case RROP_WHITE: + pGC->ops->FillSpans = mfbWhiteSolidFS; + pGC->ops->FillPolygon = mfbFillPolyWhite; + break; + case RROP_BLACK: + pGC->ops->FillSpans = mfbBlackSolidFS; + pGC->ops->FillPolygon = mfbFillPolyBlack; + break; + case RROP_INVERT: + pGC->ops->FillSpans = mfbInvertSolidFS; + pGC->ops->FillPolygon = mfbFillPolyInvert; + break; + case RROP_NOP: + pGC->ops->FillSpans = (void (*)())NoopDDA; + pGC->ops->FillPolygon = (void (*)())NoopDDA; + break; + } + } + /* beyond this point, opaqueStippled ==> fg != bg */ + else if (((pGC->fillStyle == FillTiled) || + (pGC->fillStyle == FillOpaqueStippled)) && + !devPriv->pRotatedPixmap) + { + pGC->ops->FillSpans = mfbUnnaturalTileFS; + } + else if ((pGC->fillStyle == FillStippled) && !devPriv->pRotatedPixmap) + { + pGC->ops->FillSpans = mfbUnnaturalStippleFS; + } + else if (pGC->fillStyle == FillStippled) + { + switch(devPriv->rop) + { + case RROP_WHITE: + pGC->ops->FillSpans = mfbWhiteStippleFS; + case RROP_BLACK: + pGC->ops->FillSpans = mfbBlackStippleFS; + case RROP_INVERT: + pGC->ops->FillSpans = mfbInvertStippleFS; + case RROP_NOP: + pGC->ops->FillSpans = (void (*)())NoopDDA; + break; + } + } + else /* overload tiles to do parti-colored opaque stipples */ + { + pGC->ops->FillSpans = mfbTileFS; + } + pGC->ops->PolyFillArc = miPolyFillArc; + /* the rectangle code doesn't deal with opaque stipples that + are two colors -- we can fool it for fg==bg, though + */ + if ((((pGC->fillStyle == FillTiled) || + (pGC->fillStyle == FillStippled)) && + !devPriv->pRotatedPixmap) || + ((pGC->fillStyle == FillOpaqueStippled) && + ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))) + ) + { + pGC->ops->PolyFillRect = miPolyFillRect; + } + else /* deal with solids and natural stipples and tiles */ + { + pGC->ops->PolyFillRect = mfbPolyFillRect; + + if ((pGC->fillStyle == FillSolid) || + ((pGC->fillStyle == FillOpaqueStippled) && + ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)))) + { + switch(devPriv->rop) + { + case RROP_WHITE: + devPriv->FillArea = mfbSolidWhiteArea; + break; + case RROP_BLACK: + devPriv->FillArea = mfbSolidBlackArea; + break; + case RROP_INVERT: + devPriv->FillArea = mfbSolidInvertArea; + break; + case RROP_NOP: + devPriv->FillArea = (void (*)())NoopDDA; + break; + } + } + else if (pGC->fillStyle == FillStippled) + { + switch(devPriv->rop) + { + case RROP_WHITE: + devPriv->FillArea = mfbStippleWhiteArea; + break; + case RROP_BLACK: + devPriv->FillArea = mfbStippleBlackArea; + break; + case RROP_INVERT: + devPriv->FillArea = mfbStippleInvertArea; + break; + case RROP_NOP: + devPriv->FillArea = (void (*)())NoopDDA; + break; + } + } + else /* deal with tiles */ + { + switch (pGC->alu) + { + case GXcopy: + devPriv->FillArea = mfbTileAreaPPWCopy; + break; + default: + devPriv->FillArea = mfbTileAreaPPWGeneral; + break; + } + } + } /* end of natural rectangles */ + } /* end of new_fill */ + +#endif /* ifndef LOWMEMFTPT */ + +} + +/* table to map alu(src, dst) to alu(~src, dst) */ +int InverseAlu[16] = { + GXclear, + GXandInverted, + GXnor, + GXcopyInverted, + GXand, + GXnoop, + GXequiv, + GXorInverted, + GXandReverse, + GXxor, + GXinvert, + GXnand, + GXcopy, + GXor, + GXorReverse, + GXset +}; + +int +mfbReduceRop(alu, src) + register int alu; + register Pixel src; +{ + int rop; + if ((src & 1) == 0) /* src is black */ + { + switch(alu) + { + case GXclear: + rop = RROP_BLACK; + break; + case GXand: + rop = RROP_BLACK; + break; + case GXandReverse: + rop = RROP_BLACK; + break; + case GXcopy: + rop = RROP_BLACK; + break; + case GXandInverted: + rop = RROP_NOP; + break; + case GXnoop: + rop = RROP_NOP; + break; + case GXxor: + rop = RROP_NOP; + break; + case GXor: + rop = RROP_NOP; + break; + case GXnor: + rop = RROP_INVERT; + break; + case GXequiv: + rop = RROP_INVERT; + break; + case GXinvert: + rop = RROP_INVERT; + break; + case GXorReverse: + rop = RROP_INVERT; + break; + case GXcopyInverted: + rop = RROP_WHITE; + break; + case GXorInverted: + rop = RROP_WHITE; + break; + case GXnand: + rop = RROP_WHITE; + break; + case GXset: + rop = RROP_WHITE; + break; + } + } + else /* src is white */ + { + switch(alu) + { + case GXclear: + rop = RROP_BLACK; + break; + case GXand: + rop = RROP_NOP; + break; + case GXandReverse: + rop = RROP_INVERT; + break; + case GXcopy: + rop = RROP_WHITE; + break; + case GXandInverted: + rop = RROP_BLACK; + break; + case GXnoop: + rop = RROP_NOP; + break; + case GXxor: + rop = RROP_INVERT; + break; + case GXor: + rop = RROP_WHITE; + break; + case GXnor: + rop = RROP_BLACK; + break; + case GXequiv: + rop = RROP_NOP; + break; + case GXinvert: + rop = RROP_INVERT; + break; + case GXorReverse: + rop = RROP_WHITE; + break; + case GXcopyInverted: + rop = RROP_BLACK; + break; + case GXorInverted: + rop = RROP_NOP; + break; + case GXnand: + rop = RROP_INVERT; + break; + case GXset: + rop = RROP_WHITE; + break; + } + } + return rop; +} diff --git a/mfb/mfbgetsp.c b/mfb/mfbgetsp.c new file mode 100644 index 000000000..9e0a5b513 --- /dev/null +++ b/mfb/mfbgetsp.c @@ -0,0 +1,154 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbgetsp.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" +#include "Xmd.h" + +#include "misc.h" +#include "region.h" +#include "gc.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "mfb.h" +#include "maskbits.h" + +#include "servermd.h" + +/* GetSpans -- for each span, gets bits from drawable starting at ppt[i] + * and continuing for pwidth[i] bits + * Each scanline returned will be server scanline padded, i.e., it will come + * out to an integral number of words. + */ +/*ARGSUSED*/ +void +mfbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart) + DrawablePtr pDrawable; /* drawable from which to get bits */ + int wMax; /* largest value of all *pwidths */ + register DDXPointPtr ppt; /* points to start copying from */ + int *pwidth; /* list of number of bits to copy */ + int nspans; /* number of scanlines to copy */ + char *pchardstStart; /* where to put the bits */ +{ + PixelType *pdstStart = (PixelType *)pchardstStart; + register PixelType *pdst; /* where to put the bits */ + register PixelType *psrc; /* where to get the bits */ + register PixelType tmpSrc; /* scratch buffer for bits */ + PixelType *psrcBase; /* start of src bitmap */ + int widthSrc; /* width of pixmap in bytes */ + register DDXPointPtr pptLast; /* one past last point to get */ + int xEnd; /* last pixel to copy from */ + register int nstart; + int nend; + int srcStartOver; + PixelType startmask, endmask; + unsigned int srcBit; + int nlMiddle, nl; + int w; + + pptLast = ppt + nspans; + + mfbGetPixelWidthAndPointer(pDrawable, widthSrc, psrcBase); + pdst = pdstStart; + + while(ppt < pptLast) + { + /* XXX should this really be << PWSH, or * 8, or * PGSZB? */ + xEnd = min(ppt->x + *pwidth, widthSrc << PWSH); + pwidth++; + psrc = mfbScanline(psrcBase, ppt->x, ppt->y, widthSrc); + w = xEnd - ppt->x; + srcBit = ppt->x & PIM; + + if (srcBit + w <= PPW) + { + getandputbits0(psrc, srcBit, w, pdst); + pdst++; + } + else + { + + maskbits(ppt->x, w, startmask, endmask, nlMiddle); + if (startmask) + nstart = PPW - srcBit; + else + nstart = 0; + if (endmask) + nend = xEnd & PIM; + srcStartOver = srcBit + nstart > PLST; + if (startmask) + { + getandputbits0(psrc, srcBit, nstart, pdst); + if(srcStartOver) + psrc++; + } + nl = nlMiddle; +#ifdef FASTPUTBITS + Duff(nl, putbits(*psrc, nstart, PPW, pdst); psrc++; pdst++;); +#else + while (nl--) + { + tmpSrc = *psrc; + putbits(tmpSrc, nstart, PPW, pdst); + psrc++; + pdst++; + } +#endif + if (endmask) + { + putbits(*psrc, nstart, nend, pdst); + if(nstart + nend > PPW) + pdst++; + } + if (startmask || endmask) + pdst++; + } + ppt++; + } +} diff --git a/mfb/mfbhrzvert.c b/mfb/mfbhrzvert.c new file mode 100644 index 000000000..5498a4c0b --- /dev/null +++ b/mfb/mfbhrzvert.c @@ -0,0 +1,172 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbhrzvert.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" + +#include "gc.h" +#include "window.h" +#include "pixmap.h" +#include "region.h" + +#include "mfb.h" +#include "maskbits.h" + +/* horizontal solid line + abs(len) > 1 +*/ +mfbHorzS(rop, addrl, nlwidth, x1, y1, len) +int rop; /* a reduced rasterop */ +register PixelType *addrl; /* pointer to base of bitmap */ +register int nlwidth; /* width in longwords of bitmap */ +int x1; /* initial point */ +int y1; +int len; /* length of line */ +{ + register PixelType startmask; + register PixelType endmask; + register int nlmiddle; + + + /* force the line to go left to right + but don't draw the last point + */ + if (len < 0) + { + x1 += len; + x1 += 1; + len = -len; + } + + addrl = mfbScanline(addrl, x1, y1, nlwidth); + + /* all bits inside same longword */ + if ( ((x1 & PIM) + len) < PPW) + { + maskpartialbits(x1, len, startmask); + if (rop == RROP_BLACK) + { + *addrl &= ~startmask; + } + else if (rop == RROP_WHITE) + { + *addrl |= startmask; + } + else if (rop == RROP_INVERT) + { + *addrl ^= startmask; + } + } + else + { + maskbits(x1, len, startmask, endmask, nlmiddle); + if (rop == RROP_BLACK) + { + if (startmask) + *addrl++ &= ~startmask; + Duff (nlmiddle, *addrl++ = 0x0); + if (endmask) + *addrl &= ~endmask; + } + else if (rop == RROP_WHITE) + { + if (startmask) + *addrl++ |= startmask; + Duff (nlmiddle, *addrl++ = ~0); + if (endmask) + *addrl |= endmask; + } + else if (rop == RROP_INVERT) + { + if (startmask) + *addrl++ ^= startmask; + Duff (nlmiddle, *addrl++ ^= ~0); + if (endmask) + *addrl ^= endmask; + } + } +} + +/* vertical solid line + this uses do loops because pcc (Ultrix 1.2, bsd 4.2) generates + better code. sigh. we know that len will never be 0 or 1, so + it's OK to use it. +*/ + +mfbVertS(rop, addrl, nlwidth, x1, y1, len) +int rop; /* a reduced rasterop */ +register PixelType *addrl; /* pointer to base of bitmap */ +register int nlwidth; /* width in longwords of bitmap */ +int x1, y1; /* initial point */ +register int len; /* length of line */ +{ + register PixelType bitmask; + + addrl = mfbScanline(addrl, x1, y1, nlwidth); + + if (len < 0) + { + nlwidth = -nlwidth; + len = -len; + } + + if (rop == RROP_BLACK) + { + bitmask = rmask[x1 & PIM]; + Duff(len, *addrl &= bitmask; mfbScanlineInc(addrl, nlwidth) ); + } + else if (rop == RROP_WHITE) + { + bitmask = mask[x1 & PIM]; + Duff(len, *addrl |= bitmask; mfbScanlineInc(addrl, nlwidth) ); + } + else if (rop == RROP_INVERT) + { + bitmask = mask[x1 & PIM]; + Duff(len, *addrl ^= bitmask; mfbScanlineInc(addrl, nlwidth) ); + } +} diff --git a/mfb/mfbimage.c b/mfb/mfbimage.c new file mode 100644 index 000000000..93b01db02 --- /dev/null +++ b/mfb/mfbimage.c @@ -0,0 +1,173 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbimage.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +#include "X.h" + +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" + +#include "mfb.h" +#include "mi.h" +#include "Xmd.h" + +#include "maskbits.h" + +#include "servermd.h" + +/* Put and Get images on a monochrome frame buffer + * + * we do this by creating a temporary pixmap and making its + * pointer to bits point to the buffer read in from the client. + * this works because of the padding rules specified at startup + * + * Note that CopyArea must know how to copy a bitmap into the server-format + * temporary pixmap. + * + * For speed, mfbPutImage should allocate the temporary pixmap on the stack. + * + * even though an XYBitmap and an XYPixmap have the same + * format (for this device), PutImage has different semantics for the + * two. XYPixmap just does the copy; XYBitmap takes gc.fgPixel for + * a 1 bit, gc.bgPixel for a 0 bit, which we notice is exactly + * like CopyPlane. + * + * written by drewry, september 1986 + */ + + + +/*ARGSUSED*/ +void +mfbPutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pImage) + DrawablePtr dst; + GCPtr pGC; + int depth, x, y, w, h; + int leftPad; + int format; + char *pImage; +{ + PixmapPtr pPixmap; + + if (!(pGC->planemask & 1)) + return; + + /* 0 may confuse CreatePixmap, and will sometimes be + passed by the mi text code + */ + if ((w == 0) || (h == 0)) + return; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w+leftPad, h, 1, 1, + BitmapBytePad(w+leftPad), (pointer)pImage); + if (!pPixmap) + return; + + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->fExpose = FALSE; + if (format != XYBitmap) + (*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, leftPad, 0, + w, h, x, y); + else + (*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, leftPad, 0, + w, h, x, y, 1); + ((mfbPrivGC*)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->fExpose = TRUE; + FreeScratchPixmapHeader(pPixmap); +} + + +/* + * pdstLine points to space allocated by caller, which he can do since + * he knows dimensions of the pixmap + * we can call mfbDoBitblt because the dispatcher has promised not to send us + * anything that would require going over the edge of the screen. + * + * XYPixmap and ZPixmap are the same for mfb. + * For any planemask with bit 0 == 0, just fill the dst with 0. + */ +/*ARGSUSED*/ +void +mfbGetImage( pDrawable, sx, sy, w, h, format, planeMask, pdstLine) + DrawablePtr pDrawable; + int sx, sy, w, h; + unsigned int format; + unsigned long planeMask; + char *pdstLine; +{ + PixmapPtr pPixmap; + BoxRec box; + DDXPointRec ptSrc; + RegionRec rgnDst; + + if (planeMask & 0x1) + { + ScreenPtr pScreen = pDrawable->pScreen; + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(pScreen, w, h, /*depth*/ 1, /*bpp*/ 1, + BitmapBytePad(w), (pointer)pdstLine); + if (!pPixmap) + return; + + ptSrc.x = sx + pDrawable->x; + ptSrc.y = sy + pDrawable->y; + box.x1 = 0; + box.y1 = 0; + box.x2 = w; + box.y2 = h; + REGION_INIT(pScreen, &rgnDst, &box, 1); + mfbDoBitblt(pDrawable, (DrawablePtr)pPixmap, + GXcopy, &rgnDst, &ptSrc); + REGION_UNINIT(pScreen, &rgnDst); + FreeScratchPixmapHeader(pPixmap); + } + else + { + bzero(pdstLine, BitmapBytePad(w) * h); + } +} diff --git a/mfb/mfbimggblt.c b/mfb/mfbimggblt.c new file mode 100644 index 000000000..9542b5556 --- /dev/null +++ b/mfb/mfbimggblt.c @@ -0,0 +1,440 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbimggblt.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "mfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "maskbits.h" + +/* + we should eventually special-case fixed-width fonts for ImageText. + + this works for fonts with glyphs <= 32 bits wide. + + the clipping calculations are done for worst-case fonts. +we make no assumptions about the heights, widths, or bearings +of the glyphs. if we knew that the glyphs are all the same height, +we could clip the tops and bottoms per clipping box, rather +than per character per clipping box. if we knew that the glyphs' +left and right bearings were wlle-behaved, we could clip a single +character at the start, output until the last unclipped +character, and then clip the last one. this is all straightforward +to determine based on max-bounds and min-bounds from the font. + there is some inefficiency introduced in the per-character +clipping to make what's going on clearer. + + (it is possible, for example, for a font to be defined in which the +next-to-last character in a font would be clipped out, but the last +one wouldn't. the code below deals with this.) + + Image text looks at the bits in the glyph and the fg and bg in the +GC. it paints a rectangle, as defined in the protocol dcoument, +and the paints the characters. + + to avoid source proliferation, this file is compiled +three times: + MFBIMAGEGLYPHBLT OPEQ + mfbImageGlyphBltWhite |= + mfbImageGlyphBltBlack &=~ + + the register allocations for startmask and endmask may not +be the right thing. are there two other deserving candidates? +xoff, pdst, pglyph, and tmpSrc seem like the right things, though. +*/ + +void +MFBIMAGEGLYPHBLT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GC *pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + ExtentInfoRec info; /* used by QueryGlyphExtents() */ + BoxRec bbox; /* string's bounding box */ + xRectangle backrect;/* backing rectangle to paint. + in the general case, NOT necessarily + the same as the string's bounding box + */ + + CharInfoPtr pci; + int xorg, yorg; /* origin of drawable in bitmap */ + int widthDst; /* width of dst in longwords */ + + /* these keep track of the character origin */ + PixelType *pdstBase; + /* points to longword with character origin */ + int xchar; /* xorigin of char (mod 32) */ + + /* these are used for placing the glyph */ + register int xoff; /* x offset of left edge of glyph (mod 32) */ + register PixelType *pdst; + /* pointer to current longword in dst */ + + int w; /* width of glyph in bits */ + int h; /* height of glyph */ + int widthGlyph; /* width of glyph, in bytes */ + register unsigned char *pglyph; + /* pointer to current row of glyph */ + + /* used for putting down glyph */ + register PixelType tmpSrc; + /* for getting bits from glyph */ + register PixelType startmask; + register PixelType endmask; + + register int nFirst;/* bits of glyph in current longword */ + void (* oldFillArea)(); + /* we might temporarily usurp this + field in devPriv */ + + if (!(pGC->planemask & 1)) + return; + + xorg = pDrawable->x; + yorg = pDrawable->y; + mfbGetPixelWidthAndPointer(pDrawable, widthDst, pdstBase); + + QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info); + + backrect.x = x; + backrect.y = y - FONTASCENT(pGC->font); + backrect.width = info.overallWidth; + backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + + x += xorg; + y += yorg; + + bbox.x1 = x + info.overallLeft; + bbox.x2 = x + info.overallRight; + bbox.y1 = y - info.overallAscent; + bbox.y2 = y + info.overallDescent; + + /* UNCLEAN CODE + we know the mfbPolyFillRect uses only three fields in + devPrivate[mfbGCPrivateIndex].ptr, two of which (the rotated + tile/stipple and the ropFillArea) are + irrelevant for solid filling, so we just poke the FillArea + field. the GC is now in an inconsistent state, but we'll fix + it as soon as PolyFillRect returns. fortunately, the server + is single threaded. + + NOTE: + if you are not using the standard mfbFillRectangle code, you + need to poke any fields in the GC the rectangle stuff need + (probably alu, fgPixel, and fillStyle) and in devPrivate[mfbGCPrivateIndex].ptr + (probably rop or ropFillArea.) You could just call ValidateGC, + but that is usually not a cheap thing to do. + */ + + oldFillArea = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->FillArea; + +/* pcc doesn't like this. why? + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->FillArea = + ((pGC->bgPixel & 1) ? mfbSolidWhiteArea : mfbSolidBlackArea); +*/ + if (pGC->bgPixel & 1) + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->FillArea = mfbSolidWhiteArea; + else + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->FillArea = mfbSolidBlackArea; + +#ifndef LOWMEMFTPT + mfbPolyFillRect(pDrawable, pGC, 1, &backrect); +#else + miPolyFillRect(pDrawable, pGC, 1, &backrect); +#endif + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->FillArea = oldFillArea; + + /* the faint-hearted can open their eyes now */ + switch (RECT_IN_REGION(pGC->pScreen, + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, &bbox)) + { + case rgnOUT: + break; + case rgnIN: + pdstBase = mfbScanlineNoBankSwitch(pdstBase, x, y, widthDst); + xchar = x & PIM; + + while(nglyph--) + { + pci = *ppci; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + h = pci->metrics.ascent + pci->metrics.descent; + widthGlyph = GLYPHWIDTHBYTESPADDED(pci); + + /* start at top scanline of glyph */ + pdst = mfbScanlineDelta(pdstBase, -pci->metrics.ascent, widthDst); + + /* find correct word in scanline and x offset within it + for left edge of glyph + */ + xoff = xchar + pci->metrics.leftSideBearing; + if (xoff > PLST) + { + pdst++; + xoff &= PIM; + } + else if (xoff < 0) + { + xoff += PPW; + pdst--; + } + + if ((xoff + w) <= PPW) + { + /* glyph all in one longword */ + maskpartialbits(xoff, w, startmask); + while (h--) + { + getleftbits(pglyph, w, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } + else + { + /* glyph crosses longword boundary */ + maskPPWbits(xoff, w, startmask, endmask); + nFirst = PPW - xoff; + while (h--) + { + getleftbits(pglyph, w, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } /* glyph crosses longwords boundary */ + + /* update character origin */ + x += pci->metrics.characterWidth; + xchar += pci->metrics.characterWidth; + if (xchar > PLST) + { + xchar -= PPW; + pdstBase++; + } + else if (xchar < 0) + { + xchar += PPW; + pdstBase--; + } + ppci++; + } /* while nglyph-- */ + break; + case rgnPART: + { + TEXTPOS *ppos; + int nbox; + BoxPtr pbox; + RegionPtr cclip; + int xpos; /* x position of char origin */ + int i; + BoxRec clip; + int leftEdge, rightEdge; + int topEdge, bottomEdge; + int glyphRow; /* first row of glyph not wholly + clipped out */ + int glyphCol; /* leftmost visible column of glyph */ + int getWidth; /* bits to get from glyph */ + + if(!(ppos = (TEXTPOS *)ALLOCATE_LOCAL(nglyph * sizeof(TEXTPOS)))) + return; + + pdstBase = mfbScanlineNoBankSwitch(pdstBase, x, y, widthDst); + xpos = x; + xchar = xpos & PIM; + + for (i=0; imetrics.leftSideBearing; + ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing; + ppos[i].topEdge = y - pci->metrics.ascent; + ppos[i].bottomEdge = y + pci->metrics.descent; + ppos[i].pdstBase = pdstBase; + ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci); + + xpos += pci->metrics.characterWidth; + xchar += pci->metrics.characterWidth; + if (xchar > PLST) + { + xchar &= PIM; + pdstBase++; + } + else if (xchar < 0) + { + xchar += PPW; + pdstBase--; + } + } + + cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + pbox = REGION_RECTS(cclip); + nbox = REGION_NUM_RECTS(cclip); + + /* HACK ALERT + since we continue out of the loop below so often, it + is easier to increment pbox at the top than at the end. + don't try this at home. + */ + pbox--; + while(nbox--) + { + pbox++; + clip.x1 = max(bbox.x1, pbox->x1); + clip.y1 = max(bbox.y1, pbox->y1); + clip.x2 = min(bbox.x2, pbox->x2); + clip.y2 = min(bbox.y2, pbox->y2); + if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1)) + continue; + + for(i=0; i clip.x2) + rightEdge = clip.x2; + else + rightEdge = ppos[i].rightEdge; + + w = rightEdge - leftEdge; + if (w <= 0) + continue; + + /* clip the top and bottom edges */ + if (ppos[i].topEdge < clip.y1) + topEdge = clip.y1; + else + topEdge = ppos[i].topEdge; + + if (ppos[i].bottomEdge > clip.y2) + bottomEdge = clip.y2; + else + bottomEdge = ppos[i].bottomEdge; + + h = bottomEdge - topEdge; + if (h <= 0) + continue; + + glyphRow = (topEdge - y) + pci->metrics.ascent; + widthGlyph = ppos[i].widthGlyph; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + pglyph += (glyphRow * widthGlyph); + + pdst = mfbScanlineDelta(ppos[i].pdstBase, -(y-topEdge), widthDst); + + glyphCol = (leftEdge - ppos[i].xpos) - + (pci->metrics.leftSideBearing); + getWidth = w + glyphCol; + xoff = xchar + (leftEdge - ppos[i].xpos); + if (xoff > PLST) + { + xoff &= PIM; + pdst++; + } + else if (xoff < 0) + { + xoff += PPW; + pdst--; + } + + if ((xoff + w) <= PPW) + { + maskpartialbits(xoff, w, startmask); + while (h--) + { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } + else + { + maskPPWbits(xoff, w, startmask, endmask); + nFirst = PPW - xoff; + while (h--) + { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } + } /* for each glyph */ + } /* while nbox-- */ + DEALLOCATE_LOCAL(ppos); + break; + } + default: + break; + } +} diff --git a/mfb/mfbline.c b/mfb/mfbline.c new file mode 100644 index 000000000..70e61e6ed --- /dev/null +++ b/mfb/mfbline.c @@ -0,0 +1,750 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbline.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" + +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "mistruct.h" + +#include "mfb.h" +#include "maskbits.h" +#include "miline.h" + +/* single-pixel lines on a color frame buffer + + NON-SLOPED LINES + horizontal lines are always drawn left to right; we have to +move the endpoints right by one after they're swapped. + horizontal lines will be confined to a single band of a +region. the code finds that band (giving up if the lower +bound of the band is above the line we're drawing); then it +finds the first box in that band that contains part of the +line. we clip the line to subsequent boxes in that band. + vertical lines are always drawn top to bottom (y-increasing.) +this requires adding one to the y-coordinate of each endpoint +after swapping. + + SLOPED LINES + when clipping a sloped line, we bring the second point inside +the clipping box, rather than one beyond it, and then add 1 to +the length of the line before drawing it. this lets us use +the same box for finding the outcodes for both endpoints. since +the equation for clipping the second endpoint to an edge gives us +1 beyond the edge, we then have to move the point towards the +first point by one step on the major axis. + eventually, there will be a diagram here to explain what's going +on. the method uses Cohen-Sutherland outcodes to determine +outsideness, and a method similar to Pike's layers for doing the +actual clipping. + +*/ + +void +#ifdef POLYSEGMENT +mfbSegmentSS (pDrawable, pGC, nseg, pSeg) + DrawablePtr pDrawable; + GCPtr pGC; + int nseg; + register xSegment *pSeg; +#else +mfbLineSS (pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; /* number of points */ + DDXPointPtr pptInit; +#endif +{ + int nboxInit; + register int nbox; + BoxPtr pboxInit; + register BoxPtr pbox; +#ifndef POLYSEGMENT + register DDXPointPtr ppt; /* pointer to list of translated points */ +#endif + + unsigned int oc1; /* outcode of point 1 */ + unsigned int oc2; /* outcode of point 2 */ + + PixelType *addrlBase; /* pointer to start of drawable */ + PixelType *addrl; /* address of destination pixmap */ + int nlwidth; /* width in longwords of destination pixmap */ + int xorg, yorg; /* origin of window */ + + int adx; /* abs values of dx and dy */ + int ady; + int signdx; /* sign of dx and dy */ + int signdy; + int e, e1, e2; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + + /* a bunch of temporaries */ + register int y1, y2; + register int x1, x2; + RegionPtr cclip; + int alu; + + if (!(pGC->planemask & 1)) + return; + + cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + alu = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop; + pboxInit = REGION_RECTS(cclip); + nboxInit = REGION_NUM_RECTS(cclip); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase); + + xorg = pDrawable->x; + yorg = pDrawable->y; +#ifdef POLYSEGMENT + while (nseg--) +#else + ppt = pptInit; + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; + while(--npt) +#endif + { + nbox = nboxInit; + pbox = pboxInit; + +#ifdef POLYSEGMENT + x1 = pSeg->x1 + xorg; + y1 = pSeg->y1 + yorg; + x2 = pSeg->x2 + xorg; + y2 = pSeg->y2 + yorg; + pSeg++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) + { + xorg = x1; + yorg = y1; + } + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; +#endif + + if (x1 == x2) /* vertical line */ + { + /* make the line go top to bottom of screen, keeping + endpoint semantics + */ + if (y1 > y2) + { + register int tmp; + + tmp = y2; + y2 = y1 + 1; + y1 = tmp + 1; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + y1--; +#endif + } +#ifdef POLYSEGMENT + else if (pGC->capStyle != CapNotLast) + y2++; +#endif + /* get to first band that might contain part of line */ + while ((nbox) && (pbox->y2 <= y1)) + { + pbox++; + nbox--; + } + + if (nbox) + { + /* stop when lower edge of box is beyond end of line */ + while((nbox) && (y2 >= pbox->y1)) + { + if ((x1 >= pbox->x1) && (x1 < pbox->x2)) + { + int y1t, y2t; + /* this box has part of the line in it */ + y1t = max(y1, pbox->y1); + y2t = min(y2, pbox->y2); + if (y1t != y2t) + { + mfbVertS (alu, + addrlBase, nlwidth, + x1, y1t, y2t-y1t); + } + } + nbox--; + pbox++; + } + } +#ifndef POLYSEGMENT + y2 = ppt->y + yorg; +#endif + } + else if (y1 == y2) /* horizontal line */ + { + /* force line from left to right, keeping + endpoint semantics + */ + if (x1 > x2) + { + register int tmp; + + tmp = x2; + x2 = x1 + 1; + x1 = tmp + 1; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + x1--; +#endif + } +#ifdef POLYSEGMENT + else if (pGC->capStyle != CapNotLast) + x2++; +#endif + + /* find the correct band */ + while( (nbox) && (pbox->y2 <= y1)) + { + pbox++; + nbox--; + } + + /* try to draw the line, if we haven't gone beyond it */ + if ((nbox) && (pbox->y1 <= y1)) + { + int tmp; + + /* when we leave this band, we're done */ + tmp = pbox->y1; + while((nbox) && (pbox->y1 == tmp)) + { + int x1t, x2t; + + if (pbox->x2 <= x1) + { + /* skip boxes until one might contain start point */ + nbox--; + pbox++; + continue; + } + + /* stop if left of box is beyond right of line */ + if (pbox->x1 >= x2) + { + nbox = 0; + break; + } + + x1t = max(x1, pbox->x1); + x2t = min(x2, pbox->x2); + if (x1t != x2t) + { + mfbHorzS (alu, + addrlBase, nlwidth, + x1t, y1, x2t-x1t); + } + nbox--; + pbox++; + } + } +#ifndef POLYSEGMENT + x2 = ppt->x + xorg; +#endif + } + else /* sloped line */ + { + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, + 1, 1, octant); + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + } + else + { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + SetYMajorOctant(octant); + } + + FIXUP_ERROR(e, octant, bias); + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + while(nbox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pbox); + OUTCODES(oc2, x2, y2, pbox); + if ((oc1 | oc2) == 0) + { + if (axis == X_AXIS) + len = adx; + else + len = ady; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + len++; +#endif + mfbBresS (alu, + addrlBase, nlwidth, + signdx, signdy, axis, x1, y1, + e, e1, e2, len); + break; + } + else if (oc1 & oc2) + { + pbox++; + } + else + { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int clipdx, clipdy; + int err; + + if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1, + pbox->y2-1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) + { + pbox++; + continue; + } + + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); +#ifdef POLYSEGMENT + if (clip2 != 0 || pGC->capStyle != CapNotLast) + len++; +#else + len += (clip2 != 0); +#endif + if (len) + { + /* unwind bresenham error term to first point */ + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + err = e+((clipdy*e2) + ((clipdx-clipdy)*e1)); + else + err = e+((clipdx*e2) + ((clipdy-clipdx)*e1)); + } + else + err = e; + mfbBresS + (alu, + addrlBase, nlwidth, + signdx, signdy, axis, new_x1, new_y1, + err, e1, e2, len); + } + pbox++; + } + } /* while (nbox--) */ + } /* sloped line */ + } /* while (nline--) */ + +#ifndef POLYSEGMENT + + /* paint the last point if the end style isn't CapNotLast. + (Assume that a projecting, butt, or round cap that is one + pixel wide is the same as the single pixel of the endpoint.) + */ + + if ((pGC->capStyle != CapNotLast) && + ((ppt->x + xorg != pptInit->x + pDrawable->x) || + (ppt->y + yorg != pptInit->y + pDrawable->y) || + (ppt == pptInit + 1))) + { + PixelType _mask; + + if (alu == RROP_BLACK) + _mask = rmask[x2 & PIM]; + else + _mask = mask[x2 & PIM]; + + nbox = nboxInit; + pbox = pboxInit; + while (nbox--) + { + if ((x2 >= pbox->x1) && + (y2 >= pbox->y1) && + (x2 < pbox->x2) && + (y2 < pbox->y2)) + { + addrl = mfbScanline(addrlBase, x2, y2, nlwidth); + switch(alu) + { + case RROP_BLACK: + *addrl &= _mask; + break; + case RROP_WHITE: + *addrl |= _mask; + break; + case RROP_INVERT: + *addrl ^= _mask; + break; + } + break; + } + else + pbox++; + } + } +#endif +} + +/* + * Draw dashed 1-pixel lines. + */ + +void +#ifdef POLYSEGMENT +mfbSegmentSD (pDrawable, pGC, nseg, pSeg) + DrawablePtr pDrawable; + register GCPtr pGC; + int nseg; + register xSegment *pSeg; +#else +mfbLineSD( pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + register GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; /* number of points */ + DDXPointPtr pptInit; +#endif +{ + int nboxInit; + register int nbox; + BoxPtr pboxInit; + register BoxPtr pbox; +#ifndef POLYSEGMENT + register DDXPointPtr ppt; /* pointer to list of translated points */ +#endif + + register unsigned int oc1; /* outcode of point 1 */ + register unsigned int oc2; /* outcode of point 2 */ + + PixelType *addrl; /* address of destination pixmap */ + int nlwidth; /* width in longwords of destination pixmap */ + int xorg, yorg; /* origin of window */ + + int adx; /* abs values of dx and dy */ + int ady; + int signdx; /* sign of dx and dy */ + int signdy; + int e, e1, e2; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + int x1, x2, y1, y2; + RegionPtr cclip; + int fgrop, bgrop; + unsigned char *pDash; + int dashOffset; + int numInDashList; + int dashIndex; + int isDoubleDash; + int dashIndexTmp, dashOffsetTmp; + int unclippedlen; + + if (!(pGC->planemask & 1)) + return; + + cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + fgrop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop; + pboxInit = REGION_RECTS(cclip); + nboxInit = REGION_NUM_RECTS(cclip); + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrl); + + /* compute initial dash values */ + + pDash = (unsigned char *) pGC->dash; + numInDashList = pGC->numInDashList; + isDoubleDash = (pGC->lineStyle == LineDoubleDash); + dashIndex = 0; + dashOffset = 0; + miStepDash ((int)pGC->dashOffset, &dashIndex, pDash, + numInDashList, &dashOffset); + + if (isDoubleDash) + bgrop = mfbReduceRop(pGC->alu, pGC->bgPixel); + + xorg = pDrawable->x; + yorg = pDrawable->y; +#ifdef POLYSEGMENT + while (nseg--) +#else + ppt = pptInit; + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; + while(--npt) +#endif + { + nbox = nboxInit; + pbox = pboxInit; + +#ifdef POLYSEGMENT + x1 = pSeg->x1 + xorg; + y1 = pSeg->y1 + yorg; + x2 = pSeg->x2 + xorg; + y2 = pSeg->y2 + yorg; + pSeg++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) + { + xorg = x1; + yorg = y1; + } + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; +#endif + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + unclippedlen = adx; + } + else + { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + unclippedlen = ady; + SetYMajorOctant(octant); + } + + FIXUP_ERROR(e, octant, bias); + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + while(nbox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pbox); + OUTCODES(oc2, x2, y2, pbox); + if ((oc1 | oc2) == 0) + { +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + unclippedlen++; + dashIndexTmp = dashIndex; + dashOffsetTmp = dashOffset; + mfbBresD (fgrop, bgrop, + &dashIndexTmp, pDash, numInDashList, + &dashOffsetTmp, isDoubleDash, + addrl, nlwidth, + signdx, signdy, axis, x1, y1, + e, e1, e2, unclippedlen); + break; +#else + mfbBresD (fgrop, bgrop, + &dashIndex, pDash, numInDashList, + &dashOffset, isDoubleDash, + addrl, nlwidth, + signdx, signdy, axis, x1, y1, + e, e1, e2, unclippedlen); + goto dontStep; +#endif + } + else if (oc1 & oc2) + { + pbox++; + } + else /* have to clip */ + { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int clipdx, clipdy; + int err; + + if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1, pbox->y2-1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) + { + pbox++; + continue; + } + dashIndexTmp = dashIndex; + dashOffsetTmp = dashOffset; + if (clip1) + { + int dlen; + + if (axis == X_AXIS) + dlen = abs(new_x1 - x1); + else + dlen = abs(new_y1 - y1); + miStepDash (dlen, &dashIndexTmp, pDash, + numInDashList, &dashOffsetTmp); + } + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); +#ifdef POLYSEGMENT + if (clip2 != 0 || pGC->capStyle != CapNotLast) + len++; +#else + len += (clip2 != 0); +#endif + if (len) + { + /* unwind bresenham error term to first point */ + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + err = e+((clipdy*e2) + ((clipdx-clipdy)*e1)); + else + err = e+((clipdx*e2) + ((clipdy-clipdx)*e1)); + } + else + err = e; + mfbBresD (fgrop, bgrop, + &dashIndexTmp, pDash, numInDashList, + &dashOffsetTmp, isDoubleDash, + addrl, nlwidth, + signdx, signdy, axis, new_x1, new_y1, + err, e1, e2, len); + } + pbox++; + } + } /* while (nbox--) */ +#ifndef POLYSEGMENT + /* + * walk the dash list around to the next line + */ + miStepDash (unclippedlen, &dashIndex, pDash, + numInDashList, &dashOffset); +dontStep: ; +#endif + } /* while (nline--) */ + +#ifndef POLYSEGMENT + /* paint the last point if the end style isn't CapNotLast. + (Assume that a projecting, butt, or round cap that is one + pixel wide is the same as the single pixel of the endpoint.) + */ + + if ((pGC->capStyle != CapNotLast) && + ((dashIndex & 1) == 0 || isDoubleDash) && + ((ppt->x + xorg != pptInit->x + pDrawable->x) || + (ppt->y + yorg != pptInit->y + pDrawable->y) || + (ppt == pptInit + 1))) + { + nbox = nboxInit; + pbox = pboxInit; + while (nbox--) + { + if ((x2 >= pbox->x1) && + (y2 >= pbox->y1) && + (x2 < pbox->x2) && + (y2 < pbox->y2)) + { + unsigned long _mask; + int rop; + + rop = fgrop; + if (dashIndex & 1) + rop = bgrop; + if (rop == RROP_BLACK) + _mask = rmask[x2 & PIM]; + else + _mask = mask[x2 & PIM]; + addrl = mfbScanline(addrl, x2, y2, nlwidth); + if (rop == RROP_BLACK) + *addrl &= _mask; + else if (rop == RROP_WHITE) + *addrl |= _mask; + else + *addrl ^= _mask; + break; + } + else + pbox++; + } + } +#endif +} diff --git a/mfb/mfbmisc.c b/mfb/mfbmisc.c new file mode 100644 index 000000000..67cbf6fc6 --- /dev/null +++ b/mfb/mfbmisc.c @@ -0,0 +1,91 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbmisc.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" +#include "misc.h" +#include "cursor.h" +#include "scrnintstr.h" + +#include "mfb.h" + +/*ARGSUSED*/ +void +mfbQueryBestSize(class, pwidth, pheight, pScreen) +int class; +unsigned short *pwidth; +unsigned short *pheight; +ScreenPtr pScreen; +{ + unsigned width, test; + + switch(class) + { + case CursorShape: + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + case TileShape: + case StippleShape: + width = *pwidth; + if (!width) break; + /* Return the closes power of two not less than what they gave me */ + 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; + } +} + diff --git a/mfb/mfbpixmap.c b/mfb/mfbpixmap.c new file mode 100644 index 000000000..b6ff40292 --- /dev/null +++ b/mfb/mfbpixmap.c @@ -0,0 +1,294 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbpixmap.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +/* pixmap management + written by drewry, september 1986 + + on a monchrome device, a pixmap is a bitmap. +*/ + +#include "Xmd.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "maskbits.h" + +#include "mfb.h" +#include "mi.h" + +#include "servermd.h" + +#ifndef LOWMEMFTPT + +PixmapPtr +mfbCreatePixmap (pScreen, width, height, depth) + ScreenPtr pScreen; + int width; + int height; + int depth; +{ + PixmapPtr pPixmap; + int datasize; + int paddedWidth; + + if (depth != 1) + return NullPixmap; + paddedWidth = BitmapBytePad(width); + datasize = height * paddedWidth; + pPixmap = AllocatePixmap(pScreen, datasize); + if (!pPixmap) + return NullPixmap; + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = depth; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = paddedWidth; + pPixmap->refcnt = 1; +#ifdef PIXPRIV + pPixmap->devPrivate.ptr = datasize ? + (pointer)((char *)pPixmap + pScreen->totalPixmapSize) : NULL; +#else + pPixmap->devPrivate.ptr = (pointer)(pPixmap + 1); +#endif + return pPixmap; +} + +#endif /* ifndef LOWMEMFTPT */ + +Bool +mfbDestroyPixmap(pPixmap) + PixmapPtr pPixmap; +{ + if(--pPixmap->refcnt) + return TRUE; + xfree(pPixmap); + return TRUE; +} + + +PixmapPtr +mfbCopyPixmap(pSrc) + register PixmapPtr pSrc; +{ + register PixmapPtr pDst; + int size; + ScreenPtr pScreen; + + size = pSrc->drawable.height * pSrc->devKind; + pScreen = pSrc->drawable.pScreen; + pDst = (*pScreen->CreatePixmap) (pScreen, pSrc->drawable.width, + pSrc->drawable.height, pSrc->drawable.depth); + if (!pDst) + return NullPixmap; + memmove((char *)pDst->devPrivate.ptr, (char *)pSrc->devPrivate.ptr, size); + return pDst; +} + + +/* replicates a pattern to be a full 32 bits wide. + relies on the fact that each scnaline is longword padded. + doesn't do anything if pixmap is not a factor of 32 wide. + changes width field of pixmap if successful, so that the fast + XRotatePixmap code gets used if we rotate the pixmap later. + + calculate number of times to repeat + for each scanline of pattern + zero out area to be filled with replicate + left shift and or in original as many times as needed +*/ +void +mfbPadPixmap(pPixmap) + PixmapPtr pPixmap; +{ + register int width = pPixmap->drawable.width; + register int h; + register PixelType mask; + register PixelType *p; + register PixelType bits; /* real pattern bits */ + register int i; + int rep; /* repeat count for pattern */ + + if (width >= PPW) + return; + + rep = PPW/width; + if (rep*width != PPW) + return; + + mask = endtab[width]; + + p = (PixelType *)(pPixmap->devPrivate.ptr); + for (h=0; h < pPixmap->drawable.height; h++) + { + *p &= mask; + bits = *p; + for(i=1; idrawable.width = PPW; +} + +/* Rotates pixmap pPix by w pixels to the right on the screen. Assumes that + * words are PPW bits wide, and that the least significant bit appears on the + * left. + */ +void +mfbXRotatePixmap(pPix, rw) + PixmapPtr pPix; + register int rw; +{ + register PixelType *pw, *pwFinal; + register PixelType t; + + if (pPix == NullPixmap) + return; + + pw = (PixelType *)pPix->devPrivate.ptr; + rw %= (int)pPix->drawable.width; + if (rw < 0) + rw += (int)pPix->drawable.width; + if(pPix->drawable.width == PPW) + { + pwFinal = pw + pPix->drawable.height; + while(pw < pwFinal) + { + t = *pw; + *pw++ = SCRRIGHT(t, rw) | + (SCRLEFT(t, (PPW-rw)) & endtab[rw]); + } + } + else + { + /* We no longer do this. Validate doesn't try to rotate odd-size + * tiles or stipples. mfbUnnaturalFS works directly off + * the unrotate tile/stipple in the GC + */ + ErrorF("X internal error: trying to rotate odd-sized pixmap.\n"); + } + +} + +/* Rotates pixmap pPix by h lines. Assumes that h is always less than + pPix->height + works on any width. + */ +void +mfbYRotatePixmap(pPix, rh) + register PixmapPtr pPix; + int rh; +{ + int nbyDown; /* bytes to move down to row 0; also offset of + row rh */ + int nbyUp; /* bytes to move up to line rh; also + offset of first line moved down to 0 */ + char *pbase; + char *ptmp; + int height; + + if (pPix == NullPixmap) + return; + height = (int) pPix->drawable.height; + rh %= height; + if (rh < 0) + rh += height; + + pbase = (char *)pPix->devPrivate.ptr; + + nbyDown = rh * pPix->devKind; + nbyUp = (pPix->devKind * height) - nbyDown; + if(!(ptmp = (char *)ALLOCATE_LOCAL(nbyUp))) + return; + + memmove(ptmp, pbase, nbyUp); /* save the low rows */ + memmove(pbase, pbase+nbyUp, nbyDown); /* slide the top rows down */ + memmove(pbase+nbyDown, ptmp, nbyUp); /* move lower rows up to row rh */ + DEALLOCATE_LOCAL(ptmp); +} + +void +mfbCopyRotatePixmap(psrcPix, ppdstPix, xrot, yrot) + register PixmapPtr psrcPix, *ppdstPix; + int xrot, yrot; +{ + register PixmapPtr pdstPix; + + if ((pdstPix = *ppdstPix) && + (pdstPix->devKind == psrcPix->devKind) && + (pdstPix->drawable.height == psrcPix->drawable.height)) + { + memmove((char *)pdstPix->devPrivate.ptr, + (char *)psrcPix->devPrivate.ptr, + psrcPix->drawable.height * psrcPix->devKind); + pdstPix->drawable.width = psrcPix->drawable.width; + pdstPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + else + { + if (pdstPix) + /* FIX XBUG 6168 */ + (*pdstPix->drawable.pScreen->DestroyPixmap)(pdstPix); + *ppdstPix = pdstPix = mfbCopyPixmap(psrcPix); + if (!pdstPix) + return; + } + mfbPadPixmap(pdstPix); + if (xrot) + mfbXRotatePixmap(pdstPix, xrot); + if (yrot) + mfbYRotatePixmap(pdstPix, yrot); +} diff --git a/mfb/mfbply1rct.c b/mfb/mfbply1rct.c new file mode 100644 index 000000000..5cb81df53 --- /dev/null +++ b/mfb/mfbply1rct.c @@ -0,0 +1,255 @@ +/* + * $Xorg: mfbply1rct.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +#include "X.h" + +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "mistruct.h" + +#include "mfb.h" +#include "maskbits.h" + +#if defined(mips) || defined(sparc) +#define GetHighWord(x) (((int) (x)) >> 16) +#else +#define GetHighWord(x) (((int) (x)) / 65536) +#endif + +#if IMAGE_BYTE_ORDER == MSBFirst +#define intToCoord(i,x,y) (((x) = GetHighWord(i)), ((y) = (int) ((short) (i)))) +#define coordToInt(x,y) (((x) << 16) | (y)) +#define intToX(i) (GetHighWord(i)) +#define intToY(i) ((int) ((short) i)) +#else +#define intToCoord(i,x,y) (((x) = (int) ((short) (i))), ((y) = GetHighWord(i))) +#define coordToInt(x,y) (((y) << 16) | (x)) +#define intToX(i) ((int) ((short) (i))) +#define intToY(i) (GetHighWord(i)) +#endif + +void +MFBFILLPOLY1RECT (pDrawable, pGC, shape, mode, count, ptsIn) + DrawablePtr pDrawable; + GCPtr pGC; + int count; + DDXPointPtr ptsIn; +{ + mfbPrivGCPtr devPriv; + int nlwidth; + PixelType *addrl, *addr; + int maxy; + int origin; + register int vertex1, vertex2; + int c; + BoxPtr extents; + int clip; + int y; + int *vertex1p, *vertex2p; + int *endp; + int x1, x2; + int dx1, dx2; + int dy1, dy2; + int e1, e2; + int step1, step2; + int sign1, sign2; + int h; + int l, r; + PixelType mask, bits = ~((PixelType)0); + int nmiddle; + + devPriv = (mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr); + if (mode == CoordModePrevious || shape != Convex || + REGION_NUM_RECTS(devPriv->pCompositeClip) != 1) + { + miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn); + return; + } + origin = *((int *) &pDrawable->x); + vertex2 = origin - ((origin & 0x8000) << 1); + extents = &devPriv->pCompositeClip->extents; + vertex1 = *((int *) &extents->x1) - vertex2; + vertex2 = *((int *) &extents->x2) - vertex2 - 0x00010001; + clip = 0; + y = 32767; + maxy = 0; + vertex2p = (int *) ptsIn; + endp = vertex2p + count; + while (count--) + { + c = *vertex2p; + clip |= (c - vertex1) | (vertex2 - c); + c = intToY(c); + if (c < y) + { + y = c; + vertex1p = vertex2p; + } + vertex2p++; + if (c > maxy) + maxy = c; + } + if (y == maxy) + return; + + if (clip & 0x80008000) + { + miFillPolygon (pDrawable, pGC, shape, mode, vertex2p - (int *) ptsIn, ptsIn); + return; + } + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrl); + addrl = mfbScanlineDelta(addrl, y + pDrawable->y, nlwidth); + origin = intToX(origin); + vertex2p = vertex1p; + vertex2 = vertex1 = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; +#define Setup(c,x,vertex,dx,dy,e,sign,step) {\ + x = intToX(vertex); \ + if (dy = intToY(c) - y) { \ + dx = intToX(c) - x; \ + step = 0; \ + if (dx >= 0) \ + { \ + e = 0; \ + sign = 1; \ + if (dx >= dy) {\ + step = dx / dy; \ + dx = dx % dy; \ + } \ + } \ + else \ + { \ + e = 1 - dy; \ + sign = -1; \ + dx = -dx; \ + if (dx >= dy) { \ + step = - (dx / dy); \ + dx = dx % dy; \ + } \ + } \ + } \ + x += origin; \ + vertex = c; \ +} + +#define Step(x,dx,dy,e,sign,step) {\ + x += step; \ + if ((e += dx) > 0) \ + { \ + x += sign; \ + e -= dy; \ + } \ +} + for (;;) + { + if (y == intToY(vertex1)) + { + do + { + if (vertex1p == (int *) ptsIn) + vertex1p = endp; + c = *--vertex1p; + Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1) + } while (y >= intToY(vertex1)); + h = dy1; + } + else + { + Step(x1,dx1,dy1,e1,sign1,step1) + h = intToY(vertex1) - y; + } + if (y == intToY(vertex2)) + { + do + { + c = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2) + } while (y >= intToY(vertex2)); + if (dy2 < h) + h = dy2; + } + else + { + Step(x2,dx2,dy2,e2,sign2,step2) + if ((c = (intToY(vertex2) - y)) < h) + h = c; + } + /* fill spans for this segment */ + y += h; + for (;;) + { + l = x1; + r = x2; + nmiddle = x2 - x1; + if (nmiddle < 0) + { + nmiddle = -nmiddle; + l = x2; + r = x1; + } + c = l & PIM; + l -= c; + l = l >> PWSH; + addr = addrl + l; + if (c + nmiddle < PPW) + { + mask = SCRRIGHT (bits,c) ^ SCRRIGHT (bits,c+nmiddle); + *addr OPEQ mask; + } + else + { + if (c) + { + mask = SCRRIGHT(bits, c); + *addr OPEQ mask; + nmiddle += c - PPW; + addr++; + } + nmiddle >>= PWSH; + Duff (nmiddle, *addr++ EQWHOLEWORD) + if (mask = ~SCRRIGHT(bits, r & PIM)) + *addr OPEQ mask; + } + if (!--h) + break; + mfbScanlineInc(addrl, nlwidth); + Step(x1,dx1,dy1,e1,sign1,step1) + Step(x2,dx2,dy2,e2,sign2,step2) + } + if (y == maxy) + break; + mfbScanlineInc(addrl, nlwidth); + } +} diff --git a/mfb/mfbplygblt.c b/mfb/mfbplygblt.c new file mode 100644 index 000000000..f8931b5c2 --- /dev/null +++ b/mfb/mfbplygblt.c @@ -0,0 +1,387 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbplygblt.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "mfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "regionstr.h" +#include "maskbits.h" +#include "miscstruct.h" + +/* + we should eventually special-case fixed-width fonts, although +its more important for ImageText, which is meant for terminal +emulators. + + this works for fonts with glyphs <= 32 bits wide. + + the clipping calculations are done for worst-case fonts. +we make no assumptions about the heights, widths, or bearings +of the glyphs. if we knew that the glyphs are all the same height, +we could clip the tops and bottoms per clipping box, rather +than per character per clipping box. if we knew that the glyphs' +left and right bearings were well-behaved, we could clip a single +character at the start, output until the last unclipped +character, and then clip the last one. this is all straightforward +to determine based on max-bounds and min-bounds from the font. + there is some inefficiency introduced in the per-character +clipping to make what's going on clearer. + + (it is possible, for example, for a font to be defined in which the +next-to-last character in a font would be clipped out, but the last +one wouldn't. the code below deals with this.) + + PolyText looks at the fg color and the rasterop; mfbValidateGC +swaps in the right routine after looking at the reduced ratserop +in the private field of the GC. + + the register allocations are provisional; in particualr startmask and +endmask might not be the right things. pglyph, xoff, pdst, and tmpSrc +are fairly obvious, though. + + to avoid source proliferation, this file is compiled +three times: + MFBPOLYGLYPHBLT OPEQ + mfbPolyGlyphBltWhite |= + mfbPolyGlyphBltBlack &=~ + mfbPolyGlyphBltInvert ^= +*/ + +void +MFBPOLYGLYPHBLT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs (unused in R5) */ +{ + ExtentInfoRec info; /* used by QueryGlyphExtents() */ + BoxRec bbox; /* string's bounding box */ + + CharInfoPtr pci; + int xorg, yorg; /* origin of drawable in bitmap */ + int widthDst; /* width of dst in longwords */ + + /* these keep track of the character origin */ + PixelType *pdstBase; + /* points to longword with character origin */ + int xchar; /* xorigin of char (mod 32) */ + + /* these are used for placing the glyph */ + register int xoff; /* x offset of left edge of glyph (mod 32) */ + register PixelType *pdst; + /* pointer to current longword in dst */ + + int w; /* width of glyph in bits */ + int h; /* height of glyph */ + int widthGlyph; /* width of glyph, in bytes */ + register unsigned char *pglyph; + /* pointer to current row of glyph */ + + /* used for putting down glyph */ + register PixelType tmpSrc; + /* for getting bits from glyph */ + register PixelType startmask; + register PixelType endmask; + register int nFirst;/* bits of glyph in current longword */ + + if (!(pGC->planemask & 1)) + return; + + xorg = pDrawable->x; + yorg = pDrawable->y; + mfbGetPixelWidthAndPointer(pDrawable, widthDst, pdstBase); + + x += xorg; + y += yorg; + + QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info); + bbox.x1 = x + info.overallLeft; + bbox.x2 = x + info.overallRight; + bbox.y1 = y - info.overallAscent; + bbox.y2 = y + info.overallDescent; + + switch (RECT_IN_REGION(pGC->pScreen, + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, &bbox)) + { + case rgnOUT: + break; + case rgnIN: + pdstBase = mfbScanlineNoBankSwitch(pdstBase, x, y, widthDst); + xchar = x & PIM; + + while(nglyph--) + { + pci = *ppci; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + h = pci->metrics.ascent + pci->metrics.descent; + widthGlyph = GLYPHWIDTHBYTESPADDED(pci); + + /* start at top scanline of glyph */ + pdst = mfbScanlineDelta(pdstBase, -pci->metrics.ascent, widthDst); + + /* find correct word in scanline and x offset within it + for left edge of glyph + */ + xoff = xchar + pci->metrics.leftSideBearing; + if (xoff > PLST) + { + pdst++; + xoff &= PIM; + } + else if (xoff < 0) + { + xoff += PPW; + pdst--; + } + + if ((xoff + w) <= PPW) + { + /* glyph all in one longword */ + maskpartialbits(xoff, w, startmask); + while (h--) + { + getleftbits(pglyph, w, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } + else + { + /* glyph crosses longword boundary */ + maskPPWbits(xoff, w, startmask, endmask); + nFirst = PPW - xoff; + while (h--) + { + getleftbits(pglyph, w, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } /* glyph crosses longwords boundary */ + + /* update character origin */ + x += pci->metrics.characterWidth; + xchar += pci->metrics.characterWidth; + if (xchar > PLST) + { + xchar -= PPW; + pdstBase++; + } + else if (xchar < 0) + { + xchar += PPW; + pdstBase--; + } + ppci++; + } /* while nglyph-- */ + break; + case rgnPART: + { + TEXTPOS *ppos; + RegionPtr cclip; + int nbox; + BoxPtr pbox; + int xpos; /* x position of char origin */ + int i; + BoxRec clip; + int leftEdge, rightEdge; + int topEdge, bottomEdge; + int glyphRow; /* first row of glyph not wholly + clipped out */ + int glyphCol; /* leftmost visible column of glyph */ + int getWidth; /* bits to get from glyph */ + + if(!(ppos = (TEXTPOS *)ALLOCATE_LOCAL(nglyph * sizeof(TEXTPOS)))) + return; + + pdstBase = mfbScanlineNoBankSwitch(pdstBase, x, y, widthDst); + xpos = x; + xchar = xpos & PIM; + + for (i=0; imetrics.leftSideBearing; + ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing; + ppos[i].topEdge = y - pci->metrics.ascent; + ppos[i].bottomEdge = y + pci->metrics.descent; + ppos[i].pdstBase = pdstBase; + ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci); + + xpos += pci->metrics.characterWidth; + xchar += pci->metrics.characterWidth; + if (xchar > PLST) + { + xchar &= PIM; + pdstBase++; + } + else if (xchar < 0) + { + xchar += PPW; + pdstBase--; + } + } + + cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + pbox = REGION_RECTS(cclip); + nbox = REGION_NUM_RECTS(cclip); + + for (; --nbox >= 0; pbox++) + { + clip.x1 = max(bbox.x1, pbox->x1); + clip.y1 = max(bbox.y1, pbox->y1); + clip.x2 = min(bbox.x2, pbox->x2); + clip.y2 = min(bbox.y2, pbox->y2); + if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1)) + continue; + + for(i=0; i clip.x2) + rightEdge = clip.x2; + else + rightEdge = ppos[i].rightEdge; + + w = rightEdge - leftEdge; + if (w <= 0) + continue; + + /* clip the top and bottom edges */ + if (ppos[i].topEdge < clip.y1) + topEdge = clip.y1; + else + topEdge = ppos[i].topEdge; + + if (ppos[i].bottomEdge > clip.y2) + bottomEdge = clip.y2; + else + bottomEdge = ppos[i].bottomEdge; + + h = bottomEdge - topEdge; + if (h <= 0) + continue; + + glyphRow = (topEdge - y) + pci->metrics.ascent; + widthGlyph = ppos[i].widthGlyph; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + pglyph += (glyphRow * widthGlyph); + + pdst = mfbScanlineDelta(ppos[i].pdstBase, -(y-topEdge), widthDst); + + glyphCol = (leftEdge - ppos[i].xpos) - + (pci->metrics.leftSideBearing); + getWidth = w + glyphCol; + xoff = xchar + (leftEdge - ppos[i].xpos); + if (xoff > PLST) + { + xoff &= PIM; + pdst++; + } + else if (xoff < 0) + { + xoff += PPW; + pdst--; + } + + if ((xoff + w) <= PPW) + { + maskpartialbits(xoff, w, startmask); + while (h--) + { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } + else + { + maskPPWbits(xoff, w, startmask, endmask); + nFirst = PPW - xoff; + while (h--) + { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + mfbScanlineInc(pdst, widthDst); + } + } + } /* for each glyph */ + } /* while nbox-- */ + DEALLOCATE_LOCAL(ppos); + break; + } + default: + break; + } +} diff --git a/mfb/mfbpntarea.c b/mfb/mfbpntarea.c new file mode 100644 index 000000000..6b45d3f48 --- /dev/null +++ b/mfb/mfbpntarea.c @@ -0,0 +1,296 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbpntarea.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" + +#include "windowstr.h" +#include "regionstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "mfb.h" +#include "maskbits.h" + +/* + the solid fillers are called for rectangles and window backgrounds. + the boxes are already translated. + maybe this should always take a pixmap instead of a drawable? + + NOTE: + iy = ++iy < tileHeight ? iy : 0 +is equivalent to iy%= tileheight, and saves a division. +*/ + +/* + MFBSOLIDFILLAREA OPEQ EQWHOLEOWRD + mfbSolidWhiteArea |= = ~0 + mfbSolidBlackArea &=~ = 0 + mfbSolidInvertArea ^= ^= ~0 + +EQWHOLEWORD is used to write whole longwords. it could use OPEQ, +but *p++ |= ~0 on at least two compilers generates much +worse code than *p++ = ~0. similarly for *p++ &= ~~0 +and *p++ = 0. + +*/ + +/*ARGSUSED*/ +void +MFBSOLIDFILLAREA(pDraw, nbox, pbox, alu, nop) + DrawablePtr pDraw; + int nbox; + BoxPtr pbox; + int alu; + PixmapPtr nop; +{ + int nlwidth; /* width in longwords of the drawable */ + int w; /* width of current box */ + register int h; /* height of current box */ + register PixelType *p; /* pointer to bits we're writing */ + register int nlw; /* loop version of nlwMiddle */ + register PixelType startmask; + register PixelType endmask;/* masks for reggedy bits at either end of line */ + register int nlwExtra; + /* to get from right of box to left of next span */ + int nlwMiddle; /* number of longwords between sides of boxes */ + PixelType *pbits; /* pointer to start of drawable */ + + mfbGetPixelWidthAndPointer(pDraw, nlwidth, pbits); + + while (nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + p = mfbScanline(pbits, pbox->x1, pbox->y1, nlwidth); + + if ( ((pbox->x1 & PIM) + w) < PPW) + { + maskpartialbits(pbox->x1, w, startmask); + nlwExtra = nlwidth; + Duff(h, *p OPEQ startmask; mfbScanlineInc(p, nlwExtra)); + } + else + { + maskbits(pbox->x1, w, startmask, endmask, nlwMiddle); + nlwExtra = nlwidth - nlwMiddle; + + if (startmask && endmask) + { + nlwExtra -= 1; + while (h--) + { + nlw = nlwMiddle; + *p OPEQ startmask; + p++; + Duff(nlw, *p++ EQWHOLEWORD); + *p OPEQ endmask; + mfbScanlineInc(p, nlwExtra); + } + } + else if (startmask && !endmask) + { + nlwExtra -= 1; + while (h--) + { + nlw = nlwMiddle; + *p OPEQ startmask; + p++; + Duff(nlw, *p++ EQWHOLEWORD); + mfbScanlineInc(p, nlwExtra); + } + } + else if (!startmask && endmask) + { + while (h--) + { + nlw = nlwMiddle; + Duff(nlw, *p++ EQWHOLEWORD); + *p OPEQ endmask; + mfbScanlineInc(p, nlwExtra); + } + } + else /* no ragged bits at either end */ + { + while (h--) + { + nlw = nlwMiddle; + Duff(nlw, *p++ EQWHOLEWORD); + mfbScanlineInc(p, nlwExtra); + } + } + } + pbox++; + } +} + + + +/* stipple a list of boxes + +you can use the reduced rasterop for stipples. if rrop is +black, AND the destination with (not stipple pattern). if rrop is +white OR the destination with the stipple pattern. if rrop is invert, +XOR the destination with the stipple pattern. + + MFBSTIPPLEFILLAREA OPEQ + mfbStippleWhiteArea |= + mfbStippleBlackArea &=~ + mfbStippleInveryArea ^= +*/ + +/*ARGSUSED*/ +void +MFBSTIPPLEFILLAREA(pDraw, nbox, pbox, alu, pstipple) + DrawablePtr pDraw; + int nbox; + BoxPtr pbox; + int alu; + PixmapPtr pstipple; +{ + register PixelType *psrc; + /* pointer to bits in tile, if needed */ + int tileHeight; /* height of the tile */ + register PixelType srcpix; + + int nlwidth; /* width in longwords of the drawable */ + int w; /* width of current box */ + register int nlw; /* loop version of nlwMiddle */ + register PixelType *p; /* pointer to bits we're writing */ + register int h; /* height of current box */ + PixelType startmask; + PixelType endmask; /* masks for reggedy bits at either end of line */ + int nlwMiddle; /* number of longwords between sides of boxes */ + int nlwExtra; /* to get from right of box to left of next span */ + register int iy; /* index of current scanline in tile */ + PixelType *pbits; /* pointer to start of drawable */ + + mfbGetPixelWidthAndPointer(pDraw, nlwidth, pbits); + + tileHeight = pstipple->drawable.height; + psrc = (PixelType *)(pstipple->devPrivate.ptr); + + while (nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + iy = pbox->y1 % tileHeight; + p = mfbScanline(pbits, pbox->x1, pbox->y1, nlwidth); + + if ( ((pbox->x1 & PIM) + w) < PPW) + { + maskpartialbits(pbox->x1, w, startmask); + nlwExtra = nlwidth; + while (h--) + { + srcpix = psrc[iy]; + iy = ++iy < tileHeight ? iy : 0; + *p OPEQ (srcpix & startmask); + mfbScanlineInc(p, nlwExtra); + } + } + else + { + maskbits(pbox->x1, w, startmask, endmask, nlwMiddle); + nlwExtra = nlwidth - nlwMiddle; + + if (startmask && endmask) + { + nlwExtra -= 1; + while (h--) + { + srcpix = psrc[iy]; + iy = ++iy < tileHeight ? iy : 0; + nlw = nlwMiddle; + *p OPEQ (srcpix & startmask); + p++; + Duff (nlw, *p++ OPEQ srcpix); + *p OPEQ (srcpix & endmask); + mfbScanlineInc(p, nlwExtra); + } + } + else if (startmask && !endmask) + { + nlwExtra -= 1; + while (h--) + { + srcpix = psrc[iy]; + iy = ++iy < tileHeight ? iy : 0; + nlw = nlwMiddle; + *p OPEQ (srcpix & startmask); + p++; + Duff(nlw, *p++ OPEQ srcpix); + mfbScanlineInc(p, nlwExtra); + } + } + else if (!startmask && endmask) + { + while (h--) + { + srcpix = psrc[iy]; + iy = ++iy < tileHeight ? iy : 0; + nlw = nlwMiddle; + Duff(nlw, *p++ OPEQ srcpix); + *p OPEQ (srcpix & endmask); + mfbScanlineInc(p, nlwExtra); + } + } + else /* no ragged bits at either end */ + { + while (h--) + { + srcpix = psrc[iy]; + iy = ++iy < tileHeight ? iy : 0; + nlw = nlwMiddle; + Duff(nlw, *p++ OPEQ srcpix); + mfbScanlineInc(p, nlwExtra); + } + } + } + pbox++; + } +} diff --git a/mfb/mfbpntwin.c b/mfb/mfbpntwin.c new file mode 100644 index 000000000..97db3bf79 --- /dev/null +++ b/mfb/mfbpntwin.c @@ -0,0 +1,123 @@ +/* $Xorg: mfbpntwin.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "X.h" + +#include "windowstr.h" +#include "regionstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "mfb.h" +#include "maskbits.h" +#include "mi.h" + +void +mfbPaintWindow(pWin, pRegion, what) + WindowPtr pWin; + RegionPtr pRegion; + int what; +{ + register mfbPrivWin *pPrivWin; + + pPrivWin = (mfbPrivWin *)(pWin->devPrivates[mfbWindowPrivateIndex].ptr); + + switch (what) { + case PW_BACKGROUND: + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + do { + pWin = pWin->parent; + } while (pWin->backgroundState == ParentRelative); + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, + what); + return; + case BackgroundPixmap: + if (pPrivWin->fastBackground) + { + mfbTileAreaPPWCopy((DrawablePtr)pWin, REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), GXcopy, + pPrivWin->pRotatedBackground); + return; + } + break; + case BackgroundPixel: + if (pWin->background.pixel & 1) + mfbSolidWhiteArea((DrawablePtr)pWin, REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), GXset, NullPixmap); + else + mfbSolidBlackArea((DrawablePtr)pWin, REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), GXclear, NullPixmap); + return; + } + break; + case PW_BORDER: + if (pWin->borderIsPixel) + { + if (pWin->border.pixel & 1) + mfbSolidWhiteArea((DrawablePtr)pWin, REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), GXset, NullPixmap); + else + mfbSolidBlackArea((DrawablePtr)pWin, REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), GXclear, NullPixmap); + return; + } + else if (pPrivWin->fastBorder) + { + mfbTileAreaPPWCopy((DrawablePtr)pWin, REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), GXcopy, + pPrivWin->pRotatedBorder); + return; + } + break; + } + miPaintWindow(pWin, pRegion, what); +} diff --git a/mfb/mfbpolypnt.c b/mfb/mfbpolypnt.c new file mode 100644 index 000000000..8b6efab98 --- /dev/null +++ b/mfb/mfbpolypnt.c @@ -0,0 +1,140 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbpolypnt.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +#include "X.h" +#include "Xprotostr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "miscstruct.h" +#include "regionstr.h" +#include "scrnintstr.h" + +#include "mfb.h" +#include "maskbits.h" + +void +mfbPolyPoint(pDrawable, pGC, mode, npt, pptInit) + register DrawablePtr pDrawable; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; + xPoint *pptInit; +{ + + register BoxPtr pbox; + register int nbox; + + register PixelType *addrl; + int nlwidth; + + int nptTmp; + register xPoint *ppt; + + register int x; + register int y; + register int rop; + mfbPrivGC *pGCPriv; + + if (!(pGC->planemask & 1)) + return; + + pGCPriv = (mfbPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr; + rop = pGCPriv->rop; + + mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrl); + + if ((mode == CoordModePrevious) && (npt > 1)) + { + for (ppt = pptInit + 1, nptTmp = npt - 1; --nptTmp >= 0; ppt++) + { + ppt->x += (ppt-1)->x; + ppt->y += (ppt-1)->y; + } + } + + nbox = REGION_NUM_RECTS(pGCPriv->pCompositeClip); + pbox = REGION_RECTS(pGCPriv->pCompositeClip); + for (; --nbox >= 0; pbox++) + { + if (rop == RROP_BLACK) + { + for (ppt = pptInit, nptTmp = npt; --nptTmp >= 0; ppt++) + { + x = ppt->x + pDrawable->x; + y = ppt->y + pDrawable->y; + if ((x >= pbox->x1) && (x < pbox->x2) && + (y >= pbox->y1) && (y < pbox->y2)) + *mfbScanline(addrl, x, y, nlwidth) &= rmask[x & PIM]; + } + } + else if (rop == RROP_WHITE) + { + for (ppt = pptInit, nptTmp = npt; --nptTmp >= 0; ppt++) + { + x = ppt->x + pDrawable->x; + y = ppt->y + pDrawable->y; + if ((x >= pbox->x1) && (x < pbox->x2) && + (y >= pbox->y1) && (y < pbox->y2)) + *mfbScanline(addrl, x, y, nlwidth) |= mask[x & PIM]; + } + } + else if (rop == RROP_INVERT) + { + for (ppt = pptInit, nptTmp = npt; --nptTmp >= 0; ppt++) + { + x = ppt->x + pDrawable->x; + y = ppt->y + pDrawable->y; + if ((x >= pbox->x1) && (x < pbox->x2) && + (y >= pbox->y1) && (y < pbox->y2)) + *mfbScanline(addrl, x, y, nlwidth) ^= mask[x & PIM]; + } + } + } +} diff --git a/mfb/mfbpushpxl.c b/mfb/mfbpushpxl.c new file mode 100644 index 000000000..12b94f6b1 --- /dev/null +++ b/mfb/mfbpushpxl.c @@ -0,0 +1,278 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbpushpxl.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +#include "X.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "miscstruct.h" +#include "maskbits.h" +#include "regionstr.h" +#include "mfb.h" + +/* mfbSolidPP is courtesy of xhacks@csri.toronto.edu + + For fillStyle==FillSolid, a monochrome PushPixels can be reduced to + a ROP in the following way: (Note that the ROP is the same as the + result of ROP(src=0x3,dst=0x5)) + + src=0011 0000 0011 + dst=0101 0101 0101 + rop fg=0 fg=1 + GXclear 0x0 0000 0100 0100 0 + GXand 0x1 0001 0100 0101 s&d + GXandReverse 0x2 0010 0100 0110 s&~d + GXcopy 0x3 0011 0100 0111 s + GXandInverted 0x4 0100 0101 0100 ~s&d + GXnoop 0x5 0101 0101 0101 d + GXxor 0x6 0110 0101 0110 s^d + GXor 0x7 0111 0101 0111 s|d + GXnor 0x8 1000 0110 0100 ~s&~d + GXequiv 0x9 1001 0110 0101 ~s^d + GXinvert 0xa 1010 0110 0110 ~d + GXorReverse 0xb 1011 0110 0111 s|~d + GXcopyInverted 0xc 1100 0111 0100 ~s + GXorInverted 0xd 1101 0111 0101 ~s|d + GXnand 0xe 1110 0111 0110 ~s|~d + GXset 0xf 1111 0111 0111 1 + +For src=0: newRop = 0x4|(rop>>2) +For src=1: newRop = 0x4|(rop&3) +*/ + +/* mfbSolidPP -- squeegees the forground color of pGC through pBitMap + * into pDrawable. pBitMap is a stencil (dx by dy of it is used, it may + * be bigger) which is placed on the drawable at xOrg, yOrg. Where a 1 bit + * is set in the bitmap, the fill style is put onto the drawable using + * the GC's logical function. The drawable is not changed where the bitmap + * has a zero bit or outside the area covered by the stencil. + */ +void +mfbSolidPP(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg) + GCPtr pGC; + PixmapPtr pBitMap; + DrawablePtr pDrawable; + int dx, dy, xOrg, yOrg; +{ + unsigned char alu; + RegionRec rgnDst; + DDXPointPtr pptSrc; + BoxRec srcBox; + register DDXPointPtr ppt; + register BoxPtr pbox; + int i; + + if (!pGC->planemask & 1) return; + + /* compute the reduced rop function */ + alu = pGC->alu; + if (!(pGC->fgPixel&1)) alu >>= 2; + alu = (alu & 0x3) | 0x4; + if (alu == GXnoop) return; + + srcBox.x1 = xOrg; + srcBox.y1 = yOrg; + srcBox.x2 = xOrg + dx; + srcBox.y2 = yOrg + dy; + REGION_INIT(pGC->pScreen, &rgnDst, &srcBox, 1); + + /* clip the shape of the dst to the destination composite clip */ + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip); + + if (!REGION_NIL(&rgnDst)) + { + i = REGION_NUM_RECTS(&rgnDst); + pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(i * sizeof(DDXPointRec)); + if(pptSrc) + { + for (pbox = REGION_RECTS(&rgnDst), ppt = pptSrc; + --i >= 0; + pbox++, ppt++) + { + ppt->x = pbox->x1 - xOrg; + ppt->y = pbox->y1 - yOrg; + } + mfbDoBitblt((DrawablePtr)pBitMap, pDrawable, alu, &rgnDst, pptSrc); + DEALLOCATE_LOCAL(pptSrc); + } + } + REGION_UNINIT(pGC->pScreen, &rgnDst); +} + +#define NPT 128 + +/* mfbPushPixels -- squeegees the forground color of pGC through pBitMap + * into pDrawable. pBitMap is a stencil (dx by dy of it is used, it may + * be bigger) which is placed on the drawable at xOrg, yOrg. Where a 1 bit + * is set in the bitmap, the fill style is put onto the drawable using + * the GC's logical function. The drawable is not changed where the bitmap + * has a zero bit or outside the area covered by the stencil. + */ +void +mfbPushPixels(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg) + GCPtr pGC; + PixmapPtr pBitMap; + DrawablePtr pDrawable; + int dx, dy, xOrg, yOrg; +{ + int h, dxDivPPW, ibEnd; + PixelType *pwLineStart; + register PixelType *pw, *pwEnd; + register PixelType mask; + register int ib; + register PixelType w; + register int ipt; /* index into above arrays */ + Bool fInBox; + DDXPointRec pt[NPT]; + int width[NPT]; + + /* Now scan convert the pixmap and use the result to call fillspans in + * in the drawable with the original GC */ + ipt = 0; + dxDivPPW = dx/PPW; + for(h = 0; h < dy; h++) + { + + pw = (PixelType *) + (((char *)(pBitMap->devPrivate.ptr))+(h * pBitMap->devKind)); + pwLineStart = pw; + /* Process all words which are fully in the pixmap */ + + fInBox = FALSE; + pwEnd = pwLineStart + dxDivPPW; + while(pw < pwEnd) + { + w = *pw; + mask = endtab[1]; + for(ib = 0; ib < PPW; ib++) + { + if(w & mask) + { + if(!fInBox) + { + pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg; + pt[ipt].y = h + yOrg; + /* start new box */ + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + width[ipt] = ((pw - pwLineStart) << PWSH) + + ib + xOrg - pt[ipt].x; + if (++ipt >= NPT) + { + (*pGC->ops->FillSpans)(pDrawable, pGC, NPT, pt, + width, TRUE); + ipt = 0; + } + /* end box */ + fInBox = FALSE; + } + } + mask = SCRRIGHT(mask, 1); + } + pw++; + } + ibEnd = dx & PIM; + if(ibEnd) + { + /* Process final partial word on line */ + w = *pw; + mask = endtab[1]; + for(ib = 0; ib < ibEnd; ib++) + { + if(w & mask) + { + if(!fInBox) + { + /* start new box */ + pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg; + pt[ipt].y = h + yOrg; + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + /* end box */ + width[ipt] = ((pw - pwLineStart) << PWSH) + + ib + xOrg - pt[ipt].x; + if (++ipt >= NPT) + { + (*pGC->ops->FillSpans)(pDrawable, pGC, NPT, pt, + width, TRUE); + ipt = 0; + } + fInBox = FALSE; + } + } + mask = SCRRIGHT(mask, 1); + } + } + /* If scanline ended with last bit set, end the box */ + if(fInBox) + { + width[ipt] = dx + xOrg - pt[ipt].x; + if (++ipt >= NPT) + { + (*pGC->ops->FillSpans)(pDrawable, pGC, NPT, pt, width, TRUE); + ipt = 0; + } + } + } + /* Flush any remaining spans */ + if (ipt) + { + (*pGC->ops->FillSpans)(pDrawable, pGC, ipt, pt, width, TRUE); + } +} diff --git a/mfb/mfbscrclse.c b/mfb/mfbscrclse.c new file mode 100644 index 000000000..a93e7f07b --- /dev/null +++ b/mfb/mfbscrclse.c @@ -0,0 +1,59 @@ +/* $Xorg: mfbscrclse.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "scrnintstr.h" + +/*ARGSUSED*/ +Bool +mfbCloseScreen(index, pScreen) + register ScreenPtr pScreen; +{ + xfree(pScreen->devPrivate); + return TRUE; +} + diff --git a/mfb/mfbscrinit.c b/mfb/mfbscrinit.c new file mode 100644 index 000000000..080e8d2e8 --- /dev/null +++ b/mfb/mfbscrinit.c @@ -0,0 +1,166 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbscrinit.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +#include "X.h" +#include "Xproto.h" /* for xColorItem */ +#include "Xmd.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "resource.h" +#include "colormap.h" +#include "mfb.h" +#include "mistruct.h" +#include "dix.h" +#include "mi.h" +#include "mibstore.h" +#include "migc.h" +#include "servermd.h" + +#ifdef PIXMAP_PER_WINDOW +int frameWindowPrivateIndex; +#endif +int mfbWindowPrivateIndex; +int mfbGCPrivateIndex; +static unsigned long mfbGeneration = 0; + +static VisualRec visual = { +/* vid class bpRGB cmpE nplan rMask gMask bMask oRed oGreen oBlue */ + 0, StaticGray, 1, 2, 1, 0, 0, 0, 0, 0, 0 +}; + +static VisualID VID; + +static DepthRec depth = { +/* depth numVid vids */ + 1, 1, &VID +}; + +#ifndef LOWMEMFTPT + +miBSFuncRec mfbBSFuncRec = { + mfbSaveAreas, + mfbRestoreAreas, + (void (*)()) 0, + (PixmapPtr (*)()) 0, + (PixmapPtr (*)()) 0, +}; + +#endif /* ifndef LOWMEMFTPT */ + +Bool +mfbAllocatePrivates(pScreen, pWinIndex, pGCIndex) + ScreenPtr pScreen; + int *pWinIndex, *pGCIndex; +{ + if (mfbGeneration != serverGeneration) + { +#ifdef PIXMAP_PER_WINDOW + frameWindowPrivateIndex = AllocateWindowPrivateIndex(); +#endif + mfbWindowPrivateIndex = AllocateWindowPrivateIndex(); + mfbGCPrivateIndex = AllocateGCPrivateIndex(); + miRegisterGCPrivateIndex(mfbGCPrivateIndex); + visual.vid = FakeClientID(0); + VID = visual.vid; + mfbGeneration = serverGeneration; + } + if (pWinIndex) + *pWinIndex = mfbWindowPrivateIndex; + if (pGCIndex) + *pGCIndex = mfbGCPrivateIndex; + return (AllocateWindowPrivate(pScreen, mfbWindowPrivateIndex, + sizeof(mfbPrivWin)) && + AllocateGCPrivate(pScreen, mfbGCPrivateIndex, sizeof(mfbPrivGC))); +} + +#ifndef LOWMEMFTPT + +/* dts * (inch/dot) * (25.4 mm / inch) = mm */ +Bool +mfbScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width) + register ScreenPtr pScreen; + pointer pbits; /* pointer to screen bitmap */ + int xsize, ysize; /* in pixels */ + int dpix, dpiy; /* dots per inch */ + int width; /* pixel width of frame buffer */ +{ + if (!mfbAllocatePrivates(pScreen, (int *)NULL, (int *)NULL)) + return FALSE; + pScreen->defColormap = (Colormap) FakeClientID(0); + /* whitePixel, blackPixel */ + pScreen->QueryBestSize = mfbQueryBestSize; + /* SaveScreen */ + pScreen->GetImage = mfbGetImage; + pScreen->GetSpans = mfbGetSpans; + pScreen->CreateWindow = mfbCreateWindow; + pScreen->DestroyWindow = mfbDestroyWindow; + pScreen->PositionWindow = mfbPositionWindow; + pScreen->ChangeWindowAttributes = mfbChangeWindowAttributes; + pScreen->RealizeWindow = mfbMapWindow; + pScreen->UnrealizeWindow = mfbUnmapWindow; + pScreen->PaintWindowBackground = mfbPaintWindow; + pScreen->PaintWindowBorder = mfbPaintWindow; + pScreen->CopyWindow = mfbCopyWindow; + pScreen->CreatePixmap = mfbCreatePixmap; + pScreen->DestroyPixmap = mfbDestroyPixmap; + pScreen->RealizeFont = mfbRealizeFont; + pScreen->UnrealizeFont = mfbUnrealizeFont; + pScreen->CreateGC = mfbCreateGC; + pScreen->CreateColormap = mfbCreateColormap; + pScreen->DestroyColormap = mfbDestroyColormap; + pScreen->InstallColormap = mfbInstallColormap; + pScreen->UninstallColormap = mfbUninstallColormap; + pScreen->ListInstalledColormaps = mfbListInstalledColormaps; + pScreen->StoreColors = (void (*)())NoopDDA; + pScreen->ResolveColor = mfbResolveColor; + pScreen->BitmapToRegion = mfbPixmapToRegion; + return miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width, + 1, 1, &depth, VID, 1, &visual, &mfbBSFuncRec); +} + +#endif /* ifndef LOWMEMFTPT */ diff --git a/mfb/mfbsetsp.c b/mfb/mfbsetsp.c new file mode 100644 index 000000000..08578c0f7 --- /dev/null +++ b/mfb/mfbsetsp.c @@ -0,0 +1,277 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbsetsp.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" + +#include "misc.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "mfb.h" +#include "maskbits.h" + +#include "servermd.h" + + +/* mfbSetScanline -- copies the bits from psrc to the drawable starting at + * (xStart, y) and continuing to (xEnd, y). xOrigin tells us where psrc + * starts on the scanline. (I.e., if this scanline passes through multiple + * boxes, we may not want to start grabbing bits at psrc but at some offset + * further on.) + */ +mfbSetScanline(y, xOrigin, xStart, xEnd, psrc, alu, pdstBase, widthDst) + int y; + int xOrigin; /* where this scanline starts */ + int xStart; /* first bit to use from scanline */ + int xEnd; /* last bit to use from scanline + 1 */ + register PixelType *psrc; + register int alu; /* raster op */ + PixelType *pdstBase; /* start of the drawable */ + int widthDst; /* width of drawable in words */ +{ + int w; /* width of scanline in bits */ + register PixelType *pdst; /* where to put the bits */ + register PixelType tmpSrc; /* scratch buffer to collect bits in */ + int dstBit; /* offset in bits from beginning of + * word */ + register int nstart; /* number of bits from first partial */ + register int nend; /* " " last partial word */ + int offSrc; + PixelType startmask, endmask; + int nlMiddle, nl; + + pdst = mfbScanline(pdstBase, xStart, y, widthDst); + psrc += (xStart - xOrigin) >> PWSH; + offSrc = (xStart - xOrigin) & PIM; + w = xEnd - xStart; + dstBit = xStart & PIM; + + if (dstBit + w <= PPW) + { + getandputrop(psrc, offSrc, dstBit, w, pdst, alu) + } + else + { + + maskbits(xStart, w, startmask, endmask, nlMiddle); + if (startmask) + nstart = PPW - dstBit; + else + nstart = 0; + if (endmask) + nend = xEnd & PIM; + else + nend = 0; + if (startmask) + { + getandputrop(psrc, offSrc, dstBit, nstart, pdst, alu) + pdst++; + offSrc += nstart; + if (offSrc > PLST) + { + psrc++; + offSrc -= PPW; + } + } + nl = nlMiddle; + while (nl--) + { + getbits(psrc, offSrc, PPW, tmpSrc); + DoRop(*pdst, alu, tmpSrc, *pdst); + pdst++; + psrc++; + } + if (endmask) + { + getandputrop0(psrc, offSrc, nend, pdst, alu); + } + + } +} + + + +/* SetSpans -- for each span copy pwidth[i] bits from psrc to pDrawable at + * ppt[i] using the raster op from the GC. If fSorted is TRUE, the scanlines + * are in increasing Y order. + * Source bit lines are server scanline padded so that they always begin + * on a word boundary. + */ +void +mfbSetSpans(pDrawable, pGC, pcharsrc, ppt, pwidth, nspans, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + char *pcharsrc; + register DDXPointPtr ppt; + int *pwidth; + int nspans; + int fSorted; +{ + PixelType *psrc = (PixelType *)pcharsrc; + PixelType *pdstBase; /* start of dst bitmap */ + int widthDst; /* width of bitmap in words */ + register BoxPtr pbox, pboxLast, pboxTest; + register DDXPointPtr pptLast; + int alu; + RegionPtr prgnDst; + int xStart, xEnd; + int yMax; + + alu = pGC->alu; + prgnDst = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + + pptLast = ppt + nspans; + + yMax = pDrawable->y + (int) pDrawable->height; + mfbGetPixelWidthAndPointer(pDrawable, widthDst, pdstBase); + + pbox = REGION_RECTS(prgnDst); + pboxLast = pbox + REGION_NUM_RECTS(prgnDst); + + if(fSorted) + { + /* scan lines sorted in ascending order. Because they are sorted, we + * don't have to check each scanline against each clip box. We can be + * sure that this scanline only has to be clipped to boxes at or after the + * beginning of this y-band + */ + pboxTest = pbox; + while(ppt < pptLast) + { + pbox = pboxTest; + if(ppt->y >= yMax) + break; + while(pbox < pboxLast) + { + if(pbox->y1 > ppt->y) + { + /* scanline is before clip box */ + break; + } + else if(pbox->y2 <= ppt->y) + { + /* clip box is before scanline */ + pboxTest = ++pbox; + continue; + } + else if(pbox->x1 > ppt->x + *pwidth) + { + /* clip box is to right of scanline */ + break; + } + else if(pbox->x2 <= ppt->x) + { + /* scanline is to right of clip box */ + pbox++; + continue; + } + + /* at least some of the scanline is in the current clip box */ + xStart = max(pbox->x1, ppt->x); + xEnd = min(ppt->x + *pwidth, pbox->x2); + mfbSetScanline(ppt->y, ppt->x, xStart, xEnd, psrc, alu, + pdstBase, widthDst); + if(ppt->x + *pwidth <= pbox->x2) + { + /* End of the line, as it were */ + break; + } + else + pbox++; + } + /* We've tried this line against every box; it must be outside them + * all. move on to the next point */ + ppt++; + psrc += PixmapWidthInPadUnits(*pwidth, 1); + pwidth++; + } + } + else + { + /* scan lines not sorted. We must clip each line against all the boxes */ + while(ppt < pptLast) + { + if(ppt->y >= 0 && ppt->y < yMax) + { + + for(pbox = REGION_RECTS(prgnDst); pbox< pboxLast; pbox++) + { + if(pbox->y1 > ppt->y) + { + /* rest of clip region is above this scanline, + * skip it */ + break; + } + if(pbox->y2 <= ppt->y) + { + /* clip box is below scanline */ + pbox++; + break; + } + if(pbox->x1 <= ppt->x + *pwidth && + pbox->x2 > ppt->x) + { + xStart = max(pbox->x1, ppt->x); + xEnd = min(pbox->x2, ppt->x + *pwidth); + mfbSetScanline(ppt->y, ppt->x, xStart, xEnd, + psrc, alu, pdstBase, widthDst); + } + + } + } + psrc += PixmapWidthInPadUnits(*pwidth, 1); + ppt++; + pwidth++; + } + } +} diff --git a/mfb/mfbtegblt.c b/mfb/mfbtegblt.c new file mode 100644 index 000000000..aa5b01f3d --- /dev/null +++ b/mfb/mfbtegblt.c @@ -0,0 +1,419 @@ +/* $Xorg: mfbtegblt.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "mfb.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "maskbits.h" + +/* + this works for fonts with glyphs <= PPW bits wide. + + This should be called only with a terminal-emulator font; +this means that the FIXED_METRICS flag is set, and that +glyphbounds == charbounds. + + in theory, this goes faster; even if it doesn't, it reduces the +flicker caused by writing a string over itself with image text (since +the background gets repainted per character instead of per string.) +this seems to be important for some converted X10 applications. + + Image text looks at the bits in the glyph and the fg and bg in the +GC. it paints a rectangle, as defined in the protocol dcoument, +and the paints the characters. + + to avoid source proliferation, this file is compiled +two times: + MFBTEGLYPHBLT OP + mfbTEGlyphBltWhite (white text, black bg ) + mfbTEGlyphBltBlack ~ (black text, white bg ) + +*/ + +#if defined(NO_3_60_CG4) && defined(FASTPUTBITS) && defined(FASTGETBITS) +#define FASTCHARS +#endif + +/* + * this macro "knows" that only characters <= 8 bits wide will + * fit this case (which is why it is independent of GLYPHPADBYTES) + */ + +#if (BITMAP_BIT_ORDER == MSBFirst) && (GLYPHPADBYTES != 4) +#if GLYPHPADBYTES == 1 +#define ShiftAmnt 24 +#else +#define ShiftAmnt 16 +#endif + +/* + * Note: for BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER, SCRRIGHT() evaluates its + * first argument more than once. Thus the imbedded char++ have to be moved. + * (DHD) + */ +#if BITMAP_BIT_ORDER == IMAGE_BYTE_ORDER +#if PPW == 32 +#define GetBits4 c = (*char1++ << ShiftAmnt) | \ + SCRRIGHT (*char2++ << ShiftAmnt, xoff2) | \ + SCRRIGHT (*char3++ << ShiftAmnt, xoff3) | \ + SCRRIGHT (*char4++ << ShiftAmnt, xoff4); +#else /* PPW */ +#define GetBits4 c = ((unsigned long)(*char1++ << ShiftAmnt) << 32 ) | \ + (SCRRIGHT (*char2++ << ShiftAmnt, xoff2) << 32 ) | \ + (SCRRIGHT (*char3++ << ShiftAmnt, xoff3) << 32 ) | \ + (SCRRIGHT (*char4++ << ShiftAmnt, xoff4) << 32 ) | \ + (*char5++ << ShiftAmnt) | \ + SCRRIGHT (*char6++ << ShiftAmnt, xoff6) | \ + SCRRIGHT (*char7++ << ShiftAmnt, xoff7) | \ + SCRRIGHT (*char8++ << ShiftAmnt, xoff8); +#endif /* PPW */ +#else /* BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER */ +#if PPW == 32 +#define GetBits4 c = (*char1++ << ShiftAmnt) | \ + SCRRIGHT (*char2 << ShiftAmnt, xoff2) | \ + SCRRIGHT (*char3 << ShiftAmnt, xoff3) | \ + SCRRIGHT (*char4 << ShiftAmnt, xoff4); \ + char2++; char3++; char4++; +#else /* PPW == 64 */ +#define GetBits4 c = ((unsigned long)(*char1++ << ShiftAmnt) << 32 ) | \ + (SCRRIGHT (*char2 << ShiftAmnt, xoff2) << 32 ) | \ + (SCRRIGHT (*char3 << ShiftAmnt, xoff3) << 32 ) | \ + (SCRRIGHT (*char4 << ShiftAmnt, xoff4) << 32 ) | \ + (*char5++ << ShiftAmnt) | \ + SCRRIGHT (*char6 << ShiftAmnt, xoff6) | \ + SCRRIGHT (*char7 << ShiftAmnt, xoff7) | \ + SCRRIGHT (*char8 << ShiftAmnt, xoff8); \ + char2++; char3++; char4++; char6++; char7++; char8++; +#endif /* PPW */ +#endif /* BITMAP_BIT_ORDER == IMAGE_BYTE_ORDER */ + +#else /* (BITMAP_BIT_ORDER != MSBFirst) || (GLYPHPADBYTES == 4) */ + +#if BITMAP_BIT_ORDER == IMAGE_BYTE_ORDER +#if PPW == 32 +#define GetBits4 c = *char1++ | \ + SCRRIGHT (*char2++, xoff2) | \ + SCRRIGHT (*char3++, xoff3) | \ + SCRRIGHT (*char4++, xoff4); +#else /* PPW == 64 */ +#define GetBits4 c = (unsigned long)(((*char1++) << 64 ) | \ + (SCRRIGHT (*char2++, xoff2) << 64 ) | \ + (SCRRIGHT (*char3++, xoff3) << 64 ) | \ + (SCRRIGHT (*char4++, xoff4) << 64 ) | \ + SCRRIGHT (*char5++, xoff5) | \ + SCRRIGHT (*char6++, xoff6) | \ + SCRRIGHT (*char7++, xoff7) | \ + SCRRIGHT (*char8++, xoff8)); +#endif /* PPW */ +#else /* BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER */ +#if PPW == 32 +#define GetBits4 c = *char1++ | \ + SCRRIGHT (*char2, xoff2) | \ + SCRRIGHT (*char3, xoff3) | \ + SCRRIGHT (*char4, xoff4); \ + char2++; char3++; char4++; +#else /* PPW == 64 */ +#define GetBits4 c = (unsigned long)(((*char1++) << 64 ) | \ + (SCRRIGHT (*char2, xoff2) << 64 ) | \ + (SCRRIGHT (*char3, xoff3) << 64 ) | \ + (SCRRIGHT (*char4, xoff4) << 64 ) | \ + SCRRIGHT (*char5, xoff5) | \ + SCRRIGHT (*char6, xoff6) | \ + SCRRIGHT (*char7, xoff7) | \ + SCRRIGHT (*char8, xoff8)); \ + char2++; char3++; char4++; \ + char5++; char6++; char7++; char8++; +#endif /* PPW */ +#endif /* BITMAP_BIT_ORDER == IMAGE_BYTE_ORDER */ + +#endif /* BITMAP_BIT_ORDER && GLYPHPADBYTES */ + + +#if GLYPHPADBYTES == 1 +typedef unsigned char *glyphPointer; +#define USE_LEFTBITS +#endif + +#if GLYPHPADBYTES == 2 +typedef unsigned short *glyphPointer; +#define USE_LEFTBITS +#endif + +#if GLYPHPADBYTES == 4 +typedef unsigned int *glyphPointer; +#endif + +#ifdef USE_LEFTBITS +#define GetBits1 getleftbits (char1, widthGlyph, c); \ + c &= glyphMask; \ + char1 = (glyphPointer) (((char *) char1) + glyphBytes); +#else +#define GetBits1 c = *char1++; +#endif + +void +MFBTEGLYPHBLT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GC *pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + FontPtr pfont = pGC->font; + int widthDst; + PixelType *pdstBase; /* pointer to longword with top row + of current glyph */ + + int h; /* height of glyph and char */ + register int xpos; /* current x */ + int ypos; /* current y */ + int widthGlyph; + + int hTmp; /* counter for height */ + register PixelType startmask, endmask; + int nfirst; /* used if glyphs spans a longword boundary */ + BoxRec bbox; /* for clipping */ + int widthGlyphs; + register PixelType *dst; + register PixelType c; + register int xoff1, xoff2, xoff3, xoff4; + register glyphPointer char1, char2, char3, char4; +#if PPW == 64 + register int xoff5, xoff6, xoff7, xoff8; + register glyphPointer char5, char6, char7, char8; +#endif /* PPW */ + +#ifdef USE_LEFTBITS + register PixelType glyphMask; + register PixelType tmpSrc; + register int glyphBytes; +#endif + + if (!(pGC->planemask & 1)) + return; + + mfbGetPixelWidthAndPointer(pDrawable, widthDst, pdstBase); + + xpos = x + pDrawable->x; + ypos = y + pDrawable->y; + + widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); + h = FONTASCENT(pfont) + FONTDESCENT(pfont); + + xpos += FONTMAXBOUNDS(pfont,leftSideBearing); + ypos -= FONTASCENT(pfont); + + bbox.x1 = xpos; + bbox.x2 = xpos + (widthGlyph * nglyph); + bbox.y1 = ypos; + bbox.y2 = ypos + h; + + switch (RECT_IN_REGION(pGC->pScreen, + ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, &bbox)) + { + case rgnPART: + /* this is the WRONG thing to do, but it works. + calling the non-terminal text is easy, but slow, given + what we know about the font. + + the right thing to do is something like: + for each clip rectangle + compute at which row the glyph starts to be in it, + and at which row the glyph ceases to be in it + compute which is the first glyph inside the left + edge, and the last one inside the right edge + draw a fractional first glyph, using only + the rows we know are in + draw all the whole glyphs, using the appropriate rows + draw any pieces of the last glyph, using the right rows + + this way, the code would take advantage of knowing that + all glyphs are the same height and don't overlap. + + one day... + */ + CLIPTETEXT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + case rgnOUT: + return; + } + pdstBase = mfbScanlineDeltaNoBankSwitch(pdstBase, ypos, widthDst); + widthGlyphs = widthGlyph * PGSZB; + +#ifdef USE_LEFTBITS + glyphMask = endtab[widthGlyph]; + glyphBytes = GLYPHWIDTHBYTESPADDED(*ppci); +#endif + + if (nglyph >= PGSZB && widthGlyphs <= PPW) + { + while (nglyph >= PGSZB) + { + nglyph -= PGSZB; + xoff1 = xpos & PIM; + xoff2 = widthGlyph; + xoff3 = xoff2 + widthGlyph; + xoff4 = xoff3 + widthGlyph; +#if PPW == 64 + xoff5 = xoff4 + widthGlyph; + xoff6 = xoff5 + widthGlyph; + xoff7 = xoff6 + widthGlyph; + xoff8 = xoff7 + widthGlyph; +#endif /* PPW */ + char1 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); + char2 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); + char3 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); + char4 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); +#if PPW == 64 + char5 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); + char6 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); + char7 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); + char8 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); +#endif /* PPW */ + + hTmp = h; + dst = mfbScanlineOffset(pdstBase, (xpos >> PWSH)); /* switch now */ + +#ifndef FASTCHARS + if (xoff1 + widthGlyphs <= PPW) + { + maskpartialbits (xoff1, widthGlyphs, startmask); +#endif + while (hTmp--) + { + GetBits4 +#ifdef FASTCHARS +# if BITMAP_BIT_ORDER == MSBFirst + c >>= PPW - widthGlyphs; +# endif + FASTPUTBITS(OP(c), xoff1, widthGlyphs, dst); +#else + *(dst) = (*dst) & ~startmask | OP(SCRRIGHT(c, xoff1)) & startmask; +#endif + mfbScanlineInc(dst, widthDst); + } +#ifndef FASTCHARS + } + else + { + maskPPWbits (xoff1, widthGlyphs, startmask, endmask); + nfirst = PPW - xoff1; + while (hTmp--) + { + GetBits4 + dst[0] = dst[0] & ~startmask | + OP(SCRRIGHT(c,xoff1)) & startmask; + dst[1] = dst[1] & ~endmask | + OP(SCRLEFT(c,nfirst)) & endmask; + mfbScanlineInc(dst, widthDst); + } + } +#endif + xpos += widthGlyphs; + } + } + + while(nglyph--) + { + xoff1 = xpos & PIM; + char1 = (glyphPointer) FONTGLYPHBITS(pglyphBase,(*ppci++)); + hTmp = h; + dst = mfbScanlineOffset(pdstBase, (xpos >> PWSH)); + +#ifndef FASTCHARS + if (xoff1 + widthGlyph <= PPW) + { + maskpartialbits (xoff1, widthGlyph, startmask); +#endif + while (hTmp--) + { +#ifdef FASTCHARS +#ifdef USE_LEFTBITS + FASTGETBITS (char1,0,widthGlyph,c); + char1 = (glyphPointer) (((char *) char1) + glyphBytes); +#else + c = *char1++; +#if BITMAP_BIT_ORDER == MSBFirst + c >>= PPW - widthGlyph; +#endif +#endif + FASTPUTBITS (OP(c),xoff1,widthGlyph,dst); +#else + GetBits1 + (*dst) = (*dst) & ~startmask | OP(SCRRIGHT(c, xoff1)) & startmask; +#endif + mfbScanlineInc(dst, widthDst); + } +#ifndef FASTCHARS + } + else + { + maskPPWbits (xoff1, widthGlyph, startmask, endmask); + nfirst = PPW - xoff1; + while (hTmp--) + { + GetBits1 + dst[0] = dst[0] & ~startmask | + OP(SCRRIGHT(c,xoff1)) & startmask; + dst[1] = dst[1] & ~endmask | + OP(SCRLEFT(c,nfirst)) & endmask; + mfbScanlineInc(dst, widthDst); + } + } +#endif + xpos += widthGlyph; + } +} diff --git a/mfb/mfbtile.c b/mfb/mfbtile.c new file mode 100644 index 000000000..f716f4487 --- /dev/null +++ b/mfb/mfbtile.c @@ -0,0 +1,230 @@ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mfbtile.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +#include "X.h" + +#include "windowstr.h" +#include "regionstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +#include "mfb.h" +#include "maskbits.h" + +#include "mergerop.h" +/* + + the boxes are already translated. + + NOTE: + iy = ++iy < tileHeight ? iy : 0 +is equivalent to iy%= tileheight, and saves a division. +*/ + +/* + tile area with a PPW bit wide pixmap +*/ +void +MROP_NAME(mfbTileAreaPPW)(pDraw, nbox, pbox, alu, ptile) + DrawablePtr pDraw; + int nbox; + BoxPtr pbox; + int alu; + PixmapPtr ptile; +{ + register PixelType *psrc; + /* pointer to bits in tile, if needed */ + int tileHeight; /* height of the tile */ + register PixelType srcpix; + int nlwidth; /* width in longwords of the drawable */ + int w; /* width of current box */ + MROP_DECLARE_REG () + register int h; /* height of current box */ + register int nlw; /* loop version of nlwMiddle */ + register PixelType *p; /* pointer to bits we're writing */ + PixelType startmask; + PixelType endmask; /* masks for reggedy bits at either end of line */ + int nlwMiddle; /* number of longwords between sides of boxes */ + int nlwExtra; /* to get from right of box to left of next span */ + register int iy; /* index of current scanline in tile */ + PixelType *pbits; /* pointer to start of drawable */ + + mfbGetPixelWidthAndPointer(pDraw, nlwidth, pbits); + + MROP_INITIALIZE(alu,~0) + + tileHeight = ptile->drawable.height; + psrc = (PixelType *)(ptile->devPrivate.ptr); + + while (nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + iy = pbox->y1 % tileHeight; + p = mfbScanline(pbits, pbox->x1, pbox->y1, nlwidth); + + if ( ((pbox->x1 & PIM) + w) < PPW) + { + maskpartialbits(pbox->x1, w, startmask); + nlwExtra = nlwidth; + while (h--) + { + srcpix = psrc[iy]; + iy++; + if (iy == tileHeight) + iy = 0; + *p = MROP_MASK(srcpix,*p,startmask); + mfbScanlineInc(p, nlwExtra); + } + } + else + { + maskbits(pbox->x1, w, startmask, endmask, nlwMiddle); + nlwExtra = nlwidth - nlwMiddle; + + if (startmask && endmask) + { + nlwExtra -= 1; + while (h--) + { + srcpix = psrc[iy]; + iy++; + if (iy == tileHeight) + iy = 0; + nlw = nlwMiddle; + *p = MROP_MASK (srcpix,*p,startmask); + p++; + while (nlw--) + { + *p = MROP_SOLID(srcpix,*p); + p++; + } + + *p = MROP_MASK(srcpix,*p,endmask); + mfbScanlineInc(p, nlwExtra); + } + } + else if (startmask && !endmask) + { + nlwExtra -= 1; + while (h--) + { + srcpix = psrc[iy]; + iy++; + if (iy == tileHeight) + iy = 0; + nlw = nlwMiddle; + *p = MROP_MASK(srcpix,*p,startmask); + p++; + while (nlw--) + { + *p = MROP_SOLID(srcpix,*p); + p++; + } + mfbScanlineInc(p, nlwExtra); + } + } + else if (!startmask && endmask) + { + while (h--) + { + srcpix = psrc[iy]; + iy++; + if (iy == tileHeight) + iy = 0; + nlw = nlwMiddle; + while (nlw--) + { + *p = MROP_SOLID(srcpix,*p); + p++; + } + + *p = MROP_MASK(srcpix,*p,endmask); + mfbScanlineInc(p, nlwExtra); + } + } + else /* no ragged bits at either end */ + { + while (h--) + { + srcpix = psrc[iy]; + iy++; + if (iy == tileHeight) + iy = 0; + nlw = nlwMiddle; + while (nlw--) + { + *p = MROP_SOLID (srcpix,*p); + p++; + } + mfbScanlineInc(p, nlwExtra); + } + } + } + pbox++; + } +} + +#if (MROP) == 0 +void +mfbTileAreaPPW (pDraw, nbox, pbox, alu, ptile) + DrawablePtr pDraw; + int nbox; + BoxPtr pbox; + int alu; + PixmapPtr ptile; +{ + void (*f)(), mfbTileAreaPPWCopy(), mfbTileAreaPPWGeneral(); + + if (alu == GXcopy) + f = mfbTileAreaPPWCopy; + else + f = mfbTileAreaPPWGeneral; + (*f) (pDraw, nbox, pbox, alu, ptile); +} +#endif diff --git a/mfb/mfbwindow.c b/mfb/mfbwindow.c new file mode 100644 index 000000000..8107b9807 --- /dev/null +++ b/mfb/mfbwindow.c @@ -0,0 +1,338 @@ +/* $Xorg: mfbwindow.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "mfb.h" +#include "mistruct.h" +#include "regionstr.h" +#include "maskbits.h" + +extern WindowPtr *WindowTable; + +Bool +mfbCreateWindow(pWin) + register WindowPtr pWin; +{ + register mfbPrivWin *pPrivWin; + + pPrivWin = (mfbPrivWin *)(pWin->devPrivates[mfbWindowPrivateIndex].ptr); + pPrivWin->pRotatedBorder = NullPixmap; + pPrivWin->pRotatedBackground = NullPixmap; + pPrivWin->fastBackground = FALSE; + pPrivWin->fastBorder = FALSE; + + return (TRUE); +} + +/* This always returns true, because Xfree can't fail. It might be possible + * on some devices for Destroy to fail */ +Bool +mfbDestroyWindow(pWin) + WindowPtr pWin; +{ + register mfbPrivWin *pPrivWin; + + pPrivWin = (mfbPrivWin *)(pWin->devPrivates[mfbWindowPrivateIndex].ptr); + + if (pPrivWin->pRotatedBorder) + (*pWin->drawable.pScreen->DestroyPixmap)(pPrivWin->pRotatedBorder); + if (pPrivWin->pRotatedBackground) + (*pWin->drawable.pScreen->DestroyPixmap)(pPrivWin->pRotatedBackground); + return (TRUE); +} + +/*ARGSUSED*/ +Bool mfbMapWindow(pWindow) + WindowPtr pWindow; +{ + return (TRUE); +} + +/* (x, y) is the upper left corner of the window on the screen + do we really need to pass this? (is it a;ready in pWin->absCorner?) + we only do the rotation for pixmaps that are 32 bits wide (padded +or otherwise.) + mfbChangeWindowAttributes() has already put a copy of the pixmap +in pPrivWin->pRotated* +*/ + +/*ARGSUSED*/ +Bool +mfbPositionWindow(pWin, x, y) + register WindowPtr pWin; + int x, y; +{ + register mfbPrivWin *pPrivWin; + int reset = 0; + + pPrivWin = (mfbPrivWin *)(pWin->devPrivates[mfbWindowPrivateIndex].ptr); + if (pWin->backgroundState == BackgroundPixmap && pPrivWin->fastBackground) + { + mfbXRotatePixmap(pPrivWin->pRotatedBackground, + pWin->drawable.x - pPrivWin->oldRotate.x); + mfbYRotatePixmap(pPrivWin->pRotatedBackground, + pWin->drawable.y - pPrivWin->oldRotate.y); + reset = 1; + } + + if (!pWin->borderIsPixel && pPrivWin->fastBorder) + { + while (pWin->backgroundState == ParentRelative) + pWin = pWin->parent; + mfbXRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.x - pPrivWin->oldRotate.x); + mfbYRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.y - pPrivWin->oldRotate.y); + reset = 1; + } + if (reset) + { + pPrivWin->oldRotate.x = pWin->drawable.x; + pPrivWin->oldRotate.y = pWin->drawable.y; + } + + /* This is the "wrong" fix to the right problem, but it doesn't really + * cost very much. When the window is moved, we need to invalidate any + * RotatedPixmap that exists in any GC currently validated against this + * window. + */ + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + /* Again, we have no failure modes indicated by any of the routines + * we've called, so we have to assume it worked */ + return (TRUE); +} + +/*ARGSUSED*/ +Bool +mfbUnmapWindow(pWindow) + WindowPtr pWindow; +{ + return (TRUE); +} + +/* UNCLEAN! + this code calls the bitblt helper code directly. + + mfbCopyWindow copies only the parts of the destination that are +visible in the source. +*/ + + +void +mfbCopyWindow(pWin, ptOldOrg, prgnSrc) + WindowPtr pWin; + DDXPointRec ptOldOrg; + RegionPtr prgnSrc; +{ + DDXPointPtr pptSrc; + register DDXPointPtr ppt; + RegionPtr prgnDst; + register BoxPtr pbox; + register int dx, dy; + register int i, nbox; + WindowPtr pwinRoot; + + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + prgnDst = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); + REGION_INTERSECT(pWin->drawable.pScreen, prgnDst, &pWin->borderClip, + prgnSrc); + + pbox = REGION_RECTS(prgnDst); + nbox = REGION_NUM_RECTS(prgnDst); + if(!(pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) + return; + ppt = pptSrc; + + for (i=nbox; --i >= 0; ppt++, pbox++) + { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + mfbDoBitblt((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + GXcopy, prgnDst, pptSrc); + DEALLOCATE_LOCAL(pptSrc); + REGION_DESTROY(pWin->drawable.pScreen, prgnDst); +} + + + +/* swap in correct PaintWindow* routine. If we can use a fast output +routine (i.e. the pixmap is paddable to 32 bits), also pre-rotate a copy +of it in devPrivate. +*/ +Bool +mfbChangeWindowAttributes(pWin, mask) + register WindowPtr pWin; + register unsigned long mask; +{ + register unsigned long index; + register mfbPrivWin *pPrivWin; + WindowPtr pBgWin; + + pPrivWin = (mfbPrivWin *)(pWin->devPrivates[mfbWindowPrivateIndex].ptr); + /* + * When background state changes from ParentRelative and + * we had previously rotated the fast border pixmap to match + * the parent relative origin, rerotate to match window + */ + if (mask & (CWBackPixmap | CWBackPixel) && + pWin->backgroundState != ParentRelative && + pPrivWin->fastBorder && + (pPrivWin->oldRotate.x != pWin->drawable.x || + pPrivWin->oldRotate.y != pWin->drawable.y)) + { + mfbXRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.x - pPrivWin->oldRotate.x); + mfbYRotatePixmap(pPrivWin->pRotatedBorder, + pWin->drawable.y - pPrivWin->oldRotate.y); + pPrivWin->oldRotate.x = pWin->drawable.x; + pPrivWin->oldRotate.y = pWin->drawable.y; + } + while(mask) + { + index = lowbit (mask); + mask &= ~index; + switch(index) + { + case CWBackPixmap: + if (pWin->backgroundState == None) + { + pPrivWin->fastBackground = FALSE; + } + else if (pWin->backgroundState == ParentRelative) + { + pPrivWin->fastBackground = FALSE; + /* Rotate border to match parent origin */ + if (pPrivWin->pRotatedBorder) { + for (pBgWin = pWin->parent; + pBgWin->backgroundState == ParentRelative; + pBgWin = pBgWin->parent); + mfbXRotatePixmap(pPrivWin->pRotatedBorder, + pBgWin->drawable.x - pPrivWin->oldRotate.x); + mfbYRotatePixmap(pPrivWin->pRotatedBorder, + pBgWin->drawable.y - pPrivWin->oldRotate.y); + pPrivWin->oldRotate.x = pBgWin->drawable.x; + pPrivWin->oldRotate.y = pBgWin->drawable.y; + } + } + else if ((pWin->background.pixmap->drawable.width <= PPW) && + !(pWin->background.pixmap->drawable.width & + (pWin->background.pixmap->drawable.width - 1))) + { + mfbCopyRotatePixmap(pWin->background.pixmap, + &pPrivWin->pRotatedBackground, + pWin->drawable.x, + pWin->drawable.y); + if (pPrivWin->pRotatedBackground) + { + pPrivWin->fastBackground = TRUE; + pPrivWin->oldRotate.x = pWin->drawable.x; + pPrivWin->oldRotate.y = pWin->drawable.y; + } + else + { + pPrivWin->fastBackground = FALSE; + } + } + else + { + pPrivWin->fastBackground = FALSE; + } + break; + + case CWBackPixel: + pPrivWin->fastBackground = FALSE; + break; + + case CWBorderPixmap: + if ((pWin->border.pixmap->drawable.width <= PPW) && + !(pWin->border.pixmap->drawable.width & + (pWin->border.pixmap->drawable.width - 1))) + { + for (pBgWin = pWin; + pBgWin->backgroundState == ParentRelative; + pBgWin = pBgWin->parent); + mfbCopyRotatePixmap(pWin->border.pixmap, + &pPrivWin->pRotatedBorder, + pBgWin->drawable.x, + pBgWin->drawable.y); + if (pPrivWin->pRotatedBorder) + { + pPrivWin->fastBorder = TRUE; + pPrivWin->oldRotate.x = pBgWin->drawable.x; + pPrivWin->oldRotate.y = pBgWin->drawable.y; + } + else + { + pPrivWin->fastBorder = FALSE; + } + } + else + { + pPrivWin->fastBorder = FALSE; + } + break; + case CWBorderPixel: + pPrivWin->fastBorder = FALSE; + break; + } + } + /* Again, we have no failure modes indicated by any of the routines + * we've called, so we have to assume it worked */ + return (TRUE); +} diff --git a/mfb/mfbzerarc.c b/mfb/mfbzerarc.c new file mode 100644 index 000000000..2135a7969 --- /dev/null +++ b/mfb/mfbzerarc.c @@ -0,0 +1,253 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mfbzerarc.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ + +/* Derived from: + * "Algorithm for drawing ellipses or hyperbolae with a digital plotter" + * by M. L. V. Pitteway + * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289 + */ + +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "mfb.h" +#include "maskbits.h" +#include "mizerarc.h" +#include "mi.h" + +/* + * Note: LEFTMOST must be the bit leftmost in the actual screen + * representation. This depends also on the IMAGE_BYTE_ORDER. + * LONG2CHARS() takes care of the re-ordering as required. (DHD) + */ +#if (BITMAP_BIT_ORDER == MSBFirst) +#define LEFTMOST ((PixelType) LONG2CHARS((1 << PLST))) +#else +#define LEFTMOST ((PixelType) LONG2CHARS(1)) +#endif + +#define PixelateWhite(addr,yoff,xoff) \ + *mfbScanlineOffset(addr, (yoff)+((xoff)>>PWSH)) |= \ + SCRRIGHT (LEFTMOST, ((xoff) & PIM)) +#define PixelateBlack(addr,yoff,xoff) \ + *mfbScanlineOffset(addr, (yoff)+((xoff)>>PWSH)) &= \ + ~(SCRRIGHT (LEFTMOST, ((xoff) & PIM))) + +#define Pixelate(base,yoff,xoff) \ +{ \ + paddr = mfbScanlineOffset(base, (yoff) + ((xoff)>>PWSH)); \ + pmask = SCRRIGHT(LEFTMOST, (xoff) & PIM); \ + *paddr = (*paddr & ~pmask) | (pixel & pmask); \ +} + +#define DoPix(bit,base,yoff,xoff) if (mask & bit) Pixelate(base,yoff,xoff); + +static void +mfbZeroArcSS(pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + miZeroArcRec info; + Bool do360; + register int x, y, a, b, d, mask; + register int k1, k3, dx, dy; + PixelType *addrl; + PixelType *yorgl, *yorgol; + PixelType pixel; + int nlwidth, yoffset, dyoffset; + PixelType pmask; + register PixelType *paddr; + + if (((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop == + RROP_BLACK) + pixel = 0; + else + pixel = ~0; + + mfbGetPixelWidthAndPointer(pDraw, nlwidth, addrl); + do360 = miZeroArcSetup(arc, &info, TRUE); + yorgl = addrl + ((info.yorg + pDraw->y) * nlwidth); + yorgol = addrl + ((info.yorgo + pDraw->y) * nlwidth); + info.xorg += pDraw->x; + info.xorgo += pDraw->x; + MIARCSETUP(); + yoffset = y ? nlwidth : 0; + dyoffset = 0; + mask = info.initialMask; + if (!(arc->width & 1)) + { + DoPix(2, yorgl, 0, info.xorgo); + DoPix(8, yorgol, 0, info.xorgo); + } + if (!info.end.x || !info.end.y) + { + mask = info.end.mask; + info.end = info.altend; + } + if (do360 && (arc->width == arc->height) && !(arc->width & 1)) + { + int xoffset = nlwidth; + PixelType *yorghl = mfbScanlineDeltaNoBankSwitch(yorgl, info.h, nlwidth); + int xorghp = info.xorg + info.h; + int xorghn = info.xorg - info.h; + + if (pixel) + { + while (1) + { + PixelateWhite(yorgl, yoffset, info.xorg + x); + PixelateWhite(yorgl, yoffset, info.xorg - x); + PixelateWhite(yorgol, -yoffset, info.xorg - x); + PixelateWhite(yorgol, -yoffset, info.xorg + x); + if (a < 0) + break; + PixelateWhite(yorghl, -xoffset, xorghp - y); + PixelateWhite(yorghl, -xoffset, xorghn + y); + PixelateWhite(yorghl, xoffset, xorghn + y); + PixelateWhite(yorghl, xoffset, xorghp - y); + xoffset += nlwidth; + MIARCCIRCLESTEP(yoffset += nlwidth;); + } + } + else + { + while (1) + { + PixelateBlack(yorgl, yoffset, info.xorg + x); + PixelateBlack(yorgl, yoffset, info.xorg - x); + PixelateBlack(yorgol, -yoffset, info.xorg - x); + PixelateBlack(yorgol, -yoffset, info.xorg + x); + if (a < 0) + break; + PixelateBlack(yorghl, -xoffset, xorghp - y); + PixelateBlack(yorghl, -xoffset, xorghn + y); + PixelateBlack(yorghl, xoffset, xorghn + y); + PixelateBlack(yorghl, xoffset, xorghp - y); + xoffset += nlwidth; + MIARCCIRCLESTEP(yoffset += nlwidth;); + } + } + x = info.w; + yoffset = info.h * nlwidth; + } + else if (do360) + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(dyoffset = nlwidth;); + Pixelate(yorgl, yoffset, info.xorg + x); + Pixelate(yorgl, yoffset, info.xorgo - x); + Pixelate(yorgol, -yoffset, info.xorgo - x); + Pixelate(yorgol, -yoffset, info.xorg + x); + MIARCSTEP(yoffset += dyoffset;, yoffset += nlwidth;); + } + } + else + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(dyoffset = nlwidth;); + if ((x == info.start.x) || (y == info.start.y)) + { + mask = info.start.mask; + info.start = info.altstart; + } + DoPix(1, yorgl, yoffset, info.xorg + x); + DoPix(2, yorgl, yoffset, info.xorgo - x); + DoPix(4, yorgol, -yoffset, info.xorgo - x); + DoPix(8, yorgol, -yoffset, info.xorg + x); + if ((x == info.end.x) || (y == info.end.y)) + { + mask = info.end.mask; + info.end = info.altend; + } + MIARCSTEP(yoffset += dyoffset;, yoffset += nlwidth;); + } + } + if ((x == info.start.x) || (y == info.start.y)) + mask = info.start.mask; + DoPix(1, yorgl, yoffset, info.xorg + x); + DoPix(4, yorgol, -yoffset, info.xorgo - x); + if (arc->height & 1) + { + DoPix(2, yorgl, yoffset, info.xorgo - x); + DoPix(8, yorgol, -yoffset, info.xorg + x); + } +} + +void +mfbZeroPolyArcSS(pDraw, pGC, narcs, parcs) + DrawablePtr pDraw; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + register xArc *arc; + register int i; + BoxRec box; + int x2, y2; + RegionPtr cclip; + + if (!pGC->planemask & 1) + return; + cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip; + for (arc = parcs, i = narcs; --i >= 0; arc++) + { + if (miCanZeroArc(arc)) + { + box.x1 = arc->x + pDraw->x; + box.y1 = arc->y + pDraw->y; + /* + * Because box.x2 and box.y2 get truncated to 16 bits, and the + * RECT_IN_REGION test treats the resulting number as a signed + * integer, the RECT_IN_REGION test alone can go the wrong way. + * This can result in a server crash because the rendering + * routines in this file deal directly with cpu addresses + * of pixels to be stored, and do not clip or otherwise check + * that all such addresses are within their respective pixmaps. + * So we only allow the RECT_IN_REGION test to be used for + * values that can be expressed correctly in a signed short. + */ + x2 = box.x1 + (int)arc->width + 1; + box.x2 = x2; + y2 = box.y1 + (int)arc->height + 1; + box.y2 = y2; + if ( (x2 <= MAXSHORT) && (y2 <= MAXSHORT) && + (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) ) + mfbZeroArcSS(pDraw, pGC, arc); + else + miZeroPolyArc(pDraw, pGC, 1, arc); + } + else + miPolyArc(pDraw, pGC, 1, arc); + } +} diff --git a/mi/cbrt.c b/mi/cbrt.c new file mode 100644 index 000000000..44a017ad5 --- /dev/null +++ b/mi/cbrt.c @@ -0,0 +1,39 @@ +/* $Xorg: cbrt.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* simple cbrt, in case your math library doesn't have a good one */ + +double pow(); + +double +cbrt(x) + double x; +{ + return pow(x, 1.0/3.0); +} diff --git a/mi/mi.h b/mi/mi.h new file mode 100644 index 000000000..dd7dc94ed --- /dev/null +++ b/mi/mi.h @@ -0,0 +1,748 @@ +/* $Xorg: mi.h,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef MI_H +#define MI_H +#include "X11/X.h" +#include "region.h" +#include "validate.h" +#include "window.h" +#include "gc.h" +#include "font.h" +#include "input.h" +#include "cursor.h" + +typedef struct _miDash *miDashPtr; +#define EVEN_DASH 0 +#define ODD_DASH ~0 + +/* miarc.c */ + +extern void miPolyArc( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); + +/* mibitblt.c */ + +extern RegionPtr miCopyArea( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr /*pGC*/, + int /*xIn*/, + int /*yIn*/, + int /*widthSrc*/, + int /*heightSrc*/, + int /*xOut*/, + int /*yOut*/ +#endif +); + +extern void miOpqStipDrawable( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + RegionPtr /*prgnSrc*/, + unsigned long * /*pbits*/, + int /*srcx*/, + int /*w*/, + int /*h*/, + int /*dstx*/, + int /*dsty*/ +#endif +); + +extern RegionPtr miCopyPlane( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr /*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/, + unsigned long /*bitPlane*/ +#endif +); + +extern void miGetImage( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + int /*sx*/, + int /*sy*/, + int /*w*/, + int /*h*/, + unsigned int /*format*/, + unsigned long /*planeMask*/, + char * /*pdstLine*/ +#endif +); + +extern void miPutImage( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*depth*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*leftPad*/, + int /*format*/, + char * /*pImage*/ +#endif +); + +/* miclipn.c */ + +extern void miClipNotify( +#if NeedFunctionPrototypes + void (* /*func*/)() +#endif +); + +/* micursor.c */ + +extern void miRecolorCursor( +#if NeedFunctionPrototypes + ScreenPtr /*pScr*/, + CursorPtr /*pCurs*/, + Bool /*displayed*/ +#endif +); + +/* midash.c */ + +extern miDashPtr miDashLine( +#if NeedFunctionPrototypes + int /*npt*/, + DDXPointPtr /*ppt*/, + unsigned int /*nDash*/, + unsigned char * /*pDash*/, + unsigned int /*offset*/, + int * /*pnseg*/ +#endif +); + +extern void miStepDash( +#if NeedFunctionPrototypes + int /*dist*/, + int * /*pDashIndex*/, + unsigned char * /*pDash*/, + int /*numInDashList*/, + int * /*pDashOffset*/ +#endif +); + +/* mieq.c */ + + +#ifndef INPUT_H +typedef struct _DeviceRec *DevicePtr; +#endif + +extern Bool mieqInit( +#if NeedFunctionPrototypes + DevicePtr /*pKbd*/, + DevicePtr /*pPtr*/ +#endif +); + +extern void mieqEnqueue( +#if NeedFunctionPrototypes + xEventPtr /*e*/ +#endif +); + +extern void mieqSwitchScreen( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + Bool /*fromDIX*/ +#endif +); + +extern int mieqProcessInputEvents( +#if NeedFunctionPrototypes + void +#endif +); + +/* miexpose.c */ + +extern RegionPtr miHandleExposures( +#if NeedFunctionPrototypes + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr /*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/, + unsigned long /*plane*/ +#endif +); + +extern void miSendGraphicsExpose( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + RegionPtr /*pRgn*/, + XID /*drawable*/, + int /*major*/, + int /*minor*/ +#endif +); + +extern void miSendExposures( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + RegionPtr /*pRgn*/, + int /*dx*/, + int /*dy*/ +#endif +); + +extern void miWindowExposures( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + RegionPtr /*prgn*/, + RegionPtr /*other_exposed*/ +#endif +); + +extern void miPaintWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + RegionPtr /*prgn*/, + int /*what*/ +#endif +); + +extern int miClearDrawable( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/ +#endif +); + +/* mifillrct.c */ + +extern void miPolyFillRect( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nrectFill*/, + xRectangle * /*prectInit*/ +#endif +); + +/* miglblt.c */ + +extern void miPolyGlyphBlt( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); + +extern void miImageGlyphBlt( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/ +#endif +); + +/* mipoly.c */ + +extern void miFillPolygon( +#if NeedFunctionPrototypes + DrawablePtr /*dst*/, + GCPtr /*pgc*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*pPts*/ +#endif +); + +/* mipolycon.c */ + +extern Bool miFillConvexPoly( +#if NeedFunctionPrototypes + DrawablePtr /*dst*/, + GCPtr /*pgc*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +#endif +); + +/* mipolygen.c */ + +extern Bool miFillGeneralPoly( +#if NeedFunctionPrototypes + DrawablePtr /*dst*/, + GCPtr /*pgc*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +#endif +); + +/* mipolypnt.c */ + +extern void miPolyPoint( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + xPoint * /*pptInit*/ +#endif +); + +/* mipolyrect.c */ + +extern void miPolyRectangle( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*nrects*/, + xRectangle * /*pRects*/ +#endif +); + +/* mipolyseg.c */ + +extern void miPolySegment( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegs*/ +#endif +); + +/* mipolytext.c */ + +extern int miPolyText( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/, + FontEncoding /*fontEncoding*/ +#endif +); + +extern int miPolyText8( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/ +#endif +); + +extern int miPolyText16( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/ +#endif +); + +extern int miImageText( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/, + FontEncoding /*fontEncoding*/ +#endif +); + +extern void miImageText8( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/ +#endif +); + +extern void miImageText16( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/ +#endif +); + +/* mipushpxl.c */ + +extern void miPushPixels( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + PixmapPtr /*pBitMap*/, + DrawablePtr /*pDrawable*/, + int /*dx*/, + int /*dy*/, + int /*xOrg*/, + int /*yOrg*/ +#endif +); + +/* miregion.c */ + +/* see also region.h */ + +extern Bool miRectAlloc( +#if NeedFunctionPrototypes + RegionPtr /*pRgn*/, + int /*n*/ +#endif +); + +extern void miSetExtents( +#if NeedFunctionPrototypes + RegionPtr /*pReg*/ +#endif +); + +extern int miFindMaxBand( +#if NeedFunctionPrototypes + RegionPtr /*prgn*/ +#endif +); + +#ifdef DEBUG +extern Bool miValidRegion( +#if NeedFunctionPrototypes + RegionPtr /*prgn*/ +#endif +); +#endif + +/* miscrinit.c */ + +extern Bool miModifyPixmapHeader( +#if NeedFunctionPrototypes + PixmapPtr /*pPixmap*/, + int /*width*/, + int /*height*/, + int /*depth*/, + int /*bitsPerPixel*/, + int /*devKind*/, + pointer /*pPixData*/ +#endif +); + +extern Bool miCloseScreen( +#if NeedFunctionPrototypes + int /*index*/, + ScreenPtr /*pScreen*/ +#endif +); + +extern Bool miCreateScreenResources( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/ +#endif +); + +extern Bool miScreenDevPrivateInit( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int /*width*/, + pointer /*pbits*/ +#endif +); + +#ifndef _XTYPEDEF_MIBSFUNCPTR +typedef struct _miBSFuncRec *miBSFuncPtr; +#define _XTYPEDEF_MIBSFUNCPTR +#endif + +extern Bool miScreenInit( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + pointer /*pbits*/, + int /*xsize*/, + int /*ysize*/, + int /*dpix*/, + int /*dpiy*/, + int /*width*/, + int /*rootDepth*/, + int /*numDepths*/, + DepthPtr /*depths*/, + VisualID /*rootVisual*/, + int /*numVisuals*/, + VisualPtr /*visuals*/, + miBSFuncPtr /*bsfuncs*/ +#endif +); + +/* mivaltree.c */ + +extern int miShapedWindowIn( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + RegionPtr /*universe*/, + RegionPtr /*bounding*/, + BoxPtr /*rect*/, + int /*x*/, + int /*y*/ +#endif +); + +extern int miValidateTree( +#if NeedFunctionPrototypes + WindowPtr /*pParent*/, + WindowPtr /*pChild*/, + VTKind /*kind*/ +#endif +); + +extern void miWideLine( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pPts*/ +#endif +); + +extern void miWideDash( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pPts*/ +#endif +); + +extern void miMiter( +#if NeedFunctionPrototypes + void +#endif +); + +extern void miNotMiter( +#if NeedFunctionPrototypes + void +#endif +); + +/* miwindow.c */ + +extern void miClearToBackground( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + Bool /*generateExposures*/ +#endif +); + +extern Bool miChangeSaveUnder( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + WindowPtr /*first*/ +#endif +); + +extern void miPostChangeSaveUnder( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + WindowPtr /*pFirst*/ +#endif +); + +extern void miMarkWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern Bool miMarkOverlappedWindows( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + WindowPtr /*pFirst*/, + WindowPtr * /*ppLayerWin*/ +#endif +); + +extern void miHandleValidateExposures( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void miMoveWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + WindowPtr /*pNextSib*/, + VTKind /*kind*/ +#endif +); + +extern void miSlideAndSizeWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + unsigned int /*w*/, + unsigned int /*h*/, + WindowPtr /*pSib*/ +#endif +); + +extern WindowPtr miGetLayerWindow( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void miSetShape( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); + +extern void miChangeBorderWidth( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/, + unsigned int /*width*/ +#endif +); + +extern void miMarkUnrealizedWindow( +#if NeedFunctionPrototypes + WindowPtr /*pChild*/, + WindowPtr /*pWin*/, + Bool /*fromConfigure*/ +#endif +); + +extern void miZeroPolyArc( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); + +/* mizerline.c */ + +extern void miZeroLine( +#if NeedFunctionPrototypes + DrawablePtr /*dst*/, + GCPtr /*pgc*/, + int /*mode*/, + int /*nptInit*/, + DDXPointRec * /*pptInit*/ +#endif +); + +extern void miZeroDashLine( +#if NeedFunctionPrototypes + DrawablePtr /*dst*/, + GCPtr /*pgc*/, + int /*mode*/, + int /*nptInit*/, + DDXPointRec * /*pptInit*/ +#endif +); + +extern void miPolyFillArc( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/ +#endif +); + +#endif /* MI_H */ diff --git a/mi/miarc.c b/mi/miarc.c new file mode 100644 index 000000000..db569fa41 --- /dev/null +++ b/mi/miarc.c @@ -0,0 +1,3654 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: miarc.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ +/* Author: Keith Packard and Bob Scheifler */ +/* Warning: this code is toxic, do not dally very long here. */ + +#ifdef _XOPEN_SOURCE +#include +#else +#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ +#include +#undef _XOPEN_SOURCE +#endif +#include "X.h" +#include "Xprotostr.h" +#include "misc.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mifpoly.h" +#include "mi.h" +#include "mifillarc.h" +#include "Xfuncproto.h" + +static double miDsin(), miDcos(), miDasin(), miDatan2(); +double cbrt( +#if NeedFunctionPrototypes + double +#endif +); + +#ifdef ICEILTEMPDECL +ICEILTEMPDECL +#endif + +/* + * some interesting sematic interpretation of the protocol: + * + * Self intersecting arcs (i.e. those spanning 360 degrees) + * never join with other arcs, and are drawn without caps + * (unless on/off dashed, in which case each dash segment + * is capped, except when the last segment meets the + * first segment, when no caps are drawn) + * + * double dash arcs are drawn in two parts, first the + * odd dashes (drawn in background) then the even dashes + * (drawn in foreground). This means that overlapping + * sections of foreground/background are drawn twice, + * first in background then in foreground. The double-draw + * occurs even when the function uses the destination values + * (e.g. xor mode). This is the same way the wide-line + * code works and should be "fixed". + * + */ + +#undef max +#undef min + +#if defined (__GNUC__) && defined (__STDC__) && !defined (__STRICT_ANSI__) +#define USE_INLINE +#endif + +#ifdef USE_INLINE +inline static const int max (const int x, const int y) +{ + return x>y? x:y; +} + +inline static const int min (const int x, const int y) +{ + return xy? x:y; +} + +static int +min (x, y) +{ + return xlineWidth; + int a0, a1, startAngle, endAngle; + miArcFacePtr temp; + + if (!l) + l = 1; + + if (tarc.width == 0 || tarc.height == 0) { + drawZeroArc (pDraw, pGC, &tarc, l, left, right); + return; + } + + if (pGC->miTranslate) { + tarc.x += pDraw->x; + tarc.y += pDraw->y; + } + + a0 = tarc.angle1; + a1 = tarc.angle2; + if (a1 > FULLCIRCLE) + a1 = FULLCIRCLE; + else if (a1 < -FULLCIRCLE) + a1 = -FULLCIRCLE; + if (a1 < 0) { + startAngle = a0 + a1; + endAngle = a0; + temp = right; + right = left; + left = temp; + } else { + startAngle = a0; + endAngle = a0 + a1; + } + /* + * bounds check the two angles + */ + if (startAngle < 0) + startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; + if (startAngle >= FULLCIRCLE) + startAngle = startAngle % FULLCIRCLE; + if (endAngle < 0) + endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; + if (endAngle > FULLCIRCLE) + endAngle = (endAngle-1) % FULLCIRCLE + 1; + if ((startAngle == endAngle) && a1) { + startAngle = 0; + endAngle = FULLCIRCLE; + } + + drawArc (&tarc, l, startAngle, endAngle, right, left); +} + +/* + +Three equations combine to describe the boundaries of the arc + +x^2/w^2 + y^2/h^2 = 1 ellipse itself +(X-x)^2 + (Y-y)^2 = r^2 circle at (x, y) on the ellipse +(Y-y) = (X-x)*w^2*y/(h^2*x) normal at (x, y) on the ellipse + +These lead to a quartic relating Y and y + +y^4 - (2Y)y^3 + (Y^2 + (h^4 - w^2*r^2)/(w^2 - h^2))y^2 + - (2Y*h^4/(w^2 - h^2))y + (Y^2*h^4)/(w^2 - h^2) = 0 + +The reducible cubic obtained from this quartic is + +z^3 - (3N)z^2 - 2V = 0 + +where + +N = (Y^2 + (h^4 - w^2*r^2/(w^2 - h^2)))/6 +V = w^2*r^2*Y^2*h^4/(4 *(w^2 - h^2)^2) + +Let + +t = z - N +p = -N^2 +q = -N^3 - V + +Then we get + +t^3 + 3pt + 2q = 0 + +The discriminant of this cubic is + +D = q^2 + p^3 + +When D > 0, a real root is obtained as + +z = N + cbrt(-q+sqrt(D)) + cbrt(-q-sqrt(D)) + +When D < 0, a real root is obtained as + +z = N - 2m*cos(acos(-q/m^3)/3) + +where + +m = sqrt(|p|) * sign(q) + +Given a real root Z of the cubic, the roots of the quartic are the roots +of the two quadratics + +y^2 + ((b+A)/2)y + (Z + (bZ - d)/A) = 0 + +where + +A = +/- sqrt(8Z + b^2 - 4c) +b, c, d are the cubic, quadratic, and linear coefficients of the quartic + +Some experimentation is then required to determine which solutions +correspond to the inner and outer boundaries. + +*/ + +typedef struct { + short lx, lw, rx, rw; +} miArcSpan; + +typedef struct { + miArcSpan *spans; + int count1, count2, k; + char top, bot, hole; +} miArcSpanData; + +typedef struct { + unsigned long lrustamp; + unsigned short lw; + unsigned short width, height; + miArcSpanData *spdata; +} arcCacheRec; + +#define CACHESIZE 25 + +static arcCacheRec arcCache[CACHESIZE]; +static unsigned long lrustamp; +static arcCacheRec *lastCacheHit = &arcCache[0]; +static RESTYPE cacheType; + +/* + * External so it can be called when low on memory. + * Call with a zero ID in that case. + */ +/*ARGSUSED*/ +int +miFreeArcCache (data, id) + pointer data; + XID id; +{ + int k; + arcCacheRec *cent; + + if (id) + cacheType = 0; + + for (k = CACHESIZE, cent = &arcCache[0]; --k >= 0; cent++) + { + if (cent->spdata) + { + cent->lrustamp = 0; + cent->lw = 0; + xfree(cent->spdata); + cent->spdata = NULL; + } + } + lrustamp = 0; + return Success; +} + +static void +miComputeCircleSpans(lw, parc, spdata) + int lw; + xArc *parc; + miArcSpanData *spdata; +{ + register miArcSpan *span; + int doinner; + register int x, y, e; + int xk, yk, xm, ym, dx, dy; + register int slw, inslw; + int inx, iny, ine; + int inxk, inyk, inxm, inym; + + doinner = -lw; + slw = parc->width - doinner; + y = parc->height >> 1; + dy = parc->height & 1; + dx = 1 - dy; + MIWIDEARCSETUP(x, y, dy, slw, e, xk, xm, yk, ym); + inslw = parc->width + doinner; + if (inslw > 0) + { + spdata->hole = spdata->top; + MIWIDEARCSETUP(inx, iny, dy, inslw, ine, inxk, inxm, inyk, inym); + } + else + { + spdata->hole = FALSE; + doinner = -y; + } + spdata->count1 = -doinner - spdata->top; + spdata->count2 = y + doinner; + span = spdata->spans; + while (y) + { + MIFILLARCSTEP(slw); + span->lx = dy - x; + if (++doinner <= 0) + { + span->lw = slw; + span->rx = 0; + span->rw = span->lx + slw; + } + else + { + MIFILLINARCSTEP(inslw); + span->lw = x - inx; + span->rx = dy - inx + inslw; + span->rw = inx - x + slw - inslw; + } + span++; + } + if (spdata->bot) + { + if (spdata->count2) + spdata->count2--; + else + { + if (lw > (int)parc->height) + span[-1].rx = span[-1].rw = -((lw - (int)parc->height) >> 1); + else + span[-1].rw = 0; + spdata->count1--; + } + } +} + +static void +miComputeEllipseSpans(lw, parc, spdata) + int lw; + xArc *parc; + miArcSpanData *spdata; +{ + register miArcSpan *span; + double w, h, r, xorg; + double Hs, Hf, WH, K, Vk, Nk, Fk, Vr, N, Nc, Z, rs; + double A, T, b, d, x, y, t, inx, outx, hepp, hepm; + int flip, solution; + + w = (double)parc->width / 2.0; + h = (double)parc->height / 2.0; + r = lw / 2.0; + rs = r * r; + Hs = h * h; + WH = w * w - Hs; + Nk = w * r; + Vk = (Nk * Hs) / (WH + WH); + Hf = Hs * Hs; + Nk = (Hf - Nk * Nk) / WH; + Fk = Hf / WH; + hepp = h + EPSILON; + hepm = h - EPSILON; + K = h + ((lw - 1) >> 1); + span = spdata->spans; + if (parc->width & 1) + xorg = .5; + else + xorg = 0.0; + if (spdata->top) + { + span->lx = 0; + span->lw = 1; + span++; + } + spdata->count1 = 0; + spdata->count2 = 0; + spdata->hole = (spdata->top && + (int)parc->height * lw <= (int)(parc->width * parc->width) && + lw < (int)parc->height); + for (; K > 0.0; K -= 1.0) + { + N = (K * K + Nk) / 6.0; + Nc = N * N * N; + Vr = Vk * K; + t = Nc + Vr * Vr; + d = Nc + t; + if (d < 0.0) { + d = Nc; + b = N; + if ( (b < 0.0) == (t < 0.0) ) + { + b = -b; + d = -d; + } + Z = N - 2.0 * b * cos(acos(-t / d) / 3.0); + if ( (Z < 0.0) == (Vr < 0.0) ) + flip = 2; + else + flip = 1; + } + else + { + d = Vr * sqrt(d); + Z = N + cbrt(t + d) + cbrt(t - d); + flip = 0; + } + A = sqrt((Z + Z) - Nk); + T = (Fk - Z) * K / A; + inx = 0.0; + solution = FALSE; + b = -A + K; + d = b * b - 4 * (Z + T); + if (d >= 0) + { + d = sqrt(d); + y = (b + d) / 2; + if ((y >= 0.0) && (y < hepp)) + { + solution = TRUE; + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + t = sqrt(rs - (t * t)); + if (flip == 2) + inx = x - t; + else + outx = x + t; + } + } + b = A + K; + d = b * b - 4 * (Z - T); + /* Because of the large magnitudes involved, we lose enough precision + * that sometimes we end up with a negative value near the axis, when + * it should be positive. This is a workaround. + */ + if (d < 0 && !solution) + d = 0.0; + if (d >= 0) { + d = sqrt(d); + y = (b + d) / 2; + if (y < hepp) + { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + inx = x - sqrt(rs - (t * t)); + } + y = (b - d) / 2; + if (y >= 0.0) + { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + t = sqrt(rs - (t * t)); + if (flip == 1) + inx = x - t; + else + outx = x + t; + } + } + span->lx = ICEIL(xorg - outx); + if (inx <= 0.0) + { + spdata->count1++; + span->lw = ICEIL(xorg + outx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = -ICEIL(xorg - inx); + } + else + { + spdata->count2++; + span->lw = ICEIL(xorg - inx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = ICEIL(xorg + outx) - span->rx; + } + span++; + } + if (spdata->bot) + { + outx = w + r; + if (r >= h && r <= w) + inx = 0.0; + else if (Nk < 0.0 && -Nk < Hs) + { + inx = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk); + if (inx > w - r) + inx = w - r; + } + else + inx = w - r; + span->lx = ICEIL(xorg - outx); + if (inx <= 0.0) + { + span->lw = ICEIL(xorg + outx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = -ICEIL(xorg - inx); + } + else + { + span->lw = ICEIL(xorg - inx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = ICEIL(xorg + outx) - span->rx; + } + } + if (spdata->hole) + { + span = &spdata->spans[spdata->count1]; + span->lw = -span->lx; + span->rx = 1; + span->rw = span->lw; + spdata->count1--; + spdata->count2++; + } +} + +static double +tailX(K, def, bounds, acc) + double K; + struct arc_def *def; + struct arc_bound *bounds; + struct accelerators *acc; +{ + double w, h, r; + double Hs, Hf, WH, Vk, Nk, Fk, Vr, N, Nc, Z, rs; + double A, T, b, d, x, y, t, hepp, hepm; + int flip, solution; + double xs[2]; + double *xp; + + w = def->w; + h = def->h; + r = def->l; + rs = r * r; + Hs = acc->h2; + WH = -acc->h2mw2; + Nk = def->w * r; + Vk = (Nk * Hs) / (WH + WH); + Hf = acc->h4; + Nk = (Hf - Nk * Nk) / WH; + if (K == 0.0) { + if (Nk < 0.0 && -Nk < Hs) { + xs[0] = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk); + xs[1] = w - r; + if (acc->left.valid && boundedLe(K, bounds->left) && + !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0) + return xs[1]; + if (acc->right.valid && boundedLe(K, bounds->right) && + !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0) + return xs[1]; + return xs[0]; + } + return w - r; + } + Fk = Hf / WH; + hepp = h + EPSILON; + hepm = h - EPSILON; + N = (K * K + Nk) / 6.0; + Nc = N * N * N; + Vr = Vk * K; + xp = xs; + xs[0] = 0.0; + t = Nc + Vr * Vr; + d = Nc + t; + if (d < 0.0) { + d = Nc; + b = N; + if ( (b < 0.0) == (t < 0.0) ) + { + b = -b; + d = -d; + } + Z = N - 2.0 * b * cos(acos(-t / d) / 3.0); + if ( (Z < 0.0) == (Vr < 0.0) ) + flip = 2; + else + flip = 1; + } + else + { + d = Vr * sqrt(d); + Z = N + cbrt(t + d) + cbrt(t - d); + flip = 0; + } + A = sqrt((Z + Z) - Nk); + T = (Fk - Z) * K / A; + solution = FALSE; + b = -A + K; + d = b * b - 4 * (Z + T); + if (d >= 0 && flip == 2) + { + d = sqrt(d); + y = (b + d) / 2; + if ((y >= 0.0) && (y < hepp)) + { + solution = TRUE; + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + t = sqrt(rs - (t * t)); + *xp++ = x - t; + } + } + b = A + K; + d = b * b - 4 * (Z - T); + /* Because of the large magnitudes involved, we lose enough precision + * that sometimes we end up with a negative value near the axis, when + * it should be positive. This is a workaround. + */ + if (d < 0 && !solution) + d = 0.0; + if (d >= 0) { + d = sqrt(d); + y = (b + d) / 2; + if (y < hepp) + { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + *xp++ = x - sqrt(rs - (t * t)); + } + y = (b - d) / 2; + if (y >= 0.0 && flip == 1) + { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + t = sqrt(rs - (t * t)); + *xp++ = x - t; + } + } + if (xp > &xs[1]) { + if (acc->left.valid && boundedLe(K, bounds->left) && + !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0) + return xs[1]; + if (acc->right.valid && boundedLe(K, bounds->right) && + !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0) + return xs[1]; + } + return xs[0]; +} + +static miArcSpanData * +miComputeWideEllipse(lw, parc, mustFree) + int lw; + register xArc *parc; + Bool *mustFree; +{ + register miArcSpanData *spdata; + register arcCacheRec *cent, *lruent; + register int k; + arcCacheRec fakeent; + + if (!lw) + lw = 1; + if (parc->height <= 1500) + { + *mustFree = FALSE; + cent = lastCacheHit; + if (cent->lw == lw && + cent->width == parc->width && cent->height == parc->height) + { + cent->lrustamp = ++lrustamp; + return cent->spdata; + } + lruent = &arcCache[0]; + for (k = CACHESIZE, cent = lruent; --k >= 0; cent++) + { + if (cent->lw == lw && + cent->width == parc->width && cent->height == parc->height) + { + cent->lrustamp = ++lrustamp; + lastCacheHit = cent; + return cent->spdata; + } + if (cent->lrustamp < lruent->lrustamp) + lruent = cent; + } + if (!cacheType) + { + cacheType = CreateNewResourceType(miFreeArcCache); + (void) AddResource(FakeClientID(0), cacheType, NULL); + } + } else { + lruent = &fakeent; + lruent->spdata = NULL; + *mustFree = TRUE; + } + k = (parc->height >> 1) + ((lw - 1) >> 1); + spdata = lruent->spdata; + if (!spdata || spdata->k != k) + { + if (spdata) + xfree(spdata); + spdata = (miArcSpanData *)xalloc(sizeof(miArcSpanData) + + sizeof(miArcSpan) * (k + 2)); + lruent->spdata = spdata; + if (!spdata) + { + lruent->lrustamp = 0; + lruent->lw = 0; + return spdata; + } + spdata->spans = (miArcSpan *)(spdata + 1); + spdata->k = k; + } + spdata->top = !(lw & 1) && !(parc->width & 1); + spdata->bot = !(parc->height & 1); + lruent->lrustamp = ++lrustamp; + lruent->lw = lw; + lruent->width = parc->width; + lruent->height = parc->height; + if (lruent != &fakeent) + lastCacheHit = lruent; + if (parc->width == parc->height) + miComputeCircleSpans(lw, parc, spdata); + else + miComputeEllipseSpans(lw, parc, spdata); + return spdata; +} + +static void +miFillWideEllipse(pDraw, pGC, parc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *parc; +{ + DDXPointPtr points; + register DDXPointPtr pts; + int *widths; + register int *wids; + miArcSpanData *spdata; + Bool mustFree; + register miArcSpan *span; + register int xorg, yorgu, yorgl; + register int n; + + yorgu = parc->height + pGC->lineWidth; + n = (sizeof(int) * 2) * yorgu; + widths = (int *)ALLOCATE_LOCAL(n + (sizeof(DDXPointRec) * 2) * yorgu); + if (!widths) + return; + points = (DDXPointPtr)((char *)widths + n); + spdata = miComputeWideEllipse((int)pGC->lineWidth, parc, &mustFree); + if (!spdata) + { + DEALLOCATE_LOCAL(widths); + return; + } + pts = points; + wids = widths; + span = spdata->spans; + xorg = parc->x + (parc->width >> 1); + yorgu = parc->y + (parc->height >> 1); + yorgl = yorgu + (parc->height & 1); + if (pGC->miTranslate) + { + xorg += pDraw->x; + yorgu += pDraw->y; + yorgl += pDraw->y; + } + yorgu -= spdata->k; + yorgl += spdata->k; + if (spdata->top) + { + pts->x = xorg; + pts->y = yorgu - 1; + pts++; + *wids++ = 1; + span++; + } + for (n = spdata->count1; --n >= 0; ) + { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts[1].x = pts[0].x; + pts[1].y = yorgl; + wids[1] = wids[0]; + yorgu++; + yorgl--; + pts += 2; + wids += 2; + span++; + } + if (spdata->hole) + { + pts[0].x = xorg; + pts[0].y = yorgl; + wids[0] = 1; + pts++; + wids++; + } + for (n = spdata->count2; --n >= 0; ) + { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts[1].x = xorg + span->rx; + pts[1].y = pts[0].y; + wids[1] = span->rw; + pts[2].x = pts[0].x; + pts[2].y = yorgl; + wids[2] = wids[0]; + pts[3].x = pts[1].x; + pts[3].y = pts[2].y; + wids[3] = wids[1]; + yorgu++; + yorgl--; + pts += 4; + wids += 4; + span++; + } + if (spdata->bot) + { + if (span->rw <= 0) + { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts++; + wids++; + } + else + { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts[1].x = xorg + span->rx; + pts[1].y = pts[0].y; + wids[1] = span->rw; + pts += 2; + wids += 2; + } + } + if (mustFree) + xfree(spdata); + (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + + DEALLOCATE_LOCAL(widths); +} + +/* + * miPolyArc strategy: + * + * If arc is zero width and solid, we don't have to worry about the rasterop + * or join styles. For wide solid circles, we use a fast integer algorithm. + * For wide solid ellipses, we use special case floating point code. + * Otherwise, we set up pDrawTo and pGCTo according to the rasterop, then + * draw using pGCTo and pDrawTo. If the raster-op was "tricky," that is, + * if it involves the destination, then we use PushPixels to move the bits + * from the scratch drawable to pDraw. (See the wide line code for a + * fuller explanation of this.) + */ + +void +miPolyArc(pDraw, pGC, narcs, parcs) + DrawablePtr pDraw; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + register int i; + xArc *parc; + int xMin, xMax, yMin, yMax; + int pixmapWidth, pixmapHeight; + int xOrg, yOrg; + int width; + Bool fTricky; + DrawablePtr pDrawTo; + CARD32 fg, bg; + GCPtr pGCTo; + miPolyArcPtr polyArcs; + int cap[2], join[2]; + int iphase; + int halfWidth; + + width = pGC->lineWidth; + if(width == 0 && pGC->lineStyle == LineSolid) + { + for(i = narcs, parc = parcs; --i >= 0; parc++) + miArcSegment( pDraw, pGC, *parc, + (miArcFacePtr) 0, (miArcFacePtr) 0 ); + fillSpans (pDraw, pGC); + } + else + { + if ((pGC->lineStyle == LineSolid) && narcs) + { + while (parcs->width && parcs->height && + (parcs->angle2 >= FULLCIRCLE || + parcs->angle2 <= -FULLCIRCLE)) + { + miFillWideEllipse(pDraw, pGC, parcs); + if (!--narcs) + return; + parcs++; + } + } + + /* Set up pDrawTo and pGCTo based on the rasterop */ + switch(pGC->alu) + { + case GXclear: /* 0 */ + case GXcopy: /* src */ + case GXcopyInverted: /* NOT src */ + case GXset: /* 1 */ + fTricky = FALSE; + pDrawTo = pDraw; + pGCTo = pGC; + break; + default: + fTricky = TRUE; + + /* find bounding box around arcs */ + xMin = yMin = MAXSHORT; + xMax = yMax = MINSHORT; + + for(i = narcs, parc = parcs; --i >= 0; parc++) + { + xMin = min (xMin, parc->x); + yMin = min (yMin, parc->y); + xMax = max (xMax, (parc->x + (int) parc->width)); + yMax = max (yMax, (parc->y + (int) parc->height)); + } + + /* expand box to deal with line widths */ + halfWidth = (width + 1)/2; + xMin -= halfWidth; + yMin -= halfWidth; + xMax += halfWidth; + yMax += halfWidth; + + /* compute pixmap size; limit it to size of drawable */ + xOrg = max(xMin, 0); + yOrg = max(yMin, 0); + pixmapWidth = min(xMax, pDraw->width) - xOrg; + pixmapHeight = min(yMax, pDraw->height) - yOrg; + + /* if nothing left, return */ + if ( (pixmapWidth <= 0) || (pixmapHeight <= 0) ) return; + + for(i = narcs, parc = parcs; --i >= 0; parc++) + { + parc->x -= xOrg; + parc->y -= yOrg; + } + if (pGC->miTranslate) + { + xOrg += pDraw->x; + yOrg += pDraw->y; + } + + /* set up scratch GC */ + + pGCTo = GetScratchGC(1, pDraw->pScreen); + if (!pGCTo) + return; + gcvals[GCValsFunction] = GXcopy; + gcvals[GCValsForeground] = 1; + gcvals[GCValsBackground] = 0; + gcvals[GCValsLineWidth] = pGC->lineWidth; + gcvals[GCValsCapStyle] = pGC->capStyle; + gcvals[GCValsJoinStyle] = pGC->joinStyle; + dixChangeGC(NullClient, pGCTo, GCValsMask, gcvals, NULL); + + /* allocate a 1 bit deep pixmap of the appropriate size, and + * validate it */ + pDrawTo = (DrawablePtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, pixmapWidth, pixmapHeight, 1); + if (!pDrawTo) + { + FreeScratchGC(pGCTo); + return; + } + ValidateGC(pDrawTo, pGCTo); + miClearDrawable(pDrawTo, pGCTo); + } + + fg = pGC->fgPixel; + bg = pGC->bgPixel; + if ((pGC->fillStyle == FillTiled) || + (pGC->fillStyle == FillOpaqueStippled)) + bg = fg; /* the protocol sez these don't cause color changes */ + + polyArcs = miComputeArcs (parcs, narcs, pGC); + + if (!polyArcs) + { + if (fTricky) { + (*pDraw->pScreen->DestroyPixmap) ((PixmapPtr)pDrawTo); + FreeScratchGC (pGCTo); + } + return; + } + + cap[0] = cap[1] = 0; + join[0] = join[1] = 0; + for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0); + iphase >= 0; + iphase--) + { + if (iphase == 1) { + dixChangeGC (NullClient, pGC, GCForeground, &bg, NULL); + ValidateGC (pDraw, pGC); + } else if (pGC->lineStyle == LineDoubleDash) { + dixChangeGC (NullClient, pGC, GCForeground, &fg, NULL); + ValidateGC (pDraw, pGC); + } + for (i = 0; i < polyArcs[iphase].narcs; i++) { + miArcDataPtr arcData; + + arcData = &polyArcs[iphase].arcs[i]; + miArcSegment(pDrawTo, pGCTo, arcData->arc, + &arcData->bounds[RIGHT_END], + &arcData->bounds[LEFT_END]); + if (polyArcs[iphase].arcs[i].render) { + fillSpans (pDrawTo, pGCTo); + /* + * don't cap self-joining arcs + */ + if (polyArcs[iphase].arcs[i].selfJoin && + cap[iphase] < polyArcs[iphase].arcs[i].cap) + cap[iphase]++; + while (cap[iphase] < polyArcs[iphase].arcs[i].cap) { + int arcIndex, end; + miArcDataPtr arcData0; + + arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex; + end = polyArcs[iphase].caps[cap[iphase]].end; + arcData0 = &polyArcs[iphase].arcs[arcIndex]; + miArcCap (pDrawTo, pGCTo, + &arcData0->bounds[end], end, + arcData0->arc.x, arcData0->arc.y, + (double) arcData0->arc.width / 2.0, + (double) arcData0->arc.height / 2.0); + ++cap[iphase]; + } + while (join[iphase] < polyArcs[iphase].arcs[i].join) { + int arcIndex0, arcIndex1, end0, end1; + int phase0, phase1; + miArcDataPtr arcData0, arcData1; + miArcJoinPtr joinp; + + joinp = &polyArcs[iphase].joins[join[iphase]]; + arcIndex0 = joinp->arcIndex0; + end0 = joinp->end0; + arcIndex1 = joinp->arcIndex1; + end1 = joinp->end1; + phase0 = joinp->phase0; + phase1 = joinp->phase1; + arcData0 = &polyArcs[phase0].arcs[arcIndex0]; + arcData1 = &polyArcs[phase1].arcs[arcIndex1]; + miArcJoin (pDrawTo, pGCTo, + &arcData0->bounds[end0], + &arcData1->bounds[end1], + arcData0->arc.x, arcData0->arc.y, + (double) arcData0->arc.width / 2.0, + (double) arcData0->arc.height / 2.0, + arcData1->arc.x, arcData1->arc.y, + (double) arcData1->arc.width / 2.0, + (double) arcData1->arc.height / 2.0); + ++join[iphase]; + } + if (fTricky) { + if (pGC->serialNumber != pDraw->serialNumber) + ValidateGC (pDraw, pGC); + (*pGC->ops->PushPixels) (pGC, (PixmapPtr)pDrawTo, + pDraw, pixmapWidth, pixmapHeight, xOrg, yOrg); + miClearDrawable ((DrawablePtr) pDrawTo, pGCTo); + } + } + } + } + miFreeArcs(polyArcs, pGC); + + if(fTricky) + { + (*pGCTo->pScreen->DestroyPixmap)((PixmapPtr)pDrawTo); + FreeScratchGC(pGCTo); + } + } +} + +static double +angleBetween (center, point1, point2) + SppPointRec center, point1, point2; +{ + double a1, a2, a; + + /* + * reflect from X coordinates back to ellipse + * coordinates -- y increasing upwards + */ + a1 = miDatan2 (- (point1.y - center.y), point1.x - center.x); + a2 = miDatan2 (- (point2.y - center.y), point2.x - center.x); + a = a2 - a1; + if (a <= -180.0) + a += 360.0; + else if (a > 180.0) + a -= 360.0; + return a; +} + +static void +translateBounds (b, x, y, fx, fy) +miArcFacePtr b; +int x, y; +double fx, fy; +{ + fx += x; + fy += y; + b->clock.x -= fx; + b->clock.y -= fy; + b->center.x -= fx; + b->center.y -= fy; + b->counterClock.x -= fx; + b->counterClock.y -= fy; +} + +static void +miArcJoin (pDraw, pGC, pLeft, pRight, + xOrgLeft, yOrgLeft, xFtransLeft, yFtransLeft, + xOrgRight, yOrgRight, xFtransRight, yFtransRight) + DrawablePtr pDraw; + GCPtr pGC; + miArcFacePtr pRight, pLeft; + int xOrgRight, yOrgRight; + double xFtransRight, yFtransRight; + int xOrgLeft, yOrgLeft; + double xFtransLeft, yFtransLeft; +{ + SppPointRec center, corner, otherCorner; + SppPointRec poly[5], e; + SppPointPtr pArcPts; + int cpt; + SppArcRec arc; + miArcFaceRec Right, Left; + int polyLen; + int xOrg, yOrg; + double xFtrans, yFtrans; + double a; + double ae, ac2, ec2, bc2, de; + double width; + + xOrg = (xOrgRight + xOrgLeft) / 2; + yOrg = (yOrgRight + yOrgLeft) / 2; + xFtrans = (xFtransLeft + xFtransRight) / 2; + yFtrans = (yFtransLeft + yFtransRight) / 2; + Right = *pRight; + translateBounds (&Right, xOrg - xOrgRight, yOrg - yOrgRight, + xFtrans - xFtransRight, yFtrans - yFtransRight); + Left = *pLeft; + translateBounds (&Left, xOrg - xOrgLeft, yOrg - yOrgLeft, + xFtrans - xFtransLeft, yFtrans - yFtransLeft); + pRight = &Right; + pLeft = &Left; + + if (pRight->clock.x == pLeft->counterClock.x && + pRight->clock.y == pLeft->counterClock.y) + return; + center = pRight->center; + if (0 <= (a = angleBetween (center, pRight->clock, pLeft->counterClock)) + && a <= 180.0) + { + corner = pRight->clock; + otherCorner = pLeft->counterClock; + } else { + a = angleBetween (center, pLeft->clock, pRight->counterClock); + corner = pLeft->clock; + otherCorner = pRight->counterClock; + } + switch (pGC->joinStyle) { + case JoinRound: + width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1); + + arc.x = center.x - width/2; + arc.y = center.y - width/2; + arc.width = width; + arc.height = width; + arc.angle1 = -miDatan2 (corner.y - center.y, corner.x - center.x); + arc.angle2 = a; + pArcPts = (SppPointPtr) xalloc (3 * sizeof (SppPointRec)); + if (!pArcPts) + return; + pArcPts[0].x = otherCorner.x; + pArcPts[0].y = otherCorner.y; + pArcPts[1].x = center.x; + pArcPts[1].y = center.y; + pArcPts[2].x = corner.x; + pArcPts[2].y = corner.y; + if( (cpt = miGetArcPts(&arc, 3, &pArcPts)) ) + { + /* by drawing with miFillSppPoly and setting the endpoints of the arc + * to be the corners, we assure that the cap will meet up with the + * rest of the line */ + miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, yFtrans); + } + xfree(pArcPts); + return; + case JoinMiter: + /* + * don't miter arcs with less than 11 degrees between them + */ + if (a < 169.0) { + poly[0] = corner; + poly[1] = center; + poly[2] = otherCorner; + bc2 = (corner.x - otherCorner.x) * (corner.x - otherCorner.x) + + (corner.y - otherCorner.y) * (corner.y - otherCorner.y); + ec2 = bc2 / 4; + ac2 = (corner.x - center.x) * (corner.x - center.x) + + (corner.y - center.y) * (corner.y - center.y); + ae = sqrt (ac2 - ec2); + de = ec2 / ae; + e.x = (corner.x + otherCorner.x) / 2; + e.y = (corner.y + otherCorner.y) / 2; + poly[3].x = e.x + de * (e.x - center.x) / ae; + poly[3].y = e.y + de * (e.y - center.y) / ae; + poly[4] = corner; + polyLen = 5; + break; + } + case JoinBevel: + poly[0] = corner; + poly[1] = center; + poly[2] = otherCorner; + poly[3] = corner; + polyLen = 4; + break; + } + miFillSppPoly (pDraw, pGC, polyLen, poly, xOrg, yOrg, xFtrans, yFtrans); +} + +/*ARGSUSED*/ +static void +miArcCap (pDraw, pGC, pFace, end, xOrg, yOrg, xFtrans, yFtrans) + DrawablePtr pDraw; + GCPtr pGC; + miArcFacePtr pFace; + int end; + int xOrg, yOrg; + double xFtrans, yFtrans; +{ + SppPointRec corner, otherCorner, center, endPoint, poly[5]; + + corner = pFace->clock; + otherCorner = pFace->counterClock; + center = pFace->center; + switch (pGC->capStyle) { + case CapProjecting: + poly[0].x = otherCorner.x; + poly[0].y = otherCorner.y; + poly[1].x = corner.x; + poly[1].y = corner.y; + poly[2].x = corner.x - + (center.y - corner.y); + poly[2].y = corner.y + + (center.x - corner.x); + poly[3].x = otherCorner.x - + (otherCorner.y - center.y); + poly[3].y = otherCorner.y + + (otherCorner.x - center.x); + poly[4].x = otherCorner.x; + poly[4].y = otherCorner.y; + miFillSppPoly (pDraw, pGC, 5, poly, xOrg, yOrg, xFtrans, yFtrans); + break; + case CapRound: + /* + * miRoundCap just needs these to be unequal. + */ + endPoint = center; + endPoint.x = endPoint.x + 100; + miRoundCap (pDraw, pGC, center, endPoint, corner, otherCorner, 0, + -xOrg, -yOrg, xFtrans, yFtrans); + break; + } +} + +/* MIROUNDCAP -- a private helper function + * Put Rounded cap on end. pCenter is the center of this end of the line + * pEnd is the center of the other end of the line. pCorner is one of the + * two corners at this end of the line. + * NOTE: pOtherCorner must be counter-clockwise from pCorner. + */ +/*ARGSUSED*/ +static void +miRoundCap(pDraw, pGC, pCenter, pEnd, pCorner, pOtherCorner, fLineEnd, + xOrg, yOrg, xFtrans, yFtrans) + DrawablePtr pDraw; + GCPtr pGC; + SppPointRec pCenter, pEnd; + SppPointRec pCorner, pOtherCorner; + int fLineEnd, xOrg, yOrg; + double xFtrans, yFtrans; +{ + int cpt; + double width; + double miDatan2 (); + SppArcRec arc; + SppPointPtr pArcPts; + + width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1); + + arc.x = pCenter.x - width/2; + arc.y = pCenter.y - width/2; + arc.width = width; + arc.height = width; + arc.angle1 = -miDatan2 (pCorner.y - pCenter.y, pCorner.x - pCenter.x); + if(PTISEQUAL(pCenter, pEnd)) + arc.angle2 = - 180.0; + else { + arc.angle2 = -miDatan2 (pOtherCorner.y - pCenter.y, pOtherCorner.x - pCenter.x) - arc.angle1; + if (arc.angle2 < 0) + arc.angle2 += 360.0; + } + pArcPts = (SppPointPtr) NULL; + if( (cpt = miGetArcPts(&arc, 0, &pArcPts)) ) + { + /* by drawing with miFillSppPoly and setting the endpoints of the arc + * to be the corners, we assure that the cap will meet up with the + * rest of the line */ + miFillSppPoly(pDraw, pGC, cpt, pArcPts, -xOrg, -yOrg, xFtrans, yFtrans); + } + xfree(pArcPts); +} + +/* + * To avoid inaccuracy at the cardinal points, use trig functions + * which are exact for those angles + */ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +# define Dsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0))) +# define Dcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0))) +# define mod(a,b) ((a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) + +static double +miDcos (a) +double a; +{ + int i; + + if (floor (a/90) == a/90) { + i = (int) (a/90.0); + switch (mod (i, 4)) { + case 0: return 1; + case 1: return 0; + case 2: return -1; + case 3: return 0; + } + } + return cos (a * M_PI / 180.0); +} + +static double +miDsin (a) +double a; +{ + int i; + + if (floor (a/90) == a/90) { + i = (int) (a/90.0); + switch (mod (i, 4)) { + case 0: return 0; + case 1: return 1; + case 2: return 0; + case 3: return -1; + } + } + return sin (a * M_PI / 180.0); +} + +static double +miDasin (v) +double v; +{ + if (v == 0) + return 0.0; + if (v == 1.0) + return 90.0; + if (v == -1.0) + return -90.0; + return asin(v) * (180.0 / M_PI); +} + +static double +miDatan2 (dy, dx) +double dy, dx; +{ + if (dy == 0) { + if (dx >= 0) + return 0.0; + return 180.0; + } else if (dx == 0) { + if (dy > 0) + return 90.0; + return -90.0; + } else if (Fabs (dy) == Fabs (dx)) { + if (dy > 0) { + if (dx > 0) + return 45.0; + return 135.0; + } else { + if (dx > 0) + return 315.0; + return 225.0; + } + } else { + return atan2 (dy, dx) * (180.0 / M_PI); + } +} + +/* MIGETARCPTS -- Converts an arc into a set of line segments -- a helper + * routine for filled arc and line (round cap) code. + * Returns the number of points in the arc. Note that it takes a pointer + * to a pointer to where it should put the points and an index (cpt). + * This procedure allocates the space necessary to fit the arc points. + * Sometimes it's convenient for those points to be at the end of an existing + * array. (For example, if we want to leave a spare point to make sectors + * instead of segments.) So we pass in the Xalloc()ed chunk that contains the + * array and an index saying where we should start stashing the points. + * If there isn't an array already, we just pass in a null pointer and + * count on Xrealloc() to handle the null pointer correctly. + */ +static int +miGetArcPts(parc, cpt, ppPts) + SppArcPtr parc; /* points to an arc */ + int cpt; /* number of points already in arc list */ + SppPointPtr *ppPts; /* pointer to pointer to arc-list -- modified */ +{ + double st, /* Start Theta, start angle */ + et, /* End Theta, offset from start theta */ + dt, /* Delta Theta, angle to sweep ellipse */ + cdt, /* Cos Delta Theta, actually 2 cos(dt) */ + x0, y0, /* the recurrence formula needs two points to start */ + x1, y1, + x2, y2, /* this will be the new point generated */ + xc, yc; /* the center point */ + int count, i; + SppPointPtr poly; + DDXPointRec last; /* last point on integer boundaries */ + + /* The spec says that positive angles indicate counterclockwise motion. + * Given our coordinate system (with 0,0 in the upper left corner), + * the screen appears flipped in Y. The easiest fix is to negate the + * angles given */ + + st = - parc->angle1; + + et = - parc->angle2; + + /* Try to get a delta theta that is within 1/2 pixel. Then adjust it + * so that it divides evenly into the total. + * I'm just using cdt 'cause I'm lazy. + */ + cdt = parc->width; + if (parc->height > cdt) + cdt = parc->height; + cdt /= 2.0; + if(cdt <= 0) + return 0; + if (cdt < 1.0) + cdt = 1.0; + dt = miDasin ( 1.0 / cdt ); /* minimum step necessary */ + count = et/dt; + count = abs(count) + 1; + dt = et/count; + count++; + + cdt = 2 * miDcos(dt); + if (!(poly = (SppPointPtr) xrealloc((pointer)*ppPts, + (cpt + count) * sizeof(SppPointRec)))) + return(0); + *ppPts = poly; + + xc = parc->width/2.0; /* store half width and half height */ + yc = parc->height/2.0; + + x0 = xc * miDcos(st); + y0 = yc * miDsin(st); + x1 = xc * miDcos(st + dt); + y1 = yc * miDsin(st + dt); + xc += parc->x; /* by adding initial point, these become */ + yc += parc->y; /* the center point */ + + poly[cpt].x = (xc + x0); + poly[cpt].y = (yc + y0); + last.x = ROUNDTOINT( poly[cpt + 1].x = (xc + x1) ); + last.y = ROUNDTOINT( poly[cpt + 1].y = (yc + y1) ); + + for(i = 2; i < count; i++) + { + x2 = cdt * x1 - x0; + y2 = cdt * y1 - y0; + + poly[cpt + i].x = (xc + x2); + poly[cpt + i].y = (yc + y2); + + x0 = x1; y0 = y1; + x1 = x2; y1 = y2; + } + /* adjust the last point */ + if (abs(parc->angle2) >= 360.0) + poly[cpt +i -1] = poly[0]; + else { + poly[cpt +i -1].x = (miDcos(st + et) * parc->width/2.0 + xc); + poly[cpt +i -1].y = (miDsin(st + et) * parc->height/2.0 + yc); + } + + return(count); +} + +struct arcData { + double x0, y0, x1, y1; + int selfJoin; +}; + +# define ADD_REALLOC_STEP 20 + +static void +addCap (capsp, ncapsp, sizep, end, arcIndex) + miArcCapPtr *capsp; + int *ncapsp, *sizep; + int end, arcIndex; +{ + int newsize; + miArcCapPtr cap; + + if (*ncapsp == *sizep) + { + newsize = *sizep + ADD_REALLOC_STEP; + cap = (miArcCapPtr) xrealloc (*capsp, + newsize * sizeof (**capsp)); + if (!cap) + return; + *sizep = newsize; + *capsp = cap; + } + cap = &(*capsp)[*ncapsp]; + cap->end = end; + cap->arcIndex = arcIndex; + ++*ncapsp; +} + +static void +addJoin (joinsp, njoinsp, sizep, end0, index0, phase0, end1, index1, phase1) + miArcJoinPtr *joinsp; + int *njoinsp, *sizep; + int end0, index0, phase0, end1, index1, phase1; +{ + int newsize; + miArcJoinPtr join; + + if (*njoinsp == *sizep) + { + newsize = *sizep + ADD_REALLOC_STEP; + join = (miArcJoinPtr) xrealloc (*joinsp, + newsize * sizeof (**joinsp)); + if (!join) + return; + *sizep = newsize; + *joinsp = join; + } + join = &(*joinsp)[*njoinsp]; + join->end0 = end0; + join->arcIndex0 = index0; + join->phase0 = phase0; + join->end1 = end1; + join->arcIndex1 = index1; + join->phase1 = phase1; + ++*njoinsp; +} + +static miArcDataPtr +addArc (arcsp, narcsp, sizep, xarc) + miArcDataPtr *arcsp; + int *narcsp, *sizep; + xArc *xarc; +{ + int newsize; + miArcDataPtr arc; + + if (*narcsp == *sizep) + { + newsize = *sizep + ADD_REALLOC_STEP; + arc = (miArcDataPtr) xrealloc (*arcsp, + newsize * sizeof (**arcsp)); + if (!arc) + return (miArcDataPtr)NULL; + *sizep = newsize; + *arcsp = arc; + } + arc = &(*arcsp)[*narcsp]; + arc->arc = *xarc; + ++*narcsp; + return arc; +} + +static void +miFreeArcs(arcs, pGC) + miPolyArcPtr arcs; + GCPtr pGC; +{ + int iphase; + + for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0); + iphase >= 0; + iphase--) + { + if (arcs[iphase].narcs > 0) + xfree(arcs[iphase].arcs); + if (arcs[iphase].njoins > 0) + xfree(arcs[iphase].joins); + if (arcs[iphase].ncaps > 0) + xfree(arcs[iphase].caps); + } + xfree(arcs); +} + +/* + * map angles to radial distance. This only deals with the first quadrant + */ + +/* + * a polygonal approximation to the arc for computing arc lengths + */ + +# define DASH_MAP_SIZE 91 + +# define dashIndexToAngle(di) ((((double) (di)) * 90.0) / ((double) DASH_MAP_SIZE - 1)) +# define xAngleToDashIndex(xa) ((((long) (xa)) * (DASH_MAP_SIZE - 1)) / (90 * 64)) +# define dashIndexToXAngle(di) ((((long) (di)) * (90 * 64)) / (DASH_MAP_SIZE - 1)) +# define dashXAngleStep (((double) (90 * 64)) / ((double) (DASH_MAP_SIZE - 1))) + +typedef struct { + double map[DASH_MAP_SIZE]; +} dashMap; + +static void +computeDashMap (arcp, map) + xArc *arcp; + dashMap *map; +{ + int di; + double a, x, y, prevx, prevy, dist; + + for (di = 0; di < DASH_MAP_SIZE; di++) { + a = dashIndexToAngle (di); + x = ((double) arcp->width / 2.0) * miDcos (a); + y = ((double) arcp->height / 2.0) * miDsin (a); + if (di == 0) { + map->map[di] = 0.0; + } else { + dist = hypot (x - prevx, y - prevy); + map->map[di] = map->map[di - 1] + dist; + } + prevx = x; + prevy = y; + } +} + +typedef enum {HORIZONTAL, VERTICAL, OTHER} arcTypes; + +/* this routine is a bit gory */ + +static miPolyArcPtr +miComputeArcs (parcs, narcs, pGC) + xArc *parcs; + int narcs; + GCPtr pGC; +{ + int isDashed, isDoubleDash; + int dashOffset; + miPolyArcPtr arcs; + int start, i, j, k, nexti, nextk; + int joinSize[2]; + int capSize[2]; + int arcSize[2]; + int angle2; + double a0, a1; + struct arcData *data; + miArcDataPtr arc; + xArc xarc; + int iphase, prevphase, joinphase; + int arcsJoin; + int selfJoin; + + int iDash, dashRemaining; + int iDashStart, dashRemainingStart, iphaseStart; + int startAngle, spanAngle, endAngle, backwards; + int prevDashAngle, dashAngle; + dashMap map; + + isDashed = !(pGC->lineStyle == LineSolid); + isDoubleDash = (pGC->lineStyle == LineDoubleDash); + dashOffset = pGC->dashOffset; + + data = (struct arcData *) ALLOCATE_LOCAL (narcs * sizeof (struct arcData)); + if (!data) + return (miPolyArcPtr)NULL; + arcs = (miPolyArcPtr) xalloc (sizeof (*arcs) * (isDoubleDash ? 2 : 1)); + if (!arcs) + { + DEALLOCATE_LOCAL(data); + return (miPolyArcPtr)NULL; + } + for (i = 0; i < narcs; i++) { + a0 = todeg (parcs[i].angle1); + angle2 = parcs[i].angle2; + if (angle2 > FULLCIRCLE) + angle2 = FULLCIRCLE; + else if (angle2 < -FULLCIRCLE) + angle2 = -FULLCIRCLE; + data[i].selfJoin = angle2 == FULLCIRCLE || angle2 == -FULLCIRCLE; + a1 = todeg (parcs[i].angle1 + angle2); + data[i].x0 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a0)); + data[i].y0 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a0)); + data[i].x1 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a1)); + data[i].y1 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a1)); + } + + for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) { + arcs[iphase].njoins = 0; + arcs[iphase].joins = 0; + joinSize[iphase] = 0; + + arcs[iphase].ncaps = 0; + arcs[iphase].caps = 0; + capSize[iphase] = 0; + + arcs[iphase].narcs = 0; + arcs[iphase].arcs = 0; + arcSize[iphase] = 0; + } + + iphase = 0; + if (isDashed) { + iDash = 0; + dashRemaining = pGC->dash[0]; + while (dashOffset > 0) { + if (dashOffset >= dashRemaining) { + dashOffset -= dashRemaining; + iphase = iphase ? 0 : 1; + iDash++; + if (iDash == pGC->numInDashList) + iDash = 0; + dashRemaining = pGC->dash[iDash]; + } else { + dashRemaining -= dashOffset; + dashOffset = 0; + } + } + iDashStart = iDash; + dashRemainingStart = dashRemaining; + } + iphaseStart = iphase; + + for (i = narcs - 1; i >= 0; i--) { + j = i + 1; + if (j == narcs) + j = 0; + if (data[i].selfJoin || i == j || + (UNEQUAL (data[i].x1, data[j].x0) || + UNEQUAL (data[i].y1, data[j].y0))) + { + if (iphase == 0 || isDoubleDash) + addCap (&arcs[iphase].caps, &arcs[iphase].ncaps, + &capSize[iphase], RIGHT_END, 0); + break; + } + } + start = i + 1; + if (start == narcs) + start = 0; + i = start; + for (;;) { + j = i + 1; + if (j == narcs) + j = 0; + nexti = i+1; + if (nexti == narcs) + nexti = 0; + if (isDashed) { + /* + ** deal with dashed arcs. Use special rules for certain 0 area arcs. + ** Presumably, the other 0 area arcs still aren't done right. + */ + arcTypes arcType = OTHER; + CARD16 thisLength; + + if (parcs[i].height == 0 + && (parcs[i].angle1 % FULLCIRCLE) == 0x2d00 + && parcs[i].angle2 == 0x2d00) + arcType = HORIZONTAL; + else if (parcs[i].width == 0 + && (parcs[i].angle1 % FULLCIRCLE) == 0x1680 + && parcs[i].angle2 == 0x2d00) + arcType = VERTICAL; + if (arcType == OTHER) { + /* + * precompute an approximation map + */ + computeDashMap (&parcs[i], &map); + /* + * compute each individual dash segment using the path + * length function + */ + startAngle = parcs[i].angle1; + spanAngle = parcs[i].angle2; + if (spanAngle > FULLCIRCLE) + spanAngle = FULLCIRCLE; + else if (spanAngle < -FULLCIRCLE) + spanAngle = -FULLCIRCLE; + if (startAngle < 0) + startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; + if (startAngle >= FULLCIRCLE) + startAngle = startAngle % FULLCIRCLE; + endAngle = startAngle + spanAngle; + backwards = spanAngle < 0; + } else { + xarc = parcs[i]; + if (arcType == VERTICAL) { + xarc.angle1 = 0x1680; + startAngle = parcs[i].y; + endAngle = startAngle + parcs[i].height; + } else { + xarc.angle1 = 0x2d00; + startAngle = parcs[i].x; + endAngle = startAngle + parcs[i].width; + } + } + dashAngle = startAngle; + selfJoin = data[i].selfJoin && + (iphase == 0 || isDoubleDash); + /* + * add dashed arcs to each bucket + */ + arc = 0; + while (dashAngle != endAngle) { + prevDashAngle = dashAngle; + if (arcType == OTHER) { + dashAngle = computeAngleFromPath (prevDashAngle, endAngle, + &map, &dashRemaining, backwards); + /* avoid troubles with huge arcs and small dashes */ + if (dashAngle == prevDashAngle) { + if (backwards) + dashAngle--; + else + dashAngle++; + } + } else { + thisLength = (dashAngle + dashRemaining <= endAngle) ? + dashRemaining : endAngle - dashAngle; + if (arcType == VERTICAL) { + xarc.y = dashAngle; + xarc.height = thisLength; + } else { + xarc.x = dashAngle; + xarc.width = thisLength; + } + dashAngle += thisLength; + dashRemaining -= thisLength; + } + if (iphase == 0 || isDoubleDash) { + if (arcType == OTHER) { + xarc = parcs[i]; + spanAngle = prevDashAngle; + if (spanAngle < 0) + spanAngle = FULLCIRCLE - (-spanAngle) % FULLCIRCLE; + if (spanAngle >= FULLCIRCLE) + spanAngle = spanAngle % FULLCIRCLE; + xarc.angle1 = spanAngle; + spanAngle = dashAngle - prevDashAngle; + if (backwards) { + if (dashAngle > prevDashAngle) + spanAngle = - FULLCIRCLE + spanAngle; + } else { + if (dashAngle < prevDashAngle) + spanAngle = FULLCIRCLE + spanAngle; + } + if (spanAngle > FULLCIRCLE) + spanAngle = FULLCIRCLE; + if (spanAngle < -FULLCIRCLE) + spanAngle = -FULLCIRCLE; + xarc.angle2 = spanAngle; + } + arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs, + &arcSize[iphase], &xarc); + if (!arc) + goto arcfail; + /* + * cap each end of an on/off dash + */ + if (!isDoubleDash) { + if (prevDashAngle != startAngle) { + addCap (&arcs[iphase].caps, + &arcs[iphase].ncaps, + &capSize[iphase], RIGHT_END, + arc - arcs[iphase].arcs); + + } + if (dashAngle != endAngle) { + addCap (&arcs[iphase].caps, + &arcs[iphase].ncaps, + &capSize[iphase], LEFT_END, + arc - arcs[iphase].arcs); + } + } + arc->cap = arcs[iphase].ncaps; + arc->join = arcs[iphase].njoins; + arc->render = 0; + arc->selfJoin = 0; + if (dashAngle == endAngle) + arc->selfJoin = selfJoin; + } + prevphase = iphase; + if (dashRemaining <= 0) { + ++iDash; + if (iDash == pGC->numInDashList) + iDash = 0; + iphase = iphase ? 0:1; + dashRemaining = pGC->dash[iDash]; + } + } + /* + * make sure a place exists for the position data when + * drawing a zero-length arc + */ + if (startAngle == endAngle) { + prevphase = iphase; + if (!isDoubleDash && iphase == 1) + prevphase = 0; + arc = addArc (&arcs[prevphase].arcs, &arcs[prevphase].narcs, + &arcSize[prevphase], &parcs[i]); + if (!arc) + goto arcfail; + arc->join = arcs[prevphase].njoins; + arc->cap = arcs[prevphase].ncaps; + arc->selfJoin = data[i].selfJoin; + } + } else { + arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs, + &arcSize[iphase], &parcs[i]); + if (!arc) + goto arcfail; + arc->join = arcs[iphase].njoins; + arc->cap = arcs[iphase].ncaps; + arc->selfJoin = data[i].selfJoin; + prevphase = iphase; + } + if (prevphase == 0 || isDoubleDash) + k = arcs[prevphase].narcs - 1; + if (iphase == 0 || isDoubleDash) + nextk = arcs[iphase].narcs; + if (nexti == start) { + nextk = 0; + if (isDashed) { + iDash = iDashStart; + iphase = iphaseStart; + dashRemaining = dashRemainingStart; + } + } + arcsJoin = narcs > 1 && i != j && + ISEQUAL (data[i].x1, data[j].x0) && + ISEQUAL (data[i].y1, data[j].y0) && + !data[i].selfJoin && !data[j].selfJoin; + if (arc) + { + if (arcsJoin) + arc->render = 0; + else + arc->render = 1; + } + if (arcsJoin && + (prevphase == 0 || isDoubleDash) && + (iphase == 0 || isDoubleDash)) + { + joinphase = iphase; + if (isDoubleDash) { + if (nexti == start) + joinphase = iphaseStart; + /* + * if the join is right at the dash, + * draw the join in foreground + * This is because the foreground + * arcs are computed second, the results + * of which are needed to draw the join + */ + if (joinphase != prevphase) + joinphase = 0; + } + if (joinphase == 0 || isDoubleDash) { + addJoin (&arcs[joinphase].joins, + &arcs[joinphase].njoins, + &joinSize[joinphase], + LEFT_END, k, prevphase, + RIGHT_END, nextk, iphase); + arc->join = arcs[prevphase].njoins; + } + } else { + /* + * cap the left end of this arc + * unless it joins itself + */ + if ((prevphase == 0 || isDoubleDash) && + !arc->selfJoin) + { + addCap (&arcs[prevphase].caps, &arcs[prevphase].ncaps, + &capSize[prevphase], LEFT_END, k); + arc->cap = arcs[prevphase].ncaps; + } + if (isDashed && !arcsJoin) { + iDash = iDashStart; + iphase = iphaseStart; + dashRemaining = dashRemainingStart; + } + nextk = arcs[iphase].narcs; + if (nexti == start) { + nextk = 0; + iDash = iDashStart; + iphase = iphaseStart; + dashRemaining = dashRemainingStart; + } + /* + * cap the right end of the next arc. If the + * next arc is actually the first arc, only + * cap it if it joins with this arc. This + * case will occur when the final dash segment + * of an on/off dash is off. Of course, this + * cap will be drawn at a strange time, but that + * hardly matters... + */ + if ((iphase == 0 || isDoubleDash) && + (nexti != start || (arcsJoin && isDashed))) + addCap (&arcs[iphase].caps, &arcs[iphase].ncaps, + &capSize[iphase], RIGHT_END, nextk); + } + i = nexti; + if (i == start) + break; + } + /* + * make sure the last section is rendered + */ + for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) + if (arcs[iphase].narcs > 0) { + arcs[iphase].arcs[arcs[iphase].narcs-1].render = 1; + arcs[iphase].arcs[arcs[iphase].narcs-1].join = + arcs[iphase].njoins; + arcs[iphase].arcs[arcs[iphase].narcs-1].cap = + arcs[iphase].ncaps; + } + DEALLOCATE_LOCAL(data); + return arcs; +arcfail: + miFreeArcs(arcs, pGC); + DEALLOCATE_LOCAL(data); + return (miPolyArcPtr)NULL; +} + +static double +angleToLength (angle, map) + int angle; + dashMap *map; +{ + double len, excesslen, sidelen = map->map[DASH_MAP_SIZE - 1], totallen; + int di; + int excess; + Bool oddSide = FALSE; + + totallen = 0; + if (angle >= 0) { + while (angle >= 90 * 64) { + angle -= 90 * 64; + totallen += sidelen; + oddSide = !oddSide; + } + } else { + while (angle < 0) { + angle += 90 * 64; + totallen -= sidelen; + oddSide = !oddSide; + } + } + if (oddSide) + angle = 90 * 64 - angle; + + di = xAngleToDashIndex (angle); + excess = angle - dashIndexToXAngle (di); + + len = map->map[di]; + /* + * linearly interpolate between this point and the next + */ + if (excess > 0) { + excesslen = (map->map[di + 1] - map->map[di]) * + ((double) excess) / dashXAngleStep; + len += excesslen; + } + if (oddSide) + totallen += (sidelen - len); + else + totallen += len; + return totallen; +} + +/* + * len is along the arc, but may be more than one rotation + */ + +static int +lengthToAngle (len, map) + double len; + dashMap *map; +{ + double sidelen = map->map[DASH_MAP_SIZE - 1]; + int angle, angleexcess; + Bool oddSide = FALSE; + int a0, a1, a; + + angle = 0; + /* + * step around the ellipse, subtracting sidelens and + * adding 90 degrees. oddSide will tell if the + * map should be interpolated in reverse + */ + if (len >= 0) { + if (sidelen == 0) + return 2 * FULLCIRCLE; /* infinity */ + while (len >= sidelen) { + angle += 90 * 64; + len -= sidelen; + oddSide = !oddSide; + } + } else { + if (sidelen == 0) + return -2 * FULLCIRCLE; /* infinity */ + while (len < 0) { + angle -= 90 * 64; + len += sidelen; + oddSide = !oddSide; + } + } + if (oddSide) + len = sidelen - len; + a0 = 0; + a1 = DASH_MAP_SIZE - 1; + /* + * binary search for the closest pre-computed length + */ + while (a1 - a0 > 1) { + a = (a0 + a1) / 2; + if (len > map->map[a]) + a0 = a; + else + a1 = a; + } + angleexcess = dashIndexToXAngle (a0); + /* + * linearly interpolate to the next point + */ + angleexcess += (len - map->map[a0]) / + (map->map[a0+1] - map->map[a0]) * dashXAngleStep; + if (oddSide) + angle += (90 * 64) - angleexcess; + else + angle += angleexcess; + return angle; +} + +/* + * compute the angle of an ellipse which cooresponds to + * the given path length. Note that the correct solution + * to this problem is an eliptic integral, we'll punt and + * approximate (it's only for dashes anyway). This + * approximation uses a polygon. + * + * The remaining portion of len is stored in *lenp - + * this will be negative if the arc extends beyond + * len and positive if len extends beyond the arc. + */ + +static int +computeAngleFromPath (startAngle, endAngle, map, lenp, backwards) + int startAngle, endAngle; /* normalized absolute angles in *64 degrees */ + dashMap *map; + int *lenp; + int backwards; +{ + int a0, a1, a; + double len0; + int len; + + a0 = startAngle; + a1 = endAngle; + len = *lenp; + if (backwards) { + /* + * flip the problem around to always be + * forwards + */ + a0 = FULLCIRCLE - a0; + a1 = FULLCIRCLE - a1; + } + if (a1 < a0) + a1 += FULLCIRCLE; + len0 = angleToLength (a0, map); + a = lengthToAngle (len0 + len, map); + if (a > a1) { + a = a1; + len -= angleToLength (a1, map) - len0; + } else + len = 0; + if (backwards) + a = FULLCIRCLE - a; + *lenp = len; + return a; +} + +/* + * scan convert wide arcs. + */ + +/* + * draw zero width/height arcs + */ + +static void +drawZeroArc (pDraw, pGC, tarc, lw, left, right) + DrawablePtr pDraw; + GCPtr pGC; + xArc *tarc; + int lw; + miArcFacePtr right, left; +{ + double x0, y0, x1, y1, w, h, x, y; + double xmax, ymax, xmin, ymin; + int a0, a1; + double a, startAngle, endAngle; + double l, lx, ly; + + l = lw / 2.0; + a0 = tarc->angle1; + a1 = tarc->angle2; + if (a1 > FULLCIRCLE) + a1 = FULLCIRCLE; + else if (a1 < -FULLCIRCLE) + a1 = -FULLCIRCLE; + w = (double)tarc->width / 2.0; + h = (double)tarc->height / 2.0; + /* + * play in X coordinates right away + */ + startAngle = - ((double) a0 / 64.0); + endAngle = - ((double) (a0 + a1) / 64.0); + + xmax = -w; + xmin = w; + ymax = -h; + ymin = h; + a = startAngle; + for (;;) + { + x = w * miDcos(a); + y = h * miDsin(a); + if (a == startAngle) + { + x0 = x; + y0 = y; + } + if (a == endAngle) + { + x1 = x; + y1 = y; + } + if (x > xmax) + xmax = x; + if (x < xmin) + xmin = x; + if (y > ymax) + ymax = y; + if (y < ymin) + ymin = y; + if (a == endAngle) + break; + if (a1 < 0) /* clockwise */ + { + if (floor (a / 90.0) == floor (endAngle / 90.0)) + a = endAngle; + else + a = 90 * (floor (a/90.0) + 1); + } + else + { + if (ceil (a / 90.0) == ceil (endAngle / 90.0)) + a = endAngle; + else + a = 90 * (ceil (a/90.0) - 1); + } + } + lx = ly = l; + if ((x1 - x0) + (y1 - y0) < 0) + lx = ly = -l; + if (h) + { + ly = 0.0; + lx = -lx; + } + else + lx = 0.0; + if (right) + { + right->center.x = x0; + right->center.y = y0; + right->clock.x = x0 - lx; + right->clock.y = y0 - ly; + right->counterClock.x = x0 + lx; + right->counterClock.y = y0 + ly; + } + if (left) + { + left->center.x = x1; + left->center.y = y1; + left->clock.x = x1 + lx; + left->clock.y = y1 + ly; + left->counterClock.x = x1 - lx; + left->counterClock.y = y1 - ly; + } + + x0 = xmin; + x1 = xmax; + y0 = ymin; + y1 = ymax; + if (ymin != y1) { + xmin = -l; + xmax = l; + } else { + ymin = -l; + ymax = l; + } + if (xmax != xmin && ymax != ymin) { + int minx, maxx, miny, maxy; + xRectangle rect; + + minx = ICEIL (xmin + w) + tarc->x; + maxx = ICEIL (xmax + w) + tarc->x; + miny = ICEIL (ymin + h) + tarc->y; + maxy = ICEIL (ymax + h) + tarc->y; + rect.x = minx; + rect.y = miny; + rect.width = maxx - minx; + rect.height = maxy - miny; + (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect); + } +} + +/* + * this computes the ellipse y value associated with the + * bottom of the tail. + */ + +static void +tailEllipseY (def, acc) + struct arc_def *def; + struct accelerators *acc; +{ + double t; + + acc->tail_y = 0.0; + if (def->w == def->h) + return; + t = def->l * def->w; + if (def->w > def->h) { + if (t < acc->h2) + return; + } else { + if (t > acc->h2) + return; + } + t = 2.0 * def->h * t; + t = (CUBED_ROOT_4 * acc->h2 - cbrt(t * t)) / acc->h2mw2; + if (t > 0.0) + acc->tail_y = def->h / CUBED_ROOT_2 * sqrt(t); +} + +/* + * inverse functions -- compute edge coordinates + * from the ellipse + */ + +static double +outerXfromXY (x, y, def, acc) + double x, y; + struct arc_def *def; + struct accelerators *acc; +{ + return x + (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); +} + +static double +outerYfromXY (x, y, def, acc) + double x, y; + struct arc_def *def; + struct accelerators *acc; +{ + return y + (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); +} + +static double +innerXfromXY (x, y, def, acc) + double x, y; + struct arc_def *def; + struct accelerators *acc; +{ + return x - (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); +} + +static double +innerYfromXY (x, y, def, acc) + double x, y; + struct arc_def *def; + struct accelerators *acc; +{ + return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); +} + +static double +innerYfromY (y, def, acc) + double y; + struct arc_def *def; + struct accelerators *acc; +{ + double x; + + x = (def->w / def->h) * sqrt (acc->h2 - y*y); + + return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); +} + +static void +computeLine (x1, y1, x2, y2, line) + double x1, y1, x2, y2; + struct line *line; +{ + if (y1 == y2) + line->valid = 0; + else { + line->m = (x1 - x2) / (y1 - y2); + line->b = x1 - y1 * line->m; + line->valid = 1; + } +} + +/* + * compute various accelerators for an ellipse. These + * are simply values that are used repeatedly in + * the computations + */ + +static void +computeAcc (tarc, lw, def, acc) + xArc *tarc; + int lw; + struct arc_def *def; + struct accelerators *acc; +{ + def->w = ((double) tarc->width) / 2.0; + def->h = ((double) tarc->height) / 2.0; + def->l = ((double) lw) / 2.0; + acc->h2 = def->h * def->h; + acc->w2 = def->w * def->w; + acc->h4 = acc->h2 * acc->h2; + acc->w4 = acc->w2 * acc->w2; + acc->h2l = acc->h2 * def->l; + acc->w2l = acc->w2 * def->l; + acc->h2mw2 = acc->h2 - acc->w2; + acc->fromIntX = (tarc->width & 1) ? 0.5 : 0.0; + acc->fromIntY = (tarc->height & 1) ? 0.5 : 0.0; + acc->xorg = tarc->x + (tarc->width >> 1); + acc->yorgu = tarc->y + (tarc->height >> 1); + acc->yorgl = acc->yorgu + (tarc->height & 1); + tailEllipseY (def, acc); +} + +/* + * compute y value bounds of various portions of the arc, + * the outer edge, the ellipse and the inner edge. + */ + +static void +computeBound (def, bound, acc, right, left) + struct arc_def *def; + struct arc_bound *bound; + struct accelerators *acc; + miArcFacePtr right, left; +{ + double t; + double innerTaily; + double tail_y; + struct bound innerx, outerx; + struct bound ellipsex; + + bound->ellipse.min = Dsin (def->a0) * def->h; + bound->ellipse.max = Dsin (def->a1) * def->h; + if (def->a0 == 45 && def->w == def->h) + ellipsex.min = bound->ellipse.min; + else + ellipsex.min = Dcos (def->a0) * def->w; + if (def->a1 == 45 && def->w == def->h) + ellipsex.max = bound->ellipse.max; + else + ellipsex.max = Dcos (def->a1) * def->w; + bound->outer.min = outerYfromXY (ellipsex.min, bound->ellipse.min, def, acc); + bound->outer.max = outerYfromXY (ellipsex.max, bound->ellipse.max, def, acc); + bound->inner.min = innerYfromXY (ellipsex.min, bound->ellipse.min, def, acc); + bound->inner.max = innerYfromXY (ellipsex.max, bound->ellipse.max, def, acc); + + outerx.min = outerXfromXY (ellipsex.min, bound->ellipse.min, def, acc); + outerx.max = outerXfromXY (ellipsex.max, bound->ellipse.max, def, acc); + innerx.min = innerXfromXY (ellipsex.min, bound->ellipse.min, def, acc); + innerx.max = innerXfromXY (ellipsex.max, bound->ellipse.max, def, acc); + + /* + * save the line end points for the + * cap code to use. Careful here, these are + * in cartesean coordinates (y increasing upwards) + * while the cap code uses inverted coordinates + * (y increasing downwards) + */ + + if (right) { + right->counterClock.y = bound->outer.min; + right->counterClock.x = outerx.min; + right->center.y = bound->ellipse.min; + right->center.x = ellipsex.min; + right->clock.y = bound->inner.min; + right->clock.x = innerx.min; + } + + if (left) { + left->clock.y = bound->outer.max; + left->clock.x = outerx.max; + left->center.y = bound->ellipse.max; + left->center.x = ellipsex.max; + left->counterClock.y = bound->inner.max; + left->counterClock.x = innerx.max; + } + + bound->left.min = bound->inner.max; + bound->left.max = bound->outer.max; + bound->right.min = bound->inner.min; + bound->right.max = bound->outer.min; + + computeLine (innerx.min, bound->inner.min, outerx.min, bound->outer.min, + &acc->right); + computeLine (innerx.max, bound->inner.max, outerx.max, bound->outer.max, + &acc->left); + + if (bound->inner.min > bound->inner.max) { + t = bound->inner.min; + bound->inner.min = bound->inner.max; + bound->inner.max = t; + } + tail_y = acc->tail_y; + if (tail_y > bound->ellipse.max) + tail_y = bound->ellipse.max; + else if (tail_y < bound->ellipse.min) + tail_y = bound->ellipse.min; + innerTaily = innerYfromY (tail_y, def, acc); + if (bound->inner.min > innerTaily) + bound->inner.min = innerTaily; + if (bound->inner.max < innerTaily) + bound->inner.max = innerTaily; + bound->inneri.min = ICEIL(bound->inner.min - acc->fromIntY); + bound->inneri.max = floor(bound->inner.max - acc->fromIntY); + bound->outeri.min = ICEIL(bound->outer.min - acc->fromIntY); + bound->outeri.max = floor(bound->outer.max - acc->fromIntY); +} + +/* + * this section computes the x value of the span at y + * intersected with the specified face of the ellipse. + * + * this is the min/max X value over the set of normal + * lines to the entire ellipse, the equation of the + * normal lines is: + * + * ellipse_x h^2 h^2 + * x = ------------ y + ellipse_x (1 - --- ) + * ellipse_y w^2 w^2 + * + * compute the derivative with-respect-to ellipse_y and solve + * for zero: + * + * (w^2 - h^2) ellipse_y^3 + h^4 y + * 0 = - ---------------------------------- + * h w ellipse_y^2 sqrt (h^2 - ellipse_y^2) + * + * ( h^4 y ) + * ellipse_y = ( ---------- ) ^ (1/3) + * ( (h^2 - w^2) ) + * + * The other two solutions to the equation are imaginary. + * + * This gives the position on the ellipse which generates + * the normal with the largest/smallest x intersection point. + * + * Now compute the second derivative to check whether + * the intersection is a minimum or maximum: + * + * h (y0^3 (w^2 - h^2) + h^2 y (3y0^2 - 2h^2)) + * - ------------------------------------------- + * w y0^3 (sqrt (h^2 - y^2)) ^ 3 + * + * as we only care about the sign, + * + * - (y0^3 (w^2 - h^2) + h^2 y (3y0^2 - 2h^2)) + * + * or (to use accelerators), + * + * y0^3 (h^2 - w^2) - h^2 y (3y0^2 - 2h^2) + * + */ + +/* + * computes the position on the ellipse whose normal line + * intersects the given scan line maximally + */ + +static double +hookEllipseY (scan_y, bound, acc, left) + double scan_y; + struct arc_bound *bound; + struct accelerators *acc; + int left; +{ + double ret; + + if (acc->h2mw2 == 0) { + if ( (scan_y > 0 && !left) || (scan_y < 0 && left) ) + return bound->ellipse.min; + return bound->ellipse.max; + } + ret = (acc->h4 * scan_y) / (acc->h2mw2); + if (ret >= 0) + return cbrt (ret); + else + return -cbrt (-ret); +} + +/* + * computes the X value of the intersection of the + * given scan line with the right side of the lower hook + */ + +static double +hookX (scan_y, def, bound, acc, left) + double scan_y; + struct arc_def *def; + struct arc_bound *bound; + struct accelerators *acc; + int left; +{ + double ellipse_y, x; + double maxMin; + + if (def->w != def->h) { + ellipse_y = hookEllipseY (scan_y, bound, acc, left); + if (boundedLe (ellipse_y, bound->ellipse)) { + /* + * compute the value of the second + * derivative + */ + maxMin = ellipse_y*ellipse_y*ellipse_y * acc->h2mw2 - + acc->h2 * scan_y * (3 * ellipse_y*ellipse_y - 2*acc->h2); + if ((left && maxMin > 0) || (!left && maxMin < 0)) { + if (ellipse_y == 0) + return def->w + left ? -def->l : def->l; + x = (acc->h2 * scan_y - ellipse_y * acc->h2mw2) * + sqrt (acc->h2 - ellipse_y * ellipse_y) / + (def->h * def->w * ellipse_y); + return x; + } + } + } + if (left) { + if (acc->left.valid && boundedLe (scan_y, bound->left)) { + x = intersectLine (scan_y, acc->left); + } else { + if (acc->right.valid) + x = intersectLine (scan_y, acc->right); + else + x = def->w - def->l; + } + } else { + if (acc->right.valid && boundedLe (scan_y, bound->right)) { + x = intersectLine (scan_y, acc->right); + } else { + if (acc->left.valid) + x = intersectLine (scan_y, acc->left); + else + x = def->w - def->l; + } + } + return x; +} + +/* + * generate the set of spans with + * the given y coordinate + */ + +static void +arcSpan (y, lx, lw, rx, rw, def, bounds, acc, mask) + int y; + int lx; + int lw; + int rx; + int rw; + struct arc_def *def; + struct arc_bound *bounds; + struct accelerators *acc; + int mask; +{ + int linx, loutx, rinx, routx; + double x, altx; + + if (boundedLe (y, bounds->inneri)) { + linx = -(lx + lw); + rinx = rx; + } else { + /* + * intersection with left face + */ + x = hookX (y + acc->fromIntY, def, bounds, acc, 1); + if (acc->right.valid && + boundedLe (y + acc->fromIntY, bounds->right)) + { + altx = intersectLine (y + acc->fromIntY, acc->right); + if (altx < x) + x = altx; + } + linx = -ICEIL(acc->fromIntX - x); + rinx = ICEIL(acc->fromIntX + x); + } + if (boundedLe (y, bounds->outeri)) { + loutx = -lx; + routx = rx + rw; + } else { + /* + * intersection with right face + */ + x = hookX (y + acc->fromIntY, def, bounds, acc, 0); + if (acc->left.valid && + boundedLe (y + acc->fromIntY, bounds->left)) + { + altx = x; + x = intersectLine (y + acc->fromIntY, acc->left); + if (x < altx) + x = altx; + } + loutx = -ICEIL(acc->fromIntX - x); + routx = ICEIL(acc->fromIntX + x); + } + if (routx > rinx) { + if (mask & 1) + newFinalSpan (acc->yorgu - y, + acc->xorg + rinx, acc->xorg + routx); + if (mask & 8) + newFinalSpan (acc->yorgl + y, + acc->xorg + rinx, acc->xorg + routx); + } + if (loutx > linx) { + if (mask & 2) + newFinalSpan (acc->yorgu - y, + acc->xorg - loutx, acc->xorg - linx); + if (mask & 4) + newFinalSpan (acc->yorgl + y, + acc->xorg - loutx, acc->xorg - linx); + } +} + +static void +arcSpan0 (lx, lw, rx, rw, def, bounds, acc, mask) + int lx; + int lw; + int rx; + int rw; + struct arc_def *def; + struct arc_bound *bounds; + struct accelerators *acc; + int mask; +{ + double x; + + if (boundedLe (0, bounds->inneri) && + acc->left.valid && boundedLe (0, bounds->left) && + acc->left.b > 0) + { + x = def->w - def->l; + if (acc->left.b < x) + x = acc->left.b; + lw = ICEIL(acc->fromIntX - x) - lx; + rw += rx; + rx = ICEIL(acc->fromIntX + x); + rw -= rx; + } + arcSpan (0, lx, lw, rx, rw, def, bounds, acc, mask); +} + +static void +tailSpan (y, lw, rw, def, bounds, acc, mask) + int y; + int lw; + int rw; + struct arc_def *def; + struct arc_bound *bounds; + struct accelerators *acc; + int mask; +{ + double yy, xalt, x, lx, rx; + int n; + + if (boundedLe(y, bounds->outeri)) + arcSpan (y, 0, lw, -rw, rw, def, bounds, acc, mask); + else if (def->w != def->h) { + yy = y + acc->fromIntY; + x = tailX(yy, def, bounds, acc); + if (yy == 0.0 && x == -rw - acc->fromIntX) + return; + if (acc->right.valid && boundedLe (yy, bounds->right)) { + rx = x; + lx = -x; + xalt = intersectLine (yy, acc->right); + if (xalt >= -rw - acc->fromIntX && xalt <= rx) + rx = xalt; + n = ICEIL(acc->fromIntX + lx); + if (lw > n) { + if (mask & 2) + newFinalSpan (acc->yorgu - y, + acc->xorg + n, acc->xorg + lw); + if (mask & 4) + newFinalSpan (acc->yorgl + y, + acc->xorg + n, acc->xorg + lw); + } + n = ICEIL(acc->fromIntX + rx); + if (n > -rw) { + if (mask & 1) + newFinalSpan (acc->yorgu - y, + acc->xorg - rw, acc->xorg + n); + if (mask & 8) + newFinalSpan (acc->yorgl + y, + acc->xorg - rw, acc->xorg + n); + } + } + arcSpan (y, + ICEIL(acc->fromIntX - x), 0, + ICEIL(acc->fromIntX + x), 0, + def, bounds, acc, mask); + } +} + +/* + * create whole arcs out of pieces. This code is + * very bad. + */ + +static struct finalSpan **finalSpans = NULL; +static int finalMiny = 0, finalMaxy = -1; +static int finalSize = 0; + +static int nspans = 0; /* total spans, not just y coords */ + +struct finalSpan { + struct finalSpan *next; + int min, max; /* x values */ +}; + +static struct finalSpan *freeFinalSpans, *tmpFinalSpan; + +# define allocFinalSpan() (freeFinalSpans ?\ + ((tmpFinalSpan = freeFinalSpans), \ + (freeFinalSpans = freeFinalSpans->next), \ + (tmpFinalSpan->next = 0), \ + tmpFinalSpan) : \ + realAllocSpan ()) + +# define SPAN_CHUNK_SIZE 128 + +struct finalSpanChunk { + struct finalSpan data[SPAN_CHUNK_SIZE]; + struct finalSpanChunk *next; +}; + +static struct finalSpanChunk *chunks; + +struct finalSpan * +realAllocSpan () +{ + register struct finalSpanChunk *newChunk; + register struct finalSpan *span; + register int i; + + newChunk = (struct finalSpanChunk *) xalloc (sizeof (struct finalSpanChunk)); + if (!newChunk) + return (struct finalSpan *) NULL; + newChunk->next = chunks; + chunks = newChunk; + freeFinalSpans = span = newChunk->data + 1; + for (i = 1; i < SPAN_CHUNK_SIZE-1; i++) { + span->next = span+1; + span++; + } + span->next = 0; + span = newChunk->data; + span->next = 0; + return span; +} + +static void +disposeFinalSpans () +{ + struct finalSpanChunk *chunk, *next; + + for (chunk = chunks; chunk; chunk = next) { + next = chunk->next; + xfree (chunk); + } + chunks = 0; + freeFinalSpans = 0; + xfree(finalSpans); + finalSpans = 0; +} + +static void +fillSpans (pDrawable, pGC) + DrawablePtr pDrawable; + GCPtr pGC; +{ + register struct finalSpan *span; + register DDXPointPtr xSpan; + register int *xWidth; + register int i; + register struct finalSpan **f; + register int spany; + DDXPointPtr xSpans; + int *xWidths; + + if (nspans == 0) + return; + xSpan = xSpans = (DDXPointPtr) xalloc (nspans * sizeof (DDXPointRec)); + xWidth = xWidths = (int *) xalloc (nspans * sizeof (int)); + if (xSpans && xWidths) + { + i = 0; + f = finalSpans; + for (spany = finalMiny; spany <= finalMaxy; spany++, f++) { + for (span = *f; span; span=span->next) { + if (span->max <= span->min) + continue; + xSpan->x = span->min; + xSpan->y = spany; + ++xSpan; + *xWidth++ = span->max - span->min; + ++i; + } + } + (*pGC->ops->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, TRUE); + } + disposeFinalSpans (); + xfree (xSpans); + xfree (xWidths); + finalMiny = 0; + finalMaxy = -1; + finalSize = 0; + nspans = 0; +} + +# define SPAN_REALLOC 100 + +# define findSpan(y) ((finalMiny <= (y) && (y) <= finalMaxy) ? \ + &finalSpans[(y) - finalMiny] : \ + realFindSpan (y)) + +static struct finalSpan ** +realFindSpan (y) + int y; +{ + struct finalSpan **newSpans; + int newSize, newMiny, newMaxy; + int change; + int i; + + if (y < finalMiny || y > finalMaxy) { + if (!finalSize) { + finalMiny = y; + finalMaxy = y - 1; + } + if (y < finalMiny) + change = finalMiny - y; + else + change = y - finalMaxy; + if (change >= SPAN_REALLOC) + change += SPAN_REALLOC; + else + change = SPAN_REALLOC; + newSize = finalSize + change; + newSpans = (struct finalSpan **) xalloc + (newSize * sizeof (struct finalSpan *)); + if (!newSpans) + return (struct finalSpan **)NULL; + newMiny = finalMiny; + newMaxy = finalMaxy; + if (y < finalMiny) + newMiny = finalMiny - change; + else + newMaxy = finalMaxy + change; + if (finalSpans) { + memmove(((char *) newSpans) + (finalMiny-newMiny) * sizeof (struct finalSpan *), + (char *) finalSpans, + finalSize * sizeof (struct finalSpan *)); + xfree (finalSpans); + } + if ((i = finalMiny - newMiny) > 0) + bzero ((char *)newSpans, i * sizeof (struct finalSpan *)); + if ((i = newMaxy - finalMaxy) > 0) + bzero ((char *)(newSpans + newSize - i), + i * sizeof (struct finalSpan *)); + finalSpans = newSpans; + finalMaxy = newMaxy; + finalMiny = newMiny; + finalSize = newSize; + } + return &finalSpans[y - finalMiny]; +} + +static void +newFinalSpan (y, xmin, xmax) + int y; + register int xmin, xmax; +{ + register struct finalSpan *x; + register struct finalSpan **f; + struct finalSpan *oldx; + struct finalSpan *prev; + + f = findSpan (y); + if (!f) + return; + oldx = 0; + for (;;) { + prev = 0; + for (x = *f; x; x=x->next) { + if (x == oldx) { + prev = x; + continue; + } + if (x->min <= xmax && xmin <= x->max) { + if (oldx) { + oldx->min = min (x->min, xmin); + oldx->max = max (x->max, xmax); + if (prev) + prev->next = x->next; + else + *f = x->next; + --nspans; + } else { + x->min = min (x->min, xmin); + x->max = max (x->max, xmax); + oldx = x; + } + xmin = oldx->min; + xmax = oldx->max; + break; + } + prev = x; + } + if (!x) + break; + } + if (!oldx) { + x = allocFinalSpan (); + if (x) + { + x->min = xmin; + x->max = xmax; + x->next = *f; + *f = x; + ++nspans; + } + } +} + +static void +mirrorSppPoint (quadrant, sppPoint) + int quadrant; + SppPointPtr sppPoint; +{ + switch (quadrant) { + case 0: + break; + case 1: + sppPoint->x = -sppPoint->x; + break; + case 2: + sppPoint->x = -sppPoint->x; + sppPoint->y = -sppPoint->y; + break; + case 3: + sppPoint->y = -sppPoint->y; + break; + } + /* + * and translate to X coordinate system + */ + sppPoint->y = -sppPoint->y; +} + +/* + * split an arc into pieces which are scan-converted + * in the first-quadrant and mirrored into position. + * This is necessary as the scan-conversion code can + * only deal with arcs completely contained in the + * first quadrant. + */ + +static void +drawArc (tarc, l, a0, a1, right, left) + xArc *tarc; + int l, a0, a1; + miArcFacePtr right, left; /* save end line points */ +{ + struct arc_def def; + struct accelerators acc; + int startq, endq, curq; + int rightq, leftq, righta, lefta; + miArcFacePtr passRight, passLeft; + int q0, q1, mask; + struct band { + int a0, a1; + int mask; + } band[5], sweep[20]; + int bandno, sweepno; + int i, j; + int flipRight = 0, flipLeft = 0; + int copyEnd = 0; + miArcSpanData *spdata; + Bool mustFree; + + spdata = miComputeWideEllipse(l, tarc, &mustFree); + if (!spdata) + return; + + if (a1 < a0) + a1 += 360 * 64; + startq = a0 / (90 * 64); + if (a0 == a1) + endq = startq; + else + endq = (a1-1) / (90 * 64); + bandno = 0; + curq = startq; + rightq = -1; + for (;;) { + switch (curq) { + case 0: + if (a0 > 90 * 64) + q0 = 0; + else + q0 = a0; + if (a1 < 360 * 64) + q1 = min (a1, 90 * 64); + else + q1 = 90 * 64; + if (curq == startq && a0 == q0 && rightq < 0) { + righta = q0; + rightq = curq; + } + if (curq == endq && a1 == q1) { + lefta = q1; + leftq = curq; + } + break; + case 1: + if (a1 < 90 * 64) + q0 = 0; + else + q0 = 180 * 64 - min (a1, 180 * 64); + if (a0 > 180 * 64) + q1 = 90 * 64; + else + q1 = 180 * 64 - max (a0, 90 * 64); + if (curq == startq && 180 * 64 - a0 == q1) { + righta = q1; + rightq = curq; + } + if (curq == endq && 180 * 64 - a1 == q0) { + lefta = q0; + leftq = curq; + } + break; + case 2: + if (a0 > 270 * 64) + q0 = 0; + else + q0 = max (a0, 180 * 64) - 180 * 64; + if (a1 < 180 * 64) + q1 = 90 * 64; + else + q1 = min (a1, 270 * 64) - 180 * 64; + if (curq == startq && a0 - 180*64 == q0) { + righta = q0; + rightq = curq; + } + if (curq == endq && a1 - 180 * 64 == q1) { + lefta = q1; + leftq = curq; + } + break; + case 3: + if (a1 < 270 * 64) + q0 = 0; + else + q0 = 360 * 64 - min (a1, 360 * 64); + q1 = 360 * 64 - max (a0, 270 * 64); + if (curq == startq && 360 * 64 - a0 == q1) { + righta = q1; + rightq = curq; + } + if (curq == endq && 360 * 64 - a1 == q0) { + lefta = q0; + leftq = curq; + } + break; + } + band[bandno].a0 = q0; + band[bandno].a1 = q1; + band[bandno].mask = 1 << curq; + bandno++; + if (curq == endq) + break; + curq++; + if (curq == 4) { + a0 = 0; + a1 -= 360 * 64; + curq = 0; + endq -= 4; + } + } + sweepno = 0; + for (;;) { + q0 = 90 * 64; + mask = 0; + /* + * find left-most point + */ + for (i = 0; i < bandno; i++) + if (band[i].a0 <= q0) { + q0 = band[i].a0; + q1 = band[i].a1; + mask = band[i].mask; + } + if (!mask) + break; + /* + * locate next point of change + */ + for (i = 0; i < bandno; i++) + if (!(mask & band[i].mask)) { + if (band[i].a0 == q0) { + if (band[i].a1 < q1) + q1 = band[i].a1; + mask |= band[i].mask; + } else if (band[i].a0 < q1) + q1 = band[i].a0; + } + /* + * create a new sweep + */ + sweep[sweepno].a0 = q0; + sweep[sweepno].a1 = q1; + sweep[sweepno].mask = mask; + sweepno++; + /* + * subtract the sweep from the affected bands + */ + for (i = 0; i < bandno; i++) + if (band[i].a0 == q0) { + band[i].a0 = q1; + /* + * check if this band is empty + */ + if (band[i].a0 == band[i].a1) + band[i].a1 = band[i].a0 = 90 * 64 + 1; + } + } + computeAcc (tarc, l, &def, &acc); + for (j = 0; j < sweepno; j++) { + mask = sweep[j].mask; + passRight = passLeft = 0; + if (mask & (1 << rightq)) { + if (sweep[j].a0 == righta) + passRight = right; + else if (sweep[j].a1 == righta) { + passLeft = right; + flipRight = 1; + } + } + if (mask & (1 << leftq)) { + if (sweep[j].a1 == lefta) + { + if (passLeft) + copyEnd = 1; + passLeft = left; + } + else if (sweep[j].a0 == lefta) { + if (passRight) + copyEnd = 1; + passRight = left; + flipLeft = 1; + } + } + drawQuadrant (&def, &acc, sweep[j].a0, sweep[j].a1, mask, + passRight, passLeft, spdata); + } + /* + * when copyEnd is set, both ends of the arc were computed + * at the same time; drawQuadrant only takes one end though, + * so the left end will be the only one holding the data. Copy + * it from there. + */ + if (copyEnd) + *right = *left; + /* + * mirror the coordinates generated for the + * faces of the arc + */ + if (right) { + mirrorSppPoint (rightq, &right->clock); + mirrorSppPoint (rightq, &right->center); + mirrorSppPoint (rightq, &right->counterClock); + if (flipRight) { + SppPointRec temp; + + temp = right->clock; + right->clock = right->counterClock; + right->counterClock = temp; + } + } + if (left) { + mirrorSppPoint (leftq, &left->counterClock); + mirrorSppPoint (leftq, &left->center); + mirrorSppPoint (leftq, &left->clock); + if (flipLeft) { + SppPointRec temp; + + temp = left->clock; + left->clock = left->counterClock; + left->counterClock = temp; + } + } + if (mustFree) + xfree(spdata); +} + +static void +drawQuadrant (def, acc, a0, a1, mask, right, left, spdata) + struct arc_def *def; + struct accelerators *acc; + int a0, a1; + int mask; + miArcFacePtr right, left; + miArcSpanData *spdata; +{ + struct arc_bound bound; + double yy, x, xalt; + int y, miny, maxy; + int n; + miArcSpan *span; + + def->a0 = ((double) a0) / 64.0; + def->a1 = ((double) a1) / 64.0; + computeBound (def, &bound, acc, right, left); + yy = bound.inner.min; + if (bound.outer.min < yy) + yy = bound.outer.min; + miny = ICEIL(yy - acc->fromIntY); + yy = bound.inner.max; + if (bound.outer.max > yy) + yy = bound.outer.max; + maxy = floor(yy - acc->fromIntY); + y = spdata->k; + span = spdata->spans; + if (spdata->top) + { + if (a1 == 90 * 64 && (mask & 1)) + newFinalSpan (acc->yorgu - y - 1, acc->xorg, acc->xorg + 1); + span++; + } + for (n = spdata->count1; --n >= 0; ) + { + if (y < miny) + return; + if (y <= maxy) { + arcSpan (y, + span->lx, -span->lx, 0, span->lx + span->lw, + def, &bound, acc, mask); + if (span->rw + span->rx) + tailSpan (y, -span->rw, -span->rx, def, &bound, acc, mask); + } + y--; + span++; + } + if (y < miny) + return; + if (spdata->hole) + { + if (y <= maxy) + arcSpan (y, 0, 0, 0, 1, def, &bound, acc, mask & 0xc); + } + for (n = spdata->count2; --n >= 0; ) + { + if (y < miny) + return; + if (y <= maxy) + arcSpan (y, span->lx, span->lw, span->rx, span->rw, + def, &bound, acc, mask); + y--; + span++; + } + if (spdata->bot && miny <= y && y <= maxy) + { + n = mask; + if (y == miny) + n &= 0xc; + if (span->rw <= 0) { + arcSpan0 (span->lx, -span->lx, 0, span->lx + span->lw, + def, &bound, acc, n); + if (span->rw + span->rx) + tailSpan (y, -span->rw, -span->rx, def, &bound, acc, n); + } + else + arcSpan0 (span->lx, span->lw, span->rx, span->rw, + def, &bound, acc, n); + y--; + } + while (y >= miny) { + yy = y + acc->fromIntY; + if (def->w == def->h) { + xalt = def->w - def->l; + x = -sqrt(xalt * xalt - yy * yy); + } else { + x = tailX(yy, def, &bound, acc); + if (acc->left.valid && boundedLe (yy, bound.left)) { + xalt = intersectLine (yy, acc->left); + if (xalt < x) + x = xalt; + } + if (acc->right.valid && boundedLe (yy, bound.right)) { + xalt = intersectLine (yy, acc->right); + if (xalt < x) + x = xalt; + } + } + arcSpan (y, + ICEIL(acc->fromIntX - x), 0, + ICEIL(acc->fromIntX + x), 0, + def, &bound, acc, mask); + y--; + } +} diff --git a/mi/mibitblt.c b/mi/mibitblt.c new file mode 100644 index 000000000..762e7effa --- /dev/null +++ b/mi/mibitblt.c @@ -0,0 +1,818 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mibitblt.c,v 1.5 2001/02/09 02:05:20 xorgcvs Exp $ */ +/* Author: Todd Newman (aided and abetted by Mr. Drewry) */ + +#include "X.h" +#include "Xprotostr.h" + +#include "misc.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "mi.h" +#include "regionstr.h" +#include "Xmd.h" +#include "servermd.h" + +/* MICOPYAREA -- public entry for the CopyArea request + * For each rectangle in the source region + * get the pixels with GetSpans + * set them in the destination with SetSpans + * We let SetSpans worry about clipping to the destination. + */ +RegionPtr +miCopyArea(pSrcDrawable, pDstDrawable, + pGC, xIn, yIn, widthSrc, heightSrc, xOut, yOut) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int xIn, yIn; + int widthSrc, heightSrc; + int xOut, yOut; +{ + DDXPointPtr ppt, pptFirst; + unsigned int *pwidthFirst, *pwidth, *pbits; + BoxRec srcBox, *prect; + /* may be a new region, or just a copy */ + RegionPtr prgnSrcClip; + /* non-0 if we've created a src clip */ + RegionPtr prgnExposed; + int realSrcClip = 0; + int srcx, srcy, dstx, dsty, i, j, y, width, height, + xMin, xMax, yMin, yMax; + unsigned int *ordering; + int numRects; + BoxPtr boxes; + + srcx = xIn + pSrcDrawable->x; + srcy = yIn + pSrcDrawable->y; + + /* If the destination isn't realized, this is easy */ + if (pDstDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr)pDstDrawable)->realized) + return (RegionPtr)NULL; + + /* clip the source */ + if (pSrcDrawable->type == DRAWABLE_PIXMAP) + { + BoxRec box; + + box.x1 = pSrcDrawable->x; + box.y1 = pSrcDrawable->y; + box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + + prgnSrcClip = REGION_CREATE(pGC->pScreen, &box, 1); + realSrcClip = 1; + } + else + { + if (pGC->subWindowMode == IncludeInferiors) { + prgnSrcClip = NotClippedByChildren ((WindowPtr) pSrcDrawable); + realSrcClip = 1; + } else + prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; + } + + /* If the src drawable is a window, we need to translate the srcBox so + * that we can compare it with the window's clip region later on. */ + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx + widthSrc; + srcBox.y2 = srcy + heightSrc; + + dstx = xOut; + dsty = yOut; + if (pGC->miTranslate) + { + dstx += pDstDrawable->x; + dsty += pDstDrawable->y; + } + + pptFirst = ppt = (DDXPointPtr) + ALLOCATE_LOCAL(heightSrc * sizeof(DDXPointRec)); + pwidthFirst = pwidth = (unsigned int *) + ALLOCATE_LOCAL(heightSrc * sizeof(unsigned int)); + numRects = REGION_NUM_RECTS(prgnSrcClip); + boxes = REGION_RECTS(prgnSrcClip); + ordering = (unsigned int *) + ALLOCATE_LOCAL(numRects * sizeof(unsigned int)); + if(!pptFirst || !pwidthFirst || !ordering) + { + if (ordering) + DEALLOCATE_LOCAL(ordering); + if (pwidthFirst) + DEALLOCATE_LOCAL(pwidthFirst); + if (pptFirst) + DEALLOCATE_LOCAL(pptFirst); + return (RegionPtr)NULL; + } + + /* If not the same drawable then order of move doesn't matter. + Following assumes that boxes are sorted from top + to bottom and left to right. + */ + if ((pSrcDrawable != pDstDrawable) && + ((pGC->subWindowMode != IncludeInferiors) || + (pSrcDrawable->type == DRAWABLE_PIXMAP) || + (pDstDrawable->type == DRAWABLE_PIXMAP))) + for (i=0; i < numRects; i++) + ordering[i] = i; + else { /* within same drawable, must sequence moves carefully! */ + if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical. + Vertical order OK */ + if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal. + Horizontal order OK as well */ + for (i=0; i < numRects; i++) + ordering[i] = i; + else { /* scroll right. must reverse horizontal banding of rects. */ + for (i=0, j=1, xMax=0; i < numRects; j=i+1, xMax=i) { + /* find extent of current horizontal band */ + y=boxes[i].y1; /* band has this y coordinate */ + while ((j < numRects) && (boxes[j].y1 == y)) + j++; + /* reverse the horizontal band in the output ordering */ + for (j-- ; j >= xMax; j--, i++) + ordering[i] = j; + } + } + } + else { /* Scroll down. Must reverse vertical banding. */ + if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */ + for (i=numRects-1, j=i-1, yMin=i, yMax=0; + i >= 0; + j=i-1, yMin=i) { + /* find extent of current horizontal band */ + y=boxes[i].y1; /* band has this y coordinate */ + while ((j >= 0) && (boxes[j].y1 == y)) + j--; + /* reverse the horizontal band in the output ordering */ + for (j++ ; j <= yMin; j++, i--, yMax++) + ordering[yMax] = j; + } + } + else /* Scroll right or horizontal stationary. + Reverse horizontal order as well (if stationary, horizontal + order can be swapped without penalty and this is faster + to compute). */ + for (i=0, j=numRects-1; i < numRects; i++, j--) + ordering[i] = j; + } + } + + for(i = 0; i < numRects; i++) + { + prect = &boxes[ordering[i]]; + xMin = max(prect->x1, srcBox.x1); + xMax = min(prect->x2, srcBox.x2); + yMin = max(prect->y1, srcBox.y1); + yMax = min(prect->y2, srcBox.y2); + /* is there anything visible here? */ + if(xMax <= xMin || yMax <= yMin) + continue; + + ppt = pptFirst; + pwidth = pwidthFirst; + y = yMin; + height = yMax - yMin; + width = xMax - xMin; + + for(j = 0; j < height; j++) + { + /* We must untranslate before calling GetSpans */ + ppt->x = xMin; + ppt++->y = y++; + *pwidth++ = width; + } + pbits = (unsigned int *)xalloc(height * PixmapBytePad(width, + pSrcDrawable->depth)); + if (pbits) + { + (*pSrcDrawable->pScreen->GetSpans)(pSrcDrawable, width, pptFirst, + (int *)pwidthFirst, height, (char *)pbits); + ppt = pptFirst; + pwidth = pwidthFirst; + xMin -= (srcx - dstx); + y = yMin - (srcy - dsty); + for(j = 0; j < height; j++) + { + ppt->x = xMin; + ppt++->y = y++; + *pwidth++ = width; + } + + (*pGC->ops->SetSpans)(pDstDrawable, pGC, (char *)pbits, pptFirst, + (int *)pwidthFirst, height, TRUE); + xfree(pbits); + } + } + prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn, + widthSrc, heightSrc, xOut, yOut, (unsigned long)0); + if(realSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + + DEALLOCATE_LOCAL(ordering); + DEALLOCATE_LOCAL(pwidthFirst); + DEALLOCATE_LOCAL(pptFirst); + return prgnExposed; +} + +/* MIGETPLANE -- gets a bitmap representing one plane of pDraw + * A helper used for CopyPlane and XY format GetImage + * No clever strategy here, we grab a scanline at a time, pull out the + * bits and then stuff them in a 1 bit deep map. + */ +static +unsigned long * +miGetPlane(pDraw, planeNum, sx, sy, w, h, result) + DrawablePtr pDraw; + int planeNum; /* number of the bitPlane */ + int sx, sy, w, h; + unsigned long *result; +{ + int i, j, k, width, bitsPerPixel, widthInBytes; + DDXPointRec pt; + unsigned long pixel; + unsigned long bit; + unsigned char *pCharsOut; + +#if BITMAP_SCANLINE_UNIT == 8 +#define OUT_TYPE unsigned char +#endif +#if BITMAP_SCANLINE_UNIT == 16 +#define OUT_TYPE CARD16 +#endif +#if BITMAP_SCANLINE_UNIT == 32 +#define OUT_TYPE CARD32 +#endif +#if BITMAP_SCANLINE_UNIT == 64 +#define OUT_TYPE CARD64 +#endif + + OUT_TYPE *pOut; + int delta; + + sx += pDraw->x; + sy += pDraw->y; + widthInBytes = BitmapBytePad(w); + if(!result) + result = (unsigned long *)xalloc(h * widthInBytes); + if (!result) + return (unsigned long *)NULL; + bitsPerPixel = pDraw->bitsPerPixel; + bzero((char *)result, h * widthInBytes); + pOut = (OUT_TYPE *) result; + if(bitsPerPixel == 1) + { + pCharsOut = (unsigned char *) result; + width = w; + } + else + { + delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) - + (w / BITMAP_SCANLINE_UNIT); + width = 1; +#if IMAGE_BYTE_ORDER == MSBFirst + planeNum += (32 - bitsPerPixel); +#endif + } + pt.y = sy; + for (i = h; --i >= 0; pt.y++) + { + pt.x = sx; + if(bitsPerPixel == 1) + { + (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1, + (char *)pCharsOut); + pCharsOut += widthInBytes; + } + else + { + k = 0; + for(j = w; --j >= 0; pt.x++) + { + /* Fetch the next pixel */ + (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1, + (char *)&pixel); + /* + * Now get the bit and insert into a bitmap in XY format. + */ + bit = (pixel >> planeNum) & 1; + /* XXX assuming bit order == byte order */ +#if BITMAP_BIT_ORDER == LSBFirst + bit <<= k; +#else + bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k); +#endif + *pOut |= (OUT_TYPE) bit; + k++; + if (k == BITMAP_SCANLINE_UNIT) + { + pOut++; + k = 0; + } + } + pOut += delta; + } + } + return(result); + +} + +/* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw. + * Drawing through the clip mask we SetSpans() the bits into a + * bitmap and stipple those bits onto the destination drawable by doing a + * PolyFillRect over the whole drawable, + * then we invert the bitmap by copying it onto itself with an alu of + * GXinvert, invert the foreground/background colors of the gc, and draw + * the background bits. + * Note how the clipped out bits of the bitmap are always the background + * color so that the stipple never causes FillRect to draw them. + */ +void +miOpqStipDrawable(pDraw, pGC, prgnSrc, pbits, srcx, w, h, dstx, dsty) + DrawablePtr pDraw; + GCPtr pGC; + RegionPtr prgnSrc; + unsigned long *pbits; + int srcx, w, h, dstx, dsty; +{ + int oldfill, i; + unsigned long oldfg; + int *pwidth, *pwidthFirst; + ChangeGCVal gcv[6]; + PixmapPtr pStipple, pPixmap; + DDXPointRec oldOrg; + GCPtr pGCT; + DDXPointPtr ppt, pptFirst; + xRectangle rect; + RegionPtr prgnSrcClip; + + pPixmap = (*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, w + srcx, h, 1); + if (!pPixmap) + return; + + /* Put the image into a 1 bit deep pixmap */ + pGCT = GetScratchGC(1, pDraw->pScreen); + if (!pGCT) + { + (*pDraw->pScreen->DestroyPixmap)(pPixmap); + return; + } + /* First set the whole pixmap to 0 */ + gcv[0].val = 0; + dixChangeGC(NullClient, pGCT, GCBackground, NULL, gcv); + ValidateGC((DrawablePtr)pPixmap, pGCT); + miClearDrawable((DrawablePtr)pPixmap, pGCT); + ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec)); + pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int)); + if(!pptFirst || !pwidthFirst) + { + if (pwidthFirst) DEALLOCATE_LOCAL(pwidthFirst); + if (pptFirst) DEALLOCATE_LOCAL(pptFirst); + FreeScratchGC(pGCT); + return; + } + + /* we need a temporary region because ChangeClip must be assumed + to destroy what it's sent. note that this means we don't + have to free prgnSrcClip ourselves. + */ + prgnSrcClip = REGION_CREATE(pGCT->pScreen, NULL, 0); + REGION_COPY(pGCT->pScreen, prgnSrcClip, prgnSrc); + REGION_TRANSLATE(pGCT->pScreen, prgnSrcClip, srcx, 0); + (*pGCT->funcs->ChangeClip)(pGCT, CT_REGION, prgnSrcClip, 0); + ValidateGC((DrawablePtr)pPixmap, pGCT); + + /* Since we know pDraw is always a pixmap, we never need to think + * about translation here */ + for(i = 0; i < h; i++) + { + ppt->x = 0; + ppt++->y = i; + *pwidth++ = w + srcx; + } + + (*pGCT->ops->SetSpans)((DrawablePtr)pPixmap, pGCT, (char *)pbits, + pptFirst, pwidthFirst, h, TRUE); + DEALLOCATE_LOCAL(pwidthFirst); + DEALLOCATE_LOCAL(pptFirst); + + + /* Save current values from the client GC */ + oldfill = pGC->fillStyle; + pStipple = pGC->stipple; + if(pStipple) + pStipple->refcnt++; + oldOrg = pGC->patOrg; + + /* Set a new stipple in the drawable */ + gcv[0].val = FillStippled; + gcv[1].ptr = pPixmap; + gcv[2].val = dstx - srcx; + gcv[3].val = dsty; + + dixChangeGC(NullClient, pGC, + GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin, + NULL, gcv); + ValidateGC(pDraw, pGC); + + /* Fill the drawable with the stipple. This will draw the + * foreground color whereever 1 bits are set, leaving everything + * with 0 bits untouched. Note that the part outside the clip + * region is all 0s. */ + rect.x = dstx; + rect.y = dsty; + rect.width = w; + rect.height = h; + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + + /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only + * within the clipping region, the part outside is still all 0s */ + gcv[0].val = GXinvert; + dixChangeGC(NullClient, pGCT, GCFunction, NULL, gcv); + ValidateGC((DrawablePtr)pPixmap, pGCT); + (*pGCT->ops->CopyArea)((DrawablePtr)pPixmap, (DrawablePtr)pPixmap, + pGCT, 0, 0, w + srcx, h, 0, 0); + + /* Swap foreground and background colors on the GC for the drawable. + * Now when we fill the drawable, we will fill in the "Background" + * values */ + oldfg = pGC->fgPixel; + gcv[0].val = pGC->bgPixel; + gcv[1].val = oldfg; + gcv[2].ptr = pPixmap; + dixChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple, + NULL, gcv); + ValidateGC(pDraw, pGC); + /* PolyFillRect might have bashed the rectangle */ + rect.x = dstx; + rect.y = dsty; + rect.width = w; + rect.height = h; + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + + /* Now put things back */ + if(pStipple) + pStipple->refcnt--; + gcv[0].val = oldfg; + gcv[1].val = pGC->fgPixel; + gcv[2].val = oldfill; + gcv[3].ptr = pStipple; + gcv[4].val = oldOrg.x; + gcv[5].val = oldOrg.y; + dixChangeGC(NullClient, pGC, + GCForeground | GCBackground | GCFillStyle | GCStipple | + GCTileStipXOrigin | GCTileStipYOrigin, NULL, gcv); + + ValidateGC(pDraw, pGC); + /* put what we hope is a smaller clip region back in the scratch gc */ + (*pGCT->funcs->ChangeClip)(pGCT, CT_NONE, NULL, 0); + FreeScratchGC(pGCT); + (*pDraw->pScreen->DestroyPixmap)(pPixmap); + +} + +/* MICOPYPLANE -- public entry for the CopyPlane request. + * strategy: + * First build up a bitmap out of the bits requested + * build a source clip + * Use the bitmap we've built up as a Stipple for the destination + */ +RegionPtr +miCopyPlane(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane) + DrawablePtr pSrcDrawable; + DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long bitPlane; +{ + unsigned long *ptile; + BoxRec box; + RegionPtr prgnSrc, prgnExposed; + + /* incorporate the source clip */ + + box.x1 = srcx + pSrcDrawable->x; + box.y1 = srcy + pSrcDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + /* clip to visible drawable */ + if (box.x1 < pSrcDrawable->x) + box.x1 = pSrcDrawable->x; + if (box.y1 < pSrcDrawable->y) + box.y1 = pSrcDrawable->y; + if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) + box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) + box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1); + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) { + /* clip to visible drawable */ + + if (pGC->subWindowMode == IncludeInferiors) + { + RegionPtr clipList = NotClippedByChildren ((WindowPtr) pSrcDrawable); + REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, clipList); + REGION_DESTROY(pGC->pScreen, clipList); + } else + REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, + &((WindowPtr)pSrcDrawable)->clipList); + } + + box = *REGION_EXTENTS(pGC->pScreen, prgnSrc); + REGION_TRANSLATE(pGC->pScreen, prgnSrc, -box.x1, -box.y1); + + if ((box.x2 > box.x1) && (box.y2 > box.y1)) + { + /* minimize the size of the data extracted */ + /* note that we convert the plane mask bitPlane into a plane number */ + box.x1 -= pSrcDrawable->x; + box.x2 -= pSrcDrawable->x; + box.y1 -= pSrcDrawable->y; + box.y2 -= pSrcDrawable->y; + ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1, + box.x1, box.y1, + box.x2 - box.x1, box.y2 - box.y1, + (unsigned long *) NULL); + if (ptile) + { + miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0, + box.x2 - box.x1, box.y2 - box.y1, + dstx + box.x1 - srcx, dsty + box.y1 - srcy); + xfree(ptile); + } + } + prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, + width, height, dstx, dsty, bitPlane); + REGION_DESTROY(pGC->pScreen, prgnSrc); + return prgnExposed; +} + +/* MIGETIMAGE -- public entry for the GetImage Request + * We're getting the image into a memory buffer. While we have to use GetSpans + * to read a line from the device (since we don't know what that looks like), + * we can just write into the destination buffer + * + * two different strategies are used, depending on whether we're getting the + * image in Z format or XY format + * Z format: + * Line at a time, GetSpans a line into the destination buffer, then if the + * planemask is not all ones, we do a SetSpans into a temporary buffer (to get + * bits turned off) and then another GetSpans to get stuff back (because + * pixmaps are opaque, and we are passed in the memory to write into). This is + * pretty ugly and slow but works. Life is hard. + * XY format: + * get the single plane specified in planemask + */ +void +miGetImage(pDraw, sx, sy, w, h, format, planeMask, pDst) + DrawablePtr pDraw; + int sx, sy, w, h; + unsigned int format; + unsigned long planeMask; + char * pDst; +{ + unsigned char depth; + int i, linelength, width, srcx, srcy; + DDXPointRec pt; + XID gcv[2]; + PixmapPtr pPixmap = (PixmapPtr)NULL; + GCPtr pGC; + + depth = pDraw->depth; + if(format == ZPixmap) + { + if ( (((1<pScreen); + if (!pGC) + return; + pPixmap = (*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, w, 1, depth); + if (!pPixmap) + { + FreeScratchGC(pGC); + return; + } + /* + * Clear the pixmap before doing anything else + */ + ValidateGC((DrawablePtr)pPixmap, pGC); + pt.x = pt.y = 0; + width = w; + (*pGC->ops->FillSpans)((DrawablePtr)pPixmap, pGC, 1, &pt, &width, + TRUE); + + /* alu is already GXCopy */ + gcv[0] = (XID)planeMask; + DoChangeGC(pGC, GCPlaneMask, gcv, 0); + ValidateGC((DrawablePtr)pPixmap, pGC); + } + + linelength = PixmapBytePad(w, depth); + srcx = sx + pDraw->x; + srcy = sy + pDraw->y; + for(i = 0; i < h; i++) + { + pt.x = srcx; + pt.y = srcy + i; + width = w; + (*pDraw->pScreen->GetSpans)(pDraw, w, &pt, &width, 1, pDst); + if (pPixmap) + { + pt.x = 0; + pt.y = 0; + width = w; + (*pGC->ops->SetSpans)((DrawablePtr)pPixmap, pGC, pDst, + &pt, &width, 1, TRUE); + (*pDraw->pScreen->GetSpans)((DrawablePtr)pPixmap, w, &pt, + &width, 1, pDst); + } + pDst += linelength; + } + if (pPixmap) + { + (*pGC->pScreen->DestroyPixmap)(pPixmap); + FreeScratchGC(pGC); + } + } + else + { + (void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h, + (unsigned long *)pDst); + } +} + + +/* MIPUTIMAGE -- public entry for the PutImage request + * Here we benefit from knowing the format of the bits pointed to by pImage, + * even if we don't know how pDraw represents them. + * Three different strategies are used depending on the format + * XYBitmap Format: + * we just use the Opaque Stipple helper function to cover the destination + * Note that this covers all the planes of the drawable with the + * foreground color (masked with the GC planemask) where there are 1 bits + * and the background color (masked with the GC planemask) where there are + * 0 bits + * XYPixmap format: + * what we're called with is a series of XYBitmaps, but we only want + * each XYPixmap to update 1 plane, instead of updating all of them. + * we set the foreground color to be all 1s and the background to all 0s + * then for each plane, we set the plane mask to only effect that one + * plane and recursive call ourself with the format set to XYBitmap + * (This clever idea courtesy of RGD.) + * ZPixmap format: + * This part is simple, just call SetSpans + */ +void +miPutImage(pDraw, pGC, depth, x, y, w, h, leftPad, format, pImage) + DrawablePtr pDraw; + GCPtr pGC; + int depth, x, y, w, h, leftPad; + int format; + char *pImage; +{ + DDXPointPtr pptFirst, ppt; + int *pwidthFirst, *pwidth; + RegionPtr prgnSrc; + BoxRec box; + unsigned long oldFg, oldBg; + XID gcv[3]; + unsigned long oldPlanemask; + unsigned long i; + long bytesPer; + + if (!w || !h) + return; + switch(format) + { + case XYBitmap: + + box.x1 = 0; + box.y1 = 0; + box.x2 = w; + box.y2 = h; + prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1); + + miOpqStipDrawable(pDraw, pGC, prgnSrc, (unsigned long *) pImage, + leftPad, w, h, x, y); + REGION_DESTROY(pGC->pScreen, prgnSrc); + break; + + case XYPixmap: + depth = pGC->depth; + oldPlanemask = pGC->planemask; + oldFg = pGC->fgPixel; + oldBg = pGC->bgPixel; + gcv[0] = (XID)~0; + gcv[1] = (XID)0; + DoChangeGC(pGC, GCForeground | GCBackground, gcv, 0); + bytesPer = (long)h * BitmapBytePad(w + leftPad); + + for (i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer) + { + if (i & oldPlanemask) + { + gcv[0] = (XID)i; + DoChangeGC(pGC, GCPlaneMask, gcv, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad, + XYBitmap, (char *)pImage); + } + } + gcv[0] = (XID)oldPlanemask; + gcv[1] = (XID)oldFg; + gcv[2] = (XID)oldBg; + DoChangeGC(pGC, GCPlaneMask | GCForeground | GCBackground, gcv, 0); + break; + + case ZPixmap: + ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec)); + pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int)); + if(!pptFirst || !pwidthFirst) + { + if (pwidthFirst) + DEALLOCATE_LOCAL(pwidthFirst); + if (pptFirst) + DEALLOCATE_LOCAL(pptFirst); + return; + } + if (pGC->miTranslate) + { + x += pDraw->x; + y += pDraw->y; + } + + for(i = 0; i < h; i++) + { + ppt->x = x; + ppt->y = y + i; + ppt++; + *pwidth++ = w; + } + + (*pGC->ops->SetSpans)(pDraw, pGC, (char *)pImage, pptFirst, + pwidthFirst, h, TRUE); + DEALLOCATE_LOCAL(pwidthFirst); + DEALLOCATE_LOCAL(pptFirst); + break; + } +} diff --git a/mi/mibstore.c b/mi/mibstore.c new file mode 100644 index 000000000..f8a4cc891 --- /dev/null +++ b/mi/mibstore.c @@ -0,0 +1,3823 @@ +/* $Xorg: mibstore.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by the Regents of the University of California + + 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 name The Open Group not be used in advertising or publicity +pertaining to distribution of the software without specific, written prior +permission. + +The University of California makes no representations about the suitability +of this software for any purpose. It is provided "as is" without express or +implied warranty. + +******************************************************************/ + +#define NEED_EVENTS +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "dixstruct.h" /* For requestingClient */ +#include "mi.h" +#include "mibstorest.h" + +/* + * When the server fails to allocate a backing store pixmap, if you want + * it to dynamically retry to allocate backing store on every subsequent + * graphics op, you can enable BSEAGER; otherwise, backing store will be + * disabled on the window until it is unmapped and then remapped. + */ +/* #define BSEAGER */ + +/*- + * NOTES ON USAGE: + * + * The functions in this file implement a machine-independent backing-store + * scheme. To use it, the output library must do the following: + * - Provide a SaveAreas function that takes a destination pixmap, a + * region of the areas to save (in the pixmap's coordinate system) + * and the screen origin of the region. It should copy the areas from + * the screen into the pixmap. + * - Provide a RestoreAreas function that takes a source pixmap, a region + * of the areas to restore (in the screen's coordinate system) and the + * origin of the pixmap on the screen. It should copy the areas from + * the pixmap into the screen. + * - Provide a SetClipmaskRgn function that takes a gc and a region + * and merges the region into any CT_PIXMAP client clip that + * is specified in the GC. This routine is only needed if + * miValidateBackingStore will see CT_PIXMAP clip lists; not + * true for any of the sample servers (which convert the PIXMAP + * clip lists into CT_REGION clip lists; an expensive but simple + * to code option). + * - The function placed in a window's ClearToBackground vector must call + * pScreen->ClearBackingStore with the window, followed by + * the window-relative x and y coordinates, followed by the width and + * height of the area to be cleared, followed by the generateExposures + * flag. This has been taken care of in miClearToBackground. + * - Whatever determines GraphicsExpose events for the CopyArea and + * CopyPlane requests should call pWin->backStorage->ExposeCopy + * with the source and destination drawables, the GC used, a source- + * window-relative region of exposed areas, the source and destination + * coordinates and the bitplane copied, if CopyPlane, or 0, if + * CopyArea. + * + * JUSTIFICATION + * This is a cross between saving everything and just saving the + * obscued areas (as in Pike's layers.) This method has the advantage + * of only doing each output operation once per pixel, visible or + * invisible, and avoids having to do all the crufty storage + * management of keeping several separate rectangles. Since the + * ddx layer ouput primitives are required to draw through clipping + * rectangles anyway, sending multiple drawing requests for each of + * several rectangles isn't necessary. (Of course, it could be argued + * that the ddx routines should just take one rectangle each and + * get called multiple times, but that would make taking advantage of + * smart hardware harder, and probably be slower as well.) + */ + +#define SETUP_BACKING_TERSE(pGC) \ + miBSGCPtr pGCPrivate = (miBSGCPtr)(pGC)->devPrivates[miBSGCIndex].ptr; \ + GCFuncs *oldFuncs = pGC->funcs; + +#define SETUP_BACKING(pDrawable,pGC) \ + miBSWindowPtr pBackingStore = \ + (miBSWindowPtr)((WindowPtr)(pDrawable))->backStorage; \ + DrawablePtr pBackingDrawable = (DrawablePtr) \ + pBackingStore->pBackingPixmap; \ + SETUP_BACKING_TERSE(pGC) \ + GCPtr pBackingGC = pGCPrivate->pBackingGC; + +#define PROLOGUE(pGC) { \ + pGC->ops = pGCPrivate->wrapOps;\ + pGC->funcs = pGCPrivate->wrapFuncs; \ + } + +#define EPILOGUE(pGC) { \ + pGCPrivate->wrapOps = (pGC)->ops; \ + (pGC)->ops = &miBSGCOps; \ + (pGC)->funcs = oldFuncs; \ + } + +static void miCreateBSPixmap(); +static void miDestroyBSPixmap(); +static void miTileVirtualBS(); +static void miBSAllocate(), miBSFree(); +static Bool miBSCreateGCPrivate (); +static void miBSClearBackingRegion (); + +#define MoreCopy0 ; +#define MoreCopy2 *dstCopy++ = *srcCopy++; *dstCopy++ = *srcCopy++; +#define MoreCopy4 MoreCopy2 MoreCopy2 + +#define copyData(src,dst,n,morecopy) \ +{ \ + register short *srcCopy = (short *)(src); \ + register short *dstCopy = (short *)(dst); \ + register int i; \ + register int bsx = pBackingStore->x; \ + register int bsy = pBackingStore->y; \ + for (i = n; --i >= 0; ) \ + { \ + *dstCopy++ = *srcCopy++ - bsx; \ + *dstCopy++ = *srcCopy++ - bsy; \ + morecopy \ + } \ +} + +#define copyPoints(src,dst,n,mode) \ +if (mode == CoordModeOrigin) \ +{ \ + copyData(src,dst,n,MoreCopy0); \ +} \ +else \ +{ \ + memmove((char *)(dst), (char *)(src), (n) << 2); \ + *((short *)(dst)) -= pBackingStore->x; \ + *((short *)(dst) + 1) -= pBackingStore->y; \ +} + +/* + * wrappers for screen funcs + */ + +static int miBSScreenIndex; +static unsigned long miBSGeneration = 0; + +static Bool miBSCloseScreen(); +static void miBSGetImage(); +static void miBSGetSpans(); +static Bool miBSChangeWindowAttributes(); +static Bool miBSCreateGC(); +static Bool miBSDestroyWindow(); + +/* + * backing store screen functions + */ + +static void miBSSaveDoomedAreas(); +static RegionPtr miBSRestoreAreas(); +static void miBSExposeCopy(); +static RegionPtr miBSTranslateBackingStore(), miBSClearBackingStore(); +static void miBSDrawGuarantee(); + +/* + * wrapper vectors for GC funcs and ops + */ + +static int miBSGCIndex; + +static void miBSValidateGC (), miBSCopyGC (), miBSDestroyGC(); +static void miBSChangeGC(); +static void miBSChangeClip(), miBSDestroyClip(), miBSCopyClip(); + +static GCFuncs miBSGCFuncs = { + miBSValidateGC, + miBSChangeGC, + miBSCopyGC, + miBSDestroyGC, + miBSChangeClip, + miBSDestroyClip, + miBSCopyClip, +}; + +static void miBSFillSpans(), miBSSetSpans(), miBSPutImage(); +static RegionPtr miBSCopyArea(), miBSCopyPlane(); +static void miBSPolyPoint(), miBSPolylines(), miBSPolySegment(); +static void miBSPolyRectangle(),miBSPolyArc(), miBSFillPolygon(); +static void miBSPolyFillRect(), miBSPolyFillArc(); +static int miBSPolyText8(), miBSPolyText16(); +static void miBSImageText8(), miBSImageText16(); +static void miBSImageGlyphBlt(),miBSPolyGlyphBlt(); +static void miBSPushPixels(); +#ifdef NEED_LINEHELPER +static void miBSLineHelper(); +#endif + +static GCOps miBSGCOps = { + miBSFillSpans, miBSSetSpans, miBSPutImage, + miBSCopyArea, miBSCopyPlane, miBSPolyPoint, + miBSPolylines, miBSPolySegment, miBSPolyRectangle, + miBSPolyArc, miBSFillPolygon, miBSPolyFillRect, + miBSPolyFillArc, miBSPolyText8, miBSPolyText16, + miBSImageText8, miBSImageText16, miBSImageGlyphBlt, + miBSPolyGlyphBlt, miBSPushPixels +#ifdef NEED_LINEHELPER + , miBSLineHelper +#endif +}; + +#define FUNC_PROLOGUE(pGC, pPriv) \ + ((pGC)->funcs = pPriv->wrapFuncs),\ + ((pGC)->ops = pPriv->wrapOps) + +#define FUNC_EPILOGUE(pGC, pPriv) \ + ((pGC)->funcs = &miBSGCFuncs),\ + ((pGC)->ops = &miBSGCOps) + +/* + * every GC in the server is initially wrapped with these + * "cheap" functions. This allocates no memory and is used + * to discover GCs used with windows which have backing + * store enabled + */ + +static void miBSCheapValidateGC(), miBSCheapCopyGC(), miBSCheapDestroyGC(); +static void miBSCheapChangeGC (); +static void miBSCheapChangeClip(), miBSCheapDestroyClip(); +static void miBSCheapCopyClip(); + +static GCFuncs miBSCheapGCFuncs = { + miBSCheapValidateGC, + miBSCheapChangeGC, + miBSCheapCopyGC, + miBSCheapDestroyGC, + miBSCheapChangeClip, + miBSCheapDestroyClip, + miBSCheapCopyClip, +}; + +#define CHEAP_FUNC_PROLOGUE(pGC) \ + ((pGC)->funcs = (GCFuncs *) (pGC)->devPrivates[miBSGCIndex].ptr) + +#define CHEAP_FUNC_EPILOGUE(pGC) \ + ((pGC)->funcs = &miBSCheapGCFuncs) + +/* + * called from device screen initialization proc. Gets a GCPrivateIndex + * and wraps appropriate per-screen functions + */ + +void +miInitializeBackingStore (pScreen, funcs) + ScreenPtr pScreen; + miBSFuncPtr funcs; +{ + miBSScreenPtr pScreenPriv; + + if (miBSGeneration != serverGeneration) + { + miBSScreenIndex = AllocateScreenPrivateIndex (); + if (miBSScreenIndex < 0) + return; + miBSGCIndex = AllocateGCPrivateIndex (); + miBSGeneration = serverGeneration; + } + if (!AllocateGCPrivate(pScreen, miBSGCIndex, 0)) + return; + pScreenPriv = (miBSScreenPtr) xalloc (sizeof (miBSScreenRec)); + if (!pScreenPriv) + return; + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->GetImage = pScreen->GetImage; + pScreenPriv->GetSpans = pScreen->GetSpans; + pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pScreenPriv->CreateGC = pScreen->CreateGC; + pScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreenPriv->funcs = funcs; + + pScreen->CloseScreen = miBSCloseScreen; + pScreen->GetImage = miBSGetImage; + pScreen->GetSpans = miBSGetSpans; + pScreen->ChangeWindowAttributes = miBSChangeWindowAttributes; + pScreen->CreateGC = miBSCreateGC; + pScreen->DestroyWindow = miBSDestroyWindow; + + pScreen->SaveDoomedAreas = miBSSaveDoomedAreas; + pScreen->RestoreAreas = miBSRestoreAreas; + pScreen->ExposeCopy = miBSExposeCopy; + pScreen->TranslateBackingStore = miBSTranslateBackingStore; + pScreen->ClearBackingStore = miBSClearBackingStore; + pScreen->DrawGuarantee = miBSDrawGuarantee; + + pScreen->devPrivates[miBSScreenIndex].ptr = (pointer) pScreenPriv; +} + +/* + * Screen function wrappers + */ + +#define SCREEN_PROLOGUE(pScreen, field)\ + ((pScreen)->field = \ + ((miBSScreenPtr) \ + (pScreen)->devPrivates[miBSScreenIndex].ptr)->field) + +#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ + ((pScreen)->field = wrapper) + +/* + * CloseScreen wrapper -- unwrap everything, free the private data + * and call the wrapped function + */ + +static Bool +miBSCloseScreen (i, pScreen) + int i; + ScreenPtr pScreen; +{ + miBSScreenPtr pScreenPriv; + + pScreenPriv = (miBSScreenPtr) pScreen->devPrivates[miBSScreenIndex].ptr; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes; + pScreen->CreateGC = pScreenPriv->CreateGC; + + xfree ((pointer) pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void miBSFillVirtualBits(); + +static void +miBSGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) + DrawablePtr pDrawable; + int sx, sy, w, h; + unsigned int format; + unsigned long planemask; + char *pdstLine; +{ + ScreenPtr pScreen = pDrawable->pScreen; + BoxRec bounds; + unsigned char depth; + + SCREEN_PROLOGUE (pScreen, GetImage); + + if (pDrawable->type != DRAWABLE_PIXMAP && + ((WindowPtr) pDrawable)->visibility != VisibilityUnobscured) + { + PixmapPtr pPixmap; + miBSWindowPtr pWindowPriv; + GCPtr pGC; + WindowPtr pWin, pSrcWin; + int xoff, yoff; + RegionRec Remaining; + RegionRec Border; + RegionRec Inside; + BoxPtr pBox; + int n; + + pWin = (WindowPtr) pDrawable; + pPixmap = 0; + depth = pDrawable->depth; + bounds.x1 = sx + pDrawable->x; + bounds.y1 = sy + pDrawable->y; + bounds.x2 = bounds.x1 + w; + bounds.y2 = bounds.y1 + h; + REGION_INIT(pScreen, &Remaining, &bounds, 0); + for (;;) + { + bounds.x1 = sx + pDrawable->x - pWin->drawable.x; + bounds.y1 = sy + pDrawable->y - pWin->drawable.y; + bounds.x2 = bounds.x1 + w; + bounds.y2 = bounds.y1 + h; + if (pWin->viewable && pWin->backStorage && + pWin->drawable.depth == depth && + (RECT_IN_REGION(pScreen, &(pWindowPriv = + (miBSWindowPtr) pWin->backStorage)->SavedRegion, + &bounds) != rgnOUT || + RECT_IN_REGION(pScreen, &Remaining, + REGION_EXTENTS(pScreen, &pWin->borderSize)) != rgnOUT)) + { + if (!pPixmap) + { + XID subWindowMode = IncludeInferiors; + int x, y; + + pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, depth); + if (!pPixmap) + goto punt; + pGC = GetScratchGC (depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + goto punt; + } + ChangeGC (pGC, GCSubwindowMode, &subWindowMode); + ValidateGC ((DrawablePtr)pPixmap, pGC); + REGION_INIT(pScreen, &Border, NullBox, 0); + REGION_INIT(pScreen, &Inside, NullBox, 0); + pSrcWin = (WindowPtr) pDrawable; + x = sx; + y = sy; + if (pSrcWin->parent) + { + x += pSrcWin->origin.x; + y += pSrcWin->origin.y; + pSrcWin = pSrcWin->parent; + } + (*pGC->ops->CopyArea) ((DrawablePtr)pSrcWin, + (DrawablePtr)pPixmap, pGC, + x, y, w, h, + 0, 0); + REGION_SUBTRACT(pScreen, &Remaining, &Remaining, + &((WindowPtr) pDrawable)->borderClip); + } + + REGION_INTERSECT(pScreen, &Inside, &Remaining, &pWin->winSize); + REGION_TRANSLATE(pScreen, &Inside, + -pWin->drawable.x, + -pWin->drawable.y); + REGION_INTERSECT(pScreen, &Inside, &Inside, + &pWindowPriv->SavedRegion); + + /* offset of sub-window in GetImage pixmap */ + xoff = pWin->drawable.x - pDrawable->x - sx; + yoff = pWin->drawable.y - pDrawable->y - sy; + + if (REGION_NUM_RECTS(&Inside) > 0) + { + switch (pWindowPriv->status) + { + case StatusContents: + pBox = REGION_RECTS(&Inside); + for (n = REGION_NUM_RECTS(&Inside); --n >= 0;) + { + (*pGC->ops->CopyArea) ( + (DrawablePtr)pWindowPriv->pBackingPixmap, + (DrawablePtr)pPixmap, pGC, + pBox->x1 - pWindowPriv->x, + pBox->y1 - pWindowPriv->y, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + pBox->x1 + xoff, + pBox->y1 + yoff); + ++pBox; + } + break; + case StatusVirtual: + case StatusVDirty: + if (pWindowPriv->backgroundState == BackgroundPixmap || + pWindowPriv->backgroundState == BackgroundPixel) + miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Inside, + xoff, yoff, + (int) pWindowPriv->backgroundState, + pWindowPriv->background, ~0L); + break; + } + } + REGION_SUBTRACT(pScreen, &Border, &pWin->borderSize, + &pWin->winSize); + REGION_INTERSECT(pScreen, &Border, &Border, &Remaining); + if (REGION_NUM_RECTS(&Border) > 0) + { + REGION_TRANSLATE(pScreen, &Border, -pWin->drawable.x, + -pWin->drawable.y); + miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Border, + xoff, yoff, + pWin->borderIsPixel ? (int)BackgroundPixel : (int)BackgroundPixmap, + pWin->border, ~0L); + } + } + + if (pWin->viewable && pWin->firstChild) + pWin = pWin->firstChild; + else + { + while (!pWin->nextSib && pWin != (WindowPtr) pDrawable) + pWin = pWin->parent; + if (pWin == (WindowPtr) pDrawable) + break; + pWin = pWin->nextSib; + } + } + + REGION_UNINIT(pScreen, &Remaining); + + if (pPixmap) + { + REGION_UNINIT(pScreen, &Border); + REGION_UNINIT(pScreen, &Inside); + (*pScreen->GetImage) ((DrawablePtr) pPixmap, + 0, 0, w, h, format, planemask, pdstLine); + (*pScreen->DestroyPixmap) (pPixmap); + FreeScratchGC (pGC); + } + else + { + goto punt; + } + } + else + { +punt: ; + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + } + + SCREEN_EPILOGUE (pScreen, GetImage, miBSGetImage); +} + +static void +miBSGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) + DrawablePtr pDrawable; + int wMax; + DDXPointPtr ppt; + int *pwidth; + int nspans; + char *pdstStart; +{ + ScreenPtr pScreen = pDrawable->pScreen; + BoxRec bounds; + int i; + WindowPtr pWin; + int dx, dy; + + SCREEN_PROLOGUE (pScreen, GetSpans); + + if (pDrawable->type != DRAWABLE_PIXMAP && ((WindowPtr) pDrawable)->backStorage) + { + PixmapPtr pPixmap; + miBSWindowPtr pWindowPriv; + GCPtr pGC; + + pWin = (WindowPtr) pDrawable; + pWindowPriv = (miBSWindowPtr) pWin->backStorage; + pPixmap = pWindowPriv->pBackingPixmap; + + bounds.x1 = ppt->x; + bounds.y1 = ppt->y; + bounds.x2 = bounds.x1 + *pwidth; + bounds.y2 = ppt->y; + for (i = 0; i < nspans; i++) + { + if (ppt[i].x < bounds.x1) + bounds.x1 = ppt[i].x; + if (ppt[i].x + pwidth[i] > bounds.x2) + bounds.x2 = ppt[i].x + pwidth[i]; + if (ppt[i].y < bounds.y1) + bounds.y1 = ppt[i].y; + else if (ppt[i].y > bounds.y2) + bounds.y2 = ppt[i].y; + } + + switch (RECT_IN_REGION(pScreen, &pWindowPriv->SavedRegion, &bounds)) + { + case rgnPART: + if (!pPixmap) + { + miCreateBSPixmap (pWin, NullBox); + if (!(pPixmap = pWindowPriv->pBackingPixmap)) + break; + } + pWindowPriv->status = StatusNoPixmap; + pGC = GetScratchGC(pPixmap->drawable.depth, + pPixmap->drawable.pScreen); + if (pGC) + { + ValidateGC ((DrawablePtr) pPixmap, pGC); + (*pGC->ops->CopyArea) + (pDrawable, (DrawablePtr) pPixmap, pGC, + bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1, + bounds.x1 + pPixmap->drawable.x - pWin->drawable.x - + pWindowPriv->x, + bounds.y1 + pPixmap->drawable.y - pWin->drawable.y - + pWindowPriv->y); + FreeScratchGC(pGC); + } + pWindowPriv->status = StatusContents; + /* fall through */ + case rgnIN: + if (!pPixmap) + { + miCreateBSPixmap (pWin, NullBox); + if (!(pPixmap = pWindowPriv->pBackingPixmap)) + break; + } + dx = pPixmap->drawable.x - pWin->drawable.x - pWindowPriv->x; + dy = pPixmap->drawable.y - pWin->drawable.y - pWindowPriv->y; + for (i = 0; i < nspans; i++) + { + ppt[i].x += dx; + ppt[i].y += dy; + } + (*pScreen->GetSpans) ((DrawablePtr) pPixmap, wMax, ppt, pwidth, + nspans, pdstStart); + break; + case rgnOUT: + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, + pdstStart); + break; + } + } + else + { + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + } + + SCREEN_EPILOGUE (pScreen, GetSpans, miBSGetSpans); +} + +static Bool +miBSChangeWindowAttributes (pWin, mask) + WindowPtr pWin; + unsigned long mask; +{ + ScreenPtr pScreen; + Bool ret; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE (pScreen, ChangeWindowAttributes); + + ret = (*pScreen->ChangeWindowAttributes) (pWin, mask); + + if (ret && (mask & CWBackingStore)) + { + if (pWin->backingStore != NotUseful || pWin->DIXsaveUnder) + miBSAllocate (pWin); + else + miBSFree (pWin); + } + + SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, miBSChangeWindowAttributes); + + return ret; +} + +/* + * GC Create wrapper. Set up the cheap GC func wrappers to track + * GC validation on BackingStore windows + */ + +static Bool +miBSCreateGC (pGC) + GCPtr pGC; +{ + ScreenPtr pScreen = pGC->pScreen; + Bool ret; + + SCREEN_PROLOGUE (pScreen, CreateGC); + + if ( (ret = (*pScreen->CreateGC) (pGC)) ) + { + pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs; + pGC->funcs = &miBSCheapGCFuncs; + } + + SCREEN_EPILOGUE (pScreen, CreateGC, miBSCreateGC); + + return ret; +} + +static Bool +miBSDestroyWindow (pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + Bool ret; + + SCREEN_PROLOGUE (pScreen, DestroyWindow); + + ret = (*pScreen->DestroyWindow) (pWin); + + miBSFree (pWin); + + SCREEN_EPILOGUE (pScreen, DestroyWindow, miBSDestroyWindow); + + return ret; +} + +/* + * cheap GC func wrappers. Simply track validation on windows + * with backing store to enable the real func/op wrappers + */ + +static void +miBSCheapValidateGC (pGC, stateChanges, pDrawable) + GCPtr pGC; + unsigned long stateChanges; + DrawablePtr pDrawable; +{ + CHEAP_FUNC_PROLOGUE (pGC); + + if (pDrawable->type != DRAWABLE_PIXMAP && + ((WindowPtr) pDrawable)->backStorage != NULL && + miBSCreateGCPrivate (pGC)) + { + (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable); + } + else + { + (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable); + + /* rewrap funcs as Validate may have changed them */ + pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs; + + CHEAP_FUNC_EPILOGUE (pGC); + } +} + +static void +miBSCheapChangeGC (pGC, mask) + GCPtr pGC; + unsigned long mask; +{ + CHEAP_FUNC_PROLOGUE (pGC); + + (*pGC->funcs->ChangeGC) (pGC, mask); + + CHEAP_FUNC_EPILOGUE (pGC); +} + +static void +miBSCheapCopyGC (pGCSrc, mask, pGCDst) + GCPtr pGCSrc, pGCDst; + unsigned long mask; +{ + CHEAP_FUNC_PROLOGUE (pGCDst); + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + + CHEAP_FUNC_EPILOGUE (pGCDst); +} + +static void +miBSCheapDestroyGC (pGC) + GCPtr pGC; +{ + CHEAP_FUNC_PROLOGUE (pGC); + + (*pGC->funcs->DestroyGC) (pGC); + + /* leave it unwrapped */ +} + +static void +miBSCheapChangeClip (pGC, type, pvalue, nrects) + GCPtr pGC; + int type; + pointer pvalue; + int nrects; +{ + CHEAP_FUNC_PROLOGUE (pGC); + + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + + CHEAP_FUNC_EPILOGUE (pGC); +} + +static void +miBSCheapCopyClip(pgcDst, pgcSrc) + GCPtr pgcDst, pgcSrc; +{ + CHEAP_FUNC_PROLOGUE (pgcDst); + + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + + CHEAP_FUNC_EPILOGUE (pgcDst); +} + +static void +miBSCheapDestroyClip(pGC) + GCPtr pGC; +{ + CHEAP_FUNC_PROLOGUE (pGC); + + (* pGC->funcs->DestroyClip)(pGC); + + CHEAP_FUNC_EPILOGUE (pGC); +} + +/* + * create the full func/op wrappers for a GC + */ + +static Bool +miBSCreateGCPrivate (pGC) + GCPtr pGC; +{ + miBSGCRec *pPriv; + + pPriv = (miBSGCRec *) xalloc (sizeof (miBSGCRec)); + if (!pPriv) + return FALSE; + pPriv->pBackingGC = NULL; + pPriv->guarantee = GuaranteeNothing; + pPriv->serialNumber = 0; + pPriv->stateChanges = (1 << (GCLastBit + 1)) - 1; + pPriv->wrapOps = pGC->ops; + pPriv->wrapFuncs = pGC->funcs; + pGC->funcs = &miBSGCFuncs; + pGC->ops = &miBSGCOps; + pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv; + return TRUE; +} + +static void +miBSDestroyGCPrivate (pGC) + GCPtr pGC; +{ + miBSGCRec *pPriv; + + pPriv = (miBSGCRec *) pGC->devPrivates[miBSGCIndex].ptr; + if (pPriv) + { + pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv->wrapFuncs; + pGC->funcs = &miBSCheapGCFuncs; + pGC->ops = pPriv->wrapOps; + if (pPriv->pBackingGC) + FreeGC (pPriv->pBackingGC, (GContext) 0); + xfree ((pointer) pPriv); + } +} + +/* + * GC ops -- wrap each GC operation with our own function + */ + +/*- + *----------------------------------------------------------------------- + * miBSFillSpans -- + * Perform a FillSpans, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + DDXPointPtr pptCopy, pptReset; + int *pwidthCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nInit*sizeof(DDXPointRec)); + pwidthCopy=(int *)ALLOCATE_LOCAL(nInit*sizeof(int)); + if (pptCopy && pwidthCopy) + { + copyData(pptInit, pptCopy, nInit, MoreCopy0); + memmove((char *)pwidthCopy,(char *)pwidthInit,nInit*sizeof(int)); + + (* pGC->ops->FillSpans)(pDrawable, pGC, nInit, pptInit, + pwidthInit, fSorted); + if (pGC->miTranslate) + { + int dx, dy; + int nReset; + + pptReset = pptCopy; + dx = pDrawable->x - pBackingDrawable->x; + dy = pDrawable->y - pBackingDrawable->y; + nReset = nInit; + while (nReset--) + { + pptReset->x -= dx; + pptReset->y -= dy; + ++pptReset; + } + } + (* pBackingGC->ops->FillSpans)(pBackingDrawable, + pBackingGC, nInit, pptCopy, pwidthCopy, + fSorted); + } + if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy); + if (pptCopy) DEALLOCATE_LOCAL(pptCopy); + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSSetSpans -- + * Perform a SetSpans, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + char *psrc; + register DDXPointPtr ppt; + int *pwidth; + int nspans; + int fSorted; +{ + DDXPointPtr pptCopy, pptReset; + int *pwidthCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nspans*sizeof(DDXPointRec)); + pwidthCopy=(int *)ALLOCATE_LOCAL(nspans*sizeof(int)); + if (pptCopy && pwidthCopy) + { + copyData(ppt, pptCopy, nspans, MoreCopy0); + memmove((char *)pwidthCopy,(char *)pwidth,nspans*sizeof(int)); + + (* pGC->ops->SetSpans)(pDrawable, pGC, psrc, ppt, pwidth, + nspans, fSorted); + if (pGC->miTranslate) + { + int dx, dy; + int nReset; + + pptReset = pptCopy; + dx = pDrawable->x - pBackingDrawable->x; + dy = pDrawable->y - pBackingDrawable->y; + nReset = nspans; + while (nReset--) + { + pptReset->x -= dx; + pptReset->y -= dy; + ++pptReset; + } + } + (* pBackingGC->ops->SetSpans)(pBackingDrawable, pBackingGC, + psrc, pptCopy, pwidthCopy, nspans, fSorted); + } + if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy); + if (pptCopy) DEALLOCATE_LOCAL(pptCopy); + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPutImage -- + * Perform a PutImage, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) + DrawablePtr pDrawable; + GCPtr pGC; + int depth; + int x; + int y; + int w; + int h; + int leftPad; + int format; + char *pBits; +{ + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + (*pGC->ops->PutImage)(pDrawable, pGC, + depth, x, y, w, h, leftPad, format, pBits); + (*pBackingGC->ops->PutImage)(pBackingDrawable, pBackingGC, + depth, x - pBackingStore->x, y - pBackingStore->y, + w, h, leftPad, format, pBits); + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSDoCopy -- + * Perform a CopyArea or CopyPlane within a window that has backing + * store enabled. + * + * Results: + * TRUE if the copy was performed or FALSE if a regular one should + * be done. + * + * Side Effects: + * Things are copied (no s***!) + * + * Notes: + * The idea here is to form two regions that cover the source box. + * One contains the exposed rectangles while the other contains + * the obscured ones. An array of pairs is then + * formed where the indicates the area to be copied and the + * indicates from where it is to be copied (exposed regions + * come from the screen while obscured ones come from the backing + * pixmap). The array 'sequence' is then filled with the indices of + * the pairs in the order in which they should be copied to prevent + * things from getting screwed up. A call is also made through the + * backingGC to take care of any copying into the backing pixmap. + * + *----------------------------------------------------------------------- + */ +static Bool +miBSDoCopy(pWin, pGC, srcx, srcy, w, h, dstx, dsty, plane, copyProc, ppRgn) + WindowPtr pWin; /* Window being scrolled */ + GCPtr pGC; /* GC we're called through */ + int srcx; /* X of source rectangle */ + int srcy; /* Y of source rectangle */ + int w; /* Width of source rectangle */ + int h; /* Height of source rectangle */ + int dstx; /* X of destination rectangle */ + int dsty; /* Y of destination rectangle */ + unsigned long plane; /* Plane to copy (0 for CopyArea) */ + RegionPtr (*copyProc)(); /* Procedure to call to perform the copy */ + RegionPtr *ppRgn; /* resultant Graphics Expose region */ +{ + RegionPtr pRgnExp; /* Exposed region */ + RegionPtr pRgnObs; /* Obscured region */ + BoxRec box; /* Source box (screen coord) */ + struct BoxDraw { + BoxPtr pBox; /* Source box */ + enum { + win, pix + } source; /* Place from which to copy */ + } *boxes; /* Array of box/drawable pairs covering + * source box. */ + int *sequence; /* Sequence of boxes to move */ + register int i, j, k, l, y; + register BoxPtr pBox; + int dx, dy, nrects; + Bool graphicsExposures; + RegionPtr (*pixCopyProc)(); + int numRectsExp, numRectsObs; + BoxPtr pBoxExp, pBoxObs; + + SETUP_BACKING (pWin, pGC); + + /* + * Create a region of exposed boxes in pRgnExp. + */ + box.x1 = srcx + pWin->drawable.x; + box.x2 = box.x1 + w; + box.y1 = srcy + pWin->drawable.y; + box.y2 = box.y1 + h; + + pRgnExp = REGION_CREATE(pGC->pScreen, &box, 1); + REGION_INTERSECT(pGC->pScreen, pRgnExp, pRgnExp, &pWin->clipList); + pRgnObs = REGION_CREATE(pGC->pScreen, NULL, 1); + REGION_INVERSE( pGC->pScreen, pRgnObs, pRgnExp, &box); + + /* + * Translate regions into window coordinates for proper calls + * to the copyProc, then make sure none of the obscured region sticks + * into invalid areas of the backing pixmap. + */ + REGION_TRANSLATE(pGC->pScreen, pRgnExp, + -pWin->drawable.x, + -pWin->drawable.y); + REGION_TRANSLATE(pGC->pScreen, pRgnObs, + -pWin->drawable.x, + -pWin->drawable.y); + REGION_INTERSECT(pGC->pScreen, pRgnObs, pRgnObs, &pBackingStore->SavedRegion); + + /* + * If the obscured region is empty, there's no point being fancy. + */ + if (!REGION_NOTEMPTY(pGC->pScreen, pRgnObs)) + { + REGION_DESTROY(pGC->pScreen, pRgnExp); + REGION_DESTROY(pGC->pScreen, pRgnObs); + + return (FALSE); + } + + numRectsExp = REGION_NUM_RECTS(pRgnExp); + pBoxExp = REGION_RECTS(pRgnExp); + pBoxObs = REGION_RECTS(pRgnObs); + numRectsObs = REGION_NUM_RECTS(pRgnObs); + nrects = numRectsExp + numRectsObs; + + boxes = (struct BoxDraw *)ALLOCATE_LOCAL(nrects * sizeof(struct BoxDraw)); + sequence = (int *) ALLOCATE_LOCAL(nrects * sizeof(int)); + *ppRgn = NULL; + + if (!boxes || !sequence) + { + if (sequence) DEALLOCATE_LOCAL(sequence); + if (boxes) DEALLOCATE_LOCAL(boxes); + REGION_DESTROY(pGC->pScreen, pRgnExp); + REGION_DESTROY(pGC->pScreen, pRgnObs); + + return(TRUE); + } + + /* + * Order the boxes in the two regions so we know from which drawable + * to copy which box, storing the result in the boxes array + */ + for (i = 0, j = 0, k = 0; + (i < numRectsExp) && (j < numRectsObs); + k++) + { + if (pBoxExp[i].y1 < pBoxObs[j].y1) + { + boxes[k].pBox = &pBoxExp[i]; + boxes[k].source = win; + i++; + } + else if ((pBoxObs[j].y1 < pBoxExp[i].y1) || + (pBoxObs[j].x1 < pBoxExp[i].x1)) + { + boxes[k].pBox = &pBoxObs[j]; + boxes[k].source = pix; + j++; + } + else + { + boxes[k].pBox = &pBoxExp[i]; + boxes[k].source = win; + i++; + } + } + + /* + * Catch any leftover boxes from either region (note that only + * one can have leftover boxes...) + */ + if (i != numRectsExp) + { + do + { + boxes[k].pBox = &pBoxExp[i]; + boxes[k].source = win; + i++; + k++; + } while (i < numRectsExp); + + } + else + { + do + { + boxes[k].pBox = &pBoxObs[j]; + boxes[k].source = pix; + j++; + k++; + } while (j < numRectsObs); + } + + if (dsty <= srcy) + { + /* + * Scroll up or vertically stationary, so vertical order is ok. + */ + if (dstx <= srcx) + { + /* + * Scroll left or horizontally stationary, so horizontal order + * is ok as well. + */ + for (i = 0; i < nrects; i++) + { + sequence[i] = i; + } + } + else + { + /* + * Scroll right. Need to reverse the rectangles within each + * band. + */ + for (i = 0, j = 1, k = 0; + i < nrects; + j = i + 1, k = i) + { + y = boxes[i].pBox->y1; + while ((j < nrects) && (boxes[j].pBox->y1 == y)) + { + j++; + } + for (j--; j >= k; j--, i++) + { + sequence[i] = j; + } + } + } + } + else + { + /* + * Scroll down. Must reverse vertical banding, at least. + */ + if (dstx < srcx) + { + /* + * Scroll left. Horizontal order is ok. + */ + for (i = nrects - 1, j = i - 1, k = i, l = 0; + i >= 0; + j = i - 1, k = i) + { + /* + * Find extent of current horizontal band, then reverse + * the order of the whole band. + */ + y = boxes[i].pBox->y1; + while ((j >= 0) && (boxes[j].pBox->y1 == y)) + { + j--; + } + for (j++; j <= k; j++, i--, l++) + { + sequence[l] = j; + } + } + } + else + { + /* + * Scroll right or horizontal stationary. + * Reverse horizontal order as well (if stationary, horizontal + * order can be swapped without penalty and this is faster + * to compute). + */ + for (i = 0, j = nrects - 1; i < nrects; i++, j--) + { + sequence[i] = j; + } + } + } + + /* + * XXX: To avoid getting multiple NoExpose events from this operation, + * we turn OFF graphicsExposures in the gc and deal with any uncopied + * areas later, if there's something not in backing-store. + */ + + graphicsExposures = pGC->graphicsExposures; + pGC->graphicsExposures = FALSE; + + dx = dstx - srcx; + dy = dsty - srcy; + + /* + * Figure out which copy procedure to use from the backing GC. Note we + * must do this because some implementations (sun's, e.g.) have + * pBackingGC a fake GC with the real one below it, thus the devPriv for + * pBackingGC won't be what the output library expects. + */ + if (plane != 0) + { + pixCopyProc = pBackingGC->ops->CopyPlane; + } + else + { + pixCopyProc = pBackingGC->ops->CopyArea; + } + + for (i = 0; i < nrects; i++) + { + pBox = boxes[sequence[i]].pBox; + + /* + * If we're copying from the pixmap, we need to place its contents + * onto the screen before scrolling the pixmap itself. If we're copying + * from the window, we need to copy its contents into the pixmap before + * we scroll the window itself. + */ + if (boxes[sequence[i]].source == pix) + { + (void) (* copyProc) (pBackingDrawable, pWin, pGC, + pBox->x1 - pBackingStore->x, + pBox->y1 - pBackingStore->y, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, + pBox->x1 + dx, pBox->y1 + dy, plane); + (void) (* pixCopyProc) (pBackingDrawable, pBackingDrawable, pBackingGC, + pBox->x1 - pBackingStore->x, + pBox->y1 - pBackingStore->y, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, + pBox->x1 + dx - pBackingStore->x, + pBox->y1 + dy - pBackingStore->y, plane); + } + else + { + (void) (* pixCopyProc) (pWin, pBackingDrawable, pBackingGC, + pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, + pBox->x1 + dx - pBackingStore->x, + pBox->y1 + dy - pBackingStore->y, plane); + (void) (* copyProc) (pWin, pWin, pGC, + pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, + pBox->x1 + dx, pBox->y1 + dy, plane); + } + } + DEALLOCATE_LOCAL(sequence); + DEALLOCATE_LOCAL(boxes); + + pGC->graphicsExposures = graphicsExposures; + /* + * Form union of rgnExp and rgnObs and see if covers entire area + * to be copied. Store the resultant region for miBSCopyArea + * to return to dispatch which will send the appropriate expose + * events. + */ + REGION_UNION(pGC->pScreen, pRgnExp, pRgnExp, pRgnObs); + box.x1 = srcx; + box.x2 = srcx + w; + box.y1 = srcy; + box.y2 = srcy + h; + if (RECT_IN_REGION(pGC->pScreen, pRgnExp, &box) == rgnIN) + { + REGION_EMPTY(pGC->pScreen, pRgnExp); + } + else + { + REGION_INVERSE( pGC->pScreen, pRgnExp, pRgnExp, &box); + REGION_TRANSLATE( pGC->pScreen, pRgnExp, + dx + pWin->drawable.x, + dy + pWin->drawable.y); + REGION_INTERSECT( pGC->pScreen, pRgnObs, pRgnExp, &pWin->clipList); + (*pWin->drawable.pScreen->PaintWindowBackground) (pWin, + pRgnObs, PW_BACKGROUND); + REGION_TRANSLATE( pGC->pScreen, pRgnExp, + -pWin->drawable.x, + -pWin->drawable.y); + miBSClearBackingRegion (pWin, pRgnExp); + } + if (graphicsExposures) + *ppRgn = pRgnExp; + else + REGION_DESTROY(pGC->pScreen, pRgnExp); + REGION_DESTROY(pGC->pScreen, pRgnObs); + + return (TRUE); +} + +/*- + *----------------------------------------------------------------------- + * miBSCopyArea -- + * Perform a CopyArea from the source to the destination, extracting + * from the source's backing-store and storing into the destination's + * backing-store without messing anything up. If the source and + * destination are different, there's not too much to worry about: + * we can just issue several calls to the regular CopyArea function. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static RegionPtr +miBSCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) + DrawablePtr pSrc; + DrawablePtr pDst; + GCPtr pGC; + int srcx; + int srcy; + int w; + int h; + int dstx; + int dsty; +{ + BoxPtr pExtents; + long dx, dy; + int bsrcx, bsrcy, bw, bh, bdstx, bdsty; + RegionPtr pixExposed = 0, winExposed = 0; + + SETUP_BACKING(pDst, pGC); + + PROLOGUE(pGC); + + if ((pSrc != pDst) || + (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty, + (unsigned long) 0, pGC->ops->CopyArea, &winExposed))) + { + /* + * always copy to the backing store first, miBSDoCopy + * returns FALSE if the *source* region is disjoint + * from the backing store saved region. So, copying + * *to* the backing store is always safe + */ + if (pGC->clientClipType != CT_PIXMAP) + { + /* + * adjust srcx, srcy, w, h, dstx, dsty to be clipped to + * the backing store. An unnecessary optimisation, + * but a useful one when GetSpans is slow. + */ + pExtents = REGION_EXTENTS(pDst->pScreen, + (RegionPtr)pBackingGC->clientClip); + bsrcx = srcx; + bsrcy = srcy; + bw = w; + bh = h; + bdstx = dstx; + bdsty = dsty; + dx = pExtents->x1 - bdstx; + if (dx > 0) + { + bsrcx += dx; + bdstx += dx; + bw -= dx; + } + dy = pExtents->y1 - bdsty; + if (dy > 0) + { + bsrcy += dy; + bdsty += dy; + bh -= dy; + } + dx = (bdstx + bw) - pExtents->x2; + if (dx > 0) + bw -= dx; + dy = (bdsty + bh) - pExtents->y2; + if (dy > 0) + bh -= dy; + if (bw > 0 && bh > 0) + pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, + pBackingDrawable, pBackingGC, + bsrcx, bsrcy, bw, bh, bdstx - pBackingStore->x, + bdsty - pBackingStore->y); + } + else + pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, + pBackingDrawable, pBackingGC, + srcx, srcy, w, h, + dstx - pBackingStore->x, dsty - pBackingStore->y); + + winExposed = (* pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + } + + /* + * compute the composite graphics exposure region + */ + if (winExposed) + { + if (pixExposed){ + REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed); + REGION_DESTROY(pDst->pScreen, pixExposed); + } + } else + winExposed = pixExposed; + + EPILOGUE (pGC); + + return winExposed; +} + +/*- + *----------------------------------------------------------------------- + * miBSCopyPlane -- + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static RegionPtr +miBSCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) + DrawablePtr pSrc; + DrawablePtr pDst; + register GC *pGC; + int srcx, + srcy; + int w, + h; + int dstx, + dsty; + unsigned long plane; +{ + BoxPtr pExtents; + long dx, dy; + int bsrcx, bsrcy, bw, bh, bdstx, bdsty; + RegionPtr winExposed = 0, pixExposed = 0; + SETUP_BACKING(pDst, pGC); + + PROLOGUE(pGC); + + if ((pSrc != pDst) || + (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty, + plane, pGC->ops->CopyPlane, &winExposed))) + { + /* + * always copy to the backing store first, miBSDoCopy + * returns FALSE if the *source* region is disjoint + * from the backing store saved region. So, copying + * *to* the backing store is always safe + */ + if (pGC->clientClipType != CT_PIXMAP) + { + /* + * adjust srcx, srcy, w, h, dstx, dsty to be clipped to + * the backing store. An unnecessary optimisation, + * but a useful one when GetSpans is slow. + */ + pExtents = REGION_EXTENTS(pDst->pScreen, + (RegionPtr)pBackingGC->clientClip); + bsrcx = srcx; + bsrcy = srcy; + bw = w; + bh = h; + bdstx = dstx; + bdsty = dsty; + dx = pExtents->x1 - bdstx; + if (dx > 0) + { + bsrcx += dx; + bdstx += dx; + bw -= dx; + } + dy = pExtents->y1 - bdsty; + if (dy > 0) + { + bsrcy += dy; + bdsty += dy; + bh -= dy; + } + dx = (bdstx + bw) - pExtents->x2; + if (dx > 0) + bw -= dx; + dy = (bdsty + bh) - pExtents->y2; + if (dy > 0) + bh -= dy; + if (bw > 0 && bh > 0) + pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc, + pBackingDrawable, + pBackingGC, bsrcx, bsrcy, bw, bh, + bdstx - pBackingStore->x, + bdsty - pBackingStore->y, plane); + } + else + pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc, + pBackingDrawable, + pBackingGC, srcx, srcy, w, h, + dstx - pBackingStore->x, + dsty - pBackingStore->y, plane); + + winExposed = (* pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, plane); + + } + + /* + * compute the composite graphics exposure region + */ + if (winExposed) + { + if (pixExposed) + { + REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed); + REGION_DESTROY(pDst->pScreen, pixExposed); + } + } else + winExposed = pixExposed; + + EPILOGUE (pGC); + + return winExposed; +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyPoint -- + * Perform a PolyPoint, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolyPoint (pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; + xPoint *pptInit; +{ + xPoint *pptCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pptCopy = (xPoint *)ALLOCATE_LOCAL(npt*sizeof(xPoint)); + if (pptCopy) + { + copyPoints(pptInit, pptCopy, npt, mode); + + (* pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit); + + (* pBackingGC->ops->PolyPoint) (pBackingDrawable, + pBackingGC, mode, npt, pptCopy); + + DEALLOCATE_LOCAL(pptCopy); + } + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyLines -- + * Perform a Polylines, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolylines (pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int npt; + DDXPointPtr pptInit; +{ + DDXPointPtr pptCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(npt*sizeof(DDXPointRec)); + if (pptCopy) + { + copyPoints(pptInit, pptCopy, npt, mode); + + (* pGC->ops->Polylines)(pDrawable, pGC, mode, npt, pptInit); + (* pBackingGC->ops->Polylines)(pBackingDrawable, + pBackingGC, mode, npt, pptCopy); + DEALLOCATE_LOCAL(pptCopy); + } + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPolySegment -- + * Perform a PolySegment, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolySegment(pDrawable, pGC, nseg, pSegs) + DrawablePtr pDrawable; + GCPtr pGC; + int nseg; + xSegment *pSegs; +{ + xSegment *pSegsCopy; + + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pSegsCopy = (xSegment *)ALLOCATE_LOCAL(nseg*sizeof(xSegment)); + if (pSegsCopy) + { + copyData(pSegs, pSegsCopy, nseg << 1, MoreCopy0); + + (* pGC->ops->PolySegment)(pDrawable, pGC, nseg, pSegs); + (* pBackingGC->ops->PolySegment)(pBackingDrawable, + pBackingGC, nseg, pSegsCopy); + + DEALLOCATE_LOCAL(pSegsCopy); + } + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyRectangle -- + * Perform a PolyRectangle, routing output to backing-store as needed. + * + * Results: + * None + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolyRectangle(pDrawable, pGC, nrects, pRects) + DrawablePtr pDrawable; + GCPtr pGC; + int nrects; + xRectangle *pRects; +{ + xRectangle *pRectsCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pRectsCopy =(xRectangle *)ALLOCATE_LOCAL(nrects*sizeof(xRectangle)); + if (pRectsCopy) + { + copyData(pRects, pRectsCopy, nrects, MoreCopy2); + + (* pGC->ops->PolyRectangle)(pDrawable, pGC, nrects, pRects); + (* pBackingGC->ops->PolyRectangle)(pBackingDrawable, + pBackingGC, nrects, pRectsCopy); + + DEALLOCATE_LOCAL(pRectsCopy); + } + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyArc -- + * Perform a PolyArc, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolyArc(pDrawable, pGC, narcs, parcs) + DrawablePtr pDrawable; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + xArc *pArcsCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc)); + if (pArcsCopy) + { + copyData(parcs, pArcsCopy, narcs, MoreCopy4); + + (* pGC->ops->PolyArc)(pDrawable, pGC, narcs, parcs); + (* pBackingGC->ops->PolyArc)(pBackingDrawable, pBackingGC, + narcs, pArcsCopy); + + DEALLOCATE_LOCAL(pArcsCopy); + } + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSFillPolygon -- + * Perform a FillPolygon, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSFillPolygon(pDrawable, pGC, shape, mode, count, pPts) + DrawablePtr pDrawable; + register GCPtr pGC; + int shape, mode; + register int count; + DDXPointPtr pPts; +{ + DDXPointPtr pPtsCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pPtsCopy = (DDXPointPtr)ALLOCATE_LOCAL(count*sizeof(DDXPointRec)); + if (pPtsCopy) + { + copyPoints(pPts, pPtsCopy, count, mode); + (* pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, count, pPts); + (* pBackingGC->ops->FillPolygon)(pBackingDrawable, + pBackingGC, shape, mode, + count, pPtsCopy); + + DEALLOCATE_LOCAL(pPtsCopy); + } + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyFillRect -- + * Perform a PolyFillRect, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolyFillRect(pDrawable, pGC, nrectFill, prectInit) + DrawablePtr pDrawable; + GCPtr pGC; + int nrectFill; /* number of rectangles to fill */ + xRectangle *prectInit; /* Pointer to first rectangle to fill */ +{ + xRectangle *pRectCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pRectCopy = + (xRectangle *)ALLOCATE_LOCAL(nrectFill*sizeof(xRectangle)); + if (pRectCopy) + { + copyData(prectInit, pRectCopy, nrectFill, MoreCopy2); + + (* pGC->ops->PolyFillRect)(pDrawable, pGC, nrectFill, prectInit); + (* pBackingGC->ops->PolyFillRect)(pBackingDrawable, + pBackingGC, nrectFill, pRectCopy); + + DEALLOCATE_LOCAL(pRectCopy); + } + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyFillArc -- + * Perform a PolyFillArc, routing output to backing-store as needed. + * + * Results: + * None. + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolyFillArc(pDrawable, pGC, narcs, parcs) + DrawablePtr pDrawable; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + xArc *pArcsCopy; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc)); + if (pArcsCopy) + { + copyData(parcs, pArcsCopy, narcs, MoreCopy4); + (* pGC->ops->PolyFillArc)(pDrawable, pGC, narcs, parcs); + (* pBackingGC->ops->PolyFillArc)(pBackingDrawable, + pBackingGC, narcs, pArcsCopy); + DEALLOCATE_LOCAL(pArcsCopy); + } + + EPILOGUE (pGC); +} + + +/*- + *----------------------------------------------------------------------- + * miBSPolyText8 -- + * Perform a PolyText8, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static int +miBSPolyText8(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + char *chars; +{ + int result; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + result = (* pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + (* pBackingGC->ops->PolyText8)(pBackingDrawable, pBackingGC, + x - pBackingStore->x, y - pBackingStore->y, + count, chars); + + EPILOGUE (pGC); + return result; +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyText16 -- + * Perform a PolyText16, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static int +miBSPolyText16(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + unsigned short *chars; +{ + int result; + SETUP_BACKING (pDrawable, pGC); + + PROLOGUE(pGC); + + result = (* pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + (* pBackingGC->ops->PolyText16)(pBackingDrawable, pBackingGC, + x - pBackingStore->x, y - pBackingStore->y, + count, chars); + + EPILOGUE (pGC); + + return result; +} + +/*- + *----------------------------------------------------------------------- + * miBSImageText8 -- + * Perform a ImageText8, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSImageText8(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + char *chars; +{ + SETUP_BACKING (pDrawable, pGC); + PROLOGUE(pGC); + + (* pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + (* pBackingGC->ops->ImageText8)(pBackingDrawable, pBackingGC, + x - pBackingStore->x, y - pBackingStore->y, + count, chars); + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSImageText16 -- + * Perform a ImageText16, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSImageText16(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + unsigned short *chars; +{ + SETUP_BACKING (pDrawable, pGC); + PROLOGUE(pGC); + + (* pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + (* pBackingGC->ops->ImageText16)(pBackingDrawable, pBackingGC, + x - pBackingStore->x, y - pBackingStore->y, + count, chars); + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSImageGlyphBlt -- + * Perform a ImageGlyphBlt, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + SETUP_BACKING (pDrawable, pGC); + PROLOGUE(pGC); + + (* pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci, + pglyphBase); + (* pBackingGC->ops->ImageGlyphBlt)(pBackingDrawable, pBackingGC, + x - pBackingStore->x, y - pBackingStore->y, + nglyph, ppci, pglyphBase); + + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPolyGlyphBlt -- + * Perform a PolyGlyphBlt, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + SETUP_BACKING (pDrawable, pGC); + PROLOGUE(pGC); + + (* pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + (* pBackingGC->ops->PolyGlyphBlt)(pBackingDrawable, pBackingGC, + x - pBackingStore->x, y - pBackingStore->y, + nglyph, ppci, pglyphBase); + EPILOGUE (pGC); +} + +/*- + *----------------------------------------------------------------------- + * miBSPushPixels -- + * Perform a PushPixels, routing output to backing-store as needed. + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +static void +miBSPushPixels(pGC, pBitMap, pDst, w, h, x, y) + GCPtr pGC; + PixmapPtr pBitMap; + DrawablePtr pDst; + int w, h, x, y; +{ + SETUP_BACKING (pDst, pGC); + PROLOGUE(pGC); + + (* pGC->ops->PushPixels)(pGC, pBitMap, pDst, w, h, x, y); + if (pGC->miTranslate) { + x -= pDst->x; + y -= pDst->y; + } + (* pBackingGC->ops->PushPixels)(pBackingGC, pBitMap, + pBackingDrawable, w, h, + x - pBackingStore->x, y - pBackingStore->y); + + EPILOGUE (pGC); +} + +#ifdef NEED_LINEHELPER +/*- + *----------------------------------------------------------------------- + * miBSLineHelper -- + * + * Results: should never be called + * + * Side Effects: server dies + * + *----------------------------------------------------------------------- + */ +static void +miBSLineHelper() +{ + FatalError("miBSLineHelper called\n"); +} +#endif + +/*- + *----------------------------------------------------------------------- + * miBSClearBackingStore -- + * Clear the given area of the backing pixmap with the background of + * the window, whatever it is. If generateExposures is TRUE, generate + * exposure events for the area. Note that if the area has any + * part outside the saved portions of the window, we do not allow the + * count in the expose events to be 0, since there will be more + * expose events to come. + * + * Results: + * None. + * + * Side Effects: + * Areas of pixmap are cleared and Expose events are generated. + * + *----------------------------------------------------------------------- + */ +static RegionPtr +miBSClearBackingStore(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x; + int y; + int w; + int h; + Bool generateExposures; +{ + RegionPtr pRgn; + int i; + miBSWindowPtr pBackingStore; + ScreenPtr pScreen; + GCPtr pGC; + int ts_x_origin, + ts_y_origin; + pointer gcvalues[4]; + unsigned long gcmask; + xRectangle *rects; + BoxPtr pBox; + BoxRec box; + PixUnion background; + char backgroundState; + int numRects; + + pBackingStore = (miBSWindowPtr)pWin->backStorage; + pScreen = pWin->drawable.pScreen; + + if ((pBackingStore->status == StatusNoPixmap) || + (pBackingStore->status == StatusBadAlloc)) + return NullRegion; + + if (w == 0) + w = (int) pWin->drawable.width - x; + if (h == 0) + h = (int) pWin->drawable.height - y; + + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); + if (!pRgn) + return NullRegion; + REGION_INTERSECT( pScreen, pRgn, pRgn, &pBackingStore->SavedRegion); + + if (REGION_NOTEMPTY( pScreen, pRgn)) + { + /* + * if clearing entire window, simply make new virtual + * tile. For the root window, we also destroy the pixmap + * to save a pile of memory + */ + if (x == 0 && y == 0 && + w == pWin->drawable.width && + h == pWin->drawable.height) + { + if (!pWin->parent) + miDestroyBSPixmap (pWin); + if (pBackingStore->status != StatusContents) + miTileVirtualBS (pWin); + } + + ts_x_origin = ts_y_origin = 0; + + backgroundState = pWin->backgroundState; + background = pWin->background; + if (backgroundState == ParentRelative) { + WindowPtr pParent; + + pParent = pWin; + while (pParent->backgroundState == ParentRelative) { + ts_x_origin -= pParent->origin.x; + ts_y_origin -= pParent->origin.y; + pParent = pParent->parent; + } + backgroundState = pParent->backgroundState; + background = pParent->background; + } + + if ((backgroundState != None) && + ((pBackingStore->status == StatusContents) || + !SameBackground (pBackingStore->backgroundState, + pBackingStore->background, + backgroundState, + background))) + { + if (!pBackingStore->pBackingPixmap) + miCreateBSPixmap(pWin, NullBox); + + pGC = GetScratchGC(pWin->drawable.depth, pScreen); + if (pGC && pBackingStore->pBackingPixmap) + { + /* + * First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + + if (backgroundState == BackgroundPixel) + { + gcvalues[0] = (pointer) background.pixel; + gcvalues[1] = (pointer)FillSolid; + gcmask = GCForeground|GCFillStyle; + } + else + { + gcvalues[0] = (pointer)FillTiled; + gcvalues[1] = (pointer) background.pixmap; + gcmask = GCFillStyle|GCTile; + } + gcvalues[2] = (pointer)(ts_x_origin - pBackingStore->x); + gcvalues[3] = (pointer)(ts_y_origin - pBackingStore->y); + gcmask |= GCTileStipXOrigin|GCTileStipYOrigin; + DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE); + ValidateGC((DrawablePtr)pBackingStore->pBackingPixmap, pGC); + + /* + * Figure out the array of rectangles to fill and fill them with + * PolyFillRect in the proper mode, as set in the GC above. + */ + numRects = REGION_NUM_RECTS(pRgn); + rects = (xRectangle *)ALLOCATE_LOCAL(numRects*sizeof(xRectangle)); + + if (rects) + { + for (i = 0, pBox = REGION_RECTS(pRgn); + i < numRects; + i++, pBox++) + { + rects[i].x = pBox->x1 - pBackingStore->x; + rects[i].y = pBox->y1 - pBackingStore->y; + rects[i].width = pBox->x2 - pBox->x1; + rects[i].height = pBox->y2 - pBox->y1; + } + (* pGC->ops->PolyFillRect) ( + (DrawablePtr)pBackingStore->pBackingPixmap, + pGC, numRects, rects); + DEALLOCATE_LOCAL(rects); + } + FreeScratchGC(pGC); + } + } + + if (!generateExposures) + { + REGION_DESTROY(pScreen, pRgn); + pRgn = NULL; + } + else + { + /* + * result must be screen relative, but is currently + * drawable relative. + */ + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, + pWin->drawable.y); + } + } + else + { + REGION_DESTROY( pScreen, pRgn); + pRgn = NULL; + } + return pRgn; +} + +static void +miBSClearBackingRegion (pWin, pRgn) + WindowPtr pWin; + RegionPtr pRgn; +{ + BoxPtr pBox; + int i; + + i = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + while (i--) + { + (void) miBSClearBackingStore(pWin, pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + FALSE); + pBox++; + } +} + +/* + * fill a region of the destination with virtual bits + * + * pRgn is to be translated by (x,y) + */ + +static void +miBSFillVirtualBits (pDrawable, pGC, pRgn, x, y, state, pixunion, planeMask) + DrawablePtr pDrawable; + GCPtr pGC; + RegionPtr pRgn; + int x, y; + int state; + PixUnion pixunion; + unsigned long planeMask; +{ + int i; + BITS32 gcmask; + pointer gcval[5]; + xRectangle *pRect; + BoxPtr pBox; + WindowPtr pWin; + int numRects; + + if (state == None) + return; + numRects = REGION_NUM_RECTS(pRgn); + pRect = (xRectangle *)ALLOCATE_LOCAL(numRects * sizeof(xRectangle)); + if (!pRect) + return; + pWin = 0; + if (pDrawable->type != DRAWABLE_PIXMAP) + { + pWin = (WindowPtr) pDrawable; + if (!pWin->backStorage) + pWin = 0; + } + i = 0; + gcmask = 0; + gcval[i++] = (pointer)planeMask; + gcmask |= GCPlaneMask; + if (state == BackgroundPixel) + { + if (pGC->fgPixel != pixunion.pixel) + { + gcval[i++] = (pointer)pixunion.pixel; + gcmask |= GCForeground; + } + if (pGC->fillStyle != FillSolid) + { + gcval[i++] = (pointer)FillSolid; + gcmask |= GCFillStyle; + } + } + else + { + if (pGC->fillStyle != FillTiled) + { + gcval[i++] = (pointer)FillTiled; + gcmask |= GCFillStyle; + } + if (pGC->tileIsPixel || pGC->tile.pixmap != pixunion.pixmap) + { + gcval[i++] = (pointer)pixunion.pixmap; + gcmask |= GCTile; + } + if (pGC->patOrg.x != x) + { + gcval[i++] = (pointer)x; + gcmask |= GCTileStipXOrigin; + } + if (pGC->patOrg.y != y) + { + gcval[i++] = (pointer)y; + gcmask |= GCTileStipYOrigin; + } + } + if (gcmask) + DoChangeGC (pGC, gcmask, (XID *)gcval, 1); + + if (pWin) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + if (pDrawable->serialNumber != pGC->serialNumber) + ValidateGC (pDrawable, pGC); + + pBox = REGION_RECTS(pRgn); + for (i = numRects; --i >= 0; pBox++, pRect++) + { + pRect->x = pBox->x1 + x; + pRect->y = pBox->y1 + y; + pRect->width = pBox->x2 - pBox->x1; + pRect->height = pBox->y2 - pBox->y1; + } + pRect -= numRects; + (*pGC->ops->PolyFillRect) (pDrawable, pGC, numRects, pRect); + if (pWin) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + DEALLOCATE_LOCAL (pRect); +} + +/*- + *----------------------------------------------------------------------- + * miBSAllocate -- + * Create and install backing store info for a window + * + *----------------------------------------------------------------------- + */ + +static void +miBSAllocate(pWin) + WindowPtr pWin; +{ + register miBSWindowPtr pBackingStore; + register ScreenPtr pScreen; + + if (pWin->drawable.pScreen->backingStoreSupport == NotUseful) + return; + pScreen = pWin->drawable.pScreen; + if (!(pBackingStore = (miBSWindowPtr)pWin->backStorage)) + { + + pBackingStore = (miBSWindowPtr)xalloc(sizeof(miBSWindowRec)); + if (!pBackingStore) + return; + + pBackingStore->pBackingPixmap = NullPixmap; + pBackingStore->x = 0; + pBackingStore->y = 0; + REGION_INIT( pScreen, &pBackingStore->SavedRegion, NullBox, 1); + pBackingStore->viewable = (char)pWin->viewable; + pBackingStore->status = StatusNoPixmap; + pBackingStore->backgroundState = None; + pWin->backStorage = (pointer) pBackingStore; + } + + /* + * Now want to initialize the backing pixmap and SavedRegion if + * necessary. The initialization consists of finding all the + * currently-obscured regions, by taking the inverse of the window's + * clip list, storing the result in SavedRegion, and exposing those + * areas of the window. + */ + + if (pBackingStore->status == StatusNoPixmap && + ((pWin->backingStore == WhenMapped && pWin->viewable) || + (pWin->backingStore == Always))) + { + BoxRec box; + RegionPtr pSavedRegion; + + pSavedRegion = &pBackingStore->SavedRegion; + + box.x1 = pWin->drawable.x; + box.x2 = box.x1 + (int) pWin->drawable.width; + box.y1 = pWin->drawable.y; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + + REGION_INVERSE( pScreen, pSavedRegion, &pWin->clipList, &box); + REGION_TRANSLATE( pScreen, pSavedRegion, + -pWin->drawable.x, + -pWin->drawable.y); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion, + wClipShape (pWin)); +#endif + /* if window is already on-screen, assume it has been drawn to */ + if (pWin->viewable) + pBackingStore->status = StatusVDirty; + miTileVirtualBS (pWin); + + /* + * deliver all the newly available regions + * as exposure events to the window + */ + + miSendExposures(pWin, pSavedRegion, 0, 0); + } + else if (!pWin->viewable) + { + /* + * Turn off backing store when we're not supposed to + * be saving anything + */ + if (pBackingStore->status != StatusNoPixmap) + { + REGION_EMPTY( pScreen, &pBackingStore->SavedRegion); + miDestroyBSPixmap (pWin); + } + } +} + +/*- + *----------------------------------------------------------------------- + * miBSFree -- + * Destroy and free all the stuff associated with the backing-store + * for the given window. + * + * Results: + * None. + * + * Side Effects: + * The backing pixmap and all the regions and GC's are destroyed. + * + *----------------------------------------------------------------------- + */ +static void +miBSFree(pWin) + WindowPtr pWin; +{ + miBSWindowPtr pBackingStore; + register ScreenPtr pScreen = pWin->drawable.pScreen; + + pBackingStore = (miBSWindowPtr)pWin->backStorage; + if (pBackingStore) + { + miDestroyBSPixmap (pWin); + + REGION_UNINIT( pScreen, &pBackingStore->SavedRegion); + + xfree(pBackingStore); + pWin->backStorage = NULL; + } +} + +/*- + *----------------------------------------------------------------------- + * miResizeBackingStore -- + * Alter the size of the backing pixmap as necessary when the + * SavedRegion changes size. The contents of the old pixmap are + * copied/shifted into the new/same pixmap. + * + * Results: + * The new Pixmap is created as necessary. + * + * Side Effects: + * The old pixmap is destroyed. + * + *----------------------------------------------------------------------- + */ +static void +miResizeBackingStore(pWin, dx, dy, saveBits) + WindowPtr pWin; + int dx, dy; /* bits are moving this far */ + Bool saveBits; /* bits are useful */ +{ + miBSWindowPtr pBackingStore; + PixmapPtr pBackingPixmap; + ScreenPtr pScreen; + GC *pGC; + BoxPtr extents; + PixmapPtr pNewPixmap; + int nx, ny; + int nw, nh; + + pBackingStore = (miBSWindowPtr)(pWin->backStorage); + pBackingPixmap = pBackingStore->pBackingPixmap; + if (!pBackingPixmap) + return; + pScreen = pWin->drawable.pScreen; + extents = REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion); + pNewPixmap = pBackingPixmap; + + nw = extents->x2 - extents->x1; + nh = extents->y2 - extents->y1; + + /* the policy here could be more sophisticated */ + if (nw != pBackingPixmap->drawable.width || + nh != pBackingPixmap->drawable.height) + { + if (!saveBits) + { + pNewPixmap = NullPixmap; + pBackingStore->status = StatusNoPixmap; + } + else + { + pNewPixmap = (PixmapPtr)(*pScreen->CreatePixmap) + (pScreen, + nw, nh, + pWin->drawable.depth); + if (!pNewPixmap) + { +#ifdef BSEAGER + pBackingStore->status = StatusNoPixmap; +#else + pBackingStore->status = StatusBadAlloc; +#endif + } + } + } + if (!pNewPixmap) + { + pBackingStore->x = 0; + pBackingStore->y = 0; + } + else + { + nx = pBackingStore->x - extents->x1 + dx; + ny = pBackingStore->y - extents->y1 + dy; + pBackingStore->x = extents->x1; + pBackingStore->y = extents->y1; + + if (saveBits && (pNewPixmap != pBackingPixmap || nx != 0 || ny != 0)) + { + pGC = GetScratchGC(pNewPixmap->drawable.depth, pScreen); + if (pGC) + { + ValidateGC((DrawablePtr)pNewPixmap, pGC); + /* if we implement a policy where the pixmap can be larger than + * the region extents, we might want to optimize this copyarea + * by only copying the old extents, rather than the entire + * pixmap + */ + (*pGC->ops->CopyArea)((DrawablePtr)pBackingPixmap, + (DrawablePtr)pNewPixmap, pGC, + 0, 0, + pBackingPixmap->drawable.width, + pBackingPixmap->drawable.height, + nx, ny); + FreeScratchGC(pGC); + } + } + } + /* SavedRegion is used in the backingGC clip; force an update */ + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (pNewPixmap != pBackingPixmap) + { + (* pScreen->DestroyPixmap)(pBackingPixmap); + pBackingStore->pBackingPixmap = pNewPixmap; + } +} + +/*- + *----------------------------------------------------------------------- + * miBSSaveDoomedAreas -- + * Saved the areas of the given window that are about to be + * obscured. If the window has moved, pObscured is expected to + * be at the new screen location and (dx,dy) is expected to be the offset + * to the window's previous location. + * + * Results: + * None. + * + * Side Effects: + * The region is copied from the screen into pBackingPixmap and + * SavedRegion is updated. + * + *----------------------------------------------------------------------- + */ +static void +miBSSaveDoomedAreas(pWin, pObscured, dx, dy) + register WindowPtr pWin; + RegionPtr pObscured; + int dx, dy; +{ + miBSWindowPtr pBackingStore; + ScreenPtr pScreen; + int x, y; + + pBackingStore = (miBSWindowPtr)pWin->backStorage; + pScreen = pWin->drawable.pScreen; + + /* + * If the window isn't realized, it's being unmapped, thus we don't + * want to save anything if backingStore isn't Always. + */ + if (!pWin->realized) + { + pBackingStore->viewable = (char)pWin->viewable; + if (pWin->backingStore != Always) + { + REGION_EMPTY( pScreen, &pBackingStore->SavedRegion); + miDestroyBSPixmap (pWin); + return; + } + if (pBackingStore->status == StatusBadAlloc) + pBackingStore->status = StatusNoPixmap; + } + + /* Don't even pretend to save anything for a virtual background None */ + if ((pBackingStore->status == StatusVirtual) && + (pBackingStore->backgroundState == None)) + return; + + if (REGION_NOTEMPTY(pScreen, pObscured)) + { + BoxRec oldExtents; + x = pWin->drawable.x; + y = pWin->drawable.y; + REGION_TRANSLATE(pScreen, pObscured, -x, -y); + oldExtents = *REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion); + REGION_UNION( pScreen, &pBackingStore->SavedRegion, + &pBackingStore->SavedRegion, + pObscured); + /* + * only save the bits if we've actually + * started using backing store + */ + if (pBackingStore->status != StatusVirtual) + { + miBSScreenPtr pScreenPriv; + + pScreenPriv = (miBSScreenPtr) pScreen->devPrivates[miBSScreenIndex].ptr; + if (!pBackingStore->pBackingPixmap) + miCreateBSPixmap (pWin, &oldExtents); + else + miResizeBackingStore(pWin, 0, 0, TRUE); + + if (pBackingStore->pBackingPixmap) { + if (pBackingStore->x | pBackingStore->y) + { + REGION_TRANSLATE( pScreen, pObscured, + -pBackingStore->x, + -pBackingStore->y); + x += pBackingStore->x; + y += pBackingStore->y; + } + (* pScreenPriv->funcs->SaveAreas) (pBackingStore->pBackingPixmap, + pObscured, x - dx, y - dy, pWin); + } + } + REGION_TRANSLATE(pScreen, pObscured, x, y); + } +} + +/*- + *----------------------------------------------------------------------- + * miBSRestoreAreas -- + * Restore areas from backing-store that are no longer obscured. + * expects prgnExposed to contain a screen-relative area. + * + * Results: + * The region to generate exposure events on (which may be + * different from the region to paint). + * + * Side Effects: + * Areas are copied from pBackingPixmap to the screen. prgnExposed + * is altered to contain the region that could not be restored from + * backing-store. + * + * Notes: + * This is called before sending any exposure events to the client, + * and so might be called if the window has grown. Changing the backing + * pixmap doesn't require revalidating the backingGC because the + * client's next output request will result in a call to ValidateGC, + * since the window clip region has changed, which will in turn call + * miValidateBackingStore. + *----------------------------------------------------------------------- + */ +static RegionPtr +miBSRestoreAreas(pWin, prgnExposed) + register WindowPtr pWin; + RegionPtr prgnExposed; +{ + PixmapPtr pBackingPixmap; + miBSWindowPtr pBackingStore; + RegionPtr prgnSaved; + RegionPtr prgnRestored; + register ScreenPtr pScreen; + RegionPtr exposures = prgnExposed; + + pScreen = pWin->drawable.pScreen; + pBackingStore = (miBSWindowPtr)pWin->backStorage; + pBackingPixmap = pBackingStore->pBackingPixmap; + + prgnSaved = &pBackingStore->SavedRegion; + + if (pBackingStore->status == StatusContents) + { + REGION_TRANSLATE(pScreen, prgnSaved, pWin->drawable.x, + pWin->drawable.y); + + prgnRestored = REGION_CREATE( pScreen, (BoxPtr)NULL, 1); + REGION_INTERSECT( pScreen, prgnRestored, prgnExposed, prgnSaved); + + /* + * Since prgnExposed is no longer obscured, we no longer + * will have a valid copy of it in backing-store, but there is a valid + * copy of it on screen, so subtract the area we just restored from + * from the area to be exposed. + */ + + if (REGION_NOTEMPTY( pScreen, prgnRestored)) + { + miBSScreenPtr pScreenPriv; + + REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed); + REGION_SUBTRACT( pScreen, prgnExposed, prgnExposed, prgnRestored); + + /* + * Do the actual restoration + */ + + pScreenPriv = (miBSScreenPtr) + pScreen->devPrivates[miBSScreenIndex].ptr; + (* pScreenPriv->funcs->RestoreAreas) (pBackingPixmap, + prgnRestored, + pWin->drawable.x + pBackingStore->x, + pWin->drawable.y + pBackingStore->y, pWin); + /* + * if the saved region is completely empty, dispose of the + * backing pixmap, otherwise, retranslate the saved + * region to window relative + */ + + if (REGION_NOTEMPTY(pScreen, prgnSaved)) + { + REGION_TRANSLATE(pScreen, prgnSaved, + -pWin->drawable.x, + -pWin->drawable.y); + miResizeBackingStore(pWin, 0, 0, TRUE); + } + else + miDestroyBSPixmap (pWin); + } + else + REGION_TRANSLATE(pScreen, prgnSaved, + -pWin->drawable.x, -pWin->drawable.y); + REGION_DESTROY( pScreen, prgnRestored); + + } + else if ((pBackingStore->status == StatusVirtual) || + (pBackingStore->status == StatusVDirty)) + { + REGION_TRANSLATE(pScreen, prgnSaved, + pWin->drawable.x, pWin->drawable.y); + exposures = REGION_CREATE( pScreen, NullBox, 1); + if (SameBackground (pBackingStore->backgroundState, + pBackingStore->background, + pWin->backgroundState, + pWin->background)) + { + REGION_SUBTRACT( pScreen, exposures, prgnExposed, prgnSaved); + } + else + { + miTileVirtualBS(pWin); + + /* we need to expose all we have (virtually) retiled */ + REGION_UNION( pScreen, exposures, prgnExposed, prgnSaved); + } + REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed); + REGION_TRANSLATE(pScreen, prgnSaved, + -pWin->drawable.x, -pWin->drawable.y); + } + else if (pWin->viewable && !pBackingStore->viewable && + pWin->backingStore != Always) + { + /* + * The window was just mapped and nothing has been saved in + * backing-store from the last time it was mapped. We want to capture + * any output to regions that are already obscured but there are no + * bits to snag off the screen, so we initialize things just as we did + * in miBSAllocate, above. + */ + BoxRec box; + + prgnSaved = &pBackingStore->SavedRegion; + + box.x1 = pWin->drawable.x; + box.x2 = box.x1 + (int) pWin->drawable.width; + box.y1 = pWin->drawable.y; + box.y2 = box.y1 + (int) pWin->drawable.height; + + REGION_INVERSE( pScreen, prgnSaved, &pWin->clipList, &box); + REGION_TRANSLATE( pScreen, prgnSaved, + -pWin->drawable.x, + -pWin->drawable.y); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, prgnSaved, prgnSaved, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, prgnSaved, prgnSaved, + wClipShape (pWin)); +#endif + miTileVirtualBS(pWin); + + exposures = REGION_CREATE( pScreen, &box, 1); + } + pBackingStore->viewable = (char)pWin->viewable; + return exposures; +} + + +/*- + *----------------------------------------------------------------------- + * miBSTranslateBackingStore -- + * Shift the backing-store in the given direction. Called when bit + * gravity is shifting things around. + * + * Results: + * An occluded region of the window which should be sent exposure events. + * This region should be in absolute coordinates (i.e. include + * new window position). + * + * Side Effects: + * If the window changed size as well as position, the backing pixmap + * is resized. The contents of the backing pixmap are shifted + * + * Warning: + * Bob and I have rewritten this routine quite a few times, each + * time it gets a few more cases correct, and introducing some + * interesting bugs. Naturally, I think the code is correct this + * time. + * + * Let me try to explain what this routine is for: + * + * It's called from SlideAndSizeWindow whenever a window + * with backing store is resized. There are two separate + * possibilities: + * + * a) The window has ForgetGravity + * + * In this case, windx, windy will be 0 and oldClip will + * be NULL. This indicates that all of the window contents + * currently saved offscreen should be discarded, and the + * entire window exposed. TranslateBackingStore, then, should + * prepare a completely new backing store region based on the + * new window clipList and return that region for exposure. + * + * b) The window has some other gravity + * + * In this case, windx, windy will be set to the distance + * that the bits should move within the window. oldClip + * will be set to the old visible portion of the window. + * TranslateBackingStore, then, should adjust the backing + * store to accommodate the portion of the existing backing + * store bits which coorespond to backing store bits which + * will still be occluded in the new configuration. oldx,oldy + * are set to the old position of the window on the screen. + * + * Furthermore, in this case any contents of the screen which + * are about to become occluded should be fetched from the screen + * and placed in backing store. This is to avoid the eventual + * occlusion by the win gravity shifting the child window bits around + * on top of this window, and potentially losing information + * + * It's also called from SetShape, but I think (he says not + * really knowing for sure) that this code will even work + * in that case. + *----------------------------------------------------------------------- + */ + +static RegionPtr +miBSTranslateBackingStore(pWin, windx, windy, oldClip, oldx, oldy) + WindowPtr pWin; + int windx; /* bit translation distance in window */ + int windy; + RegionPtr oldClip; /* Region being copied */ + int oldx; /* old window position */ + int oldy; +{ + register miBSWindowPtr pBackingStore; + register RegionPtr pSavedRegion; + register RegionPtr newSaved, doomed; + register ScreenPtr pScreen; + BoxRec extents; + int scrdx; /* bit translation distance on screen */ + int scrdy; + int dx; /* distance window moved on screen */ + int dy; + + pScreen = pWin->drawable.pScreen; + pBackingStore = (miBSWindowPtr)(pWin->backStorage); + if ((pBackingStore->status == StatusNoPixmap) || + (pBackingStore->status == StatusBadAlloc)) + return NullRegion; + + /* + * Compute the new saved region + */ + + newSaved = REGION_CREATE( pScreen, NullBox, 1); + extents.x1 = pWin->drawable.x; + extents.x2 = pWin->drawable.x + (int) pWin->drawable.width; + extents.y1 = pWin->drawable.y; + extents.y2 = pWin->drawable.y + (int) pWin->drawable.height; + REGION_INVERSE( pScreen, newSaved, &pWin->clipList, &extents); + + REGION_TRANSLATE( pScreen, newSaved, + -pWin->drawable.x, -pWin->drawable.y); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + if (wBoundingShape (pWin)) + REGION_INTERSECT( pScreen, newSaved, newSaved, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT( pScreen, newSaved, newSaved, wClipShape (pWin)); + } +#endif + + pSavedRegion = &pBackingStore->SavedRegion; + + /* now find any visible areas we can save from the screen */ + /* and then translate newSaved to old local coordinates */ + if (oldClip) + { + /* bit gravity makes things virtually too hard, punt */ + if (((windx != 0) || (windy != 0)) && + (pBackingStore->status != StatusContents)) + miCreateBSPixmap(pWin, NullBox); + + /* + * The window is moving this far on the screen + */ + dx = pWin->drawable.x - oldx; + dy = pWin->drawable.y - oldy; + /* + * The bits will be moving on the screen by the + * amount the window is moving + the amount the + * bits are moving within the window + */ + scrdx = windx + dx; + scrdy = windy + dy; + + /* + * intersect at old bit position to discover the + * bits on the screen which can be put into the + * new backing store + */ + REGION_TRANSLATE( pScreen, oldClip, windx - oldx, windy - oldy); + doomed = REGION_CREATE( pScreen, NullBox, 1); + REGION_INTERSECT( pScreen, doomed, oldClip, newSaved); + REGION_TRANSLATE( pScreen, oldClip, oldx - windx, oldy - windy); + + /* + * Translate the old saved region to the position in the + * window where it will appear to be + */ + REGION_TRANSLATE( pScreen, pSavedRegion, windx, windy); + + /* + * Add the old saved region to the new saved region, so + * that calls to RestoreAreas will be able to fetch those + * bits back + */ + REGION_UNION( pScreen, newSaved, newSaved, pSavedRegion); + + /* + * Swap the new saved region into the window + */ + { + RegionRec tmp; + + tmp = *pSavedRegion; + *pSavedRegion = *newSaved; + *newSaved = tmp; + } + miResizeBackingStore (pWin, windx, windy, TRUE); + + /* + * Compute the newly enabled region + * of backing store. This region will be + * set to background in the backing pixmap and + * sent as exposure events to the client. + */ + REGION_SUBTRACT( pScreen, newSaved, pSavedRegion, newSaved); + + /* + * Fetch bits which will be obscured from + * the screen + */ + if (REGION_NOTEMPTY( pScreen, doomed)) + { + /* + * Don't clear regions which have bits on the + * screen + */ + REGION_SUBTRACT( pScreen, newSaved, newSaved, doomed); + + /* + * Make the region to SaveDoomedAreas absolute, instead + * of window relative. + */ + REGION_TRANSLATE( pScreen, doomed, + pWin->drawable.x, pWin->drawable.y); + (* pScreen->SaveDoomedAreas) (pWin, doomed, scrdx, scrdy); + } + + REGION_DESTROY(pScreen, doomed); + + /* + * and clear whatever there is that's new + */ + if (REGION_NOTEMPTY( pScreen, newSaved)) + { + miBSClearBackingRegion (pWin, newSaved); + /* + * Make the exposed region absolute + */ + REGION_TRANSLATE(pScreen, newSaved, + pWin->drawable.x, + pWin->drawable.y); + } + else + { + REGION_DESTROY(pScreen, newSaved); + newSaved = NullRegion; + } + } + else + { + /* + * ForgetGravity: just reset backing store and + * expose the whole mess + */ + REGION_COPY( pScreen, pSavedRegion, newSaved); + REGION_TRANSLATE( pScreen, newSaved, + pWin->drawable.x, pWin->drawable.y); + + miResizeBackingStore (pWin, 0, 0, FALSE); + (void) miBSClearBackingStore (pWin, 0, 0, 0, 0, FALSE); + } + + return newSaved; +} + +/* + * Inform the backing store layer that you are about to validate + * a gc with a window, and that subsequent output to the window + * is (or is not) guaranteed to be already clipped to the visible + * regions of the window. + */ + +static void +miBSDrawGuarantee (pWin, pGC, guarantee) + WindowPtr pWin; + GCPtr pGC; + int guarantee; +{ + miBSGCPtr pPriv; + + if (pWin->backStorage) + { + pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr; + if (!pPriv) + (void) miBSCreateGCPrivate (pGC); + pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr; + if (pPriv) + { + /* + * XXX KLUDGE ALERT + * + * when the GC is Cheap pPriv will point + * at some device's gc func structure. guarantee + * will point at the ChangeGC entry of that struct + * and will never match a valid guarantee value. + */ + switch (pPriv->guarantee) + { + case GuaranteeNothing: + case GuaranteeVisBack: + pPriv->guarantee = guarantee; + break; + } + } + } +} + +#define noBackingCopy (GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin| \ + GCClipMask|GCSubwindowMode| \ + GCTileStipXOrigin|GCTileStipYOrigin) + +/*- + *----------------------------------------------------------------------- + * miBSValidateGC -- + * Wrapper around output-library's ValidateGC routine + * + * Results: + * None. + * + * Side Effects: + * + * Notes: + * The idea here is to perform several functions: + * - All the output calls must be intercepted and routed to + * backing-store as necessary. + * - pGC in the window's devBackingStore must be set up with the + * clip list appropriate for writing to pBackingPixmap (i.e. + * the inverse of the window's clipList intersected with the + * clientClip of the GC). Since the destination for this GC is + * a pixmap, it is sufficient to set the clip list as its + * clientClip. + *----------------------------------------------------------------------- + */ + +static void +miBSValidateGC (pGC, stateChanges, pDrawable) + GCPtr pGC; + unsigned long stateChanges; + DrawablePtr pDrawable; +{ + GCPtr pBackingGC; + miBSWindowPtr pWindowPriv; + miBSGCPtr pPriv; + WindowPtr pWin; + int lift_functions; + RegionPtr backingCompositeClip = NULL; + + if (pDrawable->type != DRAWABLE_PIXMAP) + { + pWin = (WindowPtr) pDrawable; + pWindowPriv = (miBSWindowPtr) pWin->backStorage; + lift_functions = (pWindowPriv == (miBSWindowPtr) NULL); + } + else + { + pWin = (WindowPtr) NULL; + lift_functions = TRUE; + } + + pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr; + + FUNC_PROLOGUE (pGC, pPriv); + + (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable); + + /* + * rewrap funcs and ops as Validate may have changed them + */ + + pPriv->wrapFuncs = pGC->funcs; + pPriv->wrapOps = pGC->ops; + + if (!lift_functions && ((pPriv->guarantee == GuaranteeVisBack) || + (pWindowPriv->status == StatusNoPixmap) || + (pWindowPriv->status == StatusBadAlloc))) + lift_functions = TRUE; + + /* + * check to see if a new backingCompositeClip region must + * be generated + */ + + if (!lift_functions && + ((pDrawable->serialNumber != pPriv->serialNumber) || + (stateChanges&(GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)))) + { + if (REGION_NOTEMPTY(pGC->pScreen, &pWindowPriv->SavedRegion)) + { + backingCompositeClip = REGION_CREATE(pGC->pScreen, NULL, 1); + if ((pGC->clientClipType == CT_NONE) || + (pGC->clientClipType == CT_PIXMAP)) + { + REGION_COPY(pGC->pScreen, backingCompositeClip, + &pWindowPriv->SavedRegion); + } + else + { + /* + * Make a new copy of the client clip, translated to + * its proper origin. + */ + + REGION_COPY(pGC->pScreen, backingCompositeClip, + pGC->clientClip); + REGION_TRANSLATE(pGC->pScreen, backingCompositeClip, + pGC->clipOrg.x, + pGC->clipOrg.y); + REGION_INTERSECT(pGC->pScreen, backingCompositeClip, + backingCompositeClip, + &pWindowPriv->SavedRegion); + } + if (pGC->subWindowMode == IncludeInferiors) + { + RegionPtr translatedClip; + + /* XXX + * any output in IncludeInferiors mode will not + * be redirected to Inferiors backing store. This + * can be fixed only at great cost to the shadow routines. + */ + translatedClip = NotClippedByChildren (pWin); + REGION_TRANSLATE(pGC->pScreen, translatedClip, + -pDrawable->x, + -pDrawable->y); + REGION_SUBTRACT(pGC->pScreen, backingCompositeClip, + backingCompositeClip, translatedClip); + REGION_DESTROY(pGC->pScreen, translatedClip); + } + if (!REGION_NOTEMPTY(pGC->pScreen, backingCompositeClip)) + lift_functions = TRUE; + } + else + { + lift_functions = TRUE; + } + + /* Reset the status when drawing to an unoccluded window so that + * future SaveAreas will actually copy bits from the screen. Note that + * output to root window in IncludeInferiors mode will not cause this + * to change. This causes all transient graphics by the window + * manager to the root window to not enable backing store. + */ + if (lift_functions && (pWindowPriv->status == StatusVirtual) && + (pWin->parent || pGC->subWindowMode != IncludeInferiors)) + pWindowPriv->status = StatusVDirty; + } + + /* + * if no backing store has been allocated, and it's needed, + * create it now. + */ + + if (!lift_functions && !pWindowPriv->pBackingPixmap) + { + miCreateBSPixmap (pWin, NullBox); + if (!pWindowPriv->pBackingPixmap) + lift_functions = TRUE; + } + + /* + * create the backing GC if needed, lift functions + * if the creation fails + */ + + if (!lift_functions && !pPriv->pBackingGC) + { + int status; + XID noexpose = xFalse; + + /* We never want ops with the backingGC to generate GraphicsExpose */ + pBackingGC = CreateGC ((DrawablePtr)pWindowPriv->pBackingPixmap, + GCGraphicsExposures, &noexpose, &status); + if (status != Success) + lift_functions = TRUE; + else + pPriv->pBackingGC = pBackingGC; + } + + pBackingGC = pPriv->pBackingGC; + + pPriv->stateChanges |= stateChanges; + + if (lift_functions) + { + if (backingCompositeClip) + REGION_DESTROY( pGC->pScreen, backingCompositeClip); + + /* unwrap the GC again */ + miBSDestroyGCPrivate (pGC); + + return; + } + + /* + * the rest of this function gets the pBackingGC + * into shape for possible draws + */ + + pPriv->stateChanges &= ~noBackingCopy; + if (pPriv->stateChanges) + CopyGC(pGC, pBackingGC, pPriv->stateChanges); + if ((pGC->patOrg.x - pWindowPriv->x) != pBackingGC->patOrg.x || + (pGC->patOrg.y - pWindowPriv->y) != pBackingGC->patOrg.y) + { + XID vals[2]; + vals[0] = pGC->patOrg.x - pWindowPriv->x; + vals[1] = pGC->patOrg.y - pWindowPriv->y; + DoChangeGC(pBackingGC, GCTileStipXOrigin|GCTileStipYOrigin, vals, 0); + } + pPriv->stateChanges = 0; + + if (backingCompositeClip) + { + XID vals[2]; + + if (pGC->clientClipType == CT_PIXMAP) + { + miBSScreenPtr pScreenPriv; + + (*pBackingGC->funcs->CopyClip)(pBackingGC, pGC); + REGION_TRANSLATE(pGC->pScreen, backingCompositeClip, + -pGC->clipOrg.x, -pGC->clipOrg.y); + vals[0] = pGC->clipOrg.x - pWindowPriv->x; + vals[1] = pGC->clipOrg.y - pWindowPriv->y; + DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0); + pScreenPriv = (miBSScreenPtr) + pGC->pScreen->devPrivates[miBSScreenIndex].ptr; + (* pScreenPriv->funcs->SetClipmaskRgn) + (pBackingGC, backingCompositeClip); + REGION_DESTROY( pGC->pScreen, backingCompositeClip); + } + else + { + vals[0] = -pWindowPriv->x; + vals[1] = -pWindowPriv->y; + DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0); + (*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION, backingCompositeClip, 0); + } + pPriv->serialNumber = pDrawable->serialNumber; + } + + if (pWindowPriv->pBackingPixmap->drawable.serialNumber + != pBackingGC->serialNumber) + { + ValidateGC((DrawablePtr)pWindowPriv->pBackingPixmap, pBackingGC); + } + + if (pBackingGC->clientClip == 0) + ErrorF ("backing store clip list nil"); + + FUNC_EPILOGUE (pGC, pPriv); +} + +static void +miBSChangeGC (pGC, mask) + GCPtr pGC; + unsigned long mask; +{ + miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; + + FUNC_PROLOGUE (pGC, pPriv); + + (*pGC->funcs->ChangeGC) (pGC, mask); + + FUNC_EPILOGUE (pGC, pPriv); +} + +static void +miBSCopyGC (pGCSrc, mask, pGCDst) + GCPtr pGCSrc, pGCDst; + unsigned long mask; +{ + miBSGCPtr pPriv = (miBSGCPtr) (pGCDst)->devPrivates[miBSGCIndex].ptr; + + FUNC_PROLOGUE (pGCDst, pPriv); + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + + FUNC_EPILOGUE (pGCDst, pPriv); +} + +static void +miBSDestroyGC (pGC) + GCPtr pGC; +{ + miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; + + FUNC_PROLOGUE (pGC, pPriv); + + if (pPriv->pBackingGC) + FreeGC(pPriv->pBackingGC, (GContext)0); + + (*pGC->funcs->DestroyGC) (pGC); + + FUNC_EPILOGUE (pGC, pPriv); + + xfree(pPriv); +} + +static void +miBSChangeClip(pGC, type, pvalue, nrects) + GCPtr pGC; + int type; + pointer pvalue; + int nrects; +{ + miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; + + FUNC_PROLOGUE (pGC, pPriv); + + (* pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects); + + FUNC_EPILOGUE (pGC, pPriv); +} + +static void +miBSCopyClip(pgcDst, pgcSrc) + GCPtr pgcDst, pgcSrc; +{ + miBSGCPtr pPriv = (miBSGCPtr) (pgcDst)->devPrivates[miBSGCIndex].ptr; + + FUNC_PROLOGUE (pgcDst, pPriv); + + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + + FUNC_EPILOGUE (pgcDst, pPriv); +} + +static void +miBSDestroyClip(pGC) + GCPtr pGC; +{ + miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; + + FUNC_PROLOGUE (pGC, pPriv); + + (* pGC->funcs->DestroyClip)(pGC); + + FUNC_EPILOGUE (pGC, pPriv); +} + +static void +miDestroyBSPixmap (pWin) + WindowPtr pWin; +{ + miBSWindowPtr pBackingStore; + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + pBackingStore = (miBSWindowPtr) pWin->backStorage; + if (pBackingStore->pBackingPixmap) + (* pScreen->DestroyPixmap)(pBackingStore->pBackingPixmap); + pBackingStore->pBackingPixmap = NullPixmap; + pBackingStore->x = 0; + pBackingStore->y = 0; + if (pBackingStore->backgroundState == BackgroundPixmap) + (* pScreen->DestroyPixmap)(pBackingStore->background.pixmap); + pBackingStore->backgroundState = None; + pBackingStore->status = StatusNoPixmap; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; +} + +static void +miTileVirtualBS (pWin) + WindowPtr pWin; +{ + miBSWindowPtr pBackingStore; + + pBackingStore = (miBSWindowPtr) pWin->backStorage; + if (pBackingStore->backgroundState == BackgroundPixmap) + (* pWin->drawable.pScreen->DestroyPixmap) + (pBackingStore->background.pixmap); + pBackingStore->backgroundState = pWin->backgroundState; + pBackingStore->background = pWin->background; + if (pBackingStore->backgroundState == BackgroundPixmap) + pBackingStore->background.pixmap->refcnt++; + + if (pBackingStore->status != StatusVDirty) + pBackingStore->status = StatusVirtual; + + /* + * punt parent relative tiles and do it now + */ + if (pBackingStore->backgroundState == ParentRelative) + miCreateBSPixmap (pWin, NullBox); +} + +#ifdef DEBUG +static int BSAllocationsFailed = 0; +#define FAILEDSIZE 32 +static struct { int w, h; } failedRecord[FAILEDSIZE]; +static int failedIndex; +#endif + +static void +miCreateBSPixmap (pWin, pExtents) + WindowPtr pWin; + BoxPtr pExtents; +{ + miBSWindowPtr pBackingStore; + ScreenPtr pScreen; + PixUnion background; + char backgroundState; + BoxPtr extents; + Bool backSet; + + pScreen = pWin->drawable.pScreen; + pBackingStore = (miBSWindowPtr) pWin->backStorage; + if (pBackingStore->status == StatusBadAlloc) + return; + backSet = ((pBackingStore->status == StatusVirtual) || + (pBackingStore->status == StatusVDirty)); + + extents = REGION_EXTENTS( pScreen, &pBackingStore->SavedRegion); + + if (!pBackingStore->pBackingPixmap) + { + /* the policy here could be more sophisticated */ + pBackingStore->x = extents->x1; + pBackingStore->y = extents->y1; + pBackingStore->pBackingPixmap = + (PixmapPtr)(* pScreen->CreatePixmap) + (pScreen, + extents->x2 - extents->x1, + extents->y2 - extents->y1, + pWin->drawable.depth); + } + if (!pBackingStore->pBackingPixmap) + { +#ifdef DEBUG + BSAllocationsFailed++; + /* + * record failed allocations + */ + failedRecord[failedIndex].w = pWin->drawable.width; + failedRecord[failedIndex].h = pWin->drawable.height; + failedIndex++; + if (failedIndex == FAILEDSIZE) + failedIndex = 0; +#endif +#ifdef BSEAGER + pBackingStore->status = StatusNoPixmap; +#else + pBackingStore->status = StatusBadAlloc; +#endif + return; + } + + pBackingStore->status = StatusContents; + + if (backSet) + { + backgroundState = pWin->backgroundState; + background = pWin->background; + + pWin->backgroundState = pBackingStore->backgroundState; + pWin->background = pBackingStore->background; + if (pWin->backgroundState == BackgroundPixmap) + pWin->background.pixmap->refcnt++; + } + + if (!pExtents) + pExtents = extents; + + if (pExtents->y1 != pExtents->y2) + { + RegionPtr exposed; + + exposed = miBSClearBackingStore(pWin, + pExtents->x1, pExtents->y1, + pExtents->x2 - pExtents->x1, + pExtents->y2 - pExtents->y1, + !backSet); + if (exposed) + { + miSendExposures(pWin, exposed, pWin->drawable.x, pWin->drawable.y); + REGION_DESTROY( pScreen, exposed); + } + } + + if (backSet) + { + if (pWin->backgroundState == BackgroundPixmap) + (* pScreen->DestroyPixmap) (pWin->background.pixmap); + pWin->backgroundState = backgroundState; + pWin->background = background; + if (pBackingStore->backgroundState == BackgroundPixmap) + (* pScreen->DestroyPixmap) (pBackingStore->background.pixmap); + pBackingStore->backgroundState = None; + } +} + +/*- + *----------------------------------------------------------------------- + * miBSExposeCopy -- + * Handle the restoration of areas exposed by graphics operations. + * + * Results: + * None. + * + * Side Effects: + * prgnExposed has the areas exposed from backing-store removed + * from it. + * + *----------------------------------------------------------------------- + */ +static void +miBSExposeCopy (pSrc, pDst, pGC, prgnExposed, srcx, srcy, dstx, dsty, plane) + WindowPtr pSrc; + DrawablePtr pDst; + GCPtr pGC; + RegionPtr prgnExposed; + int srcx, srcy; + int dstx, dsty; + unsigned long plane; +{ + RegionRec tempRgn; + miBSWindowPtr pBackingStore; + RegionPtr (*copyProc)(); + GCPtr pScratchGC; + register BoxPtr pBox; + register int i; + register int dx, dy; + BITS32 gcMask; + + if (!REGION_NOTEMPTY(pGC->pScreen, prgnExposed)) + return; + pBackingStore = (miBSWindowPtr)pSrc->backStorage; + + if ((pBackingStore->status == StatusNoPixmap) || + (pBackingStore->status == StatusBadAlloc)) + return; + + REGION_INIT( pGC->pScreen, &tempRgn, NullBox, 0); + REGION_INTERSECT( pGC->pScreen, &tempRgn, prgnExposed, + &pBackingStore->SavedRegion); + REGION_SUBTRACT( pGC->pScreen, prgnExposed, prgnExposed, &tempRgn); + + if (plane != 0) { + copyProc = pGC->ops->CopyPlane; + } else { + copyProc = pGC->ops->CopyArea; + } + + dx = dstx - srcx; + dy = dsty - srcy; + + switch (pBackingStore->status) { + case StatusVirtual: + case StatusVDirty: + pScratchGC = GetScratchGC (pDst->depth, pDst->pScreen); + if (pScratchGC) + { + gcMask = 0; + if (pGC->alu != pScratchGC->alu) + gcMask = GCFunction; + if (pGC->planemask != pScratchGC->planemask) + gcMask |= GCPlaneMask; + if (gcMask) + CopyGC (pGC, pScratchGC, gcMask); + miBSFillVirtualBits (pDst, pScratchGC, &tempRgn, dx, dy, + (int) pBackingStore->backgroundState, + pBackingStore->background, + ~0L); + FreeScratchGC (pScratchGC); + } + break; + case StatusContents: + for (i = REGION_NUM_RECTS(&tempRgn), pBox = REGION_RECTS(&tempRgn); + --i >= 0; + pBox++) + { + (* copyProc) (pBackingStore->pBackingPixmap, pDst, pGC, + pBox->x1 - pBackingStore->x, + pBox->y1 - pBackingStore->y, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, + pBox->x1 + dx, pBox->y1 + dy, plane); + } + break; + } + REGION_UNINIT( pGC->pScreen, &tempRgn); +} diff --git a/mi/mibstore.h b/mi/mibstore.h new file mode 100644 index 000000000..fe6c759e0 --- /dev/null +++ b/mi/mibstore.h @@ -0,0 +1,62 @@ +/*- + * mibstore.h -- + * Header file for users of the MI backing-store scheme. + * + * Copyright (c) 1987 by the Regents of the University of California + * + * 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. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * "$Xorg: mibstore.h,v 1.3 2000/08/17 19:53:37 cpqbld Exp $ + */ + +#ifndef _MIBSTORE_H +#define _MIBSTORE_H + +typedef struct _miBSFuncRec { + void (*SaveAreas)( +#if NeedNestedPrototypes + PixmapPtr /*pBackingPixmap*/, + RegionPtr /*pObscured*/, + int /*x*/, + int /*y*/, + WindowPtr /*pWin*/ +#endif +); + void (*RestoreAreas)( +#if NeedNestedPrototypes + PixmapPtr /*pBackingPixmap*/, + RegionPtr /*pExposed*/, + int /*x*/, + int /*y*/, + WindowPtr /*pWin*/ +#endif +); + void (*SetClipmaskRgn)( +#if NeedNestedPrototypes + GCPtr /*pBackingGC*/, + RegionPtr /*pbackingCompositeClip*/ +#endif +); + PixmapPtr (*GetImagePixmap)(); /* unused */ + PixmapPtr (*GetSpansPixmap)(); /* unused */ +} miBSFuncRec; + +#ifndef _XTYPEDEF_MIBSFUNCPTR +typedef struct _miBSFuncRec *miBSFuncPtr; +#define _XTYPEDEF_MIBSFUNCPTR +#endif + +extern void miInitializeBackingStore( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + miBSFuncPtr /*funcs*/ +#endif +); + +#endif /* _MIBSTORE_H */ diff --git a/mi/mibstorest.h b/mi/mibstorest.h new file mode 100644 index 000000000..d56ee76f6 --- /dev/null +++ b/mi/mibstorest.h @@ -0,0 +1,91 @@ +/* + * mibstorest.h + * + * internal structure definitions for mi backing store + */ + +/* $Xorg: mibstorest.h,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +#include "mibstore.h" +#include "regionstr.h" + +/* + * One of these structures is allocated per GC used with a backing-store + * drawable. + */ + +typedef struct { + GCPtr pBackingGC; /* Copy of the GC but with graphicsExposures + * set FALSE and the clientClip set to + * clip output to the valid regions of the + * backing pixmap. */ + int guarantee; /* GuaranteeNothing, etc. */ + unsigned long serialNumber; /* clientClip computed time */ + unsigned long stateChanges; /* changes in parent gc since last copy */ + GCOps *wrapOps; /* wrapped ops */ + GCFuncs *wrapFuncs; /* wrapped funcs */ +} miBSGCRec, *miBSGCPtr; + +/* + * one of these structures is allocated per Window with backing store + */ + +typedef struct { + PixmapPtr pBackingPixmap; /* Pixmap for saved areas */ + short x; /* origin of pixmap relative to window */ + short y; + RegionRec SavedRegion; /* Valid area in pBackingPixmap */ + char viewable; /* Tracks pWin->viewable so SavedRegion may + * be initialized correctly when the window + * is first mapped */ + char status; /* StatusNoPixmap, etc. */ + char backgroundState; /* background type */ + PixUnion background; /* background pattern */ +} miBSWindowRec, *miBSWindowPtr; + +#define StatusNoPixmap 1 /* pixmap has not been created */ +#define StatusVirtual 2 /* pixmap is virtual, tiled with background */ +#define StatusVDirty 3 /* pixmap is virtual, visiblt has contents */ +#define StatusBadAlloc 4 /* pixmap create failed, do not try again */ +#define StatusContents 5 /* pixmap is created, has valid contents */ + +typedef struct { + /* + * screen func wrappers + */ + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + CreateGCProcPtr CreateGC; + DestroyWindowProcPtr DestroyWindow; + /* + * pointer to vector of device-specific backing store functions + */ + miBSFuncPtr funcs; +} miBSScreenRec, *miBSScreenPtr; diff --git a/mi/miclipn.c b/mi/miclipn.c new file mode 100644 index 000000000..6eca416f8 --- /dev/null +++ b/mi/miclipn.c @@ -0,0 +1,73 @@ +/* $Xorg: miclipn.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#include "windowstr.h" +#include "scrnintstr.h" + +static void (*clipNotify)() = 0; +static void (*ClipNotifies[MAXSCREENS])(); + +static void +miClipNotifyWrapper(pWin, dx, dy) + WindowPtr pWin; + int dx, dy; +{ + if (clipNotify) + (*clipNotify)(pWin, dx, dy); + if (ClipNotifies[pWin->drawable.pScreen->myNum]) + (*ClipNotifies[pWin->drawable.pScreen->myNum])(pWin, dx, dy); +} + +/* + * miClipNotify -- + * Hook to let DDX request notification when the clipList of + * a window is recomputed on any screen. For R4 compatibility; + * better if you wrap the ClipNotify screen proc yourself. + */ + +static unsigned long clipGeneration = 0; + +void +miClipNotify (func) + void (*func)(); +{ + int i; + + clipNotify = func; + if (clipGeneration != serverGeneration) + { + clipGeneration = serverGeneration; + for (i = 0; i < screenInfo.numScreens; i++) + { + ClipNotifies[i] = screenInfo.screens[i]->ClipNotify; + screenInfo.screens[i]->ClipNotify = miClipNotifyWrapper; + } + } +} diff --git a/mi/micursor.c b/mi/micursor.c new file mode 100644 index 000000000..b23bcddf6 --- /dev/null +++ b/mi/micursor.c @@ -0,0 +1,71 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: micursor.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ +#include "scrnintstr.h" +#include "cursor.h" +#include "misc.h" + +extern Bool Must_have_memory; + +void +miRecolorCursor( pScr, pCurs, displayed) + ScreenPtr pScr; + CursorPtr pCurs; + Bool displayed; +{ + /* + * This is guaranteed to correct any color-dependent state which may have + * been bound up in private state created by RealizeCursor + */ + (* pScr->UnrealizeCursor)( pScr, pCurs); + Must_have_memory = TRUE; /* XXX */ + (* pScr->RealizeCursor)( pScr, pCurs); + Must_have_memory = FALSE; /* XXX */ + if ( displayed) + (* pScr->DisplayCursor)( pScr, pCurs); + +} diff --git a/mi/midash.c b/mi/midash.c new file mode 100644 index 000000000..cc7e31b28 --- /dev/null +++ b/mi/midash.c @@ -0,0 +1,310 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: midash.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ +#include "miscstruct.h" +#include "mistruct.h" +#include "mifpoly.h" + +static miDashPtr CheckDashStorage(); + +/* return a list of DashRec. there will be an extra +entry at the end holding the last point of the polyline. + this means that the code that actually draws dashes can +get a pair of points for every dash. only the point in the last +dash record is useful; the other fields are not used. + nseg is the number of segments, not the number of points. + +example: + + dash1.start + dash2.start + dash3.start + last-point + +defines a list of segments + (dash1.pt, dash2.pt) + (dash2.pt, dash3.pt) + (dash3.pt, last-point) +and nseg == 3. + +NOTE: + EVEN_DASH == ~ODD_DASH + +NOTE ALSO: + miDashLines may return 0 segments, going from pt[0] to pt[0] with one dash. +*/ + +miDashPtr +miDashLine(npt, ppt, nDash, pDash, offset, pnseg) +int npt; +DDXPointPtr ppt; +unsigned int nDash; +unsigned char *pDash; +unsigned int offset; +int *pnseg; +{ + DDXPointRec pt1, pt2; + int lenCur; /* npt used from this dash */ + int lenMax; /* npt in this dash */ + int iDash = 0; /* index of current dash */ + int which; /* EVEN_DASH or ODD_DASH */ + miDashPtr pseg; /* list of dash segments */ + miDashPtr psegBase; /* start of list */ + int nseg = 0; /* number of dashes so far */ + int nsegMax = 0; /* num segs we can fit in this list */ + + int x, y, len; + int adx, ady, signdx, signdy; + int du, dv, e1, e2, e, base_e = 0; + + lenCur = offset; + which = EVEN_DASH; + while(lenCur >= pDash[iDash]) + { + lenCur -= pDash[iDash]; + iDash++; + if (iDash >= nDash) + iDash = 0; + which = ~which; + } + lenMax = pDash[iDash]; + + psegBase = (miDashPtr)NULL; + pt2 = ppt[0]; /* just in case there is only one point */ + + while(--npt) + { + if (PtEqual(ppt[0], ppt[1])) + { + ppt++; + continue; /* no duplicated points in polyline */ + } + pt1 = *ppt++; + pt2 = *ppt; + + adx = pt2.x - pt1.x; + ady = pt2.y - pt1.y; + signdx = sign(adx); + signdy = sign(ady); + adx = abs(adx); + ady = abs(ady); + + if (adx > ady) + { + du = adx; + dv = ady; + len = adx; + } + else + { + du = ady; + dv = adx; + len = ady; + } + + e1 = dv * 2; + e2 = e1 - 2*du; + e = e1 - du; + x = pt1.x; + y = pt1.y; + + nseg++; + pseg = CheckDashStorage(&psegBase, nseg, &nsegMax); + if (!pseg) + return (miDashPtr)NULL; + pseg->pt = pt1; + pseg->e1 = e1; + pseg->e2 = e2; + base_e = pseg->e = e; + pseg->which = which; + pseg->newLine = 1; + + while (len--) + { + if (adx > ady) + { + /* X_AXIS */ + if (((signdx > 0) && (e < 0)) || + ((signdx <=0) && (e <=0)) + ) + { + e += e1; + } + else + { + y += signdy; + e += e2; + } + x += signdx; + } + else + { + /* Y_AXIS */ + if (((signdx > 0) && (e < 0)) || + ((signdx <=0) && (e <=0)) + ) + { + e +=e1; + } + else + { + x += signdx; + e += e2; + } + y += signdy; + } + + lenCur++; + if (lenCur >= lenMax && (len || npt <= 1)) + { + nseg++; + pseg = CheckDashStorage(&psegBase, nseg, &nsegMax); + if (!pseg) + return (miDashPtr)NULL; + pseg->pt.x = x; + pseg->pt.y = y; + pseg->e1 = e1; + pseg->e2 = e2; + pseg->e = e; + which = ~which; + pseg->which = which; + pseg->newLine = 0; + + /* move on to next dash */ + iDash++; + if (iDash >= nDash) + iDash = 0; + lenMax = pDash[iDash]; + lenCur = 0; + } + } /* while len-- */ + } /* while --npt */ + + if (lenCur == 0 && nseg != 0) + { + nseg--; + which = ~which; + } + *pnseg = nseg; + pseg = CheckDashStorage(&psegBase, nseg+1, &nsegMax); + if (!pseg) + return (miDashPtr)NULL; + pseg->pt = pt2; + pseg->e = base_e; + pseg->which = which; + pseg->newLine = 0; + return psegBase; +} + + +#define NSEGDELTA 16 + +/* returns a pointer to the pseg[nseg-1], growing the storage as +necessary. this interface seems unnecessarily cumbersome. + +*/ + +static +miDashPtr +CheckDashStorage(ppseg, nseg, pnsegMax) +miDashPtr *ppseg; /* base pointer */ +int nseg; /* number of segment we want to write to */ +int *pnsegMax; /* size (in segments) of list so far */ +{ + if (nseg > *pnsegMax) + { + miDashPtr newppseg; + + *pnsegMax += NSEGDELTA; + newppseg = (miDashPtr)xrealloc(*ppseg, + (*pnsegMax)*sizeof(miDashRec)); + if (!newppseg) + { + xfree(*ppseg); + return (miDashPtr)NULL; + } + *ppseg = newppseg; + } + return(*ppseg+(nseg-1)); +} + +void +miStepDash (dist, pDashIndex, pDash, numInDashList, pDashOffset) + int dist; /* distance to step */ + int *pDashIndex; /* current dash */ + unsigned char *pDash; /* dash list */ + int numInDashList; /* total length of dash list */ + int *pDashOffset; /* offset into current dash */ +{ + int dashIndex, dashOffset; + int totallen; + int i; + + dashIndex = *pDashIndex; + dashOffset = *pDashOffset; + if (dist < pDash[dashIndex] - dashOffset) + { + *pDashOffset = dashOffset + dist; + return; + } + dist -= pDash[dashIndex] - dashOffset; + if (++dashIndex == numInDashList) + dashIndex = 0; + totallen = 0; + for (i = 0; i < numInDashList; i++) + totallen += pDash[i]; + if (totallen <= dist) + dist = dist % totallen; + while (dist >= pDash[dashIndex]) + { + dist -= pDash[dashIndex]; + if (++dashIndex == numInDashList) + dashIndex = 0; + } + *pDashIndex = dashIndex; + *pDashOffset = dist; +} diff --git a/mi/midispcur.c b/mi/midispcur.c new file mode 100644 index 000000000..4c33d8e1d --- /dev/null +++ b/mi/midispcur.c @@ -0,0 +1,614 @@ +/* + * midispcur.c + * + * machine independent cursor display routines + */ + +/* $Xorg: midispcur.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +#define NEED_EVENTS +# include "X.h" +# include "misc.h" +# include "input.h" +# include "cursorstr.h" +# include "windowstr.h" +# include "regionstr.h" +# include "dixstruct.h" +# include "scrnintstr.h" +# include "servermd.h" +# include "mipointer.h" +# include "misprite.h" +# include "gcstruct.h" + +extern WindowPtr *WindowTable; + +/* per-screen private data */ + +static int miDCScreenIndex; +static unsigned long miDCGeneration = 0; + +static Bool miDCCloseScreen(); + +typedef struct { + GCPtr pSourceGC, pMaskGC; + GCPtr pSaveGC, pRestoreGC; + GCPtr pMoveGC; + GCPtr pPixSourceGC, pPixMaskGC; + CloseScreenProcPtr CloseScreen; + PixmapPtr pSave, pTemp; +} miDCScreenRec, *miDCScreenPtr; + +/* per-cursor per-screen private data */ +typedef struct { + PixmapPtr sourceBits; /* source bits */ + PixmapPtr maskBits; /* mask bits */ +} miDCCursorRec, *miDCCursorPtr; + +/* + * sprite/cursor method table + */ + +static Bool miDCRealizeCursor(), miDCUnrealizeCursor(); +static Bool miDCPutUpCursor(), miDCSaveUnderCursor(); +static Bool miDCRestoreUnderCursor(), miDCMoveCursor(); +static Bool miDCChangeSave(); + +static miSpriteCursorFuncRec miDCFuncs = { + miDCRealizeCursor, + miDCUnrealizeCursor, + miDCPutUpCursor, + miDCSaveUnderCursor, + miDCRestoreUnderCursor, + miDCMoveCursor, + miDCChangeSave, +}; + +Bool +miDCInitialize (pScreen, screenFuncs) + ScreenPtr pScreen; + miPointerScreenFuncPtr screenFuncs; +{ + miDCScreenPtr pScreenPriv; + + if (miDCGeneration != serverGeneration) + { + miDCScreenIndex = AllocateScreenPrivateIndex (); + if (miDCScreenIndex < 0) + return FALSE; + miDCGeneration = serverGeneration; + } + pScreenPriv = (miDCScreenPtr) xalloc (sizeof (miDCScreenRec)); + if (!pScreenPriv) + return FALSE; + + /* + * initialize the entire private structure to zeros + */ + + pScreenPriv->pSourceGC = + pScreenPriv->pMaskGC = + pScreenPriv->pSaveGC = + pScreenPriv->pRestoreGC = + pScreenPriv->pMoveGC = + pScreenPriv->pPixSourceGC = + pScreenPriv->pPixMaskGC = NULL; + + pScreenPriv->pSave = pScreenPriv->pTemp = NULL; + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miDCCloseScreen; + + pScreen->devPrivates[miDCScreenIndex].ptr = (pointer) pScreenPriv; + + if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs)) + { + xfree ((pointer) pScreenPriv); + return FALSE; + } + return TRUE; +} + +#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0) +#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE) + +static Bool +miDCCloseScreen (index, pScreen) + ScreenPtr pScreen; +{ + miDCScreenPtr pScreenPriv; + + pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; + pScreen->CloseScreen = pScreenPriv->CloseScreen; + tossGC (pScreenPriv->pSourceGC); + tossGC (pScreenPriv->pMaskGC); + tossGC (pScreenPriv->pSaveGC); + tossGC (pScreenPriv->pRestoreGC); + tossGC (pScreenPriv->pMoveGC); + tossGC (pScreenPriv->pPixSourceGC); + tossGC (pScreenPriv->pPixMaskGC); + tossPix (pScreenPriv->pSave); + tossPix (pScreenPriv->pTemp); + xfree ((pointer) pScreenPriv); + return (*pScreen->CloseScreen) (index, pScreen); +} + +static Bool +miDCRealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + if (pCursor->bits->refcnt <= 1) + pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; + return TRUE; +} + +static miDCCursorPtr +miDCRealize (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + miDCCursorPtr pPriv; + GCPtr pGC; + XID gcvals[3]; + + pPriv = (miDCCursorPtr) xalloc (sizeof (miDCCursorRec)); + if (!pPriv) + return (miDCCursorPtr)NULL; + pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); + if (!pPriv->sourceBits) + { + xfree ((pointer) pPriv); + return (miDCCursorPtr)NULL; + } + pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); + if (!pPriv->maskBits) + { + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + xfree ((pointer) pPriv); + return (miDCCursorPtr)NULL; + } + pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; + + /* create the two sets of bits, clipping as appropriate */ + + pGC = GetScratchGC (1, pScreen); + if (!pGC) + { + (void) miDCUnrealizeCursor (pScreen, pCursor); + return (miDCCursorPtr)NULL; + } + + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + gcvals[0] = GXand; + ChangeGC (pGC, GCFunction, gcvals); + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + + /* mask bits -- pCursor->mask & ~pCursor->source */ + gcvals[0] = GXcopy; + ChangeGC (pGC, GCFunction, gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + gcvals[0] = GXandInverted; + ChangeGC (pGC, GCFunction, gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + FreeScratchGC (pGC); + return pPriv; +} + +static Bool +miDCUnrealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + miDCCursorPtr pPriv; + + pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; + if (pPriv && (pCursor->bits->refcnt <= 1)) + { + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + (*pScreen->DestroyPixmap) (pPriv->maskBits); + xfree ((pointer) pPriv); + pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; + } + return TRUE; +} + +static void +miDCPutBits (pDrawable, pPriv, sourceGC, maskGC, x, y, w, h, source, mask) + DrawablePtr pDrawable; + GCPtr sourceGC, maskGC; + int x, y; + unsigned w, h; + miDCCursorPtr pPriv; + unsigned long source, mask; +{ + XID gcvals[1]; + + if (sourceGC->fgPixel != source) + { + gcvals[0] = source; + DoChangeGC (sourceGC, GCForeground, gcvals, 0); + } + if (sourceGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, sourceGC); + (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); + if (maskGC->fgPixel != mask) + { + gcvals[0] = mask; + DoChangeGC (maskGC, GCForeground, gcvals, 0); + } + if (maskGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, maskGC); + (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); +} + +#define EnsureGC(gc,win) (gc || miDCMakeGC(&gc, win)) + +static GCPtr +miDCMakeGC(ppGC, pWin) + GCPtr *ppGC; + WindowPtr pWin; +{ + GCPtr pGC; + int status; + XID gcvals[2]; + + gcvals[0] = IncludeInferiors; + gcvals[1] = FALSE; + pGC = CreateGC((DrawablePtr)pWin, + GCSubwindowMode|GCGraphicsExposures, gcvals, &status); + if (pGC) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + *ppGC = pGC; + return pGC; +} + +static Bool +miDCPutUpCursor (pScreen, pCursor, x, y, source, mask) + ScreenPtr pScreen; + CursorPtr pCursor; + int x, y; + unsigned long source, mask; +{ + miDCScreenPtr pScreenPriv; + miDCCursorPtr pPriv; + WindowPtr pWin; + + pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; + if (!pPriv) + { + pPriv = miDCRealize(pScreen, pCursor); + if (!pPriv) + return FALSE; + } + pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; + pWin = WindowTable[pScreen->myNum]; + if (!EnsureGC(pScreenPriv->pSourceGC, pWin)) + return FALSE; + if (!EnsureGC(pScreenPriv->pMaskGC, pWin)) + { + FreeGC (pScreenPriv->pSourceGC, (GContext) 0); + pScreenPriv->pSourceGC = 0; + return FALSE; + } + miDCPutBits ((DrawablePtr)pWin, pPriv, + pScreenPriv->pSourceGC, pScreenPriv->pMaskGC, + x, y, pCursor->bits->width, pCursor->bits->height, + source, mask); + return TRUE; +} + +static Bool +miDCSaveUnderCursor (pScreen, x, y, w, h) + ScreenPtr pScreen; + int x, y, w, h; +{ + miDCScreenPtr pScreenPriv; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; + pSave = pScreenPriv->pSave; + pWin = WindowTable[pScreen->myNum]; + if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) + { + if (pSave) + (*pScreen->DestroyPixmap) (pSave); + pScreenPriv->pSave = pSave = + (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth); + if (!pSave) + return FALSE; + } + if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) + return FALSE; + pGC = pScreenPriv->pSaveGC; + if (pSave->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pSave, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x, y, w, h, 0, 0); + return TRUE; +} + +static Bool +miDCRestoreUnderCursor (pScreen, x, y, w, h) + ScreenPtr pScreen; + int x, y, w, h; +{ + miDCScreenPtr pScreenPriv; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; + pSave = pScreenPriv->pSave; + pWin = WindowTable[pScreen->myNum]; + if (!pSave) + return FALSE; + if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) + return FALSE; + pGC = pScreenPriv->pRestoreGC; + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + 0, 0, w, h, x, y); + return TRUE; +} + +static Bool +miDCChangeSave (pScreen, x, y, w, h, dx, dy) + ScreenPtr pScreen; + int x, y, w, h, dx, dy; +{ + miDCScreenPtr pScreenPriv; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + int sourcex, sourcey, destx, desty, copyw, copyh; + + pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; + pSave = pScreenPriv->pSave; + pWin = WindowTable[pScreen->myNum]; + /* + * restore the bits which are about to get trashed + */ + if (!pSave) + return FALSE; + if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) + return FALSE; + pGC = pScreenPriv->pRestoreGC; + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pWin, pGC); + /* + * copy the old bits to the screen. + */ + if (dy > 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + 0, h - dy, w, dy, x + dx, y + h); + } + else if (dy < 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + 0, 0, w, -dy, x + dx, y + dy); + } + if (dy >= 0) + { + desty = y + dy; + sourcey = 0; + copyh = h - dy; + } + else + { + desty = y; + sourcey = - dy; + copyh = h + dy; + } + if (dx > 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + w - dx, sourcey, dx, copyh, x + w, desty); + } + else if (dx < 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + 0, sourcey, -dx, copyh, x + dx, desty); + } + if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) + return FALSE; + pGC = pScreenPriv->pSaveGC; + if (pSave->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pSave, pGC); + /* + * move the bits that are still valid within the pixmap + */ + if (dx >= 0) + { + sourcex = 0; + destx = dx; + copyw = w - dx; + } + else + { + destx = 0; + sourcex = - dx; + copyw = w + dx; + } + if (dy >= 0) + { + sourcey = 0; + desty = dy; + copyh = h - dy; + } + else + { + desty = 0; + sourcey = -dy; + copyh = h + dy; + } + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC, + sourcex, sourcey, copyw, copyh, destx, desty); + /* + * copy the new bits from the screen into the remaining areas of the + * pixmap + */ + if (dy > 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x, y, w, dy, 0, 0); + } + else if (dy < 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x, y + h + dy, w, -dy, 0, h + dy); + } + if (dy >= 0) + { + desty = dy; + sourcey = y + dy; + copyh = h - dy; + } + else + { + desty = 0; + sourcey = y; + copyh = h + dy; + } + if (dx > 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x, sourcey, dx, copyh, 0, desty); + } + else if (dx < 0) + { + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x + w + dx, sourcey, -dx, copyh, w + dx, desty); + } + return TRUE; +} + +static Bool +miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) + ScreenPtr pScreen; + CursorPtr pCursor; + int x, y, w, h, dx, dy; + unsigned long source, mask; +{ + miDCCursorPtr pPriv; + miDCScreenPtr pScreenPriv; + int status; + WindowPtr pWin; + GCPtr pGC; + XID gcval = FALSE; + PixmapPtr pTemp; + + pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; + if (!pPriv) + { + pPriv = miDCRealize(pScreen, pCursor); + if (!pPriv) + return FALSE; + } + pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; + pWin = WindowTable[pScreen->myNum]; + pTemp = pScreenPriv->pTemp; + if (!pTemp || + pTemp->drawable.width != pScreenPriv->pSave->drawable.width || + pTemp->drawable.height != pScreenPriv->pSave->drawable.height) + { + if (pTemp) + (*pScreen->DestroyPixmap) (pTemp); + pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap) + (pScreen, w, h, pScreenPriv->pSave->drawable.depth); + if (!pTemp) + return FALSE; + } + if (!pScreenPriv->pMoveGC) + { + pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp, + GCGraphicsExposures, &gcval, &status); + if (!pScreenPriv->pMoveGC) + return FALSE; + } + /* + * copy the saved area to a temporary pixmap + */ + pGC = pScreenPriv->pMoveGC; + if (pGC->serialNumber != pTemp->drawable.serialNumber) + ValidateGC ((DrawablePtr) pTemp, pGC); + (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave, + (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0); + + /* + * draw the cursor in the temporary pixmap + */ + if (!pScreenPriv->pPixSourceGC) + { + pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, + GCGraphicsExposures, &gcval, &status); + if (!pScreenPriv->pPixSourceGC) + return FALSE; + } + if (!pScreenPriv->pPixMaskGC) + { + pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, + GCGraphicsExposures, &gcval, &status); + if (!pScreenPriv->pPixMaskGC) + return FALSE; + } + miDCPutBits ((DrawablePtr)pTemp, pPriv, + pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC, + dx, dy, pCursor->bits->width, pCursor->bits->height, + source, mask); + + /* + * copy the temporary pixmap onto the screen + */ + + if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) + return FALSE; + pGC = pScreenPriv->pRestoreGC; + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pWin, pGC); + + (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin, + pGC, + 0, 0, w, h, x, y); + return TRUE; +} diff --git a/mi/mieq.c b/mi/mieq.c new file mode 100644 index 000000000..02b35160c --- /dev/null +++ b/mi/mieq.c @@ -0,0 +1,191 @@ +/* + * $Xorg: mieq.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * mieq.c + * + * Machine independent event queue + * + */ + +# define NEED_EVENTS +# include "X.h" +# include "Xmd.h" +# include "Xproto.h" +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "inputstr.h" +# include "mi.h" +# include "scrnintstr.h" + +#define QUEUE_SIZE 256 + +typedef struct _Event { + xEvent event; + ScreenPtr pScreen; +} EventRec, *EventPtr; + +typedef struct _EventQueue { + HWEventQueueType head, tail; /* long for SetInputCheck */ + CARD32 lastEventTime; /* to avoid time running backwards */ + Bool lastMotion; + EventRec events[QUEUE_SIZE]; /* static allocation for signals */ + DevicePtr pKbd, pPtr; /* device pointer, to get funcs */ + ScreenPtr pEnqueueScreen; /* screen events are being delivered to */ + ScreenPtr pDequeueScreen; /* screen events are being dispatched to */ +} EventQueueRec, *EventQueuePtr; + +static EventQueueRec miEventQueue; + +Bool +mieqInit (pKbd, pPtr) + DevicePtr pKbd, pPtr; +{ + miEventQueue.head = miEventQueue.tail = 0; + miEventQueue.lastEventTime = GetTimeInMillis (); + miEventQueue.pKbd = pKbd; + miEventQueue.pPtr = pPtr; + miEventQueue.lastMotion = FALSE; + miEventQueue.pEnqueueScreen = screenInfo.screens[0]; + miEventQueue.pDequeueScreen = miEventQueue.pEnqueueScreen; + SetInputCheck (&miEventQueue.head, &miEventQueue.tail); + return TRUE; +} + +/* + * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue + * will never be interrupted. If this is called from both signal + * handlers and regular code, make sure the signal is suspended when + * called from regular code. + */ + +void +mieqEnqueue (e) + xEvent *e; +{ + HWEventQueueType oldtail, newtail, prevtail; + Bool isMotion; + + oldtail = miEventQueue.tail; + isMotion = e->u.u.type == MotionNotify; + if (isMotion && miEventQueue.lastMotion && oldtail != miEventQueue.head) + { + if (oldtail == 0) + oldtail = QUEUE_SIZE; + oldtail = oldtail - 1; + } + else + { + newtail = oldtail + 1; + if (newtail == QUEUE_SIZE) + newtail = 0; + /* Toss events which come in late */ + if (newtail == miEventQueue.head) + return; + miEventQueue.tail = newtail; + } + miEventQueue.lastMotion = isMotion; + miEventQueue.events[oldtail].event = *e; + /* + * Make sure that event times don't go backwards - this + * is "unnecessary", but very useful + */ + if (e->u.keyButtonPointer.time < miEventQueue.lastEventTime && + miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000) + { + miEventQueue.events[oldtail].event.u.keyButtonPointer.time = + miEventQueue.lastEventTime; + } + miEventQueue.events[oldtail].pScreen = miEventQueue.pEnqueueScreen; +} + +void +mieqSwitchScreen (pScreen, fromDIX) + ScreenPtr pScreen; + Bool fromDIX; +{ + miEventQueue.pEnqueueScreen = pScreen; + if (fromDIX) + miEventQueue.pDequeueScreen = pScreen; +} + +/* + * Call this from ProcessInputEvents() + */ + +mieqProcessInputEvents () +{ + EventRec *e; + int x, y; + xEvent xe; + + while (miEventQueue.head != miEventQueue.tail) + { + extern int screenIsSaved; + + if (screenIsSaved == SCREEN_SAVER_ON) + SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset); + + e = &miEventQueue.events[miEventQueue.head]; + /* + * Assumption - screen switching can only occur on motion events + */ + if (e->pScreen != miEventQueue.pDequeueScreen) + { + miEventQueue.pDequeueScreen = e->pScreen; + x = e->event.u.keyButtonPointer.rootX; + y = e->event.u.keyButtonPointer.rootY; + if (miEventQueue.head == QUEUE_SIZE - 1) + miEventQueue.head = 0; + else + ++miEventQueue.head; + NewCurrentScreen (miEventQueue.pDequeueScreen, x, y); + } + else + { + xe = e->event; + if (miEventQueue.head == QUEUE_SIZE - 1) + miEventQueue.head = 0; + else + ++miEventQueue.head; + switch (xe.u.u.type) + { + case KeyPress: + case KeyRelease: + (*miEventQueue.pKbd->processInputProc) + (&xe, (DeviceIntPtr)miEventQueue.pKbd, 1); + break; + default: + (*miEventQueue.pPtr->processInputProc) + (&xe, (DeviceIntPtr)miEventQueue.pPtr, 1); + break; + } + } + } +} diff --git a/mi/miexpose.c b/mi/miexpose.c new file mode 100644 index 000000000..cacb2f983 --- /dev/null +++ b/mi/miexpose.c @@ -0,0 +1,827 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "Xprotostr.h" + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include "Xmd.h" + +extern WindowPtr *WindowTable; + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr = pGC->pScreen; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, NullBox, 0); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, NullBox, 0); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + DeliverEvents(pWin, pEvent, numRects, NullWindow); + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC (value, id) +pointer value; +XID id; +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +} diff --git a/mi/mifillarc.c b/mi/mifillarc.c new file mode 100644 index 000000000..5889f1c06 --- /dev/null +++ b/mi/mifillarc.c @@ -0,0 +1,810 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Bob Scheifler, MIT X Consortium + +********************************************************/ + +/* $Xorg: mifillarc.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#include +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "mifpoly.h" +#include "mi.h" +#include "mifillarc.h" + +#define QUADRANT (90 * 64) +#define HALFCIRCLE (180 * 64) +#define QUADRANT3 (270 * 64) + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define Dsin(d) sin((double)d*(M_PI/11520.0)) +#define Dcos(d) cos((double)d*(M_PI/11520.0)) + +void +miFillArcSetup(arc, info) + register xArc *arc; + register miFillArcRec *info; +{ + info->y = arc->height >> 1; + info->dy = arc->height & 1; + info->yorg = arc->y + info->y; + info->dx = arc->width & 1; + info->xorg = arc->x + (arc->width >> 1) + info->dx; + info->dx = 1 - info->dx; + if (arc->width == arc->height) + { + /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */ + /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ + info->ym = 8; + info->xm = 8; + info->yk = info->y << 3; + if (!info->dx) + { + info->xk = 0; + info->e = -1; + } + else + { + info->y++; + info->yk += 4; + info->xk = -4; + info->e = - (info->y << 3); + } + } + else + { + /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ + /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ + info->ym = (arc->width * arc->width) << 3; + info->xm = (arc->height * arc->height) << 3; + info->yk = info->y * info->ym; + if (!info->dy) + info->yk -= info->ym >> 1; + if (!info->dx) + { + info->xk = 0; + info->e = - (info->xm >> 3); + } + else + { + info->y++; + info->yk += info->ym; + info->xk = -(info->xm >> 1); + info->e = info->xk - info->yk; + } + } +} + +void +miFillArcDSetup(arc, info) + register xArc *arc; + register miFillArcDRec *info; +{ + /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ + /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ + info->y = arc->height >> 1; + info->dy = arc->height & 1; + info->yorg = arc->y + info->y; + info->dx = arc->width & 1; + info->xorg = arc->x + (arc->width >> 1) + info->dx; + info->dx = 1 - info->dx; + info->ym = ((double)arc->width) * (arc->width * 8); + info->xm = ((double)arc->height) * (arc->height * 8); + info->yk = info->y * info->ym; + if (!info->dy) + info->yk -= info->ym / 2.0; + if (!info->dx) + { + info->xk = 0; + info->e = - (info->xm / 8.0); + } + else + { + info->y++; + info->yk += info->ym; + info->xk = -info->xm / 2.0; + info->e = info->xk - info->yk; + } +} + +static void +miGetArcEdge(arc, edge, k, top, left) + register xArc *arc; + register miSliceEdgePtr edge; + int k; + Bool top, left; +{ + register int xady, y; + + y = arc->height >> 1; + if (!(arc->width & 1)) + y++; + if (!top) + { + y = -y; + if (arc->height & 1) + y--; + } + xady = k + y * edge->dx; + if (xady <= 0) + edge->x = - ((-xady) / edge->dy + 1); + else + edge->x = (xady - 1) / edge->dy; + edge->e = xady - edge->x * edge->dy; + if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0))) + edge->e = edge->dy - edge->e + 1; + if (left) + edge->x++; + edge->x += arc->x + (arc->width >> 1); + if (edge->dx > 0) + { + edge->deltax = 1; + edge->stepx = edge->dx / edge->dy; + edge->dx = edge->dx % edge->dy; + } + else + { + edge->deltax = -1; + edge->stepx = - ((-edge->dx) / edge->dy); + edge->dx = (-edge->dx) % edge->dy; + } + if (!top) + { + edge->deltax = -edge->deltax; + edge->stepx = -edge->stepx; + } +} + +void +miEllipseAngleToSlope (angle, width, height, dxp, dyp, d_dxp, d_dyp) + int angle; + int width; + int height; + int *dxp; + int *dyp; + double *d_dxp; + double *d_dyp; +{ + int dx, dy; + double d_dx, d_dy, scale; + Bool negative_dx, negative_dy; + + switch (angle) { + case 0: + *dxp = -1; + *dyp = 0; + if (d_dxp) { + *d_dxp = width / 2.0; + *d_dyp = 0; + } + break; + case QUADRANT: + *dxp = 0; + *dyp = 1; + if (d_dxp) { + *d_dxp = 0; + *d_dyp = - height / 2.0; + } + break; + case HALFCIRCLE: + *dxp = 1; + *dyp = 0; + if (d_dxp) { + *d_dxp = - width / 2.0; + *d_dyp = 0; + } + break; + case QUADRANT3: + *dxp = 0; + *dyp = -1; + if (d_dxp) { + *d_dxp = 0; + *d_dyp = height / 2.0; + } + break; + default: + d_dx = Dcos(angle) * width; + d_dy = Dsin(angle) * height; + if (d_dxp) { + *d_dxp = d_dx / 2.0; + *d_dyp = - d_dy / 2.0; + } + negative_dx = FALSE; + if (d_dx < 0.0) + { + d_dx = -d_dx; + negative_dx = TRUE; + } + negative_dy = FALSE; + if (d_dy < 0.0) + { + d_dy = -d_dy; + negative_dy = TRUE; + } + scale = d_dx; + if (d_dy > d_dx) + scale = d_dy; + dx = floor ((d_dx * 32768) / scale + 0.5); + if (negative_dx) + dx = -dx; + *dxp = dx; + dy = floor ((d_dy * 32768) / scale + 0.5); + if (negative_dy) + dy = -dy; + *dyp = dy; + break; + } +} + +static void +miGetPieEdge(arc, angle, edge, top, left) + register xArc *arc; + register int angle; + register miSliceEdgePtr edge; + Bool top, left; +{ + register int k, signdx, signdy; + int dx, dy; + + miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0); + + if (dy == 0) + { + edge->x = left ? -65536 : 65536; + edge->stepx = 0; + edge->e = 0; + edge->dx = -1; + return; + } + if (dx == 0) + { + edge->x = arc->x + (arc->width >> 1); + if (left && (arc->width & 1)) + edge->x++; + else if (!left && !(arc->width & 1)) + edge->x--; + edge->stepx = 0; + edge->e = 0; + edge->dx = -1; + return; + } + if (dy < 0) { + dx = -dx; + dy = -dy; + } + k = (arc->height & 1) ? dx : 0; + if (arc->width & 1) + k += dy; + edge->dx = dx << 1; + edge->dy = dy << 1; + miGetArcEdge(arc, edge, k, top, left); +} + +void +miFillArcSliceSetup(arc, slice, pGC) + register xArc *arc; + register miArcSliceRec *slice; + GCPtr pGC; +{ + register int angle1, angle2; + + angle1 = arc->angle1; + if (arc->angle2 < 0) + { + angle2 = angle1; + angle1 += arc->angle2; + } + else + angle2 = angle1 + arc->angle2; + while (angle1 < 0) + angle1 += FULLCIRCLE; + while (angle1 >= FULLCIRCLE) + angle1 -= FULLCIRCLE; + while (angle2 < 0) + angle2 += FULLCIRCLE; + while (angle2 >= FULLCIRCLE) + angle2 -= FULLCIRCLE; + slice->min_top_y = 0; + slice->max_top_y = arc->height >> 1; + slice->min_bot_y = 1 - (arc->height & 1); + slice->max_bot_y = slice->max_top_y - 1; + slice->flip_top = FALSE; + slice->flip_bot = FALSE; + if (pGC->arcMode == ArcPieSlice) + { + slice->edge1_top = (angle1 < HALFCIRCLE); + slice->edge2_top = (angle2 <= HALFCIRCLE); + if ((angle2 == 0) || (angle1 == HALFCIRCLE)) + { + if (angle2 ? slice->edge2_top : slice->edge1_top) + slice->min_top_y = slice->min_bot_y; + else + slice->min_top_y = arc->height; + slice->min_bot_y = 0; + } + else if ((angle1 == 0) || (angle2 == HALFCIRCLE)) + { + slice->min_top_y = slice->min_bot_y; + if (angle1 ? slice->edge1_top : slice->edge2_top) + slice->min_bot_y = arc->height; + else + slice->min_bot_y = 0; + } + else if (slice->edge1_top == slice->edge2_top) + { + if (angle2 < angle1) + { + slice->flip_top = slice->edge1_top; + slice->flip_bot = !slice->edge1_top; + } + else if (slice->edge1_top) + { + slice->min_top_y = 1; + slice->min_bot_y = arc->height; + } + else + { + slice->min_bot_y = 0; + slice->min_top_y = arc->height; + } + } + miGetPieEdge(arc, angle1, &slice->edge1, + slice->edge1_top, !slice->edge1_top); + miGetPieEdge(arc, angle2, &slice->edge2, + slice->edge2_top, slice->edge2_top); + } + else + { + double w2, h2, x1, y1, x2, y2, dx, dy, scale; + int signdx, signdy, y, k; + Bool isInt1 = TRUE, isInt2 = TRUE; + + w2 = (double)arc->width / 2.0; + h2 = (double)arc->height / 2.0; + if ((angle1 == 0) || (angle1 == HALFCIRCLE)) + { + x1 = angle1 ? -w2 : w2; + y1 = 0.0; + } + else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3)) + { + x1 = 0.0; + y1 = (angle1 == QUADRANT) ? h2 : -h2; + } + else + { + isInt1 = FALSE; + x1 = Dcos(angle1) * w2; + y1 = Dsin(angle1) * h2; + } + if ((angle2 == 0) || (angle2 == HALFCIRCLE)) + { + x2 = angle2 ? -w2 : w2; + y2 = 0.0; + } + else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3)) + { + x2 = 0.0; + y2 = (angle2 == QUADRANT) ? h2 : -h2; + } + else + { + isInt2 = FALSE; + x2 = Dcos(angle2) * w2; + y2 = Dsin(angle2) * h2; + } + dx = x2 - x1; + dy = y2 - y1; + if (arc->height & 1) + { + y1 -= 0.5; + y2 -= 0.5; + } + if (arc->width & 1) + { + x1 += 0.5; + x2 += 0.5; + } + if (dy < 0.0) + { + dy = -dy; + signdy = -1; + } + else + signdy = 1; + if (dx < 0.0) + { + dx = -dx; + signdx = -1; + } + else + signdx = 1; + if (isInt1 && isInt2) + { + slice->edge1.dx = dx * 2; + slice->edge1.dy = dy * 2; + } + else + { + scale = (dx > dy) ? dx : dy; + slice->edge1.dx = floor((dx * 32768) / scale + .5); + slice->edge1.dy = floor((dy * 32768) / scale + .5); + } + if (!slice->edge1.dy) + { + if (signdx < 0) + { + y = floor(y1 + 1.0); + if (y >= 0) + { + slice->min_top_y = y; + slice->min_bot_y = arc->height; + } + else + { + slice->max_bot_y = -y - (arc->height & 1); + } + } + else + { + y = floor(y1); + if (y >= 0) + slice->max_top_y = y; + else + { + slice->min_top_y = arc->height; + slice->min_bot_y = -y - (arc->height & 1); + } + } + slice->edge1_top = TRUE; + slice->edge1.x = 65536; + slice->edge1.stepx = 0; + slice->edge1.e = 0; + slice->edge1.dx = -1; + slice->edge2 = slice->edge1; + slice->edge2_top = FALSE; + } + else if (!slice->edge1.dx) + { + if (signdy < 0) + x1 -= 1.0; + slice->edge1.x = ceil(x1); + slice->edge1_top = signdy < 0; + slice->edge1.x += arc->x + (arc->width >> 1); + slice->edge1.stepx = 0; + slice->edge1.e = 0; + slice->edge1.dx = -1; + slice->edge2_top = !slice->edge1_top; + slice->edge2 = slice->edge1; + } + else + { + if (signdx < 0) + slice->edge1.dx = -slice->edge1.dx; + if (signdy < 0) + slice->edge1.dx = -slice->edge1.dx; + k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0); + slice->edge2.dx = slice->edge1.dx; + slice->edge2.dy = slice->edge1.dy; + slice->edge1_top = signdy < 0; + slice->edge2_top = !slice->edge1_top; + miGetArcEdge(arc, &slice->edge1, k, + slice->edge1_top, !slice->edge1_top); + miGetArcEdge(arc, &slice->edge2, k, + slice->edge2_top, slice->edge2_top); + } + } +} + +#define ADDSPANS() \ + pts->x = xorg - x; \ + pts->y = yorg - y; \ + *wids = slw; \ + pts++; \ + wids++; \ + if (miFillArcLower(slw)) \ + { \ + pts->x = xorg - x; \ + pts->y = yorg + y + dy; \ + pts++; \ + *wids++ = slw; \ + } + +static void +miFillEllipseI(pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + register int x, y, e; + int yk, xk, ym, xm, dx, dy, xorg, yorg; + int slw; + miFillArcRec info; + DDXPointPtr points; + register DDXPointPtr pts; + int *widths; + register int *wids; + + points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * arc->height); + if (!points) + return; + widths = (int *)ALLOCATE_LOCAL(sizeof(int) * arc->height); + if (!widths) + { + DEALLOCATE_LOCAL(points); + return; + } + miFillArcSetup(arc, &info); + MIFILLARCSETUP(); + if (pGC->miTranslate) + { + xorg += pDraw->x; + yorg += pDraw->y; + } + pts = points; + wids = widths; + while (y > 0) + { + MIFILLARCSTEP(slw); + ADDSPANS(); + } + (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + DEALLOCATE_LOCAL(widths); + DEALLOCATE_LOCAL(points); +} + +static void +miFillEllipseD(pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + register int x, y; + int xorg, yorg, dx, dy, slw; + double e, yk, xk, ym, xm; + miFillArcDRec info; + DDXPointPtr points; + register DDXPointPtr pts; + int *widths; + register int *wids; + + points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * arc->height); + if (!points) + return; + widths = (int *)ALLOCATE_LOCAL(sizeof(int) * arc->height); + if (!widths) + { + DEALLOCATE_LOCAL(points); + return; + } + miFillArcDSetup(arc, &info); + MIFILLARCSETUP(); + if (pGC->miTranslate) + { + xorg += pDraw->x; + yorg += pDraw->y; + } + pts = points; + wids = widths; + while (y > 0) + { + MIFILLARCSTEP(slw); + ADDSPANS(); + } + (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + DEALLOCATE_LOCAL(widths); + DEALLOCATE_LOCAL(points); +} + +#define ADDSPAN(l,r) \ + if (r >= l) \ + { \ + pts->x = l; \ + pts->y = ya; \ + pts++; \ + *wids++ = r - l + 1; \ + } + +#define ADDSLICESPANS(flip) \ + if (!flip) \ + { \ + ADDSPAN(xl, xr); \ + } \ + else \ + { \ + xc = xorg - x; \ + ADDSPAN(xc, xr); \ + xc += slw - 1; \ + ADDSPAN(xl, xc); \ + } + +static void +miFillArcSliceI(pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; + register int x, y, e; + miFillArcRec info; + miArcSliceRec slice; + int ya, xl, xr, xc; + DDXPointPtr points; + register DDXPointPtr pts; + int *widths; + register int *wids; + + miFillArcSetup(arc, &info); + miFillArcSliceSetup(arc, &slice, pGC); + MIFILLARCSETUP(); + slw = arc->height; + if (slice.flip_top || slice.flip_bot) + slw += (arc->height >> 1) + 1; + points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * slw); + if (!points) + return; + widths = (int *)ALLOCATE_LOCAL(sizeof(int) * slw); + if (!widths) + { + DEALLOCATE_LOCAL(points); + return; + } + if (pGC->miTranslate) + { + xorg += pDraw->x; + yorg += pDraw->y; + slice.edge1.x += pDraw->x; + slice.edge2.x += pDraw->x; + } + pts = points; + wids = widths; + while (y > 0) + { + MIFILLARCSTEP(slw); + MIARCSLICESTEP(slice.edge1); + MIARCSLICESTEP(slice.edge2); + if (miFillSliceUpper(slice)) + { + ya = yorg - y; + MIARCSLICEUPPER(xl, xr, slice, slw); + ADDSLICESPANS(slice.flip_top); + } + if (miFillSliceLower(slice)) + { + ya = yorg + y + dy; + MIARCSLICELOWER(xl, xr, slice, slw); + ADDSLICESPANS(slice.flip_bot); + } + } + (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + DEALLOCATE_LOCAL(widths); + DEALLOCATE_LOCAL(points); +} + +static void +miFillArcSliceD(pDraw, pGC, arc) + DrawablePtr pDraw; + GCPtr pGC; + xArc *arc; +{ + register int x, y; + int dx, dy, xorg, yorg, slw; + double e, yk, xk, ym, xm; + miFillArcDRec info; + miArcSliceRec slice; + int ya, xl, xr, xc; + DDXPointPtr points; + register DDXPointPtr pts; + int *widths; + register int *wids; + + miFillArcDSetup(arc, &info); + miFillArcSliceSetup(arc, &slice, pGC); + MIFILLARCSETUP(); + slw = arc->height; + if (slice.flip_top || slice.flip_bot) + slw += (arc->height >> 1) + 1; + points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * slw); + if (!points) + return; + widths = (int *)ALLOCATE_LOCAL(sizeof(int) * slw); + if (!widths) + { + DEALLOCATE_LOCAL(points); + return; + } + if (pGC->miTranslate) + { + xorg += pDraw->x; + yorg += pDraw->y; + slice.edge1.x += pDraw->x; + slice.edge2.x += pDraw->x; + } + pts = points; + wids = widths; + while (y > 0) + { + MIFILLARCSTEP(slw); + MIARCSLICESTEP(slice.edge1); + MIARCSLICESTEP(slice.edge2); + if (miFillSliceUpper(slice)) + { + ya = yorg - y; + MIARCSLICEUPPER(xl, xr, slice, slw); + ADDSLICESPANS(slice.flip_top); + } + if (miFillSliceLower(slice)) + { + ya = yorg + y + dy; + MIARCSLICELOWER(xl, xr, slice, slw); + ADDSLICESPANS(slice.flip_bot); + } + } + (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + DEALLOCATE_LOCAL(widths); + DEALLOCATE_LOCAL(points); +} + +/* MIPOLYFILLARC -- The public entry for the PolyFillArc request. + * Since we don't have to worry about overlapping segments, we can just + * fill each arc as it comes. + */ +void +miPolyFillArc(pDraw, pGC, narcs, parcs) + DrawablePtr pDraw; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + register int i; + register xArc *arc; + + for(i = narcs, arc = parcs; --i >= 0; arc++) + { + if (miFillArcEmpty(arc)) + continue;; + if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) + { + if (miCanFillArc(arc)) + miFillEllipseI(pDraw, pGC, arc); + else + miFillEllipseD(pDraw, pGC, arc); + } + else + { + if (miCanFillArc(arc)) + miFillArcSliceI(pDraw, pGC, arc); + else + miFillArcSliceD(pDraw, pGC, arc); + } + } +} diff --git a/mi/mifillarc.h b/mi/mifillarc.h new file mode 100644 index 000000000..63071bbd1 --- /dev/null +++ b/mi/mifillarc.h @@ -0,0 +1,223 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mifillarc.h,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#define FULLCIRCLE (360 * 64) + +typedef struct _miFillArc { + int xorg, yorg; + int y; + int dx, dy; + int e; + int ym, yk, xm, xk; +} miFillArcRec; + +/* could use 64-bit integers */ +typedef struct _miFillArcD { + int xorg, yorg; + int y; + int dx, dy; + double e; + double ym, yk, xm, xk; +} miFillArcDRec; + +#define miFillArcEmpty(arc) (!(arc)->angle2 || \ + !(arc)->width || !(arc)->height || \ + (((arc)->width == 1) && ((arc)->height & 1))) + +#define miCanFillArc(arc) (((arc)->width == (arc)->height) || \ + (((arc)->width <= 800) && ((arc)->height <= 800))) + +#define MIFILLARCSETUP() \ + x = 0; \ + y = info.y; \ + e = info.e; \ + xk = info.xk; \ + xm = info.xm; \ + yk = info.yk; \ + ym = info.ym; \ + dx = info.dx; \ + dy = info.dy; \ + xorg = info.xorg; \ + yorg = info.yorg + +#define MIFILLARCSTEP(slw) \ + e += yk; \ + while (e >= 0) \ + { \ + x++; \ + xk -= xm; \ + e += xk; \ + } \ + y--; \ + yk -= ym; \ + slw = (x << 1) + dx; \ + if ((e == xk) && (slw > 1)) \ + slw-- + +#define MIFILLCIRCSTEP(slw) MIFILLARCSTEP(slw) +#define MIFILLELLSTEP(slw) MIFILLARCSTEP(slw) + +#define miFillArcLower(slw) (((y + dy) != 0) && ((slw > 1) || (e != xk))) + +typedef struct _miSliceEdge { + int x; + int stepx; + int deltax; + int e; + int dy; + int dx; +} miSliceEdgeRec, *miSliceEdgePtr; + +typedef struct _miArcSlice { + miSliceEdgeRec edge1, edge2; + int min_top_y, max_top_y; + int min_bot_y, max_bot_y; + Bool edge1_top, edge2_top; + Bool flip_top, flip_bot; +} miArcSliceRec; + +#define MIARCSLICESTEP(edge) \ + edge.x -= edge.stepx; \ + edge.e -= edge.dx; \ + if (edge.e <= 0) \ + { \ + edge.x -= edge.deltax; \ + edge.e += edge.dy; \ + } + +#define miFillSliceUpper(slice) \ + ((y >= slice.min_top_y) && (y <= slice.max_top_y)) + +#define miFillSliceLower(slice) \ + ((y >= slice.min_bot_y) && (y <= slice.max_bot_y)) + +#define MIARCSLICEUPPER(xl,xr,slice,slw) \ + xl = xorg - x; \ + xr = xl + slw - 1; \ + if (slice.edge1_top && (slice.edge1.x < xr)) \ + xr = slice.edge1.x; \ + if (slice.edge2_top && (slice.edge2.x > xl)) \ + xl = slice.edge2.x; + +#define MIARCSLICELOWER(xl,xr,slice,slw) \ + xl = xorg - x; \ + xr = xl + slw - 1; \ + if (!slice.edge1_top && (slice.edge1.x > xl)) \ + xl = slice.edge1.x; \ + if (!slice.edge2_top && (slice.edge2.x < xr)) \ + xr = slice.edge2.x; + +#define MIWIDEARCSETUP(x,y,dy,slw,e,xk,xm,yk,ym) \ + x = 0; \ + y = slw >> 1; \ + yk = y << 3; \ + xm = 8; \ + ym = 8; \ + if (dy) \ + { \ + xk = 0; \ + if (slw & 1) \ + e = -1; \ + else \ + e = -(y << 2) - 2; \ + } \ + else \ + { \ + y++; \ + yk += 4; \ + xk = -4; \ + if (slw & 1) \ + e = -(y << 2) - 3; \ + else \ + e = - (y << 3); \ + } + +#define MIFILLINARCSTEP(slw) \ + ine += inyk; \ + while (ine >= 0) \ + { \ + inx++; \ + inxk -= inxm; \ + ine += inxk; \ + } \ + iny--; \ + inyk -= inym; \ + slw = (inx << 1) + dx; \ + if ((ine == inxk) && (slw > 1)) \ + slw-- + +#define miFillInArcLower(slw) (((iny + dy) != 0) && \ + ((slw > 1) || (ine != inxk))) + +extern int miFreeArcCache( +#if NeedFunctionPrototypes + pointer /*data*/, + XID /*id*/ +#endif +); + +extern struct finalSpan *realAllocSpan( +#if NeedFunctionPrototypes + void +#endif +); + +extern void miFillArcSetup( +#if NeedFunctionPrototypes + xArc * /*arc*/, + miFillArcRec * /*info*/ +#endif +); + +extern void miFillArcDSetup( +#if NeedFunctionPrototypes + xArc * /*arc*/, + miFillArcDRec * /*info*/ +#endif +); + +extern void miEllipseAngleToSlope( +#if NeedFunctionPrototypes + int /*angle*/, + int /*width*/, + int /*height*/, + int * /*dxp*/, + int * /*dyp*/, + double * /*d_dxp*/, + double * /*d_dyp*/ +#endif +); + +extern void miFillArcSliceSetup( +#if NeedFunctionPrototypes + xArc * /*arc*/, + miArcSliceRec * /*slice*/, + GCPtr /*pGC*/ +#endif +); + diff --git a/mi/mifillrct.c b/mi/mifillrct.c new file mode 100644 index 000000000..af2f9429b --- /dev/null +++ b/mi/mifillrct.c @@ -0,0 +1,139 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mifillrct.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#include "X.h" +#include "Xprotostr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" + +#include "misc.h" + +/* mi rectangles + written by newman, with debts to all and sundry +*/ + +/* MIPOLYFILLRECT -- public entry for PolyFillRect request + * very straight forward: translate rectangles if necessary + * then call FillSpans to fill each rectangle. We let FillSpans worry about + * clipping to the destination + */ +void +miPolyFillRect(pDrawable, pGC, nrectFill, prectInit) + DrawablePtr pDrawable; + GCPtr pGC; + int nrectFill; /* number of rectangles to fill */ + xRectangle *prectInit; /* Pointer to first rectangle to fill */ +{ + int i; + register int height; + register int width; + register xRectangle *prect; + int xorg; + register int yorg; + int maxheight; + DDXPointPtr pptFirst; + register DDXPointPtr ppt; + int *pwFirst; + register int *pw; + + if (pGC->miTranslate) + { + xorg = pDrawable->x; + yorg = pDrawable->y; + prect = prectInit; + maxheight = 0; + for (i = 0; ix += xorg; + prect->y += yorg; + maxheight = max(maxheight, prect->height); + } + } + else + { + prect = prectInit; + maxheight = 0; + for (i = 0; iheight); + } + + pptFirst = (DDXPointPtr) ALLOCATE_LOCAL(maxheight * sizeof(DDXPointRec)); + pwFirst = (int *) ALLOCATE_LOCAL(maxheight * sizeof(int)); + if(!pptFirst || !pwFirst) + { + if (pwFirst) DEALLOCATE_LOCAL(pwFirst); + if (pptFirst) DEALLOCATE_LOCAL(pptFirst); + return; + } + + prect = prectInit; + while(nrectFill--) + { + ppt = pptFirst; + pw = pwFirst; + height = prect->height; + width = prect->width; + xorg = prect->x; + yorg = prect->y; + while(height--) + { + *pw++ = width; + ppt->x = xorg; + ppt->y = yorg; + ppt++; + yorg++; + } + (* pGC->ops->FillSpans)(pDrawable, pGC, + prect->height, pptFirst, pwFirst, + 1); + prect++; + } + DEALLOCATE_LOCAL(pwFirst); + DEALLOCATE_LOCAL(pptFirst); +} diff --git a/mi/mifpoly.h b/mi/mifpoly.h new file mode 100644 index 000000000..bb923e2b6 --- /dev/null +++ b/mi/mifpoly.h @@ -0,0 +1,108 @@ +/* $Xorg: mifpoly.h,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#define EPSILON 0.000001 +#define ISEQUAL(a,b) (Fabs((a) - (b)) <= EPSILON) +#define UNEQUAL(a,b) (Fabs((a) - (b)) > EPSILON) +#define WITHINHALF(a, b) (((a) - (b) > 0.0) ? (a) - (b) < 0.5 : \ + (b) - (a) <= 0.5) +#define ROUNDTOINT(x) ((int) (((x) > 0.0) ? ((x) + 0.5) : ((x) - 0.5))) +#define ISZERO(x) (Fabs((x)) <= EPSILON) +#define PTISEQUAL(a,b) (ISEQUAL(a.x,b.x) && ISEQUAL(a.y,b.y)) +#define PTUNEQUAL(a,b) (UNEQUAL(a.x,b.x) || UNEQUAL(a.y,b.y)) +#define PtEqual(a, b) (((a).x == (b).x) && ((a).y == (b).y)) + +#define NotEnd 0 +#define FirstEnd 1 +#define SecondEnd 2 + +#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - for 11o miter cutoff */ +#define D2SECANT 5.21671526231167 /* 1/2*sin(11/2) - max extension per width */ + +#ifdef NOINLINEICEIL +#define ICEIL(x) ((int)ceil(x)) +#else +#ifdef __GNUC__ +static __inline int ICEIL(x) + double x; +{ + int _cTmp = x; + return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp+1; +} +#else +#define ICEIL(x) ((((x) == (_cTmp = (x))) || ((x) < 0.0)) ? _cTmp : _cTmp+1) +#define ICEILTEMPDECL static int _cTmp; +#endif +#endif + +/* Point with sub-pixel positioning. In this case we use doubles, but + * see mifpolycon.c for other suggestions + */ +typedef struct _SppPoint { + double x, y; +} SppPointRec, *SppPointPtr; + +typedef struct _SppArc { + double x, y, width, height; + double angle1, angle2; +} SppArcRec, *SppArcPtr; + +/* mifpolycon.c */ + +extern void miFillSppPoly( +#if NeedFunctionPrototypes + DrawablePtr /*dst*/, + GCPtr /*pgc*/, + int /*count*/, + SppPointPtr /*ptsIn*/, + int /*xTrans*/, + int /*yTrans*/, + double /*xFtrans*/, + double /*yFtrans*/ +#endif +); diff --git a/mi/mifpolycon.c b/mi/mifpolycon.c new file mode 100644 index 000000000..0b6655186 --- /dev/null +++ b/mi/mifpolycon.c @@ -0,0 +1,277 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mifpolycon.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include +#include "X.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "mifpoly.h" + +static int GetFPolyYBounds(); + +#ifdef ICEILTEMPDECL +ICEILTEMPDECL +#endif + +/* + * Written by Todd Newman; April. 1987. + * + * Fill a convex polygon. If the given polygon + * is not convex, then the result is undefined. + * The algorithm is to order the edges from smallest + * y to largest by partitioning the array into a left + * edge list and a right edge list. The algorithm used + * to traverse each edge is digital differencing analyzer + * line algorithm with y as the major axis. There's some funny linear + * interpolation involved because of the subpixel postioning. + */ +void +miFillSppPoly(dst, pgc, count, ptsIn, xTrans, yTrans, xFtrans, yFtrans) + DrawablePtr dst; + GCPtr pgc; + int count; /* number of points */ + SppPointPtr ptsIn; /* the points */ + int xTrans, yTrans; /* Translate each point by this */ + double xFtrans, yFtrans; /* translate before conversion + by this amount. This provides + a mechanism to match rounding + errors with any shape that must + meet the polygon exactly. + */ +{ + double xl, xr, /* x vals of left and right edges */ + ml, /* left edge slope */ + mr, /* right edge slope */ + dy, /* delta y */ + i; /* loop counter */ + int y, /* current scanline */ + j, + imin, /* index of vertex with smallest y */ + ymin, /* y-extents of polygon */ + ymax, + *width, + *FirstWidth, /* output buffer */ + *Marked; /* set if this vertex has been used */ + register int left, right, /* indices to first endpoints */ + nextleft, + nextright; /* indices to second endpoints */ + DDXPointPtr ptsOut, + FirstPoint; /* output buffer */ + + if (pgc->miTranslate) + { + xTrans += dst->x; + yTrans += dst->y; + } + + imin = GetFPolyYBounds(ptsIn, count, yFtrans, &ymin, &ymax); + + y = ymax - ymin + 1; + if ((count < 3) || (y <= 0)) + return; + ptsOut = FirstPoint = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * y); + width = FirstWidth = (int *) ALLOCATE_LOCAL(sizeof(int) * y); + Marked = (int *) ALLOCATE_LOCAL(sizeof(int) * count); + + if(!ptsOut || !width || !Marked) + { + if (Marked) DEALLOCATE_LOCAL(Marked); + if (width) DEALLOCATE_LOCAL(width); + if (ptsOut) DEALLOCATE_LOCAL(ptsOut); + return; + } + + for(j = 0; j < count; j++) + Marked[j] = 0; + nextleft = nextright = imin; + Marked[imin] = -1; + y = ICEIL(ptsIn[nextleft].y + yFtrans); + + /* + * loop through all edges of the polygon + */ + do + { + /* add a left edge if we need to */ + if ((y > (ptsIn[nextleft].y + yFtrans) || + ISEQUAL(y, ptsIn[nextleft].y + yFtrans)) && + Marked[nextleft] != 1) + { + Marked[nextleft]++; + left = nextleft++; + + /* find the next edge, considering the end conditions */ + if (nextleft >= count) + nextleft = 0; + + /* now compute the starting point and slope */ + dy = ptsIn[nextleft].y - ptsIn[left].y; + if (dy != 0.0) + { + ml = (ptsIn[nextleft].x - ptsIn[left].x) / dy; + dy = y - (ptsIn[left].y + yFtrans); + xl = (ptsIn[left].x + xFtrans) + ml * max(dy, 0); + } + } + + /* add a right edge if we need to */ + if ((y > ptsIn[nextright].y + yFtrans) || + ISEQUAL(y, ptsIn[nextright].y + yFtrans) + && Marked[nextright] != 1) + { + Marked[nextright]++; + right = nextright--; + + /* find the next edge, considering the end conditions */ + if (nextright < 0) + nextright = count - 1; + + /* now compute the starting point and slope */ + dy = ptsIn[nextright].y - ptsIn[right].y; + if (dy != 0.0) + { + mr = (ptsIn[nextright].x - ptsIn[right].x) / dy; + dy = y - (ptsIn[right].y + yFtrans); + xr = (ptsIn[right].x + xFtrans) + mr * max(dy, 0); + } + } + + + /* + * generate scans to fill while we still have + * a right edge as well as a left edge. + */ + i = (min(ptsIn[nextleft].y, ptsIn[nextright].y) + yFtrans) - y; + + if (i < EPSILON) + { + if(Marked[nextleft] && Marked[nextright]) + { + /* Arrgh, we're trapped! (no more points) + * Out, we've got to get out of here before this decadence saps + * our will completely! */ + break; + } + continue; + } + else + { + j = (int) i; + if(!j) + j++; + } + while (j > 0) + { + int cxl, cxr; + + ptsOut->y = (y) + yTrans; + + cxl = ICEIL(xl); + cxr = ICEIL(xr); + /* reverse the edges if necessary */ + if (xl < xr) + { + *(width++) = cxr - cxl; + (ptsOut++)->x = cxl + xTrans; + } + else + { + *(width++) = cxl - cxr; + (ptsOut++)->x = cxr + xTrans; + } + y++; + + /* increment down the edges */ + xl += ml; + xr += mr; + j--; + } + } while (y <= ymax); + + /* Finally, fill the spans we've collected */ + (*pgc->ops->FillSpans)(dst, pgc, + ptsOut-FirstPoint, FirstPoint, FirstWidth, 1); + DEALLOCATE_LOCAL(Marked); + DEALLOCATE_LOCAL(FirstWidth); + DEALLOCATE_LOCAL(FirstPoint); +} + + +/* Find the index of the point with the smallest y.also return the + * smallest and largest y */ +static +int +GetFPolyYBounds(pts, n, yFtrans, by, ty) + register SppPointPtr pts; + int n; + double yFtrans; + int *by, *ty; +{ + register SppPointPtr ptMin; + double ymin, ymax; + SppPointPtr ptsStart = pts; + + ptMin = pts; + ymin = ymax = (pts++)->y; + + while (--n > 0) { + if (pts->y < ymin) + { + ptMin = pts; + ymin = pts->y; + } + if(pts->y > ymax) + ymax = pts->y; + + pts++; + } + + *by = ICEIL(ymin + yFtrans); + *ty = ICEIL(ymax + yFtrans - 1); + return(ptMin-ptsStart); +} diff --git a/mi/migc.c b/mi/migc.c new file mode 100644 index 000000000..808347d22 --- /dev/null +++ b/mi/migc.c @@ -0,0 +1,295 @@ +/* $Xorg: migc.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "migc.h" + +int miGCPrivateIndex; + +void +miRegisterGCPrivateIndex(gcindex) + int gcindex; +{ + miGCPrivateIndex = gcindex; +} + +/* ARGSUSED */ +void +miChangeGC(pGC, mask) + GCPtr pGC; + unsigned long mask; +{ + return; +} + +void +miDestroyGC(pGC) + GCPtr pGC; +{ + miPrivGC *pPriv; + + pPriv = (miPrivGC *) (pGC->devPrivates[miGCPrivateIndex].ptr); + if (pPriv->pRotatedPixmap) + (*pGC->pScreen->DestroyPixmap) (pPriv->pRotatedPixmap); + if (pPriv->freeCompClip) + REGION_DESTROY(pGC->pScreen, pPriv->pCompositeClip); + miDestroyGCOps(pGC->ops); +} + +/* + * create a private op array for a gc + */ + +GCOpsPtr +miCreateGCOps(prototype) + GCOpsPtr prototype; +{ + GCOpsPtr ret; + extern Bool Must_have_memory; + + /* XXX */ Must_have_memory = TRUE; + ret = (GCOpsPtr) xalloc(sizeof(GCOps)); + /* XXX */ Must_have_memory = FALSE; + if (!ret) + return 0; + *ret = *prototype; + ret->devPrivate.val = 1; + return ret; +} + +void +miDestroyGCOps(ops) + GCOpsPtr ops; +{ + if (ops->devPrivate.val) + xfree(ops); +} + + +void +miDestroyClip(pGC) + GCPtr pGC; +{ + if (pGC->clientClipType == CT_NONE) + return; + else if (pGC->clientClipType == CT_PIXMAP) + { + (*pGC->pScreen->DestroyPixmap) ((PixmapPtr) (pGC->clientClip)); + } + else + { + /* + * we know we'll never have a list of rectangles, since ChangeClip + * immediately turns them into a region + */ + REGION_DESTROY(pGC->pScreen, pGC->clientClip); + } + pGC->clientClip = NULL; + pGC->clientClipType = CT_NONE; +} + +void +miChangeClip(pGC, type, pvalue, nrects) + GCPtr pGC; + int type; + pointer pvalue; + int nrects; +{ + (*pGC->funcs->DestroyClip) (pGC); + if (type == CT_PIXMAP) + { + /* convert the pixmap to a region */ + pGC->clientClip = (pointer) BITMAP_TO_REGION(pGC->pScreen, + (PixmapPtr) pvalue); + (*pGC->pScreen->DestroyPixmap) (pvalue); + } + else if (type == CT_REGION) + { + /* stuff the region in the GC */ + pGC->clientClip = pvalue; + } + else if (type != CT_NONE) + { + pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nrects, + (xRectangle *) pvalue, + type); + xfree(pvalue); + } + pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : CT_NONE; + pGC->stateChanges |= GCClipMask; +} + +void +miCopyClip(pgcDst, pgcSrc) + GCPtr pgcDst, pgcSrc; +{ + RegionPtr prgnNew; + + switch (pgcSrc->clientClipType) + { + case CT_PIXMAP: + ((PixmapPtr) pgcSrc->clientClip)->refcnt++; + /* Fall through !! */ + case CT_NONE: + (*pgcDst->funcs->ChangeClip) (pgcDst, (int) pgcSrc->clientClipType, + pgcSrc->clientClip, 0); + break; + case CT_REGION: + prgnNew = REGION_CREATE(pgcSrc->pScreen, NULL, 1); + REGION_COPY(pgcDst->pScreen, prgnNew, + (RegionPtr) (pgcSrc->clientClip)); + (*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, (pointer) prgnNew, 0); + break; + } +} + +/* ARGSUSED */ +void +miCopyGC(pGCSrc, changes, pGCDst) + GCPtr pGCSrc; + unsigned long changes; + GCPtr pGCDst; +{ + return; +} + +void +miComputeCompositeClip(pGC, pDrawable) + GCPtr pGC; + DrawablePtr pDrawable; +{ + ScreenPtr pScreen = pGC->pScreen; + miPrivGC *devPriv = (miPrivGC *) (pGC->devPrivates[miGCPrivateIndex].ptr); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDrawable; + RegionPtr pregWin; + Bool freeTmpClip, freeCompClip; + + if (pGC->subWindowMode == IncludeInferiors) + { + pregWin = NotClippedByChildren(pWin); + freeTmpClip = TRUE; + } + else + { + pregWin = &pWin->clipList; + freeTmpClip = FALSE; + } + freeCompClip = devPriv->freeCompClip; + + /* + * if there is no client clip, we can get by with just keeping the + * pointer we got, and remembering whether or not should destroy (or + * maybe re-use) it later. this way, we avoid unnecessary copying of + * regions. (this wins especially if many clients clip by children + * and have no client clip.) + */ + if (pGC->clientClipType == CT_NONE) + { + if (freeCompClip) + REGION_DESTROY(pScreen, devPriv->pCompositeClip); + devPriv->pCompositeClip = pregWin; + devPriv->freeCompClip = freeTmpClip; + } + else + { + /* + * we need one 'real' region to put into the composite clip. if + * pregWin the current composite clip are real, we can get rid of + * one. if pregWin is real and the current composite clip isn't, + * use pregWin for the composite clip. if the current composite + * clip is real and pregWin isn't, use the current composite + * clip. if neither is real, create a new region. + */ + + REGION_TRANSLATE(pScreen, pGC->clientClip, + pDrawable->x + pGC->clipOrg.x, + pDrawable->y + pGC->clipOrg.y); + + if (freeCompClip) + { + REGION_INTERSECT(pGC->pScreen, devPriv->pCompositeClip, + pregWin, pGC->clientClip); + if (freeTmpClip) + REGION_DESTROY(pScreen, pregWin); + } + else if (freeTmpClip) + { + REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip); + devPriv->pCompositeClip = pregWin; + } + else + { + devPriv->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); + REGION_INTERSECT(pScreen, devPriv->pCompositeClip, + pregWin, pGC->clientClip); + } + devPriv->freeCompClip = TRUE; + REGION_TRANSLATE(pScreen, pGC->clientClip, + -(pDrawable->x + pGC->clipOrg.x), + -(pDrawable->y + pGC->clipOrg.y)); + } + } /* end of composite clip for a window */ + else + { + BoxRec pixbounds; + + /* XXX should we translate by drawable.x/y here ? */ + pixbounds.x1 = 0; + pixbounds.y1 = 0; + pixbounds.x2 = pDrawable->width; + pixbounds.y2 = pDrawable->height; + + if (devPriv->freeCompClip) + { + REGION_RESET(pScreen, devPriv->pCompositeClip, &pixbounds); + } + else + { + devPriv->freeCompClip = TRUE; + devPriv->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1); + } + + if (pGC->clientClipType == CT_REGION) + { + REGION_TRANSLATE(pScreen, devPriv->pCompositeClip, + -pGC->clipOrg.x, -pGC->clipOrg.y); + REGION_INTERSECT(pScreen, devPriv->pCompositeClip, + devPriv->pCompositeClip, pGC->clientClip); + REGION_TRANSLATE(pScreen, devPriv->pCompositeClip, + pGC->clipOrg.x, pGC->clipOrg.y); + } + } /* end of composite clip for pixmap */ +} /* end miComputeCompositeClip */ diff --git a/mi/migc.h b/mi/migc.h new file mode 100644 index 000000000..9e9974c3e --- /dev/null +++ b/mi/migc.h @@ -0,0 +1,113 @@ +/* $Xorg: migc.h,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* This structure has to line up with the mfb and cfb gc private structures so + * that when it is superimposed on them, the three fields that migc.c needs to + * see will be accessed correctly. I know this is not beautiful, but it seemed + * better than all the code duplication in cfb and mfb. + */ +typedef struct { + unsigned char pad1; + unsigned char pad2; + unsigned char pad3; + unsigned pad4:1; + unsigned freeCompClip:1; + PixmapPtr pRotatedPixmap; + RegionPtr pCompositeClip; +} miPrivGC; + +extern int miGCPrivateIndex; + +extern void miRegisterGCPrivateIndex( +#if NeedFunctionPrototypes + int /*gcindex*/ +#endif +); + +extern void miChangeGC( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + unsigned long /*mask*/ +#endif +); + +extern void miDestroyGC( +#if NeedFunctionPrototypes + GCPtr /*pGC*/ +#endif +); + +extern GCOpsPtr miCreateGCOps( +#if NeedFunctionPrototypes + GCOpsPtr /*prototype*/ +#endif +); + +extern void miDestroyGCOps( +#if NeedFunctionPrototypes + GCOpsPtr /*ops*/ +#endif +); + +extern void miDestroyClip( +#if NeedFunctionPrototypes + GCPtr /*pGC*/ +#endif +); + +extern void miChangeClip( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + int /*type*/, + pointer /*pvalue*/, + int /*nrects*/ +#endif +); + +extern void miCopyClip( +#if NeedFunctionPrototypes + GCPtr /*pgcDst*/, + GCPtr /*pgcSrc*/ +#endif +); + +extern void miCopyGC( +#if NeedFunctionPrototypes + GCPtr /*pGCSrc*/, + unsigned long /*changes*/, + GCPtr /*pGCDst*/ +#endif +); + +extern void miComputeCompositeClip( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + DrawablePtr /*pDrawable*/ +#endif +); diff --git a/mi/miglblt.c b/mi/miglblt.c new file mode 100644 index 000000000..4a7a8eaeb --- /dev/null +++ b/mi/miglblt.c @@ -0,0 +1,248 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: miglblt.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "misc.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmap.h" +#include "servermd.h" + +/* + machine-independent glyph blt. + assumes that glyph bits in snf are written in bytes, +have same bit order as the server's bitmap format, +and are byte padded. this corresponds to the snf distributed +with the sample server. + + get a scratch GC. + in the scratch GC set alu = GXcopy, fg = 1, bg = 0 + allocate a bitmap big enough to hold the largest glyph in the font + validate the scratch gc with the bitmap + for each glyph + carefully put the bits of the glyph in a buffer, + padded to the server pixmap scanline padding rules + fake a call to PutImage from the buffer into the bitmap + use the bitmap in a call to PushPixels +*/ + +void +miPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GC *pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + unsigned char *pglyphBase; /* start of array of glyphs */ +{ + int width, height; + PixmapPtr pPixmap; + int nbyLine; /* bytes per line of padded pixmap */ + FontPtr pfont; + GCPtr pGCtmp; + register int i; + register int j; + unsigned char *pbits; /* buffer for PutImage */ + register unsigned char *pb; /* temp pointer into buffer */ + register CharInfoPtr pci; /* currect char info */ + register unsigned char *pglyph; /* pointer bits in glyph */ + int gWidth, gHeight; /* width and height of glyph */ + register int nbyGlyphWidth; /* bytes per scanline of glyph */ + int nbyPadGlyph; /* server padded line of glyph */ + + XID gcvals[3]; + + if (pGC->miTranslate) + { + x += pDrawable->x; + y += pDrawable->y; + } + + pfont = pGC->font; + width = FONTMAXBOUNDS(pfont,rightSideBearing) - + FONTMINBOUNDS(pfont,leftSideBearing); + height = FONTMAXBOUNDS(pfont,ascent) + + FONTMAXBOUNDS(pfont,descent); + + pPixmap = (*pDrawable->pScreen->CreatePixmap)(pDrawable->pScreen, + width, height, 1); + if (!pPixmap) + return; + + pGCtmp = GetScratchGC(1, pDrawable->pScreen); + if (!pGCtmp) + { + (*pDrawable->pScreen->DestroyPixmap)(pPixmap); + return; + } + + gcvals[0] = GXcopy; + gcvals[1] = 1; + gcvals[2] = 0; + + DoChangeGC(pGCtmp, GCFunction|GCForeground|GCBackground, gcvals, 0); + + nbyLine = BitmapBytePad(width); + pbits = (unsigned char *)ALLOCATE_LOCAL(height*nbyLine); + if (!pbits) + { + (*pDrawable->pScreen->DestroyPixmap)(pPixmap); + FreeScratchGC(pGCtmp); + return; + } + while(nglyph--) + { + pci = *ppci++; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + gWidth = GLYPHWIDTHPIXELS(pci); + gHeight = GLYPHHEIGHTPIXELS(pci); + if (gWidth && gHeight) + { + nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci); + nbyPadGlyph = BitmapBytePad(gWidth); + + if (nbyGlyphWidth == nbyPadGlyph +#if GLYPHPADBYTES != 4 + && (((int) pglyph) & 3) == 0 +#endif + ) + { + pb = pglyph; + } + else + { + for (i=0, pb = pbits; iserialNumber) != (pPixmap->drawable.serialNumber)) + ValidateGC((DrawablePtr)pPixmap, pGCtmp); + (*pGCtmp->ops->PutImage)((DrawablePtr)pPixmap, pGCtmp, + pPixmap->drawable.depth, + 0, 0, gWidth, gHeight, + 0, XYBitmap, (char *)pb); + + if ((pGC->serialNumber) != (pDrawable->serialNumber)) + ValidateGC(pDrawable, pGC); + (*pGC->ops->PushPixels)(pGC, pPixmap, pDrawable, + gWidth, gHeight, + x + pci->metrics.leftSideBearing, + y - pci->metrics.ascent); + } + x += pci->metrics.characterWidth; + } + (*pDrawable->pScreen->DestroyPixmap)(pPixmap); + DEALLOCATE_LOCAL(pbits); + FreeScratchGC(pGCtmp); +} + + +void +miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GC *pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + unsigned char *pglyphBase; /* start of array of glyphs */ +{ + ExtentInfoRec info; /* used by QueryGlyphExtents() */ + XID gcvals[3]; + int oldAlu, oldFS; + unsigned long oldFG; + xRectangle backrect; + + QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info); + + if (info.overallWidth >= 0) + { + backrect.x = x; + backrect.width = info.overallWidth; + } + else + { + backrect.x = x + info.overallWidth; + backrect.width = -info.overallWidth; + } + backrect.y = y - FONTASCENT(pGC->font); + backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + + oldAlu = pGC->alu; + oldFG = pGC->fgPixel; + oldFS = pGC->fillStyle; + + /* fill in the background */ + gcvals[0] = GXcopy; + gcvals[1] = pGC->bgPixel; + gcvals[2] = FillSolid; + DoChangeGC(pGC, GCFunction|GCForeground|GCFillStyle, gcvals, 0); + ValidateGC(pDrawable, pGC); + (*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &backrect); + + /* put down the glyphs */ + gcvals[0] = oldFG; + DoChangeGC(pGC, GCForeground, gcvals, 0); + ValidateGC(pDrawable, pGC); + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci, + (char *)pglyphBase); + + /* put all the toys away when done playing */ + gcvals[0] = oldAlu; + gcvals[1] = oldFG; + gcvals[2] = oldFS; + DoChangeGC(pGC, GCFunction|GCForeground|GCFillStyle, gcvals, 0); + +} diff --git a/mi/miinitext.c b/mi/miinitext.c new file mode 100644 index 000000000..c9ea7444c --- /dev/null +++ b/mi/miinitext.c @@ -0,0 +1,246 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: miinitext.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +#include "misc.h" + +#ifdef NOPEXEXT /* sleaze for Solaris cpp building XsunMono */ +#undef PEXEXT +#endif +#ifdef PANORAMIX +extern Bool noPanoramiXExtension; +#endif +extern Bool noTestExtensions; +#ifdef XKB +extern Bool noXkbExtension; +#endif + +#ifdef BEZIER +extern void BezierExtensionInit(); +#endif +#ifdef XTESTEXT1 +extern void XTestExtension1Init(); +#endif +#ifdef SHAPE +extern void ShapeExtensionInit(); +#endif +#ifdef EVI +extern void EVIExtensionInit(); +#endif +#ifdef MITSHM +extern void ShmExtensionInit(); +#endif +#ifdef PEXEXT +extern void PexExtensionInit(); +#endif +#ifdef MULTIBUFFER +extern void MultibufferExtensionInit(); +#endif +#ifdef PANORAMIX +extern void PanoramiXExtensionInit(); +#endif +#ifdef XINPUT +extern void XInputExtensionInit(); +#endif +#ifdef XTEST +extern void XTestExtensionInit(); +#endif +#ifdef BIGREQS +extern void BigReqExtensionInit(); +#endif +#ifdef MITMISC +extern void MITMiscExtensionInit(); +#endif +#ifdef XIDLE +extern void XIdleExtensionInit(); +#endif +#ifdef XTRAP +extern void DEC_XTRAPInit(); +#endif +#ifdef SCREENSAVER +extern void ScreenSaverExtensionInit (); +#endif +#ifdef XV +extern void XvExtensionInit(); +#endif +#ifdef XIE +extern void XieInit(); +#endif +#ifdef XSYNC +extern void SyncExtensionInit(); +#endif +#ifdef XKB +extern void XkbExtensionInit(); +#endif +#ifdef XCMISC +extern void XCMiscExtensionInit(); +#endif +#ifdef XRECORD +extern void XRecordExtensionInit(); +#endif +#ifdef LBX +extern void LbxExtensionInit(); +#endif +#ifdef DBE +extern void DbeExtensionInit(); +#endif +#ifdef XAPPGROUP +extern void XagExtensionInit(); +#endif +#ifdef XF86VIDMODE +extern void XFree86VidModeExtensionInit(); +#endif +#ifdef XCSECURITY +extern void SecurityExtensionInit(); +#endif +#ifdef XPRINT +extern void XpExtensionInit(); +#endif +#ifdef TOGCUP +extern void XcupExtensionInit(); +#endif +#ifdef DPMSExtension +extern void DPMSExtensionInit(); +#endif + + +/*ARGSUSED*/ +void +InitExtensions(argc, argv) + int argc; + char *argv[]; +{ +#ifdef PANORAMIX +#if !defined(PRINT_ONLY_SERVER) && !defined(NO_PANORAMIX) + if (!noPanoramiXExtension) PanoramiXExtensionInit(); +#endif +#endif +#ifdef BEZIER + BezierExtensionInit(); +#endif +#ifdef XTESTEXT1 + if (!noTestExtensions) XTestExtension1Init(); +#endif +#ifdef SHAPE + ShapeExtensionInit(); +#endif +#ifdef MITSHM + ShmExtensionInit(); +#endif +#ifdef EVI + EVIExtensionInit(); +#endif +#ifdef PEXEXT + PexExtensionInit(); +#endif +#ifdef MULTIBUFFER + MultibufferExtensionInit(); +#endif +#ifdef XINPUT + XInputExtensionInit(); +#endif +#ifdef XTEST + if (!noTestExtensions) XTestExtensionInit(); +#endif +#ifdef BIGREQS + BigReqExtensionInit(); +#endif +#ifdef MITMISC + MITMiscExtensionInit(); +#endif +#ifdef XIDLE + XIdleExtensionInit(); +#endif +#ifdef XTRAP + if (!noTestExtensions) DEC_XTRAPInit(); +#endif +#if defined(SCREENSAVER) && !defined(PRINT_ONLY_SERVER) + ScreenSaverExtensionInit (); +#endif +#ifdef XV + XvExtensionInit(); +#endif +#ifdef XIE + XieInit(); +#endif +#ifdef XSYNC + SyncExtensionInit(); +#endif +#if defined(XKB) && !defined(PRINT_ONLY_SERVER) + if (!noXkbExtension) XkbExtensionInit(); +#endif +#ifdef XCMISC + XCMiscExtensionInit(); +#endif +#ifdef XRECORD + if (!noTestExtensions) RecordExtensionInit(); +#endif +#ifdef LBX + LbxExtensionInit(); +#endif +#ifdef DBE + DbeExtensionInit(); +#endif +#ifdef XAPPGROUP + XagExtensionInit(); +#endif +#if defined(XF86VIDMODE) && !defined(PRINT_ONLY_SERVER) + XFree86VidModeExtensionInit(); +#endif +#ifdef XCSECURITY + SecurityExtensionInit(); +#endif +#ifdef XPRINT + XpExtensionInit(); +#endif +#ifdef TOGCUP + XcupExtensionInit(); +#endif +#if defined(DPMSExtension) && !defined(PRINT_ONLY_SERVER) + DPMSExtensionInit(); +#endif +} diff --git a/mi/miline.h b/mi/miline.h new file mode 100644 index 000000000..329dea51e --- /dev/null +++ b/mi/miline.h @@ -0,0 +1,167 @@ +/* $Xorg: miline.h,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifndef MILINE_H + +/* + * Public definitions used for configuring basic pixelization aspects + * of the sample implementation line-drawing routines provided in + * {mfb,mi,cfb*} at run-time. + */ + +#define XDECREASING 4 +#define YDECREASING 2 +#define YMAJOR 1 + +#define OCTANT1 (1 << (YDECREASING)) +#define OCTANT2 (1 << (YDECREASING|YMAJOR)) +#define OCTANT3 (1 << (XDECREASING|YDECREASING|YMAJOR)) +#define OCTANT4 (1 << (XDECREASING|YDECREASING)) +#define OCTANT5 (1 << (XDECREASING)) +#define OCTANT6 (1 << (XDECREASING|YMAJOR)) +#define OCTANT7 (1 << (YMAJOR)) +#define OCTANT8 (1 << (0)) + +#define XMAJOROCTANTS (OCTANT1 | OCTANT4 | OCTANT5 | OCTANT8) + +#define DEFAULTZEROLINEBIAS (OCTANT2 | OCTANT3 | OCTANT4 | OCTANT5) + +/* + * Devices can configure the rendering of routines in mi, mfb, and cfb* + * by specifying a thin line bias to be applied to a particular screen + * using the following function. The bias parameter is an OR'ing of + * the appropriate OCTANT constants defined above to indicate which + * octants to bias a line to prefer an axial step when the Bresenham + * error term is exactly zero. The octants are mapped as follows: + * + * \ | / + * \ 3 | 2 / + * \ | / + * 4 \ | / 1 + * \|/ + * ----------- + * /|\ + * 5 / | \ 8 + * / | \ + * / 6 | 7 \ + * / | \ + * + * For more information, see "Ambiguities in Incremental Line Rastering," + * Jack E. Bresenham, IEEE CG&A, May 1987. + */ + +extern void miSetZeroLineBias( +#if NeedFunctionPrototypes + ScreenPtr /* pScreen */, + unsigned int /* bias */ +#endif +); + +/* + * Private definitions needed for drawing thin (zero width) lines + * Used by the mi, mfb, and all cfb* components. + */ + +#define X_AXIS 0 +#define Y_AXIS 1 + +#define OUT_LEFT 0x08 +#define OUT_RIGHT 0x04 +#define OUT_ABOVE 0x02 +#define OUT_BELOW 0x01 + +#define OUTCODES(_result, _x, _y, _pbox) \ + if ( (_x) < (_pbox)->x1) (_result) |= OUT_LEFT; \ + else if ( (_x) >= (_pbox)->x2) (_result) |= OUT_RIGHT; \ + if ( (_y) < (_pbox)->y1) (_result) |= OUT_ABOVE; \ + else if ( (_y) >= (_pbox)->y2) (_result) |= OUT_BELOW; + +#define SWAPINT(i, j) \ +{ register int _t = i; i = j; j = _t; } + +#define SWAPPT(i, j) \ +{ DDXPointRec _t; _t = i; i = j; j = _t; } + +#define SWAPINT_PAIR(x1, y1, x2, y2)\ +{ int t = x1; x1 = x2; x2 = t;\ + t = y1; y1 = y2; y2 = t;\ +} + +#define miGetZeroLineBias(_pScreen) \ + ((miZeroLineScreenIndex < 0) ? \ + 0 : ((_pScreen)->devPrivates[miZeroLineScreenIndex].uval)) + +#define CalcLineDeltas(_x1,_y1,_x2,_y2,_adx,_ady,_sx,_sy,_SX,_SY,_octant) \ + (_octant) = 0; \ + (_sx) = (_SX); \ + if (((_adx) = (_x2) - (_x1)) < 0) { \ + (_adx) = -(_adx); \ + (_sx = -(_sx)); \ + (_octant) |= XDECREASING; \ + } \ + (_sy) = (_SY); \ + if (((_ady) = (_y2) - (_y1)) < 0) { \ + (_ady) = -(_ady); \ + (_sy = -(_sy)); \ + (_octant) |= YDECREASING; \ + } + +#define SetYMajorOctant(_octant) ((_octant) |= YMAJOR) + +#define FIXUP_ERROR(_e, _octant, _bias) \ + (_e) -= (((_bias) >> (_octant)) & 1) + +#define IsXMajorOctant(_octant) (!((_octant) & YMAJOR)) +#define IsYMajorOctant(_octant) ((_octant) & YMAJOR) +#define IsXDecreasingOctant(_octant) ((_octant) & XDECREASING) +#define IsYDecreasingOctant(_octant) ((_octant) & YDECREASING) + +extern int miZeroLineScreenIndex; + +extern int miZeroClipLine( +#if NeedFunctionPrototypes + int /*xmin*/, + int /*ymin*/, + int /*xmax*/, + int /*ymax*/, + int * /*new_x1*/, + int * /*new_y1*/, + int * /*new_x2*/, + int * /*new_y2*/, + unsigned int /*adx*/, + unsigned int /*ady*/, + int * /*pt1_clipped*/, + int * /*pt2_clipped*/, + int /*octant*/, + unsigned int /*bias*/, + int /*oc1*/, + int /*oc2*/ +#endif +); + +#endif /* MILINE_H */ diff --git a/mi/mipointer.c b/mi/mipointer.c new file mode 100644 index 000000000..8617861cd --- /dev/null +++ b/mi/mipointer.c @@ -0,0 +1,498 @@ +/* + * mipointer.c + */ + +/* $Xorg: mipointer.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +# define NEED_EVENTS +# include "X.h" +# include "Xmd.h" +# include "Xproto.h" +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "mi.h" +# include "scrnintstr.h" +# include "mipointrst.h" +# include "cursorstr.h" +# include "dixstruct.h" + +static int miPointerScreenIndex; +static unsigned long miPointerGeneration = 0; + +#define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr)) +#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) + +/* + * until more than one pointer device exists. + */ + +static miPointerRec miPointer; + +static Bool miPointerRealizeCursor (), miPointerUnrealizeCursor (); +static Bool miPointerDisplayCursor (); +static void miPointerConstrainCursor (), miPointerPointerNonInterestBox(); +static void miPointerCursorLimits (); +static Bool miPointerSetCursorPosition (); + +static Bool miPointerCloseScreen(); + +static void miPointerMove (); + +Bool +miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate) + ScreenPtr pScreen; + miPointerSpriteFuncPtr spriteFuncs; + miPointerScreenFuncPtr screenFuncs; + Bool waitForUpdate; +{ + miPointerScreenPtr pScreenPriv; + + if (miPointerGeneration != serverGeneration) + { + miPointerScreenIndex = AllocateScreenPrivateIndex(); + if (miPointerScreenIndex < 0) + return FALSE; + miPointerGeneration = serverGeneration; + } + pScreenPriv = (miPointerScreenPtr) xalloc (sizeof (miPointerScreenRec)); + if (!pScreenPriv) + return FALSE; + pScreenPriv->spriteFuncs = spriteFuncs; + pScreenPriv->screenFuncs = screenFuncs; + /* + * check for uninitialized methods + */ + if (!screenFuncs->EnqueueEvent) + screenFuncs->EnqueueEvent = mieqEnqueue; + if (!screenFuncs->NewEventScreen) + screenFuncs->NewEventScreen = mieqSwitchScreen; + pScreenPriv->waitForUpdate = waitForUpdate; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miPointerCloseScreen; + pScreen->devPrivates[miPointerScreenIndex].ptr = (pointer) pScreenPriv; + /* + * set up screen cursor method table + */ + pScreen->ConstrainCursor = miPointerConstrainCursor; + pScreen->CursorLimits = miPointerCursorLimits; + pScreen->DisplayCursor = miPointerDisplayCursor; + pScreen->RealizeCursor = miPointerRealizeCursor; + pScreen->UnrealizeCursor = miPointerUnrealizeCursor; + pScreen->SetCursorPosition = miPointerSetCursorPosition; + pScreen->RecolorCursor = miRecolorCursor; + pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox; + /* + * set up the pointer object + */ + miPointer.pScreen = NULL; + miPointer.pSpriteScreen = NULL; + miPointer.pCursor = NULL; + miPointer.pSpriteCursor = NULL; + miPointer.limits.x1 = 0; + miPointer.limits.x2 = 32767; + miPointer.limits.y1 = 0; + miPointer.limits.y2 = 32767; + miPointer.confined = FALSE; + miPointer.x = 0; + miPointer.y = 0; + miPointer.history_start = miPointer.history_end = 0; + return TRUE; +} + +static Bool +miPointerCloseScreen (index, pScreen) + int index; + ScreenPtr pScreen; +{ + SetupScreen(pScreen); + + if (pScreen == miPointer.pScreen) + miPointer.pScreen = 0; + if (pScreen == miPointer.pSpriteScreen) + miPointer.pSpriteScreen = 0; + pScreen->CloseScreen = pScreenPriv->CloseScreen; + xfree ((pointer) pScreenPriv); + return (*pScreen->CloseScreen) (index, pScreen); +} + +/* + * DIX/DDX interface routines + */ + +static Bool +miPointerRealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + SetupScreen(pScreen); + + return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor); +} + +static Bool +miPointerUnrealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + SetupScreen(pScreen); + + return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor); +} + +static Bool +miPointerDisplayCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + SetupScreen(pScreen); + + miPointer.pCursor = pCursor; + miPointer.pScreen = pScreen; + miPointerUpdate (); + return TRUE; +} + +static void +miPointerConstrainCursor (pScreen, pBox) + ScreenPtr pScreen; + BoxPtr pBox; +{ + miPointer.limits = *pBox; + miPointer.confined = PointerConfinedToScreen(); +} + +/*ARGSUSED*/ +static void +miPointerPointerNonInterestBox (pScreen, pBox) + ScreenPtr pScreen; + BoxPtr pBox; +{ + /* until DIX uses this, this will remain a stub */ +} + +/*ARGSUSED*/ +static void +miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox) + ScreenPtr pScreen; + CursorPtr pCursor; + BoxPtr pHotBox; + BoxPtr pTopLeftBox; +{ + *pTopLeftBox = *pHotBox; +} + +static Bool GenerateEvent; + +static Bool +miPointerSetCursorPosition(pScreen, x, y, generateEvent) + ScreenPtr pScreen; + int x, y; + Bool generateEvent; +{ + SetupScreen (pScreen); + + GenerateEvent = generateEvent; + /* device dependent - must pend signal and call miPointerWarpCursor */ + (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y); + if (!generateEvent) + miPointerUpdate(); + return TRUE; +} + +/* Once signals are ignored, the WarpCursor function can call this */ + +void +miPointerWarpCursor (pScreen, x, y) + ScreenPtr pScreen; + int x, y; +{ + SetupScreen (pScreen); + + if (miPointer.pScreen != pScreen) + (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE); + + if (GenerateEvent) + { + miPointerMove (pScreen, x, y, GetTimeInMillis()); + } + else + { + /* everything from miPointerMove except the event and history */ + + if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen) + { + miPointer.devx = x; + miPointer.devy = y; + (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y); + } + miPointer.x = x; + miPointer.y = y; + miPointer.pScreen = pScreen; + } +} + +/* + * Pointer/CursorDisplay interface routines + */ + +int +miPointerGetMotionBufferSize () +{ + return MOTION_SIZE; +} + +int +miPointerGetMotionEvents (pPtr, coords, start, stop, pScreen) + DeviceIntPtr pPtr; + xTimecoord *coords; + unsigned long start, stop; + ScreenPtr pScreen; +{ + int i; + int count = 0; + miHistoryPtr h; + + for (i = miPointer.history_start; i != miPointer.history_end;) + { + h = &miPointer.history[i]; + if (h->event.time >= stop) + break; + if (h->event.time >= start) + { + *coords++ = h->event; + count++; + } + if (++i == MOTION_SIZE) i = 0; + } + return count; +} + + +/* + * miPointerUpdate + * + * Syncronize the sprite with the cursor - called from ProcessInputEvents + */ + +void +miPointerUpdate () +{ + ScreenPtr pScreen; + miPointerScreenPtr pScreenPriv; + int x, y, devx, devy; + + pScreen = miPointer.pScreen; + x = miPointer.x; + y = miPointer.y; + devx = miPointer.devx; + devy = miPointer.devy; + if (!pScreen) + return; + pScreenPriv = GetScreenPrivate (pScreen); + /* + * if the cursor has switched screens, disable the sprite + * on the old screen + */ + if (pScreen != miPointer.pSpriteScreen) + { + if (miPointer.pSpriteScreen) + { + miPointerScreenPtr pOldPriv; + + pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen); + if (miPointer.pCursor) + { + (*pOldPriv->spriteFuncs->SetCursor) + (miPointer.pSpriteScreen, NullCursor, 0, 0); + } + (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE); + } + (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); + (*pScreenPriv->spriteFuncs->SetCursor) + (pScreen, miPointer.pCursor, x, y); + miPointer.devx = x; + miPointer.devy = y; + miPointer.pSpriteCursor = miPointer.pCursor; + miPointer.pSpriteScreen = pScreen; + } + /* + * if the cursor has changed, display the new one + */ + else if (miPointer.pCursor != miPointer.pSpriteCursor) + { + (*pScreenPriv->spriteFuncs->SetCursor) + (pScreen, miPointer.pCursor, x, y); + miPointer.devx = x; + miPointer.devy = y; + miPointer.pSpriteCursor = miPointer.pCursor; + } + else if (x != devx || y != devy) + { + miPointer.devx = x; + miPointer.devy = y; + (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y); + } +} + +/* + * miPointerDeltaCursor. The pointer has moved dx,dy from it's previous + * position. + */ + +void +miPointerDeltaCursor (dx, dy, time) + int dx, dy; + unsigned long time; +{ + miPointerAbsoluteCursor (miPointer.x + dx, miPointer.y + dy, time); +} + +/* + * miPointerAbsoluteCursor. The pointer has moved to x,y + */ + +void +miPointerAbsoluteCursor (x, y, time) + int x, y; + unsigned long time; +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + ScreenPtr newScreen; + + pScreen = miPointer.pScreen; + if (!pScreen) + return; /* called before ready */ + if (x < 0 || x >= pScreen->width || y < 0 || y >= pScreen->height) + { + pScreenPriv = GetScreenPrivate (pScreen); + if (!miPointer.confined) + { + newScreen = pScreen; + (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y); + if (newScreen != pScreen) + { + pScreen = newScreen; + (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE); + pScreenPriv = GetScreenPrivate (pScreen); + /* Smash the confine to the new screen */ + miPointer.limits.x2 = pScreen->width; + miPointer.limits.y2 = pScreen->height; + } + } + } + /* + * constrain the hot-spot to the current + * limits + */ + if (x < miPointer.limits.x1) + x = miPointer.limits.x1; + if (x >= miPointer.limits.x2) + x = miPointer.limits.x2 - 1; + if (y < miPointer.limits.y1) + y = miPointer.limits.y1; + if (y >= miPointer.limits.y2) + y = miPointer.limits.y2 - 1; + if (miPointer.x == x && miPointer.y == y && miPointer.pScreen == pScreen) + return; + miPointerMove (pScreen, x, y, time); +} + +void +miPointerPosition (x, y) + int *x, *y; +{ + *x = miPointer.x; + *y = miPointer.y; +} + +/* + * miPointerMove. The pointer has moved to x,y on current screen + */ + +static void +miPointerMove (pScreen, x, y, time) + ScreenPtr pScreen; + int x, y; + unsigned long time; +{ + SetupScreen(pScreen); + xEvent xE; + miHistoryPtr history; + int prev, end, start; + + if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen) + { + miPointer.devx = x; + miPointer.devy = y; + (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y); + } + miPointer.x = x; + miPointer.y = y; + miPointer.pScreen = pScreen; + + xE.u.u.type = MotionNotify; + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + xE.u.keyButtonPointer.time = time; + (*pScreenPriv->screenFuncs->EnqueueEvent) (&xE); + + end = miPointer.history_end; + start = miPointer.history_start; + prev = end - 1; + if (end == 0) + prev = MOTION_SIZE - 1; + history = &miPointer.history[prev]; + if (end == start || history->event.time != time) + { + history = &miPointer.history[end]; + if (++end == MOTION_SIZE) + end = 0; + if (end == start) + { + start = end + 1; + if (start == MOTION_SIZE) + start = 0; + miPointer.history_start = start; + } + miPointer.history_end = end; + } + history->event.x = x; + history->event.y = y; + history->event.time = time; + history->pScreen = pScreen; +} + +void +miRegisterPointerDevice (pScreen, pDevice) + ScreenPtr pScreen; + DevicePtr pDevice; +{ + miPointer.pPointer = pDevice; +} diff --git a/mi/mipointer.h b/mi/mipointer.h new file mode 100644 index 000000000..a2f74b07b --- /dev/null +++ b/mi/mipointer.h @@ -0,0 +1,122 @@ +/* + * mipointer.h + * + */ + +/* $Xorg: mipointer.h,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +typedef struct _miPointerSpriteFuncRec { + Bool (*RealizeCursor)(); /* pScreen, pCursor */ + Bool (*UnrealizeCursor)(); /* pScreen, pCursor */ + void (*SetCursor)(); /* pScreen, pCursor, x, y */ + void (*MoveCursor)(); /* pScreen, x, y */ +} miPointerSpriteFuncRec, *miPointerSpriteFuncPtr; + +typedef struct _miPointerScreenFuncRec { + Bool (*CursorOffScreen)(); /* ppScreen, px, py */ + void (*CrossScreen)(); /* pScreen, entering */ + void (*WarpCursor)(); /* pScreen, x, y */ + void (*EnqueueEvent)(); /* xEvent */ + void (*NewEventScreen)(); /* pScreen */ +} miPointerScreenFuncRec, *miPointerScreenFuncPtr; + +extern Bool miDCInitialize( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + miPointerScreenFuncPtr /*screenFuncs*/ +#endif +); + +extern Bool miPointerInitialize( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + miPointerSpriteFuncPtr /*spriteFuncs*/, + miPointerScreenFuncPtr /*screenFuncs*/, + Bool /*waitForUpdate*/ +#endif +); + +extern void miPointerWarpCursor( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + int /*x*/, + int /*y*/ +#endif +); + +extern int miPointerGetMotionBufferSize( +#if NeedFunctionPrototypes + void +#endif +); + +extern int miPointerGetMotionEvents( +#if NeedFunctionPrototypes + DeviceIntPtr /*pPtr*/, + xTimecoord * /*coords*/, + unsigned long /*start*/, + unsigned long /*stop*/, + ScreenPtr /*pScreen*/ +#endif +); + +extern void miPointerUpdate( +#if NeedFunctionPrototypes + void +#endif +); + +extern void miPointerDeltaCursor( +#if NeedFunctionPrototypes + int /*dx*/, + int /*dy*/, + unsigned long /*time*/ +#endif +); + +extern void miPointerAbsoluteCursor( +#if NeedFunctionPrototypes + int /*x*/, + int /*y*/, + unsigned long /*time*/ +#endif +); + +extern void miPointerPosition( +#if NeedFunctionPrototypes + int * /*x*/, + int * /*y*/ +#endif +); + +extern void miRegisterPointerDevice( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + DevicePtr /*pDevice*/ +#endif +); diff --git a/mi/mipointrst.h b/mi/mipointrst.h new file mode 100644 index 000000000..236079166 --- /dev/null +++ b/mi/mipointrst.h @@ -0,0 +1,62 @@ +/* + * mipointrst.h + * + */ + +/* $Xorg: mipointrst.h,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +# include +# include + +#define MOTION_SIZE 256 + +typedef struct { + xTimecoord event; + ScreenPtr pScreen; +} miHistoryRec, *miHistoryPtr; + +typedef struct { + ScreenPtr pScreen; /* current screen */ + ScreenPtr pSpriteScreen;/* screen containing current sprite */ + CursorPtr pCursor; /* current cursor */ + CursorPtr pSpriteCursor;/* cursor on screen */ + BoxRec limits; /* current constraints */ + Bool confined; /* pointer can't change screens */ + int x, y; /* hot spot location */ + int devx, devy; /* sprite position */ + DevicePtr pPointer; /* pointer device structure */ + miHistoryRec history[MOTION_SIZE]; + int history_start, history_end; +} miPointerRec, *miPointerPtr; + +typedef struct { + miPointerSpriteFuncPtr spriteFuncs; /* sprite-specific methods */ + miPointerScreenFuncPtr screenFuncs; /* screen-specific methods */ + CloseScreenProcPtr CloseScreen; + Bool waitForUpdate; /* don't move cursor in SIGIO */ +} miPointerScreenRec, *miPointerScreenPtr; diff --git a/mi/mipoly.c b/mi/mipoly.c new file mode 100644 index 000000000..b25ee780f --- /dev/null +++ b/mi/mipoly.c @@ -0,0 +1,124 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipoly.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +/* + * mipoly.c + * + * Written by Brian Kelleher; June 1986 + * + * Draw polygons. This routine translates the point by the + * origin if pGC->miTranslate is non-zero, and calls + * to the appropriate routine to actually scan convert the + * polygon. + */ +#include "X.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "mi.h" +#include "miscstruct.h" + + +void +miFillPolygon(dst, pgc, shape, mode, count, pPts) + DrawablePtr dst; + register GCPtr pgc; + int shape, mode; + register int count; + DDXPointPtr pPts; +{ + int i; + register int xorg, yorg; + register DDXPointPtr ppt; + + if (count == 0) + return; + + ppt = pPts; + if (pgc->miTranslate) + { + xorg = dst->x; + yorg = dst->y; + + if (mode == CoordModeOrigin) + { + for (i = 0; ix += xorg; + ppt++->y += yorg; + } + } + else + { + ppt->x += xorg; + ppt++->y += yorg; + for (i = 1; ix += (ppt-1)->x; + ppt->y += (ppt-1)->y; + ppt++; + } + } + } + else + { + if (mode == CoordModePrevious) + { + ppt++; + for (i = 1; ix += (ppt-1)->x; + ppt->y += (ppt-1)->y; + ppt++; + } + } + } + if (shape == Convex) + miFillConvexPoly(dst, pgc, count, pPts); + else + miFillGeneralPoly(dst, pgc, count, pPts); +} diff --git a/mi/mipoly.h b/mi/mipoly.h new file mode 100644 index 000000000..d946388a6 --- /dev/null +++ b/mi/mipoly.h @@ -0,0 +1,228 @@ +/* $Xorg: mipoly.h,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +/* + * fill.h + * + * Created by Brian Kelleher; Oct 1985 + * + * Include file for filled polygon routines. + * + * These are the data structures needed to scan + * convert regions. Two different scan conversion + * methods are available -- the even-odd method, and + * the winding number method. + * The even-odd rule states that a point is inside + * the polygon if a ray drawn from that point in any + * direction will pass through an odd number of + * path segments. + * By the winding number rule, a point is decided + * to be inside the polygon if a ray drawn from that + * point in any direction passes through a different + * number of clockwise and counter-clockwise path + * segments. + * + * These data structures are adapted somewhat from + * the algorithm in (Foley/Van Dam) for scan converting + * polygons. + * The basic algorithm is to start at the top (smallest y) + * of the polygon, stepping down to the bottom of + * the polygon by incrementing the y coordinate. We + * keep a list of edges which the current scanline crosses, + * sorted by x. This list is called the Active Edge Table (AET) + * As we change the y-coordinate, we update each entry in + * in the active edge table to reflect the edges new xcoord. + * This list must be sorted at each scanline in case + * two edges intersect. + * We also keep a data structure known as the Edge Table (ET), + * which keeps track of all the edges which the current + * scanline has not yet reached. The ET is basically a + * list of ScanLineList structures containing a list of + * edges which are entered at a given scanline. There is one + * ScanLineList per scanline at which an edge is entered. + * When we enter a new edge, we move it from the ET to the AET. + * + * From the AET, we can implement the even-odd rule as in + * (Foley/Van Dam). + * The winding number rule is a little trickier. We also + * keep the EdgeTableEntries in the AET linked by the + * nextWETE (winding EdgeTableEntry) link. This allows + * the edges to be linked just as before for updating + * purposes, but only uses the edges linked by the nextWETE + * link as edges representing spans of the polygon to + * drawn (as with the even-odd rule). + */ + +/* + * for the winding number rule + */ +#define CLOCKWISE 1 +#define COUNTERCLOCKWISE -1 + +typedef struct _EdgeTableEntry { + int ymax; /* ycoord at which we exit this edge. */ + BRESINFO bres; /* Bresenham info to run the edge */ + struct _EdgeTableEntry *next; /* next in the list */ + struct _EdgeTableEntry *back; /* for insertion sort */ + struct _EdgeTableEntry *nextWETE; /* for winding num rule */ + int ClockWise; /* flag for winding number rule */ +} EdgeTableEntry; + + +typedef struct _ScanLineList{ + int scanline; /* the scanline represented */ + EdgeTableEntry *edgelist; /* header node */ + struct _ScanLineList *next; /* next in the list */ +} ScanLineList; + + +typedef struct { + int ymax; /* ymax for the polygon */ + int ymin; /* ymin for the polygon */ + ScanLineList scanlines; /* header node */ +} EdgeTable; + + +/* + * Here is a struct to help with storage allocation + * so we can allocate a big chunk at a time, and then take + * pieces from this heap when we need to. + */ +#define SLLSPERBLOCK 25 + +typedef struct _ScanLineListBlock { + ScanLineList SLLs[SLLSPERBLOCK]; + struct _ScanLineListBlock *next; +} ScanLineListBlock; + +/* + * number of points to buffer before sending them off + * to scanlines() : Must be an even number + */ +#define NUMPTSTOBUFFER 200 + + +/* + * + * a few macros for the inner loops of the fill code where + * performance considerations don't allow a procedure call. + * + * Evaluate the given edge at the given scanline. + * If the edge has expired, then we leave it and fix up + * the active edge table; otherwise, we increment the + * x value to be ready for the next scanline. + * The winding number rule is in effect, so we must notify + * the caller when the edge has been removed so he + * can reorder the Winding Active Edge Table. + */ +#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \ + if (pAET->ymax == y) { /* leaving this edge */ \ + pPrevAET->next = pAET->next; \ + pAET = pPrevAET->next; \ + fixWAET = 1; \ + if (pAET) \ + pAET->back = pPrevAET; \ + } \ + else { \ + BRESINCRPGONSTRUCT(pAET->bres); \ + pPrevAET = pAET; \ + pAET = pAET->next; \ + } \ +} + + +/* + * Evaluate the given edge at the given scanline. + * If the edge has expired, then we leave it and fix up + * the active edge table; otherwise, we increment the + * x value to be ready for the next scanline. + * The even-odd rule is in effect. + */ +#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \ + if (pAET->ymax == y) { /* leaving this edge */ \ + pPrevAET->next = pAET->next; \ + pAET = pPrevAET->next; \ + if (pAET) \ + pAET->back = pPrevAET; \ + } \ + else { \ + BRESINCRPGONSTRUCT(pAET->bres); \ + pPrevAET = pAET; \ + pAET = pAET->next; \ + } \ +} + +/* mipolyutil.c */ + +extern Bool miInsertEdgeInET( +#if NeedFunctionPrototypes + EdgeTable * /*ET*/, + EdgeTableEntry * /*ETE*/, + int /*scanline*/, + ScanLineListBlock ** /*SLLBlock*/, + int * /*iSLLBlock*/ +#endif +); + +extern Bool miCreateETandAET( +#if NeedFunctionPrototypes + int /*count*/, + DDXPointPtr /*pts*/, + EdgeTable * /*ET*/, + EdgeTableEntry * /*AET*/, + EdgeTableEntry * /*pETEs*/, + ScanLineListBlock * /*pSLLBlock*/ +#endif +); + +extern void miloadAET( +#if NeedFunctionPrototypes + EdgeTableEntry * /*AET*/, + EdgeTableEntry * /*ETEs*/ +#endif +); + +extern void micomputeWAET( +#if NeedFunctionPrototypes + EdgeTableEntry * /*AET*/ +#endif +); + +extern int miInsertionSort( +#if NeedFunctionPrototypes + EdgeTableEntry * /*AET*/ +#endif +); + +extern void miFreeStorage( +#if NeedFunctionPrototypes + ScanLineListBlock * /*pSLLBlock*/ +#endif +); diff --git a/mi/mipolycon.c b/mi/mipolycon.c new file mode 100644 index 000000000..9daf44543 --- /dev/null +++ b/mi/mipolycon.c @@ -0,0 +1,245 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipolycon.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include "gcstruct.h" +#include "pixmap.h" +#include "miscanfill.h" + +static int getPolyYBounds(); + +/* + * convexpoly.c + * + * Written by Brian Kelleher; Dec. 1985. + * + * Fill a convex polygon. If the given polygon + * is not convex, then the result is undefined. + * The algorithm is to order the edges from smallest + * y to largest by partitioning the array into a left + * edge list and a right edge list. The algorithm used + * to traverse each edge is an extension of Bresenham's + * line algorithm with y as the major axis. + * For a derivation of the algorithm, see the author of + * this code. + */ +Bool +miFillConvexPoly(dst, pgc, count, ptsIn) + DrawablePtr dst; + GCPtr pgc; + int count; /* number of points */ + DDXPointPtr ptsIn; /* the points */ +{ + register int xl, xr; /* x vals of left and right edges */ + register int dl, dr; /* decision variables */ + register int ml, m1l; /* left edge slope and slope+1 */ + int mr, m1r; /* right edge slope and slope+1 */ + int incr1l, incr2l; /* left edge error increments */ + int incr1r, incr2r; /* right edge error increments */ + int dy; /* delta y */ + int y; /* current scanline */ + int left, right; /* indices to first endpoints */ + int i; /* loop counter */ + int nextleft, nextright; /* indices to second endpoints */ + DDXPointPtr ptsOut, FirstPoint; /* output buffer */ + int *width, *FirstWidth; /* output buffer */ + int imin; /* index of smallest vertex (in y) */ + int ymin; /* y-extents of polygon */ + int ymax; + + /* + * find leftx, bottomy, rightx, topy, and the index + * of bottomy. Also translate the points. + */ + imin = getPolyYBounds(ptsIn, count, &ymin, &ymax); + + dy = ymax - ymin + 1; + if ((count < 3) || (dy < 0)) + return(TRUE); + ptsOut = FirstPoint = (DDXPointPtr )ALLOCATE_LOCAL(sizeof(DDXPointRec)*dy); + width = FirstWidth = (int *)ALLOCATE_LOCAL(sizeof(int) * dy); + if(!FirstPoint || !FirstWidth) + { + if (FirstWidth) DEALLOCATE_LOCAL(FirstWidth); + if (FirstPoint) DEALLOCATE_LOCAL(FirstPoint); + return(FALSE); + } + + nextleft = nextright = imin; + y = ptsIn[nextleft].y; + + /* + * loop through all edges of the polygon + */ + do { + /* + * add a left edge if we need to + */ + if (ptsIn[nextleft].y == y) { + left = nextleft; + + /* + * find the next edge, considering the end + * conditions of the array. + */ + nextleft++; + if (nextleft >= count) + nextleft = 0; + + /* + * now compute all of the random information + * needed to run the iterative algorithm. + */ + BRESINITPGON(ptsIn[nextleft].y-ptsIn[left].y, + ptsIn[left].x,ptsIn[nextleft].x, + xl, dl, ml, m1l, incr1l, incr2l); + } + + /* + * add a right edge if we need to + */ + if (ptsIn[nextright].y == y) { + right = nextright; + + /* + * find the next edge, considering the end + * conditions of the array. + */ + nextright--; + if (nextright < 0) + nextright = count-1; + + /* + * now compute all of the random information + * needed to run the iterative algorithm. + */ + BRESINITPGON(ptsIn[nextright].y-ptsIn[right].y, + ptsIn[right].x,ptsIn[nextright].x, + xr, dr, mr, m1r, incr1r, incr2r); + } + + /* + * generate scans to fill while we still have + * a right edge as well as a left edge. + */ + i = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y; + /* in case we're called with non-convex polygon */ + if(i < 0) + { + DEALLOCATE_LOCAL(FirstWidth); + DEALLOCATE_LOCAL(FirstPoint); + return(TRUE); + } + while (i-- > 0) + { + ptsOut->y = y; + + /* + * reverse the edges if necessary + */ + if (xl < xr) + { + *(width++) = xr - xl; + (ptsOut++)->x = xl; + } + else + { + *(width++) = xl - xr; + (ptsOut++)->x = xr; + } + y++; + + /* increment down the edges */ + BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l); + BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r); + } + } while (y != ymax); + + /* + * Finally, fill the spans + */ + (*pgc->ops->FillSpans)(dst, pgc, + ptsOut-FirstPoint,FirstPoint,FirstWidth, + 1); + DEALLOCATE_LOCAL(FirstWidth); + DEALLOCATE_LOCAL(FirstPoint); + return(TRUE); +} + + +/* + * Find the index of the point with the smallest y. + */ +static +int +getPolyYBounds(pts, n, by, ty) + DDXPointPtr pts; + int n; + int *by, *ty; +{ + register DDXPointPtr ptMin; + int ymin, ymax; + DDXPointPtr ptsStart = pts; + + ptMin = pts; + ymin = ymax = (pts++)->y; + + while (--n > 0) { + if (pts->y < ymin) + { + ptMin = pts; + ymin = pts->y; + } + if(pts->y > ymax) + ymax = pts->y; + + pts++; + } + + *by = ymin; + *ty = ymax; + return(ptMin-ptsStart); +} diff --git a/mi/mipolygen.c b/mi/mipolygen.c new file mode 100644 index 000000000..b9c0248c6 --- /dev/null +++ b/mi/mipolygen.c @@ -0,0 +1,226 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipolygen.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include "X.h" +#include "gcstruct.h" +#include "miscanfill.h" +#include "mipoly.h" +#include "pixmap.h" + +/* + * + * Written by Brian Kelleher; Oct. 1985 + * + * Routine to fill a polygon. Two fill rules are + * supported: frWINDING and frEVENODD. + * + * See fillpoly.h for a complete description of the algorithm. + */ + +Bool +miFillGeneralPoly(dst, pgc, count, ptsIn) + DrawablePtr dst; + GCPtr pgc; + int count; /* number of points */ + DDXPointPtr ptsIn; /* the points */ +{ + register EdgeTableEntry *pAET; /* the Active Edge Table */ + register int y; /* the current scanline */ + register int nPts = 0; /* number of pts in buffer */ + register EdgeTableEntry *pWETE; /* Winding Edge Table */ + register ScanLineList *pSLL; /* Current ScanLineList */ + register DDXPointPtr ptsOut; /* ptr to output buffers */ + int *width; + DDXPointRec FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */ + int FirstWidth[NUMPTSTOBUFFER]; + EdgeTableEntry *pPrevAET; /* previous AET entry */ + EdgeTable ET; /* Edge Table header node */ + EdgeTableEntry AET; /* Active ET header node */ + EdgeTableEntry *pETEs; /* Edge Table Entries buff */ + ScanLineListBlock SLLBlock; /* header for ScanLineList */ + int fixWAET = 0; + + if (count < 3) + return(TRUE); + + if(!(pETEs = (EdgeTableEntry *) + ALLOCATE_LOCAL(sizeof(EdgeTableEntry) * count))) + return(FALSE); + ptsOut = FirstPoint; + width = FirstWidth; + if (!miCreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock)) + { + DEALLOCATE_LOCAL(pETEs); + return(FALSE); + } + pSLL = ET.scanlines.next; + + if (pgc->fillRule == EvenOddRule) + { + /* + * for each scanline + */ + for (y = ET.ymin; y < ET.ymax; y++) + { + /* + * Add a new edge to the active edge table when we + * get to the next edge. + */ + if (pSLL && y == pSLL->scanline) + { + miloadAET(&AET, pSLL->edgelist); + pSLL = pSLL->next; + } + pPrevAET = &AET; + pAET = AET.next; + + /* + * for each active edge + */ + while (pAET) + { + ptsOut->x = pAET->bres.minor; + ptsOut++->y = y; + *width++ = pAET->next->bres.minor - pAET->bres.minor; + nPts++; + + /* + * send out the buffer when its full + */ + if (nPts == NUMPTSTOBUFFER) + { + (*pgc->ops->FillSpans)(dst, pgc, + nPts, FirstPoint, FirstWidth, + 1); + ptsOut = FirstPoint; + width = FirstWidth; + nPts = 0; + } + EVALUATEEDGEEVENODD(pAET, pPrevAET, y) + EVALUATEEDGEEVENODD(pAET, pPrevAET, y); + } + miInsertionSort(&AET); + } + } + else /* default to WindingNumber */ + { + /* + * for each scanline + */ + for (y = ET.ymin; y < ET.ymax; y++) + { + /* + * Add a new edge to the active edge table when we + * get to the next edge. + */ + if (pSLL && y == pSLL->scanline) + { + miloadAET(&AET, pSLL->edgelist); + micomputeWAET(&AET); + pSLL = pSLL->next; + } + pPrevAET = &AET; + pAET = AET.next; + pWETE = pAET; + + /* + * for each active edge + */ + while (pAET) + { + /* + * if the next edge in the active edge table is + * also the next edge in the winding active edge + * table. + */ + if (pWETE == pAET) + { + ptsOut->x = pAET->bres.minor; + ptsOut++->y = y; + *width++ = pAET->nextWETE->bres.minor - pAET->bres.minor; + nPts++; + + /* + * send out the buffer + */ + if (nPts == NUMPTSTOBUFFER) + { + (*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint, + FirstWidth, 1); + ptsOut = FirstPoint; + width = FirstWidth; + nPts = 0; + } + + pWETE = pWETE->nextWETE; + while (pWETE != pAET) + EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); + pWETE = pWETE->nextWETE; + } + EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); + } + + /* + * reevaluate the Winding active edge table if we + * just had to resort it or if we just exited an edge. + */ + if (miInsertionSort(&AET) || fixWAET) + { + micomputeWAET(&AET); + fixWAET = 0; + } + } + } + + /* + * Get any spans that we missed by buffering + */ + (*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint, FirstWidth, 1); + DEALLOCATE_LOCAL(pETEs); + miFreeStorage(SLLBlock.next); + return(TRUE); +} diff --git a/mi/mipolypnt.c b/mi/mipolypnt.c new file mode 100644 index 000000000..933e1cc3b --- /dev/null +++ b/mi/mipolypnt.c @@ -0,0 +1,119 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipolypnt.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include "X.h" +#include "Xprotostr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "windowstr.h" + +void +miPolyPoint(pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; + xPoint *pptInit; +{ + + int xorg; + int yorg; + int nptTmp; + XID fsOld, fsNew; + int *pwidthInit, *pwidth; + int i; + register xPoint *ppt; + + /* make pointlist origin relative */ + if (mode == CoordModePrevious) + { + ppt = pptInit; + nptTmp = npt; + nptTmp--; + while(nptTmp--) + { + ppt++; + ppt->x += (ppt-1)->x; + ppt->y += (ppt-1)->y; + } + } + + if(pGC->miTranslate) + { + ppt = pptInit; + nptTmp = npt; + xorg = pDrawable->x; + yorg = pDrawable->y; + while(nptTmp--) + { + ppt->x += xorg; + ppt++->y += yorg; + } + } + + fsOld = pGC->fillStyle; + fsNew = FillSolid; + if(pGC->fillStyle != FillSolid) + { + DoChangeGC(pGC, GCFillStyle, &fsNew, 0); + ValidateGC(pDrawable, pGC); + } + if(!(pwidthInit = (int *)ALLOCATE_LOCAL(npt * sizeof(int)))) + return; + pwidth = pwidthInit; + for(i = 0; i < npt; i++) + *pwidth++ = 1; + (*pGC->ops->FillSpans)(pDrawable, pGC, npt, pptInit, pwidthInit, FALSE); + + if(fsOld != FillSolid) + { + DoChangeGC(pGC, GCFillStyle, &fsOld, 0); + ValidateGC(pDrawable, pGC); + } + DEALLOCATE_LOCAL(pwidthInit); +} + diff --git a/mi/mipolyrect.c b/mi/mipolyrect.c new file mode 100644 index 000000000..935203d9a --- /dev/null +++ b/mi/mipolyrect.c @@ -0,0 +1,187 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipolyrect.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmap.h" + +void +miPolyRectangle(pDraw, pGC, nrects, pRects) + DrawablePtr pDraw; + GCPtr pGC; + int nrects; + xRectangle *pRects; +{ + int i; + xRectangle *pR = pRects; + DDXPointRec rect[5]; + int bound_tmp; + +#define MINBOUND(dst,eqn) bound_tmp = eqn; \ + if (bound_tmp < -32768) \ + bound_tmp = -32768; \ + dst = bound_tmp; + +#define MAXBOUND(dst,eqn) bound_tmp = eqn; \ + if (bound_tmp > 32767) \ + bound_tmp = 32767; \ + dst = bound_tmp; + +#define MAXUBOUND(dst,eqn) bound_tmp = eqn; \ + if (bound_tmp > 65535) \ + bound_tmp = 65535; \ + dst = bound_tmp; + + if (pGC->lineStyle == LineSolid && pGC->joinStyle == JoinMiter && + pGC->lineWidth != 0) + { + xRectangle *tmp, *t; + int ntmp; + int offset1, offset2, offset3; + int x, y, width, height; + + ntmp = (nrects << 2); + offset2 = pGC->lineWidth; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + tmp = (xRectangle *) ALLOCATE_LOCAL(ntmp * sizeof (xRectangle)); + if (!tmp) + return; + t = tmp; + for (i = 0; i < nrects; i++) + { + x = pR->x; + y = pR->y; + width = pR->width; + height = pR->height; + pR++; + if (width == 0 && height == 0) + { + rect[0].x = x; + rect[0].y = y; + rect[1].x = x; + rect[1].y = y; + (*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 2, rect); + } + else if (height < offset2 || width < offset1) + { + if (height == 0) + { + t->x = x; + t->width = width; + } + else + { + MINBOUND (t->x, x - offset1) + MAXUBOUND (t->width, width + offset2) + } + if (width == 0) + { + t->y = y; + t->height = height; + } + else + { + MINBOUND (t->y, y - offset1) + MAXUBOUND (t->height, height + offset2) + } + t++; + } + else + { + MINBOUND(t->x, x - offset1) + MINBOUND(t->y, y - offset1) + MAXUBOUND(t->width, width + offset2) + t->height = offset2; + t++; + MINBOUND(t->x, x - offset1) + MAXBOUND(t->y, y + offset3); + t->width = offset2; + t->height = height - offset2; + t++; + MAXBOUND(t->x, x + width - offset1); + MAXBOUND(t->y, y + offset3) + t->width = offset2; + t->height = height - offset2; + t++; + MINBOUND(t->x, x - offset1) + MAXBOUND(t->y, y + height - offset1) + MAXUBOUND(t->width, width + offset2) + t->height = offset2; + t++; + } + } + (*pGC->ops->PolyFillRect) (pDraw, pGC, t - tmp, tmp); + DEALLOCATE_LOCAL ((pointer) tmp); + } + else + { + + for (i=0; ix; + rect[0].y = pR->y; + + MAXBOUND(rect[1].x, pR->x + (int) pR->width) + rect[1].y = rect[0].y; + + rect[2].x = rect[1].x; + MAXBOUND(rect[2].y, pR->y + (int) pR->height); + + rect[3].x = rect[0].x; + rect[3].y = rect[2].y; + + rect[4].x = rect[0].x; + rect[4].y = rect[0].y; + + (*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 5, rect); + pR++; + } + } +} diff --git a/mi/mipolyseg.c b/mi/mipolyseg.c new file mode 100644 index 000000000..2500f7abb --- /dev/null +++ b/mi/mipolyseg.c @@ -0,0 +1,79 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipolyseg.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmap.h" + +/***************************************************************** + * miPolySegment + * + * For each segment, draws a line between (x1, y1) and (x2, y2). The + * lines are drawn in the order listed. + * + * Walks the segments, compressing them into format for PolyLines. + * + *****************************************************************/ + + +void +miPolySegment(pDraw, pGC, nseg, pSegs) + DrawablePtr pDraw; + GCPtr pGC; + int nseg; + xSegment *pSegs; +{ + int i; + + for (i=0; iops->Polylines)(pDraw, pGC, CoordModeOrigin, 2,(DDXPointPtr)pSegs); + pSegs++; + } +} diff --git a/mi/mipolytext.c b/mi/mipolytext.c new file mode 100644 index 000000000..22dc6b2a9 --- /dev/null +++ b/mi/mipolytext.c @@ -0,0 +1,196 @@ +/******************************************************************* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +************************************************************************/ +/* $Xorg: mipolytext.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +/* + * mipolytext.c - text routines + * + * Author: haynes + * Digital Equipment Corporation + * Western Software Laboratory + * Date: Thu Feb 5 1987 + */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "misc.h" +#include "gcstruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" + +int +miPolyText(pDraw, pGC, x, y, count, chars, fontEncoding) + DrawablePtr pDraw; + GCPtr pGC; + int x, y; + int count; + char *chars; + FontEncoding fontEncoding; +{ + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, + fontEncoding, &n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n != 0) + (*pGC->ops->PolyGlyphBlt)( + pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); + return x+w; +} + + +int +miPolyText8(pDraw, pGC, x, y, count, chars) + DrawablePtr pDraw; + GCPtr pGC; + int x, y; + int count; + char *chars; +{ + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, + Linear8Bit, &n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n != 0) + (*pGC->ops->PolyGlyphBlt)( + pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); + return x+w; +} + + +int +miPolyText16(pDraw, pGC, x, y, count, chars) + DrawablePtr pDraw; + GCPtr pGC; + int x, y; + int count; + unsigned short *chars; +{ + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n != 0) + (*pGC->ops->PolyGlyphBlt)( + pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); + return x+w; +} + + +int +miImageText(pDraw, pGC, x, y, count, chars, fontEncoding) + DrawablePtr pDraw; + GCPtr pGC; + int x, y; + int count; + char *chars; + FontEncoding fontEncoding; +{ + unsigned long n, i; + FontPtr font = pGC->font; + int w; + CharInfoPtr charinfo[255]; + + GetGlyphs(font, (unsigned long)count, (unsigned char *)chars, + fontEncoding, &n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n !=0 ) + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(font)); + return x+w; +} + + +void +miImageText8(pDraw, pGC, x, y, count, chars) + DrawablePtr pDraw; + GCPtr pGC; + int x, y; + int count; + char *chars; +{ + unsigned long n; + FontPtr font = pGC->font; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(font, (unsigned long)count, (unsigned char *)chars, + Linear8Bit, &n, charinfo); + if (n !=0 ) + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(font)); +} + + +void +miImageText16(pDraw, pGC, x, y, count, chars) + DrawablePtr pDraw; + GCPtr pGC; + int x, y; + int count; + unsigned short *chars; +{ + unsigned long n; + FontPtr font = pGC->font; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, charinfo); + if (n !=0 ) + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(font)); +} diff --git a/mi/mipolyutil.c b/mi/mipolyutil.c new file mode 100644 index 000000000..879bd6e1d --- /dev/null +++ b/mi/mipolyutil.c @@ -0,0 +1,398 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipolyutil.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include "miscstruct.h" +#include "gc.h" +#include "miscanfill.h" +#include "mipoly.h" + +#define MAXINT 0x7fffffff +#define MININT -MAXINT + +/* + * fillUtils.c + * + * Written by Brian Kelleher; Oct. 1985 + * + * This module contains all of the utility functions + * needed to scan convert a polygon. + * + */ + +/* + * InsertEdgeInET + * + * Insert the given edge into the edge table. + * First we must find the correct bucket in the + * Edge table, then find the right slot in the + * bucket. Finally, we can insert it. + * + */ +Bool +miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock) + EdgeTable *ET; + EdgeTableEntry *ETE; + int scanline; + ScanLineListBlock **SLLBlock; + int *iSLLBlock; +{ + register EdgeTableEntry *start, *prev; + register ScanLineList *pSLL, *pPrevSLL; + ScanLineListBlock *tmpSLLBlock; + + /* + * find the right bucket to put the edge into + */ + pPrevSLL = &ET->scanlines; + pSLL = pPrevSLL->next; + while (pSLL && (pSLL->scanline < scanline)) + { + pPrevSLL = pSLL; + pSLL = pSLL->next; + } + + /* + * reassign pSLL (pointer to ScanLineList) if necessary + */ + if ((!pSLL) || (pSLL->scanline > scanline)) + { + if (*iSLLBlock > SLLSPERBLOCK-1) + { + tmpSLLBlock = + (ScanLineListBlock *)xalloc(sizeof(ScanLineListBlock)); + if (!tmpSLLBlock) + return FALSE; + (*SLLBlock)->next = tmpSLLBlock; + tmpSLLBlock->next = (ScanLineListBlock *)NULL; + *SLLBlock = tmpSLLBlock; + *iSLLBlock = 0; + } + pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]); + + pSLL->next = pPrevSLL->next; + pSLL->edgelist = (EdgeTableEntry *)NULL; + pPrevSLL->next = pSLL; + } + pSLL->scanline = scanline; + + /* + * now insert the edge in the right bucket + */ + prev = (EdgeTableEntry *)NULL; + start = pSLL->edgelist; + while (start && (start->bres.minor < ETE->bres.minor)) + { + prev = start; + start = start->next; + } + ETE->next = start; + + if (prev) + prev->next = ETE; + else + pSLL->edgelist = ETE; + return TRUE; +} + +/* + * CreateEdgeTable + * + * This routine creates the edge table for + * scan converting polygons. + * The Edge Table (ET) looks like: + * + * EdgeTable + * -------- + * | ymax | ScanLineLists + * |scanline|-->------------>-------------->... + * -------- |scanline| |scanline| + * |edgelist| |edgelist| + * --------- --------- + * | | + * | | + * V V + * list of ETEs list of ETEs + * + * where ETE is an EdgeTableEntry data structure, + * and there is one ScanLineList per scanline at + * which an edge is initially entered. + * + */ + +Bool +miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock) + register int count; + register DDXPointPtr pts; + EdgeTable *ET; + EdgeTableEntry *AET; + register EdgeTableEntry *pETEs; + ScanLineListBlock *pSLLBlock; +{ + register DDXPointPtr top, bottom; + register DDXPointPtr PrevPt, CurrPt; + int iSLLBlock = 0; + + int dy; + + if (count < 2) return TRUE; + + /* + * initialize the Active Edge Table + */ + AET->next = (EdgeTableEntry *)NULL; + AET->back = (EdgeTableEntry *)NULL; + AET->nextWETE = (EdgeTableEntry *)NULL; + AET->bres.minor = MININT; + + /* + * initialize the Edge Table. + */ + ET->scanlines.next = (ScanLineList *)NULL; + ET->ymax = MININT; + ET->ymin = MAXINT; + pSLLBlock->next = (ScanLineListBlock *)NULL; + + PrevPt = &pts[count-1]; + + /* + * for each vertex in the array of points. + * In this loop we are dealing with two vertices at + * a time -- these make up one edge of the polygon. + */ + while (count--) + { + CurrPt = pts++; + + /* + * find out which point is above and which is below. + */ + if (PrevPt->y > CurrPt->y) + { + bottom = PrevPt, top = CurrPt; + pETEs->ClockWise = 0; + } + else + { + bottom = CurrPt, top = PrevPt; + pETEs->ClockWise = 1; + } + + /* + * don't add horizontal edges to the Edge table. + */ + if (bottom->y != top->y) + { + pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */ + + /* + * initialize integer edge algorithm + */ + dy = bottom->y - top->y; + BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres); + + if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock)) + { + miFreeStorage(pSLLBlock->next); + return FALSE; + } + + ET->ymax = max(ET->ymax, PrevPt->y); + ET->ymin = min(ET->ymin, PrevPt->y); + pETEs++; + } + + PrevPt = CurrPt; + } + return TRUE; +} + +/* + * loadAET + * + * This routine moves EdgeTableEntries from the + * EdgeTable into the Active Edge Table, + * leaving them sorted by smaller x coordinate. + * + */ + +void +miloadAET(AET, ETEs) + register EdgeTableEntry *AET, *ETEs; +{ + register EdgeTableEntry *pPrevAET; + register EdgeTableEntry *tmp; + + pPrevAET = AET; + AET = AET->next; + while (ETEs) + { + while (AET && (AET->bres.minor < ETEs->bres.minor)) + { + pPrevAET = AET; + AET = AET->next; + } + tmp = ETEs->next; + ETEs->next = AET; + if (AET) + AET->back = ETEs; + ETEs->back = pPrevAET; + pPrevAET->next = ETEs; + pPrevAET = ETEs; + + ETEs = tmp; + } +} + +/* + * computeWAET + * + * This routine links the AET by the + * nextWETE (winding EdgeTableEntry) link for + * use by the winding number rule. The final + * Active Edge Table (AET) might look something + * like: + * + * AET + * ---------- --------- --------- + * |ymax | |ymax | |ymax | + * | ... | |... | |... | + * |next |->|next |->|next |->... + * |nextWETE| |nextWETE| |nextWETE| + * --------- --------- ^-------- + * | | | + * V-------------------> V---> ... + * + */ +void +micomputeWAET(AET) + register EdgeTableEntry *AET; +{ + register EdgeTableEntry *pWETE; + register int inside = 1; + register int isInside = 0; + + AET->nextWETE = (EdgeTableEntry *)NULL; + pWETE = AET; + AET = AET->next; + while (AET) + { + if (AET->ClockWise) + isInside++; + else + isInside--; + + if ((!inside && !isInside) || + ( inside && isInside)) + { + pWETE->nextWETE = AET; + pWETE = AET; + inside = !inside; + } + AET = AET->next; + } + pWETE->nextWETE = (EdgeTableEntry *)NULL; +} + +/* + * InsertionSort + * + * Just a simple insertion sort using + * pointers and back pointers to sort the Active + * Edge Table. + * + */ + +int +miInsertionSort(AET) + register EdgeTableEntry *AET; +{ + register EdgeTableEntry *pETEchase; + register EdgeTableEntry *pETEinsert; + register EdgeTableEntry *pETEchaseBackTMP; + register int changed = 0; + + AET = AET->next; + while (AET) + { + pETEinsert = AET; + pETEchase = AET; + while (pETEchase->back->bres.minor > AET->bres.minor) + pETEchase = pETEchase->back; + + AET = AET->next; + if (pETEchase != pETEinsert) + { + pETEchaseBackTMP = pETEchase->back; + pETEinsert->back->next = AET; + if (AET) + AET->back = pETEinsert->back; + pETEinsert->next = pETEchase; + pETEchase->back->next = pETEinsert; + pETEchase->back = pETEinsert; + pETEinsert->back = pETEchaseBackTMP; + changed = 1; + } + } + return(changed); +} + +/* + * Clean up our act. + */ +void +miFreeStorage(pSLLBlock) + register ScanLineListBlock *pSLLBlock; +{ + register ScanLineListBlock *tmpSLLBlock; + + while (pSLLBlock) + { + tmpSLLBlock = pSLLBlock->next; + xfree(pSLLBlock); + pSLLBlock = tmpSLLBlock; + } +} diff --git a/mi/mipushpxl.c b/mi/mipushpxl.c new file mode 100644 index 000000000..24ee8bbe3 --- /dev/null +++ b/mi/mipushpxl.c @@ -0,0 +1,197 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mipushpxl.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +#include "X.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "miscstruct.h" +#include "../mfb/maskbits.h" + +#define NPT 128 + +/* miPushPixels -- squeegees the fill style of pGC through pBitMap + * into pDrawable. pBitMap is a stencil (dx by dy of it is used, it may + * be bigger) which is placed on the drawable at xOrg, yOrg. Where a 1 bit + * is set in the bitmap, the fill style is put onto the drawable using + * the GC's logical function. The drawable is not changed where the bitmap + * has a zero bit or outside the area covered by the stencil. + +WARNING: + this code works if the 1-bit deep pixmap format returned by GetSpans +is the same as the format defined by the mfb code (i.e. 32-bit padding +per scanline, scanline unit = 32 bits; later, this might mean +bitsizeof(int) padding and sacnline unit == bitsizeof(int).) + + */ +void +miPushPixels(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg) + GCPtr pGC; + PixmapPtr pBitMap; + DrawablePtr pDrawable; + int dx, dy, xOrg, yOrg; +{ + int h, dxDiv32, ibEnd; + unsigned long *pwLineStart; + register unsigned long *pw, *pwEnd; + register unsigned long msk; + register int ib, w; + register int ipt; /* index into above arrays */ + Bool fInBox; + DDXPointRec pt[NPT], ptThisLine; + int width[NPT]; + + pwLineStart = (unsigned long *)xalloc(BitmapBytePad(dx)); + if (!pwLineStart) + return; + ipt = 0; + dxDiv32 = dx/32; + + for(h = 0, ptThisLine.x = 0, ptThisLine.y = 0; + h < dy; + h++, ptThisLine.y++) + { + + (*pBitMap->drawable.pScreen->GetSpans)((DrawablePtr)pBitMap, dx, + &ptThisLine, &dx, 1, (char *)pwLineStart); + + pw = pwLineStart; + /* Process all words which are fully in the pixmap */ + + fInBox = FALSE; + pwEnd = pwLineStart + dxDiv32; + while(pw < pwEnd) + { + w = *pw; + msk = endtab[1]; + for(ib = 0; ib < 32; ib++) + { + if(w & msk) + { + if(!fInBox) + { + pt[ipt].x = ((pw - pwLineStart) << 5) + ib + xOrg; + pt[ipt].y = h + yOrg; + /* start new box */ + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + width[ipt] = ((pw - pwLineStart) << 5) + + ib + xOrg - pt[ipt].x; + if (++ipt >= NPT) + { + (*pGC->ops->FillSpans)(pDrawable, pGC, + NPT, pt, width, TRUE); + ipt = 0; + } + /* end box */ + fInBox = FALSE; + } + } + msk = SCRRIGHT(msk, 1); + } + pw++; + } + ibEnd = dx & 0x1F; + if(ibEnd) + { + /* Process final partial word on line */ + w = *pw; + msk = endtab[1]; + for(ib = 0; ib < ibEnd; ib++) + { + if(w & msk) + { + if(!fInBox) + { + /* start new box */ + pt[ipt].x = ((pw - pwLineStart) << 5) + ib + xOrg; + pt[ipt].y = h + yOrg; + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + /* end box */ + width[ipt] = ((pw - pwLineStart) << 5) + + ib + xOrg - pt[ipt].x; + if (++ipt >= NPT) + { + (*pGC->ops->FillSpans)(pDrawable, + pGC, NPT, pt, width, TRUE); + ipt = 0; + } + fInBox = FALSE; + } + } + msk = SCRRIGHT(msk, 1); + } + } + /* If scanline ended with last bit set, end the box */ + if(fInBox) + { + width[ipt] = dx + xOrg - pt[ipt].x; + if (++ipt >= NPT) + { + (*pGC->ops->FillSpans)(pDrawable, pGC, NPT, pt, width, TRUE); + ipt = 0; + } + } + } + xfree(pwLineStart); + /* Flush any remaining spans */ + if (ipt) + { + (*pGC->ops->FillSpans)(pDrawable, pGC, ipt, pt, width, TRUE); + } +} diff --git a/mi/miregion.c b/mi/miregion.c new file mode 100644 index 000000000..f9c25b09d --- /dev/null +++ b/mi/miregion.c @@ -0,0 +1,2419 @@ +/*********************************************************** + +Copyright 1987, 1988, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988, 1989 by +Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: miregion.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +#include +#include "miscstruct.h" +#include "regionstr.h" +#include "Xprotostr.h" +#include "gc.h" + +#if defined (__GNUC__) && !defined (NO_INLINES) +#define INLINE __inline +#else +#define INLINE +#endif + +/* + * hack until callers of these functions can deal with out-of-memory + */ + +extern Bool Must_have_memory; + +#ifdef DEBUG +#define assert(expr) {if (!(expr)) \ + FatalError("Assertion failed file %s, line %d: expr\n", \ + __FILE__, __LINE__); } +#else +#define assert(expr) +#endif + +#define good(reg) assert(miValidRegion(reg)) + +/* + * The functions in this file implement the Region abstraction used extensively + * throughout the X11 sample server. A Region is simply a set of disjoint + * (non-overlapping) rectangles, plus an "extent" rectangle which is the + * smallest single rectangle that contains all the non-overlapping rectangles. + * + * A Region is implemented as a "y-x-banded" array of rectangles. This array + * imposes two degrees of order. First, all rectangles are sorted by top side + * y coordinate first (y1), and then by left side x coordinate (x1). + * + * Furthermore, the rectangles are grouped into "bands". Each rectangle in a + * band has the same top y coordinate (y1), and each has the same bottom y + * coordinate (y2). Thus all rectangles in a band differ only in their left + * and right side (x1 and x2). Bands are implicit in the array of rectangles: + * there is no separate list of band start pointers. + * + * The y-x band representation does not minimize rectangles. In particular, + * if a rectangle vertically crosses a band (the rectangle has scanlines in + * the y1 to y2 area spanned by the band), then the rectangle may be broken + * down into two or more smaller rectangles stacked one atop the other. + * + * ----------- ----------- + * | | | | band 0 + * | | -------- ----------- -------- + * | | | | in y-x banded | | | | band 1 + * | | | | form is | | | | + * ----------- | | ----------- -------- + * | | | | band 2 + * -------- -------- + * + * An added constraint on the rectangles is that they must cover as much + * horizontal area as possible: no two rectangles within a band are allowed + * to touch. + * + * Whenever possible, bands will be merged together to cover a greater vertical + * distance (and thus reduce the number of rectangles). Two bands can be merged + * only if the bottom of one touches the top of the other and they have + * rectangles in the same places (of the same width, of course). + * + * Adam de Boor wrote most of the original region code. Joel McCormack + * substantially modified or rewrote most of the core arithmetic routines, + * and added miRegionValidate in order to support several speed improvements + * to miValidateTree. Bob Scheifler changed the representation to be more + * compact when empty or a single rectangle, and did a bunch of gratuitous + * reformatting. + */ + +/* true iff two Boxes overlap */ +#define EXTENTCHECK(r1,r2) \ + (!( ((r1)->x2 <= (r2)->x1) || \ + ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || \ + ((r1)->y1 >= (r2)->y2) ) ) + +/* true iff (x,y) is in Box */ +#define INBOX(r,x,y) \ + ( ((r)->x2 > x) && \ + ((r)->x1 <= x) && \ + ((r)->y2 > y) && \ + ((r)->y1 <= y) ) + +/* true iff Box r1 contains Box r2 */ +#define SUBSUMES(r1,r2) \ + ( ((r1)->x1 <= (r2)->x1) && \ + ((r1)->x2 >= (r2)->x2) && \ + ((r1)->y1 <= (r2)->y1) && \ + ((r1)->y2 >= (r2)->y2) ) + +#define xallocData(n) (RegDataPtr)xalloc(REGION_SZOF(n)) +#define xfreeData(reg) if ((reg)->data && (reg)->data->size) xfree((reg)->data) + +#define RECTALLOC(pReg,n) \ +if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ + miRectAlloc(pReg, n) + +#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \ +{ \ + pNextRect->x1 = nx1; \ + pNextRect->y1 = ny1; \ + pNextRect->x2 = nx2; \ + pNextRect->y2 = ny2; \ + pNextRect++; \ +} + +#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \ +{ \ + if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\ + { \ + miRectAlloc(pReg, 1); \ + pNextRect = REGION_TOP(pReg); \ + } \ + ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \ + pReg->data->numRects++; \ + assert(pReg->data->numRects<=pReg->data->size); \ +} + + +#define DOWNSIZE(reg,numRects) \ +if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ +{ \ + RegDataPtr NewData; \ + NewData = (RegDataPtr)xrealloc((reg)->data, REGION_SZOF(numRects)); \ + if (NewData) \ + { \ + NewData->size = (numRects); \ + (reg)->data = NewData; \ + } \ +} + + +BoxRec miEmptyBox = {0, 0, 0, 0}; +RegDataRec miEmptyData = {0, 0}; + +#ifdef DEBUG +int +miPrintRegion(rgn) + RegionPtr rgn; +{ + int num, size; + register int i; + BoxPtr rects; + + num = REGION_NUM_RECTS(rgn); + size = REGION_SIZE(rgn); + rects = REGION_RECTS(rgn); + ErrorF("num: %d size: %d\n", num, size); + ErrorF("extents: %d %d %d %d\n", + rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2); + for (i = 0; i < num; i++) + ErrorF("%d %d %d %d \n", + rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); + ErrorF("\n"); + return(num); +} + + +Bool +miRegionsEqual(reg1, reg2) + RegionPtr reg1; + RegionPtr reg2; +{ + int i; + BoxPtr rects1, rects2; + + if (reg1->extents.x1 != reg2->extents.x1) return FALSE; + if (reg1->extents.x2 != reg2->extents.x2) return FALSE; + if (reg1->extents.y1 != reg2->extents.y1) return FALSE; + if (reg1->extents.y2 != reg2->extents.y2) return FALSE; + if (REGION_NUM_RECTS(reg1) != REGION_NUM_RECTS(reg2)) return FALSE; + + rects1 = REGION_RECTS(reg1); + rects2 = REGION_RECTS(reg2); + for (i = 0; i != REGION_NUM_RECTS(reg1); i++) { + if (rects1[i].x1 != rects2[i].x1) return FALSE; + if (rects1[i].x2 != rects2[i].x2) return FALSE; + if (rects1[i].y1 != rects2[i].y1) return FALSE; + if (rects1[i].y2 != rects2[i].y2) return FALSE; + } + return TRUE; +} + +Bool +miValidRegion(reg) + RegionPtr reg; +{ + register int i, numRects; + + if ((reg->extents.x1 > reg->extents.x2) || + (reg->extents.y1 > reg->extents.y2)) + return FALSE; + numRects = REGION_NUM_RECTS(reg); + if (!numRects) + return ((reg->extents.x1 == reg->extents.x2) && + (reg->extents.y1 == reg->extents.y2) && + (reg->data->size || (reg->data == &miEmptyData))); + else if (numRects == 1) + return (!reg->data); + else + { + register BoxPtr pboxP, pboxN; + BoxRec box; + + pboxP = REGION_RECTS(reg); + box = *pboxP; + box.y2 = pboxP[numRects-1].y2; + pboxN = pboxP + 1; + for (i = numRects; --i > 0; pboxP++, pboxN++) + { + if ((pboxN->x1 >= pboxN->x2) || + (pboxN->y1 >= pboxN->y2)) + return FALSE; + if (pboxN->x1 < box.x1) + box.x1 = pboxN->x1; + if (pboxN->x2 > box.x2) + box.x2 = pboxN->x2; + if ((pboxN->y1 < pboxP->y1) || + ((pboxN->y1 == pboxP->y1) && + ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2)))) + return FALSE; + } + return ((box.x1 == reg->extents.x1) && + (box.x2 == reg->extents.x2) && + (box.y1 == reg->extents.y1) && + (box.y2 == reg->extents.y2)); + } +} + +#endif /* DEBUG */ + + +/***************************************************************** + * RegionCreate(rect, size) + * This routine does a simple malloc to make a structure of + * REGION of "size" number of rectangles. + *****************************************************************/ + +RegionPtr +miRegionCreate(rect, size) + BoxPtr rect; + int size; +{ + register RegionPtr pReg; + + Must_have_memory = TRUE; /* XXX */ + pReg = (RegionPtr)xalloc(sizeof(RegionRec)); + Must_have_memory = FALSE; /* XXX */ + if (rect) + { + pReg->extents = *rect; + pReg->data = (RegDataPtr)NULL; + } + else + { + pReg->extents = miEmptyBox; + if ((size > 1) && (pReg->data = xallocData(size))) + { + pReg->data->size = size; + pReg->data->numRects = 0; + } + else + pReg->data = &miEmptyData; + } + return(pReg); +} + +/***************************************************************** + * RegionInit(pReg, rect, size) + * Outer region rect is statically allocated. + *****************************************************************/ + +void +miRegionInit(pReg, rect, size) + RegionPtr pReg; + BoxPtr rect; + int size; +{ + if (rect) + { + pReg->extents = *rect; + pReg->data = (RegDataPtr)NULL; + } + else + { + pReg->extents = miEmptyBox; + if ((size > 1) && (pReg->data = xallocData(size))) + { + pReg->data->size = size; + pReg->data->numRects = 0; + } + else + pReg->data = &miEmptyData; + } +} + +void +miRegionDestroy(pReg) + RegionPtr pReg; +{ + good(pReg); + xfreeData(pReg); + xfree(pReg); +} + +void +miRegionUninit(pReg) + RegionPtr pReg; +{ + good(pReg); + xfreeData(pReg); +} + +Bool +miRectAlloc(pRgn, n) + register RegionPtr pRgn; + int n; +{ + Must_have_memory = TRUE; /* XXX */ + if (!pRgn->data) + { + n++; + pRgn->data = xallocData(n); + pRgn->data->numRects = 1; + *REGION_BOXPTR(pRgn) = pRgn->extents; + } + else if (!pRgn->data->size) + { + pRgn->data = xallocData(n); + pRgn->data->numRects = 0; + } + else + { + if (n == 1) + { + n = pRgn->data->numRects; + if (n > 500) /* XXX pick numbers out of a hat */ + n = 250; + } + n += pRgn->data->numRects; + pRgn->data = (RegDataPtr)xrealloc(pRgn->data, REGION_SZOF(n)); + } + Must_have_memory = FALSE; /* XXX */ + pRgn->data->size = n; + return TRUE; +} + +Bool +miRegionCopy(dst, src) + register RegionPtr dst; + register RegionPtr src; +{ + good(dst); + good(src); + if (dst == src) + return TRUE; + dst->extents = src->extents; + if (!src->data || !src->data->size) + { + xfreeData(dst); + dst->data = src->data; + return TRUE; + } + if (!dst->data || (dst->data->size < src->data->numRects)) + { + xfreeData(dst); + Must_have_memory = TRUE; /* XXX */ + dst->data = xallocData(src->data->numRects); + Must_have_memory = FALSE; /* XXX */ + dst->data->size = src->data->numRects; + } + dst->data->numRects = src->data->numRects; + memmove((char *)REGION_BOXPTR(dst),(char *)REGION_BOXPTR(src), + dst->data->numRects * sizeof(BoxRec)); + return TRUE; +} + + +/*====================================================================== + * Generic Region Operator + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * miCoalesce -- + * Attempt to merge the boxes in the current band with those in the + * previous one. We are guaranteed that the current band extends to + * the end of the rects array. Used only by miRegionOp. + * + * Results: + * The new index for the previous band. + * + * Side Effects: + * If coalescing takes place: + * - rectangles in the previous band will have their y2 fields + * altered. + * - pReg->data->numRects will be decreased. + * + *----------------------------------------------------------------------- + */ +INLINE static int +miCoalesce (pReg, prevStart, curStart) + register RegionPtr pReg; /* Region to coalesce */ + int prevStart; /* Index of start of previous band */ + int curStart; /* Index of start of current band */ +{ + register BoxPtr pPrevBox; /* Current box in previous band */ + register BoxPtr pCurBox; /* Current box in current band */ + register int numRects; /* Number rectangles in both bands */ + register int y2; /* Bottom of current band */ + /* + * Figure out how many rectangles are in the band. + */ + numRects = curStart - prevStart; + assert(numRects == pReg->data->numRects - curStart); + + if (!numRects) return curStart; + + /* + * The bands may only be coalesced if the bottom of the previous + * matches the top scanline of the current. + */ + pPrevBox = REGION_BOX(pReg, prevStart); + pCurBox = REGION_BOX(pReg, curStart); + if (pPrevBox->y2 != pCurBox->y1) return curStart; + + /* + * Make sure the bands have boxes in the same places. This + * assumes that boxes have been added in such a way that they + * cover the most area possible. I.e. two boxes in a band must + * have some horizontal space between them. + */ + y2 = pCurBox->y2; + + do { + if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) { + return (curStart); + } + pPrevBox++; + pCurBox++; + numRects--; + } while (numRects); + + /* + * The bands may be merged, so set the bottom y of each box + * in the previous band to the bottom y of the current band. + */ + numRects = curStart - prevStart; + pReg->data->numRects -= numRects; + do { + pPrevBox--; + pPrevBox->y2 = y2; + numRects--; + } while (numRects); + return prevStart; +} + + +/* Quicky macro to avoid trivial reject procedure calls to miCoalesce */ + +#define Coalesce(newReg, prevBand, curBand) \ + if (curBand - prevBand == newReg->data->numRects - curBand) { \ + prevBand = miCoalesce(newReg, prevBand, curBand); \ + } else { \ + prevBand = curBand; \ + } + +/*- + *----------------------------------------------------------------------- + * miAppendNonO -- + * Handle a non-overlapping band for the union and subtract operations. + * Just adds the (top/bottom-clipped) rectangles into the region. + * Doesn't have to check for subsumption or anything. + * + * Results: + * None. + * + * Side Effects: + * pReg->data->numRects is incremented and the rectangles overwritten + * with the rectangles we're passed. + * + *----------------------------------------------------------------------- + */ + +INLINE static Bool +miAppendNonO (pReg, r, rEnd, y1, y2) + register RegionPtr pReg; + register BoxPtr r; + BoxPtr rEnd; + register int y1; + register int y2; +{ + register BoxPtr pNextRect; + register int newRects; + + newRects = rEnd - r; + + assert(y1 < y2); + assert(newRects != 0); + + /* Make sure we have enough space for all rectangles to be added */ + RECTALLOC(pReg, newRects); + pNextRect = REGION_TOP(pReg); + pReg->data->numRects += newRects; + do { + assert(r->x1 < r->x2); + ADDRECT(pNextRect, r->x1, y1, r->x2, y2); + r++; + } while (r != rEnd); + + return TRUE; +} + +#define FindBand(r, rBandEnd, rEnd, ry1) \ +{ \ + ry1 = r->y1; \ + rBandEnd = r+1; \ + while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \ + rBandEnd++; \ + } \ +} + +#define AppendRegions(newReg, r, rEnd) \ +{ \ + int newRects; \ + if (newRects = rEnd - r) { \ + RECTALLOC(newReg, newRects); \ + memmove((char *)REGION_TOP(newReg),(char *)r, \ + newRects * sizeof(BoxRec)); \ + newReg->data->numRects += newRects; \ + } \ +} + +/*- + *----------------------------------------------------------------------- + * miRegionOp -- + * Apply an operation to two regions. Called by miUnion, miInverse, + * miSubtract, miIntersect.... Both regions MUST have at least one + * rectangle, and cannot be the same object. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * The new region is overwritten. + * pOverlap set to TRUE if overlapFunc ever returns TRUE. + * + * Notes: + * The idea behind this function is to view the two regions as sets. + * Together they cover a rectangle of area that this function divides + * into horizontal bands where points are covered only by one region + * or by both. For the first case, the nonOverlapFunc is called with + * each the band and the band's upper and lower extents. For the + * second, the overlapFunc is called to process the entire band. It + * is responsible for clipping the rectangles in the band, though + * this function provides the boundaries. + * At the end of each band, the new region is coalesced, if possible, + * to reduce the number of rectangles in the region. + * + *----------------------------------------------------------------------- + */ +static Bool +miRegionOp(newReg, reg1, reg2, overlapFunc, appendNon1, appendNon2, pOverlap) + RegionPtr newReg; /* Place to store result */ + RegionPtr reg1; /* First region in operation */ + RegionPtr reg2; /* 2d region in operation */ + Bool (*overlapFunc)(); /* Function to call for over- + * lapping bands */ + Bool appendNon1; /* Append non-overlapping bands */ + /* in region 1 ? */ + Bool appendNon2; /* Append non-overlapping bands */ + /* in region 2 ? */ + Bool *pOverlap; +{ + register BoxPtr r1; /* Pointer into first region */ + register BoxPtr r2; /* Pointer into 2d region */ + BoxPtr r1End; /* End of 1st region */ + BoxPtr r2End; /* End of 2d region */ + short ybot; /* Bottom of intersection */ + short ytop; /* Top of intersection */ + RegDataPtr oldData; /* Old data for newReg */ + int prevBand; /* Index of start of + * previous band in newReg */ + int curBand; /* Index of start of current + * band in newReg */ + register BoxPtr r1BandEnd; /* End of current band in r1 */ + register BoxPtr r2BandEnd; /* End of current band in r2 */ + short top; /* Top of non-overlapping band */ + short bot; /* Bottom of non-overlapping band*/ + register int r1y1; /* Temps for r1->y1 and r2->y1 */ + register int r2y1; + int newSize; + int numRects; + + /* + * Initialization: + * set r1, r2, r1End and r2End appropriately, save the rectangles + * of the destination region until the end in case it's one of + * the two source regions, then mark the "new" region empty, allocating + * another array of rectangles for it to use. + */ + + r1 = REGION_RECTS(reg1); + newSize = REGION_NUM_RECTS(reg1); + r1End = r1 + newSize; + numRects = REGION_NUM_RECTS(reg2); + r2 = REGION_RECTS(reg2); + r2End = r2 + numRects; + assert(r1 != r1End); + assert(r2 != r2End); + + oldData = (RegDataPtr)NULL; + if (((newReg == reg1) && (newSize > 1)) || + ((newReg == reg2) && (numRects > 1))) + { + oldData = newReg->data; + newReg->data = &miEmptyData; + } + /* guess at new size */ + if (numRects > newSize) + newSize = numRects; + newSize <<= 1; + if (!newReg->data) + newReg->data = &miEmptyData; + else if (newReg->data->size) + newReg->data->numRects = 0; + if (newSize > newReg->data->size) + miRectAlloc(newReg, newSize); + + /* + * Initialize ybot. + * In the upcoming loop, ybot and ytop serve different functions depending + * on whether the band being handled is an overlapping or non-overlapping + * band. + * In the case of a non-overlapping band (only one of the regions + * has points in the band), ybot is the bottom of the most recent + * intersection and thus clips the top of the rectangles in that band. + * ytop is the top of the next intersection between the two regions and + * serves to clip the bottom of the rectangles in the current band. + * For an overlapping band (where the two regions intersect), ytop clips + * the top of the rectangles of both regions and ybot clips the bottoms. + */ + + ybot = min(r1->y1, r2->y1); + + /* + * prevBand serves to mark the start of the previous band so rectangles + * can be coalesced into larger rectangles. qv. miCoalesce, above. + * In the beginning, there is no previous band, so prevBand == curBand + * (curBand is set later on, of course, but the first band will always + * start at index 0). prevBand and curBand must be indices because of + * the possible expansion, and resultant moving, of the new region's + * array of rectangles. + */ + prevBand = 0; + + do { + /* + * This algorithm proceeds one source-band (as opposed to a + * destination band, which is determined by where the two regions + * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the + * rectangle after the last one in the current band for their + * respective regions. + */ + assert(r1 != r1End); + assert(r2 != r2End); + + FindBand(r1, r1BandEnd, r1End, r1y1); + FindBand(r2, r2BandEnd, r2End, r2y1); + + /* + * First handle the band that doesn't intersect, if any. + * + * Note that attention is restricted to one band in the + * non-intersecting region at once, so if a region has n + * bands between the current position and the next place it overlaps + * the other, this entire loop will be passed through n times. + */ + if (r1y1 < r2y1) { + if (appendNon1) { + top = max(r1y1, ybot); + bot = min(r1->y2, r2y1); + if (top != bot) { + curBand = newReg->data->numRects; + miAppendNonO(newReg, r1, r1BandEnd, top, bot); + Coalesce(newReg, prevBand, curBand); + } + } + ytop = r2y1; + } else if (r2y1 < r1y1) { + if (appendNon2) { + top = max(r2y1, ybot); + bot = min(r2->y2, r1y1); + if (top != bot) { + curBand = newReg->data->numRects; + miAppendNonO(newReg, r2, r2BandEnd, top, bot); + Coalesce(newReg, prevBand, curBand); + } + } + ytop = r1y1; + } else { + ytop = r1y1; + } + + /* + * Now see if we've hit an intersecting band. The two bands only + * intersect if ybot > ytop + */ + ybot = min(r1->y2, r2->y2); + if (ybot > ytop) { + curBand = newReg->data->numRects; + (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot, + pOverlap); + Coalesce(newReg, prevBand, curBand); + } + + /* + * If we've finished with a band (y2 == ybot) we skip forward + * in the region to the next band. + */ + if (r1->y2 == ybot) r1 = r1BandEnd; + if (r2->y2 == ybot) r2 = r2BandEnd; + + } while (r1 != r1End && r2 != r2End); + + /* + * Deal with whichever region (if any) still has rectangles left. + * + * We only need to worry about banding and coalescing for the very first + * band left. After that, we can just group all remaining boxes, + * regardless of how many bands, into one final append to the list. + */ + + if ((r1 != r1End) && appendNon1) { + /* Do first nonOverlap1Func call, which may be able to coalesce */ + FindBand(r1, r1BandEnd, r1End, r1y1); + curBand = newReg->data->numRects; + miAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2); + Coalesce(newReg, prevBand, curBand); + /* Just append the rest of the boxes */ + AppendRegions(newReg, r1BandEnd, r1End); + + } else if ((r2 != r2End) && appendNon2) { + /* Do first nonOverlap2Func call, which may be able to coalesce */ + FindBand(r2, r2BandEnd, r2End, r2y1); + curBand = newReg->data->numRects; + miAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2); + Coalesce(newReg, prevBand, curBand); + /* Append rest of boxes */ + AppendRegions(newReg, r2BandEnd, r2End); + } + + if (oldData) + xfree(oldData); + + if (!(numRects = newReg->data->numRects)) + { + xfreeData(newReg); + newReg->data = &miEmptyData; + } + else if (numRects == 1) + { + newReg->extents = *REGION_BOXPTR(newReg); + xfreeData(newReg); + newReg->data = (RegDataPtr)NULL; + } + else + { + DOWNSIZE(newReg, numRects); + } + + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * miSetExtents -- + * Reset the extents of a region to what they should be. Called by + * miSubtract and miIntersect as they can't figure it out along the + * way or do so easily, as miUnion can. + * + * Results: + * None. + * + * Side Effects: + * The region's 'extents' structure is overwritten. + * + *----------------------------------------------------------------------- + */ +void +miSetExtents (pReg) + register RegionPtr pReg; +{ + register BoxPtr pBox, pBoxEnd; + + if (!pReg->data) + return; + if (!pReg->data->size) + { + pReg->extents.x2 = pReg->extents.x1; + pReg->extents.y2 = pReg->extents.y1; + return; + } + + pBox = REGION_BOXPTR(pReg); + pBoxEnd = REGION_END(pReg); + + /* + * Since pBox is the first rectangle in the region, it must have the + * smallest y1 and since pBoxEnd is the last rectangle in the region, + * it must have the largest y2, because of banding. Initialize x1 and + * x2 from pBox and pBoxEnd, resp., as good things to initialize them + * to... + */ + pReg->extents.x1 = pBox->x1; + pReg->extents.y1 = pBox->y1; + pReg->extents.x2 = pBoxEnd->x2; + pReg->extents.y2 = pBoxEnd->y2; + + assert(pReg->extents.y1 < pReg->extents.y2); + while (pBox <= pBoxEnd) { + if (pBox->x1 < pReg->extents.x1) + pReg->extents.x1 = pBox->x1; + if (pBox->x2 > pReg->extents.x2) + pReg->extents.x2 = pBox->x2; + pBox++; + }; + + assert(pReg->extents.x1 < pReg->extents.x2); +} + +/*====================================================================== + * Region Intersection + *====================================================================*/ +/*- + *----------------------------------------------------------------------- + * miIntersectO -- + * Handle an overlapping band for miIntersect. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * Rectangles may be added to the region. + * + *----------------------------------------------------------------------- + */ +/*ARGSUSED*/ +static Bool +miIntersectO (pReg, r1, r1End, r2, r2End, y1, y2, pOverlap) + register RegionPtr pReg; + register BoxPtr r1; + BoxPtr r1End; + register BoxPtr r2; + BoxPtr r2End; + short y1; + short y2; + Bool *pOverlap; +{ + register int x1; + register int x2; + register BoxPtr pNextRect; + + pNextRect = REGION_TOP(pReg); + + assert(y1 < y2); + assert(r1 != r1End && r2 != r2End); + + do { + x1 = max(r1->x1, r2->x1); + x2 = min(r1->x2, r2->x2); + + /* + * If there's any overlap between the two rectangles, add that + * overlap to the new region. + */ + if (x1 < x2) + NEWRECT(pReg, pNextRect, x1, y1, x2, y2); + + /* + * Advance the pointer(s) with the leftmost right side, since the next + * rectangle on that list may still overlap the other region's + * current rectangle. + */ + if (r1->x2 == x2) { + r1++; + } + if (r2->x2 == x2) { + r2++; + } + } while ((r1 != r1End) && (r2 != r2End)); + + return TRUE; +} + + +Bool +miIntersect(newReg, reg1, reg2) + register RegionPtr newReg; /* destination Region */ + register RegionPtr reg1; + register RegionPtr reg2; /* source regions */ +{ + good(reg1); + good(reg2); + good(newReg); + /* check for trivial reject */ + if (REGION_NIL(reg1) || REGION_NIL(reg2) || + !EXTENTCHECK(®1->extents, ®2->extents)) + { + /* Covers about 20% of all cases */ + xfreeData(newReg); + newReg->extents.x2 = newReg->extents.x1; + newReg->extents.y2 = newReg->extents.y1; + newReg->data = &miEmptyData; + } + else if (!reg1->data && !reg2->data) + { + /* Covers about 80% of cases that aren't trivially rejected */ + newReg->extents.x1 = max(reg1->extents.x1, reg2->extents.x1); + newReg->extents.y1 = max(reg1->extents.y1, reg2->extents.y1); + newReg->extents.x2 = min(reg1->extents.x2, reg2->extents.x2); + newReg->extents.y2 = min(reg1->extents.y2, reg2->extents.y2); + xfreeData(newReg); + newReg->data = (RegDataPtr)NULL; + } + else if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) + { + return miRegionCopy(newReg, reg1); + } + else if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) + { + return miRegionCopy(newReg, reg2); + } + else if (reg1 == reg2) + { + return miRegionCopy(newReg, reg1); + } + else + { + /* General purpose intersection */ + Bool overlap; /* result ignored */ + if (!miRegionOp(newReg, reg1, reg2, miIntersectO, FALSE, FALSE, + &overlap)) + return FALSE; + miSetExtents(newReg); + } + + good(newReg); + return(TRUE); +} + +#define MERGERECT(r) \ +{ \ + if (r->x1 <= x2) { \ + /* Merge with current rectangle */ \ + if (r->x1 < x2) *pOverlap = TRUE; \ + if (x2 < r->x2) x2 = r->x2; \ + } else { \ + /* Add current rectangle, start new one */ \ + NEWRECT(pReg, pNextRect, x1, y1, x2, y2); \ + x1 = r->x1; \ + x2 = r->x2; \ + } \ + r++; \ +} + +/*====================================================================== + * Region Union + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * miUnionO -- + * Handle an overlapping band for the union operation. Picks the + * left-most rectangle each time and merges it into the region. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * pReg is overwritten. + * pOverlap is set to TRUE if any boxes overlap. + * + *----------------------------------------------------------------------- + */ +static Bool +miUnionO (pReg, r1, r1End, r2, r2End, y1, y2, pOverlap) + register RegionPtr pReg; + register BoxPtr r1; + BoxPtr r1End; + register BoxPtr r2; + BoxPtr r2End; + short y1; + short y2; + Bool *pOverlap; +{ + register BoxPtr pNextRect; + register int x1; /* left and right side of current union */ + register int x2; + + assert (y1 < y2); + assert(r1 != r1End && r2 != r2End); + + pNextRect = REGION_TOP(pReg); + + /* Start off current rectangle */ + if (r1->x1 < r2->x1) + { + x1 = r1->x1; + x2 = r1->x2; + r1++; + } + else + { + x1 = r2->x1; + x2 = r2->x2; + r2++; + } + while (r1 != r1End && r2 != r2End) + { + if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2); + } + + /* Finish off whoever (if any) is left */ + if (r1 != r1End) + { + do + { + MERGERECT(r1); + } while (r1 != r1End); + } + else if (r2 != r2End) + { + do + { + MERGERECT(r2); + } while (r2 != r2End); + } + + /* Add current rectangle */ + NEWRECT(pReg, pNextRect, x1, y1, x2, y2); + + return TRUE; +} + +Bool +miUnion(newReg, reg1, reg2) + RegionPtr newReg; /* destination Region */ + register RegionPtr reg1; + register RegionPtr reg2; /* source regions */ +{ + Bool overlap; /* result ignored */ + + /* Return TRUE if some overlap between reg1, reg2 */ + good(reg1); + good(reg2); + good(newReg); + /* checks all the simple cases */ + + /* + * Region 1 and 2 are the same + */ + if (reg1 == reg2) + { + return miRegionCopy(newReg, reg1); + } + + /* + * Region 1 is empty + */ + if (REGION_NIL(reg1)) + { + if (newReg != reg2) + return miRegionCopy(newReg, reg2); + return TRUE; + } + + /* + * Region 2 is empty + */ + if (REGION_NIL(reg2)) + { + if (newReg != reg1) + return miRegionCopy(newReg, reg1); + return TRUE; + } + + /* + * Region 1 completely subsumes region 2 + */ + if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) + { + if (newReg != reg1) + return miRegionCopy(newReg, reg1); + return TRUE; + } + + /* + * Region 2 completely subsumes region 1 + */ + if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) + { + if (newReg != reg2) + return miRegionCopy(newReg, reg2); + return TRUE; + } + + if (!miRegionOp(newReg, reg1, reg2, miUnionO, TRUE, TRUE, &overlap)) + return FALSE; + + newReg->extents.x1 = min(reg1->extents.x1, reg2->extents.x1); + newReg->extents.y1 = min(reg1->extents.y1, reg2->extents.y1); + newReg->extents.x2 = max(reg1->extents.x2, reg2->extents.x2); + newReg->extents.y2 = max(reg1->extents.y2, reg2->extents.y2); + good(newReg); + return TRUE; +} + + +/*====================================================================== + * Batch Rectangle Union + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * miRegionAppend -- + * + * "Append" the rgn rectangles onto the end of dstrgn, maintaining + * knowledge of YX-banding when it's easy. Otherwise, dstrgn just + * becomes a non-y-x-banded random collection of rectangles, and not + * yet a true region. After a sequence of appends, the caller must + * call miRegionValidate to ensure that a valid region is constructed. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * dstrgn is modified if rgn has rectangles. + * + */ +Bool +miRegionAppend(dstrgn, rgn) + register RegionPtr dstrgn; + register RegionPtr rgn; +{ + int numRects, dnumRects, size; + BoxPtr new, old; + Bool prepend; + + if (!rgn->data && (dstrgn->data == &miEmptyData)) + { + dstrgn->extents = rgn->extents; + dstrgn->data = (RegDataPtr)NULL; + return TRUE; + } + + numRects = REGION_NUM_RECTS(rgn); + if (!numRects) + return TRUE; + prepend = FALSE; + size = numRects; + dnumRects = REGION_NUM_RECTS(dstrgn); + if (!dnumRects && (size < 200)) + size = 200; /* XXX pick numbers out of a hat */ + RECTALLOC(dstrgn, size); + old = REGION_RECTS(rgn); + if (!dnumRects) + dstrgn->extents = rgn->extents; + else if (dstrgn->extents.x2 > dstrgn->extents.x1) + { + register BoxPtr first, last; + + first = old; + last = REGION_BOXPTR(dstrgn) + (dnumRects - 1); + if ((first->y1 > last->y2) || + ((first->y1 == last->y1) && (first->y2 == last->y2) && + (first->x1 > last->x2))) + { + if (rgn->extents.x1 < dstrgn->extents.x1) + dstrgn->extents.x1 = rgn->extents.x1; + if (rgn->extents.x2 > dstrgn->extents.x2) + dstrgn->extents.x2 = rgn->extents.x2; + dstrgn->extents.y2 = rgn->extents.y2; + } + else + { + first = REGION_BOXPTR(dstrgn); + last = old + (numRects - 1); + if ((first->y1 > last->y2) || + ((first->y1 == last->y1) && (first->y2 == last->y2) && + (first->x1 > last->x2))) + { + prepend = TRUE; + if (rgn->extents.x1 < dstrgn->extents.x1) + dstrgn->extents.x1 = rgn->extents.x1; + if (rgn->extents.x2 > dstrgn->extents.x2) + dstrgn->extents.x2 = rgn->extents.x2; + dstrgn->extents.y1 = rgn->extents.y1; + } + else + dstrgn->extents.x2 = dstrgn->extents.x1; + } + } + if (prepend) + { + new = REGION_BOX(dstrgn, numRects); + if (dnumRects == 1) + *new = *REGION_BOXPTR(dstrgn); + else + memmove((char *)new,(char *)REGION_BOXPTR(dstrgn), + dnumRects * sizeof(BoxRec)); + new = REGION_BOXPTR(dstrgn); + } + else + new = REGION_BOXPTR(dstrgn) + dnumRects; + if (numRects == 1) + *new = *old; + else + memmove((char *)new, (char *)old, numRects * sizeof(BoxRec)); + dstrgn->data->numRects += numRects; + return TRUE; +} + + +#define ExchangeRects(a, b) \ +{ \ + BoxRec t; \ + t = rects[a]; \ + rects[a] = rects[b]; \ + rects[b] = t; \ +} + +static void +QuickSortRects(rects, numRects) + register BoxRec rects[]; + register int numRects; +{ + register int y1; + register int x1; + register int i, j; + register BoxPtr r; + + /* Always called with numRects > 1 */ + + do + { + if (numRects == 2) + { + if (rects[0].y1 > rects[1].y1 || + (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1)) + ExchangeRects(0, 1); + return; + } + + /* Choose partition element, stick in location 0 */ + ExchangeRects(0, numRects >> 1); + y1 = rects[0].y1; + x1 = rects[0].x1; + + /* Partition array */ + i = 0; + j = numRects; + do + { + r = &(rects[i]); + do + { + r++; + i++; + } while (i != numRects && + (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))); + r = &(rects[j]); + do + { + r--; + j--; + } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1)); + if (i < j) + ExchangeRects(i, j); + } while (i < j); + + /* Move partition element back to middle */ + ExchangeRects(0, j); + + /* Recurse */ + if (numRects-j-1 > 1) + QuickSortRects(&rects[j+1], numRects-j-1); + numRects = j; + } while (numRects > 1); +} + +/*- + *----------------------------------------------------------------------- + * miRegionValidate -- + * + * Take a ``region'' which is a non-y-x-banded random collection of + * rectangles, and compute a nice region which is the union of all the + * rectangles. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * The passed-in ``region'' may be modified. + * pOverlap set to TRUE if any retangles overlapped, else FALSE; + * + * Strategy: + * Step 1. Sort the rectangles into ascending order with primary key y1 + * and secondary key x1. + * + * Step 2. Split the rectangles into the minimum number of proper y-x + * banded regions. This may require horizontally merging + * rectangles, and vertically coalescing bands. With any luck, + * this step in an identity tranformation (ala the Box widget), + * or a coalescing into 1 box (ala Menus). + * + * Step 3. Merge the separate regions down to a single region by calling + * miUnion. Maximize the work each miUnion call does by using + * a binary merge. + * + *----------------------------------------------------------------------- + */ + +Bool +miRegionValidate(badreg, pOverlap) + RegionPtr badreg; + Bool *pOverlap; +{ + /* Descriptor for regions under construction in Step 2. */ + typedef struct { + RegionRec reg; + int prevBand; + int curBand; + } RegionInfo; + + int numRects; /* Original numRects for badreg */ + RegionInfo *ri; /* Array of current regions */ + int numRI; /* Number of entries used in ri */ + int sizeRI; /* Number of entries available in ri */ + int i; /* Index into rects */ + register int j; /* Index into ri */ + register RegionInfo *rit; /* &ri[j] */ + register RegionPtr reg; /* ri[j].reg */ + register BoxPtr box; /* Current box in rects */ + register BoxPtr riBox; /* Last box in ri[j].reg */ + register RegionPtr hreg; /* ri[j_half].reg */ + + *pOverlap = FALSE; + if (!badreg->data) + { + good(badreg); + return TRUE; + } + numRects = badreg->data->numRects; + if (!numRects) + { + good(badreg); + return TRUE; + } + if (badreg->extents.x1 < badreg->extents.x2) + { + if ((numRects) == 1) + { + xfreeData(badreg); + badreg->data = (RegDataPtr) NULL; + } + else + { + DOWNSIZE(badreg, numRects); + } + good(badreg); + return TRUE; + } + + /* Step 1: Sort the rects array into ascending (y1, x1) order */ + QuickSortRects(REGION_BOXPTR(badreg), numRects); + + /* Step 2: Scatter the sorted array into the minimum number of regions */ + + /* Set up the first region to be the first rectangle in badreg */ + /* Note that step 2 code will never overflow the ri[0].reg rects array */ + Must_have_memory = TRUE; /* XXX */ + ri = (RegionInfo *) xalloc(4 * sizeof(RegionInfo)); + Must_have_memory = FALSE; /* XXX */ + sizeRI = 4; + numRI = 1; + ri[0].prevBand = 0; + ri[0].curBand = 0; + ri[0].reg = *badreg; + box = REGION_BOXPTR(&ri[0].reg); + ri[0].reg.extents = *box; + ri[0].reg.data->numRects = 1; + + /* Now scatter rectangles into the minimum set of valid regions. If the + next rectangle to be added to a region would force an existing rectangle + in the region to be split up in order to maintain y-x banding, just + forget it. Try the next region. If it doesn't fit cleanly into any + region, make a new one. */ + + for (i = numRects; --i > 0;) + { + box++; + /* Look for a region to append box to */ + for (j = numRI, rit = ri; --j >= 0; rit++) + { + reg = &rit->reg; + riBox = REGION_END(reg); + + if (box->y1 == riBox->y1 && box->y2 == riBox->y2) + { + /* box is in same band as riBox. Merge or append it */ + if (box->x1 <= riBox->x2) + { + /* Merge it with riBox */ + if (box->x1 < riBox->x2) *pOverlap = TRUE; + if (box->x2 > riBox->x2) riBox->x2 = box->x2; + } + else + { + RECTALLOC(reg, 1); + *REGION_TOP(reg) = *box; + reg->data->numRects++; + } + goto NextRect; /* So sue me */ + } + else if (box->y1 >= riBox->y2) + { + /* Put box into new band */ + if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; + if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1; + Coalesce(reg, rit->prevBand, rit->curBand); + rit->curBand = reg->data->numRects; + RECTALLOC(reg, 1); + *REGION_TOP(reg) = *box; + reg->data->numRects++; + goto NextRect; + } + /* Well, this region was inappropriate. Try the next one. */ + } /* for j */ + + /* Uh-oh. No regions were appropriate. Create a new one. */ + if (sizeRI == numRI) + { + /* Oops, allocate space for new region information */ + sizeRI <<= 1; + Must_have_memory = TRUE; /* XXX */ + ri = (RegionInfo *) xrealloc(ri, sizeRI * sizeof(RegionInfo)); + Must_have_memory = FALSE; /* XXX */ + rit = &ri[numRI]; + } + numRI++; + rit->prevBand = 0; + rit->curBand = 0; + rit->reg.extents = *box; + rit->reg.data = (RegDataPtr)NULL; + miRectAlloc(&rit->reg, (i+numRI) / numRI); /* MUST force allocation */ +NextRect: ; + } /* for i */ + + /* Make a final pass over each region in order to Coalesce and set + extents.x2 and extents.y2 */ + + for (j = numRI, rit = ri; --j >= 0; rit++) + { + reg = &rit->reg; + riBox = REGION_END(reg); + reg->extents.y2 = riBox->y2; + if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; + Coalesce(reg, rit->prevBand, rit->curBand); + if (reg->data->numRects == 1) /* keep unions happy below */ + { + xfreeData(reg); + reg->data = (RegDataPtr)NULL; + } + } + + /* Step 3: Union all regions into a single region */ + while (numRI > 1) + { + int half = numRI/2; + for (j = numRI & 1; j < (half + (numRI & 1)); j++) + { + reg = &ri[j].reg; + hreg = &ri[j+half].reg; + miRegionOp(reg, reg, hreg, miUnionO, TRUE, TRUE, pOverlap); + if (hreg->extents.x1 < reg->extents.x1) + reg->extents.x1 = hreg->extents.x1; + if (hreg->extents.y1 < reg->extents.y1) + reg->extents.y1 = hreg->extents.y1; + if (hreg->extents.x2 > reg->extents.x2) + reg->extents.x2 = hreg->extents.x2; + if (hreg->extents.y2 > reg->extents.y2) + reg->extents.y2 = hreg->extents.y2; + xfreeData(hreg); + } + numRI -= half; + } + *badreg = ri[0].reg; + xfree(ri); + good(badreg); + return TRUE; +} + +RegionPtr +miRectsToRegion(nrects, prect, ctype) + int nrects; + register xRectangle *prect; + int ctype; +{ + register RegionPtr pRgn; + register RegDataPtr pData; + register BoxPtr pBox; + register int i; + int x1, y1, x2, y2; + + pRgn = miRegionCreate(NullBox, 0); + if (!nrects) + return pRgn; + if (nrects == 1) + { + x1 = prect->x; + y1 = prect->y; + if ((x2 = x1 + (int) prect->width) > MAXSHORT) + x2 = MAXSHORT; + if ((y2 = y1 + (int) prect->height) > MAXSHORT) + y2 = MAXSHORT; + if (x1 != x2 && y1 != y2) + { + pRgn->extents.x1 = x1; + pRgn->extents.y1 = y1; + pRgn->extents.x2 = x2; + pRgn->extents.y2 = y2; + pRgn->data = (RegDataPtr)NULL; + } + return pRgn; + } + Must_have_memory = TRUE; /* XXX */ + pData = xallocData(nrects); + pBox = (BoxPtr) (pData + 1); + Must_have_memory = FALSE; /* XXX */ + for (i = nrects; --i >= 0; prect++) + { + x1 = prect->x; + y1 = prect->y; + if ((x2 = x1 + (int) prect->width) > MAXSHORT) + x2 = MAXSHORT; + if ((y2 = y1 + (int) prect->height) > MAXSHORT) + y2 = MAXSHORT; + if (x1 != x2 && y1 != y2) + { + pBox->x1 = x1; + pBox->y1 = y1; + pBox->x2 = x2; + pBox->y2 = y2; + pBox++; + } + } + if (pBox != (BoxPtr) (pData + 1)) + { + pData->size = nrects; + pData->numRects = pBox - (BoxPtr) (pData + 1); + pRgn->data = pData; + if (ctype != CT_YXBANDED) + { + Bool overlap; /* result ignored */ + pRgn->extents.x1 = pRgn->extents.x2 = 0; + miRegionValidate(pRgn, &overlap); + } + else + miSetExtents(pRgn); + good(pRgn); + } + else + { + xfree (pData); + } + return pRgn; +} + +/*====================================================================== + * Region Subtraction + *====================================================================*/ + + +/*- + *----------------------------------------------------------------------- + * miSubtractO -- + * Overlapping band subtraction. x1 is the left-most point not yet + * checked. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * pReg may have rectangles added to it. + * + *----------------------------------------------------------------------- + */ +/*ARGSUSED*/ +static Bool +miSubtractO (pReg, r1, r1End, r2, r2End, y1, y2, pOverlap) + register RegionPtr pReg; + register BoxPtr r1; + BoxPtr r1End; + register BoxPtr r2; + BoxPtr r2End; + register int y1; + int y2; + Bool *pOverlap; +{ + register BoxPtr pNextRect; + register int x1; + + x1 = r1->x1; + + assert(y1x2 <= x1) + { + /* + * Subtrahend entirely to left of minuend: go to next subtrahend. + */ + r2++; + } + else if (r2->x1 <= x1) + { + /* + * Subtrahend preceeds minuend: nuke left edge of minuend. + */ + x1 = r2->x2; + if (x1 >= r1->x2) + { + /* + * Minuend completely covered: advance to next minuend and + * reset left fence to edge of new minuend. + */ + r1++; + if (r1 != r1End) + x1 = r1->x1; + } + else + { + /* + * Subtrahend now used up since it doesn't extend beyond + * minuend + */ + r2++; + } + } + else if (r2->x1 < r1->x2) + { + /* + * Left part of subtrahend covers part of minuend: add uncovered + * part of minuend to region and skip to next subtrahend. + */ + assert(x1x1); + NEWRECT(pReg, pNextRect, x1, y1, r2->x1, y2); + + x1 = r2->x2; + if (x1 >= r1->x2) + { + /* + * Minuend used up: advance to new... + */ + r1++; + if (r1 != r1End) + x1 = r1->x1; + } + else + { + /* + * Subtrahend used up + */ + r2++; + } + } + else + { + /* + * Minuend used up: add any remaining piece before advancing. + */ + if (r1->x2 > x1) + NEWRECT(pReg, pNextRect, x1, y1, r1->x2, y2); + r1++; + if (r1 != r1End) + x1 = r1->x1; + } + } while ((r1 != r1End) && (r2 != r2End)); + + + /* + * Add remaining minuend rectangles to region. + */ + while (r1 != r1End) + { + assert(x1x2); + NEWRECT(pReg, pNextRect, x1, y1, r1->x2, y2); + r1++; + if (r1 != r1End) + x1 = r1->x1; + } + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * miSubtract -- + * Subtract regS from regM and leave the result in regD. + * S stands for subtrahend, M for minuend and D for difference. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * regD is overwritten. + * + *----------------------------------------------------------------------- + */ +Bool +miSubtract(regD, regM, regS) + register RegionPtr regD; + register RegionPtr regM; + register RegionPtr regS; +{ + Bool overlap; /* result ignored */ + + good(regM); + good(regS); + good(regD); + /* check for trivial rejects */ + if (REGION_NIL(regM) || REGION_NIL(regS) || + !EXTENTCHECK(®M->extents, ®S->extents)) + { + return miRegionCopy(regD, regM); + } + else if (regM == regS) + { + xfreeData(regD); + regD->extents.x2 = regD->extents.x1; + regD->extents.y2 = regD->extents.y1; + regD->data = &miEmptyData; + return TRUE; + } + + /* Add those rectangles in region 1 that aren't in region 2, + do yucky substraction for overlaps, and + just throw away rectangles in region 2 that aren't in region 1 */ + if (!miRegionOp(regD, regM, regS, miSubtractO, TRUE, FALSE, &overlap)) + return FALSE; + + /* + * Can't alter RegD's extents before we call miRegionOp because + * it might be one of the source regions and miRegionOp depends + * on the extents of those regions being unaltered. Besides, this + * way there's no checking against rectangles that will be nuked + * due to coalescing, so we have to examine fewer rectangles. + */ + miSetExtents(regD); + good(regD); + return TRUE; +} + +/*====================================================================== + * Region Inversion + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * miInverse -- + * Take a region and a box and return a region that is everything + * in the box but not in the region. The careful reader will note + * that this is the same as subtracting the region from the box... + * + * Results: + * TRUE. + * + * Side Effects: + * newReg is overwritten. + * + *----------------------------------------------------------------------- + */ +Bool +miInverse(newReg, reg1, invRect) + RegionPtr newReg; /* Destination region */ + RegionPtr reg1; /* Region to invert */ + BoxPtr invRect; /* Bounding box for inversion */ +{ + RegionRec invReg; /* Quick and dirty region made from the + * bounding box */ + Bool overlap; /* result ignored */ + + good(reg1); + good(newReg); + /* check for trivial rejects */ + if (REGION_NIL(reg1) || !EXTENTCHECK(invRect, ®1->extents)) + { + newReg->extents = *invRect; + xfreeData(newReg); + newReg->data = (RegDataPtr)NULL; + return TRUE; + } + + /* Add those rectangles in region 1 that aren't in region 2, + do yucky substraction for overlaps, and + just throw away rectangles in region 2 that aren't in region 1 */ + invReg.extents = *invRect; + invReg.data = (RegDataPtr)NULL; + if (!miRegionOp(newReg, &invReg, reg1, miSubtractO, TRUE, FALSE, &overlap)) + return FALSE; + + /* + * Can't alter newReg's extents before we call miRegionOp because + * it might be one of the source regions and miRegionOp depends + * on the extents of those regions being unaltered. Besides, this + * way there's no checking against rectangles that will be nuked + * due to coalescing, so we have to examine fewer rectangles. + */ + miSetExtents(newReg); + good(newReg); + return TRUE; +} + +/* + * RectIn(region, rect) + * This routine takes a pointer to a region and a pointer to a box + * and determines if the box is outside/inside/partly inside the region. + * + * The idea is to travel through the list of rectangles trying to cover the + * passed box with them. Anytime a piece of the rectangle isn't covered + * by a band of rectangles, partOut is set TRUE. Any time a rectangle in + * the region covers part of the box, partIn is set TRUE. The process ends + * when either the box has been completely covered (we reached a band that + * doesn't overlap the box, partIn is TRUE and partOut is false), the + * box has been partially covered (partIn == partOut == TRUE -- because of + * the banding, the first time this is true we know the box is only + * partially in the region) or is outside the region (we reached a band + * that doesn't overlap the box at all and partIn is false) + */ + +int +miRectIn(region, prect) + register RegionPtr region; + register BoxPtr prect; +{ + register int x; + register int y; + register BoxPtr pbox; + register BoxPtr pboxEnd; + int partIn, partOut; + int numRects; + + good(region); + numRects = REGION_NUM_RECTS(region); + /* useful optimization */ + if (!numRects || !EXTENTCHECK(®ion->extents, prect)) + return(rgnOUT); + + if (numRects == 1) + { + /* We know that it must be rgnIN or rgnPART */ + if (SUBSUMES(®ion->extents, prect)) + return(rgnIN); + else + return(rgnPART); + } + + partOut = FALSE; + partIn = FALSE; + + /* (x,y) starts at upper left of rect, moving to the right and down */ + x = prect->x1; + y = prect->y1; + + /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ + for (pbox = REGION_BOXPTR(region), pboxEnd = pbox + numRects; + pbox != pboxEnd; + pbox++) + { + + if (pbox->y2 <= y) + continue; /* getting up to speed or skipping remainder of band */ + + if (pbox->y1 > y) + { + partOut = TRUE; /* missed part of rectangle above */ + if (partIn || (pbox->y1 >= prect->y2)) + break; + y = pbox->y1; /* x guaranteed to be == prect->x1 */ + } + + if (pbox->x2 <= x) + continue; /* not far enough over yet */ + + if (pbox->x1 > x) + { + partOut = TRUE; /* missed part of rectangle to left */ + if (partIn) + break; + } + + if (pbox->x1 < prect->x2) + { + partIn = TRUE; /* definitely overlap */ + if (partOut) + break; + } + + if (pbox->x2 >= prect->x2) + { + y = pbox->y2; /* finished with this band */ + if (y >= prect->y2) + break; + x = prect->x1; /* reset x out to left again */ + } + else + { + /* + * Because boxes in a band are maximal width, if the first box + * to overlap the rectangle doesn't completely cover it in that + * band, the rectangle must be partially out, since some of it + * will be uncovered in that band. partIn will have been set true + * by now... + */ + partOut = TRUE; + break; + } + } + + return(partIn ? ((y < prect->y2) ? rgnPART : rgnIN) : rgnOUT); +} + +/* TranslateRegion(pReg, x, y) + translates in place +*/ + +void +miTranslateRegion(pReg, x, y) + register RegionPtr pReg; + register int x; + register int y; +{ + int x1, x2, y1, y2; + register int nbox; + register BoxPtr pbox; + + good(pReg); + pReg->extents.x1 = x1 = pReg->extents.x1 + x; + pReg->extents.y1 = y1 = pReg->extents.y1 + y; + pReg->extents.x2 = x2 = pReg->extents.x2 + x; + pReg->extents.y2 = y2 = pReg->extents.y2 + y; + if (((x1 - MINSHORT)|(y1 - MINSHORT)|(MAXSHORT - x2)|(MAXSHORT - y2)) >= 0) + { + if (pReg->data && (nbox = pReg->data->numRects)) + { + for (pbox = REGION_BOXPTR(pReg); nbox--; pbox++) + { + pbox->x1 += x; + pbox->y1 += y; + pbox->x2 += x; + pbox->y2 += y; + } + } + return; + } + if (((x2 - MINSHORT)|(y2 - MINSHORT)|(MAXSHORT - x1)|(MAXSHORT - y1)) <= 0) + { + pReg->extents.x2 = pReg->extents.x1; + pReg->extents.y2 = pReg->extents.y1; + xfreeData(pReg); + pReg->data = &miEmptyData; + return; + } + if (x1 < MINSHORT) + pReg->extents.x1 = MINSHORT; + else if (x2 > MAXSHORT) + pReg->extents.x2 = MAXSHORT; + if (y1 < MINSHORT) + pReg->extents.y1 = MINSHORT; + else if (y2 > MAXSHORT) + pReg->extents.y2 = MAXSHORT; + if (pReg->data && (nbox = pReg->data->numRects)) + { + register BoxPtr pboxout; + + for (pboxout = pbox = REGION_BOXPTR(pReg); nbox--; pbox++) + { + pboxout->x1 = x1 = pbox->x1 + x; + pboxout->y1 = y1 = pbox->y1 + y; + pboxout->x2 = x2 = pbox->x2 + x; + pboxout->y2 = y2 = pbox->y2 + y; + if (((x2 - MINSHORT)|(y2 - MINSHORT)| + (MAXSHORT - x1)|(MAXSHORT - y1)) <= 0) + { + pReg->data->numRects--; + continue; + } + if (x1 < MINSHORT) + pboxout->x1 = MINSHORT; + else if (x2 > MAXSHORT) + pboxout->x2 = MAXSHORT; + if (y1 < MINSHORT) + pboxout->y1 = MINSHORT; + else if (y2 > MAXSHORT) + pboxout->y2 = MAXSHORT; + pboxout++; + } + if (pboxout != pbox) + { + if (pReg->data->numRects == 1) + { + pReg->extents = *REGION_BOXPTR(pReg); + xfreeData(pReg); + pReg->data = (RegDataPtr)NULL; + } + else + miSetExtents(pReg); + } + } +} + +void +miRegionReset(pReg, pBox) + RegionPtr pReg; + BoxPtr pBox; +{ + good(pReg); + assert(pBox->x1<=pBox->x2); + assert(pBox->y1<=pBox->y2); + pReg->extents = *pBox; + xfreeData(pReg); + pReg->data = (RegDataPtr)NULL; +} + +Bool +miPointInRegion(pReg, x, y, box) + register RegionPtr pReg; + register int x, y; + BoxPtr box; /* "return" value */ +{ + register BoxPtr pbox, pboxEnd; + int numRects; + + good(pReg); + numRects = REGION_NUM_RECTS(pReg); + if (!numRects || !INBOX(&pReg->extents, x, y)) + return(FALSE); + if (numRects == 1) + { + *box = pReg->extents; + return(TRUE); + } + for (pbox = REGION_BOXPTR(pReg), pboxEnd = pbox + numRects; + pbox != pboxEnd; + pbox++) + { + if (y >= pbox->y2) + continue; /* not there yet */ + if ((y < pbox->y1) || (x < pbox->x1)) + break; /* missed it */ + if (x >= pbox->x2) + continue; /* not there yet */ + *box = *pbox; + return(TRUE); + } + return(FALSE); +} + +Bool +miRegionNotEmpty(pReg) + RegionPtr pReg; +{ + good(pReg); + return(!REGION_NIL(pReg)); +} + + +void +miRegionEmpty(pReg) + RegionPtr pReg; +{ + good(pReg); + xfreeData(pReg); + pReg->extents.x2 = pReg->extents.x1; + pReg->extents.y2 = pReg->extents.y1; + pReg->data = &miEmptyData; +} + +BoxPtr +miRegionExtents(pReg) + RegionPtr pReg; +{ + good(pReg); + return(&pReg->extents); +} + +#define ExchangeSpans(a, b) \ +{ \ + DDXPointRec tpt; \ + register int tw; \ + \ + tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ + tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ +} + +/* ||| I should apply the merge sort code to rectangle sorting above, and see + if mapping time can be improved. But right now I've been at work 12 hours, + so forget it. +*/ + +static void QuickSortSpans(spans, widths, numSpans) + register DDXPointRec spans[]; + register int widths[]; + register int numSpans; +{ + register int y; + register int i, j, m; + register DDXPointPtr r; + + /* Always called with numSpans > 1 */ + /* Sorts only by y, doesn't bother to sort by x */ + + do + { + if (numSpans < 9) + { + /* Do insertion sort */ + register int yprev; + + yprev = spans[0].y; + i = 1; + do + { /* while i != numSpans */ + y = spans[i].y; + if (yprev > y) + { + /* spans[i] is out of order. Move into proper location. */ + DDXPointRec tpt; + int tw, k; + + for (j = 0; y >= spans[j].y; j++) {} + tpt = spans[i]; + tw = widths[i]; + for (k = i; k != j; k--) + { + spans[k] = spans[k-1]; + widths[k] = widths[k-1]; + } + spans[j] = tpt; + widths[j] = tw; + y = spans[i].y; + } /* if out of order */ + yprev = y; + i++; + } while (i != numSpans); + return; + } + + /* Choose partition element, stick in location 0 */ + m = numSpans / 2; + if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); + if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); + if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); + y = spans[0].y; + + /* Partition array */ + i = 0; + j = numSpans; + do + { + r = &(spans[i]); + do + { + r++; + i++; + } while (i != numSpans && r->y < y); + r = &(spans[j]); + do + { + r--; + j--; + } while (y < r->y); + if (i < j) + ExchangeSpans(i, j); + } while (i < j); + + /* Move partition element back to middle */ + ExchangeSpans(0, j); + + /* Recurse */ + if (numSpans-j-1 > 1) + QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); + numSpans = j; + } while (numSpans > 1); +} + +#define NextBand() \ +{ \ + clipy1 = pboxBandStart->y1; \ + clipy2 = pboxBandStart->y2; \ + pboxBandEnd = pboxBandStart + 1; \ + while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \ + pboxBandEnd++; \ + } \ + for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \ +} + +/* + Clip a list of scanlines to a region. The caller has allocated the + space. FSorted is non-zero if the scanline origins are in ascending + order. + returns the number of new, clipped scanlines. +*/ + +int +miClipSpans(prgnDst, ppt, pwidth, nspans, pptNew, pwidthNew, fSorted) + RegionPtr prgnDst; + register DDXPointPtr ppt; + register int *pwidth; + int nspans; + register DDXPointPtr pptNew; + int *pwidthNew; + int fSorted; +{ + register DDXPointPtr pptLast; + int *pwidthNewStart; /* the vengeance of Xerox! */ + register int y, x1, x2; + register int numRects; + + good(prgnDst); + pptLast = ppt + nspans; + pwidthNewStart = pwidthNew; + + if (!prgnDst->data) + { + /* Do special fast code with clip boundaries in registers(?) */ + /* It doesn't pay much to make use of fSorted in this case, + so we lump everything together. */ + + register int clipx1, clipx2, clipy1, clipy2; + + clipx1 = prgnDst->extents.x1; + clipy1 = prgnDst->extents.y1; + clipx2 = prgnDst->extents.x2; + clipy2 = prgnDst->extents.y2; + + for (; ppt != pptLast; ppt++, pwidth++) + { + y = ppt->y; + x1 = ppt->x; + if (clipy1 <= y && y < clipy2) + { + x2 = x1 + *pwidth; + if (x1 < clipx1) x1 = clipx1; + if (x2 > clipx2) x2 = clipx2; + if (x1 < x2) + { + /* part of span in clip rectangle */ + pptNew->x = x1; + pptNew->y = y; + *pwidthNew = x2 - x1; + pptNew++; + pwidthNew++; + } + } + } /* end for */ + + } + else if (numRects = prgnDst->data->numRects) + { + /* Have to clip against many boxes */ + BoxPtr pboxBandStart, pboxBandEnd; + register BoxPtr pbox; + register BoxPtr pboxLast; + register int clipy1, clipy2; + + /* In this case, taking advantage of sorted spans gains more than + the sorting costs. */ + if ((! fSorted) && (nspans > 1)) + QuickSortSpans(ppt, pwidth, nspans); + + pboxBandStart = REGION_BOXPTR(prgnDst); + pboxLast = pboxBandStart + numRects; + + NextBand(); + + for (; ppt != pptLast; ) + { + y = ppt->y; + if (y < clipy2) + { + /* span is in the current band */ + pbox = pboxBandStart; + x1 = ppt->x; + x2 = x1 + *pwidth; + do + { /* For each box in band */ + register int newx1, newx2; + + newx1 = x1; + newx2 = x2; + if (newx1 < pbox->x1) newx1 = pbox->x1; + if (newx2 > pbox->x2) newx2 = pbox->x2; + if (newx1 < newx2) + { + /* Part of span in clip rectangle */ + pptNew->x = newx1; + pptNew->y = y; + *pwidthNew = newx2 - newx1; + pptNew++; + pwidthNew++; + } + pbox++; + } while (pbox != pboxBandEnd); + ppt++; + pwidth++; + } + else + { + /* Move to next band, adjust ppt as needed */ + pboxBandStart = pboxBandEnd; + if (pboxBandStart == pboxLast) + break; /* We're completely done */ + NextBand(); + } + } + } + return (pwidthNew - pwidthNewStart); +} + +/* find the band in a region with the most rectangles */ +int +miFindMaxBand(prgn) + RegionPtr prgn; +{ + register int nbox; + register BoxPtr pbox; + register int nThisBand; + register int nMaxBand = 0; + short yThisBand; + + good(prgn); + nbox = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + + while(nbox > 0) + { + yThisBand = pbox->y1; + nThisBand = 0; + while((nbox > 0) && (pbox->y1 == yThisBand)) + { + nbox--; + pbox++; + nThisBand++; + } + if (nThisBand > nMaxBand) + nMaxBand = nThisBand; + } + return (nMaxBand); +} diff --git a/mi/miscanfill.h b/mi/miscanfill.h new file mode 100644 index 000000000..06baee399 --- /dev/null +++ b/mi/miscanfill.h @@ -0,0 +1,144 @@ +/* $Xorg: miscanfill.h,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +#ifndef SCANFILLINCLUDED +#define SCANFILLINCLUDED +/* + * scanfill.h + * + * Written by Brian Kelleher; Jan 1985 + * + * This file contains a few macros to help track + * the edge of a filled object. The object is assumed + * to be filled in scanline order, and thus the + * algorithm used is an extension of Bresenham's line + * drawing algorithm which assumes that y is always the + * major axis. + * Since these pieces of code are the same for any filled shape, + * it is more convenient to gather the library in one + * place, but since these pieces of code are also in + * the inner loops of output primitives, procedure call + * overhead is out of the question. + * See the author for a derivation if needed. + */ + + +/* + * In scan converting polygons, we want to choose those pixels + * which are inside the polygon. Thus, we add .5 to the starting + * x coordinate for both left and right edges. Now we choose the + * first pixel which is inside the pgon for the left edge and the + * first pixel which is outside the pgon for the right edge. + * Draw the left pixel, but not the right. + * + * How to add .5 to the starting x coordinate: + * If the edge is moving to the right, then subtract dy from the + * error term from the general form of the algorithm. + * If the edge is moving to the left, then add dy to the error term. + * + * The reason for the difference between edges moving to the left + * and edges moving to the right is simple: If an edge is moving + * to the right, then we want the algorithm to flip immediately. + * If it is moving to the left, then we don't want it to flip until + * we traverse an entire pixel. + */ +#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \ + int dx; /* local storage */ \ +\ + /* \ + * if the edge is horizontal, then it is ignored \ + * and assumed not to be processed. Otherwise, do this stuff. \ + */ \ + if ((dy) != 0) { \ + xStart = (x1); \ + dx = (x2) - xStart; \ + if (dx < 0) { \ + m = dx / (dy); \ + m1 = m - 1; \ + incr1 = -2 * dx + 2 * (dy) * m1; \ + incr2 = -2 * dx + 2 * (dy) * m; \ + d = 2 * m * (dy) - 2 * dx - 2 * (dy); \ + } else { \ + m = dx / (dy); \ + m1 = m + 1; \ + incr1 = 2 * dx - 2 * (dy) * m1; \ + incr2 = 2 * dx - 2 * (dy) * m; \ + d = -2 * m * (dy) + 2 * dx; \ + } \ + } \ +} + +#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \ + if (m1 > 0) { \ + if (d > 0) { \ + minval += m1; \ + d += incr1; \ + } \ + else { \ + minval += m; \ + d += incr2; \ + } \ + } else {\ + if (d >= 0) { \ + minval += m1; \ + d += incr1; \ + } \ + else { \ + minval += m; \ + d += incr2; \ + } \ + } \ +} + + +/* + * This structure contains all of the information needed + * to run the bresenham algorithm. + * The variables may be hardcoded into the declarations + * instead of using this structure to make use of + * register declarations. + */ +typedef struct { + int minor; /* minor axis */ + int d; /* decision variable */ + int m, m1; /* slope and slope+1 */ + int incr1, incr2; /* error increments */ +} BRESINFO; + + +#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \ + BRESINITPGON(dmaj, min1, min2, bres.minor, bres.d, \ + bres.m, bres.m1, bres.incr1, bres.incr2) + +#define BRESINCRPGONSTRUCT(bres) \ + BRESINCRPGON(bres.d, bres.minor, bres.m, bres.m1, bres.incr1, bres.incr2) + + +#endif diff --git a/mi/miscrinit.c b/mi/miscrinit.c new file mode 100644 index 000000000..1561c1844 --- /dev/null +++ b/mi/miscrinit.c @@ -0,0 +1,288 @@ +/* $Xorg: miscrinit.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#include "servermd.h" +#include "misc.h" +#include "mi.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mibstore.h" +#include "dix.h" +#include "miline.h" + +/* We use this structure to propogate some information from miScreenInit to + * miCreateScreenResources. miScreenInit allocates the structure, fills it + * in, and puts it into pScreen->devPrivate. miCreateScreenResources + * extracts the info and frees the structure. We could've accomplished the + * same thing by adding fields to the screen structure, but they would have + * ended up being redundant, and would have exposed this mi implementation + * detail to the whole server. + */ + +typedef struct +{ + pointer pbits; /* pointer to framebuffer */ + int width; /* delta to add to a framebuffer addr to move one row down */ +} miScreenInitParmsRec, *miScreenInitParmsPtr; + + +/* this plugs into pScreen->ModifyPixmapHeader */ +Bool +miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, + pPixData) + PixmapPtr pPixmap; + int width; + int height; + int depth; + int bitsPerPixel; + int devKind; + pointer pPixData; +{ + if (!pPixmap) + return FALSE; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bitsPerPixel; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = devKind; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = pPixData; + return TRUE; +} + + +/*ARGSUSED*/ +Bool +miCloseScreen (index, pScreen) + int index; + ScreenPtr pScreen; +{ + return ((*pScreen->DestroyPixmap)((PixmapPtr)pScreen->devPrivate)); +} + +/* With the introduction of pixmap privates, the "screen pixmap" can no + * longer be created in miScreenInit, since all the modules that could + * possibly ask for pixmap private space have not been initialized at + * that time. pScreen->CreateScreenResources is called after all + * possible private-requesting modules have been inited; we create the + * screen pixmap here. + */ +Bool +miCreateScreenResources(pScreen) + ScreenPtr pScreen; +{ + miScreenInitParmsPtr pScrInitParms; + pointer value; + + pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; + + /* if width is non-zero, pScreen->devPrivate will be a pixmap + * else it will just take the value pbits + */ + if (pScrInitParms->width) + { + PixmapPtr pPixmap; + + /* create a pixmap with no data, then redirect it to point to + * the screen + */ + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); + if (!pPixmap) + return FALSE; + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width, + pScreen->height, pScreen->rootDepth, pScreen->rootDepth, + PixmapBytePad(pScrInitParms->width, pScreen->rootDepth), + pScrInitParms->pbits)) + return FALSE; + value = (pointer)pPixmap; + } + else + { + value = pScrInitParms->pbits; + } + xfree(pScreen->devPrivate); /* freeing miScreenInitParmsRec */ + pScreen->devPrivate = value; /* pPixmap or pbits */ + return TRUE; +} + +Bool +miScreenDevPrivateInit(pScreen, width, pbits) + register ScreenPtr pScreen; + int width; + pointer pbits; +{ + miScreenInitParmsPtr pScrInitParms; + + /* Stash pbits and width in a short-lived miScreenInitParmsRec attached + * to the screen, until CreateScreenResources can put them in the + * screen pixmap. + */ + pScrInitParms = (miScreenInitParmsPtr)xalloc(sizeof(miScreenInitParmsRec)); + if (!pScrInitParms) + return FALSE; + pScrInitParms->pbits = pbits; + pScrInitParms->width = width; + pScreen->devPrivate = (pointer)pScrInitParms; + return TRUE; +} + +/* + * If you pass in bsfuncs, then you must preinitialize the missing + * screen procs before calling miScreenInit, so that the backing store + * code can correctly wrap them. + */ + +Bool +miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width, + rootDepth, numDepths, depths, rootVisual, numVisuals, visuals, + bsfuncs) + register ScreenPtr pScreen; + pointer pbits; /* pointer to screen bits */ + int xsize, ysize; /* in pixels */ + int dpix, dpiy; /* dots per inch */ + int width; /* pixel width of frame buffer */ + int rootDepth; /* depth of root window */ + int numDepths; /* number of depths supported */ + DepthRec *depths; /* supported depths */ + VisualID rootVisual; /* root visual */ + int numVisuals; /* number of visuals supported */ + VisualRec *visuals; /* supported visuals */ + miBSFuncPtr bsfuncs; /* backing store functions */ +{ + pScreen->width = xsize; + pScreen->height = ysize; + pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10); + pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10); + pScreen->numDepths = numDepths; + pScreen->rootDepth = rootDepth; + pScreen->allowedDepths = depths; + pScreen->rootVisual = rootVisual; + /* defColormap */ + pScreen->minInstalledCmaps = 1; + pScreen->maxInstalledCmaps = 1; + pScreen->backingStoreSupport = Always; + pScreen->saveUnderSupport = NotUseful; + /* whitePixel, blackPixel */ + pScreen->ModifyPixmapHeader = miModifyPixmapHeader; + pScreen->CreateScreenResources = miCreateScreenResources; + pScreen->numVisuals = numVisuals; + pScreen->visuals = visuals; + if (width) + { +#ifdef MITSHM + ShmRegisterFbFuncs(pScreen); +#endif + pScreen->CloseScreen = miCloseScreen; + } + /* else CloseScreen */ + /* QueryBestSize, SaveScreen, GetImage, GetSpans */ + pScreen->PointerNonInterestBox = (void (*)()) 0; + pScreen->SourceValidate = (void (*)()) 0; + /* CreateWindow, DestroyWindow, PositionWindow, ChangeWindowAttributes */ + /* RealizeWindow, UnrealizeWindow */ + pScreen->ValidateTree = miValidateTree; + pScreen->PostValidateTree = (void (*)()) 0; + pScreen->WindowExposures = miWindowExposures; + /* PaintWindowBackground, PaintWindowBorder, CopyWindow */ + pScreen->ClearToBackground = miClearToBackground; + pScreen->ClipNotify = (void (*)()) 0; + /* CreatePixmap, DestroyPixmap */ + /* RealizeFont, UnrealizeFont */ + /* CreateGC */ + /* CreateColormap, DestroyColormap, InstallColormap, UninstallColormap */ + /* ListInstalledColormaps, StoreColors, ResolveColor */ + pScreen->RegionCreate = miRegionCreate; + pScreen->RegionInit = miRegionInit; + pScreen->RegionCopy = miRegionCopy; + pScreen->RegionDestroy = miRegionDestroy; + pScreen->RegionUninit = miRegionUninit; + pScreen->Intersect = miIntersect; + pScreen->Union = miUnion; + pScreen->Subtract = miSubtract; + pScreen->Inverse = miInverse; + pScreen->RegionReset = miRegionReset; + pScreen->TranslateRegion = miTranslateRegion; + pScreen->RectIn = miRectIn; + pScreen->PointInRegion = miPointInRegion; + pScreen->RegionNotEmpty = miRegionNotEmpty; + pScreen->RegionEmpty = miRegionEmpty; + pScreen->RegionExtents = miRegionExtents; + pScreen->RegionAppend = miRegionAppend; + pScreen->RegionValidate = miRegionValidate; + /* BitmapToRegion */ + pScreen->RectsToRegion = miRectsToRegion; + pScreen->SendGraphicsExpose = miSendGraphicsExpose; + pScreen->BlockHandler = (void (*)())NoopDDA; + pScreen->WakeupHandler = (void (*)())NoopDDA; + pScreen->blockData = (pointer)0; + pScreen->wakeupData = (pointer)0; + if (bsfuncs) + miInitializeBackingStore (pScreen, bsfuncs); + pScreen->MarkWindow = miMarkWindow; + pScreen->MarkOverlappedWindows = miMarkOverlappedWindows; + pScreen->ChangeSaveUnder = miChangeSaveUnder; + pScreen->PostChangeSaveUnder = miPostChangeSaveUnder; + pScreen->MoveWindow = miMoveWindow; + pScreen->ResizeWindow = miSlideAndSizeWindow; + pScreen->GetLayerWindow = miGetLayerWindow; + pScreen->HandleExposures = miHandleValidateExposures; + pScreen->ReparentWindow = (void (*)())0; + pScreen->ChangeBorderWidth = miChangeBorderWidth; +#ifdef SHAPE + pScreen->SetShape = miSetShape; +#endif + pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow; + + miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS); + + return miScreenDevPrivateInit(pScreen, width, pbits); +} + +int miZeroLineScreenIndex; +int miZeroLineGeneration; + +void +miSetZeroLineBias(pScreen, bias) + ScreenPtr pScreen; + unsigned int bias; +{ + if (miZeroLineGeneration != serverGeneration) + { + miZeroLineScreenIndex = AllocateScreenPrivateIndex(); + miZeroLineGeneration = serverGeneration; + } + if (miZeroLineScreenIndex >= 0) + pScreen->devPrivates[miZeroLineScreenIndex].uval = bias; +} diff --git a/mi/mispans.c b/mi/mispans.c new file mode 100644 index 000000000..562b843ce --- /dev/null +++ b/mi/mispans.c @@ -0,0 +1,554 @@ +/*********************************************************** + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: mispans.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +#include "misc.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "mispans.h" + +/* + +These routines maintain lists of Spans, in order to implement the +``touch-each-pixel-once'' rules of wide lines and arcs. + +Written by Joel McCormack, Summer 1989. + +*/ + + +void miInitSpanGroup(spanGroup) + SpanGroup *spanGroup; +{ + spanGroup->size = 0; + spanGroup->count = 0; + spanGroup->group = NULL; + spanGroup->ymin = MAXSHORT; + spanGroup->ymax = MINSHORT; +} /* InitSpanGroup */ + +#define YMIN(spans) (spans->points[0].y) +#define YMAX(spans) (spans->points[spans->count-1].y) + +void miSubtractSpans (spanGroup, sub) + SpanGroup *spanGroup; + Spans *sub; +{ + int i, subCount, spansCount; + int ymin, ymax, xmin, xmax; + Spans *spans; + DDXPointPtr subPt, spansPt; + int *subWid, *spansWid; + int extra; + + ymin = YMIN(sub); + ymax = YMAX(sub); + spans = spanGroup->group; + for (i = spanGroup->count; i; i--, spans++) { + if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) { + subCount = sub->count; + subPt = sub->points; + subWid = sub->widths; + spansCount = spans->count; + spansPt = spans->points; + spansWid = spans->widths; + extra = 0; + for (;;) + { + while (spansCount && spansPt->y < subPt->y) + { + spansPt++; spansWid++; spansCount--; + } + if (!spansCount) + break; + while (subCount && subPt->y < spansPt->y) + { + subPt++; subWid++; subCount--; + } + if (!subCount) + break; + if (subPt->y == spansPt->y) + { + xmin = subPt->x; + xmax = xmin + *subWid; + if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax) + { + ; + } + else if (xmin <= spansPt->x) + { + if (xmax >= spansPt->x + *spansWid) + { + memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1)); + memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1)); + spansPt--; + spansWid--; + spans->count--; + extra++; + } + else + { + *spansWid = *spansWid - (xmax - spansPt->x); + spansPt->x = xmax; + } + } + else + { + if (xmax >= spansPt->x + *spansWid) + { + *spansWid = xmin - spansPt->x; + } + else + { + if (!extra) { + DDXPointPtr newPt; + int *newwid; + +#define EXTRA 8 + newPt = (DDXPointPtr) xrealloc (spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec)); + if (!newPt) + break; + spansPt = newPt + (spansPt - spans->points); + spans->points = newPt; + newwid = (int *) xrealloc (spans->widths, (spans->count + EXTRA) * sizeof (int)); + if (!newwid) + break; + spansWid = newwid + (spansWid - spans->widths); + spans->widths = newwid; + extra = EXTRA; + } + memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount)); + memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount)); + spans->count++; + extra--; + *spansWid = xmin - spansPt->x; + spansWid++; + spansPt++; + *spansWid = *spansWid - (xmax - spansPt->x); + spansPt->x = xmax; + } + } + } + spansPt++; spansWid++; spansCount--; + } + } + } +} + +void miAppendSpans(spanGroup, otherGroup, spans) + SpanGroup *spanGroup; + SpanGroup *otherGroup; + Spans *spans; +{ + register int ymin, ymax; + register int spansCount; + + spansCount = spans->count; + if (spansCount > 0) { + if (spanGroup->size == spanGroup->count) { + spanGroup->size = (spanGroup->size + 8) * 2; + spanGroup->group = (Spans *) + xrealloc(spanGroup->group, sizeof(Spans) * spanGroup->size); + } + + spanGroup->group[spanGroup->count] = *spans; + (spanGroup->count)++; + ymin = spans->points[0].y; + if (ymin < spanGroup->ymin) spanGroup->ymin = ymin; + ymax = spans->points[spansCount - 1].y; + if (ymax > spanGroup->ymax) spanGroup->ymax = ymax; + if (otherGroup && + otherGroup->ymin < ymax && + ymin < otherGroup->ymax) + { + miSubtractSpans (otherGroup, spans); + } + } + else + { + xfree (spans->points); + xfree (spans->widths); + } +} /* AppendSpans */ + +void miFreeSpanGroup(spanGroup) + SpanGroup *spanGroup; +{ + if (spanGroup->group != NULL) xfree(spanGroup->group); +} + +static void QuickSortSpansX(points, widths, numSpans) + register DDXPointRec points[]; + register int widths[]; + register int numSpans; +{ + register int x; + register int i, j, m; + register DDXPointPtr r; + +/* Always called with numSpans > 1 */ +/* Sorts only by x, as all y should be the same */ + +#define ExchangeSpans(a, b) \ +{ \ + DDXPointRec tpt; \ + register int tw; \ + \ + tpt = points[a]; points[a] = points[b]; points[b] = tpt; \ + tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ +} + + do { + if (numSpans < 9) { + /* Do insertion sort */ + register int xprev; + + xprev = points[0].x; + i = 1; + do { /* while i != numSpans */ + x = points[i].x; + if (xprev > x) { + /* points[i] is out of order. Move into proper location. */ + DDXPointRec tpt; + int tw, k; + + for (j = 0; x >= points[j].x; j++) {} + tpt = points[i]; + tw = widths[i]; + for (k = i; k != j; k--) { + points[k] = points[k-1]; + widths[k] = widths[k-1]; + } + points[j] = tpt; + widths[j] = tw; + x = points[i].x; + } /* if out of order */ + xprev = x; + i++; + } while (i != numSpans); + return; + } + + /* Choose partition element, stick in location 0 */ + m = numSpans / 2; + if (points[m].x > points[0].x) ExchangeSpans(m, 0); + if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1); + if (points[m].x > points[0].x) ExchangeSpans(m, 0); + x = points[0].x; + + /* Partition array */ + i = 0; + j = numSpans; + do { + r = &(points[i]); + do { + r++; + i++; + } while (i != numSpans && r->x < x); + r = &(points[j]); + do { + r--; + j--; + } while (x < r->x); + if (i < j) ExchangeSpans(i, j); + } while (i < j); + + /* Move partition element back to middle */ + ExchangeSpans(0, j); + + /* Recurse */ + if (numSpans-j-1 > 1) + QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1); + numSpans = j; + } while (numSpans > 1); +} /* QuickSortSpans */ + + +static int UniquifySpansX(spans, newPoints, newWidths) + Spans *spans; + register DDXPointRec *newPoints; + register int *newWidths; +{ + register int newx1, newx2, oldpt, i, y; + register DDXPointRec *oldPoints; + register int *oldWidths; + int *startNewWidths; + +/* Always called with numSpans > 1 */ +/* Uniquify the spans, and stash them into newPoints and newWidths. Return the + number of unique spans. */ + + + startNewWidths = newWidths; + + oldPoints = spans->points; + oldWidths = spans->widths; + + y = oldPoints->y; + newx1 = oldPoints->x; + newx2 = newx1 + *oldWidths; + + for (i = spans->count-1; i != 0; i--) { + oldPoints++; + oldWidths++; + oldpt = oldPoints->x; + if (oldpt > newx2) { + /* Write current span, start a new one */ + newPoints->x = newx1; + newPoints->y = y; + *newWidths = newx2 - newx1; + newPoints++; + newWidths++; + newx1 = oldpt; + newx2 = oldpt + *oldWidths; + } else { + /* extend current span, if old extends beyond new */ + oldpt = oldpt + *oldWidths; + if (oldpt > newx2) newx2 = oldpt; + } + } /* for */ + + /* Write final span */ + newPoints->x = newx1; + *newWidths = newx2 - newx1; + newPoints->y = y; + + return (newWidths - startNewWidths) + 1; +} /* UniquifySpansX */ + +void +miDisposeSpanGroup (spanGroup) + SpanGroup *spanGroup; +{ + int i; + Spans *spans; + + for (i = 0; i < spanGroup->count; i++) + { + spans = spanGroup->group + i; + xfree (spans->points); + xfree (spans->widths); + } +} + +void miFillUniqueSpanGroup(pDraw, pGC, spanGroup) + DrawablePtr pDraw; + GCPtr pGC; + SpanGroup *spanGroup; +{ + register int i; + register Spans *spans; + register Spans *yspans; + register int *ysizes; + register int ymin, ylength; + + /* Outgoing spans for one big call to FillSpans */ + register DDXPointPtr points; + register int *widths; + register int count; + + if (spanGroup->count == 0) return; + + if (spanGroup->count == 1) { + /* Already should be sorted, unique */ + spans = spanGroup->group; + (*pGC->ops->FillSpans) + (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE); + xfree(spans->points); + xfree(spans->widths); + } + else + { + /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */ + /* This seems to be the fastest thing to do. I've tried sorting on + both x and y at the same time rather than creating into all those + y buckets, but it was somewhat slower. */ + + ymin = spanGroup->ymin; + ylength = spanGroup->ymax - ymin + 1; + + /* Allocate Spans for y buckets */ + yspans = (Spans *) xalloc(ylength * sizeof(Spans)); + ysizes = (int *) xalloc(ylength * sizeof (int)); + + if (!yspans || !ysizes) + { + xfree (yspans); + xfree (ysizes); + miDisposeSpanGroup (spanGroup); + return; + } + + for (i = 0; i != ylength; i++) { + ysizes[i] = 0; + yspans[i].count = 0; + yspans[i].points = NULL; + yspans[i].widths = NULL; + } + + /* Go through every single span and put it into the correct bucket */ + count = 0; + for (i = 0, spans = spanGroup->group; + i != spanGroup->count; + i++, spans++) { + int index; + int j; + + for (j = 0, points = spans->points, widths = spans->widths; + j != spans->count; + j++, points++, widths++) { + index = points->y - ymin; + if (index >= 0 && index < ylength) { + Spans *newspans = &(yspans[index]); + if (newspans->count == ysizes[index]) { + DDXPointPtr newpoints; + int *newwidths; + ysizes[index] = (ysizes[index] + 8) * 2; + newpoints = (DDXPointPtr) xrealloc( + newspans->points, + ysizes[index] * sizeof(DDXPointRec)); + newwidths = (int *) xrealloc( + newspans->widths, + ysizes[index] * sizeof(int)); + if (!newpoints || !newwidths) + { + int i; + + for (i = 0; i < ylength; i++) + { + xfree (yspans[i].points); + xfree (yspans[i].widths); + } + xfree (yspans); + xfree (ysizes); + miDisposeSpanGroup (spanGroup); + return; + } + newspans->points = newpoints; + newspans->widths = newwidths; + } + newspans->points[newspans->count] = *points; + newspans->widths[newspans->count] = *widths; + (newspans->count)++; + } /* if y value of span in range */ + } /* for j through spans */ + count += spans->count; + xfree(spans->points); + spans->points = NULL; + xfree(spans->widths); + spans->widths = NULL; + } /* for i thorough Spans */ + + /* Now sort by x and uniquify each bucket into the final array */ + points = (DDXPointPtr) xalloc(count * sizeof(DDXPointRec)); + widths = (int *) xalloc(count * sizeof(int)); + if (!points || !widths) + { + int i; + + for (i = 0; i < ylength; i++) + { + xfree (yspans[i].points); + xfree (yspans[i].widths); + } + xfree (points); + xfree (widths); + xfree (yspans); + xfree (ysizes); + return; + } + count = 0; + for (i = 0; i != ylength; i++) { + int ycount = yspans[i].count; + if (ycount > 0) { + if (ycount > 1) { + QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount); + count += UniquifySpansX + (&(yspans[i]), &(points[count]), &(widths[count])); + } else { + points[count] = yspans[i].points[0]; + widths[count] = yspans[i].widths[0]; + count++; + } + xfree(yspans[i].points); + xfree(yspans[i].widths); + } + } + + (*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE); + xfree(points); + xfree(widths); + xfree(yspans); + xfree(ysizes); + } + + spanGroup->count = 0; + spanGroup->ymin = MAXSHORT; + spanGroup->ymax = MINSHORT; +} + + +void miFillSpanGroup(pDraw, pGC, spanGroup) + DrawablePtr pDraw; + GCPtr pGC; + SpanGroup *spanGroup; +{ + register int i; + register Spans *spans; + + for (i = 0, spans = spanGroup->group; i != spanGroup->count; i++, spans++) { + (*pGC->ops->FillSpans) + (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE); + xfree(spans->points); + xfree(spans->widths); + } + + spanGroup->count = 0; + spanGroup->ymin = MAXSHORT; + spanGroup->ymax = MINSHORT; +} /* FillSpanGroup */ diff --git a/mi/mispans.h b/mi/mispans.h new file mode 100644 index 000000000..3750d2add --- /dev/null +++ b/mi/mispans.h @@ -0,0 +1,132 @@ +/*********************************************************** + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: mispans.h,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ + +typedef struct { + int count; /* number of spans */ + DDXPointPtr points; /* pointer to list of start points */ + int *widths; /* pointer to list of widths */ +} Spans; + +typedef struct { + int size; /* Total number of *Spans allocated */ + int count; /* Number of *Spans actually in group */ + Spans *group; /* List of Spans */ + int ymin, ymax; /* Min, max y values encountered */ +} SpanGroup; + +/* Initialize SpanGroup. MUST BE DONE before use. */ +extern void miInitSpanGroup( +#if NeedFunctionPrototypes + SpanGroup * /*spanGroup*/ +#endif +); + +/* Add a Spans to a SpanGroup. The spans MUST BE in y-sorted order */ +extern void miAppendSpans( +#if NeedFunctionPrototypes + SpanGroup * /*spanGroup*/, + SpanGroup * /*otherGroup*/, + Spans * /*spans*/ +#endif +); + +/* Paint a span group, possibly with some overlap */ +extern void miFillSpanGroup( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + SpanGroup * /*spanGroup*/ +#endif +); + +/* Paint a span group, insuring that each pixel is painted at most once */ +extern void miFillUniqueSpanGroup( +#if NeedFunctionPrototypes + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + SpanGroup * /*spanGroup*/ +#endif +); + +/* Free up data in a span group. MUST BE DONE or you'll suffer memory leaks */ +extern void miFreeSpanGroup( +#if NeedFunctionPrototypes + SpanGroup * /*spanGroup*/ +#endif +); + +extern void miSubtractSpans( +#if NeedFunctionPrototypes + SpanGroup * /*spanGroup*/, + Spans * /*sub*/ +#endif +); + +extern void miDisposeSpanGroup( +#if NeedFunctionPrototypes + SpanGroup * /*spanGroup*/ +#endif +); + +extern int miClipSpans( +#if NeedFunctionPrototypes + RegionPtr /*prgnDst*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + int /*nspans*/, + DDXPointPtr /*pptNew*/, + int * /*pwidthNew*/, + int /*fSorted*/ +#endif +); + +/* Rops which must use span groups */ +#define miSpansCarefulRop(rop) (((rop) & 0xc) == 0x8 || ((rop) & 0x3) == 0x2) +#define miSpansEasyRop(rop) (!miSpansCarefulRop(rop)) + diff --git a/mi/misprite.c b/mi/misprite.c new file mode 100644 index 000000000..2fc6da8dd --- /dev/null +++ b/mi/misprite.c @@ -0,0 +1,2067 @@ +/* + * misprite.c + * + * machine independent software sprite routines + */ + +/* $Xorg: misprite.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +# include "X.h" +# include "Xproto.h" +# include "misc.h" +# include "pixmapstr.h" +# include "input.h" +# include "mi.h" +# include "cursorstr.h" +# include "font.h" +# include "scrnintstr.h" +# include "colormapst.h" +# include "windowstr.h" +# include "gcstruct.h" +# include "mipointer.h" +# include "mispritest.h" +# include "dixfontstr.h" +# include "fontstruct.h" + +/* + * screen wrappers + */ + +static int miSpriteScreenIndex; +static unsigned long miSpriteGeneration = 0; + +static Bool miSpriteCloseScreen(); +static void miSpriteGetImage(); +static void miSpriteGetSpans(); +static void miSpriteSourceValidate(); +static Bool miSpriteCreateGC(); +static void miSpriteBlockHandler(); +static void miSpriteInstallColormap(); +static void miSpriteStoreColors(); + +static void miSpritePaintWindowBackground(); +static void miSpritePaintWindowBorder(); +static void miSpriteCopyWindow(); +static void miSpriteClearToBackground(); + +static void miSpriteSaveDoomedAreas(); +static RegionPtr miSpriteRestoreAreas(); +static void miSpriteComputeSaved(); + +#define SCREEN_PROLOGUE(pScreen, field)\ + ((pScreen)->field = \ + ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field) + +#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ + ((pScreen)->field = wrapper) + +/* + * GC func wrappers + */ + +static int miSpriteGCIndex; + +static void miSpriteValidateGC (), miSpriteCopyGC (); +static void miSpriteDestroyGC(), miSpriteChangeGC(); +static void miSpriteChangeClip(), miSpriteDestroyClip(); +static void miSpriteCopyClip(); + +static GCFuncs miSpriteGCFuncs = { + miSpriteValidateGC, + miSpriteChangeGC, + miSpriteCopyGC, + miSpriteDestroyGC, + miSpriteChangeClip, + miSpriteDestroyClip, + miSpriteCopyClip, +}; + +#define GC_FUNC_PROLOGUE(pGC) \ + miSpriteGCPtr pGCPriv = \ + (miSpriteGCPtr) (pGC)->devPrivates[miSpriteGCIndex].ptr;\ + (pGC)->funcs = pGCPriv->wrapFuncs; \ + if (pGCPriv->wrapOps) \ + (pGC)->ops = pGCPriv->wrapOps; + +#define GC_FUNC_EPILOGUE(pGC) \ + pGCPriv->wrapFuncs = (pGC)->funcs; \ + (pGC)->funcs = &miSpriteGCFuncs; \ + if (pGCPriv->wrapOps) \ + { \ + pGCPriv->wrapOps = (pGC)->ops; \ + (pGC)->ops = &miSpriteGCOps; \ + } + +/* + * GC op wrappers + */ + +static void miSpriteFillSpans(), miSpriteSetSpans(); +static void miSpritePutImage(); +static RegionPtr miSpriteCopyArea(), miSpriteCopyPlane(); +static void miSpritePolyPoint(), miSpritePolylines(); +static void miSpritePolySegment(), miSpritePolyRectangle(); +static void miSpritePolyArc(), miSpriteFillPolygon(); +static void miSpritePolyFillRect(), miSpritePolyFillArc(); +static int miSpritePolyText8(), miSpritePolyText16(); +static void miSpriteImageText8(), miSpriteImageText16(); +static void miSpriteImageGlyphBlt(), miSpritePolyGlyphBlt(); +static void miSpritePushPixels(); +#ifdef NEED_LINEHELPER +static void miSpriteLineHelper(); +#endif + +static GCOps miSpriteGCOps = { + miSpriteFillSpans, miSpriteSetSpans, miSpritePutImage, + miSpriteCopyArea, miSpriteCopyPlane, miSpritePolyPoint, + miSpritePolylines, miSpritePolySegment, miSpritePolyRectangle, + miSpritePolyArc, miSpriteFillPolygon, miSpritePolyFillRect, + miSpritePolyFillArc, miSpritePolyText8, miSpritePolyText16, + miSpriteImageText8, miSpriteImageText16, miSpriteImageGlyphBlt, + miSpritePolyGlyphBlt, miSpritePushPixels +#ifdef NEED_LINEHELPER + , miSpriteLineHelper +#endif +}; + +/* + * testing only -- remove cursor for every draw. Eventually, + * each draw operation will perform a bounding box check against + * the saved cursor area + */ + +#define GC_SETUP_CHEAP(pDrawable) \ + miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) \ + (pDrawable)->pScreen->devPrivates[miSpriteScreenIndex].ptr; \ + +#define GC_SETUP(pDrawable, pGC) \ + GC_SETUP_CHEAP(pDrawable) \ + miSpriteGCPtr pGCPrivate = (miSpriteGCPtr) \ + (pGC)->devPrivates[miSpriteGCIndex].ptr; \ + GCFuncs *oldFuncs = pGC->funcs; + +#define GC_SETUP_AND_CHECK(pDrawable, pGC) \ + GC_SETUP(pDrawable, pGC); \ + if (GC_CHECK((WindowPtr)pDrawable)) \ + miSpriteRemoveCursor (pDrawable->pScreen); + +#define GC_CHECK(pWin) \ + (pScreenPriv->isUp && \ + (pScreenPriv->pCacheWin == pWin ? \ + pScreenPriv->isInCacheWin : ( \ + ((int) (pScreenPriv->pCacheWin = (pWin))) , \ + (pScreenPriv->isInCacheWin = \ + (pWin)->drawable.x < pScreenPriv->saved.x2 && \ + pScreenPriv->saved.x1 < (pWin)->drawable.x + \ + (int) (pWin)->drawable.width && \ + (pWin)->drawable.y < pScreenPriv->saved.y2 && \ + pScreenPriv->saved.y1 < (pWin)->drawable.y + \ + (int) (pWin)->drawable.height &&\ + RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \ + &pScreenPriv->saved) != rgnOUT)))) + +#define GC_OP_PROLOGUE(pGC) { \ + (pGC)->funcs = pGCPrivate->wrapFuncs; \ + (pGC)->ops = pGCPrivate->wrapOps; \ + } + +#define GC_OP_EPILOGUE(pGC) { \ + pGCPrivate->wrapOps = (pGC)->ops; \ + (pGC)->funcs = oldFuncs; \ + (pGC)->ops = &miSpriteGCOps; \ + } + +/* + * pointer-sprite method table + */ + +static Bool miSpriteRealizeCursor (), miSpriteUnrealizeCursor (); +static void miSpriteSetCursor (), miSpriteMoveCursor (); + +miPointerSpriteFuncRec miSpritePointerFuncs = { + miSpriteRealizeCursor, + miSpriteUnrealizeCursor, + miSpriteSetCursor, + miSpriteMoveCursor, +}; + +/* + * other misc functions + */ + +static void miSpriteRemoveCursor (), miSpriteRestoreCursor(); + +/* + * miSpriteInitialize -- called from device-dependent screen + * initialization proc after all of the function pointers have + * been stored in the screen structure. + */ + +Bool +miSpriteInitialize (pScreen, cursorFuncs, screenFuncs) + ScreenPtr pScreen; + miSpriteCursorFuncPtr cursorFuncs; + miPointerScreenFuncPtr screenFuncs; +{ + miSpriteScreenPtr pPriv; + VisualPtr pVisual; + + if (miSpriteGeneration != serverGeneration) + { + miSpriteScreenIndex = AllocateScreenPrivateIndex (); + if (miSpriteScreenIndex < 0) + return FALSE; + miSpriteGeneration = serverGeneration; + miSpriteGCIndex = AllocateGCPrivateIndex (); + } + if (!AllocateGCPrivate(pScreen, miSpriteGCIndex, sizeof(miSpriteGCRec))) + return FALSE; + pPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec)); + if (!pPriv) + return FALSE; + if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) + { + xfree ((pointer) pPriv); + return FALSE; + } + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + pPriv->pVisual = pVisual; + pPriv->CloseScreen = pScreen->CloseScreen; + pPriv->GetImage = pScreen->GetImage; + pPriv->GetSpans = pScreen->GetSpans; + pPriv->SourceValidate = pScreen->SourceValidate; + pPriv->CreateGC = pScreen->CreateGC; + pPriv->BlockHandler = pScreen->BlockHandler; + pPriv->InstallColormap = pScreen->InstallColormap; + pPriv->StoreColors = pScreen->StoreColors; + + pPriv->PaintWindowBackground = pScreen->PaintWindowBackground; + pPriv->PaintWindowBorder = pScreen->PaintWindowBorder; + pPriv->CopyWindow = pScreen->CopyWindow; + pPriv->ClearToBackground = pScreen->ClearToBackground; + + pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas; + pPriv->RestoreAreas = pScreen->RestoreAreas; + + pPriv->pCursor = NULL; + pPriv->x = 0; + pPriv->y = 0; + pPriv->isUp = FALSE; + pPriv->shouldBeUp = FALSE; + pPriv->pCacheWin = NullWindow; + pPriv->isInCacheWin = FALSE; + pPriv->checkPixels = TRUE; + pPriv->pInstalledMap = NULL; + pPriv->pColormap = NULL; + pPriv->funcs = cursorFuncs; + pPriv->colors[SOURCE_COLOR].red = 0; + pPriv->colors[SOURCE_COLOR].green = 0; + pPriv->colors[SOURCE_COLOR].blue = 0; + pPriv->colors[MASK_COLOR].red = 0; + pPriv->colors[MASK_COLOR].green = 0; + pPriv->colors[MASK_COLOR].blue = 0; + pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pPriv; + pScreen->CloseScreen = miSpriteCloseScreen; + pScreen->GetImage = miSpriteGetImage; + pScreen->GetSpans = miSpriteGetSpans; + pScreen->SourceValidate = miSpriteSourceValidate; + pScreen->CreateGC = miSpriteCreateGC; + pScreen->BlockHandler = miSpriteBlockHandler; + pScreen->InstallColormap = miSpriteInstallColormap; + pScreen->StoreColors = miSpriteStoreColors; + + pScreen->PaintWindowBackground = miSpritePaintWindowBackground; + pScreen->PaintWindowBorder = miSpritePaintWindowBorder; + pScreen->CopyWindow = miSpriteCopyWindow; + pScreen->ClearToBackground = miSpriteClearToBackground; + + pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas; + pScreen->RestoreAreas = miSpriteRestoreAreas; + + return TRUE; +} + +/* + * Screen wrappers + */ + +/* + * CloseScreen wrapper -- unwrap everything, free the private data + * and call the wrapped function + */ + +static Bool +miSpriteCloseScreen (i, pScreen) + ScreenPtr pScreen; +{ + miSpriteScreenPtr pScreenPriv; + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->SourceValidate = pScreenPriv->SourceValidate; + pScreen->CreateGC = pScreenPriv->CreateGC; + pScreen->BlockHandler = pScreenPriv->BlockHandler; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->StoreColors = pScreenPriv->StoreColors; + + pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground; + pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder; + pScreen->CopyWindow = pScreenPriv->CopyWindow; + pScreen->ClearToBackground = pScreenPriv->ClearToBackground; + + pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas; + pScreen->RestoreAreas = pScreenPriv->RestoreAreas; + + xfree ((pointer) pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) + DrawablePtr pDrawable; + int sx, sy, w, h; + unsigned int format; + unsigned long planemask; + char *pdstLine; +{ + ScreenPtr pScreen = pDrawable->pScreen; + miSpriteScreenPtr pScreenPriv; + + SCREEN_PROLOGUE (pScreen, GetImage); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + + if (pDrawable->type == DRAWABLE_WINDOW && + pScreenPriv->isUp && + ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) + { + miSpriteRemoveCursor (pScreen); + } + + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + + SCREEN_EPILOGUE (pScreen, GetImage, miSpriteGetImage); +} + +static void +miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) + DrawablePtr pDrawable; + int wMax; + DDXPointPtr ppt; + int *pwidth; + int nspans; + char *pdstStart; +{ + ScreenPtr pScreen = pDrawable->pScreen; + miSpriteScreenPtr pScreenPriv; + + SCREEN_PROLOGUE (pScreen, GetSpans); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + + if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp) + { + register DDXPointPtr pts; + register int *widths; + register int nPts; + register int xorg, + yorg; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + for (pts = ppt, widths = pwidth, nPts = nspans; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, + pts->x+xorg,*widths)) + { + miSpriteRemoveCursor (pScreen); + break; + } + } + } + + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + + SCREEN_EPILOGUE (pScreen, GetSpans, miSpriteGetSpans); +} + +static void +miSpriteSourceValidate (pDrawable, x, y, width, height) + DrawablePtr pDrawable; + int x, y, width, height; +{ + ScreenPtr pScreen = pDrawable->pScreen; + miSpriteScreenPtr pScreenPriv; + + SCREEN_PROLOGUE (pScreen, SourceValidate); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + + if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp && + ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, + x, y, width, height)) + { + miSpriteRemoveCursor (pScreen); + } + + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height); + + SCREEN_EPILOGUE (pScreen, SourceValidate, miSpriteSourceValidate); +} + +static Bool +miSpriteCreateGC (pGC) + GCPtr pGC; +{ + ScreenPtr pScreen = pGC->pScreen; + Bool ret; + miSpriteGCPtr pPriv; + + SCREEN_PROLOGUE (pScreen, CreateGC); + + pPriv = (miSpriteGCPtr)pGC->devPrivates[miSpriteGCIndex].ptr; + + ret = (*pScreen->CreateGC) (pGC); + + pPriv->wrapOps = NULL; + pPriv->wrapFuncs = pGC->funcs; + pGC->funcs = &miSpriteGCFuncs; + + SCREEN_EPILOGUE (pScreen, CreateGC, miSpriteCreateGC); + + return ret; +} + +static void +miSpriteBlockHandler (i, blockData, pTimeout, pReadmask) + int i; + pointer blockData; + OSTimePtr pTimeout; + pointer pReadmask; +{ + ScreenPtr pScreen = screenInfo.screens[i]; + miSpriteScreenPtr pPriv; + + pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + + SCREEN_PROLOGUE(pScreen, BlockHandler); + + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + SCREEN_EPILOGUE(pScreen, BlockHandler, miSpriteBlockHandler); + + if (!pPriv->isUp && pPriv->shouldBeUp) + miSpriteRestoreCursor (pScreen); +} + +static void +miSpriteInstallColormap (pMap) + ColormapPtr pMap; +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv; + + pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + + SCREEN_PROLOGUE(pScreen, InstallColormap); + + (*pScreen->InstallColormap) (pMap); + + SCREEN_EPILOGUE(pScreen, InstallColormap, miSpriteInstallColormap); + + pPriv->pInstalledMap = pMap; + if (pPriv->pColormap != pMap) + { + pPriv->checkPixels = TRUE; + if (pPriv->isUp) + miSpriteRemoveCursor (pScreen); + } +} + +static void +miSpriteStoreColors (pMap, ndef, pdef) + ColormapPtr pMap; + int ndef; + xColorItem *pdef; +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv; + int i; + int updated; + VisualPtr pVisual; + + pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + + SCREEN_PROLOGUE(pScreen, StoreColors); + + (*pScreen->StoreColors) (pMap, ndef, pdef); + + SCREEN_EPILOGUE(pScreen, StoreColors, miSpriteStoreColors); + + if (pPriv->pColormap == pMap) + { + updated = 0; + pVisual = pMap->pVisual; + if (pVisual->class == DirectColor) + { + /* Direct color - match on any of the subfields */ + +#define MaskMatch(a,b,mask) ((a) & (pVisual->mask) == (b) & (pVisual->mask)) + +#define UpdateDAC(plane,dac,mask) {\ + if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ + pPriv->colors[plane].dac = pdef[i].dac; \ + updated = 1; \ + } \ +} + +#define CheckDirect(plane) \ + UpdateDAC(plane,red,redMask) \ + UpdateDAC(plane,green,greenMask) \ + UpdateDAC(plane,blue,blueMask) + + for (i = 0; i < ndef; i++) + { + CheckDirect (SOURCE_COLOR) + CheckDirect (MASK_COLOR) + } + } + else + { + /* PseudoColor/GrayScale - match on exact pixel */ + for (i = 0; i < ndef; i++) + { + if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) + { + pPriv->colors[SOURCE_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) + { + pPriv->colors[MASK_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + } + } + if (updated) + { + pPriv->checkPixels = TRUE; + if (pPriv->isUp) + miSpriteRemoveCursor (pScreen); + } + } +} + +static void +miSpriteFindColors (pScreen) + ScreenPtr pScreen; +{ + miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) + pScreen->devPrivates[miSpriteScreenIndex].ptr; + CursorPtr pCursor; + xColorItem *sourceColor, *maskColor; + + pCursor = pScreenPriv->pCursor; + sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; + maskColor = &pScreenPriv->colors[MASK_COLOR]; + if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || + !(pCursor->foreRed == sourceColor->red && + pCursor->foreGreen == sourceColor->green && + pCursor->foreBlue == sourceColor->blue && + pCursor->backRed == maskColor->red && + pCursor->backGreen == maskColor->green && + pCursor->backBlue == maskColor->blue)) + { + pScreenPriv->pColormap = pScreenPriv->pInstalledMap; + sourceColor->red = pCursor->foreRed; + sourceColor->green = pCursor->foreGreen; + sourceColor->blue = pCursor->foreBlue; + FakeAllocColor (pScreenPriv->pColormap, sourceColor); + maskColor->red = pCursor->backRed; + maskColor->green = pCursor->backGreen; + maskColor->blue = pCursor->backBlue; + FakeAllocColor (pScreenPriv->pColormap, maskColor); + /* "free" the pixels right away, don't let this confuse you */ + FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); + FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); + } + pScreenPriv->checkPixels = FALSE; +} + +/* + * BackingStore wrappers + */ + +static void +miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy) + WindowPtr pWin; + RegionPtr pObscured; + int dx, dy; +{ + ScreenPtr pScreen; + miSpriteScreenPtr pScreenPriv; + BoxRec cursorBox; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE (pScreen, SaveDoomedAreas); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + if (pScreenPriv->isUp) + { + cursorBox = pScreenPriv->saved; + + if (dx || dy) + { + cursorBox.x1 += dx; + cursorBox.y1 += dy; + cursorBox.x2 += dx; + cursorBox.y2 += dy; + } + if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT) + miSpriteRemoveCursor (pScreen); + } + + (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy); + + SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, miSpriteSaveDoomedAreas); +} + +static RegionPtr +miSpriteRestoreAreas (pWin, prgnExposed) + WindowPtr pWin; + RegionPtr prgnExposed; +{ + ScreenPtr pScreen; + miSpriteScreenPtr pScreenPriv; + RegionPtr result; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE (pScreen, RestoreAreas); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + if (pScreenPriv->isUp) + { + if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT) + miSpriteRemoveCursor (pScreen); + } + + result = (*pScreen->RestoreAreas) (pWin, prgnExposed); + + SCREEN_EPILOGUE (pScreen, RestoreAreas, miSpriteRestoreAreas); + + return result; +} + +/* + * Window wrappers + */ + +static void +miSpritePaintWindowBackground (pWin, pRegion, what) + WindowPtr pWin; + RegionPtr pRegion; + int what; +{ + ScreenPtr pScreen; + miSpriteScreenPtr pScreenPriv; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE (pScreen, PaintWindowBackground); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + if (pScreenPriv->isUp) + { + /* + * If the cursor is on the same screen as the window, check the + * region to paint for the cursor and remove it as necessary + */ + if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) + miSpriteRemoveCursor (pScreen); + } + + (*pScreen->PaintWindowBackground) (pWin, pRegion, what); + + SCREEN_EPILOGUE (pScreen, PaintWindowBackground, miSpritePaintWindowBackground); +} + +static void +miSpritePaintWindowBorder (pWin, pRegion, what) + WindowPtr pWin; + RegionPtr pRegion; + int what; +{ + ScreenPtr pScreen; + miSpriteScreenPtr pScreenPriv; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE (pScreen, PaintWindowBorder); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + if (pScreenPriv->isUp) + { + /* + * If the cursor is on the same screen as the window, check the + * region to paint for the cursor and remove it as necessary + */ + if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) + miSpriteRemoveCursor (pScreen); + } + + (*pScreen->PaintWindowBorder) (pWin, pRegion, what); + + SCREEN_EPILOGUE (pScreen, PaintWindowBorder, miSpritePaintWindowBorder); +} + +static void +miSpriteCopyWindow (pWin, ptOldOrg, pRegion) + WindowPtr pWin; + DDXPointRec ptOldOrg; + RegionPtr pRegion; +{ + ScreenPtr pScreen; + miSpriteScreenPtr pScreenPriv; + BoxRec cursorBox; + int dx, dy; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE (pScreen, CopyWindow); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + if (pScreenPriv->isUp) + { + /* + * check both the source and the destination areas. The given + * region is source relative, so offset the cursor box by + * the delta position + */ + cursorBox = pScreenPriv->saved; + dx = pWin->drawable.x - ptOldOrg.x; + dy = pWin->drawable.y - ptOldOrg.y; + cursorBox.x1 -= dx; + cursorBox.x2 -= dx; + cursorBox.y1 -= dy; + cursorBox.y2 -= dy; + if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT || + RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT) + miSpriteRemoveCursor (pScreen); + } + + (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion); + + SCREEN_EPILOGUE (pScreen, CopyWindow, miSpriteCopyWindow); +} + +static void +miSpriteClearToBackground (pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + short x,y; + unsigned short w,h; + Bool generateExposures; +{ + ScreenPtr pScreen; + miSpriteScreenPtr pScreenPriv; + int realw, realh; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE (pScreen, ClearToBackground); + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + if (GC_CHECK(pWin)) + { + if (!(realw = w)) + realw = (int) pWin->drawable.width - x; + if (!(realh = h)) + realh = (int) pWin->drawable.height - y; + if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y, + x, y, realw, realh)) + { + miSpriteRemoveCursor (pScreen); + } + } + + (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); + + SCREEN_EPILOGUE (pScreen, ClearToBackground, miSpriteClearToBackground); +} + +/* + * GC Func wrappers + */ + +static void +miSpriteValidateGC (pGC, changes, pDrawable) + GCPtr pGC; + Mask changes; + DrawablePtr pDrawable; +{ + GC_FUNC_PROLOGUE (pGC); + + (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); + + pGCPriv->wrapOps = NULL; + if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable) + { + WindowPtr pWin; + RegionPtr pRegion; + + pWin = (WindowPtr) pDrawable; + pRegion = &pWin->clipList; + if (pGC->subWindowMode == IncludeInferiors) + pRegion = &pWin->borderClip; + if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) + pGCPriv->wrapOps = pGC->ops; + } + + GC_FUNC_EPILOGUE (pGC); +} + +static void +miSpriteChangeGC (pGC, mask) + GCPtr pGC; + unsigned long mask; +{ + GC_FUNC_PROLOGUE (pGC); + + (*pGC->funcs->ChangeGC) (pGC, mask); + + GC_FUNC_EPILOGUE (pGC); +} + +static void +miSpriteCopyGC (pGCSrc, mask, pGCDst) + GCPtr pGCSrc, pGCDst; + unsigned long mask; +{ + GC_FUNC_PROLOGUE (pGCDst); + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + + GC_FUNC_EPILOGUE (pGCDst); +} + +static void +miSpriteDestroyGC (pGC) + GCPtr pGC; +{ + GC_FUNC_PROLOGUE (pGC); + + (*pGC->funcs->DestroyGC) (pGC); + + GC_FUNC_EPILOGUE (pGC); +} + +static void +miSpriteChangeClip (pGC, type, pvalue, nrects) + GCPtr pGC; + int type; + pointer pvalue; + int nrects; +{ + GC_FUNC_PROLOGUE (pGC); + + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + + GC_FUNC_EPILOGUE (pGC); +} + +static void +miSpriteCopyClip(pgcDst, pgcSrc) + GCPtr pgcDst, pgcSrc; +{ + GC_FUNC_PROLOGUE (pgcDst); + + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + + GC_FUNC_EPILOGUE (pgcDst); +} + +static void +miSpriteDestroyClip(pGC) + GCPtr pGC; +{ + GC_FUNC_PROLOGUE (pGC); + + (* pGC->funcs->DestroyClip)(pGC); + + GC_FUNC_EPILOGUE (pGC); +} + +/* + * GC Op wrappers + */ + +static void +miSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + int nInit; /* number of spans to fill */ + DDXPointPtr pptInit; /* pointer to list of start points */ + int *pwidthInit; /* pointer to list of n widths */ + int fSorted; +{ + GC_SETUP(pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + { + register DDXPointPtr pts; + register int *widths; + register int nPts; + + for (pts = pptInit, widths = pwidthInit, nPts = nInit; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted) + DrawablePtr pDrawable; + GCPtr pGC; + char *psrc; + register DDXPointPtr ppt; + int *pwidth; + int nspans; + int fSorted; +{ + GC_SETUP(pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + { + register DDXPointPtr pts; + register int *widths; + register int nPts; + + for (pts = ppt, widths = pwidth, nPts = nspans; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths)) + { + miSpriteRemoveCursor(pDrawable->pScreen); + break; + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) + DrawablePtr pDrawable; + GCPtr pGC; + int depth; + int x; + int y; + int w; + int h; + int format; + char *pBits; +{ + GC_SETUP(pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + { + if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, + x,y,w,h)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits); + + GC_OP_EPILOGUE (pGC); +} + +static RegionPtr +miSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) + DrawablePtr pSrc; + DrawablePtr pDst; + GCPtr pGC; + int srcx; + int srcy; + int w; + int h; + int dstx; + int dsty; +{ + RegionPtr rgn; + + GC_SETUP(pDst, pGC); + + /* check destination/source overlap. */ + if (GC_CHECK((WindowPtr) pDst) && + (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || + ((pDst == pSrc) && + ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) + { + miSpriteRemoveCursor (pDst->pScreen); + } + + GC_OP_PROLOGUE (pGC); + + rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty); + + GC_OP_EPILOGUE (pGC); + + return rgn; +} + +static RegionPtr +miSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) + DrawablePtr pSrc; + DrawablePtr pDst; + register GCPtr pGC; + int srcx, + srcy; + int w, + h; + int dstx, + dsty; + unsigned long plane; +{ + RegionPtr rgn; + + GC_SETUP(pDst, pGC); + + /* + * check destination/source for overlap. + */ + if (GC_CHECK((WindowPtr) pDst) && + (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) || + ((pDst == pSrc) && + ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h)))) + { + miSpriteRemoveCursor (pDst->pScreen); + } + + GC_OP_PROLOGUE (pGC); + + rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, plane); + + GC_OP_EPILOGUE (pGC); + + return rgn; +} + +static void +miSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; + xPoint *pptInit; +{ + xPoint t; + int n; + BoxRec cursor; + register xPoint *pts; + + GC_SETUP (pDrawable, pGC); + + if (npt && GC_CHECK((WindowPtr) pDrawable)) + { + cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x; + cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y; + cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x; + cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y; + + if (mode == CoordModePrevious) + { + t.x = 0; + t.y = 0; + for (pts = pptInit, n = npt; n--; pts++) + { + t.x += pts->x; + t.y += pts->y; + if (cursor.x1 <= t.x && t.x <= cursor.x2 && + cursor.y1 <= t.y && t.y <= cursor.y2) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + else + { + for (pts = pptInit, n = npt; n--; pts++) + { + if (cursor.x1 <= pts->x && pts->x <= cursor.x2 && + cursor.y1 <= pts->y && pts->y <= cursor.y2) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePolylines (pDrawable, pGC, mode, npt, pptInit) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int npt; + DDXPointPtr pptInit; +{ + BoxPtr cursor; + register DDXPointPtr pts; + int n; + int x, y, x1, y1, x2, y2; + int lw; + int extra; + + GC_SETUP (pDrawable, pGC); + + if (npt && GC_CHECK((WindowPtr) pDrawable)) + { + cursor = &pScreenPriv->saved; + lw = pGC->lineWidth; + x = pptInit->x + pDrawable->x; + y = pptInit->y + pDrawable->y; + + if (npt == 1) + { + extra = lw >> 1; + if (LINE_OVERLAP(cursor, x, y, x, y, extra)) + miSpriteRemoveCursor (pDrawable->pScreen); + } + else + { + extra = lw >> 1; + /* + * mitered joins can project quite a way from + * the line end; the 11 degree miter limit limits + * this extension to 10.43 * lw / 2, rounded up + * and converted to int yields 6 * lw + */ + if (pGC->joinStyle == JoinMiter) + extra = 6 * lw; + else if (pGC->capStyle == CapProjecting) + extra = lw; + for (pts = pptInit + 1, n = npt - 1; n--; pts++) + { + x1 = x; + y1 = y; + if (mode == CoordModeOrigin) + { + x2 = pDrawable->x + pts->x; + y2 = pDrawable->y + pts->y; + } + else + { + x2 = x + pts->x; + y2 = y + pts->y; + } + x = x2; + y = y2; + LINE_SORT(x1, y1, x2, y2); + if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + } + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePolySegment(pDrawable, pGC, nseg, pSegs) + DrawablePtr pDrawable; + GCPtr pGC; + int nseg; + xSegment *pSegs; +{ + int n; + register xSegment *segs; + BoxPtr cursor; + int x1, y1, x2, y2; + int extra; + + GC_SETUP(pDrawable, pGC); + + if (nseg && GC_CHECK((WindowPtr) pDrawable)) + { + cursor = &pScreenPriv->saved; + extra = pGC->lineWidth >> 1; + if (pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + for (segs = pSegs, n = nseg; n--; segs++) + { + x1 = segs->x1 + pDrawable->x; + y1 = segs->y1 + pDrawable->y; + x2 = segs->x2 + pDrawable->x; + y2 = segs->y2 + pDrawable->y; + LINE_SORT(x1, y1, x2, y2); + if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePolyRectangle(pDrawable, pGC, nrects, pRects) + DrawablePtr pDrawable; + GCPtr pGC; + int nrects; + xRectangle *pRects; +{ + register xRectangle *rects; + BoxPtr cursor; + int lw; + int n; + int x1, y1, x2, y2; + + GC_SETUP (pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + { + lw = pGC->lineWidth >> 1; + cursor = &pScreenPriv->saved; + for (rects = pRects, n = nrects; n--; rects++) + { + x1 = rects->x + pDrawable->x; + y1 = rects->y + pDrawable->y; + x2 = x1 + (int)rects->width; + y2 = y1 + (int)rects->height; + if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) || + LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) || + LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) || + LINE_OVERLAP(cursor, x1, y1, x1, y2, lw)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePolyArc(pDrawable, pGC, narcs, parcs) + DrawablePtr pDrawable; + register GCPtr pGC; + int narcs; + xArc *parcs; +{ + BoxPtr cursor; + int lw; + int n; + register xArc *arcs; + + GC_SETUP (pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + { + lw = pGC->lineWidth >> 1; + cursor = &pScreenPriv->saved; + for (arcs = parcs, n = narcs; n--; arcs++) + { + if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y, + arcs->x - lw, arcs->y - lw, + (int) arcs->width + pGC->lineWidth, + (int) arcs->height + pGC->lineWidth)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts) + register DrawablePtr pDrawable; + register GCPtr pGC; + int shape, mode; + int count; + DDXPointPtr pPts; +{ + int x, y, minx, miny, maxx, maxy; + register DDXPointPtr pts; + int n; + + GC_SETUP (pDrawable, pGC); + + if (count && GC_CHECK((WindowPtr) pDrawable)) + { + x = pDrawable->x; + y = pDrawable->y; + pts = pPts; + minx = maxx = pts->x; + miny = maxy = pts->y; + pts++; + n = count - 1; + + if (mode == CoordModeOrigin) + { + for (; n--; pts++) + { + if (pts->x < minx) + minx = pts->x; + else if (pts->x > maxx) + maxx = pts->x; + if (pts->y < miny) + miny = pts->y; + else if (pts->y > maxy) + maxy = pts->y; + } + minx += x; + miny += y; + maxx += x; + maxy += y; + } + else + { + x += minx; + y += miny; + minx = maxx = x; + miny = maxy = y; + for (; n--; pts++) + { + x += pts->x; + y += pts->y; + if (x < minx) + minx = x; + else if (x > maxx) + maxx = x; + if (y < miny) + miny = y; + else if (y > maxy) + maxy = y; + } + } + if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy)) + miSpriteRemoveCursor (pDrawable->pScreen); + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit) + DrawablePtr pDrawable; + GCPtr pGC; + int nrectFill; /* number of rectangles to fill */ + xRectangle *prectInit; /* Pointer to first rectangle to fill */ +{ + GC_SETUP(pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + { + register int nRect; + register xRectangle *pRect; + register int xorg, yorg; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) { + if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){ + miSpriteRemoveCursor(pDrawable->pScreen); + break; + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePolyFillArc(pDrawable, pGC, narcs, parcs) + DrawablePtr pDrawable; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + GC_SETUP(pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + { + register int n; + BoxPtr cursor; + register xArc *arcs; + + cursor = &pScreenPriv->saved; + + for (arcs = parcs, n = narcs; n--; arcs++) + { + if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y, + arcs->x, arcs->y, + (int) arcs->width, (int) arcs->height)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + break; + } + } + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs); + + GC_OP_EPILOGUE (pGC); +} + +/* + * general Poly/Image text function. Extract glyph information, + * compute bounding box and remove cursor if it is overlapped. + */ + +static Bool +miSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox) + DrawablePtr pDraw; + FontPtr font; + int x, y; + unsigned int n; + CharInfoPtr *charinfo; + Bool imageblt; + unsigned int w; + BoxPtr cursorBox; +{ + ExtentInfoRec extents; + + x += pDraw->x; + y += pDraw->y; + + if (FONTMINBOUNDS(font,characterWidth) >= 0) + { + /* compute an approximate (but covering) bounding box */ + if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0)) + extents.overallLeft = charinfo[0]->metrics.leftSideBearing; + else + extents.overallLeft = 0; + if (w) + extents.overallRight = w - charinfo[n-1]->metrics.characterWidth; + else + extents.overallRight = FONTMAXBOUNDS(font,characterWidth) + * (n - 1); + if (imageblt && (charinfo[n-1]->metrics.characterWidth > + charinfo[n-1]->metrics.rightSideBearing)) + extents.overallRight += charinfo[n-1]->metrics.characterWidth; + else + extents.overallRight += charinfo[n-1]->metrics.rightSideBearing; + if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent)) + extents.overallAscent = FONTASCENT(font); + else + extents.overallAscent = FONTMAXBOUNDS(font, ascent); + if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent)) + extents.overallDescent = FONTDESCENT(font); + else + extents.overallDescent = FONTMAXBOUNDS(font,descent); + if (!BOX_OVERLAP(cursorBox, + x + extents.overallLeft, + y - extents.overallAscent, + x + extents.overallRight, + y + extents.overallDescent)) + return FALSE; + else if (imageblt && w) + return TRUE; + /* if it does overlap, fall through and compute exactly, because + * taking down the cursor is expensive enough to make this worth it + */ + } + QueryGlyphExtents(font, charinfo, n, &extents); + if (imageblt) + { + if (extents.overallWidth > extents.overallRight) + extents.overallRight = extents.overallWidth; + if (extents.overallWidth < extents.overallLeft) + extents.overallLeft = extents.overallWidth; + if (extents.overallLeft > 0) + extents.overallLeft = 0; + if (extents.fontAscent > extents.overallAscent) + extents.overallAscent = extents.fontAscent; + if (extents.fontDescent > extents.overallDescent) + extents.overallDescent = extents.fontDescent; + } + return (BOX_OVERLAP(cursorBox, + x + extents.overallLeft, + y - extents.overallAscent, + x + extents.overallRight, + y + extents.overallDescent)); +} + +/* + * values for textType: + */ +#define TT_POLY8 0 +#define TT_IMAGE8 1 +#define TT_POLY16 2 +#define TT_IMAGE16 3 + +static int +miSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox) + DrawablePtr pDraw; + GCPtr pGC; + int x, + y; + unsigned long count; + char *chars; + FontEncoding fontEncoding; + Bool textType; + BoxPtr cursorBox; +{ + CharInfoPtr *charinfo; + register CharInfoPtr *info; + unsigned long i; + unsigned int n; + int w; + void (*drawFunc)(); + + Bool imageblt; + + imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); + + charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); + if (!charinfo) + return x; + + GetGlyphs(pGC->font, count, (unsigned char *)chars, + fontEncoding, &i, charinfo); + n = (unsigned int)i; + w = 0; + if (!imageblt) + for (info = charinfo; i--; info++) + w += (*info)->metrics.characterWidth; + + if (n != 0) { + if (miSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox)) + miSpriteRemoveCursor(pDraw->pScreen); + +#ifdef AVOID_GLYPHBLT + /* + * On displays like Apollos, which do not optimize the GlyphBlt functions because they + * convert fonts to their internal form in RealizeFont and optimize text directly, we + * want to invoke the text functions here, not the GlyphBlt functions. + */ + switch (textType) + { + case TT_POLY8: + drawFunc = (void (*)())pGC->ops->PolyText8; + break; + case TT_IMAGE8: + drawFunc = pGC->ops->ImageText8; + break; + case TT_POLY16: + drawFunc = (void (*)())pGC->ops->PolyText16; + break; + case TT_IMAGE16: + drawFunc = pGC->ops->ImageText16; + break; + } + (*drawFunc) (pDraw, pGC, x, y, (int) count, chars); +#else /* don't AVOID_GLYPHBLT */ + /* + * On the other hand, if the device does use GlyphBlt ultimately to do text, we + * don't want to slow it down by invoking the text functions and having them call + * GetGlyphs all over again, so we go directly to the GlyphBlt functions here. + */ + drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt; + (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); +#endif /* AVOID_GLYPHBLT */ + } + DEALLOCATE_LOCAL(charinfo); + return x + w; +} + +static int +miSpritePolyText8(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + char *chars; +{ + int ret; + + GC_SETUP (pDrawable, pGC); + + GC_OP_PROLOGUE (pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars, + Linear8Bit, TT_POLY8, &pScreenPriv->saved); + else + ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); + + GC_OP_EPILOGUE (pGC); + return ret; +} + +static int +miSpritePolyText16(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + unsigned short *chars; +{ + int ret; + + GC_SETUP(pDrawable, pGC); + + GC_OP_PROLOGUE (pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, + (char *)chars, + FONTLASTROW(pGC->font) == 0 ? + Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved); + else + ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); + + GC_OP_EPILOGUE (pGC); + return ret; +} + +static void +miSpriteImageText8(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + char *chars; +{ + GC_SETUP(pDrawable, pGC); + + GC_OP_PROLOGUE (pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, + chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved); + else + (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpriteImageText16(pDrawable, pGC, x, y, count, chars) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + int count; + unsigned short *chars; +{ + GC_SETUP(pDrawable, pGC); + + GC_OP_PROLOGUE (pGC); + + if (GC_CHECK((WindowPtr) pDrawable)) + (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, + (char *)chars, + FONTLASTROW(pGC->font) == 0 ? + Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved); + else + (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + GC_SETUP(pDrawable, pGC); + + GC_OP_PROLOGUE (pGC); + + if (GC_CHECK((WindowPtr) pDrawable) && + miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved)) + { + miSpriteRemoveCursor(pDrawable->pScreen); + } + (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GCPtr pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + GC_SETUP (pDrawable, pGC); + + GC_OP_PROLOGUE (pGC); + + if (GC_CHECK((WindowPtr) pDrawable) && + miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved)) + { + miSpriteRemoveCursor(pDrawable->pScreen); + } + (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + GC_OP_EPILOGUE (pGC); +} + +static void +miSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y) + GCPtr pGC; + PixmapPtr pBitMap; + DrawablePtr pDrawable; + int w, h, x, y; +{ + GC_SETUP(pDrawable, pGC); + + if (GC_CHECK((WindowPtr) pDrawable) && + ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h)) + { + miSpriteRemoveCursor (pDrawable->pScreen); + } + + GC_OP_PROLOGUE (pGC); + + (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); + + GC_OP_EPILOGUE (pGC); +} + +#ifdef NEED_LINEHELPER +/* + * I don't expect this routine will ever be called, as the GC + * will have been unwrapped for the line drawing + */ + +static void +miSpriteLineHelper() +{ + FatalError("miSpriteLineHelper called\n"); +} +#endif + +/* + * miPointer interface routines + */ + +#define SPRITE_PAD 8 + +static Bool +miSpriteRealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + miSpriteScreenPtr pScreenPriv; + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + if (pCursor == pScreenPriv->pCursor) + pScreenPriv->checkPixels = TRUE; + return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); +} + +static Bool +miSpriteUnrealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + miSpriteScreenPtr pScreenPriv; + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); +} + +static void +miSpriteSetCursor (pScreen, pCursor, x, y) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + miSpriteScreenPtr pScreenPriv; + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + pScreenPriv->shouldBeUp = TRUE; + if (pScreenPriv->x == x && + pScreenPriv->y == y && + pScreenPriv->pCursor == pCursor && + !pScreenPriv->checkPixels) + { + return; + } + if (!pCursor) + { + pScreenPriv->shouldBeUp = FALSE; + if (pScreenPriv->isUp) + miSpriteRemoveCursor (pScreen); + pScreenPriv->pCursor = 0; + return; + } + pScreenPriv->x = x; + pScreenPriv->y = y; + pScreenPriv->pCacheWin = NullWindow; + if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) + { + pScreenPriv->pCursor = pCursor; + miSpriteFindColors (pScreen); + } + if (pScreenPriv->isUp) { + int sx, sy; + /* + * check to see if the old saved region + * encloses the new sprite, in which case we use + * the flicker-free MoveCursor primitive. + */ + sx = pScreenPriv->x - (int)pCursor->bits->xhot; + sy = pScreenPriv->y - (int)pCursor->bits->yhot; + if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && + sx < pScreenPriv->saved.x2 && + sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && + sy < pScreenPriv->saved.y2 && + (int) pCursor->bits->width + (2 * SPRITE_PAD) == + pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && + (int) pCursor->bits->height + (2 * SPRITE_PAD) == + pScreenPriv->saved.y2 - pScreenPriv->saved.y1 + ) + { + pScreenPriv->isUp = FALSE; + if (!(sx >= pScreenPriv->saved.x1 && + sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && + sy >= pScreenPriv->saved.y1 && + sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) + { + int oldx1, oldy1, dx, dy; + + oldx1 = pScreenPriv->saved.x1; + oldy1 = pScreenPriv->saved.y1; + dx = oldx1 - (sx - SPRITE_PAD); + dy = oldy1 - (sy - SPRITE_PAD); + pScreenPriv->saved.x1 -= dx; + pScreenPriv->saved.y1 -= dy; + pScreenPriv->saved.x2 -= dx; + pScreenPriv->saved.y2 -= dy; + (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, + pScreenPriv->saved.x1, + pScreenPriv->saved.y1, + pScreenPriv->saved.x2 - pScreenPriv->saved.x1, + pScreenPriv->saved.y2 - pScreenPriv->saved.y1, + dx, dy); + } + (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, + pScreenPriv->saved.x1, + pScreenPriv->saved.y1, + pScreenPriv->saved.x2 - pScreenPriv->saved.x1, + pScreenPriv->saved.y2 - pScreenPriv->saved.y1, + sx - pScreenPriv->saved.x1, + sy - pScreenPriv->saved.y1, + pScreenPriv->colors[SOURCE_COLOR].pixel, + pScreenPriv->colors[MASK_COLOR].pixel); + pScreenPriv->isUp = TRUE; + } + else + { + miSpriteRemoveCursor (pScreen); + } + } + if (!pScreenPriv->isUp && pScreenPriv->pCursor) + miSpriteRestoreCursor (pScreen); +} + +static void +miSpriteMoveCursor (pScreen, x, y) + ScreenPtr pScreen; + int x, y; +{ + miSpriteScreenPtr pScreenPriv; + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); +} + +/* + * undraw/draw cursor + */ + +static void +miSpriteRemoveCursor (pScreen) + ScreenPtr pScreen; +{ + miSpriteScreenPtr pScreenPriv; + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + pScreenPriv->isUp = FALSE; + pScreenPriv->pCacheWin = NullWindow; + if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, + pScreenPriv->saved.x1, + pScreenPriv->saved.y1, + pScreenPriv->saved.x2 - pScreenPriv->saved.x1, + pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) + { + pScreenPriv->isUp = TRUE; + } +} + +/* + * Called from the block handler, restores the cursor + * before waiting for something to do. + */ + +static void +miSpriteRestoreCursor (pScreen) + ScreenPtr pScreen; +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + + miSpriteComputeSaved (pScreen); + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + pCursor = pScreenPriv->pCursor; + x = pScreenPriv->x - (int)pCursor->bits->xhot; + y = pScreenPriv->y - (int)pCursor->bits->yhot; + if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, + pScreenPriv->saved.x1, + pScreenPriv->saved.y1, + pScreenPriv->saved.x2 - pScreenPriv->saved.x1, + pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) + { + if (pScreenPriv->checkPixels) + miSpriteFindColors (pScreen); + if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, + pScreenPriv->colors[SOURCE_COLOR].pixel, + pScreenPriv->colors[MASK_COLOR].pixel)) + pScreenPriv->isUp = TRUE; + } +} + +/* + * compute the desired area of the screen to save + */ + +static void +miSpriteComputeSaved (pScreen) + ScreenPtr pScreen; +{ + miSpriteScreenPtr pScreenPriv; + int x, y, w, h; + int wpad, hpad; + CursorPtr pCursor; + + pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; + pCursor = pScreenPriv->pCursor; + x = pScreenPriv->x - (int)pCursor->bits->xhot; + y = pScreenPriv->y - (int)pCursor->bits->yhot; + w = pCursor->bits->width; + h = pCursor->bits->height; + wpad = SPRITE_PAD; + hpad = SPRITE_PAD; + pScreenPriv->saved.x1 = x - wpad; + pScreenPriv->saved.y1 = y - hpad; + pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; + pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; +} diff --git a/mi/misprite.h b/mi/misprite.h new file mode 100644 index 000000000..be2f03e04 --- /dev/null +++ b/mi/misprite.h @@ -0,0 +1,111 @@ +/* + * misprite.h + * + * software-sprite/sprite drawing interface spec + * + * mi versions of these routines exist. + */ + +/* $Xorg: misprite.h,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +typedef struct { + Bool (*RealizeCursor)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/ +#endif +); + Bool (*UnrealizeCursor)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/ +#endif +); + Bool (*PutUpCursor)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/, + int /*x*/, + int /*y*/, + unsigned long /*source*/, + unsigned long /*mask*/ +#endif +); + Bool (*SaveUnderCursor)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/ +#endif +); + Bool (*RestoreUnderCursor)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/ +#endif +); + Bool (*MoveCursor)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*dx*/, + int /*dy*/, + unsigned long /*source*/, + unsigned long /*mask*/ +#endif +); + Bool (*ChangeSave)( +#if NeedNestedPrototypes + ScreenPtr /*pScreen*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*dx*/, + int /*dy*/ +#endif +); + +} miSpriteCursorFuncRec, *miSpriteCursorFuncPtr; + +extern Bool miSpriteInitialize( +#if NeedFunctionPrototypes + ScreenPtr /*pScreen*/, + miSpriteCursorFuncPtr /*cursorFuncs*/, + miPointerScreenFuncPtr /*screenFuncs*/ +#endif +); diff --git a/mi/mispritest.h b/mi/mispritest.h new file mode 100644 index 000000000..1b873ecbd --- /dev/null +++ b/mi/mispritest.h @@ -0,0 +1,110 @@ +/* + * mispritest.h + * + * mi sprite structures + */ + +/* $Xorg: mispritest.h,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +# include "misprite.h" + +/* + * per screen information + */ + +typedef struct { + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; + CreateGCProcPtr CreateGC; + ScreenBlockHandlerProcPtr BlockHandler; + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + ClearToBackgroundProcPtr ClearToBackground; + SaveDoomedAreasProcPtr SaveDoomedAreas; + RestoreAreasProcPtr RestoreAreas; + + CursorPtr pCursor; + int x; + int y; + BoxRec saved; + Bool isUp; + Bool shouldBeUp; + WindowPtr pCacheWin; + Bool isInCacheWin; + Bool checkPixels; + xColorItem colors[2]; + ColormapPtr pInstalledMap; + ColormapPtr pColormap; + VisualPtr pVisual; + miSpriteCursorFuncPtr funcs; +} miSpriteScreenRec, *miSpriteScreenPtr; + +#define SOURCE_COLOR 0 +#define MASK_COLOR 1 + +typedef struct { + GCFuncs *wrapFuncs; + GCOps *wrapOps; +} miSpriteGCRec, *miSpriteGCPtr; + +/* + * Overlap BoxPtr and Box elements + */ +#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ + (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ + ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) + +/* + * Overlap BoxPtr, origins, and rectangle + */ +#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ + BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) + +/* + * Overlap BoxPtr, origins and RectPtr + */ +#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ + ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ + (int)((pRect)->width), (int)((pRect)->height)) +/* + * Overlap BoxPtr and horizontal span + */ +#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) + +#define LINE_SORT(x1,y1,x2,y2) \ +{ int _t; \ + if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ + if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } + +#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ + BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) diff --git a/mi/mistruct.h b/mi/mistruct.h new file mode 100644 index 000000000..28994fec5 --- /dev/null +++ b/mi/mistruct.h @@ -0,0 +1,63 @@ +/* $Xorg: mistruct.h,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +#ifndef MISTRUCT_H +#define MISTRUCT_H + +#include "mi.h" +#include "miscstruct.h" + +/* information about dashes */ +typedef struct _miDash { + DDXPointRec pt; + int e1, e2; /* keep these, so we don't have to do it again */ + int e; /* bresenham error term for this point on line */ + int which; + int newLine;/* 0 if part of same original line as previous dash */ + } miDashRec; + +#endif /* MISTRUCT_H */ diff --git a/mi/mivalidate.h b/mi/mivalidate.h new file mode 100644 index 000000000..cca4a1b7c --- /dev/null +++ b/mi/mivalidate.h @@ -0,0 +1,51 @@ +/* $Xorg: mivalidate.h,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +#ifndef MIVALIDATE_H +#define MIVALIDATE_H + +#include "miscstruct.h" +#include "regionstr.h" + +typedef union _Validate { + struct BeforeValidate { + DDXPointRec oldAbsCorner; /* old window position */ + RegionPtr borderVisible; /* visible region of border, */ + /* non-null when size changes */ + Bool resized; /* unclipped winSize has changed - */ + /* don't call SaveDoomedAreas */ + } before; + struct AfterValidate { + RegionRec exposed; /* exposed regions, absolute pos */ + RegionRec borderExposed; + } after; +} ValidateRec; + +#endif /* MIVALIDATE_H */ diff --git a/mi/mivaltree.c b/mi/mivaltree.c new file mode 100644 index 000000000..26819ee45 --- /dev/null +++ b/mi/mivaltree.c @@ -0,0 +1,729 @@ +/* $Xorg: mivaltree.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +/* + * mivaltree.c -- + * Functions for recalculating window clip lists. Main function + * is miValidateTree. + * + +Copyright 1987, 1988, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + * + * Copyright 1987, 1988, 1989 by + * Digital Equipment Corporation, Maynard, 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 name of Digital 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. + * + ******************************************************************/ + + /* + * Aug '86: Susan Angebranndt -- original code + * July '87: Adam de Boor -- substantially modified and commented + * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible. + * In particular, much improved code for window mapping and + * circulating. + * Bob Scheifler -- avoid miComputeClips for unmapped windows, + * valdata changes + */ + +#include "X.h" +#include "scrnintstr.h" +#include "validate.h" +#include "windowstr.h" +#include "mi.h" +#include "regionstr.h" +#include "mivalidate.h" + +#ifdef SHAPE +/* + * Compute the visibility of a shaped window + */ +miShapedWindowIn (pScreen, universe, bounding, rect, x, y) + ScreenPtr pScreen; + RegionPtr universe, bounding; + BoxPtr rect; + register int x, y; +{ + BoxRec box; + register BoxPtr boundBox; + int nbox; + Bool someIn, someOut; + register int t, x1, y1, x2, y2; + + nbox = REGION_NUM_RECTS (bounding); + boundBox = REGION_RECTS (bounding); + someIn = someOut = FALSE; + x1 = rect->x1; + y1 = rect->y1; + x2 = rect->x2; + y2 = rect->y2; + while (nbox--) + { + if ((t = boundBox->x1 + x) < x1) + t = x1; + box.x1 = t; + if ((t = boundBox->y1 + y) < y1) + t = y1; + box.y1 = t; + if ((t = boundBox->x2 + x) > x2) + t = x2; + box.x2 = t; + if ((t = boundBox->y2 + y) > y2) + t = y2; + box.y2 = t; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + switch (RECT_IN_REGION(pScreen, universe, &box)) + { + case rgnIN: + if (someOut) + return rgnPART; + someIn = TRUE; + break; + case rgnOUT: + if (someIn) + return rgnPART; + someOut = TRUE; + break; + default: + return rgnPART; + } + boundBox++; + } + if (someIn) + return rgnIN; + return rgnOUT; +} +#endif + +#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ + HasBorder(w) && \ + (w)->backgroundState == ParentRelative) + +/*- + *----------------------------------------------------------------------- + * miComputeClips -- + * Recompute the clipList, borderClip, exposed and borderExposed + * regions for pParent and its children. Only viewable windows are + * taken into account. + * + * Results: + * None. + * + * Side Effects: + * clipList, borderClip, exposed and borderExposed are altered. + * A VisibilityNotify event may be generated on the parent window. + * + *----------------------------------------------------------------------- + */ + +static void +miComputeClips (pParent, pScreen, universe, kind, exposed) + register WindowPtr pParent; + register ScreenPtr pScreen; + register RegionPtr universe; + VTKind kind; + RegionPtr exposed; /* for intermediate calculations */ +{ + int dx, + dy; + RegionRec childUniverse; + register WindowPtr pChild; + int oldVis, newVis; + BoxRec borderSize; + RegionRec childUnion; + Bool overlap; + RegionPtr borderVisible; + Bool resized; + + /* + * Figure out the new visibility of this window. + * The extent of the universe should be the same as the extent of + * the borderSize region. If the window is unobscured, this rectangle + * will be completely inside the universe (the universe will cover it + * completely). If the window is completely obscured, none of the + * universe will cover the rectangle. + */ + + borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent); + borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent); + dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent); + if (dx > 32767) + dx = 32767; + borderSize.x2 = dx; + dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent); + if (dy > 32767) + dy = 32767; + borderSize.y2 = dy; + + oldVis = pParent->visibility; + switch (RECT_IN_REGION( pScreen, universe, &borderSize)) + { + case rgnIN: + newVis = VisibilityUnobscured; + break; + case rgnPART: + newVis = VisibilityPartiallyObscured; +#ifdef SHAPE + { + RegionPtr pBounding; + + if ((pBounding = wBoundingShape (pParent))) + { + switch (miShapedWindowIn (pScreen, universe, pBounding, + &borderSize, + pParent->drawable.x, + pParent->drawable.y)) + { + case rgnIN: + newVis = VisibilityUnobscured; + break; + case rgnOUT: + newVis = VisibilityFullyObscured; + break; + } + } + } +#endif + break; + default: + newVis = VisibilityFullyObscured; + break; + } + pParent->visibility = newVis; + if (oldVis != newVis && + ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask)) + SendVisibilityNotify(pParent); + + dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x; + dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y; + + /* + * avoid computations when dealing with simple operations + */ + + switch (kind) { + case VTMap: + case VTStack: + case VTUnmap: + break; + case VTMove: + if ((oldVis == newVis) && + ((oldVis == VisibilityFullyObscured) || + (oldVis == VisibilityUnobscured))) + { + pChild = pParent; + while (1) + { + if (pChild->viewable) + { + if (pChild->visibility != VisibilityFullyObscured) + { + REGION_TRANSLATE( pScreen, &pChild->borderClip, + dx, dy); + REGION_TRANSLATE( pScreen, &pChild->clipList, + dx, dy); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (pScreen->ClipNotify) + (* pScreen->ClipNotify) (pChild, dx, dy); + + } + if (pChild->valdata) + { + REGION_INIT(pScreen, + &pChild->valdata->after.borderExposed, + NullBox, 0); + if (HasParentRelativeBorder(pChild)) + { + REGION_SUBTRACT(pScreen, + &pChild->valdata->after.borderExposed, + &pChild->borderClip, + &pChild->winSize); + } + REGION_INIT( pScreen, &pChild->valdata->after.exposed, + NullBox, 0); + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pParent)) + pChild = pChild->parent; + if (pChild == pParent) + break; + pChild = pChild->nextSib; + } + return; + } + /* fall through */ + default: + /* + * To calculate exposures correctly, we have to translate the old + * borderClip and clipList regions to the window's new location so there + * is a correspondence between pieces of the new and old clipping regions. + */ + if (dx || dy) + { + /* + * We translate the old clipList because that will be exposed or copied + * if gravity is right. + */ + REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy); + REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy); + } + break; + } + + borderVisible = pParent->valdata->before.borderVisible; + resized = pParent->valdata->before.resized; + REGION_INIT( pScreen, &pParent->valdata->after.borderExposed, NullBox, 0); + REGION_INIT( pScreen, &pParent->valdata->after.exposed, NullBox, 0); + + /* + * Since the borderClip must not be clipped by the children, we do + * the border exposure first... + * + * 'universe' is the window's borderClip. To figure the exposures, remove + * the area that used to be exposed from the new. + * This leaves a region of pieces that weren't exposed before. + */ + + if (HasBorder (pParent)) + { + if (borderVisible) + { + /* + * when the border changes shape, the old visible portions + * of the border will be saved by DIX in borderVisible -- + * use that region and destroy it + */ + REGION_SUBTRACT( pScreen, exposed, universe, borderVisible); + REGION_DESTROY( pScreen, borderVisible); + } + else + { + REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip); + } + if (HasParentRelativeBorder(pParent) && (dx || dy)) + REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, + universe, + &pParent->winSize); + else + REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, + exposed, &pParent->winSize); + + REGION_COPY( pScreen, &pParent->borderClip, universe); + + /* + * To get the right clipList for the parent, and to make doubly sure + * that no child overlaps the parent's border, we remove the parent's + * border from the universe before proceeding. + */ + + REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize); + } + else + REGION_COPY( pScreen, &pParent->borderClip, universe); + + if ((pChild = pParent->firstChild) && pParent->mapped) + { + REGION_INIT(pScreen, &childUniverse, NullBox, 0); + REGION_INIT(pScreen, &childUnion, NullBox, 0); + if ((pChild->drawable.y < pParent->lastChild->drawable.y) || + ((pChild->drawable.y == pParent->lastChild->drawable.y) && + (pChild->drawable.x < pParent->lastChild->drawable.x))) + { + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); + } + } + else + { + for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) + { + if (pChild->viewable) + REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); + } + } + REGION_VALIDATE( pScreen, &childUnion, &overlap); + + for (pChild = pParent->firstChild; + pChild; + pChild = pChild->nextSib) + { + if (pChild->viewable) { + /* + * If the child is viewable, we want to remove its extents + * from the current universe, but we only re-clip it if + * it's been marked. + */ + if (pChild->valdata) { + /* + * Figure out the new universe from the child's + * perspective and recurse. + */ + REGION_INTERSECT( pScreen, &childUniverse, + universe, + &pChild->borderSize); + miComputeClips (pChild, pScreen, &childUniverse, kind, + exposed); + } + /* + * Once the child has been processed, we remove its extents + * from the current universe, thus denying its space to any + * other sibling. + */ + if (overlap) + REGION_SUBTRACT( pScreen, universe, universe, + &pChild->borderSize); + } + } + if (!overlap) + REGION_SUBTRACT( pScreen, universe, universe, &childUnion); + REGION_UNINIT( pScreen, &childUnion); + REGION_UNINIT( pScreen, &childUniverse); + } /* if any children */ + + /* + * 'universe' now contains the new clipList for the parent window. + * + * To figure the exposure of the window we subtract the old clip from the + * new, just as for the border. + */ + + if (oldVis == VisibilityFullyObscured || + oldVis == VisibilityNotViewable) + { + REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe); + } + else if (newVis != VisibilityFullyObscured && + newVis != VisibilityNotViewable) + { + REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed, + universe, &pParent->clipList); + } + + /* + * One last thing: backing storage. We have to try to save what parts of + * the window are about to be obscured. We can just subtract the universe + * from the old clipList and get the areas that were in the old but aren't + * in the new and, hence, are about to be obscured. + */ + if (pParent->backStorage && !resized) + { + REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe); + (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy); + } + + /* HACK ALERT - copying contents of regions, instead of regions */ + { + RegionRec tmp; + + tmp = pParent->clipList; + pParent->clipList = *universe; + *universe = tmp; + } + +#ifdef NOTDEF + REGION_COPY( pScreen, &pParent->clipList, universe); +#endif + + pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + if (pScreen->ClipNotify) + (* pScreen->ClipNotify) (pParent, dx, dy); +} + +static void +miTreeObscured(pParent) + register WindowPtr pParent; +{ + register WindowPtr pChild; + register int oldVis; + + pChild = pParent; + while (1) + { + if (pChild->viewable) + { + oldVis = pChild->visibility; + if (oldVis != (pChild->visibility = VisibilityFullyObscured) && + ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask)) + SendVisibilityNotify(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pParent)) + pChild = pChild->parent; + if (pChild == pParent) + break; + pChild = pChild->nextSib; + } +} + +/*- + *----------------------------------------------------------------------- + * miValidateTree -- + * Recomputes the clip list for pParent and all its inferiors. + * + * Results: + * Always returns 1. + * + * Side Effects: + * The clipList, borderClip, exposed, and borderExposed regions for + * each marked window are altered. + * + * Notes: + * This routine assumes that all affected windows have been marked + * (valdata created) and their winSize and borderSize regions + * adjusted to correspond to their new positions. The borderClip and + * clipList regions should not have been touched. + * + * The top-most level is treated differently from all lower levels + * because pParent is unchanged. For the top level, we merge the + * regions taken up by the marked children back into the clipList + * for pParent, thus forming a region from which the marked children + * can claim their areas. For lower levels, where the old clipList + * and borderClip are invalid, we can't do this and have to do the + * extra operations done in miComputeClips, but this is much faster + * e.g. when only one child has moved... + * + *----------------------------------------------------------------------- + */ +/*ARGSUSED*/ +int +miValidateTree (pParent, pChild, kind) + WindowPtr pParent; /* Parent to validate */ + WindowPtr pChild; /* First child of pParent that was + * affected */ + VTKind kind; /* What kind of configuration caused call */ +{ + RegionRec totalClip; /* Total clipping region available to + * the marked children. pParent's clipList + * merged with the borderClips of all + * the marked children. */ + RegionRec childClip; /* The new borderClip for the current + * child */ + RegionRec childUnion; /* the space covered by borderSize for + * all marked children */ + RegionRec exposed; /* For intermediate calculations */ + register ScreenPtr pScreen; + register WindowPtr pWin; + Bool overlap; + int viewvals; + Bool forward; + + pScreen = pParent->drawable.pScreen; + if (pChild == NullWindow) + pChild = pParent->firstChild; + + REGION_INIT(pScreen, &childClip, NullBox, 0); + REGION_INIT(pScreen, &exposed, NullBox, 0); + + /* + * compute the area of the parent window occupied + * by the marked children + the parent itself. This + * is the area which can be divied up among the marked + * children in their new configuration. + */ + REGION_INIT(pScreen, &totalClip, NullBox, 0); + viewvals = 0; + if ((pChild->drawable.y < pParent->lastChild->drawable.y) || + ((pChild->drawable.y == pParent->lastChild->drawable.y) && + (pChild->drawable.x < pParent->lastChild->drawable.x))) + { + forward = TRUE; + for (pWin = pChild; pWin; pWin = pWin->nextSib) + { + if (pWin->valdata) + { + REGION_APPEND( pScreen, &totalClip, &pWin->borderClip); + if (pWin->viewable) + viewvals++; + } + } + } + else + { + forward = FALSE; + pWin = pParent->lastChild; + while (1) + { + if (pWin->valdata) + { + REGION_APPEND( pScreen, &totalClip, &pWin->borderClip); + if (pWin->viewable) + viewvals++; + } + if (pWin == pChild) + break; + pWin = pWin->prevSib; + } + } + REGION_VALIDATE( pScreen, &totalClip, &overlap); + + /* + * Now go through the children of the root and figure their new + * borderClips from the totalClip, passing that off to miComputeClips + * to handle recursively. Once that's done, we remove the child + * from the totalClip to clip any siblings below it. + */ + + overlap = TRUE; + if (kind != VTStack) + { + REGION_UNION( pScreen, &totalClip, &totalClip, &pParent->clipList); + if (viewvals > 1) + { + /* + * precompute childUnion to discover whether any of them + * overlap. This seems redundant, but performance studies + * have demonstrated that the cost of this loop is + * lower than the cost of multiple Subtracts in the + * loop below. + */ + REGION_INIT(pScreen, &childUnion, NullBox, 0); + if (forward) + { + for (pWin = pChild; pWin; pWin = pWin->nextSib) + if (pWin->valdata && pWin->viewable) + REGION_APPEND( pScreen, &childUnion, + &pWin->borderSize); + } + else + { + pWin = pParent->lastChild; + while (1) + { + if (pWin->valdata && pWin->viewable) + REGION_APPEND( pScreen, &childUnion, + &pWin->borderSize); + if (pWin == pChild) + break; + pWin = pWin->prevSib; + } + } + REGION_VALIDATE(pScreen, &childUnion, &overlap); + if (overlap) + REGION_UNINIT(pScreen, &childUnion); + } + } + + for (pWin = pChild; + pWin != NullWindow; + pWin = pWin->nextSib) + { + if (pWin->viewable) { + if (pWin->valdata) { + REGION_INTERSECT( pScreen, &childClip, + &totalClip, + &pWin->borderSize); + miComputeClips (pWin, pScreen, &childClip, kind, &exposed); + if (overlap) + { + REGION_SUBTRACT( pScreen, &totalClip, + &totalClip, + &pWin->borderSize); + } + } else if (pWin->visibility == VisibilityNotViewable) { + miTreeObscured(pWin); + } + } else { + if (pWin->valdata) { + REGION_EMPTY( pScreen, &pWin->clipList); + if (pScreen->ClipNotify) + (* pScreen->ClipNotify) (pWin, 0, 0); + REGION_EMPTY( pScreen, &pWin->borderClip); + pWin->valdata = (ValidatePtr)NULL; + } + } + } + + REGION_UNINIT( pScreen, &childClip); + if (!overlap) + { + REGION_SUBTRACT(pScreen, &totalClip, &totalClip, &childUnion); + REGION_UNINIT(pScreen, &childUnion); + } + + REGION_INIT( pScreen, &pParent->valdata->after.exposed, NullBox, 0); + REGION_INIT( pScreen, &pParent->valdata->after.borderExposed, NullBox, 0); + + /* + * each case below is responsible for updating the + * clipList and serial number for the parent window + */ + + switch (kind) { + case VTStack: + break; + default: + /* + * totalClip contains the new clipList for the parent. Figure out + * exposures and obscures as per miComputeClips and reset the parent's + * clipList. + */ + REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed, + &totalClip, &pParent->clipList); + /* fall through */ + case VTMap: + if (pParent->backStorage) { + REGION_SUBTRACT( pScreen, &exposed, &pParent->clipList, &totalClip); + (* pScreen->SaveDoomedAreas)(pParent, &exposed, 0, 0); + } + + REGION_COPY( pScreen, &pParent->clipList, &totalClip); + pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; + break; + } + + REGION_UNINIT( pScreen, &totalClip); + REGION_UNINIT( pScreen, &exposed); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pParent, 0, 0); + return (1); +} diff --git a/mi/miwideline.c b/mi/miwideline.c new file mode 100644 index 000000000..b78435705 --- /dev/null +++ b/mi/miwideline.c @@ -0,0 +1,2203 @@ +/* $Xorg: miwideline.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +/* + +Copyright 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* Author: Keith Packard, MIT X Consortium */ + +/* + * Mostly integer wideline code. Uses a technique similar to + * bresenham zero-width lines, except walks an X edge + */ + +#include +#ifdef _XOPEN_SOURCE +#include +#else +#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ +#include +#undef _XOPEN_SOURCE +#endif +#include "X.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "miscstruct.h" +#include "miwideline.h" +#include "mi.h" + +#ifdef ICEILTEMPDECL +ICEILTEMPDECL +#endif + +static void miLineArc(); + +/* + * spans-based polygon filler + */ + +void +miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, overall_height, + left, right, left_count, right_count) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + SpanDataPtr spanData; + int y; /* start y coordinate */ + int overall_height; /* height of entire segment */ + PolyEdgePtr left, right; + int left_count, right_count; +{ + register int left_x, left_e; + int left_stepx; + int left_signdx; + int left_dy, left_dx; + + register int right_x, right_e; + int right_stepx; + int right_signdx; + int right_dy, right_dx; + + int height; + int left_height, right_height; + + register DDXPointPtr ppt; + DDXPointPtr pptInit; + register int *pwidth; + int *pwidthInit; + XID oldPixel; + int xorg; + Spans spanRec; + + left_height = 0; + right_height = 0; + + if (!spanData) + { + pptInit = (DDXPointPtr) ALLOCATE_LOCAL (overall_height * sizeof(*ppt)); + if (!pptInit) + return; + pwidthInit = (int *) ALLOCATE_LOCAL (overall_height * sizeof(*pwidth)); + if (!pwidthInit) + { + DEALLOCATE_LOCAL (pptInit); + return; + } + ppt = pptInit; + pwidth = pwidthInit; + oldPixel = pGC->fgPixel; + if (pixel != oldPixel) + { + DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE); + ValidateGC (pDrawable, pGC); + } + } + else + { + spanRec.points = (DDXPointPtr) xalloc (overall_height * sizeof (*ppt)); + if (!spanRec.points) + return; + spanRec.widths = (int *) xalloc (overall_height * sizeof (int)); + if (!spanRec.widths) + { + xfree (spanRec.points); + return; + } + ppt = spanRec.points; + pwidth = spanRec.widths; + } + + xorg = 0; + if (pGC->miTranslate) + { + y += pDrawable->y; + xorg = pDrawable->x; + } + while ((left_count || left_height) && + (right_count || right_height)) + { + MIPOLYRELOADLEFT + MIPOLYRELOADRIGHT + + height = left_height; + if (height > right_height) + height = right_height; + + left_height -= height; + right_height -= height; + + while (--height >= 0) + { + if (right_x >= left_x) + { + ppt->y = y; + ppt->x = left_x + xorg; + ppt++; + *pwidth++ = right_x - left_x + 1; + } + y++; + + MIPOLYSTEPLEFT + + MIPOLYSTEPRIGHT + } + } + if (!spanData) + { + (*pGC->ops->FillSpans) (pDrawable, pGC, ppt - pptInit, pptInit, pwidthInit, TRUE); + DEALLOCATE_LOCAL (pwidthInit); + DEALLOCATE_LOCAL (pptInit); + if (pixel != oldPixel) + { + DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); + ValidateGC (pDrawable, pGC); + } + } + else + { + spanRec.count = ppt - spanRec.points; + AppendSpanGroup (pGC, pixel, &spanRec, spanData) + } +} + +static void +miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, x, y, w, h) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + SpanDataPtr spanData; + int x, y, w, h; +{ + register DDXPointPtr ppt; + register int *pwidth; + XID oldPixel; + Spans spanRec; + xRectangle rect; + + if (!spanData) + { + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + oldPixel = pGC->fgPixel; + if (pixel != oldPixel) + { + DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE); + ValidateGC (pDrawable, pGC); + } + (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect); + if (pixel != oldPixel) + { + DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); + ValidateGC (pDrawable, pGC); + } + } + else + { + spanRec.points = (DDXPointPtr) xalloc (h * sizeof (*ppt)); + if (!spanRec.points) + return; + spanRec.widths = (int *) xalloc (h * sizeof (int)); + if (!spanRec.widths) + { + xfree (spanRec.points); + return; + } + ppt = spanRec.points; + pwidth = spanRec.widths; + + if (pGC->miTranslate) + { + y += pDrawable->y; + x += pDrawable->x; + } + while (h--) + { + ppt->x = x; + ppt->y = y; + ppt++; + *pwidth++ = w; + y++; + } + spanRec.count = ppt - spanRec.points; + AppendSpanGroup (pGC, pixel, &spanRec, spanData) + } +} + +/* static */ int +miPolyBuildEdge (x0, y0, k, dx, dy, xi, yi, left, edge) + double x0, y0; + double k; /* x0 * dy - y0 * dx */ + register int dx, dy; + int xi, yi; + int left; + register PolyEdgePtr edge; +{ + int x, y, e; + int xady; + + if (dy < 0) + { + dy = -dy; + dx = -dx; + k = -k; + } + +#ifdef NOTDEF + { + double realk, kerror; + realk = x0 * dy - y0 * dx; + kerror = Fabs (realk - k); + if (kerror > .1) + printf ("realk: %g k: %g\n", realk, k); + } +#endif + y = ICEIL (y0); + xady = ICEIL (k) + y * dx; + + if (xady <= 0) + x = - (-xady / dy) - 1; + else + x = (xady - 1) / dy; + + e = xady - x * dy; + + if (dx >= 0) + { + edge->signdx = 1; + edge->stepx = dx / dy; + edge->dx = dx % dy; + } + else + { + edge->signdx = -1; + edge->stepx = - (-dx / dy); + edge->dx = -dx % dy; + e = dy - e + 1; + } + edge->dy = dy; + edge->x = x + left + xi; + edge->e = e - dy; /* bias to compare against 0 instead of dy */ + return y + yi; +} + +#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) + +/* static */ int +miPolyBuildPoly (vertices, slopes, count, xi, yi, left, right, pnleft, pnright, h) + register PolyVertexPtr vertices; + register PolySlopePtr slopes; + int count; + int xi, yi; + PolyEdgePtr left, right; + int *pnleft, *pnright; + int *h; +{ + int top, bottom; + double miny, maxy; + register int i; + int j; + int clockwise; + int slopeoff; + register int s; + register int nright, nleft; + int y, lasty, bottomy, topy; + + /* find the top of the polygon */ + maxy = miny = vertices[0].y; + bottom = top = 0; + for (i = 1; i < count; i++) + { + if (vertices[i].y < miny) + { + top = i; + miny = vertices[i].y; + } + if (vertices[i].y >= maxy) + { + bottom = i; + maxy = vertices[i].y; + } + } + clockwise = 1; + slopeoff = 0; + + i = top; + j = StepAround (top, -1, count); + + if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) + { + clockwise = -1; + slopeoff = -1; + } + + bottomy = ICEIL (maxy) + yi; + + nright = 0; + + s = StepAround (top, slopeoff, count); + i = top; + while (i != bottom) + { + if (slopes[s].dy != 0) + { + y = miPolyBuildEdge (vertices[i].x, vertices[i].y, + slopes[s].k, + slopes[s].dx, slopes[s].dy, + xi, yi, 0, + &right[nright]); + if (nright != 0) + right[nright-1].height = y - lasty; + else + topy = y; + nright++; + lasty = y; + } + + i = StepAround (i, clockwise, count); + s = StepAround (s, clockwise, count); + } + if (nright != 0) + right[nright-1].height = bottomy - lasty; + + if (slopeoff == 0) + slopeoff = -1; + else + slopeoff = 0; + + nleft = 0; + s = StepAround (top, slopeoff, count); + i = top; + while (i != bottom) + { + if (slopes[s].dy != 0) + { + y = miPolyBuildEdge (vertices[i].x, vertices[i].y, + slopes[s].k, + slopes[s].dx, slopes[s].dy, xi, yi, 1, + &left[nleft]); + + if (nleft != 0) + left[nleft-1].height = y - lasty; + nleft++; + lasty = y; + } + i = StepAround (i, -clockwise, count); + s = StepAround (s, -clockwise, count); + } + if (nleft != 0) + left[nleft-1].height = bottomy - lasty; + *pnleft = nleft; + *pnright = nright; + *h = bottomy - topy; + return topy; +} + +static void +miLineOnePoint (pDrawable, pGC, pixel, spanData, x, y) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + SpanDataPtr spanData; + int x, y; +{ + DDXPointRec pt; + int wid; + unsigned long oldPixel; + + MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel); + if (pGC->fillStyle == FillSolid) + { + pt.x = x; + pt.y = y; + (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt); + } + else + { + wid = 1; + if (pGC->miTranslate) + { + x += pDrawable->x; + y += pDrawable->y; + } + pt.x = x; + pt.y = y; + (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE); + } + MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel); +} + +static void +miLineJoin (pDrawable, pGC, pixel, spanData, pLeft, pRight) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + SpanDataPtr spanData; + register LineFacePtr pLeft, pRight; +{ + double mx, my; + double denom; + PolyVertexRec vertices[4]; + PolySlopeRec slopes[4]; + int edgecount; + PolyEdgeRec left[4], right[4]; + int nleft, nright; + int y, height; + int swapslopes; + int joinStyle = pGC->joinStyle; + int lw = pGC->lineWidth; + + if (lw == 1 && !spanData) { + /* Lines going in the same direction have no join */ + if (pLeft->dx >= 0 == pRight->dx <= 0) + return; + if (joinStyle != JoinRound) { + denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; + if (denom == 0) + return; /* no join to draw */ + } + if (joinStyle != JoinMiter) { + miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y); + return; + } + } else { + if (joinStyle == JoinRound) + { + miLineArc(pDrawable, pGC, pixel, spanData, + pLeft, pRight, + (double)0.0, (double)0.0, TRUE); + return; + } + denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; + if (denom == 0.0) + return; /* no join to draw */ + } + + swapslopes = 0; + if (denom > 0) + { + pLeft->xa = -pLeft->xa; + pLeft->ya = -pLeft->ya; + pLeft->dx = -pLeft->dx; + pLeft->dy = -pLeft->dy; + } + else + { + swapslopes = 1; + pRight->xa = -pRight->xa; + pRight->ya = -pRight->ya; + pRight->dx = -pRight->dx; + pRight->dy = -pRight->dy; + } + + vertices[0].x = pRight->xa; + vertices[0].y = pRight->ya; + slopes[0].dx = -pRight->dy; + slopes[0].dy = pRight->dx; + slopes[0].k = 0; + + vertices[1].x = 0; + vertices[1].y = 0; + slopes[1].dx = pLeft->dy; + slopes[1].dy = -pLeft->dx; + slopes[1].k = 0; + + vertices[2].x = pLeft->xa; + vertices[2].y = pLeft->ya; + + if (joinStyle == JoinMiter) + { + my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - + pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) / + denom; + if (pLeft->dy != 0) + { + mx = pLeft->xa + (my - pLeft->ya) * + (double) pLeft->dx / (double) pLeft->dy; + } + else + { + mx = pRight->xa + (my - pRight->ya) * + (double) pRight->dx / (double) pRight->dy; + } + /* check miter limit */ + if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) + joinStyle = JoinBevel; + } + + if (joinStyle == JoinMiter) + { + slopes[2].dx = pLeft->dx; + slopes[2].dy = pLeft->dy; + slopes[2].k = pLeft->k; + if (swapslopes) + { + slopes[2].dx = -slopes[2].dx; + slopes[2].dy = -slopes[2].dy; + slopes[2].k = -slopes[2].k; + } + vertices[3].x = mx; + vertices[3].y = my; + slopes[3].dx = pRight->dx; + slopes[3].dy = pRight->dy; + slopes[3].k = pRight->k; + if (swapslopes) + { + slopes[3].dx = -slopes[3].dx; + slopes[3].dy = -slopes[3].dy; + slopes[3].k = -slopes[3].k; + } + edgecount = 4; + } + else + { + double scale, dx, dy, adx, ady; + + adx = dx = pRight->xa - pLeft->xa; + ady = dy = pRight->ya - pLeft->ya; + if (adx < 0) + adx = -adx; + if (ady < 0) + ady = -ady; + scale = ady; + if (adx > ady) + scale = adx; + slopes[2].dx = (dx * 65536) / scale; + slopes[2].dy = (dy * 65536) / scale; + slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - + (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; + edgecount = 3; + } + + y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, + left, right, &nleft, &nright, &height); + miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright); +} + +static int +miLineArcI (pDraw, pGC, xorg, yorg, points, widths) + DrawablePtr pDraw; + GCPtr pGC; + int xorg, yorg; + DDXPointPtr points; + int *widths; +{ + register DDXPointPtr tpts, bpts; + register int *twids, *bwids; + register int x, y, e, ex, slw; + + tpts = points; + twids = widths; + if (pGC->miTranslate) + { + xorg += pDraw->x; + yorg += pDraw->y; + } + slw = pGC->lineWidth; + if (slw == 1) + { + tpts->x = xorg; + tpts->y = yorg; + *twids = 1; + return 1; + } + bpts = tpts + slw; + bwids = twids + slw; + y = (slw >> 1) + 1; + if (slw & 1) + e = - ((y << 2) + 3); + else + e = - (y << 3); + ex = -4; + x = 0; + while (y) + { + e += (y << 3) - 4; + while (e >= 0) + { + x++; + e += (ex = -((x << 3) + 4)); + } + y--; + slw = (x << 1) + 1; + if ((e == ex) && (slw > 1)) + slw--; + tpts->x = xorg - x; + tpts->y = yorg - y; + tpts++; + *twids++ = slw; + if ((y != 0) && ((slw > 1) || (e != ex))) + { + bpts--; + bpts->x = xorg - x; + bpts->y = yorg + y; + *--bwids = slw; + } + } + return (pGC->lineWidth); +} + +#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ + if (ybase == edgey) \ + { \ + if (edgeleft) \ + { \ + if (edge->x > xcl) \ + xcl = edge->x; \ + } \ + else \ + { \ + if (edge->x < xcr) \ + xcr = edge->x; \ + } \ + edgey++; \ + edge->x += edge->stepx; \ + edge->e += edge->dx; \ + if (edge->e > 0) \ + { \ + edge->x += edge->signdx; \ + edge->e -= edge->dy; \ + } \ + } + +static int +miLineArcD (pDraw, pGC, xorg, yorg, points, widths, + edge1, edgey1, edgeleft1, edge2, edgey2, edgeleft2) + DrawablePtr pDraw; + GCPtr pGC; + double xorg, yorg; + DDXPointPtr points; + int *widths; + PolyEdgePtr edge1, edge2; + int edgey1, edgey2; + Bool edgeleft1, edgeleft2; +{ + register DDXPointPtr pts; + register int *wids; + double radius, x0, y0, el, er, yk, xlk, xrk, k; + int xbase, ybase, y, boty, xl, xr, xcl, xcr; + int ymin, ymax; + Bool edge1IsMin, edge2IsMin; + int ymin1, ymin2; + + pts = points; + wids = widths; + xbase = floor(xorg); + x0 = xorg - xbase; + ybase = ICEIL (yorg); + y0 = yorg - ybase; + if (pGC->miTranslate) + { + xbase += pDraw->x; + ybase += pDraw->y; + edge1->x += pDraw->x; + edge2->x += pDraw->x; + edgey1 += pDraw->y; + edgey2 += pDraw->y; + } + xlk = x0 + x0 + 1.0; + xrk = x0 + x0 - 1.0; + yk = y0 + y0 - 1.0; + radius = ((double)pGC->lineWidth) / 2.0; + y = floor(radius - y0 + 1.0); + ybase -= y; + ymin = ybase; + ymax = 65536; + edge1IsMin = FALSE; + ymin1 = edgey1; + if (edge1->dy >= 0) + { + if (!edge1->dy) + { + if (edgeleft1) + edge1IsMin = TRUE; + else + ymax = edgey1; + edgey1 = 65536; + } + else + { + if ((edge1->signdx < 0) == edgeleft1) + edge1IsMin = TRUE; + } + } + edge2IsMin = FALSE; + ymin2 = edgey2; + if (edge2->dy >= 0) + { + if (!edge2->dy) + { + if (edgeleft2) + edge2IsMin = TRUE; + else + ymax = edgey2; + edgey2 = 65536; + } + else + { + if ((edge2->signdx < 0) == edgeleft2) + edge2IsMin = TRUE; + } + } + if (edge1IsMin) + { + ymin = ymin1; + if (edge2IsMin && ymin1 > ymin2) + ymin = ymin2; + } else if (edge2IsMin) + ymin = ymin2; + el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); + er = el + xrk; + xl = 1; + xr = 0; + if (x0 < 0.5) + { + xl = 0; + el -= xlk; + } + boty = (y0 < -0.5) ? 1 : 0; + if (ybase + y - boty > ymax) + boty = ymax - ybase - y; + while (y > boty) + { + k = (y << 1) + yk; + er += k; + while (er > 0.0) + { + xr++; + er += xrk - (xr << 1); + } + el += k; + while (el >= 0.0) + { + xl--; + el += (xl << 1) - xlk; + } + y--; + ybase++; + if (ybase < ymin) + continue; + xcl = xl + xbase; + xcr = xr + xbase; + CLIPSTEPEDGE(edgey1, edge1, edgeleft1); + CLIPSTEPEDGE(edgey2, edge2, edgeleft2); + if (xcr >= xcl) + { + pts->x = xcl; + pts->y = ybase; + pts++; + *wids++ = xcr - xcl + 1; + } + } + er = xrk - (xr << 1) - er; + el = (xl << 1) - xlk - el; + boty = floor(-y0 - radius + 1.0); + if (ybase + y - boty > ymax) + boty = ymax - ybase - y; + while (y > boty) + { + k = (y << 1) + yk; + er -= k; + while ((er >= 0.0) && (xr >= 0)) + { + xr--; + er += xrk - (xr << 1); + } + el -= k; + while ((el > 0.0) && (xl <= 0)) + { + xl++; + el += (xl << 1) - xlk; + } + y--; + ybase++; + if (ybase < ymin) + continue; + xcl = xl + xbase; + xcr = xr + xbase; + CLIPSTEPEDGE(edgey1, edge1, edgeleft1); + CLIPSTEPEDGE(edgey2, edge2, edgeleft2); + if (xcr >= xcl) + { + pts->x = xcl; + pts->y = ybase; + pts++; + *wids++ = xcr - xcl + 1; + } + } + return (pts - points); +} + +int +miRoundJoinFace (face, edge, leftEdge) + register LineFacePtr face; + register PolyEdgePtr edge; + Bool *leftEdge; +{ + int y; + int dx, dy; + double xa, ya; + Bool left; + + dx = -face->dy; + dy = face->dx; + xa = face->xa; + ya = face->ya; + left = 1; + if (ya > 0) + { + ya = 0.0; + xa = 0.0; + } + if (dy < 0 || dy == 0 && dx > 0) + { + dx = -dx; + dy = -dy; + left = !left; + } + if (dx == 0 && dy == 0) + dy = 1; + if (dy == 0) + { + y = ICEIL (face->ya) + face->y; + edge->x = -32767; + edge->stepx = 0; + edge->signdx = 0; + edge->e = -1; + edge->dy = 0; + edge->dx = 0; + edge->height = 0; + } + else + { + y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge); + edge->height = 32767; + } + *leftEdge = !left; + return y; +} + +void +miRoundJoinClip (pLeft, pRight, edge1, edge2, y1, y2, left1, left2) + register LineFacePtr pLeft, pRight; + PolyEdgePtr edge1, edge2; + int *y1, *y2; + Bool *left1, *left2; +{ + double denom; + + denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; + + if (denom >= 0) + { + pLeft->xa = -pLeft->xa; + pLeft->ya = -pLeft->ya; + } + else + { + pRight->xa = -pRight->xa; + pRight->ya = -pRight->ya; + } + *y1 = miRoundJoinFace (pLeft, edge1, left1); + *y2 = miRoundJoinFace (pRight, edge2, left2); +} + +int +miRoundCapClip (face, isInt, edge, leftEdge) + register LineFacePtr face; + Bool isInt; + register PolyEdgePtr edge; + Bool *leftEdge; +{ + int y; + register int dx, dy; + double xa, ya, k; + Bool left; + + dx = -face->dy; + dy = face->dx; + xa = face->xa; + ya = face->ya; + k = 0.0; + if (!isInt) + k = face->k; + left = 1; + if (dy < 0 || dy == 0 && dx > 0) + { + dx = -dx; + dy = -dy; + xa = -xa; + ya = -ya; + left = !left; + } + if (dx == 0 && dy == 0) + dy = 1; + if (dy == 0) + { + y = ICEIL (face->ya) + face->y; + edge->x = -32767; + edge->stepx = 0; + edge->signdx = 0; + edge->e = -1; + edge->dy = 0; + edge->dx = 0; + edge->height = 0; + } + else + { + y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge); + edge->height = 32767; + } + *leftEdge = !left; + return y; +} + +static void +miLineArc (pDraw, pGC, pixel, spanData, leftFace, rightFace, xorg, yorg, isInt) + DrawablePtr pDraw; + register GCPtr pGC; + unsigned long pixel; + SpanDataPtr spanData; + register LineFacePtr leftFace, rightFace; + double xorg, yorg; + Bool isInt; +{ + DDXPointPtr points; + int *widths; + int xorgi, yorgi; + XID oldPixel; + Spans spanRec; + int n; + PolyEdgeRec edge1, edge2; + int edgey1, edgey2; + Bool edgeleft1, edgeleft2; + + if (isInt) + { + xorgi = leftFace ? leftFace->x : rightFace->x; + yorgi = leftFace ? leftFace->y : rightFace->y; + } + edgey1 = 65536; + edgey2 = 65536; + edge1.x = 0; /* not used, keep memory checkers happy */ + edge1.dy = -1; + edge2.x = 0; /* not used, keep memory checkers happy */ + edge2.dy = -1; + edgeleft1 = FALSE; + edgeleft2 = FALSE; + if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) && + (pGC->capStyle == CapRound && pGC->joinStyle != JoinRound || + pGC->joinStyle == JoinRound && pGC->capStyle == CapButt)) + { + if (isInt) + { + xorg = (double) xorgi; + yorg = (double) yorgi; + } + if (leftFace && rightFace) + { + miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, + &edgey1, &edgey2, &edgeleft1, &edgeleft2); + } + else if (leftFace) + { + edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); + } + else if (rightFace) + { + edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); + } + isInt = FALSE; + } + if (!spanData) + { + points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * pGC->lineWidth); + if (!points) + return; + widths = (int *)ALLOCATE_LOCAL(sizeof(int) * pGC->lineWidth); + if (!widths) + { + DEALLOCATE_LOCAL(points); + return; + } + oldPixel = pGC->fgPixel; + if (pixel != oldPixel) + { + DoChangeGC(pGC, GCForeground, (XID *)&pixel, FALSE); + ValidateGC (pDraw, pGC); + } + } + else + { + points = (DDXPointPtr) xalloc (pGC->lineWidth * sizeof (DDXPointRec)); + if (!points) + return; + widths = (int *) xalloc (pGC->lineWidth * sizeof (int)); + if (!widths) + { + xfree (points); + return; + } + spanRec.points = points; + spanRec.widths = widths; + } + if (isInt) + n = miLineArcI(pDraw, pGC, xorgi, yorgi, points, widths); + else + n = miLineArcD(pDraw, pGC, xorg, yorg, points, widths, + &edge1, edgey1, edgeleft1, + &edge2, edgey2, edgeleft2); + + if (!spanData) + { + (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, TRUE); + DEALLOCATE_LOCAL(widths); + DEALLOCATE_LOCAL(points); + if (pixel != oldPixel) + { + DoChangeGC(pGC, GCForeground, &oldPixel, FALSE); + ValidateGC (pDraw, pGC); + } + } + else + { + spanRec.count = n; + AppendSpanGroup (pGC, pixel, &spanRec, spanData) + } +} + +void +miLineProjectingCap (pDrawable, pGC, pixel, spanData, face, isLeft, xorg, yorg, isInt) + DrawablePtr pDrawable; + register GCPtr pGC; + unsigned long pixel; + SpanDataPtr spanData; + register LineFacePtr face; + Bool isLeft; + double xorg, yorg; + Bool isInt; +{ + int xorgi, yorgi; + int lw; + PolyEdgeRec lefts[2], rights[2]; + int lefty, righty, topy, bottomy; + PolyEdgePtr left, right; + PolyEdgePtr top, bottom; + double xa,ya; + double k; + double xap, yap; + int dx, dy; + double projectXoff, projectYoff; + double maxy; + int finaly; + + if (isInt) + { + xorgi = face->x; + yorgi = face->y; + } + lw = pGC->lineWidth; + dx = face->dx; + dy = face->dy; + k = face->k; + if (dy == 0) + { + lefts[0].height = lw; + lefts[0].x = xorgi; + if (isLeft) + lefts[0].x -= (lw >> 1); + lefts[0].stepx = 0; + lefts[0].signdx = 1; + lefts[0].e = -lw; + lefts[0].dx = 0; + lefts[0].dy = lw; + rights[0].height = lw; + rights[0].x = xorgi; + if (!isLeft) + rights[0].x += (lw + 1 >> 1); + rights[0].stepx = 0; + rights[0].signdx = 1; + rights[0].e = -lw; + rights[0].dx = 0; + rights[0].dy = lw; + miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw, + lefts, rights, 1, 1); + } + else if (dx == 0) + { + topy = yorgi; + bottomy = yorgi + dy; + if (isLeft) + topy -= (lw >> 1); + else + bottomy += (lw >> 1); + lefts[0].height = bottomy - topy; + lefts[0].x = xorgi - (lw >> 1); + lefts[0].stepx = 0; + lefts[0].signdx = 1; + lefts[0].e = -dy; + lefts[0].dx = dx; + lefts[0].dy = dy; + + rights[0].height = bottomy - topy; + rights[0].x = lefts[0].x + (lw-1); + rights[0].stepx = 0; + rights[0].signdx = 1; + rights[0].e = -dy; + rights[0].dx = dx; + rights[0].dy = dy; + miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1); + } + else + { + xa = face->xa; + ya = face->ya; + projectXoff = -ya; + projectYoff = xa; + if (dx < 0) + { + right = &rights[1]; + left = &lefts[0]; + top = &rights[0]; + bottom = &lefts[1]; + } + else + { + right = &rights[0]; + left = &lefts[1]; + top = &lefts[0]; + bottom = &rights[1]; + } + if (isLeft) + { + righty = miPolyBuildEdge (xa, ya, + k, dx, dy, xorgi, yorgi, 0, right); + + xa = -xa; + ya = -ya; + k = -k; + lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, xorgi, yorgi, 1, left); + if (dx > 0) + { + ya = -ya; + xa = -xa; + } + xap = xa - projectXoff; + yap = ya - projectYoff; + topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, + -dy, dx, xorgi, yorgi, dx > 0, top); + bottomy = miPolyBuildEdge (xa, ya, + 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom); + maxy = -ya; + } + else + { + righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, xorgi, yorgi, 0, right); + + xa = -xa; + ya = -ya; + k = -k; + lefty = miPolyBuildEdge (xa, ya, + k, dx, dy, xorgi, yorgi, 1, left); + if (dx > 0) + { + ya = -ya; + xa = -xa; + } + xap = xa - projectXoff; + yap = ya - projectYoff; + topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top); + bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, + -dy, dx, xorgi, xorgi, dx < 0, bottom); + maxy = -ya + projectYoff; + } + finaly = ICEIL(maxy) + yorgi; + if (dx < 0) + { + left->height = bottomy - lefty; + right->height = finaly - righty; + top->height = righty - topy; + } + else + { + right->height = bottomy - righty; + left->height = finaly - lefty; + top->height = lefty - topy; + } + bottom->height = finaly - bottomy; + miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, + bottom->height + bottomy - topy, lefts, rights, 2, 2); + } +} + +static void +miWideSegment (pDrawable, pGC, pixel, spanData, + x1, y1, x2, y2, projectLeft, projectRight, leftFace, rightFace) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + SpanDataPtr spanData; + register int x1, y1, x2, y2; + Bool projectLeft, projectRight; + register LineFacePtr leftFace, rightFace; +{ + double l, L, r; + double xa, ya; + double projectXoff, projectYoff; + double k; + double maxy; + int x, y; + int dx, dy; + int finaly; + PolyEdgePtr left, right; + PolyEdgePtr top, bottom; + int lefty, righty, topy, bottomy; + int signdx; + PolyEdgeRec lefts[2], rights[2]; + LineFacePtr tface; + int lw = pGC->lineWidth; + + /* draw top-to-bottom always */ + if (y2 < y1 || y2 == y1 && x2 < x1) + { + x = x1; + x1 = x2; + x2 = x; + + y = y1; + y1 = y2; + y2 = y; + + x = projectLeft; + projectLeft = projectRight; + projectRight = x; + + tface = leftFace; + leftFace = rightFace; + rightFace = tface; + } + + dy = y2 - y1; + signdx = 1; + dx = x2 - x1; + if (dx < 0) + signdx = -1; + + leftFace->x = x1; + leftFace->y = y1; + leftFace->dx = dx; + leftFace->dy = dy; + + rightFace->x = x2; + rightFace->y = y2; + rightFace->dx = -dx; + rightFace->dy = -dy; + + if (dy == 0) + { + rightFace->xa = 0; + rightFace->ya = (double) lw / 2.0; + rightFace->k = -(double) (lw * dx) / 2.0; + leftFace->xa = 0; + leftFace->ya = -rightFace->ya; + leftFace->k = rightFace->k; + x = x1; + if (projectLeft) + x -= (lw >> 1); + y = y1 - (lw >> 1); + dx = x2 - x; + if (projectRight) + dx += (lw + 1 >> 1); + dy = lw; + miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, + x, y, dx, dy); + } + else if (dx == 0) + { + leftFace->xa = (double) lw / 2.0; + leftFace->ya = 0; + leftFace->k = (double) (lw * dy) / 2.0; + rightFace->xa = -leftFace->xa; + rightFace->ya = 0; + rightFace->k = leftFace->k; + y = y1; + if (projectLeft) + y -= lw >> 1; + x = x1 - (lw >> 1); + dy = y2 - y; + if (projectRight) + dy += (lw + 1 >> 1); + dx = lw; + miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, + x, y, dx, dy); + } + else + { + l = ((double) lw) / 2.0; + L = hypot ((double) dx, (double) dy); + + if (dx < 0) + { + right = &rights[1]; + left = &lefts[0]; + top = &rights[0]; + bottom = &lefts[1]; + } + else + { + right = &rights[0]; + left = &lefts[1]; + top = &lefts[0]; + bottom = &rights[1]; + } + r = l / L; + + /* coord of upper bound at integral y */ + ya = -r * dx; + xa = r * dy; + + if (projectLeft | projectRight) + { + projectXoff = -ya; + projectYoff = xa; + } + + /* xa * dy - ya * dx */ + k = l * L; + + leftFace->xa = xa; + leftFace->ya = ya; + leftFace->k = k; + rightFace->xa = -xa; + rightFace->ya = -ya; + rightFace->k = k; + + if (projectLeft) + righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 0, right); + else + righty = miPolyBuildEdge (xa, ya, + k, dx, dy, x1, y1, 0, right); + + /* coord of lower bound at integral y */ + ya = -ya; + xa = -xa; + + /* xa * dy - ya * dx */ + k = - k; + + if (projectLeft) + lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 1, left); + else + lefty = miPolyBuildEdge (xa, ya, + k, dx, dy, x1, y1, 1, left); + + /* coord of top face at integral y */ + + if (signdx > 0) + { + ya = -ya; + xa = -xa; + } + + if (projectLeft) + { + double xap = xa - projectXoff; + double yap = ya - projectYoff; + topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, + -dy, dx, x1, y1, dx > 0, top); + } + else + topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top); + + /* coord of bottom face at integral y */ + + if (projectRight) + { + double xap = xa + projectXoff; + double yap = ya + projectYoff; + bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, + -dy, dx, x2, y2, dx < 0, bottom); + maxy = -ya + projectYoff; + } + else + { + bottomy = miPolyBuildEdge (xa, ya, + 0.0, -dy, dx, x2, y2, dx < 0, bottom); + maxy = -ya; + } + + finaly = ICEIL (maxy) + y2; + + if (dx < 0) + { + left->height = bottomy - lefty; + right->height = finaly - righty; + top->height = righty - topy; + } + else + { + right->height = bottomy - righty; + left->height = finaly - lefty; + top->height = lefty - topy; + } + bottom->height = finaly - bottomy; + miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, + bottom->height + bottomy - topy, lefts, rights, 2, 2); + } +} + +SpanDataPtr +miSetupSpanData (pGC, spanData, npt) + register GCPtr pGC; + SpanDataPtr spanData; + int npt; +{ + if (npt < 3 && pGC->capStyle != CapRound || miSpansEasyRop(pGC->alu)) + return (SpanDataPtr) NULL; + if (pGC->lineStyle == LineDoubleDash) + miInitSpanGroup (&spanData->bgGroup); + miInitSpanGroup (&spanData->fgGroup); + return spanData; +} + +void +miCleanupSpanData (pDrawable, pGC, spanData) + DrawablePtr pDrawable; + GCPtr pGC; + SpanDataPtr spanData; +{ + if (pGC->lineStyle == LineDoubleDash) + { + XID oldPixel, pixel; + + pixel = pGC->bgPixel; + oldPixel = pGC->fgPixel; + if (pixel != oldPixel) + { + DoChangeGC (pGC, GCForeground, &pixel, FALSE); + ValidateGC (pDrawable, pGC); + } + miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup); + miFreeSpanGroup (&spanData->bgGroup); + if (pixel != oldPixel) + { + DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); + ValidateGC (pDrawable, pGC); + } + } + miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup); + miFreeSpanGroup (&spanData->fgGroup); +} + +void +miWideLine (pDrawable, pGC, mode, npt, pPts) + DrawablePtr pDrawable; + register GCPtr pGC; + int mode; + register int npt; + register DDXPointPtr pPts; +{ + int x1, y1, x2, y2; + SpanDataRec spanDataRec; + SpanDataPtr spanData; + unsigned long pixel; + Bool projectLeft, projectRight; + LineFaceRec leftFace, rightFace, prevRightFace; + LineFaceRec firstFace; + register int first; + Bool somethingDrawn = FALSE; + Bool selfJoin; + + spanData = miSetupSpanData (pGC, &spanDataRec, npt); + pixel = pGC->fgPixel; + x2 = pPts->x; + y2 = pPts->y; + first = TRUE; + selfJoin = FALSE; + if (npt > 1) + { + if (mode == CoordModePrevious) + { + int nptTmp; + DDXPointPtr pPtsTmp; + + x1 = x2; + y1 = y2; + nptTmp = npt; + pPtsTmp = pPts + 1; + while (--nptTmp) + { + x1 += pPtsTmp->x; + y1 += pPtsTmp->y; + ++pPtsTmp; + } + if (x2 == x1 && y2 == y1) + selfJoin = TRUE; + } + else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) + { + selfJoin = TRUE; + } + } + projectLeft = pGC->capStyle == CapProjecting && !selfJoin; + projectRight = FALSE; + while (--npt) + { + x1 = x2; + y1 = y2; + ++pPts; + x2 = pPts->x; + y2 = pPts->y; + if (mode == CoordModePrevious) + { + x2 += x1; + y2 += y1; + } + if (x1 != x2 || y1 != y2) + { + somethingDrawn = TRUE; + if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin) + projectRight = TRUE; + miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2, + projectLeft, projectRight, &leftFace, &rightFace); + if (first) + { + if (selfJoin) + firstFace = leftFace; + else if (pGC->capStyle == CapRound) + { + if (pGC->lineWidth == 1 && !spanData) + miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1); + else + miLineArc (pDrawable, pGC, pixel, spanData, + &leftFace, (LineFacePtr) NULL, + (double)0.0, (double)0.0, + TRUE); + } + } + else + { + miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, + &prevRightFace); + } + prevRightFace = rightFace; + first = FALSE; + projectLeft = FALSE; + } + if (npt == 1 && somethingDrawn) + { + if (selfJoin) + miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, + &rightFace); + else if (pGC->capStyle == CapRound) + { + if (pGC->lineWidth == 1 && !spanData) + miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2); + else + miLineArc (pDrawable, pGC, pixel, spanData, + (LineFacePtr) NULL, &rightFace, + (double)0.0, (double)0.0, + TRUE); + } + } + } + /* handle crock where all points are coincedent */ + if (!somethingDrawn) + { + projectLeft = pGC->capStyle == CapProjecting; + miWideSegment (pDrawable, pGC, pixel, spanData, + x2, y2, x2, y2, projectLeft, projectLeft, + &leftFace, &rightFace); + if (pGC->capStyle == CapRound) + { + miLineArc (pDrawable, pGC, pixel, spanData, + &leftFace, (LineFacePtr) NULL, + (double)0.0, (double)0.0, + TRUE); + rightFace.dx = -1; /* sleezy hack to make it work */ + miLineArc (pDrawable, pGC, pixel, spanData, + (LineFacePtr) NULL, &rightFace, + (double)0.0, (double)0.0, + TRUE); + } + } + if (spanData) + miCleanupSpanData (pDrawable, pGC, spanData); +} + +#define V_TOP 0 +#define V_RIGHT 1 +#define V_BOTTOM 2 +#define V_LEFT 3 + +static void +miWideDashSegment (pDrawable, pGC, spanData, pDashOffset, pDashIndex, + x1, y1, x2, y2, projectLeft, projectRight, leftFace, rightFace) + DrawablePtr pDrawable; + register GCPtr pGC; + int *pDashOffset, *pDashIndex; + SpanDataPtr spanData; + int x1, y1, x2, y2; + Bool projectLeft, projectRight; + LineFacePtr leftFace, rightFace; +{ + int dashIndex, dashRemain; + unsigned char *pDash; + double L, l; + double k; + PolyVertexRec vertices[4]; + PolyVertexRec saveRight, saveBottom; + PolySlopeRec slopes[4]; + PolyEdgeRec left[2], right[2]; + LineFaceRec lcapFace, rcapFace; + int nleft, nright; + int h; + int y; + int dy, dx; + unsigned long pixel; + double LRemain; + double r; + double rdx, rdy; + double dashDx, dashDy; + double saveK; + Bool first = TRUE; + double lcenterx, lcentery, rcenterx, rcentery; + unsigned long fgPixel, bgPixel; + + dx = x2 - x1; + dy = y2 - y1; + dashIndex = *pDashIndex; + pDash = pGC->dash; + dashRemain = pDash[dashIndex] - *pDashOffset; + fgPixel = pGC->fgPixel; + bgPixel = pGC->bgPixel; + if (pGC->fillStyle == FillOpaqueStippled || + pGC->fillStyle == FillTiled) + { + bgPixel = fgPixel; + } + + l = ((double) pGC->lineWidth) / 2.0; + if (dx == 0) + { + L = dy; + rdx = 0; + rdy = l; + if (dy < 0) + { + L = -dy; + rdy = -l; + } + } + else if (dy == 0) + { + L = dx; + rdx = l; + rdy = 0; + if (dx < 0) + { + L = -dx; + rdx = -l; + } + } + else + { + L = hypot ((double) dx, (double) dy); + r = l / L; + + rdx = r * dx; + rdy = r * dy; + } + k = l * L; + LRemain = L; + /* All position comments are relative to a line with dx and dy > 0, + * but the code does not depend on this */ + /* top */ + slopes[V_TOP].dx = dx; + slopes[V_TOP].dy = dy; + slopes[V_TOP].k = k; + /* right */ + slopes[V_RIGHT].dx = -dy; + slopes[V_RIGHT].dy = dx; + slopes[V_RIGHT].k = 0; + /* bottom */ + slopes[V_BOTTOM].dx = -dx; + slopes[V_BOTTOM].dy = -dy; + slopes[V_BOTTOM].k = k; + /* left */ + slopes[V_LEFT].dx = dy; + slopes[V_LEFT].dy = -dx; + slopes[V_LEFT].k = 0; + + /* preload the start coordinates */ + vertices[V_RIGHT].x = vertices[V_TOP].x = rdy; + vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx; + + vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy; + vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx; + + if (projectLeft) + { + vertices[V_TOP].x -= rdx; + vertices[V_TOP].y -= rdy; + + vertices[V_LEFT].x -= rdx; + vertices[V_LEFT].y -= rdy; + + slopes[V_LEFT].k = rdx * dx + rdy * dy; + } + + lcenterx = x1; + lcentery = y1; + + if (pGC->capStyle == CapRound) + { + lcapFace.dx = dx; + lcapFace.dy = dy; + lcapFace.x = x1; + lcapFace.y = y1; + + rcapFace.dx = -dx; + rcapFace.dy = -dy; + rcapFace.x = x1; + rcapFace.y = y1; + } + while (LRemain > dashRemain) + { + dashDx = (dashRemain * dx) / L; + dashDy = (dashRemain * dy) / L; + + rcenterx = lcenterx + dashDx; + rcentery = lcentery + dashDy; + + vertices[V_RIGHT].x += dashDx; + vertices[V_RIGHT].y += dashDy; + + vertices[V_BOTTOM].x += dashDx; + vertices[V_BOTTOM].y += dashDy; + + slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy; + + if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) + { + if (pGC->lineStyle == LineOnOffDash && + pGC->capStyle == CapProjecting) + { + saveRight = vertices[V_RIGHT]; + saveBottom = vertices[V_BOTTOM]; + saveK = slopes[V_RIGHT].k; + + if (!first) + { + vertices[V_TOP].x -= rdx; + vertices[V_TOP].y -= rdy; + + vertices[V_LEFT].x -= rdx; + vertices[V_LEFT].y -= rdy; + + slopes[V_LEFT].k = vertices[V_LEFT].x * + slopes[V_LEFT].dy - + vertices[V_LEFT].y * + slopes[V_LEFT].dx; + } + + vertices[V_RIGHT].x += rdx; + vertices[V_RIGHT].y += rdy; + + vertices[V_BOTTOM].x += rdx; + vertices[V_BOTTOM].y += rdy; + + slopes[V_RIGHT].k = vertices[V_RIGHT].x * + slopes[V_RIGHT].dy - + vertices[V_RIGHT].y * + slopes[V_RIGHT].dx; + } + y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, + left, right, &nleft, &nright, &h); + pixel = (dashIndex & 1) ? bgPixel : fgPixel; + miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); + + if (pGC->lineStyle == LineOnOffDash) + { + switch (pGC->capStyle) + { + case CapProjecting: + vertices[V_BOTTOM] = saveBottom; + vertices[V_RIGHT] = saveRight; + slopes[V_RIGHT].k = saveK; + break; + case CapRound: + if (!first) + { + if (dx < 0) + { + lcapFace.xa = -vertices[V_LEFT].x; + lcapFace.ya = -vertices[V_LEFT].y; + lcapFace.k = slopes[V_LEFT].k; + } + else + { + lcapFace.xa = vertices[V_TOP].x; + lcapFace.ya = vertices[V_TOP].y; + lcapFace.k = -slopes[V_LEFT].k; + } + miLineArc (pDrawable, pGC, pixel, spanData, + &lcapFace, (LineFacePtr) NULL, + lcenterx, lcentery, FALSE); + } + if (dx < 0) + { + rcapFace.xa = vertices[V_BOTTOM].x; + rcapFace.ya = vertices[V_BOTTOM].y; + rcapFace.k = slopes[V_RIGHT].k; + } + else + { + rcapFace.xa = -vertices[V_RIGHT].x; + rcapFace.ya = -vertices[V_RIGHT].y; + rcapFace.k = -slopes[V_RIGHT].k; + } + miLineArc (pDrawable, pGC, pixel, spanData, + (LineFacePtr) NULL, &rcapFace, + rcenterx, rcentery, FALSE); + break; + } + } + } + LRemain -= dashRemain; + ++dashIndex; + if (dashIndex == pGC->numInDashList) + dashIndex = 0; + dashRemain = pDash[dashIndex]; + + lcenterx = rcenterx; + lcentery = rcentery; + + vertices[V_TOP] = vertices[V_RIGHT]; + vertices[V_LEFT] = vertices[V_BOTTOM]; + slopes[V_LEFT].k = -slopes[V_RIGHT].k; + first = FALSE; + } + + if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) + { + vertices[V_TOP].x -= dx; + vertices[V_TOP].y -= dy; + + vertices[V_LEFT].x -= dx; + vertices[V_LEFT].y -= dy; + + vertices[V_RIGHT].x = rdy; + vertices[V_RIGHT].y = -rdx; + + vertices[V_BOTTOM].x = -rdy; + vertices[V_BOTTOM].y = rdx; + + + if (projectRight) + { + vertices[V_RIGHT].x += rdx; + vertices[V_RIGHT].y += rdy; + + vertices[V_BOTTOM].x += rdx; + vertices[V_BOTTOM].y += rdy; + slopes[V_RIGHT].k = vertices[V_RIGHT].x * + slopes[V_RIGHT].dy - + vertices[V_RIGHT].y * + slopes[V_RIGHT].dx; + } + else + slopes[V_RIGHT].k = 0; + + if (!first && pGC->lineStyle == LineOnOffDash && + pGC->capStyle == CapProjecting) + { + vertices[V_TOP].x -= rdx; + vertices[V_TOP].y -= rdy; + + vertices[V_LEFT].x -= rdx; + vertices[V_LEFT].y -= rdy; + slopes[V_LEFT].k = vertices[V_LEFT].x * + slopes[V_LEFT].dy - + vertices[V_LEFT].y * + slopes[V_LEFT].dx; + } + else + slopes[V_LEFT].k += dx * dx + dy * dy; + + + y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, + left, right, &nleft, &nright, &h); + + pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; + miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); + if (!first && pGC->lineStyle == LineOnOffDash && + pGC->capStyle == CapRound) + { + lcapFace.x = x2; + lcapFace.y = y2; + if (dx < 0) + { + lcapFace.xa = -vertices[V_LEFT].x; + lcapFace.ya = -vertices[V_LEFT].y; + lcapFace.k = slopes[V_LEFT].k; + } + else + { + lcapFace.xa = vertices[V_TOP].x; + lcapFace.ya = vertices[V_TOP].y; + lcapFace.k = -slopes[V_LEFT].k; + } + miLineArc (pDrawable, pGC, pixel, spanData, + &lcapFace, (LineFacePtr) NULL, + rcenterx, rcentery, FALSE); + } + } + dashRemain = ((double) dashRemain) - LRemain; + if (dashRemain == 0) + { + dashIndex++; + if (dashIndex == pGC->numInDashList) + dashIndex = 0; + dashRemain = pDash[dashIndex]; + } + + leftFace->x = x1; + leftFace->y = y1; + leftFace->dx = dx; + leftFace->dy = dy; + leftFace->xa = rdy; + leftFace->ya = -rdx; + leftFace->k = k; + + rightFace->x = x2; + rightFace->y = y2; + rightFace->dx = -dx; + rightFace->dy = -dy; + rightFace->xa = -rdy; + rightFace->ya = rdx; + rightFace->k = k; + + *pDashIndex = dashIndex; + *pDashOffset = pDash[dashIndex] - dashRemain; +} + +void +miWideDash (pDrawable, pGC, mode, npt, pPts) + DrawablePtr pDrawable; + register GCPtr pGC; + int mode; + register int npt; + register DDXPointPtr pPts; +{ + int x1, y1, x2, y2; + unsigned long pixel; + Bool projectLeft, projectRight; + LineFaceRec leftFace, rightFace, prevRightFace; + LineFaceRec firstFace; + int first; + int dashIndex, dashOffset; + register int prevDashIndex; + SpanDataRec spanDataRec; + SpanDataPtr spanData; + Bool somethingDrawn = FALSE; + Bool selfJoin; + Bool endIsFg, startIsFg, firstIsFg = FALSE, prevIsFg; + + /* XXX backward compatibility */ + if (pGC->lineWidth == 0) + { + miZeroDashLine (pDrawable, pGC, mode, npt, pPts); + return; + } + if (pGC->lineStyle == LineDoubleDash && + (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled)) + { + miWideLine (pDrawable, pGC, mode, npt, pPts); + return; + } + if (npt == 0) + return; + spanData = miSetupSpanData (pGC, &spanDataRec, npt); + x2 = pPts->x; + y2 = pPts->y; + first = TRUE; + selfJoin = FALSE; + if (mode == CoordModePrevious) + { + int nptTmp; + DDXPointPtr pPtsTmp; + + x1 = x2; + y1 = y2; + nptTmp = npt; + pPtsTmp = pPts + 1; + while (--nptTmp) + { + x1 += pPtsTmp->x; + y1 += pPtsTmp->y; + ++pPtsTmp; + } + if (x2 == x1 && y2 == y1) + selfJoin = TRUE; + } + else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) + { + selfJoin = TRUE; + } + projectLeft = pGC->capStyle == CapProjecting && !selfJoin; + projectRight = FALSE; + dashIndex = 0; + dashOffset = 0; + miStepDash ((int)pGC->dashOffset, &dashIndex, + pGC->dash, (int)pGC->numInDashList, &dashOffset); + while (--npt) + { + x1 = x2; + y1 = y2; + ++pPts; + x2 = pPts->x; + y2 = pPts->y; + if (mode == CoordModePrevious) + { + x2 += x1; + y2 += y1; + } + if (x1 != x2 || y1 != y2) + { + somethingDrawn = TRUE; + if (npt == 1 && pGC->capStyle == CapProjecting && + (!selfJoin || !firstIsFg)) + projectRight = TRUE; + prevDashIndex = dashIndex; + miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex, + x1, y1, x2, y2, + projectLeft, projectRight, &leftFace, &rightFace); + startIsFg = !(prevDashIndex & 1); + endIsFg = (dashIndex & 1) ^ (dashOffset != 0); + if (pGC->lineStyle == LineDoubleDash || startIsFg) + { + pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel; + if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) + { + if (first && selfJoin) + { + firstFace = leftFace; + firstIsFg = startIsFg; + } + else if (pGC->capStyle == CapRound) + miLineArc (pDrawable, pGC, pixel, spanData, + &leftFace, (LineFacePtr) NULL, + (double)0.0, (double)0.0, TRUE); + } + else + { + miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, + &prevRightFace); + } + } + prevRightFace = rightFace; + prevIsFg = endIsFg; + first = FALSE; + projectLeft = FALSE; + } + if (npt == 1 && somethingDrawn) + { + if (pGC->lineStyle == LineDoubleDash || endIsFg) + { + pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel; + if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) + { + miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, + &rightFace); + } + else + { + if (pGC->capStyle == CapRound) + miLineArc (pDrawable, pGC, pixel, spanData, + (LineFacePtr) NULL, &rightFace, + (double)0.0, (double)0.0, TRUE); + } + } + else + { + /* glue a cap to the start of the line if + * we're OnOffDash and ended on odd dash + */ + if (selfJoin && firstIsFg) + { + pixel = pGC->fgPixel; + if (pGC->capStyle == CapProjecting) + miLineProjectingCap (pDrawable, pGC, pixel, spanData, + &firstFace, TRUE, + (double)0.0, (double)0.0, TRUE); + else if (pGC->capStyle == CapRound) + miLineArc (pDrawable, pGC, pixel, spanData, + &firstFace, (LineFacePtr) NULL, + (double)0.0, (double)0.0, TRUE); + } + } + } + } + /* handle crock where all points are coincident */ + if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) + { + /* not the same as endIsFg computation above */ + pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; + switch (pGC->capStyle) { + case CapRound: + miLineArc (pDrawable, pGC, pixel, spanData, + (LineFacePtr) NULL, (LineFacePtr) NULL, + (double)x2, (double)y2, + FALSE); + break; + case CapProjecting: + x1 = pGC->lineWidth; + miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, + x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1); + break; + } + } + if (spanData) + miCleanupSpanData (pDrawable, pGC, spanData); +} + +/* these are stubs to allow old ddx ValidateGCs to work without change */ + +void +miMiter() +{ +} + +void +miNotMiter() +{ +} diff --git a/mi/miwideline.h b/mi/miwideline.h new file mode 100644 index 000000000..71d2c369c --- /dev/null +++ b/mi/miwideline.h @@ -0,0 +1,244 @@ +/* $Xorg: miwideline.h,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +/* + +Copyright 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* Author: Keith Packard, MIT X Consortium */ + +#include "mispans.h" + +/* + * interface data to span-merging polygon filler + */ + +typedef struct _SpanData { + SpanGroup fgGroup, bgGroup; +} SpanDataRec, *SpanDataPtr; + +#define AppendSpanGroup(pGC, pixel, spanPtr, spanData) { \ + SpanGroup *group, *othergroup = NULL; \ + if (pixel == pGC->fgPixel) \ + { \ + group = &spanData->fgGroup; \ + if (pGC->lineStyle == LineDoubleDash) \ + othergroup = &spanData->bgGroup; \ + } \ + else \ + { \ + group = &spanData->bgGroup; \ + othergroup = &spanData->fgGroup; \ + } \ + miAppendSpans (group, othergroup, spanPtr); \ +} + +/* + * Polygon edge description for integer wide-line routines + */ + +typedef struct _PolyEdge { + int height; /* number of scanlines to process */ + int x; /* starting x coordinate */ + int stepx; /* fixed integral dx */ + int signdx; /* variable dx sign */ + int e; /* initial error term */ + int dy; + int dx; +} PolyEdgeRec, *PolyEdgePtr; + +#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */ + +/* + * types for general polygon routines + */ + +typedef struct _PolyVertex { + double x, y; +} PolyVertexRec, *PolyVertexPtr; + +typedef struct _PolySlope { + int dx, dy; + double k; /* x0 * dy - y0 * dx */ +} PolySlopeRec, *PolySlopePtr; + +/* + * Line face description for caps/joins + */ + +typedef struct _LineFace { + double xa, ya; + int dx, dy; + int x, y; + double k; +} LineFaceRec, *LineFacePtr; + +/* + * macros for polygon fillers + */ + +#define MIPOLYRELOADLEFT if (!left_height && left_count) { \ + left_height = left->height; \ + left_x = left->x; \ + left_stepx = left->stepx; \ + left_signdx = left->signdx; \ + left_e = left->e; \ + left_dy = left->dy; \ + left_dx = left->dx; \ + --left_count; \ + ++left; \ + } + +#define MIPOLYRELOADRIGHT if (!right_height && right_count) { \ + right_height = right->height; \ + right_x = right->x; \ + right_stepx = right->stepx; \ + right_signdx = right->signdx; \ + right_e = right->e; \ + right_dy = right->dy; \ + right_dx = right->dx; \ + --right_count; \ + ++right; \ + } + +#define MIPOLYSTEPLEFT left_x += left_stepx; \ + left_e += left_dx; \ + if (left_e > 0) \ + { \ + left_x += left_signdx; \ + left_e -= left_dy; \ + } + +#define MIPOLYSTEPRIGHT right_x += right_stepx; \ + right_e += right_dx; \ + if (right_e > 0) \ + { \ + right_x += right_signdx; \ + right_e -= right_dy; \ + } + +#define MILINESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \ + oldPixel = pGC->fgPixel; \ + if (pixel != oldPixel) { \ + DoChangeGC (pGC, GCForeground, (XID *) &pixel, FALSE); \ + ValidateGC (pDrawable, pGC); \ + } \ +} +#define MILINERESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \ + if (pixel != oldPixel) { \ + DoChangeGC (pGC, GCForeground, (XID *) &oldPixel, FALSE); \ + ValidateGC (pDrawable, pGC); \ + } \ +} + +#ifdef NOINLINEICEIL +#define ICEIL(x) ((int)ceil(x)) +#else +#ifdef __GNUC__ +static __inline int ICEIL(x) + double x; +{ + int _cTmp = x; + return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp+1; +} +#else +#define ICEIL(x) ((((x) == (_cTmp = (x))) || ((x) < 0.0)) ? _cTmp : _cTmp+1) +#define ICEILTEMPDECL static int _cTmp; +#endif +#endif + +extern void miFillPolyHelper( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + unsigned long /*pixel*/, + SpanDataPtr /*spanData*/, + int /*y*/, + int /*overall_height*/, + PolyEdgePtr /*left*/, + PolyEdgePtr /*right*/, + int /*left_count*/, + int /*right_count*/ +#endif +); +extern int miRoundJoinFace( +#if NeedFunctionPrototypes + LineFacePtr /*face*/, + PolyEdgePtr /*edge*/, + Bool * /*leftEdge*/ +#endif +); + +extern void miRoundJoinClip( +#if NeedFunctionPrototypes + LineFacePtr /*pLeft*/, + LineFacePtr /*pRight*/, + PolyEdgePtr /*edge1*/, + PolyEdgePtr /*edge2*/, + int * /*y1*/, + int * /*y2*/, + Bool * /*left1*/, + Bool * /*left2*/ +#endif +); + +extern int miRoundCapClip( +#if NeedFunctionPrototypes + LineFacePtr /*face*/, + Bool /*isInt*/, + PolyEdgePtr /*edge*/, + Bool * /*leftEdge*/ +#endif +); + +extern void miLineProjectingCap( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + unsigned long /*pixel*/, + SpanDataPtr /*spanData*/, + LineFacePtr /*face*/, + Bool /*isLeft*/, + double /*xorg*/, + double /*yorg*/, + Bool /*isInt*/ +#endif +); + +extern SpanDataPtr miSetupSpanData( +#if NeedFunctionPrototypes + GCPtr /*pGC*/, + SpanDataPtr /*spanData*/, + int /*npt*/ +#endif +); + +extern void miCleanupSpanData( +#if NeedFunctionPrototypes + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + SpanDataPtr /*spanData*/ +#endif +); diff --git a/mi/miwindow.c b/mi/miwindow.c new file mode 100644 index 000000000..f9428074c --- /dev/null +++ b/mi/miwindow.c @@ -0,0 +1,1144 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: miwindow.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#include "X.h" +#include "miscstruct.h" +#include "region.h" +#include "mi.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" + +void +miClearToBackground(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x,y; + int w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + + /* compute everything using ints to avoid overflow */ + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + extents = &pWin->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pWin->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); + if (generateExposures) + (*pScreen->WindowExposures)(pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +/* + * For SaveUnders using backing-store. The idea is that when a window is mapped + * with saveUnder set TRUE, any windows it obscures will have its backing + * store turned on setting the DIXsaveUnder bit, + * The backing-store code must be written to allow for this + */ + +/*- + *----------------------------------------------------------------------- + * miCheckSubSaveUnder -- + * Check all the inferiors of a window for coverage by saveUnder + * windows. Called from ChangeSaveUnder and CheckSaveUnder. + * This code is very inefficient. + * + * Results: + * TRUE if any windows need to have backing-store removed. + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +static Bool +miCheckSubSaveUnder(pParent, pFirst, pRegion) + register WindowPtr pParent; /* Parent to check */ + WindowPtr pFirst; /* first reconfigured window */ + RegionPtr pRegion; /* Initial area obscured by saveUnder */ +{ + register WindowPtr pChild; /* Current child */ + register ScreenPtr pScreen; /* Screen to use */ + RegionRec SubRegion; /* Area of children obscured */ + Bool res = FALSE; /* result */ + Bool subInited=FALSE;/* SubRegion initialized */ + + pScreen = pParent->drawable.pScreen; + if ( (pChild = pParent->firstChild) ) + { + /* + * build region above first changed window + */ + + for (; pChild != pFirst; pChild = pChild->nextSib) + if (pChild->viewable && pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + + /* + * check region below and including first changed window + */ + + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + { + /* + * don't save under nephew/niece windows; + * use a separate region + */ + + if (pChild->firstChild) + { + if (!subInited) + { + REGION_INIT(pScreen, &SubRegion, NullBox, 0); + subInited = TRUE; + } + REGION_COPY(pScreen, &SubRegion, pRegion); + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + &SubRegion); + } + else + { + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + pRegion); + } + + if (pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + } + } + + if (subInited) + REGION_UNINIT(pScreen, &SubRegion); + } + + /* + * Check the state of this window. DIX save unders are + * enabled for viewable windows with some client expressing + * exposure interest and which intersect the save under region + */ + + if (pParent->viewable && + ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && + REGION_NOTEMPTY(pScreen, &pParent->borderSize) && + RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, + &pParent->borderSize)) != rgnOUT) + { + if (!pParent->DIXsaveUnder) + { + pParent->DIXsaveUnder = TRUE; + (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); + } + } + else + { + if (pParent->DIXsaveUnder) + { + res = TRUE; + pParent->DIXsaveUnder = FALSE; + } + } + return res; +} + + +/*- + *----------------------------------------------------------------------- + * miChangeSaveUnder -- + * Change the save-under state of a tree of windows. Called when + * a window with saveUnder TRUE is mapped/unmapped/reconfigured. + * + * Results: + * TRUE if any windows need to have backing-store removed (which + * means that PostChangeSaveUnder needs to be called later to + * finish the job). + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +Bool +miChangeSaveUnder(pWin, first) + register WindowPtr pWin; + WindowPtr first; /* First window to check. + * Used when pWin was restacked */ +{ + RegionRec rgn; /* Area obscured by saveUnder windows */ + register ScreenPtr pScreen; + Bool res; + + if (!deltaSaveUndersViewable && !numSaveUndersViewable) + return FALSE; + numSaveUndersViewable += deltaSaveUndersViewable; + deltaSaveUndersViewable = 0; + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, &rgn, NullBox, 1); + res = miCheckSubSaveUnder (pWin->parent, + pWin->saveUnder ? first : pWin->nextSib, + &rgn); + REGION_UNINIT(pScreen, &rgn); + return res; +} + +/*- + *----------------------------------------------------------------------- + * miPostChangeSaveUnder -- + * Actually turn backing-store off for those windows that no longer + * need to have it on. + * + * Results: + * None. + * + * Side Effects: + * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those + * windows affected. + * + *----------------------------------------------------------------------- + */ +void +miPostChangeSaveUnder(pWin, pFirst) + WindowPtr pWin; + WindowPtr pFirst; +{ + register WindowPtr pParent, pChild; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + if (!(pParent = pWin->parent)) + return; + ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; + if (!pParent->DIXsaveUnder && + (pParent->backingStore == NotUseful) && pParent->backStorage) + (*ChangeWindowAttributes)(pParent, CWBackingStore); + if (!(pChild = pFirst)) + return; + while (1) + { + if (!pChild->DIXsaveUnder && + (pChild->backingStore == NotUseful) && pChild->backStorage) + (*ChangeWindowAttributes)(pChild, CWBackingStore); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib) + { + pChild = pChild->parent; + if (pChild == pParent) + return; + } + pChild = pChild->nextSib; + } +} + +void +miMarkWindow(pWin) + register WindowPtr pWin; +{ + register ValidatePtr val; + + if (pWin->valdata) + return; + val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); + val->before.oldAbsCorner.x = pWin->drawable.x; + val->before.oldAbsCorner.y = pWin->drawable.y; + val->before.borderVisible = NullRegion; + val->before.resized = FALSE; + pWin->valdata = val; +} + +Bool +miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) + WindowPtr pWin; + WindowPtr pFirst; + WindowPtr *ppLayerWin; +{ + register BoxPtr box; + register WindowPtr pChild, pLast; + Bool anyMarked = FALSE; + void (* MarkWindow)() = pWin->drawable.pScreen->MarkWindow; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* single layered systems are easy */ + if (ppLayerWin) *ppLayerWin = pWin; + + if (pWin == pFirst) + { + /* Blindly mark pWin and all of its inferiors. This is a slight + * overkill if there are mapped windows that outside pWin's border, + * but it's better than wasting time on RectIn checks. + */ + pChild = pWin; + while (1) + { + if (pChild->viewable) + { + (* MarkWindow)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + anyMarked = TRUE; + pFirst = pFirst->nextSib; + } + if ( (pChild = pFirst) ) + { + box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); + pLast = pChild->parent->lastChild; + while (1) + { + if (pChild->viewable && RECT_IN_REGION(pScreen, &pChild->borderSize, + box)) + { + (* MarkWindow)(pChild); + anyMarked = TRUE; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pLast)) + pChild = pChild->parent; + if (pChild == pLast) + break; + pChild = pChild->nextSib; + } + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + return anyMarked; +} + +/***** + * miHandleValidateExposures(pWin) + * starting at pWin, draw background in any windows that have exposure + * regions, translate the regions, restore any backing store, + * and then send any regions still exposed to the client + *****/ +void +miHandleValidateExposures(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + register ValidatePtr val; + ScreenPtr pScreen = pWin->drawable.pScreen; + void (* WindowExposures)(); + + pChild = pWin; + WindowExposures = pChild->drawable.pScreen->WindowExposures; + while (1) + { + if ( (val = pChild->valdata) ) + { + if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) + (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, + &val->after.borderExposed, + PW_BORDER); + REGION_UNINIT(pScreen, &val->after.borderExposed); + (*WindowExposures)(pChild, &val->after.exposed, NullRegion); + REGION_UNINIT(pScreen, &val->after.exposed); + xfree(val); + pChild->valdata = (ValidatePtr)NULL; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +void +miMoveWindow(pWin, x, y, pNextSib, kind) + register WindowPtr pWin; + int x,y; + WindowPtr pNextSib; + VTKind kind; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + short bw; + RegionPtr oldRegion; + DDXPointRec oldpt; + Bool anyMarked; + register ScreenPtr pScreen; + WindowPtr windowToValidate; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return ; + pScreen = pWin->drawable.pScreen; + bw = wBorderWidth (pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) + { + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->borderClip); + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + } + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + SetWinSize (pWin); + SetBorderSize (pWin); + + (*pScreen->PositionWindow)(pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) + { + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, windowToValidate, (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, pLayerWin, (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); + (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); + REGION_DESTROY(pScreen, oldRegion); + /* XXX need to retile border if ParentRelative origin */ + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + + +/* + * pValid is a region of the screen which has been + * successfully copied -- recomputed exposed regions for affected windows + */ + +static int +miRecomputeExposures (pWin, value) + register WindowPtr pWin; + pointer value; /* must conform to VisitWindowProcPtr */ +{ + register ScreenPtr pScreen; + RegionPtr pValid = (RegionPtr)value; + + if (pWin->valdata) + { + pScreen = pWin->drawable.pScreen; + /* + * compute exposed regions of this window + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->clipList, pValid); + /* + * compute exposed regions of the border + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid); + return WT_WALKCHILDREN; + } + return WT_NOMATCH; +} + +void +miSlideAndSizeWindow(pWin, x, y, w, h, pSib) + register WindowPtr pWin; + int x,y; + unsigned int w, h; + WindowPtr pSib; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + unsigned short width = pWin->drawable.width, + height = pWin->drawable.height; + short oldx = pWin->drawable.x, + oldy = pWin->drawable.y; + int bw = wBorderWidth (pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion; + Bool anyMarked; + register ScreenPtr pScreen; + WindowPtr pFirstChange; + register WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + register unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion; + RegionPtr destClip; /* portions of destination already written */ + RegionPtr oldWinClip; /* old clip list for window */ + RegionPtr borderVisible = NullRegion; /* visible area of the border */ + RegionPtr bsExposed = NullRegion; /* backing store exposures */ + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return ; + + pScreen = pWin->drawable.pScreen; + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) + { + anyMarked = FALSE; + /* + * save the visible region of the window + */ + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->winSize); + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = (RegionPtr) NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + g = pChild->winGravity; + if (g != UnmapGravity) + { + if (!gravitate[g]) + gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); + REGION_UNION(pScreen, gravitate[g], + gravitate[g], &pChild->borderClip); + } + else + { + UnmapWindow(pChild, TRUE); + anyMarked = TRUE; + } + } + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + + oldWinClip = NULL; + if (pWin->bitGravity != ForgetGravity) + { + oldWinClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldWinClip, &pWin->clipList); + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder (pWin)) + { + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) + { + if (shrunk || moved) + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, + &pWin->winSize); + else + REGION_COPY(pScreen, borderVisible, + &pWin->borderClip); + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize (pWin); + SetBorderSize (pWin); + + dw = (int)w - (int)width; + dh = (int)h - (int)height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow)(pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + pRegion = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->backStorage) + REGION_COPY(pScreen, pRegion, &pWin->clipList); + + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + + if (pWin->valdata) + { + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); + } + + GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pRegion = &pWin->clipList; /* a convenient empty region */ + if (pWin->bitGravity == ForgetGravity) + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, NullRegion, oldx, oldy); + else + { + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, nx - x, ny - y, pRegion, oldx, oldy); + } + } + + if (WasViewable) + { + /* avoid the border */ + if (HasBorder (pWin)) + { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) + { + REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip) + { + /* + * clip to new clipList + */ + REGION_COPY(pScreen, pRegion, oldWinClip); + REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); + REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) + { + if (gravitate[g]) + REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, + gravitate[g]); + } + REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else + { + REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); + REGION_DESTROY(pScreen, oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = NULL; + + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); + + /* clip to not overwrite already copied areas */ + + if (destClip) { + REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); + REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); + REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y) + (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); + + /* remove any overwritten bits from the remaining useful bits */ + + REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->winGravity != g) + continue; + REGION_INTERSECT(pScreen, pRegion, + &pChild->borderClip, gravitate[g]); + TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (!destClip) + destClip = gravitate[g]; + else + { + REGION_UNION(pScreen, destClip, destClip, gravitate[g]); + REGION_DESTROY(pScreen, gravitate[g]); + } + } + + REGION_DESTROY(pScreen, oldRegion); + REGION_DESTROY(pScreen, pRegion); + if (destClip) + REGION_DESTROY(pScreen, destClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, + VTOther); + } + else if (bsExposed) + { + (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (pWin->realized) + WindowsRestructured (); +} + +WindowPtr +miGetLayerWindow(pWin) + WindowPtr pWin; +{ + return pWin->firstChild; +} + +#ifdef SHAPE +/****** + * + * miSetShape + * The border/window shape has changed. Recompute winSize/borderSize + * and send appropriate exposure events + */ + +void +miSetShape(pWin) + register WindowPtr pWin; +{ + Bool WasViewable = (Bool)(pWin->viewable); + register ScreenPtr pScreen = pWin->drawable.pScreen; + Bool anyMarked; + WindowPtr pParent = pWin->parent; + RegionPtr pOldClip, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + CheckCursorConfinement(pWin); +} +#endif + +/* Keeps the same inside(!) origin */ + +void +miChangeBorderWidth(pWin, width) + register WindowPtr pWin; + unsigned int width; +{ + WindowPtr pParent; + int oldwidth; + Bool anyMarked; + register ScreenPtr pScreen; + Bool WasViewable = (Bool)(pWin->viewable); + Bool HadBorder; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + oldwidth = wBorderWidth (pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + pParent = pWin->parent; + if (WasViewable && width < oldwidth) + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + + pWin->borderWidth = width; + SetBorderSize (pWin); + + if (WasViewable) + { + if (width > oldwidth) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + /* + * save the old border visible region to correctly compute + * borderExposed. + */ + if (pWin->valdata && HadBorder) + { + RegionPtr borderVisible; + borderVisible = REGION_CREATE(pScreen, NULL, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, + VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +miMarkUnrealizedWindow(pChild, pWin, fromConfigure) + WindowPtr pChild; + WindowPtr pWin; + Bool fromConfigure; +{ + if ((pChild != pWin) || fromConfigure) + { + REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); + REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); + } +} diff --git a/mi/mizerarc.c b/mi/mizerarc.c new file mode 100644 index 000000000..def8d8c51 --- /dev/null +++ b/mi/mizerarc.c @@ -0,0 +1,848 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Bob Scheifler, MIT X Consortium + +********************************************************/ + +/* $Xorg: mizerarc.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ + +/* Derived from: + * "Algorithm for drawing ellipses or hyperbolae with a digital plotter" + * by M. L. V. Pitteway + * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289 + */ + +#include +#include "X.h" +#include "Xprotostr.h" +#include "miscstruct.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "mi.h" +#include "mizerarc.h" + +#define FULLCIRCLE (360 * 64) +#define OCTANT (45 * 64) +#define QUADRANT (90 * 64) +#define HALFCIRCLE (180 * 64) +#define QUADRANT3 (270 * 64) + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \ + ((d) == HALFCIRCLE ? 0.0 : \ + ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0)))))) + +#define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \ + ((d) == HALFCIRCLE ? -1.0 : \ + ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0)))))) + +#define EPSILON45 64 + +typedef struct { + int skipStart; + int haveStart; + DDXPointRec startPt; + int haveLast; + int skipLast; + DDXPointRec endPt; + int dashIndex; + int dashOffset; + int dashIndexInit; + int dashOffsetInit; +} DashInfo; + +static miZeroArcPtRec oob = {65536, 65536, 0}; + +/* + * (x - l)^2 / (W/2)^2 + (y + H/2)^2 / (H/2)^2 = 1 + * + * where l is either 0 or .5 + * + * alpha = 4(W^2) + * beta = 4(H^2) + * gamma = 0 + * u = 2(W^2)H + * v = 4(H^2)l + * k = -4(H^2)(l^2) + * + */ + +Bool +miZeroArcSetup(arc, info, ok360) + register xArc *arc; + register miZeroArcRec *info; + Bool ok360; +{ + int l; + int angle1, angle2; + int startseg, endseg; + int startAngle, endAngle; + int i, overlap; + miZeroArcPtRec start, end; + + l = arc->width & 1; + if (arc->width == arc->height) + { + info->alpha = 4; + info->beta = 4; + info->k1 = -8; + info->k3 = -16; + info->b = 12; + info->a = (arc->width << 2) - 12; + info->d = 17 - (arc->width << 1); + if (l) + { + info->b -= 4; + info->a += 4; + info->d -= 7; + } + } + else if (!arc->width || !arc->height) + { + info->alpha = 0; + info->beta = 0; + info->k1 = 0; + info->k3 = 0; + info->a = -(int)arc->height; + info->b = 0; + info->d = -1; + } + else + { + /* initial conditions */ + info->alpha = (arc->width * arc->width) << 2; + info->beta = (arc->height * arc->height) << 2; + info->k1 = info->beta << 1; + info->k3 = info->k1 + (info->alpha << 1); + info->b = l ? 0 : -info->beta; + info->a = info->alpha * arc->height; + info->d = info->b - (info->a >> 1) - (info->alpha >> 2); + if (l) + info->d -= info->beta >> 2; + info->a -= info->b; + /* take first step, d < 0 always */ + info->b -= info->k1; + info->a += info->k1; + info->d += info->b; + /* octant change, b < 0 always */ + info->k1 = -info->k1; + info->k3 = -info->k3; + info->b = -info->b; + info->d = info->b - info->a - info->d; + info->a = info->a - (info->b << 1); + } + info->dx = 1; + info->dy = 0; + info->w = (arc->width + 1) >> 1; + info->h = arc->height >> 1; + info->xorg = arc->x + (arc->width >> 1); + info->yorg = arc->y; + info->xorgo = info->xorg + l; + info->yorgo = info->yorg + arc->height; + if (!arc->width) + { + if (!arc->height) + { + info->x = 0; + info->y = 0; + info->initialMask = 0; + info->startAngle = 0; + info->endAngle = 0; + info->start = oob; + info->end = oob; + return FALSE; + } + info->x = 0; + info->y = 1; + } + else + { + info->x = 1; + info->y = 0; + } + angle1 = arc->angle1; + angle2 = arc->angle2; + if ((angle1 == 0) && (angle2 >= FULLCIRCLE)) + { + startAngle = 0; + endAngle = 0; + } + else + { + if (angle2 > FULLCIRCLE) + angle2 = FULLCIRCLE; + else if (angle2 < -FULLCIRCLE) + angle2 = -FULLCIRCLE; + if (angle2 < 0) + { + startAngle = angle1 + angle2; + endAngle = angle1; + } + else + { + startAngle = angle1; + endAngle = angle1 + angle2; + } + if (startAngle < 0) + startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; + if (startAngle >= FULLCIRCLE) + startAngle = startAngle % FULLCIRCLE; + if (endAngle < 0) + endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; + if (endAngle >= FULLCIRCLE) + endAngle = endAngle % FULLCIRCLE; + } + info->startAngle = startAngle; + info->endAngle = endAngle; + if (ok360 && (startAngle == endAngle) && arc->angle2 && + arc->width && arc->height) + { + info->initialMask = 0xf; + info->start = oob; + info->end = oob; + return TRUE; + } + startseg = startAngle / OCTANT; + if (!arc->height || (((startseg + 1) & 2) && arc->width)) + { + start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0); + if (start.x < 0) + start.x = -start.x; + start.y = -1; + } + else + { + start.y = Dsin(startAngle) * (arc->height / 2.0); + if (start.y < 0) + start.y = -start.y; + start.y = info->h - start.y; + start.x = 65536; + } + endseg = endAngle / OCTANT; + if (!arc->height || (((endseg + 1) & 2) && arc->width)) + { + end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0); + if (end.x < 0) + end.x = -end.x; + end.y = -1; + } + else + { + end.y = Dsin(endAngle) * (arc->height / 2.0); + if (end.y < 0) + end.y = -end.y; + end.y = info->h - end.y; + end.x = 65536; + } + info->firstx = start.x; + info->firsty = start.y; + info->initialMask = 0; + overlap = arc->angle2 && (endAngle <= startAngle); + for (i = 0; i < 4; i++) + { + if (overlap ? + ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) : + ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle))) + info->initialMask |= (1 << i); + } + start.mask = info->initialMask; + end.mask = info->initialMask; + startseg >>= 1; + endseg >>= 1; + overlap = overlap && (endseg == startseg); + if (start.x != end.x || start.y != end.y || !overlap) + { + if (startseg & 1) + { + if (!overlap) + info->initialMask &= ~(1 << startseg); + if (start.x > end.x || start.y > end.y) + end.mask &= ~(1 << startseg); + } + else + { + start.mask &= ~(1 << startseg); + if (((start.x < end.x || start.y < end.y) || + (start.x == end.x && start.y == end.y && (endseg & 1))) && + !overlap) + end.mask &= ~(1 << startseg); + } + if (endseg & 1) + { + end.mask &= ~(1 << endseg); + if (((start.x > end.x || start.y > end.y) || + (start.x == end.x && start.y == end.y && !(startseg & 1))) && + !overlap) + start.mask &= ~(1 << endseg); + } + else + { + if (!overlap) + info->initialMask &= ~(1 << endseg); + if (start.x < end.x || start.y < end.y) + start.mask &= ~(1 << endseg); + } + } + /* take care of case when start and stop are both near 45 */ + /* handle here rather than adding extra code to pixelization loops */ + if (startAngle && + ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0))) + { + i = (startAngle + OCTANT) % OCTANT; + if (i < EPSILON45 || i > OCTANT - EPSILON45) + { + i = (endAngle + OCTANT) % OCTANT; + if (i < EPSILON45 || i > OCTANT - EPSILON45) + { + if (start.y < 0) + { + i = Dsin(startAngle) * (arc->height / 2.0); + if (i < 0) + i = -i; + if (info->h - i == end.y) + start.mask = end.mask; + } + else + { + i = Dsin(endAngle) * (arc->height / 2.0); + if (i < 0) + i = -i; + if (info->h - i == start.y) + end.mask = start.mask; + } + } + } + } + if (startseg & 1) + { + info->start = start; + info->end = oob; + } + else + { + info->end = start; + info->start = oob; + } + if (endseg & 1) + { + info->altend = end; + if (info->altend.x < info->end.x || info->altend.y < info->end.y) + { + miZeroArcPtRec tmp; + tmp = info->altend; + info->altend = info->end; + info->end = tmp; + } + info->altstart = oob; + } + else + { + info->altstart = end; + if (info->altstart.x < info->start.x || + info->altstart.y < info->start.y) + { + miZeroArcPtRec tmp; + tmp = info->altstart; + info->altstart = info->start; + info->start = tmp; + } + info->altend = oob; + } + if (!info->start.x || !info->start.y) + { + info->initialMask = info->start.mask; + info->start = info->altstart; + } + if (!arc->width && (arc->height == 1)) + { + /* kludge! */ + info->initialMask |= info->end.mask; + info->initialMask |= info->initialMask << 1; + info->end.x = 0; + info->end.mask = 0; + } + return FALSE; +} + +#define Pixelate(xval,yval) \ + { \ + pts->x = xval; \ + pts->y = yval; \ + pts++; \ + } + +#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval); + +DDXPointPtr +miZeroArcPts(arc, pts) + xArc *arc; + register DDXPointPtr pts; +{ + miZeroArcRec info; + register int x, y, a, b, d, mask; + register int k1, k3, dx, dy; + Bool do360; + + do360 = miZeroArcSetup(arc, &info, TRUE); + MIARCSETUP(); + mask = info.initialMask; + if (!(arc->width & 1)) + { + DoPix(1, info.xorgo, info.yorg); + DoPix(3, info.xorgo, info.yorgo); + } + if (!info.end.x || !info.end.y) + { + mask = info.end.mask; + info.end = info.altend; + } + if (do360 && (arc->width == arc->height) && !(arc->width & 1)) + { + int yorgh = info.yorg + info.h; + int xorghp = info.xorg + info.h; + int xorghn = info.xorg - info.h; + + while (1) + { + Pixelate(info.xorg + x, info.yorg + y); + Pixelate(info.xorg - x, info.yorg + y); + Pixelate(info.xorg - x, info.yorgo - y); + Pixelate(info.xorg + x, info.yorgo - y); + if (a < 0) + break; + Pixelate(xorghp - y, yorgh - x); + Pixelate(xorghn + y, yorgh - x); + Pixelate(xorghn + y, yorgh + x); + Pixelate(xorghp - y, yorgh + x); + MIARCCIRCLESTEP(;); + } + if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y) + pts -= 4; + x = info.w; + y = info.h; + } + else if (do360) + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(;); + Pixelate(info.xorg + x, info.yorg + y); + Pixelate(info.xorgo - x, info.yorg + y); + Pixelate(info.xorgo - x, info.yorgo - y); + Pixelate(info.xorg + x, info.yorgo - y); + MIARCSTEP(;,;); + } + } + else + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(;); + if ((x == info.start.x) || (y == info.start.y)) + { + mask = info.start.mask; + info.start = info.altstart; + } + DoPix(0, info.xorg + x, info.yorg + y); + DoPix(1, info.xorgo - x, info.yorg + y); + DoPix(2, info.xorgo - x, info.yorgo - y); + DoPix(3, info.xorg + x, info.yorgo - y); + if ((x == info.end.x) || (y == info.end.y)) + { + mask = info.end.mask; + info.end = info.altend; + } + MIARCSTEP(;,;); + } + } + if ((x == info.start.x) || (y == info.start.y)) + mask = info.start.mask; + DoPix(0, info.xorg + x, info.yorg + y); + DoPix(2, info.xorgo - x, info.yorgo - y); + if (arc->height & 1) + { + DoPix(1, info.xorgo - x, info.yorg + y); + DoPix(3, info.xorg + x, info.yorgo - y); + } + return pts; +} + +#undef DoPix +#define DoPix(idx,xval,yval) \ + if (mask & (1 << idx)) \ + { \ + arcPts[idx]->x = xval; \ + arcPts[idx]->y = yval; \ + arcPts[idx]++; \ + } + +static void +miZeroArcDashPts(pGC, arc, dinfo, points, maxPts, evenPts, oddPts) + GCPtr pGC; + xArc *arc; + DashInfo *dinfo; + int maxPts; + register DDXPointPtr points, *evenPts, *oddPts; +{ + miZeroArcRec info; + register int x, y, a, b, d, mask; + register int k1, k3, dx, dy; + int dashRemaining; + DDXPointPtr arcPts[4]; + DDXPointPtr startPts[5], endPts[5]; + int deltas[5]; + DDXPointPtr startPt, pt, lastPt, pts; + int i, j, delta, ptsdelta, seg, startseg; + + for (i = 0; i < 4; i++) + arcPts[i] = points + (i * maxPts); + (void)miZeroArcSetup(arc, &info, FALSE); + MIARCSETUP(); + mask = info.initialMask; + startseg = info.startAngle / QUADRANT; + startPt = arcPts[startseg]; + if (!(arc->width & 1)) + { + DoPix(1, info.xorgo, info.yorg); + DoPix(3, info.xorgo, info.yorgo); + } + if (!info.end.x || !info.end.y) + { + mask = info.end.mask; + info.end = info.altend; + } + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(;); + if ((x == info.firstx) || (y == info.firsty)) + startPt = arcPts[startseg]; + if ((x == info.start.x) || (y == info.start.y)) + { + mask = info.start.mask; + info.start = info.altstart; + } + DoPix(0, info.xorg + x, info.yorg + y); + DoPix(1, info.xorgo - x, info.yorg + y); + DoPix(2, info.xorgo - x, info.yorgo - y); + DoPix(3, info.xorg + x, info.yorgo - y); + if ((x == info.end.x) || (y == info.end.y)) + { + mask = info.end.mask; + info.end = info.altend; + } + MIARCSTEP(;,;); + } + if ((x == info.firstx) || (y == info.firsty)) + startPt = arcPts[startseg]; + if ((x == info.start.x) || (y == info.start.y)) + mask = info.start.mask; + DoPix(0, info.xorg + x, info.yorg + y); + DoPix(2, info.xorgo - x, info.yorgo - y); + if (arc->height & 1) + { + DoPix(1, info.xorgo - x, info.yorg + y); + DoPix(3, info.xorg + x, info.yorgo - y); + } + for (i = 0; i < 4; i++) + { + seg = (startseg + i) & 3; + pt = points + (seg * maxPts); + if (seg & 1) + { + startPts[i] = pt; + endPts[i] = arcPts[seg]; + deltas[i] = 1; + } + else + { + startPts[i] = arcPts[seg] - 1; + endPts[i] = pt - 1; + deltas[i] = -1; + } + } + startPts[4] = startPts[0]; + endPts[4] = startPt; + startPts[0] = startPt; + if (startseg & 1) + { + if (startPts[4] != endPts[4]) + endPts[4]--; + deltas[4] = 1; + } + else + { + if (startPts[0] > startPts[4]) + startPts[0]--; + if (startPts[4] < endPts[4]) + endPts[4]--; + deltas[4] = -1; + } + if (arc->angle2 < 0) + { + DDXPointPtr tmps, tmpe; + int tmpd; + + tmpd = deltas[0]; + tmps = startPts[0] - tmpd; + tmpe = endPts[0] - tmpd; + startPts[0] = endPts[4] - deltas[4]; + endPts[0] = startPts[4] - deltas[4]; + deltas[0] = -deltas[4]; + startPts[4] = tmpe; + endPts[4] = tmps; + deltas[4] = -tmpd; + tmpd = deltas[1]; + tmps = startPts[1] - tmpd; + tmpe = endPts[1] - tmpd; + startPts[1] = endPts[3] - deltas[3]; + endPts[1] = startPts[3] - deltas[3]; + deltas[1] = -deltas[3]; + startPts[3] = tmpe; + endPts[3] = tmps; + deltas[3] = -tmpd; + tmps = startPts[2] - deltas[2]; + startPts[2] = endPts[2] - deltas[2]; + endPts[2] = tmps; + deltas[2] = -deltas[2]; + } + for (i = 0; i < 5 && startPts[i] == endPts[i]; i++) + ; + if (i == 5) + return; + pt = startPts[i]; + for (j = 4; startPts[j] == endPts[j]; j--) + ; + lastPt = endPts[j] - deltas[j]; + if (dinfo->haveLast && + (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) + { + startPts[i] += deltas[i]; + } + else + { + dinfo->dashIndex = dinfo->dashIndexInit; + dinfo->dashOffset = dinfo->dashOffsetInit; + } + if (!dinfo->skipStart && (info.startAngle != info.endAngle)) + { + dinfo->startPt = *pt; + dinfo->haveStart = TRUE; + } + else if (!dinfo->skipLast && dinfo->haveStart && + (lastPt->x == dinfo->startPt.x) && + (lastPt->y == dinfo->startPt.y) && + (lastPt != startPts[i])) + endPts[j] = lastPt; + if (info.startAngle != info.endAngle) + { + dinfo->haveLast = TRUE; + dinfo->endPt = *lastPt; + } + dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset; + for (i = 0; i < 5; i++) + { + pt = startPts[i]; + lastPt = endPts[i]; + delta = deltas[i]; + while (pt != lastPt) + { + if (dinfo->dashIndex & 1) + { + pts = *oddPts; + ptsdelta = -1; + } + else + { + pts = *evenPts; + ptsdelta = 1; + } + while ((pt != lastPt) && --dashRemaining >= 0) + { + *pts = *pt; + pts += ptsdelta; + pt += delta; + } + if (dinfo->dashIndex & 1) + *oddPts = pts; + else + *evenPts = pts; + if (dashRemaining <= 0) + { + if (++(dinfo->dashIndex) == pGC->numInDashList) + dinfo->dashIndex = 0; + dashRemaining = pGC->dash[dinfo->dashIndex]; + } + } + } + dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining; +} + +void +miZeroPolyArc(pDraw, pGC, narcs, parcs) + DrawablePtr pDraw; + GCPtr pGC; + int narcs; + xArc *parcs; +{ + int maxPts = 0; + register int n, maxw; + register xArc *arc; + register int i; + DDXPointPtr points, pts, oddPts; + register DDXPointPtr pt; + int numPts; + Bool dospans; + int *widths; + XID fgPixel = pGC->fgPixel; + DashInfo dinfo; + + for (arc = parcs, i = narcs; --i >= 0; arc++) + { + if (!miCanZeroArc(arc)) + miPolyArc(pDraw, pGC, 1, arc); + else + { + if (arc->width > arc->height) + n = arc->width + (arc->height >> 1); + else + n = arc->height + (arc->width >> 1); + if (n > maxPts) + maxPts = n; + } + } + if (!maxPts) + return; + numPts = maxPts << 2; + dospans = (pGC->lineStyle != LineSolid) || (pGC->fillStyle != FillSolid); + if (dospans) + { + widths = (int *)ALLOCATE_LOCAL(sizeof(int) * numPts); + if (!widths) + return; + maxw = 0; + } + if (pGC->lineStyle != LineSolid) + { + numPts <<= 1; + dinfo.haveStart = FALSE; + dinfo.skipStart = FALSE; + dinfo.haveLast = FALSE; + dinfo.dashIndexInit = 0; + dinfo.dashOffsetInit = 0; + miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit, + (unsigned char *) pGC->dash, (int)pGC->numInDashList, + &dinfo.dashOffsetInit); + } + points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * numPts); + if (!points) + { + if (dospans) + { + DEALLOCATE_LOCAL(widths); + } + return; + } + for (arc = parcs, i = narcs; --i >= 0; arc++) + { + if (miCanZeroArc(arc)) + { + if (pGC->lineStyle == LineSolid) + pts = miZeroArcPts(arc, points); + else + { + pts = points; + oddPts = &points[(numPts >> 1) - 1]; + dinfo.skipLast = i; + miZeroArcDashPts(pGC, arc, &dinfo, + oddPts + 1, maxPts, &pts, &oddPts); + dinfo.skipStart = TRUE; + } + n = pts - points; + if (!dospans) + (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points); + else + { + if (n > maxw) + { + while (maxw < n) + widths[maxw++] = 1; + } + if (pGC->miTranslate) + { + for (pt = points; pt != pts; pt++) + { + pt->x += pDraw->x; + pt->y += pDraw->y; + } + } + (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE); + } + if (pGC->lineStyle != LineDoubleDash) + continue; + if ((pGC->fillStyle == FillSolid) || + (pGC->fillStyle == FillStippled)) + { + DoChangeGC(pGC, GCForeground, (XID *)&pGC->bgPixel, 0); + ValidateGC(pDraw, pGC); + } + pts = &points[numPts >> 1]; + oddPts++; + n = pts - oddPts; + if (!dospans) + (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts); + else + { + if (n > maxw) + { + while (maxw < n) + widths[maxw++] = 1; + } + if (pGC->miTranslate) + { + for (pt = oddPts; pt != pts; pt++) + { + pt->x += pDraw->x; + pt->y += pDraw->y; + } + } + (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE); + } + if ((pGC->fillStyle == FillSolid) || + (pGC->fillStyle == FillStippled)) + { + DoChangeGC(pGC, GCForeground, &fgPixel, 0); + ValidateGC(pDraw, pGC); + } + } + } + DEALLOCATE_LOCAL(points); + if (dospans) + { + DEALLOCATE_LOCAL(widths); + } +} diff --git a/mi/mizerarc.h b/mi/mizerarc.h new file mode 100644 index 000000000..68c8ce3de --- /dev/null +++ b/mi/mizerarc.h @@ -0,0 +1,137 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mizerarc.h,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ + +typedef struct { + int x; + int y; + int mask; +} miZeroArcPtRec; + +typedef struct { + int x, y, k1, k3, a, b, d, dx, dy; + int alpha, beta; + int xorg, yorg; + int xorgo, yorgo; + int w, h; + int initialMask; + miZeroArcPtRec start, altstart, end, altend; + int firstx, firsty; + int startAngle, endAngle; +} miZeroArcRec; + +#define miCanZeroArc(arc) (((arc)->width == (arc)->height) || \ + (((arc)->width <= 800) && ((arc)->height <= 800))) + +#define MIARCSETUP() \ + x = info.x; \ + y = info.y; \ + k1 = info.k1; \ + k3 = info.k3; \ + a = info.a; \ + b = info.b; \ + d = info.d; \ + dx = info.dx; \ + dy = info.dy + +#define MIARCOCTANTSHIFT(clause) \ + if (a < 0) \ + { \ + if (y == info.h) \ + { \ + d = -1; \ + a = b = k1 = 0; \ + } \ + else \ + { \ + dx = (k1 << 1) - k3; \ + k1 = dx - k1; \ + k3 = -k3; \ + b = b + a - (k1 >> 1); \ + d = b + ((-a) >> 1) - d + (k3 >> 3); \ + if (dx < 0) \ + a = -((-dx) >> 1) - a; \ + else \ + a = (dx >> 1) - a; \ + dx = 0; \ + dy = 1; \ + clause \ + } \ + } + +#define MIARCSTEP(move1,move2) \ + b -= k1; \ + if (d < 0) \ + { \ + x += dx; \ + y += dy; \ + a += k1; \ + d += b; \ + move1 \ + } \ + else \ + { \ + x++; \ + y++; \ + a += k3; \ + d -= a; \ + move2 \ + } + +#define MIARCCIRCLESTEP(clause) \ + b -= k1; \ + x++; \ + if (d < 0) \ + { \ + a += k1; \ + d += b; \ + } \ + else \ + { \ + y++; \ + a += k3; \ + d -= a; \ + clause \ + } + +/* mizerarc.c */ + +extern Bool miZeroArcSetup( +#if NeedFunctionPrototypes + xArc * /*arc*/, + miZeroArcRec * /*info*/, + Bool /*ok360*/ +#endif +); + +extern DDXPointPtr miZeroArcPts( +#if NeedFunctionPrototypes + xArc * /*arc*/, + DDXPointPtr /*pts*/ +#endif +); + diff --git a/mi/mizerline.c b/mi/mizerline.c new file mode 100644 index 000000000..2279cb822 --- /dev/null +++ b/mi/mizerline.c @@ -0,0 +1,960 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: mizerline.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#include "X.h" + +#include "misc.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "mi.h" +#include "miline.h" + +/* + +The bresenham error equation used in the mi/mfb/cfb line routines is: + + e = error + dx = difference in raw X coordinates + dy = difference in raw Y coordinates + M = # of steps in X direction + N = # of steps in Y direction + B = 0 to prefer diagonal steps in a given octant, + 1 to prefer axial steps in a given octant + + For X major lines: + e = 2Mdy - 2Ndx - dx - B + -2dx <= e < 0 + + For Y major lines: + e = 2Ndx - 2Mdy - dy - B + -2dy <= e < 0 + +At the start of the line, we have taken 0 X steps and 0 Y steps, +so M = 0 and N = 0: + + X major e = 2Mdy - 2Ndx - dx - B + = -dx - B + + Y major e = 2Ndx - 2Mdy - dy - B + = -dy - B + +At the end of the line, we have taken dx X steps and dy Y steps, +so M = dx and N = dy: + + X major e = 2Mdy - 2Ndx - dx - B + = 2dxdy - 2dydx - dx - B + = -dx - B + Y major e = 2Ndx - 2Mdy - dy - B + = 2dydx - 2dxdy - dy - B + = -dy - B + +Thus, the error term is the same at the start and end of the line. + +Let us consider clipping an X coordinate. There are 4 cases which +represent the two independent cases of clipping the start vs. the +end of the line and an X major vs. a Y major line. In any of these +cases, we know the number of X steps (M) and we wish to find the +number of Y steps (N). Thus, we will solve our error term equation. +If we are clipping the start of the line, we will find the smallest +N that satisfies our error term inequality. If we are clipping the +end of the line, we will find the largest number of Y steps that +satisfies the inequality. In that case, since we are representing +the Y steps as (dy - N), we will actually want to solve for the +smallest N in that equation. + +Case 1: X major, starting X coordinate moved by M steps + + -2dx <= 2Mdy - 2Ndx - dx - B < 0 + 2Ndx <= 2Mdy - dx - B + 2dx 2Ndx > 2Mdy - dx - B + 2Ndx <= 2Mdy + dx - B N > (2Mdy - dx - B) / 2dx + N <= (2Mdy + dx - B) / 2dx + +Since we are trying to find the smallest N that satisfies these +equations, we should use the > inequality to find the smallest: + + N = floor((2Mdy - dx - B) / 2dx) + 1 + = floor((2Mdy - dx - B + 2dx) / 2dx) + = floor((2Mdy + dx - B) / 2dx) + +Case 1b: X major, ending X coordinate moved to M steps + +Same derivations as Case 1, but we want the largest N that satisfies +the equations, so we use the <= inequality: + + N = floor((2Mdy + dx - B) / 2dx) + +Case 2: X major, ending X coordinate moved by M steps + + -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 + -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 + -2dx <= 2Ndx - 2Mdy - dx - B < 0 + 2Ndx >= 2Mdy + dx + B - 2dx 2Ndx < 2Mdy + dx + B + 2Ndx >= 2Mdy - dx + B N < (2Mdy + dx + B) / 2dx + N >= (2Mdy - dx + B) / 2dx + +Since we are trying to find the highest number of Y steps that +satisfies these equations, we need to find the smallest N, so +we should use the >= inequality to find the smallest: + + N = ceiling((2Mdy - dx + B) / 2dx) + = floor((2Mdy - dx + B + 2dx - 1) / 2dx) + = floor((2Mdy + dx + B - 1) / 2dx) + +Case 2b: X major, starting X coordinate moved to M steps from end + +Same derivations as Case 2, but we want the smallest number of Y +steps, so we want the highest N, so we use the < inequality: + + N = ceiling((2Mdy + dx + B) / 2dx) - 1 + = floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1 + = floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx) + = floor((2Mdy + dx + B - 1) / 2dx) + +Case 3: Y major, starting X coordinate moved by M steps + + -2dy <= 2Ndx - 2Mdy - dy - B < 0 + 2Ndx >= 2Mdy + dy + B - 2dy 2Ndx < 2Mdy + dy + B + 2Ndx >= 2Mdy - dy + B N < (2Mdy + dy + B) / 2dx + N >= (2Mdy - dy + B) / 2dx + +Since we are trying to find the smallest N that satisfies these +equations, we should use the >= inequality to find the smallest: + + N = ceiling((2Mdy - dy + B) / 2dx) + = floor((2Mdy - dy + B + 2dx - 1) / 2dx) + = floor((2Mdy - dy + B - 1) / 2dx) + 1 + +Case 3b: Y major, ending X coordinate moved to M steps + +Same derivations as Case 3, but we want the largest N that satisfies +the equations, so we use the < inequality: + + N = ceiling((2Mdy + dy + B) / 2dx) - 1 + = floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1 + = floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx) + = floor((2Mdy + dy + B - 1) / 2dx) + +Case 4: Y major, ending X coordinate moved by M steps + + -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 + -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 + -2dy <= 2Mdy - 2Ndx - dy - B < 0 + 2Ndx <= 2Mdy - dy - B + 2dy 2Ndx > 2Mdy - dy - B + 2Ndx <= 2Mdy + dy - B N > (2Mdy - dy - B) / 2dx + N <= (2Mdy + dy - B) / 2dx + +Since we are trying to find the highest number of Y steps that +satisfies these equations, we need to find the smallest N, so +we should use the > inequality to find the smallest: + + N = floor((2Mdy - dy - B) / 2dx) + 1 + +Case 4b: Y major, starting X coordinate moved to M steps from end + +Same analysis as Case 4, but we want the smallest number of Y steps +which means the largest N, so we use the <= inequality: + + N = floor((2Mdy + dy - B) / 2dx) + +Now let's try the Y coordinates, we have the same 4 cases. + +Case 5: X major, starting Y coordinate moved by N steps + + -2dx <= 2Mdy - 2Ndx - dx - B < 0 + 2Mdy >= 2Ndx + dx + B - 2dx 2Mdy < 2Ndx + dx + B + 2Mdy >= 2Ndx - dx + B M < (2Ndx + dx + B) / 2dy + M >= (2Ndx - dx + B) / 2dy + +Since we are trying to find the smallest M, we use the >= inequality: + + M = ceiling((2Ndx - dx + B) / 2dy) + = floor((2Ndx - dx + B + 2dy - 1) / 2dy) + = floor((2Ndx - dx + B - 1) / 2dy) + 1 + +Case 5b: X major, ending Y coordinate moved to N steps + +Same derivations as Case 5, but we want the largest M that satisfies +the equations, so we use the < inequality: + + M = ceiling((2Ndx + dx + B) / 2dy) - 1 + = floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1 + = floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy) + = floor((2Ndx + dx + B - 1) / 2dy) + +Case 6: X major, ending Y coordinate moved by N steps + + -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 + -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 + -2dx <= 2Ndx - 2Mdy - dx - B < 0 + 2Mdy <= 2Ndx - dx - B + 2dx 2Mdy > 2Ndx - dx - B + 2Mdy <= 2Ndx + dx - B M > (2Ndx - dx - B) / 2dy + M <= (2Ndx + dx - B) / 2dy + +Largest # of X steps means smallest M, so use the > inequality: + + M = floor((2Ndx - dx - B) / 2dy) + 1 + +Case 6b: X major, starting Y coordinate moved to N steps from end + +Same derivations as Case 6, but we want the smallest # of X steps +which means the largest M, so use the <= inequality: + + M = floor((2Ndx + dx - B) / 2dy) + +Case 7: Y major, starting Y coordinate moved by N steps + + -2dy <= 2Ndx - 2Mdy - dy - B < 0 + 2Mdy <= 2Ndx - dy - B + 2dy 2Mdy > 2Ndx - dy - B + 2Mdy <= 2Ndx + dy - B M > (2Ndx - dy - B) / 2dy + M <= (2Ndx + dy - B) / 2dy + +To find the smallest M, use the > inequality: + + M = floor((2Ndx - dy - B) / 2dy) + 1 + = floor((2Ndx - dy - B + 2dy) / 2dy) + = floor((2Ndx + dy - B) / 2dy) + +Case 7b: Y major, ending Y coordinate moved to N steps + +Same derivations as Case 7, but we want the largest M that satisfies +the equations, so use the <= inequality: + + M = floor((2Ndx + dy - B) / 2dy) + +Case 8: Y major, ending Y coordinate moved by N steps + + -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 + -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 + -2dy <= 2Mdy - 2Ndx - dy - B < 0 + 2Mdy >= 2Ndx + dy + B - 2dy 2Mdy < 2Ndx + dy + B + 2Mdy >= 2Ndx - dy + B M < (2Ndx + dy + B) / 2dy + M >= (2Ndx - dy + B) / 2dy + +To find the highest X steps, find the smallest M, use the >= inequality: + + M = ceiling((2Ndx - dy + B) / 2dy) + = floor((2Ndx - dy + B + 2dy - 1) / 2dy) + = floor((2Ndx + dy + B - 1) / 2dy) + +Case 8b: Y major, starting Y coordinate moved to N steps from the end + +Same derivations as Case 8, but we want to find the smallest # of X +steps which means the largest M, so we use the < inequality: + + M = ceiling((2Ndx + dy + B) / 2dy) - 1 + = floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1 + = floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy) + = floor((2Ndx + dy + B - 1) / 2dy) + +So, our equations are: + + 1: X major move x1 to x1+M floor((2Mdy + dx - B) / 2dx) + 1b: X major move x2 to x1+M floor((2Mdy + dx - B) / 2dx) + 2: X major move x2 to x2-M floor((2Mdy + dx + B - 1) / 2dx) + 2b: X major move x1 to x2-M floor((2Mdy + dx + B - 1) / 2dx) + + 3: Y major move x1 to x1+M floor((2Mdy - dy + B - 1) / 2dx) + 1 + 3b: Y major move x2 to x1+M floor((2Mdy + dy + B - 1) / 2dx) + 4: Y major move x2 to x2-M floor((2Mdy - dy - B) / 2dx) + 1 + 4b: Y major move x1 to x2-M floor((2Mdy + dy - B) / 2dx) + + 5: X major move y1 to y1+N floor((2Ndx - dx + B - 1) / 2dy) + 1 + 5b: X major move y2 to y1+N floor((2Ndx + dx + B - 1) / 2dy) + 6: X major move y2 to y2-N floor((2Ndx - dx - B) / 2dy) + 1 + 6b: X major move y1 to y2-N floor((2Ndx + dx - B) / 2dy) + + 7: Y major move y1 to y1+N floor((2Ndx + dy - B) / 2dy) + 7b: Y major move y2 to y1+N floor((2Ndx + dy - B) / 2dy) + 8: Y major move y2 to y2-N floor((2Ndx + dy + B - 1) / 2dy) + 8b: Y major move y1 to y2-N floor((2Ndx + dy + B - 1) / 2dy) + +We have the following constraints on all of the above terms: + + 0 < M,N <= 2^15 2^15 can be imposed by miZeroClipLine + 0 <= dx/dy <= 2^16 - 1 + 0 <= B <= 1 + +The floor in all of the above equations can be accomplished with a +simple C divide operation provided that both numerator and denominator +are positive. + +Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0 +and moving a Y coordinate implies dy != 0, we know that the denominators +are all > 0. + +For all lines, (-B) and (B-1) are both either 0 or -1, depending on the +bias. Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1 +or > 0 to prove that the numerators are positive (or zero). + +For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the +constraints, the first four equations all have numerators >= 0. + +For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy +So (2Mdy - dy) > 0, since they are Y major lines. Also, (2Mdy + dy) >= 3dy +or (2Mdy + dy) > 0. So all of their numerators are >= 0. + +For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx) +>= dx > 0. Similarly (2Ndx + dx) >= 3dx > 0. So all numerators >= 0. + +For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators +are > 0. + +To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy. This +is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1) + <= 2^16 * (2^16 - 1) + (2^16 - 1) + <= 2^32 - 2^16 + 2^16 - 1 + <= 2^32 - 1 +Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of +the numerator is therefore (2^32 - 1), which does not overflow an unsigned +32 bit variable. + +*/ + +#define MIOUTCODES(outcode, x, y, xmin, ymin, xmax, ymax) \ +{\ + if (x < xmin) outcode |= OUT_LEFT;\ + if (x > xmax) outcode |= OUT_RIGHT;\ + if (y < ymin) outcode |= OUT_ABOVE;\ + if (y > ymax) outcode |= OUT_BELOW;\ +} + +/* Bit codes for the terms of the 16 clipping equations defined below. */ + +#define T_2NDX (1 << 0) +#define T_2MDY (0) /* implicit term */ +#define T_DXNOTY (1 << 1) +#define T_DYNOTX (0) /* implicit term */ +#define T_SUBDXORY (1 << 2) +#define T_ADDDX (T_DXNOTY) /* composite term */ +#define T_SUBDX (T_DXNOTY | T_SUBDXORY) /* composite term */ +#define T_ADDDY (T_DYNOTX) /* composite term */ +#define T_SUBDY (T_DYNOTX | T_SUBDXORY) /* composite term */ +#define T_BIASSUBONE (1 << 3) +#define T_SUBBIAS (0) /* implicit term */ +#define T_DIV2DX (1 << 4) +#define T_DIV2DY (0) /* implicit term */ +#define T_ADDONE (1 << 5) + +/* Bit masks defining the 16 equations used in miZeroClipLine. */ + +#define EQN1 (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) +#define EQN1B (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) +#define EQN2 (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) +#define EQN2B (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) + +#define EQN3 (T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE) +#define EQN3B (T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX) +#define EQN4 (T_2MDY | T_SUBDY | T_SUBBIAS | T_DIV2DX | T_ADDONE) +#define EQN4B (T_2MDY | T_ADDDY | T_SUBBIAS | T_DIV2DX) + +#define EQN5 (T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE) +#define EQN5B (T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY) +#define EQN6 (T_2NDX | T_SUBDX | T_SUBBIAS | T_DIV2DY | T_ADDONE) +#define EQN6B (T_2NDX | T_ADDDX | T_SUBBIAS | T_DIV2DY) + +#define EQN7 (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) +#define EQN7B (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) +#define EQN8 (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) +#define EQN8B (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) + +/* miZeroClipLine + * + * returns: 1 for partially clipped line + * -1 for completely clipped line + * + */ +int +miZeroClipLine(xmin, ymin, xmax, ymax, + new_x1, new_y1, new_x2, new_y2, + adx, ady, + pt1_clipped, pt2_clipped, octant, bias, oc1, oc2) + int xmin, ymin, xmax, ymax; + int *new_x1, *new_y1, *new_x2, *new_y2; + int *pt1_clipped, *pt2_clipped; + unsigned int adx, ady; + int octant; + unsigned int bias; + int oc1, oc2; +{ + int swapped = 0; + int clipDone = 0; + CARD32 utmp; + int clip1, clip2; + int x1, y1, x2, y2; + int x1_orig, y1_orig, x2_orig, y2_orig; + int xmajor; + int negslope, anchorval; + unsigned int eqn; + + x1 = x1_orig = *new_x1; + y1 = y1_orig = *new_y1; + x2 = x2_orig = *new_x2; + y2 = y2_orig = *new_y2; + + clip1 = 0; + clip2 = 0; + + xmajor = IsXMajorOctant(octant); + bias = ((bias >> octant) & 1); + + while (1) + { + if ((oc1 & oc2) != 0) /* trivial reject */ + { + clipDone = -1; + clip1 = oc1; + clip2 = oc2; + break; + } + else if ((oc1 | oc2) == 0) /* trivial accept */ + { + clipDone = 1; + if (swapped) + { + SWAPINT_PAIR(x1, y1, x2, y2); + SWAPINT(clip1, clip2); + } + break; + } + else /* have to clip */ + { + /* only clip one point at a time */ + if (oc1 == 0) + { + SWAPINT_PAIR(x1, y1, x2, y2); + SWAPINT_PAIR(x1_orig, y1_orig, x2_orig, y2_orig); + SWAPINT(oc1, oc2); + SWAPINT(clip1, clip2); + swapped = !swapped; + } + + clip1 |= oc1; + if (oc1 & OUT_LEFT) + { + negslope = IsYDecreasingOctant(octant); + utmp = xmin - x1_orig; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN2 : EQN1; + else + eqn = (swapped) ? EQN4 : EQN3; + anchorval = y1_orig; + } + else /* clip based on far endpt */ + { + utmp = x2_orig - xmin; + if (xmajor) + eqn = (swapped) ? EQN1B : EQN2B; + else + eqn = (swapped) ? EQN3B : EQN4B; + anchorval = y2_orig; + negslope = !negslope; + } + x1 = xmin; + } + else if (oc1 & OUT_ABOVE) + { + negslope = IsXDecreasingOctant(octant); + utmp = ymin - y1_orig; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN6 : EQN5; + else + eqn = (swapped) ? EQN8 : EQN7; + anchorval = x1_orig; + } + else /* clip based on far endpt */ + { + utmp = y2_orig - ymin; + if (xmajor) + eqn = (swapped) ? EQN5B : EQN6B; + else + eqn = (swapped) ? EQN7B : EQN8B; + anchorval = x2_orig; + negslope = !negslope; + } + y1 = ymin; + } + else if (oc1 & OUT_RIGHT) + { + negslope = IsYDecreasingOctant(octant); + utmp = x1_orig - xmax; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN2 : EQN1; + else + eqn = (swapped) ? EQN4 : EQN3; + anchorval = y1_orig; + } + else /* clip based on far endpt */ + { + /* + * Technically since the equations can handle + * utmp == 32768, this overflow code isn't + * needed since X11 protocol can't generate + * a line which goes more than 32768 pixels + * to the right of a clip rectangle. + */ + utmp = xmax - x2_orig; + if (xmajor) + eqn = (swapped) ? EQN1B : EQN2B; + else + eqn = (swapped) ? EQN3B : EQN4B; + anchorval = y2_orig; + negslope = !negslope; + } + x1 = xmax; + } + else if (oc1 & OUT_BELOW) + { + negslope = IsXDecreasingOctant(octant); + utmp = y1_orig - ymax; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN6 : EQN5; + else + eqn = (swapped) ? EQN8 : EQN7; + anchorval = x1_orig; + } + else /* clip based on far endpt */ + { + /* + * Technically since the equations can handle + * utmp == 32768, this overflow code isn't + * needed since X11 protocol can't generate + * a line which goes more than 32768 pixels + * below the bottom of a clip rectangle. + */ + utmp = ymax - y2_orig; + if (xmajor) + eqn = (swapped) ? EQN5B : EQN6B; + else + eqn = (swapped) ? EQN7B : EQN8B; + anchorval = x2_orig; + negslope = !negslope; + } + y1 = ymax; + } + + if (swapped) + negslope = !negslope; + + utmp <<= 1; /* utmp = 2N or 2M */ + if (eqn & T_2NDX) + utmp = (utmp * adx); + else /* (eqn & T_2MDY) */ + utmp = (utmp * ady); + if (eqn & T_DXNOTY) + if (eqn & T_SUBDXORY) + utmp -= adx; + else + utmp += adx; + else /* (eqn & T_DYNOTX) */ + if (eqn & T_SUBDXORY) + utmp -= ady; + else + utmp += ady; + if (eqn & T_BIASSUBONE) + utmp += bias - 1; + else /* (eqn & T_SUBBIAS) */ + utmp -= bias; + if (eqn & T_DIV2DX) + utmp /= (adx << 1); + else /* (eqn & T_DIV2DY) */ + utmp /= (ady << 1); + if (eqn & T_ADDONE) + utmp++; + + if (negslope) + utmp = -utmp; + + if (eqn & T_2NDX) /* We are calculating X steps */ + x1 = anchorval + utmp; + else /* else, Y steps */ + y1 = anchorval + utmp; + + oc1 = 0; + MIOUTCODES(oc1, x1, y1, xmin, ymin, xmax, ymax); + } + } + + *new_x1 = x1; + *new_y1 = y1; + *new_x2 = x2; + *new_y2 = y2; + + *pt1_clipped = clip1; + *pt2_clipped = clip2; + + return clipDone; +} + + +/* Draw lineSolid, fillStyle-independent zero width lines. + * + * Must keep X and Y coordinates in "ints" at least until after they're + * translated and clipped to accomodate CoordModePrevious lines with very + * large coordinates. + * + * Draws the same pixels regardless of sign(dx) or sign(dy). + * + * Ken Whaley + * + */ + +/* largest positive value that can fit into a component of a point. + * Assumes that the point structure is {type x, y;} where type is + * a signed type. + */ +#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1) + +#define MI_OUTPUT_POINT(xx, yy)\ +{\ + if ( !new_span && yy == current_y)\ + {\ + if (xx < spans->x)\ + spans->x = xx;\ + ++*widths;\ + }\ + else\ + {\ + ++Nspans;\ + ++spans;\ + ++widths;\ + spans->x = xx;\ + spans->y = yy;\ + *widths = 1;\ + current_y = yy;\ + new_span = FALSE;\ + }\ +} + +void +miZeroLine(pDraw, pGC, mode, npt, pptInit) + DrawablePtr pDraw; + GCPtr pGC; + int mode; /* Origin or Previous */ + int npt; /* number of points */ + DDXPointPtr pptInit; +{ + int Nspans, current_y; + DDXPointPtr ppt; + DDXPointPtr pspanInit, spans; + int *pwidthInit, *widths, list_len; + int xleft, ytop, xright, ybottom; + int new_x1, new_y1, new_x2, new_y2; + int x, y, x1, y1, x2, y2, xstart, ystart; + int oc1, oc2; + int result; + int pt1_clipped, pt2_clipped = 0; + Bool new_span; + int signdx, signdy; + int clipdx, clipdy; + int width, height; + int adx, ady; + int octant; + unsigned int bias = miGetZeroLineBias(pDraw->pScreen); + int e, e1, e2, e3; /* Bresenham error terms */ + int length; /* length of lines == # of pixels on major axis */ + + xleft = pDraw->x; + ytop = pDraw->y; + xright = pDraw->x + pDraw->width - 1; + ybottom = pDraw->y + pDraw->height - 1; + + if (!pGC->miTranslate) + { + /* do everything in drawable-relative coordinates */ + xleft = 0; + ytop = 0; + xright -= pDraw->x; + ybottom -= pDraw->y; + } + + /* it doesn't matter whether we're in drawable or screen coordinates, + * FillSpans simply cannot take starting coordinates outside of the + * range of a DDXPointRec component. + */ + if (xright > MAX_COORDINATE) + xright = MAX_COORDINATE; + if (ybottom > MAX_COORDINATE) + ybottom = MAX_COORDINATE; + + /* since we're clipping to the drawable's boundaries & coordinate + * space boundaries, we're guaranteed that the larger of width/height + * is the longest span we'll need to output + */ + width = xright - xleft + 1; + height = ybottom - ytop + 1; + list_len = (height >= width) ? height : width; + pspanInit = (DDXPointPtr)ALLOCATE_LOCAL(list_len * sizeof(DDXPointRec)); + pwidthInit = (int *)ALLOCATE_LOCAL(list_len * sizeof(int)); + if (!pspanInit || !pwidthInit) + return; + + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + ppt = pptInit; + + xstart = ppt->x; + ystart = ppt->y; + if (pGC->miTranslate) + { + xstart += pDraw->x; + ystart += pDraw->y; + } + + /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify + * iteration logic + */ + x2 = xstart; + y2 = ystart; + oc2 = 0; + MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); + + while (--npt > 0) + { + if (Nspans > 0) + (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, + pwidthInit, FALSE); + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + + x1 = x2; + y1 = y2; + oc1 = oc2; + ++ppt; + + x2 = ppt->x; + y2 = ppt->y; + if (pGC->miTranslate && (mode != CoordModePrevious)) + { + x2 += pDraw->x; + y2 += pDraw->y; + } + else if (mode == CoordModePrevious) + { + x2 += x1; + y2 += y1; + } + + oc2 = 0; + MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); + + if (adx > ady) + { + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + length = adx; /* don't draw endpoint in main loop */ + + FIXUP_ERROR(e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) + { + result = miZeroClipLine(xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs(new_x2 - new_x1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + e += (clipdy * e2) + ((clipdx - clipdy) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) + { + MI_OUTPUT_POINT(x, y); + e += e1; + if (e >= 0) + { + y += signdy; + e += e3; + } + x += signdx; + } + } + else /* Y major line */ + { + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + length = ady; /* don't draw endpoint in main loop */ + + SetYMajorOctant(octant); + FIXUP_ERROR(e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) + { + result = miZeroClipLine(xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs(new_y2 - new_y1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + e += (clipdx * e2) + ((clipdy - clipdx) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) + { + MI_OUTPUT_POINT(x, y); + e += e1; + if (e >= 0) + { + x += signdx; + e += e3; + } + y += signdy; + } + } + } + + /* only do the capnotlast check on the last segment + * and only if the endpoint wasn't clipped. And then, if the last + * point is the same as the first point, do not draw it, unless the + * line is degenerate + */ + if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) && + (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) + { + MI_OUTPUT_POINT(x, y); + } + + if (Nspans > 0) + (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, + pwidthInit, FALSE); + + DEALLOCATE_LOCAL(pwidthInit); + DEALLOCATE_LOCAL(pspanInit); +} + +void +miZeroDashLine(dst, pgc, mode, nptInit, pptInit) +DrawablePtr dst; +GCPtr pgc; +int mode; +int nptInit; /* number of points in polyline */ +DDXPointRec *pptInit; /* points in the polyline */ +{ + /* XXX kludge until real zero-width dash code is written */ + pgc->lineWidth = 1; + miWideDash (dst, pgc, mode, nptInit, pptInit); + pgc->lineWidth = 0; +} diff --git a/os/WaitFor.c b/os/WaitFor.c new file mode 100644 index 000000000..fbc05399c --- /dev/null +++ b/os/WaitFor.c @@ -0,0 +1,613 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +/* $Xorg: WaitFor.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ + +/***************************************************************** + * OS Dependent input routines: + * + * WaitForSomething + * TimerForce, TimerSet, TimerCheck, TimerFree + * + *****************************************************************/ + +#ifdef WIN32 +#include +#endif +#include "Xos.h" /* for strings, fcntl, time */ + +#include +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + +#include +#include "X.h" +#include "misc.h" + +#include +#include "osdep.h" +#include "dixstruct.h" +#include "opaque.h" + +#ifdef DPMSExtension +#include "dpms.h" +extern void DPMSSet(); +extern void DPMSGet(); +extern CARD32 DPMSStandbyTime; +extern CARD32 DPMSSuspendTime; +extern CARD32 DPMSOffTime; +extern BOOL DPMSEnabled; +extern CARD16 DPMSPowerLevel; +#endif + +extern fd_set AllSockets; +extern fd_set AllClients; +extern fd_set LastSelectMask; +extern fd_set WellKnownConnections; +extern fd_set EnabledDevices; +extern fd_set ClientsWithInput; +extern fd_set ClientsWriteBlocked; +extern fd_set OutputPending; + +extern int ConnectionTranslation[]; + +extern Bool NewOutputPending; +extern Bool AnyClientsWriteBlocked; + +extern WorkQueuePtr workQueue; + + +#ifdef XTESTEXT1 +/* + * defined in xtestext1dd.c + */ +extern int playback_on; +#endif /* XTESTEXT1 */ + +struct _OsTimerRec { + OsTimerPtr next; + CARD32 expires; + OsTimerCallback callback; + pointer arg; +}; + +static void DoTimer(); +static OsTimerPtr timers; + +/***************** + * WaitForSomething: + * Make the server suspend until there is + * 1. data from clients or + * 2. input events available or + * 3. ddx notices something of interest (graphics + * queue ready, etc.) or + * 4. clients that have buffered replies/events are ready + * + * If the time between INPUT events is + * greater than ScreenSaverTime, the display is turned off (or + * saved, depending on the hardware). So, WaitForSomething() + * has to handle this also (that's why the select() has a timeout. + * For more info on ClientsWithInput, see ReadRequestFromClient(). + * pClientsReady is an array to store ready client->index values into. + *****************/ + +static INT32 timeTilFrob = 0; /* while screen saving */ + +int +WaitForSomething(pClientsReady) + int *pClientsReady; +{ + int i; + struct timeval waittime, *wt; + INT32 timeout; +#ifdef DPMSExtension + INT32 standbyTimeout, suspendTimeout, offTimeout; +#endif + fd_set clientsReadable; + fd_set clientsWritable; + int curclient; + int selecterr; + int nready; + fd_set devicesReadable; + CARD32 now; + + FD_ZERO(&clientsReadable); + + /* We need a while loop here to handle + crashed connections and the screen saver timeout */ + while (1) + { + /* deal with any blocked jobs */ + if (workQueue) + ProcessWorkQueue(); + + if (XFD_ANYSET (&ClientsWithInput)) + { + XFD_COPYSET (&ClientsWithInput, &clientsReadable); + break; + } +#ifdef DPMSExtension + if (ScreenSaverTime > 0 || DPMSEnabled || timers) +#else + if (ScreenSaverTime > 0 || timers) +#endif + now = GetTimeInMillis(); + wt = NULL; + if (timers) + { + while (timers && timers->expires <= now) + DoTimer(timers, now, &timers); + if (timers) + { + timeout = timers->expires - now; + waittime.tv_sec = timeout / MILLI_PER_SECOND; + waittime.tv_usec = (timeout % MILLI_PER_SECOND) * + (1000000 / MILLI_PER_SECOND); + wt = &waittime; + } + } + if (ScreenSaverTime > 0 +#ifdef DPMSExtension + || (DPMSEnabled && + (DPMSStandbyTime > 0 || DPMSSuspendTime > 0 || DPMSOffTime > 0)) +#endif + ) { +#ifdef DPMSExtension + if (ScreenSaverTime > 0) +#endif + timeout = (ScreenSaverTime - + (now - lastDeviceEventTime.milliseconds)); +#ifdef DPMSExtension + if (DPMSStandbyTime > 0) + standbyTimeout = (DPMSStandbyTime - + (now - lastDeviceEventTime.milliseconds)); + if (DPMSSuspendTime > 0) + suspendTimeout = (DPMSSuspendTime - + (now - lastDeviceEventTime.milliseconds)); + if (DPMSOffTime > 0) + offTimeout = (DPMSOffTime - + (now - lastDeviceEventTime.milliseconds)); +#endif /* DPMSExtension */ + + if (timeout <= 0 +#ifdef DPMSExtension + && ScreenSaverTime > 0 +#endif /* DPMSExtension */ + ) { + INT32 timeSinceSave; + + timeSinceSave = -timeout; + if (timeSinceSave >= timeTilFrob && timeTilFrob >= 0) + { + ResetOsBuffers(); /* not ideal, but better than nothing */ + SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive); +#ifdef DPMSExtension + if (ScreenSaverInterval > 0 && + DPMSPowerLevel == DPMSModeOn) +#else + if (ScreenSaverInterval) +#endif /* DPMSExtension */ + /* round up to the next ScreenSaverInterval */ + timeTilFrob = ScreenSaverInterval * + ((timeSinceSave + ScreenSaverInterval) / + ScreenSaverInterval); + else + timeTilFrob = -1; + } + timeout = timeTilFrob - timeSinceSave; + } + else + { + if (ScreenSaverTime > 0 && timeout > ScreenSaverTime) + timeout = ScreenSaverTime; + timeTilFrob = 0; + } +#ifdef DPMSExtension + if (DPMSEnabled) + { + if (standbyTimeout > 0 && timeout > standbyTimeout) + timeout = standbyTimeout; + if (suspendTimeout > 0 && timeout > suspendTimeout) + timeout = suspendTimeout; + if (offTimeout > 0 && timeout > offTimeout) + timeout = offTimeout; + } +#endif + if (timeout > 0 && (!wt || timeout < (timers->expires - now))) + { + waittime.tv_sec = timeout / MILLI_PER_SECOND; + waittime.tv_usec = (timeout % MILLI_PER_SECOND) * + (1000000 / MILLI_PER_SECOND); + wt = &waittime; + } +#ifdef DPMSExtension + /* don't bother unless it's switched on */ + if (DPMSEnabled) { + /* + * If this mode's enabled, and if the time's come + * and if we're still at a lesser mode, do it now. + */ + if (DPMSStandbyTime > 0) { + if (standbyTimeout <= 0) { + if (DPMSPowerLevel < DPMSModeStandby) { + DPMSSet(DPMSModeStandby); + } + } + } + /* + * and ditto. Note that since these modes can have the + * same timeouts, they can happen at the same time. + */ + if (DPMSSuspendTime > 0) { + if (suspendTimeout <= 0) { + if (DPMSPowerLevel < DPMSModeSuspend) { + DPMSSet(DPMSModeSuspend); + } + } + } + if (DPMSOffTime > 0) { + if (offTimeout <= 0) { + if (DPMSPowerLevel < DPMSModeOff) { + DPMSSet(DPMSModeOff); + } + } + } + } +#endif + } + XFD_COPYSET(&AllSockets, &LastSelectMask); + BlockHandler((pointer)&wt, (pointer)&LastSelectMask); + if (NewOutputPending) + FlushAllOutput(); +#ifdef XTESTEXT1 + /* XXX how does this interact with new write block handling? */ + if (playback_on) { + wt = &waittime; + XTestComputeWaitTime (&waittime); + } +#endif /* XTESTEXT1 */ + /* keep this check close to select() call to minimize race */ + if (dispatchException) + i = -1; + else if (AnyClientsWriteBlocked) + { + XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable); + i = Select (MAXSOCKS, &LastSelectMask, &clientsWritable, NULL, wt); + } + else + i = Select (MAXSOCKS, &LastSelectMask, NULL, NULL, wt); + selecterr = errno; + WakeupHandler(i, (pointer)&LastSelectMask); +#ifdef XTESTEXT1 + if (playback_on) { + i = XTestProcessInputAction (i, &waittime); + } +#endif /* XTESTEXT1 */ + if (i <= 0) /* An error or timeout occurred */ + { + + if (dispatchException) + return 0; + FD_ZERO(&clientsWritable); + if (i < 0) + if (selecterr == EBADF) /* Some client disconnected */ + { + CheckConnections (); + if (! XFD_ANYSET (&AllClients)) + return 0; + } + else if (selecterr == EINVAL) + { + FatalError("WaitForSomething(): select: errno=%d\n", + selecterr); + } + else if (selecterr != EINTR) + { + ErrorF("WaitForSomething(): select: errno=%d\n", + selecterr); + } + if (timers) + { + now = GetTimeInMillis(); + while (timers && timers->expires <= now) + DoTimer(timers, now, &timers); + } + if (*checkForInput[0] != *checkForInput[1]) + return 0; + } + else + { +#ifdef WIN32 + fd_set tmp_set; +#endif + if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable)) + { + NewOutputPending = TRUE; + XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending); + XFD_UNSET(&ClientsWriteBlocked, &clientsWritable); + if (! XFD_ANYSET(&ClientsWriteBlocked)) + AnyClientsWriteBlocked = FALSE; + } + + XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices); + XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); +#ifndef WIN32 + if (LastSelectMask.fds_bits[0] & WellKnownConnections.fds_bits[0]) +#else + XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections); + if (XFD_ANYSET(&tmp_set)) +#endif + QueueWorkProc(EstablishNewConnections, NULL, + (pointer)&LastSelectMask); +#ifdef DPMSExtension + if (XFD_ANYSET (&devicesReadable) && (DPMSPowerLevel != DPMSModeOn)) + DPMSSet(DPMSModeOn); +#endif + if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable)) + break; + } + } + + nready = 0; + if (XFD_ANYSET (&clientsReadable)) + { +#ifndef WIN32 + for (i=0; ipriority; + if (nready == 0 || client_priority > highest_priority) + { + /* Either we found the first client, or we found + * a client whose priority is greater than all others + * that have been found so far. Either way, we want + * to initialize the list of clients to contain just + * this client. + */ + pClientsReady[0] = client_index; + highest_priority = client_priority; + nready = 1; + } + /* the following if makes sure that multiple same-priority + * clients get batched together + */ + else if (client_priority == highest_priority) +#endif + { + pClientsReady[nready++] = client_index; + } +#ifndef WIN32 + clientsReadable.fds_bits[i] &= ~(((fd_mask)1) << curclient); + } +#else + FD_CLR(curclient, &clientsReadable); +#endif + } + } + return nready; +} + +#if 0 +/* + * This is not always a macro. + */ +ANYSET(src) + FdMask *src; +{ + int i; + + for (i=0; inext; + timer->next = NULL; + newTime = (*timer->callback)(timer, now, timer->arg); + if (newTime) + TimerSet(timer, 0, newTime, timer->callback, timer->arg); +} + +OsTimerPtr +TimerSet(timer, flags, millis, func, arg) + register OsTimerPtr timer; + int flags; + CARD32 millis; + OsTimerCallback func; + pointer arg; +{ + register OsTimerPtr *prev; + CARD32 now = GetTimeInMillis(); + + if (!timer) + { + timer = (OsTimerPtr)xalloc(sizeof(struct _OsTimerRec)); + if (!timer) + return NULL; + } + else + { + for (prev = &timers; *prev; prev = &(*prev)->next) + { + if (*prev == timer) + { + *prev = timer->next; + if (flags & TimerForceOld) + (void)(*timer->callback)(timer, now, timer->arg); + break; + } + } + } + if (!millis) + return timer; + if (!(flags & TimerAbsolute)) + millis += now; + timer->expires = millis; + timer->callback = func; + timer->arg = arg; + if (millis <= now) + { + timer->next = NULL; + millis = (*timer->callback)(timer, now, timer->arg); + if (!millis) + return timer; + } + for (prev = &timers; + *prev && millis > (*prev)->expires; + prev = &(*prev)->next) + ; + timer->next = *prev; + *prev = timer; + return timer; +} + +Bool +TimerForce(timer) + register OsTimerPtr timer; +{ + register OsTimerPtr *prev; + register CARD32 newTime; + + for (prev = &timers; *prev; prev = &(*prev)->next) + { + if (*prev == timer) + { + DoTimer(timer, GetTimeInMillis(), prev); + return TRUE; + } + } + return FALSE; +} + + +void +TimerCancel(timer) + register OsTimerPtr timer; +{ + register OsTimerPtr *prev; + + if (!timer) + return; + for (prev = &timers; *prev; prev = &(*prev)->next) + { + if (*prev == timer) + { + *prev = timer->next; + break; + } + } +} + +void +TimerFree(timer) + register OsTimerPtr timer; +{ + if (!timer) + return; + TimerCancel(timer); + xfree(timer); +} + +void +TimerCheck() +{ + register CARD32 now = GetTimeInMillis(); + + while (timers && timers->expires <= now) + DoTimer(timers, now, &timers); +} + +void +TimerInit() +{ + OsTimerPtr timer; + + while (timer = timers) + { + timers = timer->next; + xfree(timer); + } +} diff --git a/os/access.c b/os/access.c new file mode 100644 index 000000000..abca79e9d --- /dev/null +++ b/os/access.c @@ -0,0 +1,1232 @@ +/* $Xorg: access.c,v 1.5 2001/02/09 02:05:23 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ + +#ifdef WIN32 +#include +#endif + +#include +#include +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "site.h" +#include + +#ifndef WIN32 +#ifdef ESIX +#include +#else +#include +#endif +#include +#include + +#if defined(TCPCONN) || defined(STREAMSCONN) || defined(ISC) +#include +#endif /* TCPCONN || STREAMSCONN || ISC */ +#ifdef DNETCONN +#include +#include +#endif + +#ifdef hpux +# include +# ifdef HAS_IFREQ +# include +# endif +#else +#if defined(SVR4) || (defined(SYSV) && defined(i386)) +# include +#endif +#if defined(SYSV) && defined(i386) +# include +#endif +#ifdef ESIX +# include +#else +# include +#endif +#endif /* hpux */ + +#ifdef SVR4 +#include +#endif + +#ifdef ESIX +#include +#else +#include +#endif + +#endif /* WIN32 */ + +#define X_INCLUDE_NETDB_H +#include + +#include "dixstruct.h" +#include "osdep.h" + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +Bool defeatAccessControl = FALSE; + +#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len) +#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len) +#define addrEqual(fam, address, length, host) \ + ((fam) == (host)->family &&\ + (length) == (host)->len &&\ + !acmp (address, (host)->addr, length)) + +static int ConvertAddr( +#if NeedFunctionPrototypes + struct sockaddr */*saddr*/, + int */*len*/, + pointer */*addr*/ +#endif +); + +static int CheckAddr( +#if NeedFunctionPrototypes + int /*family*/, + pointer /*pAddr*/, + unsigned /*length*/ +#endif +); + +static Bool NewHost( +#if NeedFunctionPrototypes + int /*family*/, + pointer /*addr*/, + int /*len*/ +#endif +); + +typedef struct _host { + short family; + short len; + unsigned char *addr; + struct _host *next; +} HOST; + +#define MakeHost(h,l) (h)=(HOST *) xalloc(sizeof *(h)+(l));\ + if((h))\ + (h)->addr=(unsigned char *) ((h) + 1); +#define FreeHost(h) xfree(h) +static HOST *selfhosts = NULL; +static HOST *validhosts = NULL; +static int AccessEnabled = DEFAULT_ACCESS_CONTROL; +static int LocalHostEnabled = FALSE; +static int UsingXdmcp = FALSE; + + +/* + * called when authorization is not enabled to add the + * local host to the access list + */ + +void +EnableLocalHost () +{ + if (!UsingXdmcp) + { + LocalHostEnabled = TRUE; + AddLocalHosts (); + } +} + +/* + * called when authorization is enabled to keep us secure + */ +void +DisableLocalHost () +{ + HOST *self; + + LocalHostEnabled = FALSE; + for (self = selfhosts; self; self = self->next) + (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr); +} + +/* + * called at init time when XDMCP will be used; xdmcp always + * adds local hosts manually when needed + */ + +void +AccessUsingXdmcp () +{ + UsingXdmcp = TRUE; + LocalHostEnabled = FALSE; +} + + +/* + * DefineSelf (fd): + * + * Define this host for access control. Find all the hosts the OS knows about + * for this fd and add them to the selfhosts list. + */ + +#ifdef WINTCP /* NCR Wollongong based TCP */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +void +DefineSelf (fd) + int fd; +{ + /* + * The Wolongong drivers used by NCR SVR4/MP-RAS don't understand the + * socket IO calls that most other drivers seem to like. Because of + * this, this routine must be special cased for NCR. Eventually, + * this will be cleared up. + */ + + struct ipb ifnet; + struct in_ifaddr ifaddr; + struct strioctl str; + unsigned char *addr; + register HOST *host; + int family, len; + + if ((fd = open ("/dev/ip", O_RDWR, 0 )) < 0) + Error ("Getting interface configuration"); + + /* Indicate that we want to start at the begining */ + ifnet.ib_next = (struct ipb *) 1; + + while (ifnet.ib_next) + { + str.ic_cmd = IPIOC_GETIPB; + str.ic_timout = 0; + str.ic_len = sizeof (struct ipb); + str.ic_dp = (char *) &ifnet; + + if (ioctl (fd, (int) I_STR, (char *) &str) < 0) + { + close (fd); + Error ("Getting interface configuration"); + } + + ifaddr.ia_next = (struct in_ifaddr *) ifnet.if_addrlist; + str.ic_cmd = IPIOC_GETINADDR; + str.ic_timout = 0; + str.ic_len = sizeof (struct in_ifaddr); + str.ic_dp = (char *) &ifaddr; + + if (ioctl (fd, (int) I_STR, (char *) &str) < 0) + { + close (fd); + Error ("Getting interface configuration"); + } + + len = sizeof(struct sockaddr_in); + family = ConvertAddr (IA_SIN(&ifaddr), &len, (pointer *)&addr); + if (family == -1 || family == FamilyLocal) + continue; + for (host = selfhosts; + host && !addrEqual (family, addr, len, host); + host = host->next) + ; + if (host) + continue; + MakeHost(host,len) + if (host) + { + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } +#ifdef XDMCP + { + struct sockaddr broad_addr; + + /* + * If this isn't an Internet Address, don't register it. + */ + if (family != FamilyInternet) + continue; + + /* + * ignore 'localhost' entries as they're not useful + * on the other end of the wire + */ + if (len == 4 && + addr[0] == 127 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 1) + continue; + + XdmcpRegisterConnection (family, (char *)addr, len); + + +#define IA_BROADADDR(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr)) + + XdmcpRegisterBroadcastAddress ( + (struct sockaddr_in *) IA_BROADADDR(&ifaddr)); + +#undef IA_BROADADDR + } +#endif /* XDMCP */ + } + + close(fd); + + /* + * add something of FamilyLocalHost + */ + for (host = selfhosts; + host && !addrEqual(FamilyLocalHost, "", 0, host); + host = host->next); + if (!host) + { + MakeHost(host, 0); + if (host) + { + host->family = FamilyLocalHost; + host->len = 0; + acopy("", host->addr, 0); + host->next = selfhosts; + selfhosts = host; + } + } +} + +#else /* WINTCP */ + +#if !defined(SIOCGIFCONF) || (defined (hpux) && ! defined (HAS_IFREQ)) +void +DefineSelf (fd) + int fd; +{ +#if !defined(TCPCONN) && !defined(UNIXCONN) + return; +#else + register int n; + int len; + caddr_t addr; + int family; + register HOST *host; + +#if defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) \ + || defined(WIN32) + char name[100]; +#else + struct utsname name; +#endif + register struct hostent *hp; + + union { + struct sockaddr sa; + struct sockaddr_in in; + } saddr; + + struct sockaddr_in *inetaddr; + struct sockaddr_in broad_addr; + _Xgethostbynameparams hparams; + +#if defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) \ + || defined(WIN32) + if (gethostname (name, sizeof name) < 0) + hp = NULL; + else + hp = _XGethostbyname(name, hparams); +#else + /* Why not use gethostname()? Well, at least on my system, I've had to + * make an ugly kernel patch to get a name longer than 8 characters, and + * uname() lets me access to the whole string (it smashes release, you + * see), whereas gethostname() kindly truncates it for me. + */ + uname(&name); + hp = _XGethostbyname(name.nodename, hparams); +#endif + if (hp != NULL) + { + saddr.sa.sa_family = hp->h_addrtype; + inetaddr = (struct sockaddr_in *) (&(saddr.sa)); + acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length); + len = sizeof(saddr.sa); + family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr); + if ( family != -1 && family != FamilyLocal ) + { + for (host = selfhosts; + host && !addrEqual (family, addr, len, host); + host = host->next) ; + if (!host) + { + /* add this host to the host list. */ + MakeHost(host,len) + if (host) + { + host->family = family; + host->len = len; + acopy ( addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } +#ifdef XDMCP + /* + * If this is an Internet Address, but not the localhost + * address (127.0.0.1), register it. + */ + if (family == FamilyInternet && + !(len == 4 && addr[0] == 127 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 1) + ) + { + XdmcpRegisterConnection (family, (char *)addr, len); + broad_addr = *inetaddr; + ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = + htonl (INADDR_BROADCAST); + XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) + &broad_addr); + } +#endif /* XDMCP */ + } + } + } + /* + * now add a host of family FamilyLocalHost... + */ + for (host = selfhosts; + host && !addrEqual(FamilyLocalHost, "", 0, host); + host = host->next); + if (!host) + { + MakeHost(host, 0); + if (host) + { + host->family = FamilyLocalHost; + host->len = 0; + acopy("", host->addr, 0); + host->next = selfhosts; + selfhosts = host; + } + } +#endif /* !TCPCONN && !UNIXCONN */ +} + +#else +void +DefineSelf (fd) + int fd; +{ + char buf[2048]; + struct ifconf ifc; + register int n; + int len; + unsigned char * addr; + int family; + register HOST *host; + register struct ifreq *ifr; + +#ifdef DNETCONN + struct dn_naddr *dnaddr = getnodeadd(); + /* + * AF_DECnet may not be listed in the interface list. Instead use + * the supported library call to find out the local address (if any). + */ + if (dnaddr) + { + addr = (unsigned char *) dnaddr; + len = dnaddr->a_len + sizeof(dnaddr->a_len); + family = FamilyDECnet; + for (host = selfhosts; + host && !addrEqual (family, addr, len, host); + host = host->next) + ; + if (!host) + { + MakeHost(host,len) + if (host) + { + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } + } + } +#endif + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (fd, (int) SIOCGIFCONF, (pointer) &ifc) < 0) + Error ("Getting interface configuration"); + for (ifr = ifc.ifc_req +#ifdef BSD44SOCKETS + ; (char *)ifr < ifc.ifc_buf + ifc.ifc_len; + ifr = (struct ifreq *)((char *)ifr + sizeof (struct ifreq) + + (ifr->ifr_addr.sa_len > sizeof (ifr->ifr_addr) ? + ifr->ifr_addr.sa_len - sizeof (ifr->ifr_addr) : 0)) +#else + , n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++ +#endif + ) + { + len = sizeof(ifr->ifr_addr); +#ifdef DNETCONN + /* + * DECnet was handled up above. + */ + if (ifr->ifr_addr.sa_family == AF_DECnet) + continue; +#endif /* DNETCONN */ + family = ConvertAddr (&ifr->ifr_addr, &len, (pointer *)&addr); + if (family == -1 || family == FamilyLocal) + continue; + for (host = selfhosts; + host && !addrEqual (family, addr, len, host); + host = host->next) + ; + if (host) + continue; + MakeHost(host,len) + if (host) + { + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } +#ifdef XDMCP + { + struct sockaddr broad_addr; + + /* + * If this isn't an Internet Address, don't register it. + */ + if (family != FamilyInternet) + continue; + + /* + * ignore 'localhost' entries as they're not useful + * on the other end of the wire + */ + if (len == 4 && + addr[0] == 127 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 1) + continue; + + XdmcpRegisterConnection (family, (char *)addr, len); + broad_addr = ifr->ifr_addr; + ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = + htonl (INADDR_BROADCAST); +#ifdef SIOCGIFBRDADDR + { + struct ifreq broad_req; + + broad_req = *ifr; + if (ioctl (fd, SIOCGIFFLAGS, (char *) &broad_req) != -1 && + (broad_req.ifr_flags & IFF_BROADCAST) && + (broad_req.ifr_flags & IFF_UP) + ) + { + broad_req = *ifr; + if (ioctl (fd, SIOCGIFBRDADDR, &broad_req) != -1) + broad_addr = broad_req.ifr_addr; + else + continue; + } + else + continue; + } +#endif + XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr); + } +#endif + } + /* + * add something of FamilyLocalHost + */ + for (host = selfhosts; + host && !addrEqual(FamilyLocalHost, "", 0, host); + host = host->next); + if (!host) + { + MakeHost(host, 0); + if (host) + { + host->family = FamilyLocalHost; + host->len = 0; + acopy("", host->addr, 0); + host->next = selfhosts; + selfhosts = host; + } + } +} +#endif /* hpux && !HAS_IFREQ */ +#endif /* WINTCP */ + +#ifdef XDMCP +void +AugmentSelf(from, len) + pointer from; + int len; +{ + int family; + pointer addr; + register HOST *host; + + family = ConvertAddr(from, &len, (pointer *)&addr); + if (family == -1 || family == FamilyLocal) + return; + for (host = selfhosts; host; host = host->next) + { + if (addrEqual(family, addr, len, host)) + return; + } + MakeHost(host,len) + if (!host) + return; + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; +} +#endif + +void +AddLocalHosts () +{ + HOST *self; + + for (self = selfhosts; self; self = self->next) + (void) NewHost (self->family, self->addr, self->len); +} + +static char* etcx_hosts = NULL; + +/* Reset access control list to initial hosts */ +void +ResetHosts (display) + char *display; +{ + register HOST *host; + char lhostname[120], ohostname[120]; + char *hostname = ohostname; + int fnamelen; + char* etcstr = "/etc/X"; + char* dothoststr = ".hosts"; + FILE *fd; + char *ptr; + int i, hostlen; + union { + struct sockaddr sa; +#if defined(TCPCONN) || defined(STREAMSCONN) + struct sockaddr_in in; +#endif /* TCPCONN || STREAMSCONN */ +#ifdef DNETCONN + struct sockaddr_dn dn; +#endif + } saddr; +#ifdef DNETCONN + struct nodeent *np; + struct dn_naddr dnaddr, *dnaddrp, *dnet_addr(); +#endif +#ifdef K5AUTH + krb5_principal princ; + krb5_data kbuf; +#endif + int family; + pointer addr; + int len; + register struct hostent *hp; + + AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL; + LocalHostEnabled = FALSE; + while (host = validhosts) + { + validhosts = host->next; + FreeHost (host); + } + if (etcx_hosts == NULL) { + fnamelen = strlen (display); + fnamelen += strlen (etcstr); + fnamelen += strlen (dothoststr); + etcx_hosts = (char*) xalloc (fnamelen + 1); /* A memory leak? No! */ + /* eventually could use snprintf, when more systems have it */ + sprintf (etcx_hosts, "%s%s%s", etcstr, display, dothoststr); +#ifndef WIN32 +#ifdef PATH_MAX + if (fnamelen > PATH_MAX) { + /* punish stupid hackers */ + strcpy (etcx_hosts, "/dev/zero"); + } +#endif +#endif + } + if (fd = fopen (etcx_hosts, "r")) + { + while (fgets (ohostname, sizeof (ohostname), fd)) + { + if (*ohostname == '#') + continue; + if (ptr = strchr(ohostname, '\n')) + *ptr = 0; + hostlen = strlen(ohostname) + 1; + for (i = 0; i < hostlen; i++) + lhostname[i] = tolower(ohostname[i]); + hostname = ohostname; + if (!strncmp("local:", lhostname, 6)) + { + family = FamilyLocalHost; + NewHost(family, "", 0); + } +#if defined(TCPCONN) || defined(STREAMSCONN) + else if (!strncmp("inet:", lhostname, 5)) + { + family = FamilyInternet; + hostname = ohostname + 5; + } +#endif +#ifdef DNETCONN + else if (!strncmp("dnet:", lhostname, 5)) + { + family = FamilyDECnet; + hostname = ohostname + 5; + } +#endif +#ifdef SECURE_RPC + else if (!strncmp("nis:", lhostname, 4)) + { + family = FamilyNetname; + hostname = ohostname + 4; + } +#endif +#ifdef K5AUTH + else if (!strncmp("krb:", lhostname, 4)) + { + family = FamilyKrb5Principal; + hostname = ohostname + 4; + } +#endif +#ifdef DNETCONN + if ((family == FamilyDECnet) || + (ptr = strchr(hostname, ':')) && (*(ptr + 1) == ':') && + !(*ptr = '\0')) /* bash trailing colons if necessary */ + { + /* node name (DECnet names end in "::") */ + dnaddrp = dnet_addr(hostname); + if (!dnaddrp && (np = getnodebyname (hostname))) + { + /* node was specified by name */ + saddr.sa.sa_family = np->n_addrtype; + len = sizeof(saddr.sa); + if (ConvertAddr (&saddr.sa, &len, (pointer *)&addr) == FamilyDECnet) + { + bzero ((char *) &dnaddr, sizeof (dnaddr)); + dnaddr.a_len = np->n_length; + acopy (np->n_addr, dnaddr.a_addr, np->n_length); + dnaddrp = &dnaddr; + } + } + if (dnaddrp) + (void) NewHost(FamilyDECnet, (pointer)dnaddrp, + (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len))); + } + else +#endif /* DNETCONN */ +#ifdef K5AUTH + if (family == FamilyKrb5Principal) + { + krb5_parse_name(hostname, &princ); + XauKrb5Encode(princ, &kbuf); + (void) NewHost(FamilyKrb5Principal, kbuf.data, kbuf.length); + krb5_free_principal(princ); + } + else +#endif +#ifdef SECURE_RPC + if ((family == FamilyNetname) || (strchr(hostname, '@'))) + { + SecureRPCInit (); + (void) NewHost (FamilyNetname, hostname, strlen (hostname)); + } + else +#endif /* SECURE_RPC */ +#if defined(TCPCONN) || defined(STREAMSCONN) + { + _Xgethostbynameparams hparams; + + /* host name */ + if (family == FamilyInternet && + (hp = _XGethostbyname(hostname, hparams)) || + (hp = _XGethostbyname(hostname, hparams))) + { + saddr.sa.sa_family = hp->h_addrtype; + len = sizeof(saddr.sa); + if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1) + { +#ifdef h_addr /* new 4.3bsd version of gethostent */ + char **list; + + /* iterate over the addresses */ + for (list = hp->h_addr_list; *list; list++) + (void) NewHost (family, (pointer)*list, len); +#else + (void) NewHost (family, (pointer)hp->h_addr, len); +#endif + } + } + } +#endif /* TCPCONN || STREAMSCONN */ + family = FamilyWild; + } + fclose (fd); + } +} + +/* Is client on the local host */ +Bool LocalClient(client) + ClientPtr client; +{ + int alen, family, notused; + Xtransaddr *from = NULL; + pointer addr; + register HOST *host; + +#ifdef XCSECURITY + /* untrusted clients can't change host access */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to change host access\n", + client->index); + return FALSE; + } +#endif +#ifdef LBX + if (!((OsCommPtr)client->osPrivate)->trans_conn) + return FALSE; +#endif + if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn, + ¬used, &alen, &from)) + { + family = ConvertAddr ((struct sockaddr *) from, + &alen, (pointer *)&addr); + if (family == -1) + { + xfree ((char *) from); + return FALSE; + } + if (family == FamilyLocal) + { + xfree ((char *) from); + return TRUE; + } + for (host = selfhosts; host; host = host->next) + { + if (addrEqual (family, addr, alen, host)) + return TRUE; + } + xfree ((char *) from); + } + return FALSE; +} + +static Bool +AuthorizedClient(client) + ClientPtr client; +{ + if (!client || defeatAccessControl) + return TRUE; + return LocalClient(client); +} + +/* Add a host to the access control list. This is the external interface + * called from the dispatcher */ + +int +AddHost (client, family, length, pAddr) + ClientPtr client; + int family; + unsigned length; /* of bytes in pAddr */ + pointer pAddr; +{ + int len; + + if (!AuthorizedClient(client)) + return(BadAccess); + switch (family) { + case FamilyLocalHost: + len = length; + LocalHostEnabled = TRUE; + break; +#ifdef K5AUTH + case FamilyKrb5Principal: + len = length; + break; +#endif +#ifdef SECURE_RPC + case FamilyNetname: + len = length; + SecureRPCInit (); + break; +#endif + case FamilyInternet: + case FamilyDECnet: + case FamilyChaos: + if ((len = CheckAddr (family, pAddr, length)) < 0) + { + client->errorValue = length; + return (BadValue); + } + break; + case FamilyLocal: + default: + client->errorValue = family; + return (BadValue); + } + if (NewHost (family, pAddr, len)) + return Success; + return BadAlloc; +} + +Bool +ForEachHostInFamily (family, func, closure) + int family; + Bool (*func)(); + pointer closure; +{ + HOST *host; + + for (host = validhosts; host; host = host->next) + if (family == host->family && func (host->addr, host->len, closure)) + return TRUE; + return FALSE; +} + +/* Add a host to the access control list. This is the internal interface + * called when starting or resetting the server */ +static Bool +NewHost (family, addr, len) + int family; + pointer addr; + int len; +{ + register HOST *host; + + for (host = validhosts; host; host = host->next) + { + if (addrEqual (family, addr, len, host)) + return TRUE; + } + MakeHost(host,len) + if (!host) + return FALSE; + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = validhosts; + validhosts = host; + return TRUE; +} + +/* Remove a host from the access control list */ + +int +RemoveHost (client, family, length, pAddr) + ClientPtr client; + int family; + unsigned length; /* of bytes in pAddr */ + pointer pAddr; +{ + int len; + register HOST *host, **prev; + + if (!AuthorizedClient(client)) + return(BadAccess); + switch (family) { + case FamilyLocalHost: + len = length; + LocalHostEnabled = FALSE; + break; +#ifdef K5AUTH + case FamilyKrb5Principal: + len = length; + break; +#endif +#ifdef SECURE_RPC + case FamilyNetname: + len = length; + break; +#endif + case FamilyInternet: + case FamilyDECnet: + case FamilyChaos: + if ((len = CheckAddr (family, pAddr, length)) < 0) + { + client->errorValue = length; + return(BadValue); + } + break; + case FamilyLocal: + default: + client->errorValue = family; + return(BadValue); + } + for (prev = &validhosts; + (host = *prev) && (!addrEqual (family, pAddr, len, host)); + prev = &host->next) + ; + if (host) + { + *prev = host->next; + FreeHost (host); + } + return (Success); +} + +/* Get all hosts in the access control list */ +int +GetHosts (data, pnHosts, pLen, pEnabled) + pointer *data; + int *pnHosts; + int *pLen; + BOOL *pEnabled; +{ + int len; + register int n = 0; + register unsigned char *ptr; + register HOST *host; + int nHosts = 0; + + *pEnabled = AccessEnabled ? EnableAccess : DisableAccess; + for (host = validhosts; host; host = host->next) + { + nHosts++; + n += (((host->len + 3) >> 2) << 2) + sizeof(xHostEntry); + } + if (n) + { + *data = ptr = (pointer) xalloc (n); + if (!ptr) + { + return(BadAlloc); + } + for (host = validhosts; host; host = host->next) + { + len = host->len; + ((xHostEntry *)ptr)->family = host->family; + ((xHostEntry *)ptr)->length = len; + ptr += sizeof(xHostEntry); + acopy (host->addr, ptr, len); + ptr += ((len + 3) >> 2) << 2; + } + } else { + *data = NULL; + } + *pnHosts = nHosts; + *pLen = n; + return(Success); +} + +/* Check for valid address family and length, and return address length. */ + +/*ARGSUSED*/ +static int +CheckAddr (family, pAddr, length) + int family; + pointer pAddr; + unsigned length; +{ + int len; + + switch (family) + { +#if defined(TCPCONN) || defined(STREAMSCONN) + case FamilyInternet: + if (length == sizeof (struct in_addr)) + len = length; + else + len = -1; + break; +#endif +#ifdef DNETCONN + case FamilyDECnet: + { + struct dn_naddr *dnaddr = (struct dn_naddr *) pAddr; + + if ((length < sizeof(dnaddr->a_len)) || + (length < dnaddr->a_len + sizeof(dnaddr->a_len))) + len = -1; + else + len = dnaddr->a_len + sizeof(dnaddr->a_len); + if (len > sizeof(struct dn_naddr)) + len = -1; + } + break; +#endif + default: + len = -1; + } + return (len); +} + +/* Check if a host is not in the access control list. + * Returns 1 if host is invalid, 0 if we've found it. */ + +InvalidHost (saddr, len) + register struct sockaddr *saddr; + int len; +{ + int family; + pointer addr; + register HOST *selfhost, *host; + + if (!AccessEnabled) /* just let them in */ + return(0); + family = ConvertAddr (saddr, &len, (pointer *)&addr); + if (family == -1) + return 1; + if (family == FamilyLocal) + { + if (!LocalHostEnabled) + { + /* + * check to see if any local address is enabled. This + * implicitly enables local connections. + */ + for (selfhost = selfhosts; selfhost; selfhost=selfhost->next) + { + for (host = validhosts; host; host=host->next) + { + if (addrEqual (selfhost->family, selfhost->addr, + selfhost->len, host)) + return 0; + } + } + return 1; + } else + return 0; + } + for (host = validhosts; host; host = host->next) + { + if (addrEqual (family, addr, len, host)) + return (0); + } + return (1); +} + +static int +ConvertAddr (saddr, len, addr) + register struct sockaddr *saddr; + int *len; + pointer *addr; +{ + if (*len == 0) + return (FamilyLocal); + switch (saddr->sa_family) + { + case AF_UNSPEC: +#if defined(UNIXCONN) || defined(LOCALCONN) + case AF_UNIX: +#endif + return FamilyLocal; +#if defined(TCPCONN) || defined(STREAMSCONN) + case AF_INET: + *len = sizeof (struct in_addr); + *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr); + return FamilyInternet; +#endif +#ifdef DNETCONN + case AF_DECnet: + { + struct sockaddr_dn *sdn = (struct sockaddr_dn *) saddr; + *len = sdn->sdn_nodeaddrl + sizeof(sdn->sdn_nodeaddrl); + *addr = (pointer) &(sdn->sdn_add); + } + return FamilyDECnet; +#endif +#ifdef CHAOSCONN + case AF_CHAOS: + { + not implemented + } + return FamilyChaos; +#endif + default: + return -1; + } +} + +int +ChangeAccessControl(client, fEnabled) + ClientPtr client; + int fEnabled; +{ + if (!AuthorizedClient(client)) + return BadAccess; + AccessEnabled = fEnabled; + return Success; +} + +/* returns FALSE if xhost + in effect, else TRUE */ +int +GetAccessControl() +{ + return AccessEnabled; +} + diff --git a/os/auth.c b/os/auth.c new file mode 100644 index 000000000..7b914bb28 --- /dev/null +++ b/os/auth.c @@ -0,0 +1,411 @@ +/* $Xorg: auth.c,v 1.5 2001/02/09 02:05:23 xorgcvs Exp $ */ +/* + +Copyright 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * authorization hooks for the server + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef K5AUTH +# include +#endif +# include "X.h" +# include "Xauth.h" +# include "misc.h" +# include "dixstruct.h" +# include +# include +#ifdef XCSECURITY +#define _SECURITY_SERVER +# include "extensions/security.h" +#endif +#ifdef WIN32 +#include "Xw32defs.h" +#endif + +struct protocol { + unsigned short name_length; + char *name; + int (*Add)(); /* new authorization data */ + XID (*Check)(); /* verify client authorization data */ + int (*Reset)(); /* delete all authorization data entries */ + XID (*ToID)(); /* convert cookie to ID */ + int (*FromID)(); /* convert ID to cookie */ + int (*Remove)(); /* remove a specific cookie */ +#ifdef XCSECURITY + XID (*Generate)(); +#endif +}; + +extern int MitAddCookie (); +extern XID MitCheckCookie (); +extern int MitResetCookie (); +extern XID MitToID (); +extern int MitFromID (), MitRemoveCookie (); +extern XID MitGenerateCookie(); + +#ifdef HASXDMAUTH +extern int XdmAddCookie (); +extern XID XdmCheckCookie (); +extern int XdmResetCookie (); +extern XID XdmToID (); +extern int XdmFromID (), XdmRemoveCookie (); +#endif + +#ifdef SECURE_RPC +extern int SecureRPCAdd(); +extern XID SecureRPCCheck(); +extern int SecureRPCReset(); +extern XID SecureRPCToID(); +extern int SecureRPCFromID(), SecureRPCRemove(); +#endif + +#ifdef K5AUTH +extern int K5Add(); +extern XID K5Check(); +extern int K5Reset(); +extern XID K5ToID(); +extern int K5FromID(), K5Remove(); +#endif + +extern XID AuthSecurityCheck(); + +static struct protocol protocols[] = { +{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1", + MitAddCookie, MitCheckCookie, MitResetCookie, + MitToID, MitFromID, MitRemoveCookie, +#ifdef XCSECURITY + MitGenerateCookie +#endif +}, +#ifdef HASXDMAUTH +{ (unsigned short) 19, "XDM-AUTHORIZATION-1", + XdmAddCookie, XdmCheckCookie, XdmResetCookie, + XdmToID, XdmFromID, XdmRemoveCookie, +#ifdef XCSECURITY + NULL +#endif +}, +#endif +#ifdef SECURE_RPC +{ (unsigned short) 9, "SUN-DES-1", + SecureRPCAdd, SecureRPCCheck, SecureRPCReset, + SecureRPCToID, SecureRPCFromID,SecureRPCRemove, +#ifdef XCSECURITY + NULL +#endif +}, +#endif +#ifdef K5AUTH +{ (unsigned short) 14, "MIT-KERBEROS-5", + K5Add, K5Check, K5Reset, + K5ToID, K5FromID, K5Remove, +#ifdef XCSECURITY + NULL +#endif +}, +#endif +#ifdef XCSECURITY +{ (unsigned short) XSecurityAuthorizationNameLen, + XSecurityAuthorizationName, + NULL, AuthSecurityCheck, NULL, + NULL, NULL, NULL, + NULL +}, +#endif +}; + +# define NUM_AUTHORIZATION (sizeof (protocols) /\ + sizeof (struct protocol)) + +/* + * Initialize all classes of authorization by reading the + * specified authorization file + */ + +static char *authorization_file = (char *)NULL; + +static Bool ShouldLoadAuth = TRUE; + +void +InitAuthorization (file_name) +char *file_name; +{ + authorization_file = file_name; +} + +int +LoadAuthorization () +{ + FILE *f; + Xauth *auth; + int i; + int count = 0; + + ShouldLoadAuth = FALSE; + if (!authorization_file) + return 0; + f = fopen (authorization_file, "r"); + if (!f) + return 0; + while (auth = XauReadAuth (f)) { + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == auth->name_length && + memcmp (protocols[i].name, auth->name, (int) auth->name_length) == 0 && + protocols[i].Add) + { + ++count; + (*protocols[i].Add) (auth->data_length, auth->data, + FakeClientID(0)); + } + } + XauDisposeAuth (auth); + } + fclose (f); + return count; +} + +#ifdef XDMCP +/* + * XdmcpInit calls this function to discover all authorization + * schemes supported by the display + */ +void +RegisterAuthorizations () +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) + XdmcpRegisterAuthorization (protocols[i].name, + (int)protocols[i].name_length); +} +#endif + +XID +CheckAuthorization (name_length, name, data_length, data, client, reason) + unsigned int name_length; + char *name; + unsigned int data_length; + char *data; + ClientPtr client; + char **reason; /* failure message. NULL for default msg */ +{ + int i; + struct stat buf; + static time_t lastmod = 0; + + if (!authorization_file || stat(authorization_file, &buf)) + { + if (lastmod != 0) { + lastmod = 0; + ShouldLoadAuth = TRUE; /* stat lost, so force reload */ + } + } + else if (buf.st_mtime > lastmod) + { + lastmod = buf.st_mtime; + ShouldLoadAuth = TRUE; + } + if (ShouldLoadAuth) + { + if (LoadAuthorization()) + DisableLocalHost(); /* got at least one */ + else + EnableLocalHost (); + } + if (name_length) + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0) + { + return (*protocols[i].Check) (data_length, data, client, reason); + } + } + return (XID) ~0L; +} + +void +ResetAuthorization () +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) + if (protocols[i].Reset) + (*protocols[i].Reset)(); + ShouldLoadAuth = TRUE; +} + +XID +AuthorizationToID (name_length, name, data_length, data) +unsigned short name_length; +char *name; +unsigned short data_length; +char *data; +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0 && + protocols[i].ToID) + { + return (*protocols[i].ToID) (data_length, data); + } + } + return (XID) ~0L; +} + +int +AuthorizationFromID (id, name_lenp, namep, data_lenp, datap) +XID id; +unsigned short *name_lenp; +char **namep; +unsigned short *data_lenp; +char **datap; +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].FromID && + (*protocols[i].FromID) (id, data_lenp, datap)) { + *name_lenp = protocols[i].name_length; + *namep = protocols[i].name; + return 1; + } + } + return 0; +} + +int +RemoveAuthorization (name_length, name, data_length, data) +unsigned short name_length; +char *name; +unsigned short data_length; +char *data; +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0 && + protocols[i].Remove) + { + return (*protocols[i].Remove) (data_length, data); + } + } + return 0; +} + +int +AddAuthorization (name_length, name, data_length, data) +unsigned int name_length; +char *name; +unsigned int data_length; +char *data; +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0 && + protocols[i].Add) + { + return (*protocols[i].Add) (data_length, data, FakeClientID(0)); + } + } + return 0; +} + +#ifdef XCSECURITY + +XID +GenerateAuthorization(name_length, name, data_length, data, + data_length_return, data_return) +unsigned int name_length; +char *name; +unsigned int data_length; +char *data; +unsigned int *data_length_return; +char **data_return; +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0 && + protocols[i].Generate) + { + return (*protocols[i].Generate) (data_length, data, + FakeClientID(0), data_length_return, data_return); + } + } + return -1; +} + +/* A random number generator that is more unpredictable + than that shipped with some systems. + This code is taken from the C standard. */ + +static unsigned long int next = 1; + +static int +xdm_rand() +{ + next = next * 1103515245 + 12345; + return (unsigned int)(next/65536) % 32768; +} + +static void +xdm_srand(seed) + unsigned int seed; +{ + next = seed; +} + +void +GenerateRandomData (len, buf) +int len; +char *buf; +{ + static int seed; + int value; + int i; + + seed += GetTimeInMillis(); + xdm_srand (seed); + for (i = 0; i < len; i++) + { + value = xdm_rand (); + buf[i] ^= (value & 0xff00) >> 8; + } + + /* XXX add getrusage, popen("ps -ale") */ +} + +#endif /* XCSECURITY */ diff --git a/os/connection.c b/os/connection.c new file mode 100644 index 000000000..7c4b9fef3 --- /dev/null +++ b/os/connection.c @@ -0,0 +1,1281 @@ +/* $Xorg: connection.c,v 1.6 2001/02/09 02:05:23 xorgcvs Exp $ */ +/*********************************************************** + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/***************************************************************** + * Stuff to create connections --- OS dependent + * + * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets, + * CloseDownConnection, CheckConnections, AddEnabledDevice, + * RemoveEnabledDevice, OnlyListToOneClient, + * ListenToAllClients, + * + * (WaitForSomething is in its own file) + * + * In this implementation, a client socket table is not kept. + * Instead, what would be the index into the table is just the + * file descriptor of the socket. This won't work for if the + * socket ids aren't small nums (0 - 2^8) + * + *****************************************************************/ + +#ifdef WIN32 +#include +#endif +#include "X.h" +#include "Xproto.h" +#include +#include +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + +#include +#include + +#ifndef WIN32 +#include + +#ifdef hpux +#include +#include +#endif + +#ifdef AIXV3 +#include +#endif + +#if defined(TCPCONN) || defined(STREAMSCONN) +# include +# ifndef hpux +# ifdef apollo +# ifndef NO_TCP_H +# include +# endif +# else +# include +# endif +# endif +#endif + +#include +#endif /* WIN32 */ +#include "misc.h" /* for typedef of pointer */ +#include +#include "osdep.h" +#include "opaque.h" +#include "dixstruct.h" +#ifdef XAPPGROUP +#include "extensions/Xagsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#ifdef X_NOT_POSIX +#define Pid_t int +#else +#define Pid_t pid_t +#endif + +#ifdef DNETCONN +#include +#endif /* DNETCONN */ + +extern char *display; /* The display number */ +int lastfdesc; /* maximum file descriptor */ + +fd_set WellKnownConnections; /* Listener mask */ +fd_set EnabledDevices; /* mask for input devices that are on */ +fd_set AllSockets; /* select on this */ +fd_set AllClients; /* available clients */ +fd_set LastSelectMask; /* mask returned from last select call */ +fd_set ClientsWithInput; /* clients with FULL requests in buffer */ +fd_set ClientsWriteBlocked; /* clients who cannot receive output */ +fd_set OutputPending; /* clients with reply/event data ready to go */ +#ifndef _SC_OPEN_MAX +int MaxClients = MAXSOCKS; /* use MAXSOCKS if sysconf(_SC_OPEN_MAX) is not supported */ +#else +int MaxClients = 0; +#endif +Bool NewOutputPending; /* not yet attempted to write some new output */ +Bool AnyClientsWriteBlocked; /* true if some client blocked on write */ + +Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ +Bool PartialNetwork; /* continue even if unable to bind all addrs */ +static Pid_t ParentProcess; + +static Bool debug_conns = FALSE; + +fd_set IgnoredClientsWithInput; +static fd_set GrabImperviousClients; +static fd_set SavedAllClients; +static fd_set SavedAllSockets; +static fd_set SavedClientsWithInput; +int GrabInProgress = 0; + +#ifndef WIN32 +int ConnectionTranslation[MAXSOCKS]; +#else +/* SPAM ALERT !!! + * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is + * not even a known maximum value, so use something quite arbitrary for now. + * This is clearly boggus and another form of storage which doesn't use the fd + * as a direct index should really be implemented for NT. + */ +#define MAXFD 500 +int ConnectionTranslation[MAXFD]; +#endif + +XtransConnInfo *ListenTransConns = NULL; +int *ListenTransFds = NULL; +int ListenTransCount; + +extern int auditTrailLevel; + +static void ErrorConnMax( +#if NeedFunctionPrototypes +XtransConnInfo /* trans_conn */ +#endif +); + +#ifndef LBX +static +#endif +void CloseDownFileDescriptor( +#if NeedFunctionPrototypes +#ifdef LBX + ClientPtr client +#else + register OsCommPtr /*oc*/ +#endif +#endif +); + +#ifdef LBX +extern int LbxFlushClient(); +extern void LbxCloseClient(); +#endif /* LBX */ + +static XtransConnInfo +lookup_trans_conn (fd) + int fd; +{ + if (ListenTransFds) + { + int i; + for (i = 0; i < ListenTransCount; i++) + if (ListenTransFds[i] == fd) + return ListenTransConns[i]; + } + + return (NULL); +} + +#ifdef XDMCP +void XdmcpOpenDisplay(), XdmcpInit(), XdmcpReset(), XdmcpCloseDisplay(); +#endif + +/***************** + * CreateWellKnownSockets + * At initialization, create the sockets to listen on for new clients. + *****************/ + +void +CreateWellKnownSockets() +{ + int request, i; + int partial; + char port[20]; + + FD_ZERO(&AllSockets); + FD_ZERO(&AllClients); + FD_ZERO(&LastSelectMask); + FD_ZERO(&ClientsWithInput); + +#ifndef WIN32 + for (i=0; i MAXSOCKS) + { + lastfdesc = MAXSOCKS; + } + + FD_ZERO (&WellKnownConnections); + + sprintf (port, "%d", atoi (display)); + + if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial, + &ListenTransCount, &ListenTransConns) >= 0) && + (ListenTransCount >= 1)) + { + if (!PartialNetwork && partial) + { + FatalError ("Failed to establish all listening sockets"); + } + else + { + ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int)); + + for (i = 0; i < ListenTransCount; i++) + { + int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); + + ListenTransFds[i] = fd; + FD_SET (fd, &WellKnownConnections); + + if (!_XSERVTransIsLocal (ListenTransConns[i])) + { + DefineSelf (fd); + } + } + } + } + + if (!XFD_ANYSET (&WellKnownConnections)) + FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); +#ifndef WIN32 + OsSignal (SIGPIPE, SIG_IGN); + OsSignal (SIGHUP, AutoResetServer); +#endif + OsSignal (SIGINT, GiveUp); + OsSignal (SIGTERM, GiveUp); + XFD_COPYSET (&WellKnownConnections, &AllSockets); + ResetHosts(display); + /* + * Magic: If SIGUSR1 was set to SIG_IGN when + * the server started, assume that either + * + * a- The parent process is ignoring SIGUSR1 + * + * or + * + * b- The parent process is expecting a SIGUSR1 + * when the server is ready to accept connections + * + * In the first case, the signal will be harmless, + * in the second case, the signal will be quite + * useful + */ +#ifndef WIN32 + if (OsSignal (SIGUSR1, SIG_IGN) == SIG_IGN) + RunFromSmartParent = TRUE; + ParentProcess = getppid (); + if (RunFromSmartParent) { + if (ParentProcess > 0) { + kill (ParentProcess, SIGUSR1); + } + } +#endif +#ifdef XDMCP + XdmcpInit (); +#endif +} + +void +ResetWellKnownSockets () +{ + int i; + + ResetOsBuffers(); + + for (i = 0; i < ListenTransCount; i++) + { + int status = _XSERVTransResetListener (ListenTransConns[i]); + + if (status != TRANS_RESET_NOOP) + { + if (status == TRANS_RESET_FAILURE) + { + /* + * ListenTransConns[i] freed by xtrans. + * Remove it from out list. + */ + + FD_CLR (ListenTransFds[i], &WellKnownConnections); + ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; + ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; + ListenTransCount -= 1; + i -= 1; + } + else if (status == TRANS_RESET_NEW_FD) + { + /* + * A new file descriptor was allocated (the old one was closed) + */ + + int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); + + FD_CLR (ListenTransFds[i], &WellKnownConnections); + ListenTransFds[i] = newfd; + FD_SET(newfd, &WellKnownConnections); + } + } + } + + ResetAuthorization (); + ResetHosts(display); + /* + * See above in CreateWellKnownSockets about SIGUSR1 + */ +#ifndef WIN32 + if (RunFromSmartParent) { + if (ParentProcess > 0) { + kill (ParentProcess, SIGUSR1); + } + } +#endif + /* + * restart XDMCP + */ +#ifdef XDMCP + XdmcpReset (); +#endif +} + +static void +AuthAudit (client, letin, saddr, len, proto_n, auth_proto, auth_id) + ClientPtr client; + Bool letin; + struct sockaddr *saddr; + int len; + unsigned short proto_n; + char *auth_proto; + int auth_id; +{ + char addr[128]; + char *out = addr; + + if (!((OsCommPtr)client->osPrivate)->trans_conn) { + strcpy(addr, "LBX proxy at "); + out += strlen(addr); + } + if (!len) + strcpy(out, "local host"); + else + switch (saddr->sa_family) + { + case AF_UNSPEC: +#if defined(UNIXCONN) || defined(LOCALCONN) + case AF_UNIX: +#endif + strcpy(out, "local host"); + break; +#if defined(TCPCONN) || defined(STREAMSCONN) + case AF_INET: + sprintf(out, "IP %s port %d", + inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr), + ((struct sockaddr_in *) saddr)->sin_port); + break; +#endif +#ifdef DNETCONN + case AF_DECnet: + sprintf(out, "DN %s", + dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add)); + break; +#endif + default: + strcpy(out, "unknown address"); + } + if (letin) + AuditF("client %d connected from %s\n", client->index, addr); + else + AuditF("client %d rejected from %s\n", client->index, addr); + if (proto_n) + AuditF(" Auth name: %.*s ID: %d\n", proto_n, auth_proto, auth_id); +} + +XID +AuthorizationIDOfClient(client) + ClientPtr client; +{ + if (client->osPrivate) + return ((OsCommPtr)client->osPrivate)->auth_id; + else + return None; +} + + +/***************************************************************** + * ClientAuthorized + * + * Sent by the client at connection setup: + * typedef struct _xConnClientPrefix { + * CARD8 byteOrder; + * BYTE pad; + * CARD16 majorVersion, minorVersion; + * CARD16 nbytesAuthProto; + * CARD16 nbytesAuthString; + * } xConnClientPrefix; + * + * It is hoped that eventually one protocol will be agreed upon. In the + * mean time, a server that implements a different protocol than the + * client expects, or a server that only implements the host-based + * mechanism, will simply ignore this information. + * + *****************************************************************/ + +char * +ClientAuthorized(client, proto_n, auth_proto, string_n, auth_string) + ClientPtr client; + char *auth_proto, *auth_string; + unsigned int proto_n, string_n; +{ + register OsCommPtr priv; + Xtransaddr *from = NULL; + int family; + int fromlen; + XID auth_id; + char *reason = NULL; + XtransConnInfo trans_conn; + int restore_trans_conn = 0; + ClientPtr lbxpc; + + priv = (OsCommPtr)client->osPrivate; + trans_conn = priv->trans_conn; + +#ifdef LBX + if (!trans_conn) { + /* + * Since trans_conn is NULL, this must be a proxy's client for + * which we have NO address. Therefore, we will temporarily + * set the client's trans_conn to the proxy's trans_conn and + * after CheckAuthorization the client's trans_conn will be + * restored. + * + * If XDM-AUTHORIZATION-1 is being used, CheckAuthorization + * will eventually call XdmAuthorizationValidate and this + * later function may use the client's trans_conn to get the + * client's address. Since a XDM-AUTH-1 auth string includes + * the client's address, this address is compared to the address + * in the client's trans_conn. If the proxy and client are + * on the same host, the comparison will fail; otherwise the + * comparison will fail and the client will not be authorized + * to connect to the server. + * + * The basis for this additional code is to prevent a + * NULL pointer dereference of the client's trans_conn. + * The fundamental problem - the fact that the client's + * trans_conn is NULL - is because the NewClient + * request in version 1.0 of the LBX protocol does not + * send the client's address to the server. When the + * spec is changed and the client's address is sent to + * server in the NewClient request, this additional code + * should be removed. + * + * See defect number XWSog08218 for more information. + */ + lbxpc = LbxProxyClient(priv->proxy); + trans_conn = ((OsCommPtr)lbxpc->osPrivate)->trans_conn; + priv->trans_conn = trans_conn; + restore_trans_conn = 1; + } +#endif + + auth_id = CheckAuthorization (proto_n, auth_proto, + string_n, auth_string, client, &reason); + +#ifdef LBX + if (restore_trans_conn) { + /* + * Restore client's trans_conn state + */ + priv = (OsCommPtr)client->osPrivate; + priv->trans_conn = NULL; + + trans_conn = NULL; + } + +#endif + +#ifdef LBX + if (!trans_conn) { + /* + * Use the proxy's trans_conn + */ + trans_conn = ((OsCommPtr)lbxpc->osPrivate)->trans_conn; + if (auth_id == (XID) ~0L && !GetAccessControl()) + auth_id = ((OsCommPtr)lbxpc->osPrivate)->auth_id; +#ifdef XCSECURITY + else if (auth_id != (XID) ~0L && !SecuritySameLevel(lbxpc, auth_id)) { + auth_id = (XID) ~0L; + reason = "Client trust level differs from that of LBX Proxy"; + } +#endif + } +#endif + if (auth_id == (XID) ~0L) + { + if ( +#ifdef XCSECURITY + (proto_n == 0 || + strncmp (auth_proto, XSecurityAuthorizationName, proto_n) != 0) && +#endif + _XSERVTransGetPeerAddr (trans_conn, + &family, &fromlen, &from) != -1) + { + if ( +#ifdef LBX + !priv->trans_conn || +#endif + InvalidHost ((struct sockaddr *) from, fromlen)) + AuthAudit(client, FALSE, (struct sockaddr *) from, + fromlen, proto_n, auth_proto, auth_id); + else + { + auth_id = (XID) 0; + if (auditTrailLevel > 1) + AuthAudit(client, TRUE, + (struct sockaddr *) from, fromlen, + proto_n, auth_proto, auth_id); + } + + free ((char *) from); + } + + if (auth_id == (XID) ~0L) + if (reason) + return reason; + else + return "Client is not authorized to connect to Server"; + } + else if (auditTrailLevel > 1) + { + if (_XSERVTransGetPeerAddr (trans_conn, + &family, &fromlen, &from) != -1) + { + AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen, + proto_n, auth_proto, auth_id); + + free ((char *) from); + } + } + priv->auth_id = auth_id; + priv->conn_time = 0; + +#ifdef XDMCP + /* indicate to Xdmcp protocol that we've opened new client */ + XdmcpOpenDisplay(priv->fd); +#endif /* XDMCP */ +#ifdef XAPPGROUP + if (ClientStateCallback) + XagCallClientStateChange (client); +#endif + /* At this point, if the client is authorized to change the access control + * list, we should getpeername() information, and add the client to + * the selfhosts list. It's not really the host machine, but the + * true purpose of the selfhosts list is to see who may change the + * access control list. + */ + return((char *)NULL); +} + +static ClientPtr +#ifdef LBX +AllocNewConnection (trans_conn, fd, conn_time, Flush, Close, proxy) +#else +AllocNewConnection (trans_conn, fd, conn_time) +#endif + XtransConnInfo trans_conn; + int fd; + CARD32 conn_time; +#ifdef LBX + int (*Flush)(); + void (*Close)(); + LbxProxyPtr proxy; +#endif +{ + OsCommPtr oc; + ClientPtr client; + + if ( +#ifdef LBX + trans_conn && +#endif +#ifndef WIN32 + fd >= lastfdesc +#else + XFD_SETCOUNT(&AllClients) >= MaxClients +#endif + ) + return NullClient; + oc = (OsCommPtr)xalloc(sizeof(OsCommRec)); + if (!oc) + return NullClient; + oc->trans_conn = trans_conn; + oc->fd = fd; + oc->input = (ConnectionInputPtr)NULL; + oc->output = (ConnectionOutputPtr)NULL; + oc->auth_id = None; + oc->conn_time = conn_time; +#ifdef LBX + oc->proxy = proxy; + oc->Flush = Flush; + oc->Close = Close; + oc->largereq = (ConnectionInputPtr) NULL; +#endif + if (!(client = NextAvailableClient((pointer)oc))) + { + xfree (oc); + return NullClient; + } +#ifdef LBX + if (trans_conn) +#endif + { + ConnectionTranslation[fd] = client->index; + if (GrabInProgress) + { + FD_SET(fd, &SavedAllClients); + FD_SET(fd, &SavedAllSockets); + } + else + { + FD_SET(fd, &AllClients); + FD_SET(fd, &AllSockets); + } + } + return client; +} + +#ifdef LBX + +int +ClientConnectionNumber (client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + return oc->fd; +} + +ClientPtr +AllocLbxClientConnection (client, proxy) + ClientPtr client; + LbxProxyPtr proxy; +{ + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + return AllocNewConnection ((XtransConnInfo)NULL, oc->fd, GetTimeInMillis(), + LbxFlushClient, LbxCloseClient, proxy); +} + +void +LbxProxyConnection (client, proxy) + ClientPtr client; + LbxProxyPtr proxy; +{ + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + FlushClient(client, oc, (char *)NULL, 0); + oc->proxy = proxy; + oc->Flush = LbxFlushClient; + oc->Close = LbxCloseClient; + LbxPrimeInput(client, proxy); +} + +#endif + +/***************** + * EstablishNewConnections + * If anyone is waiting on listened sockets, accept them. + * Returns a mask with indices of new clients. Updates AllClients + * and AllSockets. + *****************/ + +/*ARGSUSED*/ +Bool +EstablishNewConnections(clientUnused, closure) + ClientPtr clientUnused; + pointer closure; +{ +#ifndef WIN32 + fd_mask readyconnections; /* mask of listeners that are ready */ +#else + fd_set readyconnections; /* set of listeners that are ready */ +#endif + int curconn; /* fd of listener that's ready */ + register int newconn; /* fd of new client */ + CARD32 connect_time; + register int i; + register ClientPtr client; + register OsCommPtr oc; + fd_set tmask; + + XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections); +#ifndef WIN32 + readyconnections = tmask.fds_bits[0]; + if (!readyconnections) + return TRUE; +#else + XFD_COPYSET(&tmask, &readyconnections); + if (!XFD_ANYSET(&readyconnections)) + return TRUE; +#endif + connect_time = GetTimeInMillis(); + /* kill off stragglers */ + for (i=1; iosPrivate); + if (oc && (oc->conn_time != 0) && + (connect_time - oc->conn_time) >= TimeOutValue || + client->noClientException != Success && !client->clientGone) + CloseDownClient(client); + } + } +#ifndef WIN32 + while (readyconnections) +#else + for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++) +#endif + { + XtransConnInfo trans_conn, new_trans_conn; + int status; + +#ifndef WIN32 + curconn = ffs (readyconnections) - 1; + readyconnections &= ~(1 << curconn); +#else + curconn = XFD_FD(&readyconnections, i); +#endif + + if ((trans_conn = lookup_trans_conn (curconn)) == NULL) + continue; + + if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL) + continue; + + newconn = _XSERVTransGetConnectionNumber (new_trans_conn); + + if (newconn < lastfdesc) + { + int clientid; + clientid = ConnectionTranslation[newconn]; + if(clientid && (client = clients[clientid])) + CloseDownClient(client); + } + + _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); + + if (!AllocNewConnection (new_trans_conn, newconn, connect_time +#ifdef LBX + , StandardFlushClient, + CloseDownFileDescriptor, (LbxProxyPtr)NULL +#endif + )) + { + ErrorConnMax(new_trans_conn); + _XSERVTransClose(new_trans_conn); + } + } + return TRUE; +} + +#define NOROOM "Maximum number of clients reached" + +/************ + * ErrorConnMax + * Fail a connection due to lack of client or file descriptor space + ************/ + +static void +ErrorConnMax(trans_conn) +XtransConnInfo trans_conn; +{ + register int fd = _XSERVTransGetConnectionNumber (trans_conn); + xConnSetupPrefix csp; + char pad[3]; + struct iovec iov[3]; + char byteOrder = 0; + int whichbyte = 1; + struct timeval waittime; + fd_set mask; + + /* if these seems like a lot of trouble to go to, it probably is */ + waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND; + waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) * + (1000000 / MILLI_PER_SECOND); + FD_ZERO(&mask); + FD_SET(fd, &mask); + (void)Select(fd + 1, &mask, NULL, NULL, &waittime); + /* try to read the byte-order of the connection */ + (void)_XSERVTransRead(trans_conn, &byteOrder, 1); + if ((byteOrder == 'l') || (byteOrder == 'B')) + { + csp.success = xFalse; + csp.lengthReason = sizeof(NOROOM) - 1; + csp.length = (sizeof(NOROOM) + 2) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (((*(char *) &whichbyte) && (byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (byteOrder == 'l'))) + { + swaps(&csp.majorVersion, whichbyte); + swaps(&csp.minorVersion, whichbyte); + swaps(&csp.length, whichbyte); + } + iov[0].iov_len = sz_xConnSetupPrefix; + iov[0].iov_base = (char *) &csp; + iov[1].iov_len = csp.lengthReason; + iov[1].iov_base = NOROOM; + iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; + iov[2].iov_base = pad; + (void)_XSERVTransWritev(trans_conn, iov, 3); + } +} + +/************ + * CloseDownFileDescriptor: + * Remove this file descriptor and it's I/O buffers, etc. + ************/ + +#ifdef LBX +void +CloseDownFileDescriptor(client) + ClientPtr client; +#else +static void +CloseDownFileDescriptor(oc) + register OsCommPtr oc; +#endif +{ +#ifdef LBX + register OsCommPtr oc = (OsCommPtr) client->osPrivate; +#endif + int connection = oc->fd; + + if (oc->trans_conn) { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + } +#ifdef LBX + ConnectionTranslation[connection] = 0; +#else + FreeOsBuffers(oc); +#endif + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + FD_CLR(connection, &ClientsWithInput); + FD_CLR(connection, &GrabImperviousClients); + if (GrabInProgress) + { + FD_CLR(connection, &SavedAllSockets); + FD_CLR(connection, &SavedAllClients); + FD_CLR(connection, &SavedClientsWithInput); + } + FD_CLR(connection, &ClientsWriteBlocked); + if (!XFD_ANYSET(&ClientsWriteBlocked)) + AnyClientsWriteBlocked = FALSE; + FD_CLR(connection, &OutputPending); +#ifndef LBX + xfree(oc); +#endif +} + +/***************** + * CheckConections + * Some connection has died, go find which one and shut it down + * The file descriptor has been closed, but is still in AllClients. + * If would truly be wonderful if select() would put the bogus + * file descriptors in the exception mask, but nooooo. So we have + * to check each and every socket individually. + *****************/ + +void +CheckConnections() +{ +#ifndef WIN32 + fd_mask mask; +#endif + fd_set tmask; + register int curclient, curoff; + int i; + struct timeval notime; + int r; +#ifdef WIN32 + fd_set savedAllClients; +#endif + + notime.tv_sec = 0; + notime.tv_usec = 0; + +#ifndef WIN32 + for (i=0; iosPrivate; + + if (oc->output && oc->output->count) + FlushClient(client, oc, (char *)NULL, 0); +#ifdef XDMCP + XdmcpCloseDisplay(oc->fd); +#endif +#ifndef LBX + CloseDownFileDescriptor(oc); +#else + (*oc->Close) (client); + FreeOsBuffers(oc); + xfree(oc); +#endif + client->osPrivate = (pointer)NULL; + if (auditTrailLevel > 1) + AuditF("client %d disconnected\n", client->index); +} + + +AddEnabledDevice(fd) + int fd; +{ + FD_SET(fd, &EnabledDevices); + FD_SET(fd, &AllSockets); +} + + +RemoveEnabledDevice(fd) + int fd; +{ + FD_CLR(fd, &EnabledDevices); + FD_CLR(fd, &AllSockets); +} + +/***************** + * OnlyListenToOneClient: + * Only accept requests from one client. Continue to handle new + * connections, but don't take any protocol requests from the new + * ones. Note that if GrabInProgress is set, EstablishNewConnections + * needs to put new clients into SavedAllSockets and SavedAllClients. + * Note also that there is no timeout for this in the protocol. + * This routine is "undone" by ListenToAllClients() + *****************/ + +OnlyListenToOneClient(client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + if (! GrabInProgress) + { + XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput); + XFD_ANDSET(&ClientsWithInput, + &ClientsWithInput, &GrabImperviousClients); + if (FD_ISSET(connection, &SavedClientsWithInput)) + { + FD_CLR(connection, &SavedClientsWithInput); + FD_SET(connection, &ClientsWithInput); + } + XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients); + XFD_COPYSET(&AllSockets, &SavedAllSockets); + XFD_COPYSET(&AllClients, &SavedAllClients); + XFD_UNSET(&AllSockets, &AllClients); + XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients); + FD_SET(connection, &AllClients); + XFD_ORSET(&AllSockets, &AllSockets, &AllClients); + GrabInProgress = client->index; + } +} + +/**************** + * ListenToAllClients: + * Undoes OnlyListentToOneClient() + ****************/ + +ListenToAllClients() +{ + if (GrabInProgress) + { + XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets); + XFD_ORSET(&AllClients, &AllClients, &SavedAllClients); + XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput); + GrabInProgress = 0; + } +} + +/**************** + * IgnoreClient + * Removes one client from input masks. + * Must have cooresponding call to AttendClient. + ****************/ + +IgnoreClient (client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; +#ifdef LBX + LbxClientPtr lbxClient = LbxClient(client); +#endif + + isItTimeToYield = TRUE; +#ifdef LBX + if (lbxClient) { + lbxClient->ignored = TRUE; + return; + } +#endif + if (!GrabInProgress || FD_ISSET(connection, &AllClients)) + { + if (FD_ISSET (connection, &ClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + FD_CLR(connection, &LastSelectMask); + } + else + { + if (FD_ISSET (connection, &SavedClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &SavedClientsWithInput); + FD_CLR(connection, &SavedAllSockets); + FD_CLR(connection, &SavedAllClients); + } +} + +/**************** + * AttendClient + * Adds one client back into the input masks. + ****************/ + +AttendClient (client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; +#ifdef LBX + LbxClientPtr lbxClient = LbxClient(client); + + if (lbxClient) { + lbxClient->ignored = FALSE; + return; + } +#endif + if (!GrabInProgress || GrabInProgress == client->index || + FD_ISSET(connection, &GrabImperviousClients)) + { + FD_SET(connection, &AllClients); + FD_SET(connection, &AllSockets); + FD_SET(connection, &LastSelectMask); + if (FD_ISSET (connection, &IgnoredClientsWithInput)) + FD_SET(connection, &ClientsWithInput); + } + else + { + FD_SET(connection, &SavedAllClients); + FD_SET(connection, &SavedAllSockets); + if (FD_ISSET(connection, &IgnoredClientsWithInput)) + FD_SET(connection, &SavedClientsWithInput); + } +} + +/* make client impervious to grabs; assume only executing client calls this */ + +MakeClientGrabImpervious(client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + FD_SET(connection, &GrabImperviousClients); + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = CLIENT_IMPERVIOUS; + CallCallbacks(&ServerGrabCallback, &grabinfo); + } +} + +/* make client pervious to grabs; assume only executing client calls this */ + +MakeClientGrabPervious(client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + FD_CLR(connection, &GrabImperviousClients); + if (GrabInProgress && (GrabInProgress != client->index)) + { + if (FD_ISSET(connection, &ClientsWithInput)) + { + FD_SET(connection, &SavedClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + } + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + isItTimeToYield = TRUE; + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = CLIENT_PERVIOUS; + CallCallbacks(&ServerGrabCallback, &grabinfo); + } +} + +#ifdef AIXV3 + +static fd_set pendingActiveClients; +static BOOL reallyGrabbed; + +/**************** +* DontListenToAnybody: +* Don't listen to requests from any clients. Continue to handle new +* connections, but don't take any protocol requests from anybody. +* We have to take care if there is already a grab in progress, though. +* Undone by PayAttentionToClientsAgain. We also have to be careful +* not to accept any more input from the currently dispatched client. +* we do this be telling dispatch it is time to yield. + +* We call this when the server loses access to the glass +* (user hot-keys away). This looks like a grab by the +* server itself, but gets a little tricky if there is already +* a grab in progress. +******************/ + +void +DontListenToAnybody() +{ + if (!GrabInProgress) + { + XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput); + XFD_COPYSET(&AllSockets, &SavedAllSockets); + XFD_COPYSET(&AllClients, &SavedAllClients); + GrabInProgress = TRUE; + reallyGrabbed = FALSE; + } + else + { + XFD_COPYSET(&AllClients, &pendingActiveClients); + reallyGrabbed = TRUE; + } + FD_ZERO(&ClientsWithInput); + XFD_UNSET(&AllSockets, &AllClients); + FD_ZERO(&AllClients); + isItTimeToYield = TRUE; +} + +void +PayAttentionToClientsAgain() +{ + if (reallyGrabbed) + { + XFD_ORSET(&AllSockets, &AllSockets, &pendingActiveClients); + XFD_ORSET(&AllClients, &AllClients, &pendingActiveClients); + } + else + { + ListenToAllClients(); + } + reallyGrabbed = FALSE; +} + +#endif diff --git a/os/io.c b/os/io.c new file mode 100644 index 000000000..96bfd6885 --- /dev/null +++ b/os/io.c @@ -0,0 +1,1262 @@ +/*********************************************************** + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: io.c,v 1.6 2001/02/09 02:05:23 xorgcvs Exp $ */ +/***************************************************************** + * i/o functions + * + * WriteToClient, ReadRequestFromClient + * InsertFakeRequest, ResetCurrentRequest + * + *****************************************************************/ + +#ifdef WIN32 +#include +#endif +#include +#include +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif +#include "Xmd.h" +#include +#ifndef WIN32 +#include +#endif +#include "X.h" +#define NEED_REPLIES +#include "Xproto.h" +#include "os.h" +#include "Xpoll.h" +#include "osdep.h" +#include "opaque.h" +#include "dixstruct.h" +#include "misc.h" +#ifdef LBX +#include "lbxserve.h" +#endif + +CallbackListPtr ReplyCallback; +CallbackListPtr FlushCallback; + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST(err) (err == EAGAIN) +#else +#define ETEST(err) (err == EWOULDBLOCK) +#endif +#endif + +extern fd_set ClientsWithInput, IgnoredClientsWithInput, AllClients; +extern fd_set ClientsWriteBlocked; +extern fd_set OutputPending; +extern int ConnectionTranslation[]; +extern Bool NewOutputPending; +extern Bool AnyClientsWriteBlocked; + +Bool CriticalOutputPending; +int timesThisConnection = 0; +ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL; +ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL; +OsCommPtr AvailableInput = (OsCommPtr)NULL; + +#define get_req_len(req,cli) ((cli)->swapped ? \ + lswaps((req)->length) : (req)->length) + +#ifdef BIGREQS +#include "bigreqstr.h" + +#define get_big_req_len(req,cli) ((cli)->swapped ? \ + lswapl(((xBigReq *)(req))->length) : \ + ((xBigReq *)(req))->length) +#endif + +#define MAX_TIMES_PER 10 + +/* + * A lot of the code in this file manipulates a ConnectionInputPtr: + * + * ----------------------------------------------- + * |------- bufcnt ------->| | | + * | |- gotnow ->| | | + * | |-------- needed ------>| | + * |-----------+--------- size --------+---------->| + * ----------------------------------------------- + * ^ ^ + * | | + * buffer bufptr + * + * buffer is a pointer to the start of the buffer. + * bufptr points to the start of the current request. + * bufcnt counts how many bytes are in the buffer. + * size is the size of the buffer in bytes. + * + * In several of the functions, gotnow and needed are local variables + * that do the following: + * + * gotnow is the number of bytes of the request that we're + * trying to read that are currently in the buffer. + * Typically, gotnow = (buffer + bufcnt) - bufptr + * + * needed = the length of the request that we're trying to + * read. Watch out: needed sometimes counts bytes and sometimes + * counts CARD32's. + */ + + +/***************************************************************** + * ReadRequestFromClient + * Returns one request in client->requestBuffer. The request + * length will be in client->req_len. Return status is: + * + * > 0 if successful, specifies length in bytes of the request + * = 0 if entire request is not yet available + * < 0 if client should be terminated + * + * The request returned must be contiguous so that it can be + * cast in the dispatcher to the correct request type. Because requests + * are variable length, ReadRequestFromClient() must look at the first 4 + * or 8 bytes of a request to determine the length (the request length is + * in the 3rd and 4th bytes of the request unless it is a Big Request + * (see the Big Request Extension), in which case the 3rd and 4th bytes + * are zero and the following 4 bytes are the request length. + * + * Note: in order to make the server scheduler (WaitForSomething()) + * "fair", the ClientsWithInput mask is used. This mask tells which + * clients have FULL requests left in their buffers. Clients with + * partial requests require a read. Basically, client buffers + * are drained before select() is called again. But, we can't keep + * reading from a client that is sending buckets of data (or has + * a partial request) because others clients need to be scheduled. + *****************************************************************/ + +#define YieldControl() \ + { isItTimeToYield = TRUE; \ + timesThisConnection = 0; } +#define YieldControlNoInput() \ + { YieldControl(); \ + FD_CLR(fd, &ClientsWithInput); } +#define YieldControlDeath() \ + { timesThisConnection = 0; } + +#ifdef hpux_not_tog +#define LBX_NEED_OLD_SYMBOL_FOR_LOADABLES +#endif + +#ifdef LBX +#ifdef LBX_NEED_OLD_SYMBOL_FOR_LOADABLES +#undef ReadRequestFromClient +int +ReadRequestFromClient(client) + ClientPtr client; +{ + return (*client->readRequest)(client); +} +#endif +int +StandardReadRequestFromClient(client) + ClientPtr client; +#else +int +ReadRequestFromClient(client) + ClientPtr client; +#endif +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + register unsigned int gotnow, needed; + int result; + register xReq *request; + Bool need_header; +#ifdef BIGREQS + Bool move_header; +#endif + + /* If an input buffer was empty, either free it if it is too big + * or link it into our list of free input buffers. This means that + * different clients can share the same input buffer (at different + * times). This was done to save memory. + */ + + if (AvailableInput) + { + if (AvailableInput != oc) + { + register ConnectionInputPtr aci = AvailableInput->input; + if (aci->size > BUFWATERMARK) + { + xfree(aci->buffer); + xfree(aci); + } + else + { + aci->next = FreeInputs; + FreeInputs = aci; + } + AvailableInput->input = (ConnectionInputPtr)NULL; + } + AvailableInput = (OsCommPtr)NULL; + } + + /* make sure we have an input buffer */ + + if (!oci) + { + if (oci = FreeInputs) + { + FreeInputs = oci->next; + } + else if (!(oci = AllocateInputBuffer())) + { + YieldControlDeath(); + return -1; + } + oc->input = oci; + } + + /* advance to start of next request */ + + oci->bufptr += oci->lenLastReq; + + need_header = FALSE; +#ifdef BIGREQS + move_header = FALSE; +#endif + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if (gotnow < sizeof(xReq)) + { + /* We don't have an entire xReq yet. Can't tell how big + * the request will be until we get the whole xReq. + */ + needed = sizeof(xReq); + need_header = TRUE; + } + else + { + /* We have a whole xReq. We can tell how big the whole + * request will be unless it is a Big Request. + */ + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); +#ifdef BIGREQS + if (!needed && client->big_requests) + { + /* It's a Big Request. */ + move_header = TRUE; + if (gotnow < sizeof(xBigReq)) + { + /* Still need more data to tell just how big. */ + needed = sizeof(xBigReq) >> 2; /* needed is in CARD32s now */ + need_header = TRUE; + } + else + needed = get_big_req_len(request, client); + } +#endif + client->req_len = needed; + needed <<= 2; /* needed is in bytes now */ + } + if (gotnow < needed) + { + /* Need to read more data, either so that we can get a + * complete xReq (if need_header is TRUE), a complete + * xBigReq (if move_header is TRUE), or the rest of the + * request (if need_header and move_header are both FALSE). + */ + + oci->lenLastReq = 0; + if (needed > MAXBUFSIZE) + { + /* request is too big for us to handle */ + YieldControlDeath(); + return -1; + } + if ((gotnow == 0) || + ((oci->bufptr - oci->buffer + needed) > oci->size)) + { + /* no data, or the request is too big to fit in the buffer */ + + if ((gotnow > 0) && (oci->bufptr != oci->buffer)) + /* save the data we've already read */ + memmove(oci->buffer, oci->bufptr, gotnow); + if (needed > oci->size) + { + /* make buffer bigger to accomodate request */ + char *ibuf; + + ibuf = (char *)xrealloc(oci->buffer, needed); + if (!ibuf) + { + YieldControlDeath(); + return -1; + } + oci->size = needed; + oci->buffer = ibuf; + } + oci->bufptr = oci->buffer; + oci->bufcnt = gotnow; + } + /* XXX this is a workaround. This function is sometimes called + * after the trans_conn has been freed. In this case trans_conn + * will be null. Really ought to restructure things so that we + * never get here in those circumstances. + */ + if (!oc->trans_conn) + { + /* treat as if an error occured on the read, which is what + * used to happen + */ + YieldControlDeath(); + return -1; + } +#ifdef LBX + if (oc->proxy && oc->proxy->compHandle) + result = (*oc->proxy->streamOpts.streamCompRead)(fd, + (unsigned char *)oci->buffer + oci->bufcnt, + oci->size - oci->bufcnt); + else +#endif + result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt, + oci->size - oci->bufcnt); + if (result <= 0) + { + if ((result < 0) && ETEST(errno)) + { + YieldControlNoInput(); + return 0; + } + YieldControlDeath(); + return -1; + } + oci->bufcnt += result; + gotnow += result; + /* free up some space after huge requests */ + if ((oci->size > BUFWATERMARK) && + (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) + { + char *ibuf; + + ibuf = (char *)xrealloc(oci->buffer, BUFSIZE); + if (ibuf) + { + oci->size = BUFSIZE; + oci->buffer = ibuf; + oci->bufptr = ibuf + oci->bufcnt - gotnow; + } + } + if (need_header && gotnow >= needed) + { + /* We wanted an xReq, now we've gotten it. */ + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); +#ifdef BIGREQS + if (!needed && client->big_requests) + { + move_header = TRUE; + if (gotnow < sizeof(xBigReq)) + needed = sizeof(xBigReq) >> 2; + else + needed = get_big_req_len(request, client); + } +#endif + client->req_len = needed; + needed <<= 2; + } + if (gotnow < needed) + { + /* Still don't have enough; punt. */ + YieldControlNoInput(); + return 0; + } + } + if (needed == 0) + { +#ifdef BIGREQS + if (client->big_requests) + needed = sizeof(xBigReq); + else +#endif + needed = sizeof(xReq); + } + oci->lenLastReq = needed; + + /* + * Check to see if client has at least one whole request in the + * buffer beyond the request we're returning to the caller. + * If there is only a partial request, treat like buffer + * is empty so that select() will be called again and other clients + * can get into the queue. + */ + + gotnow -= needed; + if (gotnow >= sizeof(xReq)) + { + request = (xReq *)(oci->bufptr + needed); + if (gotnow >= (result = (get_req_len(request, client) << 2)) +#ifdef BIGREQS + && (result || + (client->big_requests && + (gotnow >= sizeof(xBigReq) && + gotnow >= (get_big_req_len(request, client) << 2)))) +#endif + ) + FD_SET(fd, &ClientsWithInput); + else + YieldControlNoInput(); + } + else + { + if (!gotnow) + AvailableInput = oc; + YieldControlNoInput(); + } + if (++timesThisConnection >= MAX_TIMES_PER) + YieldControl(); +#ifdef BIGREQS + if (move_header) + { + request = (xReq *)oci->bufptr; + oci->bufptr += (sizeof(xBigReq) - sizeof(xReq)); + *(xReq *)oci->bufptr = *request; + oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq)); + client->req_len -= (sizeof(xBigReq) - sizeof(xReq)) >> 2; + } +#endif + client->requestBuffer = (pointer)oci->bufptr; + return needed; +} + +/***************************************************************** + * InsertFakeRequest + * Splice a consed up (possibly partial) request in as the next request. + * + **********************/ + +Bool +InsertFakeRequest(client, data, count) + ClientPtr client; + char *data; + int count; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + register int gotnow, moveup; + + if (AvailableInput) + { + if (AvailableInput != oc) + { + register ConnectionInputPtr aci = AvailableInput->input; + if (aci->size > BUFWATERMARK) + { + xfree(aci->buffer); + xfree(aci); + } + else + { + aci->next = FreeInputs; + FreeInputs = aci; + } + AvailableInput->input = (ConnectionInputPtr)NULL; + } + AvailableInput = (OsCommPtr)NULL; + } + if (!oci) + { + if (oci = FreeInputs) + FreeInputs = oci->next; + else if (!(oci = AllocateInputBuffer())) + return FALSE; + oc->input = oci; + } + oci->bufptr += oci->lenLastReq; + oci->lenLastReq = 0; + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if ((gotnow + count) > oci->size) + { + char *ibuf; + + ibuf = (char *)xrealloc(oci->buffer, gotnow + count); + if (!ibuf) + return(FALSE); + oci->size = gotnow + count; + oci->buffer = ibuf; + oci->bufptr = ibuf + oci->bufcnt - gotnow; + } + moveup = count - (oci->bufptr - oci->buffer); + if (moveup > 0) + { + if (gotnow > 0) + memmove(oci->bufptr + moveup, oci->bufptr, gotnow); + oci->bufptr += moveup; + oci->bufcnt += moveup; + } + memmove(oci->bufptr - count, data, count); + oci->bufptr -= count; + gotnow += count; + if ((gotnow >= sizeof(xReq)) && + (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2))) + FD_SET(fd, &ClientsWithInput); + else + YieldControlNoInput(); + return(TRUE); +} + +/***************************************************************** + * ResetRequestFromClient + * Reset to reexecute the current request, and yield. + * + **********************/ + +ResetCurrentRequest(client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + register xReq *request; + int gotnow, needed; +#ifdef LBX + Bool part; + LbxClientPtr lbxClient = LbxClient(client); + + if (lbxClient) { + LbxSetForBlock(lbxClient); + if (!oci) { + AppendFakeRequest(client, + client->requestBuffer, client->req_len << 2); + return; + } + } +#endif + if (AvailableInput == oc) + AvailableInput = (OsCommPtr)NULL; + oci->lenLastReq = 0; + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if (gotnow < sizeof(xReq)) + { + YieldControlNoInput(); + } + else + { + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); +#ifdef BIGREQS + if (!needed && client->big_requests) + { + oci->bufptr -= sizeof(xBigReq) - sizeof(xReq); + *(xReq *)oci->bufptr = *request; + ((xBigReq *)oci->bufptr)->length = client->req_len; + if (client->swapped) + { + char n; + swapl(&((xBigReq *)oci->bufptr)->length, n); + } + } +#endif + if (gotnow >= (needed << 2)) + { + if (FD_ISSET(fd, &AllClients)) + { + FD_SET(fd, &ClientsWithInput); + } + else + { + FD_SET(fd, &IgnoredClientsWithInput); + } + YieldControl(); + } + else + YieldControlNoInput(); + } +} + + + +/***************************************************************** + * PeekNextRequest and SkipRequests were implemented to support DBE + * idioms, but can certainly be used outside of DBE. There are two + * related macros in os.h, ReqLen and CastxReq. See the porting + * layer document for more details. + * + **********************/ + + +/***************************************************************** + * PeekNextRequest + * lets you look ahead at the unexecuted requests in a + * client's request buffer. + * + * Note: this implementation of PeekNextRequest ignores the + * readmore parameter. + * + **********************/ + +xReqPtr +PeekNextRequest(req, client, readmore) + xReqPtr req; /* request we're starting from */ + ClientPtr client; /* client whose requests we're skipping */ + Bool readmore; /* attempt to read more if next request isn't there? */ +{ + register ConnectionInputPtr oci = ((OsCommPtr)client->osPrivate)->input; + xReqPtr pnextreq; + int needed, gotnow, reqlen; + + if (!oci) return NULL; + + if (!req) + { + /* caller wants the request after the one currently being executed */ + pnextreq = (xReqPtr) + (((CARD32 *)client->requestBuffer) + client->req_len); + } + else + { + /* caller wants the request after the one specified by req */ + reqlen = get_req_len(req, client); +#ifdef BIGREQS + if (!reqlen) reqlen = get_big_req_len(req, client); +#endif + pnextreq = (xReqPtr)(((char *)req) + (reqlen << 2)); + } + + /* see how much of the next request we have available */ + + gotnow = oci->bufcnt - (((char *)pnextreq) - oci->buffer); + + if (gotnow < sizeof(xReq)) + return NULL; + + needed = get_req_len(pnextreq, client) << 2; +#ifdef BIGREQS + if (!needed) + { + /* it's a big request */ + if (gotnow < sizeof(xBigReq)) + return NULL; + needed = get_big_req_len(pnextreq, client) << 2; + } +#endif + + /* if we have less than we need, return NULL */ + + return (gotnow < needed) ? NULL : pnextreq; +} + +/***************************************************************** + * SkipRequests + * lets you skip over some of the requests in a client's + * request buffer. Presumably the caller has used PeekNextRequest + * to examine the requests being skipped and has performed whatever + * actions they dictate. + * + **********************/ + +CallbackListPtr SkippedRequestsCallback = NULL; + +void +SkipRequests(req, client, numskipped) + xReqPtr req; /* last request being skipped */ + ClientPtr client; /* client whose requests we're skipping */ + int numskipped; /* how many requests we're skipping */ +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + int reqlen; + + /* see if anyone wants to snoop the skipped requests */ + + if (SkippedRequestsCallback) + { + SkippedRequestInfoRec skipinfo; + skipinfo.req = req; + skipinfo.client = client; + skipinfo.numskipped = numskipped; + CallCallbacks(&SkippedRequestsCallback, &skipinfo); + } + + /* adjust the sequence number */ + client->sequence += numskipped; + + /* twiddle the oci to skip over the requests */ + + reqlen = get_req_len(req, client); +#ifdef BIGREQS + if (!reqlen) reqlen = get_big_req_len(req, client); +#endif + reqlen <<= 2; + oci->bufptr = (char *)req; + oci->lenLastReq = reqlen; + + /* see if any requests left in the buffer */ + + if ( ((char *)req + reqlen) == (oci->buffer + oci->bufcnt) ) + { + /* no requests; mark input buffer as available and client + * as having no input + */ + int fd = oc->fd; + AvailableInput = oc; + YieldControlNoInput(); + } +} + + + /* lookup table for adding padding bytes to data that is read from + or written to the X socket. */ +static int padlength[4] = {0, 3, 2, 1}; + + /******************** + * FlushAllOutput() + * Flush all clients with output. However, if some client still + * has input in the queue (more requests), then don't flush. This + * will prevent the output queue from being flushed every time around + * the round robin queue. Now, some say that it SHOULD be flushed + * every time around, but... + * + **********************/ + +void +FlushAllOutput() +{ + register int index, base, mask; + OsCommPtr oc; + register ClientPtr client; + Bool newoutput = NewOutputPending; +#ifdef WIN32 + fd_set newOutputPending; +#endif + + if (FlushCallback) + CallCallbacks(&FlushCallback, NULL); + + if (!newoutput) + return; + + /* + * It may be that some client still has critical output pending, + * but he is not yet ready to receive it anyway, so we will + * simply wait for the select to tell us when he's ready to receive. + */ + CriticalOutputPending = FALSE; + NewOutputPending = FALSE; + +#ifndef WIN32 + for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) + { + mask = OutputPending.fds_bits[ base ]; + OutputPending.fds_bits[ base ] = 0; + while (mask) + { + index = ffs(mask) - 1; + mask &= ~lowbit(mask); + if ((index = ConnectionTranslation[(base << 5) + index]) == 0) + continue; + client = clients[index]; + if (client->clientGone) + continue; + oc = (OsCommPtr)client->osPrivate; + if ( +#ifdef LBX + !oc->proxy && +#endif + FD_ISSET(oc->fd, &ClientsWithInput)) + { + FD_SET(oc->fd, &OutputPending); /* set the bit again */ + NewOutputPending = TRUE; + } + else + (void)FlushClient(client, oc, (char *)NULL, 0); + } + } +#else /* WIN32 */ + FD_ZERO(&newOutputPending); + for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) + { + index = XFD_FD(&OutputPending, base); + if ((index = ConnectionTranslation[index]) == 0) + continue; + client = clients[index]; + if (client->clientGone) + continue; + oc = (OsCommPtr)client->osPrivate; + if ( +#ifdef LBX + !oc->proxy && +#endif + FD_ISSET(oc->fd, &ClientsWithInput)) + { + FD_SET(oc->fd, &newOutputPending); /* set the bit again */ + NewOutputPending = TRUE; + } + else + (void)FlushClient(client, oc, (char *)NULL, 0); + } + XFD_COPYSET(&newOutputPending, &OutputPending); +#endif /* WIN32 */ +} + +void +FlushIfCriticalOutputPending() +{ + if (CriticalOutputPending) + FlushAllOutput(); +} + +void +SetCriticalOutputPending() +{ + CriticalOutputPending = TRUE; +} + +/***************** + * WriteToClient + * Copies buf into ClientPtr.buf if it fits (with padding), else + * flushes ClientPtr.buf and buf to client. As of this writing, + * every use of WriteToClient is cast to void, and the result + * is ignored. Potentially, this could be used by requests + * that are sending several chunks of data and want to break + * out of a loop on error. Thus, we will leave the type of + * this routine as int. + *****************/ + +int +WriteToClient (who, count, buf) + ClientPtr who; + char *buf; + int count; +{ + OsCommPtr oc = (OsCommPtr)who->osPrivate; + register ConnectionOutputPtr oco = oc->output; + int padBytes; + + if (!count) + return(0); + + if (!oco) + { + if (oco = FreeOutputs) + { + FreeOutputs = oco->next; + } + else if (!(oco = AllocateOutputBuffer())) + { + if (oc->trans_conn) { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + oc->trans_conn = NULL; + } + MarkClientException(who); + return -1; + } + oc->output = oco; + } + + padBytes = padlength[count & 3]; + + if(ReplyCallback) + { + ReplyInfoRec replyinfo; + + replyinfo.client = who; + replyinfo.replyData = buf; + replyinfo.dataLenBytes = count + padBytes; + if (who->replyBytesRemaining) + { /* still sending data of an earlier reply */ + who->replyBytesRemaining -= count + padBytes; + replyinfo.startOfReply = FALSE; + replyinfo.bytesRemaining = who->replyBytesRemaining; + CallCallbacks((&ReplyCallback), (pointer)&replyinfo); + } + else if (who->clientState == ClientStateRunning + && buf[0] == X_Reply) + { /* start of new reply */ + CARD32 replylen; + unsigned long bytesleft; + char n; + + replylen = ((xGenericReply *)buf)->length; + if (who->swapped) + swapl(&replylen, n); + bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes; + replyinfo.startOfReply = TRUE; + replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft; + CallCallbacks((&ReplyCallback), (pointer)&replyinfo); + } + } + + if (oco->count + count + padBytes > oco->size) + { + FD_CLR(oc->fd, &OutputPending); + if(!XFD_ANYSET(&OutputPending)) { + CriticalOutputPending = FALSE; + NewOutputPending = FALSE; + } + return FlushClient(who, oc, buf, count); + } + + NewOutputPending = TRUE; + FD_SET(oc->fd, &OutputPending); + memmove((char *)oco->buf + oco->count, buf, count); + oco->count += count + padBytes; + return(count); +} + + /******************** + * FlushClient() + * If the client isn't keeping up with us, then we try to continue + * buffering the data and set the apropriate bit in ClientsWritable + * (which is used by WaitFor in the select). If the connection yields + * a permanent error, or we can't allocate any more space, we then + * close the connection. + * + **********************/ + +#ifdef LBX +#ifdef LBX_NEED_OLD_SYMBOL_FOR_LOADABLES +#undef FlushClient +int +FlushClient(who, oc, extraBuf, extraCount) + ClientPtr who; + OsCommPtr oc; + char *extraBuf; + int extraCount; +{ + return (*oc->Flush)(who, oc, extraBuf, extraCount); +} +#endif +int +StandardFlushClient(who, oc, extraBuf, extraCount) +#else +int +FlushClient(who, oc, extraBuf, extraCount) +#endif + ClientPtr who; + OsCommPtr oc; + char *extraBuf; + int extraCount; /* do not modify... returned below */ +{ + register ConnectionOutputPtr oco = oc->output; + int connection = oc->fd; + XtransConnInfo trans_conn = oc->trans_conn; + struct iovec iov[3]; + static char padBuffer[3]; + long written; + long padsize; + long notWritten; + long todo; + + if (!oco) + return 0; + written = 0; + padsize = padlength[extraCount & 3]; + notWritten = oco->count + extraCount + padsize; + todo = notWritten; + while (notWritten) { + long before = written; /* amount of whole thing written */ + long remain = todo; /* amount to try this time, <= notWritten */ + int i = 0; + long len; + + /* You could be very general here and have "in" and "out" iovecs + * and write a loop without using a macro, but what the heck. This + * translates to: + * + * how much of this piece is new? + * if more new then we are trying this time, clamp + * if nothing new + * then bump down amount already written, for next piece + * else put new stuff in iovec, will need all of next piece + * + * Note that todo had better be at least 1 or else we'll end up + * writing 0 iovecs. + */ +#define InsertIOV(pointer, length) \ + len = (length) - before; \ + if (len > remain) \ + len = remain; \ + if (len <= 0) { \ + before = (-len); \ + } else { \ + iov[i].iov_len = len; \ + iov[i].iov_base = (pointer) + before; \ + i++; \ + remain -= len; \ + before = 0; \ + } + + InsertIOV ((char *)oco->buf, oco->count) + InsertIOV (extraBuf, extraCount) + InsertIOV (padBuffer, padsize) + + errno = 0; + if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0) + { + written += len; + notWritten -= len; + todo = notWritten; + } + else if (ETEST(errno) +#ifdef SUNSYSV /* check for another brain-damaged OS bug */ + || (errno == 0) +#endif +#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ + || ((errno == EMSGSIZE) && (todo == 1)) +#endif + ) + { + /* If we've arrived here, then the client is stuffed to the gills + and not ready to accept more. Make a note of it and buffer + the rest. */ + FD_SET(connection, &ClientsWriteBlocked); + AnyClientsWriteBlocked = TRUE; + + if (written < oco->count) + { + if (written > 0) + { + oco->count -= written; + memmove((char *)oco->buf, + (char *)oco->buf + written, + oco->count); + written = 0; + } + } + else + { + written -= oco->count; + oco->count = 0; + } + + if (notWritten > oco->size) + { + unsigned char *obuf; + + obuf = (unsigned char *)xrealloc(oco->buf, + notWritten + BUFSIZE); + if (!obuf) + { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + oc->trans_conn = NULL; + MarkClientException(who); + oco->count = 0; + return(-1); + } + oco->size = notWritten + BUFSIZE; + oco->buf = obuf; + } + + /* If the amount written extended into the padBuffer, then the + difference "extraCount - written" may be less than 0 */ + if ((len = extraCount - written) > 0) + memmove ((char *)oco->buf + oco->count, + extraBuf + written, + len); + + oco->count = notWritten; /* this will include the pad */ + /* return only the amount explicitly requested */ + return extraCount; + } +#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ + else if (errno == EMSGSIZE) + { + todo >>= 1; + } +#endif + else + { + if (oc->trans_conn) + { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + oc->trans_conn = NULL; + } + MarkClientException(who); + oco->count = 0; + return(-1); + } + } + + /* everything was flushed out */ + oco->count = 0; + /* check to see if this client was write blocked */ + if (AnyClientsWriteBlocked) + { + FD_CLR(oc->fd, &ClientsWriteBlocked); + if (! XFD_ANYSET(&ClientsWriteBlocked)) + AnyClientsWriteBlocked = FALSE; + } + if (oco->size > BUFWATERMARK) + { + xfree(oco->buf); + xfree(oco); + } + else + { + oco->next = FreeOutputs; + FreeOutputs = oco; + } + oc->output = (ConnectionOutputPtr)NULL; + return extraCount; /* return only the amount explicitly requested */ +} + +ConnectionInputPtr +AllocateInputBuffer() +{ + register ConnectionInputPtr oci; + + oci = (ConnectionInputPtr)xalloc(sizeof(ConnectionInput)); + if (!oci) + return (ConnectionInputPtr)NULL; + oci->buffer = (char *)xalloc(BUFSIZE); + if (!oci->buffer) + { + xfree(oci); + return (ConnectionInputPtr)NULL; + } + oci->size = BUFSIZE; + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = 0; + return oci; +} + +ConnectionOutputPtr +AllocateOutputBuffer() +{ + register ConnectionOutputPtr oco; + + oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput)); + if (!oco) + return (ConnectionOutputPtr)NULL; + oco->buf = (unsigned char *) xalloc(BUFSIZE); + if (!oco->buf) + { + xfree(oco); + return (ConnectionOutputPtr)NULL; + } + oco->size = BUFSIZE; + oco->count = 0; +#ifdef LBX + oco->nocompress = FALSE; +#endif + return oco; +} + +void +FreeOsBuffers(oc) + OsCommPtr oc; +{ + register ConnectionInputPtr oci; + register ConnectionOutputPtr oco; + + if (AvailableInput == oc) + AvailableInput = (OsCommPtr)NULL; + if (oci = oc->input) + { + if (FreeInputs) + { + xfree(oci->buffer); + xfree(oci); + } + else + { + FreeInputs = oci; + oci->next = (ConnectionInputPtr)NULL; + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = 0; + } + } + if (oco = oc->output) + { + if (FreeOutputs) + { + xfree(oco->buf); + xfree(oco); + } + else + { + FreeOutputs = oco; + oco->next = (ConnectionOutputPtr)NULL; + oco->count = 0; + } + } +#ifdef LBX + if (oci = oc->largereq) { + xfree(oci->buffer); + xfree(oci); + } +#endif +} + +void +ResetOsBuffers() +{ + register ConnectionInputPtr oci; + register ConnectionOutputPtr oco; + + while (oci = FreeInputs) + { + FreeInputs = oci->next; + xfree(oci->buffer); + xfree(oci); + } + while (oco = FreeOutputs) + { + FreeOutputs = oco->next; + xfree(oco->buf); + xfree(oco); + } +} diff --git a/os/k5auth.c b/os/k5auth.c new file mode 100644 index 000000000..c6a2e3cc9 --- /dev/null +++ b/os/k5auth.c @@ -0,0 +1,796 @@ +/* $Xorg: k5auth.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */ +/* + +Copyright 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Kerberos V5 authentication scheme + * Author: Tom Yu + * + * Mostly snarfed wholesale from the user_user demo in the + * krb5 distribution. (At least the checking part) + */ + +#include +#include +#ifdef TCPCONN +#include +#endif +#ifdef DNETCONN +#include +#endif +#include +#include +/* 9/93: krb5.h leaks some symbols */ +#undef BITS32 +#undef xfree +#include +#include "X.h" +#include "os.h" +#include "osdep.h" +#include "Xproto.h" +#include "Xfuncs.h" +#include "dixstruct.h" +#include +#include "Xauth.h" + +extern int (*k5_Vector[256])(); +extern int SendConnSetup(); +extern char *display; /* need this to generate rcache name */ + +static XID krb5_id = ~0L; +static krb5_principal srvname = NULL; /* service name */ +static char *ccname = NULL; +static char *ktname = NULL; /* key table name */ +static char kerror[256]; + +/* + * tgt_keyproc: + * + * extract session key from a credentials struct + */ +krb5_error_code tgt_keyproc(keyprocarg, principal, vno, key) + krb5_pointer keyprocarg; + krb5_principal principal; + krb5_kvno vno; + krb5_keyblock **key; +{ + krb5_creds *creds = (krb5_creds *)keyprocarg; + + return krb5_copy_keyblock(&creds->keyblock, key); +} + +/* + * k5_cmpenc: + * + * compare "encoded" principals + */ +Bool k5_cmpenc(pname, plen, buf) + unsigned char *pname; + short plen; + krb5_data *buf; +{ + return (plen == buf->length && + memcmp(pname, buf->data, plen) == 0); +} + +/* + * K5Check: + * + * This is stage 0 of the krb5 authentication protocol. It + * goes through the current credentials cache and extracts the + * primary principal and tgt to send to the client, or as + * appropriate, extracts from a keytab. + * + * The packet sent to the client has the following format: + * + * CARD8 reqType = 2 + * CARD8 data = 0 + * CARD16 length = total length of packet (in 32 bit units) + * CARD16 plen = length of encoded principal following + * STRING8 princ = encoded principal + * STRING8 ticket = server tgt + * + * For client-server authentication, the packet is as follows: + * + * CARD8 reqType = 3 + * CARD8 data = 0 + * CARD16 length = total length + * STRING8 princ = encoded principal of server + */ +XID K5Check(data_length, data, client, reason) + unsigned short data_length; + char *data; + ClientPtr client; + char **reason; +{ + krb5_error_code retval; + CARD16 tlen; + krb5_principal sprinc, cprinc; + krb5_ccache cc; + krb5_creds *creds; + char *outbuf, *cp; + krb5_data princ; + register char n; + xReq prefix; + + if (krb5_id == ~0L) + return ~0L; + if (!ccname && !srvname) + return ~0L; + if (ccname) + { + if ((creds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) + return ~0L; + if (retval = krb5_cc_resolve(ccname, &cc)) + return ~0L; + bzero((char*)creds, sizeof (krb5_creds)); + if (retval = krb5_cc_get_principal(cc, &cprinc)) + { + krb5_free_creds(creds); + krb5_cc_close(cc); + return ~0L; + } + creds->client = cprinc; + if (retval = + krb5_build_principal_ext(&sprinc, + krb5_princ_realm(creds->client)->length, + krb5_princ_realm(creds->client)->data, + 6, "krbtgt", + krb5_princ_realm(creds->client)->length, + krb5_princ_realm(creds->client)->data, + 0)) + { + krb5_free_creds(creds); + krb5_cc_close(cc); + return ~0L; + } + creds->server = sprinc; + retval = krb5_get_credentials(KRB5_GC_CACHED, cc, creds); + krb5_cc_close(cc); + if (retval) + { + krb5_free_creds(creds); + return ~0L; + } + if (retval = XauKrb5Encode(cprinc, &princ)) + { + krb5_free_creds(creds); + return ~0L; + } + tlen = sz_xReq + 2 + princ.length + creds->ticket.length; + prefix.reqType = 2; /* opcode = authenticate user-to-user */ + } + else if (srvname) + { + if (retval = XauKrb5Encode(srvname, &princ)) + { + return ~0L; + } + tlen = sz_xReq + princ.length; + prefix.reqType = 3; /* opcode = authenticate client-server */ + } + prefix.data = 0; /* stage = 0 */ + prefix.length = (tlen + 3) >> 2; /* round up to nearest multiple + of 4 bytes */ + if (client->swapped) + { + swaps(&prefix.length, n); + } + if ((cp = outbuf = (char *)malloc(tlen)) == NULL) + { + if (ccname) + { + krb5_free_creds(creds); + } + free(princ.data); + return ~0L; + } + memcpy(cp, &prefix, sz_xReq); + cp += sz_xReq; + if (ccname) + { + memcpy(cp, &princ.length, 2); + if (client->swapped) + { + swaps((CARD16 *)cp, n); + } + cp += 2; + } + memcpy(cp, princ.data, princ.length); + cp += princ.length; + free(princ.data); /* we don't need that anymore */ + if (ccname) + memcpy(cp, creds->ticket.data, creds->ticket.length); + WriteToClient(client, tlen, outbuf); + free(outbuf); + client->requestVector = k5_Vector; /* hack in our dispatch vector */ + client->clientState = ClientStateAuthenticating; + if (ccname) + { + ((OsCommPtr)client->osPrivate)->authstate.srvcreds = (pointer)creds; /* save tgt creds */ + ((OsCommPtr)client->osPrivate)->authstate.ktname = NULL; + ((OsCommPtr)client->osPrivate)->authstate.srvname = NULL; + } + if (srvname) + { + ((OsCommPtr)client->osPrivate)->authstate.srvcreds = NULL; + ((OsCommPtr)client->osPrivate)->authstate.ktname = (pointer)ktname; + ((OsCommPtr)client->osPrivate)->authstate.srvname = (pointer)srvname; + } + ((OsCommPtr)client->osPrivate)->authstate.stageno = 1; /* next stage is 1 */ + return krb5_id; +} + +/* + * k5_stage1: + * + * This gets called out of the dispatcher after K5Check frobs with the + * client->requestVector. It accepts the ap_req from the client and verifies + * it. In addition, if the client has set AP_OPTS_MUTUAL_REQUIRED, it then + * sends an ap_rep to the client to achieve mutual authentication. + * + * client stage1 packet format is as follows: + * + * CARD8 reqType = 1 + * CARD8 data = ignored + * CARD16 length = total length + * STRING8 data = the actual ap_req + * + * stage2 packet sent back to client for mutual authentication: + * + * CARD8 reqType = 2 + * CARD8 data = 2 + * CARD16 length = total length + * STRING8 data = the ap_rep + */ +int k5_stage1(client) + register ClientPtr client; +{ + long addrlen; + krb5_error_code retval, retval2; + register char n; + struct sockaddr cli_net_addr; + xReq prefix; + krb5_principal cprinc; + krb5_data buf; + krb5_creds *creds = (krb5_creds *)((OsCommPtr)client->osPrivate)->authstate.srvcreds; + krb5_keyblock *skey; + krb5_address cli_addr, **localaddrs = NULL; + krb5_tkt_authent *authdat; + krb5_ap_rep_enc_part rep; + krb5_int32 ctime, cusec; + krb5_rcache rcache = NULL; + char *cachename = NULL, *rc_type = NULL, *rc_base = "rcX", *kt = NULL; + REQUEST(xReq); + + if (((OsCommPtr)client->osPrivate)->authstate.stageno != 1) + { + if (creds) + krb5_free_creds(creds); + return(SendConnSetup(client, "expected Krb5 stage1 packet")); + } + addrlen = sizeof (cli_net_addr); + if (getpeername(((OsCommPtr)client->osPrivate)->fd, + &cli_net_addr, &addrlen) == -1) + { + if (creds) + krb5_free_creds(creds); + return(SendConnSetup(client, "Krb5 stage1: getpeername failed")); + } + if (cli_net_addr.sa_family == AF_UNSPEC +#if defined(UNIXCONN) || defined(LOCALCONN) + || cli_net_addr.sa_family == AF_UNIX +#endif + ) /* assume local host */ + { + krb5_os_localaddr(&localaddrs); + if (!localaddrs || !localaddrs[0]) + { + if (creds) + krb5_free_creds(creds); + return(SendConnSetup(client, "Krb5 failed to get localaddrs")); + } + cli_addr.addrtype = localaddrs[0]->addrtype; + cli_addr.length = localaddrs[0]->length; + cli_addr.contents = localaddrs[0]->contents; + } + else + { + cli_addr.addrtype = cli_net_addr.sa_family; /* the values + are compatible */ + switch (cli_net_addr.sa_family) + { +#ifdef TCPCONN + case AF_INET: + cli_addr.length = sizeof (struct in_addr); + cli_addr.contents = + (krb5_octet *)&((struct sockaddr_in *)&cli_net_addr)->sin_addr; + break; +#endif +#ifdef DNETCONN + case AF_DECnet: + cli_addr.length = sizeof (struct dn_naddr); + cli_addr.contents = + (krb5_octet *)&((struct sockaddr_dn *)&cli_net_addr)->sdn_add; + break; +#endif + default: + if (localaddrs) + krb5_free_addresses(localaddrs); + if (creds) + krb5_free_creds(creds); + sprintf(kerror, "Krb5 stage1: unknown address family %d from getpeername", + cli_net_addr.sa_family); + return(SendConnSetup(client, kerror)); + } + } + if ((rcache = (krb5_rcache)malloc(sizeof(*rcache))) == NULL) + { + if (localaddrs) + krb5_free_addresses(localaddrs); + if (creds) + krb5_free_creds(creds); + return(SendConnSetup(client, "malloc bombed for krb5_rcache")); + } + if ((rc_type = krb5_rc_default_type()) == NULL) + rc_type = "dfl"; + if (retval = krb5_rc_resolve_type(&rcache, rc_type)) + { + if (localaddrs) + krb5_free_addresses(localaddrs); + if (creds) + krb5_free_creds(creds); + free(rcache); + strcpy(kerror, "krb5_rc_resolve_type failed: "); + strncat(kerror, error_message(retval), 231); + return(SendConnSetup(client, kerror)); + } + if ((cachename = (char *)malloc(strlen(rc_base) + strlen(display) + 1)) + == NULL) + { + if (localaddrs) + krb5_free_addresses(localaddrs); + if (creds) + krb5_free_creds(creds); + free(rcache); + return(SendConnSetup(client, "Krb5: malloc bombed for cachename")); + } + strcpy(cachename, rc_base); + strcat(cachename, display); + if (retval = krb5_rc_resolve(rcache, cachename)) + { + if (localaddrs) + krb5_free_addresses(localaddrs); + if (creds) + krb5_free_creds(creds); + free(rcache); + free(cachename); + strcpy(kerror, "krb5_rc_resolve failed: "); + strncat(kerror, error_message(retval), 236); + return(SendConnSetup(client, kerror)); + } + free(cachename); + if (krb5_rc_recover(rcache)) + { + extern krb5_deltat krb5_clockskew; + if (retval = krb5_rc_initialize(rcache, krb5_clockskew)) + { + if (localaddrs) + krb5_free_addresses(localaddrs); + if (creds) + krb5_free_creds(creds); + if (retval2 = krb5_rc_close(rcache)) + { + strcpy(kerror, "krb5_rc_close failed: "); + strncat(kerror, error_message(retval2), 238); + return(SendConnSetup(client, kerror)); + } + free(rcache); + strcpy(kerror, "krb5_rc_initialize failed: "); + strncat(kerror, error_message(retval), 233); + return(SendConnSetup(client, kerror)); + } + } + buf.length = (stuff->length << 2) - sz_xReq; + buf.data = (char *)stuff + sz_xReq; + if (creds) + { + retval = krb5_rd_req(&buf, + NULL, /* don't bother with server name */ + &cli_addr, + NULL, /* no fetchfrom */ + tgt_keyproc, + creds, /* credentials as arg to + keyproc */ + rcache, + &authdat); + krb5_free_creds(creds); + } + else if (kt = (char *)((OsCommPtr)client->osPrivate)->authstate.ktname) + { + retval = krb5_rd_req(&buf, srvname, &cli_addr, kt, NULL, NULL, + rcache, &authdat); + ((OsCommPtr)client->osPrivate)->authstate.ktname = NULL; + } + else + { + if (localaddrs) + krb5_free_addresses(localaddrs); + return(SendConnSetup(client, "Krb5: neither srvcreds nor ktname set")); + } + if (localaddrs) + krb5_free_addresses(localaddrs); + if (rcache) + { + if (retval2 = krb5_rc_close(rcache)) + { + strcpy(kerror, "krb5_rc_close failed (2): "); + strncat(kerror, error_message(retval2), 230); + return(SendConnSetup(client, kerror)); + } + free(rcache); + } + if (retval) + { + strcpy(kerror, "Krb5: Bad application request: "); + strncat(kerror, error_message(retval), 224); + return(SendConnSetup(client, kerror)); + } + cprinc = authdat->ticket->enc_part2->client; + skey = authdat->ticket->enc_part2->session; + if (XauKrb5Encode(cprinc, &buf)) + { + krb5_free_tkt_authent(authdat); + return(SendConnSetup(client, "XauKrb5Encode bombed")); + } + /* + * Now check to see if the principal we got is one that we want to let in + */ + if (ForEachHostInFamily(FamilyKrb5Principal, k5_cmpenc, (pointer)&buf)) + { + free(buf.data); + /* + * The following deals with sending an ap_rep to the client to + * achieve mutual authentication. The client sends back a stage 3 + * packet if all is ok. + */ + if (authdat->ap_options | AP_OPTS_MUTUAL_REQUIRED) + { + /* + * stage 2: send ap_rep to client + */ + if (retval = krb5_us_timeofday(&ctime, &cusec)) + { + krb5_free_tkt_authent(authdat); + strcpy(kerror, "error in krb5_us_timeofday: "); + strncat(kerror, error_message(retval), 234); + return(SendConnSetup(client, kerror)); + } + rep.ctime = ctime; + rep.cusec = cusec; + rep.subkey = NULL; + rep.seq_number = 0; + if (retval = krb5_mk_rep(&rep, skey, &buf)) + { + krb5_free_tkt_authent(authdat); + strcpy(kerror, "error in krb5_mk_rep: "); + strncat(kerror, error_message(retval), 238); + return(SendConnSetup(client, kerror)); + } + prefix.reqType = 2; /* opcode = authenticate */ + prefix.data = 2; /* stage = 2 */ + prefix.length = (buf.length + sz_xReq + 3) >> 2; + if (client->swapped) + { + swaps(&prefix.length, n); + } + WriteToClient(client, sz_xReq, (char *)&prefix); + WriteToClient(client, buf.length, buf.data); + free(buf.data); + krb5_free_tkt_authent(authdat); + ((OsCommPtr)client->osPrivate)->authstate.stageno = 3; /* expect stage3 packet */ + return(Success); + } + else + { + free(buf.data); + krb5_free_tkt_authent(authdat); + return(SendConnSetup(client, NULL)); /* success! */ + } + } + else + { + char *kname; + + krb5_free_tkt_authent(authdat); + free(buf.data); + retval = krb5_unparse_name(cprinc, &kname); + if (retval == 0) + { + sprintf(kerror, "Principal \"%s\" is not authorized to connect", + kname); + if (kname) + free(kname); + return(SendConnSetup(client, kerror)); + } + else + return(SendConnSetup(client,"Principal is not authorized to connect to Server")); + } +} + +/* + * k5_stage3: + * + * Get the short ack packet from the client. This packet can conceivably + * be expanded to allow for switching on end-to-end encryption. + * + * stage3 packet format: + * + * CARD8 reqType = 3 + * CARD8 data = ignored (for now) + * CARD16 length = should be zero + */ +int k5_stage3(client) + register ClientPtr client; +{ + REQUEST(xReq); + + if (((OsCommPtr)client->osPrivate)->authstate.stageno != 3) + { + return(SendConnSetup(client, "expected Krb5 stage3 packet")); + } + else + return(SendConnSetup(client, NULL)); /* success! */ +} + +k5_bad(client) + register ClientPtr client; +{ + if (((OsCommPtr)client->osPrivate)->authstate.srvcreds) + krb5_free_creds((krb5_creds *)((OsCommPtr)client->osPrivate)->authstate.srvcreds); + sprintf(kerror, "unrecognized Krb5 auth packet %d, expecting %d", + ((xReq *)client->requestBuffer)->reqType, + ((OsCommPtr)client->osPrivate)->authstate.stageno); + return(SendConnSetup(client, kerror)); +} + +/* + * K5Add: + * + * Takes the name of a credentials cache and resolves it. Also adds the + * primary principal of the ccache to the acl. + * + * Now will also take a service name. + */ +int K5Add(data_length, data, id) + unsigned short data_length; + char *data; + XID id; +{ + krb5_principal princ; + krb5_error_code retval; + krb5_keytab_entry tmp_entry; + krb5_keytab keytab; + krb5_kvno kvno = 0; + krb5_ccache cc; + char *nbuf, *cp; + krb5_data kbuf; + int i, ktlen; + + krb5_init_ets(); /* can't think of a better place to put it */ + krb5_id = ~0L; + if (data_length < 3) + return 0; + if ((nbuf = (char *)malloc(data_length - 2)) == NULL) + return 0; + memcpy(nbuf, data + 3, data_length - 3); + nbuf[data_length - 3] = '\0'; + if (ccname) + { + free(ccname); + ccname = NULL; + } + if (srvname) + { + krb5_free_principal(srvname); + srvname = NULL; + } + if (ktname) + { + free(ktname); + ktname = NULL; + } + if (!strncmp(data, "UU:", 3)) + { + if (retval = krb5_cc_resolve(nbuf, &cc)) + { + ErrorF("K5Add: krb5_cc_resolve of \"%s\" failed: %s\n", + nbuf, error_message(retval)); + free(nbuf); + return 0; + } + if (cc && !(retval = krb5_cc_get_principal(cc, &princ))) + { + if (XauKrb5Encode(princ, &kbuf)) + { + free(nbuf); + krb5_free_principal(princ); + krb5_cc_close(cc); + return 0; + } + if (krb5_cc_close(cc)) + return 0; + AddHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data); + krb5_free_principal(princ); + free(kbuf.data); + ccname = nbuf; + krb5_id = id; + return 1; + } + else + { + ErrorF("K5Add: getting principal from cache \"%s\" failed: %s\n", + nbuf, error_message(retval)); + } + } + else if (!strncmp(data, "CS:", 3)) + { + if ((cp = strchr(nbuf, ',')) == NULL) + { + free(nbuf); + return 0; + } + *cp = '\0'; /* gross but it works :-) */ + ktlen = strlen(cp + 1); + if ((ktname = (char *)malloc(ktlen + 1)) == NULL) + { + free(nbuf); + return 0; + } + strcpy(ktname, cp + 1); + retval = krb5_sname_to_principal(NULL, /* NULL for hostname uses + local host name*/ + nbuf, KRB5_NT_SRV_HST, + &srvname); + free(nbuf); + if (retval) + { + free(ktname); + ktname = NULL; + return 0; + } + if (retval = krb5_kt_resolve(ktname, &keytab)) + { + free(ktname); + ktname = NULL; + krb5_free_principal(srvname); + srvname = NULL; + return 0; + } + retval = krb5_kt_get_entry(keytab, srvname, kvno, &tmp_entry); + krb5_kt_free_entry(&tmp_entry); + if (retval) + { + free(ktname); + ktname = NULL; + krb5_free_principal(srvname); + srvname = NULL; + return 0; + } + if (XauKrb5Encode(srvname, &kbuf)) + { + free(ktname); + ktname = NULL; + krb5_free_principal(srvname); + srvname = NULL; + return 0; + } + AddHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data); + krb5_id = id; + return 1; + } + else + { + ErrorF("K5Add: credentials cache name \"%.*s\" in auth file: unknown type\n", + data_length, data); + } + return 0; +} + +/* + * K5Reset: + * + * Reset krb5_id, also nuke the current principal from the acl. + */ +int K5Reset() +{ + krb5_principal princ; + krb5_error_code retval; + krb5_ccache cc; + krb5_data kbuf; + int i; + + if (ccname) + { + if (retval = krb5_cc_resolve(ccname, &cc)) + { + free(ccname); + ccname = NULL; + } + if (cc && !(retval = krb5_cc_get_principal(cc, &princ))) + { + if (XauKrb5Encode(princ, &kbuf)) + return 1; + RemoveHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data); + krb5_free_principal(princ); + free(kbuf.data); + if (krb5_cc_close(cc)) + return 1; + free(ccname); + ccname = NULL; + } + } + if (srvname) + { + if (XauKrb5Encode(srvname, &kbuf)) + return 1; + RemoveHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data); + krb5_free_principal(srvname); + free(kbuf.data); + srvname = NULL; + } + if (ktname) + { + free(ktname); + ktname = NULL; + } + krb5_id = ~0L; + return 0; +} + +XID K5ToID(data_length, data) + unsigned short data_length; + char *data; +{ + return krb5_id; +} + +int K5FromID(id, data_lenp, datap) + XID id; + unsigned short *data_lenp; + char **datap; +{ + return 0; +} + +int K5Remove(data_length, data) + unsigned short data_length; + char *data; +{ + return 0; +} diff --git a/os/lbxio.c b/os/lbxio.c new file mode 100644 index 000000000..c72ac2c05 --- /dev/null +++ b/os/lbxio.c @@ -0,0 +1,585 @@ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/*********************************************************** +Copyright 1987, 1989 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. + +******************************************************************/ +/* $Xorg: lbxio.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */ + +#include +#include +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif +#include "Xmd.h" +#include +#include +#include +#include "X.h" +#include "Xproto.h" +#include "os.h" +#include "Xpoll.h" +#include "osdep.h" +#include "opaque.h" +#include "dixstruct.h" +#include "misc.h" +#include "lbxserve.h" + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST(err) (err == EAGAIN) +#else +#define ETEST(err) (err == EWOULDBLOCK) +#endif +#endif + +extern fd_set ClientsWithInput, IgnoredClientsWithInput; +extern fd_set AllClients, AllSockets; +extern fd_set ClientsWriteBlocked; +extern fd_set OutputPending; +extern int ConnectionTranslation[]; +extern Bool NewOutputPending; +extern Bool AnyClientsWriteBlocked; +extern Bool CriticalOutputPending; +extern int timesThisConnection; +extern ConnectionInputPtr FreeInputs; +extern ConnectionOutputPtr FreeOutputs; +extern OsCommPtr AvailableInput; + +#define get_req_len(req,cli) ((cli)->swapped ? \ + lswaps((req)->length) : (req)->length) + +#define YieldControl() \ + { isItTimeToYield = TRUE; \ + timesThisConnection = 0; } +#define YieldControlNoInput() \ + { YieldControl(); \ + FD_CLR(fd, &ClientsWithInput); } + +void +SwitchClientInput (client, pending) + ClientPtr client; + Bool pending; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + + ConnectionTranslation[oc->fd] = client->index; + if (pending) + FD_SET(oc->fd, &ClientsWithInput); + else + YieldControl(); +} + +void +LbxPrimeInput(client, proxy) + ClientPtr client; + LbxProxyPtr proxy; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + ConnectionInputPtr oci = oc->input; + + if (oci && proxy->compHandle) { + char *extra = oci->bufptr + oci->lenLastReq; + int left = oci->bufcnt + oci->buffer - extra; + + (*proxy->streamOpts.streamCompStuffInput)(oc->fd, + (unsigned char *)extra, + left); + oci->bufcnt -= left; + AvailableInput = oc; + } +} + +void +AvailableClientInput (client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + + if (FD_ISSET(oc->fd, &AllSockets)) + FD_SET(oc->fd, &ClientsWithInput); +} + +/***************************************************************** + * AppendFakeRequest + * Append a (possibly partial) request in as the last request. + * + **********************/ + +Bool +AppendFakeRequest (client, data, count) + ClientPtr client; + char *data; + int count; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + register int gotnow; + + if (!oci) + { + if (oci = FreeInputs) + FreeInputs = oci->next; + else if (!(oci = AllocateInputBuffer())) + return FALSE; + oc->input = oci; + } else if (AvailableInput == oc) + AvailableInput = (OsCommPtr)NULL; + /* do not free AvailableInput here, it could be proxy's */ + oci->bufptr += oci->lenLastReq; + oci->lenLastReq = 0; + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if ((gotnow + count) > oci->size) + { + char *ibuf; + + ibuf = (char *)xrealloc(oci->buffer, gotnow + count); + if (!ibuf) + return(FALSE); + oci->size = gotnow + count; + oci->buffer = ibuf; + oci->bufptr = ibuf + oci->bufcnt - gotnow; + } + if (oci->bufcnt + count > oci->size) { + memmove(oci->buffer, oci->bufptr, gotnow); + oci->bufcnt = gotnow; + oci->bufptr = oci->buffer; + } + memmove(oci->bufptr + gotnow, data, count); + oci->bufcnt += count; + gotnow += count; + if ((gotnow >= sizeof(xReq)) && + (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2))) + FD_SET(fd, &ClientsWithInput); + else + YieldControlNoInput(); + return(TRUE); +} + +static int +LbxWrite(trans_conn, proxy, buf, len) + XtransConnInfo trans_conn; + LbxProxyPtr proxy; + char *buf; + int len; +{ + struct iovec iov; + int n; + int notWritten; + + notWritten = len; + iov.iov_base = buf; + iov.iov_len = len; + while (notWritten) { + errno = 0; + if (proxy->compHandle) + n = (*proxy->streamOpts.streamCompWriteV)(proxy->fd, &iov, 1); + else + n = _XSERVTransWritev(trans_conn, &iov, 1); + if (n >= 0) { + iov.iov_base = (char *)iov.iov_base + n; + notWritten -= n; + iov.iov_len = notWritten; + } + else if (ETEST(errno) +#ifdef SUNSYSV /* check for another brain-damaged OS bug */ + || (errno == 0) +#endif +#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ + || ((errno == EMSGSIZE) && (iov.iov_len == 1)) +#endif + ) + break; +#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ + else if (errno == EMSGSIZE) + iov.iov_len >>= 1; +#endif + else + return -1; + } + return len - notWritten; +} + +static Bool +LbxAppendOutput(proxy, client, oco) + LbxProxyPtr proxy; + ClientPtr client; + ConnectionOutputPtr oco; +{ + ConnectionOutputPtr noco = proxy->olast; + LbxClientPtr lbxClient = LbxClient(client); + + if (!lbxClient) { + xfree(oco->buf); + xfree(oco); + return TRUE; + } + if (noco) + LbxReencodeOutput(client, + (char *)noco->buf, &noco->count, + (char *)oco->buf, &oco->count); + else + LbxReencodeOutput(client, + (char *)NULL, (int *)NULL, + (char *)oco->buf, &oco->count); + if (!oco->count) { + if (oco->size > BUFWATERMARK) + { + xfree(oco->buf); + xfree(oco); + } + else + { + oco->next = FreeOutputs; + FreeOutputs = oco; + } + return TRUE; + } + if ((lbxClient->id != proxy->cur_send_id) && proxy->lbxClients[0]) { + xLbxSwitchEvent *ev; + int n; + + if (!noco || (noco->size - noco->count) < sz_xLbxSwitchEvent) { + if (noco = FreeOutputs) + FreeOutputs = noco->next; + else + noco = AllocateOutputBuffer(); + if (!noco) { + MarkClientException(client); + return FALSE; + } + noco->next = NULL; + if (proxy->olast) + proxy->olast->next = noco; + else + proxy->ofirst = noco; + proxy->olast = noco; + } + ev = (xLbxSwitchEvent *) (noco->buf + noco->count); + noco->count += sz_xLbxSwitchEvent; + proxy->cur_send_id = lbxClient->id; + ev->type = LbxEventCode; + ev->lbxType = LbxSwitchEvent; + ev->pad = 0; + ev->client = proxy->cur_send_id; + if (LbxProxyClient(proxy)->swapped) { + swapl(&ev->client, n); + } + } + oco->next = NULL; + if (proxy->olast) + proxy->olast->next = oco; + else + proxy->ofirst = oco; + proxy->olast = oco; + return TRUE; +} + +static int +LbxClientOutput(client, oc, extraBuf, extraCount, nocompress) + ClientPtr client; + OsCommPtr oc; + char *extraBuf; + int extraCount; + Bool nocompress; +{ + ConnectionOutputPtr oco; + int len; + + if (oco = oc->output) { + oc->output = NULL; + if (!LbxAppendOutput(oc->proxy, client, oco)) + return -1; + } + + if (extraCount) { + NewOutputPending = TRUE; + FD_SET(oc->fd, &OutputPending); + len = (extraCount + 3) & ~3; + if ((oco = FreeOutputs) && (oco->size >= len)) + FreeOutputs = oco->next; + else { + oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput)); + if (!oco) { + MarkClientException(client); + return -1; + } + oco->size = len; + if (oco->size < BUFSIZE) + oco->size = BUFSIZE; + oco->buf = (unsigned char *) xalloc(oco->size); + if (!oco->buf) { + xfree(oco); + MarkClientException(client); + return -1; + } + } + oco->count = len; + oco->nocompress = nocompress; + memmove((char *)oco->buf, extraBuf, extraCount); + if (!nocompress && oco->count < oco->size) + oc->output = oco; + else if (!LbxAppendOutput(oc->proxy, client, oco)) + return -1; + } + return extraCount; +} + +void +LbxForceOutput(proxy) + LbxProxyPtr proxy; +{ + int i; + LbxClientPtr lbxClient; + OsCommPtr coc; + ConnectionOutputPtr oco; + + for (i = proxy->maxIndex; i >= 0; i--) { /* proxy must be last */ + lbxClient = proxy->lbxClients[i]; + if (!lbxClient) + continue; + coc = (OsCommPtr)lbxClient->client->osPrivate; + if (oco = coc->output) { + coc->output = NULL; + LbxAppendOutput(proxy, lbxClient->client, oco); + } + } +} + +int +LbxFlushClient(who, oc, extraBuf, extraCount) + ClientPtr who; + OsCommPtr oc; + char *extraBuf; + int extraCount; +{ + LbxProxyPtr proxy; + ConnectionOutputPtr oco; + int n; + XtransConnInfo trans_conn; + + if (extraBuf) + return LbxClientOutput(who, oc, extraBuf, extraCount, FALSE); + proxy = oc->proxy; + if (!proxy->lbxClients[0]) + return 0; + LbxForceOutput(proxy); + if (!proxy->compHandle) + trans_conn = ((OsCommPtr)LbxProxyClient(proxy)->osPrivate)->trans_conn; + while (oco = proxy->ofirst) { + /* XXX bundle up into writev someday */ + if (proxy->compHandle) { + if (oco->nocompress) + (*proxy->streamOpts.streamCompOff)(proxy->fd); + n = LbxWrite(NULL, proxy, (char *)oco->buf, oco->count); + if (oco->nocompress) + (*proxy->streamOpts.streamCompOn)(proxy->fd); + } else + n = LbxWrite(trans_conn, proxy, (char *)oco->buf, oco->count); + if (n < 0) { + ClientPtr pclient = LbxProxyClient(proxy); + if (proxy->compHandle) + trans_conn = ((OsCommPtr)pclient->osPrivate)->trans_conn; + _XSERVTransDisconnect(trans_conn); + _XSERVTransClose(trans_conn); + ((OsCommPtr)pclient->osPrivate)->trans_conn = NULL; + MarkClientException(pclient); + return 0; + } else if (n == oco->count) { + proxy->ofirst = oco->next; + if (!proxy->ofirst) + proxy->olast = NULL; + if (oco->size > BUFWATERMARK) + { + xfree(oco->buf); + xfree(oco); + } + else + { + oco->next = FreeOutputs; + oco->count = 0; + FreeOutputs = oco; + } + } else { + if (n) { + oco->count -= n; + memmove((char *)oco->buf, (char *)oco->buf + n, oco->count); + } + break; + } + } + if ((proxy->compHandle && + (*proxy->streamOpts.streamCompFlush)(proxy->fd)) || + proxy->ofirst) { + FD_SET(proxy->fd, &ClientsWriteBlocked); + AnyClientsWriteBlocked = TRUE; + } + return 0; +} + +int +UncompressedWriteToClient (who, count, buf) + ClientPtr who; + char *buf; + int count; +{ + return LbxClientOutput(who, (OsCommPtr)who->osPrivate, buf, count, TRUE); +} + +LbxFreeOsBuffers(proxy) + LbxProxyPtr proxy; +{ + ConnectionOutputPtr oco; + + while (oco = proxy->ofirst) { + proxy->ofirst = oco->next; + xfree(oco->buf); + xfree(oco); + } +} + +Bool +AllocateLargeReqBuffer(client, size) + ClientPtr client; + int size; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci; + + if (!(oci = oc->largereq)) { + if (oci = FreeInputs) + FreeInputs = oci->next; + else { + oci = (ConnectionInputPtr)xalloc(sizeof(ConnectionInput)); + if (!oci) + return FALSE; + oci->buffer = NULL; + oci->size = 0; + } + } + if (oci->size < size) { + char *ibuf; + + oci->size = size; + if (size < BUFSIZE) + oci->size = BUFSIZE; + if (!(ibuf = (char *)xrealloc(oci->buffer, oci->size))) + { + xfree(oci->buffer); + xfree(oci); + oc->largereq = NULL; + return FALSE; + } + oci->buffer = ibuf; + } + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = size; + oc->largereq = oci; + return TRUE; +} + +Bool +AddToLargeReqBuffer(client, data, size) + ClientPtr client; + char *data; + int size; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->largereq; + + if (!oci || (oci->bufcnt + size > oci->lenLastReq)) + return FALSE; + memcpy(oci->buffer + oci->bufcnt, data, size); + oci->bufcnt += size; + return TRUE; +} + +static OsCommRec lbxAvailableInput; + +int +PrepareLargeReqBuffer(client) + ClientPtr client; +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->largereq; + + if (!oci) + return client->req_len << 2; + oc->largereq = NULL; + if (oci->bufcnt != oci->lenLastReq) { + xfree(oci->buffer); + xfree(oci); + return client->req_len << 2; + } + client->requestBuffer = oci->buffer; + client->req_len = oci->lenLastReq >> 2; + oci->bufcnt = 0; + oci->lenLastReq = 0; + if (AvailableInput) + { + register ConnectionInputPtr aci = AvailableInput->input; + if (aci->size > BUFWATERMARK) + { + xfree(aci->buffer); + xfree(aci); + } + else + { + aci->next = FreeInputs; + FreeInputs = aci; + } + AvailableInput->input = (ConnectionInputPtr)NULL; + } + lbxAvailableInput.input = oci; + AvailableInput = &lbxAvailableInput; + return client->req_len << 2; +} diff --git a/os/mitauth.c b/os/mitauth.c new file mode 100644 index 000000000..274ab5829 --- /dev/null +++ b/os/mitauth.c @@ -0,0 +1,193 @@ +/* $Xorg: mitauth.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */ +/* + +Copyright 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * MIT-MAGIC-COOKIE-1 authorization scheme + * Author: Keith Packard, MIT X Consortium + */ + +#include "X.h" +#include "os.h" +#include "dixstruct.h" + +static struct auth { + struct auth *next; + unsigned short len; + char *data; + XID id; +} *mit_auth; + +int +MitAddCookie (data_length, data, id) +unsigned short data_length; +char *data; +XID id; +{ + struct auth *new; + + new = (struct auth *) xalloc (sizeof (struct auth)); + if (!new) + return 0; + new->data = (char *) xalloc ((unsigned) data_length); + if (!new->data) { + xfree(new); + return 0; + } + new->next = mit_auth; + mit_auth = new; + memmove(new->data, data, (int) data_length); + new->len = data_length; + new->id = id; + return 1; +} + +XID +MitCheckCookie (data_length, data, client, reason) + unsigned short data_length; + char *data; + ClientPtr client; + char **reason; +{ + struct auth *auth; + + for (auth = mit_auth; auth; auth=auth->next) { + if (data_length == auth->len && + memcmp (data, auth->data, (int) data_length) == 0) + return auth->id; + } + *reason = "Invalid MIT-MAGIC-COOKIE-1 key"; + return (XID) -1; +} + +int +MitResetCookie () +{ + struct auth *auth, *next; + + for (auth = mit_auth; auth; auth=next) { + next = auth->next; + xfree (auth->data); + xfree (auth); + } + mit_auth = 0; + return 0; +} + +XID +MitToID (data_length, data) +unsigned short data_length; +char *data; +{ + struct auth *auth; + + for (auth = mit_auth; auth; auth=auth->next) { + if (data_length == auth->len && + memcmp (data, auth->data, data_length) == 0) + return auth->id; + } + return (XID) -1; +} + +int +MitFromID (id, data_lenp, datap) +XID id; +unsigned short *data_lenp; +char **datap; +{ + struct auth *auth; + + for (auth = mit_auth; auth; auth=auth->next) { + if (id == auth->id) { + *data_lenp = auth->len; + *datap = auth->data; + return 1; + } + } + return 0; +} + +int +MitRemoveCookie (data_length, data) +unsigned short data_length; +char *data; +{ + struct auth *auth, *prev; + + prev = 0; + for (auth = mit_auth; auth; prev = auth, auth=auth->next) { + if (data_length == auth->len && + memcmp (data, auth->data, data_length) == 0) + { + if (prev) + prev->next = auth->next; + else + mit_auth = auth->next; + xfree (auth->data); + xfree (auth); + return 1; + } + } + return 0; +} + +#ifdef XCSECURITY + +static char cookie[16]; /* 128 bits */ + +XID +MitGenerateCookie (data_length, data, id, data_length_return, data_return) + unsigned int data_length; + char *data; + XID id; + unsigned int *data_length_return; + char **data_return; +{ + int i = 0; + int status; + + while (data_length--) + { + cookie[i++] += *data++; + if (i >= sizeof (cookie)) i = 0; + } + GenerateRandomData(sizeof (cookie), cookie); + status = MitAddCookie(sizeof (cookie), cookie, id); + if (!status) + { + id = -1; + } + else + { + *data_return = cookie; + *data_length_return = sizeof (cookie); + } + return id; +} + +#endif /* XCSECURITY */ diff --git a/os/oscolor.c b/os/oscolor.c new file mode 100644 index 000000000..f5fd61bc5 --- /dev/null +++ b/os/oscolor.c @@ -0,0 +1,294 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: oscolor.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */ + +#ifndef USE_RGB_TXT + +#ifdef NDBM +#include +#else +#ifdef SVR4 +#include +#else +#include +#endif +#endif +#include "rgb.h" +#include "os.h" +#include "opaque.h" + +/* Note that we are assuming there is only one database for all the screens. */ + +#ifdef NDBM +DBM *rgb_dbm = (DBM *)NULL; +#else +int rgb_dbm = 0; +#endif + +extern void CopyISOLatin1Lowered(); + +int +OsInitColors() +{ + if (!rgb_dbm) + { +#ifdef NDBM + rgb_dbm = dbm_open(rgbPath, 0, 0); +#else + if (dbminit(rgbPath) == 0) + rgb_dbm = 1; +#endif + if (!rgb_dbm) { + ErrorF( "Couldn't open RGB_DB '%s'\n", rgbPath ); + return FALSE; + } + } + return TRUE; +} + +/*ARGSUSED*/ +int +OsLookupColor(screen, name, len, pred, pgreen, pblue) + int screen; + char *name; + unsigned len; + unsigned short *pred, *pgreen, *pblue; + +{ + datum dbent; + RGB rgb; + char buf[64]; + char *lowername; + + if(!rgb_dbm) + return(0); + + /* we use Xalloc here so that we can compile with cc without alloca + * when otherwise using gcc */ + if (len < sizeof(buf)) + lowername = buf; + else if (!(lowername = (char *)Xalloc(len + 1))) + return(0); + CopyISOLatin1Lowered ((unsigned char *) lowername, (unsigned char *) name, + (int)len); + + dbent.dptr = lowername; + dbent.dsize = len; +#ifdef NDBM + dbent = dbm_fetch(rgb_dbm, dbent); +#else + dbent = fetch (dbent); +#endif + + if (len >= sizeof(buf)) + Xfree(lowername); + + if(dbent.dptr) + { + memmove((char *) &rgb, dbent.dptr, sizeof (RGB)); + *pred = rgb.red; + *pgreen = rgb.green; + *pblue = rgb.blue; + return (1); + } + return(0); +} + +#else /* USE_RGB_TXT */ + + +/* + * The dbm routines are a porting hassle. This implementation will do + * the same thing by reading the rgb.txt file directly, which is much + * more portable. + */ + +#include +#include "os.h" +#include "opaque.h" + +#define HASHSIZE 511 + +typedef struct _dbEntry * dbEntryPtr; +typedef struct _dbEntry { + dbEntryPtr link; + unsigned short red; + unsigned short green; + unsigned short blue; + char name[1]; /* some compilers complain if [0] */ +} dbEntry; + + +extern void CopyISOLatin1Lowered(); + +static dbEntryPtr hashTab[HASHSIZE]; + + +static dbEntryPtr +lookup(name, len, create) + char *name; + int len; + Bool create; +{ + unsigned int h = 0, g; + dbEntryPtr entry, *prev; + char *str = name; + + if (!(name = (char*)ALLOCATE_LOCAL(len +1))) return NULL; + CopyISOLatin1Lowered(name, str, len); + name[len] = '\0'; + + for(str = name; *str; str++) { + h = (h << 4) + *str; + if ((g = h) & 0xf0000000) h ^= (g >> 24); + h &= g; + } + h %= HASHSIZE; + + if ( entry = hashTab[h] ) + { + for( ; entry; prev = (dbEntryPtr*)entry, entry = entry->link ) + if (! strcmp(name, entry->name) ) break; + } + else + prev = &(hashTab[h]); + + if (!entry && create && (entry = (dbEntryPtr)Xalloc(sizeof(dbEntry) +len))) + { + *prev = entry; + entry->link = NULL; + strcpy( entry->name, name ); + } + + DEALLOCATE_LOCAL(name); + + return entry; +} + + +Bool +OsInitColors() +{ + FILE *rgb; + char *path; + char line[BUFSIZ]; + char name[BUFSIZ]; + int red, green, blue, lineno = 0; + dbEntryPtr entry; + + static Bool was_here = FALSE; + + if (!was_here) + { + path = (char*)ALLOCATE_LOCAL(strlen(rgbPath) +5); + strcpy(path, rgbPath); + strcat(path, ".txt"); + + if (!(rgb = fopen(path, "r"))) + { + ErrorF( "Couldn't open RGB_DB '%s'\n", rgbPath ); + DEALLOCATE_LOCAL(path); + return FALSE; + } + + while(fgets(line, sizeof(line), rgb)) + { + lineno++; + if (sscanf(line,"%d %d %d %[^\n]\n", &red, &green, &blue, name) == 4) + { + if (red >= 0 && red <= 0xff && + green >= 0 && green <= 0xff && + blue >= 0 && blue <= 0xff) + { + if (entry = lookup(name, strlen(name), TRUE)) + { + entry->red = (red * 65535) / 255; + entry->green = (green * 65535) / 255; + entry->blue = (blue * 65535) / 255; + } + } + else + ErrorF("Value for \"%s\" out of range: %s:%d\n", + name, path, lineno); + } + else if (*line && *line != '#' && *line != '!') + ErrorF("Syntax Error: %s:%d\n", path, lineno); + } + + fclose(rgb); + DEALLOCATE_LOCAL(path); + + was_here = TRUE; + } + + return TRUE; +} + + + +Bool +OsLookupColor(screen, name, len, pred, pgreen, pblue) + int screen; + char *name; + unsigned len; + unsigned short *pred, *pgreen, *pblue; + +{ + dbEntryPtr entry; + + if (entry = lookup(name, len, FALSE)) + { + *pred = entry->red; + *pgreen = entry->green; + *pblue = entry->blue; + return TRUE; + } + + return FALSE; +} + +#endif /* USE_RGB_TXT */ diff --git a/os/osdep.h b/os/osdep.h new file mode 100644 index 000000000..c7c730740 --- /dev/null +++ b/os/osdep.h @@ -0,0 +1,186 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: osdep.h,v 1.5 2001/02/09 02:05:23 xorgcvs Exp $ */ + +#define BOTIMEOUT 200 /* in milliseconds */ +#define BUFSIZE 4096 +#define BUFWATERMARK 8192 +#define MAXBUFSIZE (1 << 22) + +#ifndef sgi /* SGI defines OPEN_MAX in a useless way */ +#ifndef X_NOT_POSIX +#ifdef _POSIX_SOURCE +#include +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif +#else /* X_NOT_POSIX */ +#ifdef WIN32 +#define _POSIX_ +#include +#undef _POSIX_ +#endif +#endif /* X_NOT_POSIX */ +#endif + +#ifndef OPEN_MAX +#ifdef SVR4 +#define OPEN_MAX 256 +#else +#include +#ifndef OPEN_MAX +#if defined(NOFILE) && !defined(NOFILES_MAX) +#define OPEN_MAX NOFILE +#else +#define OPEN_MAX NOFILES_MAX +#endif +#endif +#endif +#endif + +#if OPEN_MAX <= 256 +#define MAXSOCKS (OPEN_MAX - 1) +#else +#define MAXSOCKS 256 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +typedef struct _connectionInput { + struct _connectionInput *next; + char *buffer; /* contains current client input */ + char *bufptr; /* pointer to current start of data */ + int bufcnt; /* count of bytes in buffer */ + int lenLastReq; + int size; +} ConnectionInput, *ConnectionInputPtr; + +typedef struct _connectionOutput { + struct _connectionOutput *next; + int size; + unsigned char *buf; + int count; +#ifdef LBX + Bool nocompress; +#endif +} ConnectionOutput, *ConnectionOutputPtr; + +#ifdef K5AUTH +typedef struct _k5_state { + int stageno; /* current stage of auth protocol */ + pointer srvcreds; /* server credentials */ + pointer srvname; /* server principal name */ + pointer ktname; /* key table: principal-key pairs */ + pointer skey; /* session key */ +} k5_state; +#endif + +#ifdef LBX +typedef struct _LbxProxy *OsProxyPtr; +#endif + +typedef struct _osComm { + int fd; + ConnectionInputPtr input; + ConnectionOutputPtr output; + XID auth_id; /* authorization id */ +#ifdef K5AUTH + k5_state authstate; /* state of setup auth conversation */ +#endif + CARD32 conn_time; /* timestamp if not established, else 0 */ + struct _XtransConnInfo *trans_conn; /* transport connection object */ +#ifdef LBX + OsProxyPtr proxy; + ConnectionInputPtr largereq; + void (*Close) (); + int (*Flush) (); +#endif +} OsCommRec, *OsCommPtr; + +#ifdef LBX +#define FlushClient(who, oc, extraBuf, extraCount) \ + (*(oc)->Flush)(who, oc, extraBuf, extraCount) +extern int StandardFlushClient( +#if NeedFunctionPrototypes + ClientPtr /*who*/, + OsCommPtr /*oc*/, + char* /*extraBuf*/, + int /*extraCount*/ +#endif +); +#else +extern int FlushClient( +#if NeedFunctionPrototypes + ClientPtr /*who*/, + OsCommPtr /*oc*/, + char* /*extraBuf*/, + int /*extraCount*/ +#endif +); +#endif + +extern void FreeOsBuffers( +#if NeedFunctionPrototypes + OsCommPtr /*oc*/ +#endif +); + +extern ConnectionInputPtr AllocateInputBuffer( +#if NeedFunctionPrototypes + void +#endif +); + +extern ConnectionOutputPtr AllocateOutputBuffer( +#if NeedFunctionPrototypes + void +#endif +); diff --git a/os/osinit.c b/os/osinit.c new file mode 100644 index 000000000..f240ea42c --- /dev/null +++ b/os/osinit.c @@ -0,0 +1,200 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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. + +******************************************************************/ +/* $Xorg: osinit.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */ + +#include +#include "X.h" +#include "os.h" +#include "osdep.h" +#include "Xos.h" + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +#ifndef WIN32 +#ifndef SYSV +#include +#endif +#endif + +#ifndef ADMPATH +#define ADMPATH "/usr/adm/X%smsgs" +#endif + +extern char *display; +#ifdef RLIMIT_DATA +int limitDataSpace = -1; +#endif +#ifdef RLIMIT_STACK +int limitStackSpace = -1; +#endif +#ifdef RLIMIT_NOFILE +int limitNoFile = -1; +#endif + +Bool OsDelayInitColors = FALSE; + +void +OsInit() +{ + static Bool been_here = FALSE; + static char* admpath = ADMPATH; + static char* devnull = "/dev/null"; + char fname[PATH_MAX]; + +#ifdef macII + set42sig(); +#endif + + if (!been_here) { + fclose(stdin); + fclose(stdout); + /* + * If a write of zero bytes to stderr returns non-zero, i.e. -1, + * then writing to stderr failed, and we'll write somewhere else + * instead. (Apparently this never happens in the Real World.) + */ + if (write (2, fname, 0) == -1) + { + FILE *err; + + if (strlen (display) + strlen (admpath) + 1 < sizeof fname) + sprintf (fname, admpath, display); + else + strcpy (fname, devnull); + /* + * uses stdio to avoid os dependencies here, + * a real os would use + * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) + */ + if (!(err = fopen (fname, "a+"))) + err = fopen (devnull, "w"); + if (err && (fileno(err) != 2)) { + dup2 (fileno (err), 2); + fclose (err); + } +#if defined(SYSV) || defined(SVR4) || defined(WIN32) + { + static char buf[BUFSIZ]; + setvbuf (stderr, buf, _IOLBF, BUFSIZ); + } +#else + setlinebuf(stderr); +#endif + } + +#ifndef X_NOT_POSIX + if (getpgrp () == 0) + setpgid (0, 0); +#else +#if !defined(SYSV) && !defined(WIN32) + if (getpgrp (0) == 0) + setpgrp (0, getpid ()); +#endif +#endif + +#ifdef RLIMIT_DATA + if (limitDataSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_DATA, &rlim)) + { + if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) + rlim.rlim_cur = limitDataSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_DATA, &rlim); + } + } +#endif +#ifdef RLIMIT_STACK + if (limitStackSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_STACK, &rlim)) + { + if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) + rlim.rlim_cur = limitStackSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_STACK, &rlim); + } + } +#endif +#ifdef RLIMIT_NOFILE + if (limitNoFile >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_NOFILE, &rlim)) + { + if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) + rlim.rlim_cur = limitNoFile; + else + rlim.rlim_cur = rlim.rlim_max; + if (rlim.rlim_cur > MAXSOCKS) + rlim.rlim_cur = MAXSOCKS; + (void)setrlimit(RLIMIT_NOFILE, &rlim); + } + } +#endif + been_here = TRUE; + } + TimerInit(); +#ifdef DDXOSINIT + OsVendorInit(); +#endif + OsInitAllocator(); + if (!OsDelayInitColors) OsInitColors(); +} diff --git a/os/rpcauth.c b/os/rpcauth.c new file mode 100644 index 000000000..15111921f --- /dev/null +++ b/os/rpcauth.c @@ -0,0 +1,202 @@ +/* $Xorg: rpcauth.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * SUN-DES-1 authentication mechanism + * Author: Mayank Choudhary, Sun Microsystems + */ + + +#ifdef SECURE_RPC + +#include "X.h" +#include "Xauth.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" + +#include + +#ifdef ultrix +#include +#include +#endif + +static enum auth_stat why; + +static char * +authdes_ezdecode(inmsg, len) +char *inmsg; +int len; +{ + struct rpc_msg msg; + char cred_area[MAX_AUTH_BYTES]; + char verf_area[MAX_AUTH_BYTES]; + char *temp_inmsg; + struct svc_req r; + bool_t res0, res1; + XDR xdr; + SVCXPRT xprt; + + temp_inmsg = (char *) xalloc(len); + memmove(temp_inmsg, inmsg, len); + + memset((char *)&msg, 0, sizeof(msg)); + memset((char *)&r, 0, sizeof(r)); + memset(cred_area, 0, sizeof(cred_area)); + memset(verf_area, 0, sizeof(verf_area)); + + msg.rm_call.cb_cred.oa_base = cred_area; + msg.rm_call.cb_verf.oa_base = verf_area; + why = AUTH_FAILED; + xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE); + + if ((r.rq_clntcred = (caddr_t) xalloc(MAX_AUTH_BYTES)) == NULL) + goto bad1; + r.rq_xprt = &xprt; + + /* decode into msg */ + res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred)); + res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf)); + if ( ! (res0 && res1) ) + goto bad2; + + /* do the authentication */ + + r.rq_cred = msg.rm_call.cb_cred; /* read by opaque stuff */ + if (r.rq_cred.oa_flavor != AUTH_DES) { + why = AUTH_TOOWEAK; + goto bad2; + } +#ifdef SVR4 + if ((why = __authenticate(&r, &msg)) != AUTH_OK) { +#else + if ((why = _authenticate(&r, &msg)) != AUTH_OK) { +#endif + goto bad2; + } + return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name); + +bad2: + Xfree(r.rq_clntcred); +bad1: + return ((char *)0); /* ((struct authdes_cred *) NULL); */ +} + +static XID rpc_id = (XID) ~0L; + +static Bool +CheckNetName (addr, len, closure) + unsigned char *addr; + int len; + pointer closure; +{ + return (len == strlen ((char *) closure) && + strncmp ((char *) addr, (char *) closure, len) == 0); +} + +static char rpc_error[MAXNETNAMELEN+50]; + +XID +SecureRPCCheck (data_length, data, client, reason) + register unsigned short data_length; + char *data; + ClientPtr client; + char **reason; +{ + char *fullname; + + if (rpc_id == (XID) ~0L) { + *reason = "Secure RPC authorization not initialized"; + } else { + fullname = authdes_ezdecode(data, data_length); + if (fullname == (char *)0) { + sprintf(rpc_error, "Unable to authenticate secure RPC client (why=%d)", why); + *reason = rpc_error; + } else { + if (ForEachHostInFamily (FamilyNetname, CheckNetName, + (pointer) fullname)) + return rpc_id; + else { + sprintf(rpc_error, "Principal \"%s\" is not authorized to connect", + fullname); + *reason = rpc_error; + } + } + } + return (XID) ~0L; +} + + +SecureRPCInit () +{ + if (rpc_id == ~0L) + AddAuthorization (9, "SUN-DES-1", 0, (char *) 0); +} + +int +SecureRPCAdd (data_length, data, id) +unsigned short data_length; +char *data; +XID id; +{ + if (data_length) + AddHost ((pointer) 0, FamilyNetname, data_length, data); + rpc_id = id; +} + +int +SecureRPCReset () +{ + rpc_id = (XID) ~0L; +} + +XID +SecureRPCToID (data_length, data) + unsigned short data_length; + char *data; +{ + return rpc_id; +} + +SecureRPCFromID (id, data_lenp, datap) + XID id; + unsigned short *data_lenp; + char **datap; +{ + return 0; +} + +SecureRPCRemove (data_length, data) + unsigned short data_length; + char *data; +{ + return 0; +} +#endif /* SECURE_RPC */ diff --git a/os/secauth.c b/os/secauth.c new file mode 100644 index 000000000..a73f4e718 --- /dev/null +++ b/os/secauth.c @@ -0,0 +1,201 @@ +/* $Xorg: secauth.c,v 1.5 2001/02/15 02:06:01 coskrey Exp $ */ +/* +Copyright 1996, 1998, 2001 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. +*/ + +#include "X.h" +#include "os.h" +#include "osdep.h" +#include "dixstruct.h" + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +static char InvalidPolicyReason[] = "invalid policy specification"; +static char PolicyViolationReason[] = "policy violation"; + +static Bool +AuthCheckSitePolicy(data_lengthP, dataP, client, reason) + unsigned short *data_lengthP; + char **dataP; + ClientPtr client; + char **reason; +{ + CARD8 *policy = *(CARD8 **)dataP; + int length; + Bool permit; + int nPolicies; + char **sitePolicies; + int nSitePolicies; + Bool found = FALSE; + + if ((length = *data_lengthP) < 2) { + *reason = InvalidPolicyReason; + return FALSE; + } + + permit = (*policy++ == 0); + nPolicies = (CARD8) *policy++; + + length -= 2; + + sitePolicies = SecurityGetSitePolicyStrings(&nSitePolicies); + + while (nPolicies > 0) { + int strLen, sitePolicy; + + if (length == 0) { + *reason = InvalidPolicyReason; + return FALSE; + } + + strLen = (CARD8) *policy++; + if (--length < strLen) { + *reason = InvalidPolicyReason; + return FALSE; + } + + if (!found) + { + for (sitePolicy = 0; sitePolicy < nSitePolicies; sitePolicy++) + { + char *testPolicy = sitePolicies[sitePolicy]; + if ((strLen == strlen(testPolicy)) && + (strncmp((char *)policy, testPolicy, strLen) == 0)) + { + found = TRUE; /* need to continue parsing the policy... */ + break; + } + } + } + + policy += strLen; + length -= strLen; + nPolicies--; + } + + if (found != permit) + { + *reason = PolicyViolationReason; + return FALSE; + } + + *data_lengthP = length; + *dataP = (char *)policy; + return TRUE; +} + +XID +AuthSecurityCheck (data_length, data, client, reason) + unsigned short data_length; + char *data; + ClientPtr client; + char **reason; +{ +#ifdef XCSECURITY + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + xConnSetupPrefix csp; + xReq freq; + + if (client->clientState == ClientStateCheckedSecurity) + { + *reason = "repeated security check not permitted"; + return (XID) -1; + } + else if (data_length > 0) + { + char policy_mask = *data++; + + if (--data_length == 1) { + *reason = InvalidPolicyReason; + return (XID) -1; + } + + if (policy_mask & 0x01) /* Extensions policy */ + { + /* AuthCheckExtensionPolicy(&data_length, &data, client, reason) */ + *reason = "security policy not implemented"; + return (XID) -1; + } + + if (policy_mask & 0x02) /* Site policy */ + { + if (!AuthCheckSitePolicy(&data_length, &data, client, reason)) + return (XID) -1; + } + + if (data_length > 0) { /* did we consume the whole policy? */ + *reason = InvalidPolicyReason; + return (XID) -1; + } + + } + else if (!GetAccessControl()) + { + /* + * The client - possibly the X FireWall Proxy - gave + * no auth data and host-based authorization is turned + * off. In this case, the client should be denied + * access to the X server. + */ + *reason = "server host access control is disabled"; + return (XID) -1; + } + + client->clientState = ClientStateCheckingSecurity; + + csp.success = 2 /* Authenticate */; + csp.lengthReason = 0; + csp.length = 0; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + + /* + * Next time the client sends the real auth data, we want + * ProcEstablishConnection to be called. + */ + + freq.reqType = 1; + freq.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + client->swapped = FALSE; + if (!InsertFakeRequest(client, (char *)&freq, sz_xReq)) + { + *reason = "internal error"; + return (XID) -1; + } + + return (XID) 0; +#else + *reason = "method not supported"; + return (XID) -1; +#endif +} diff --git a/os/utils.c b/os/utils.c new file mode 100644 index 000000000..2c3d0ba63 --- /dev/null +++ b/os/utils.c @@ -0,0 +1,1105 @@ +/* $Xorg: utils.c,v 1.5 2001/02/09 02:05:24 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +Copyright 1994 Quarterdeck Office Systems. + + 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 and +Quarterdeck not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +DIGITAL AND QUARTERDECK DISCLAIM 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. + +*/ + +#ifdef WIN32 +#include +#endif +#include "Xos.h" +#include +#include "misc.h" +#include "X.h" +#include "input.h" +#include "opaque.h" +#ifdef X_POSIX_C_SOURCE +#define _POSIX_C_SOURCE X_POSIX_C_SOURCE +#include +#undef _POSIX_C_SOURCE +#else +#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) +#include +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif +#endif +#ifndef WIN32 +#ifndef SYSV +#include +#endif +#endif +#include +#include +#include /* for isspace */ +#if NeedVarargsPrototypes +#include +#endif +#if defined(TCPCONN) || defined(STREAMSCONN) +# ifndef WIN32 +# include +# endif +#endif + +#define X_INCLUDE_NETDB_H +#include + +extern char *display; + +extern CARD32 defaultScreenSaverTime; /* for parsing command line */ +extern CARD32 defaultScreenSaverInterval; +extern int defaultScreenSaverBlanking; +extern int defaultBackingStore; +extern Bool disableBackingStore; +extern Bool disableSaveUnders; +extern Bool PartialNetwork; +#ifndef NOLOGOHACK +extern int logoScreenSaver; +#endif +#ifdef RLIMIT_DATA +extern int limitDataSpace; +#endif +#ifdef RLIMIT_STACK +extern int limitStackSpace; +#endif +#ifdef RLIMIT_NOFILE +extern int limitNoFile; +#endif +extern int defaultColorVisualClass; +extern Bool permitOldBugs; +extern int monitorResolution; +extern Bool defeatAccessControl; + +#ifdef DPMSExtension +extern BOOL DPMSEnabledSwitch; +extern BOOL DPMSDisabledSwitch; +#endif + +Bool CoreDump; +Bool noTestExtensions; + +Bool noPanoramiXExtension = TRUE; +#ifdef PANORAMIX +Bool PanoramiXVisibilityNotifySent = FALSE; +Bool PanoramiXMapped = FALSE; +Bool PanoramiXWindowExposureSent = FALSE; +Bool PanoramiXOneExposeRequest = FALSE; +#endif + +int auditTrailLevel = 1; + +void ddxUseMsg(); +#if NeedVarargsPrototypes +void VErrorF(char*, va_list); +#endif + +#ifdef AIXV3 +int SyncOn = 0; +extern int SelectWaitTime; +#endif + +#ifdef DEBUG +#ifndef SPECIAL_MALLOC +#define MEMBUG +#endif +#endif + +#ifdef MEMBUG +#define MEM_FAIL_SCALE 100000 +long Memory_fail = 0; + +#endif + +#ifdef sgi +int userdefinedfontpath = 0; +#endif /* sgi */ + +Bool Must_have_memory = FALSE; + +char *dev_tty_from_init = NULL; /* since we need to parse it anyway */ + +OsSigHandlerPtr +OsSignal(sig, handler) + int sig; + OsSigHandlerPtr handler; +{ +#ifdef X_NOT_POSIX + return signal(sig, handler); +#else + struct sigaction act, oact; + + sigemptyset(&act.sa_mask); + if (handler != SIG_IGN) + sigaddset(&act.sa_mask, sig); + act.sa_flags = 0; + act.sa_handler = handler; + sigaction(sig, &act, &oact); + return oact.sa_handler; +#endif +} + +/* Force connections to close on SIGHUP from init */ + +/*ARGSUSED*/ +SIGVAL +AutoResetServer (sig) + int sig; +{ + dispatchException |= DE_RESET; + isItTimeToYield = TRUE; +#ifdef GPROF + chdir ("/tmp"); + exit (0); +#endif +#if defined(SYSV) && defined(X_NOT_POSIX) + OsSignal (SIGHUP, AutoResetServer); +#endif +} + +/* Force connections to close and then exit on SIGTERM, SIGINT */ + +/*ARGSUSED*/ +SIGVAL +GiveUp(sig) + int sig; +{ + dispatchException |= DE_TERMINATE; + isItTimeToYield = TRUE; +#if defined(SYSV) && defined(X_NOT_POSIX) + if (sig) + OsSignal(sig, SIG_IGN); +#endif +} + + +static void +AbortServer() +{ + extern void AbortDDX(); + + AbortDDX(); + fflush(stderr); + if (CoreDump) + abort(); + exit (1); +} + +void +Error(str) + char *str; +{ + perror(str); +} + +#ifndef DDXTIME +CARD32 +GetTimeInMillis() +{ + struct timeval tp; + + X_GETTIMEOFDAY(&tp); + return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} +#endif + +AdjustWaitForDelay (waitTime, newdelay) + pointer waitTime; + unsigned long newdelay; +{ + static struct timeval delay_val; + struct timeval **wt = (struct timeval **) waitTime; + unsigned long olddelay; + + if (*wt == NULL) + { + delay_val.tv_sec = newdelay / 1000; + delay_val.tv_usec = 1000 * (newdelay % 1000); + *wt = &delay_val; + } + else + { + olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000; + if (newdelay < olddelay) + { + (*wt)->tv_sec = newdelay / 1000; + (*wt)->tv_usec = 1000 * (newdelay % 1000); + } + } +} + +void UseMsg() +{ +#if !defined(AIXrt) && !defined(AIX386) + ErrorF("use: X [:] [option]\n"); + ErrorF("-a # mouse acceleration (pixels)\n"); + ErrorF("-ac disable access control restrictions\n"); +#ifdef MEMBUG + ErrorF("-alloc int chance alloc should fail\n"); +#endif + ErrorF("-audit int set audit trail level\n"); + ErrorF("-auth file select authorization file\n"); + ErrorF("bc enable bug compatibility\n"); + ErrorF("-bs disable any backing store support\n"); + ErrorF("-c turns off key-click\n"); + ErrorF("c # key-click volume (0-100)\n"); + ErrorF("-cc int default color visual class\n"); + ErrorF("-co file color database file\n"); +#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS + ErrorF("-config file read options from file\n"); +#endif + ErrorF("-core generate core dump on fatal error\n"); + ErrorF("-dpi int screen resolution in dots per inch\n"); +#ifdef DPMSExtension + ErrorF("dpms enables VESA DPMS monitor control\n"); + ErrorF("-dpms disables VESA DPMS monitor control\n"); +#endif + ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n"); + ErrorF("-f # bell base (0-100)\n"); + ErrorF("-fc string cursor font\n"); + ErrorF("-fn string default font name\n"); + ErrorF("-fp string default font path\n"); + ErrorF("-help prints message with these options\n"); + ErrorF("-I ignore all remaining arguments\n"); +#ifdef RLIMIT_DATA + ErrorF("-ld int limit data space to N Kb\n"); +#endif +#ifdef RLIMIT_NOFILE + ErrorF("-lf int limit number of open files to N\n"); +#endif +#ifdef RLIMIT_STACK + ErrorF("-ls int limit stack space to N Kb\n"); +#endif +#ifndef NOLOGOHACK + ErrorF("-logo enable logo in screen saver\n"); + ErrorF("nologo disable logo in screen saver\n"); +#endif + ErrorF("-p # screen-saver pattern duration (minutes)\n"); + ErrorF("-pn accept failure to listen on all ports\n"); + ErrorF("-r turns off auto-repeat\n"); + ErrorF("r turns on auto-repeat \n"); + ErrorF("-s # screen-saver timeout (minutes)\n"); +#ifdef XCSECURITY + ErrorF("-sp file security policy file\n"); +#endif + ErrorF("-su disable any save under support\n"); + ErrorF("-t # mouse threshold (pixels)\n"); + ErrorF("-terminate terminate at server reset\n"); + ErrorF("-to # connection time out\n"); + ErrorF("-tst disable testing extensions\n"); + ErrorF("ttyxx server started from init on /dev/ttyxx\n"); + ErrorF("v video blanking for screen-saver\n"); + ErrorF("-v screen-saver without video blanking\n"); + ErrorF("-wm WhenMapped default backing-store\n"); +#ifdef PANORAMIX + ErrorF("+xinerama Enable XINERAMA extension\n"); + ErrorF("-xinerama Disable XINERAMA extension\n"); +#endif + ErrorF("-x string loads named extension at init time \n"); +#ifdef XDMCP + XdmcpUseMsg(); +#endif +#endif /* !AIXrt && ! AIX386 */ +#ifdef XKB + XkbUseMsg(); +#endif + ddxUseMsg(); +} + +/* + * This function parses the command line. Handles device-independent fields + * and allows ddx to handle additional fields. It is not allowed to modify + * argc or any of the strings pointed to by argv. + */ +void +ProcessCommandLine ( argc, argv ) +int argc; +char *argv[]; + +{ + int i, skip; + + defaultKeyboardControl.autoRepeat = TRUE; + + for ( i = 1; i < argc; i++ ) + { + /* call ddx first, so it can peek/override if it wants */ + if(skip = ddxProcessArgument(argc, argv, i)) + { + i += (skip - 1); + } + else if(argv[i][0] == ':') + { + /* initialize display */ + display = argv[i]; + display++; + } + else if ( strcmp( argv[i], "-a") == 0) + { + if(++i < argc) + defaultPointerControl.num = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-ac") == 0) + { + defeatAccessControl = TRUE; + } +#ifdef MEMBUG + else if ( strcmp( argv[i], "-alloc") == 0) + { + if(++i < argc) + Memory_fail = atoi(argv[i]); + else + UseMsg(); + } +#endif + else if ( strcmp( argv[i], "-audit") == 0) + { + if(++i < argc) + auditTrailLevel = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-auth") == 0) + { + if(++i < argc) + InitAuthorization (argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "bc") == 0) + permitOldBugs = TRUE; + else if ( strcmp( argv[i], "-bs") == 0) + disableBackingStore = TRUE; + else if ( strcmp( argv[i], "c") == 0) + { + if(++i < argc) + defaultKeyboardControl.click = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-c") == 0) + { + defaultKeyboardControl.click = 0; + } + else if ( strcmp( argv[i], "-cc") == 0) + { + if(++i < argc) + defaultColorVisualClass = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-co") == 0) + { + if(++i < argc) + rgbPath = argv[i]; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-core") == 0) + CoreDump = TRUE; + else if ( strcmp( argv[i], "-dpi") == 0) + { + if(++i < argc) + monitorResolution = atoi(argv[i]); + else + UseMsg(); + } +#ifdef DPMSExtension + else if ( strcmp( argv[i], "dpms") == 0) + DPMSEnabledSwitch = TRUE; + else if ( strcmp( argv[i], "-dpms") == 0) + DPMSDisabledSwitch = TRUE; +#endif + else if ( strcmp( argv[i], "-deferglyphs") == 0) + { + if(++i >= argc || !ParseGlyphCachingMode(argv[i])) + UseMsg(); + } + else if ( strcmp( argv[i], "-f") == 0) + { + if(++i < argc) + defaultKeyboardControl.bell = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-fc") == 0) + { + if(++i < argc) + defaultCursorFont = argv[i]; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-fn") == 0) + { + if(++i < argc) + defaultTextFont = argv[i]; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-fp") == 0) + { + if(++i < argc) + { +#ifdef sgi + userdefinedfontpath = 1; +#endif /* sgi */ + defaultFontPath = argv[i]; + } + else + UseMsg(); + } + else if ( strcmp( argv[i], "-help") == 0) + { + UseMsg(); + exit(0); + } +#ifdef XKB + else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) { + if (skip>0) + i+= skip-1; + else UseMsg(); + } +#endif +#ifdef RLIMIT_DATA + else if ( strcmp( argv[i], "-ld") == 0) + { + if(++i < argc) + { + limitDataSpace = atoi(argv[i]); + if (limitDataSpace > 0) + limitDataSpace *= 1024; + } + else + UseMsg(); + } +#endif +#ifdef RLIMIT_NOFILE + else if ( strcmp( argv[i], "-lf") == 0) + { + if(++i < argc) + limitNoFile = atoi(argv[i]); + else + UseMsg(); + } +#endif +#ifdef RLIMIT_STACK + else if ( strcmp( argv[i], "-ls") == 0) + { + if(++i < argc) + { + limitStackSpace = atoi(argv[i]); + if (limitStackSpace > 0) + limitStackSpace *= 1024; + } + else + UseMsg(); + } +#endif +#ifndef NOLOGOHACK + else if ( strcmp( argv[i], "-logo") == 0) + { + logoScreenSaver = 1; + } + else if ( strcmp( argv[i], "nologo") == 0) + { + logoScreenSaver = 0; + } +#endif + else if ( strcmp( argv[i], "-p") == 0) + { + if(++i < argc) + defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) * + MILLI_PER_MIN; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-pn") == 0) + PartialNetwork = TRUE; + else if ( strcmp( argv[i], "r") == 0) + defaultKeyboardControl.autoRepeat = TRUE; + else if ( strcmp( argv[i], "-r") == 0) + defaultKeyboardControl.autoRepeat = FALSE; + else if ( strcmp( argv[i], "-s") == 0) + { + if(++i < argc) + defaultScreenSaverTime = ((CARD32)atoi(argv[i])) * + MILLI_PER_MIN; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-su") == 0) + disableSaveUnders = TRUE; + else if ( strcmp( argv[i], "-t") == 0) + { + if(++i < argc) + defaultPointerControl.threshold = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-terminate") == 0) + { + extern Bool terminateAtReset; + + terminateAtReset = TRUE; + } + else if ( strcmp( argv[i], "-to") == 0) + { + if(++i < argc) + TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-tst") == 0) + { + noTestExtensions = TRUE; + } + else if ( strcmp( argv[i], "v") == 0) + defaultScreenSaverBlanking = PreferBlanking; + else if ( strcmp( argv[i], "-v") == 0) + defaultScreenSaverBlanking = DontPreferBlanking; + else if ( strcmp( argv[i], "-wm") == 0) + defaultBackingStore = WhenMapped; +#ifdef PANORAMIX + else if ( strcmp( argv[i], "+xinerama") == 0){ + noPanoramiXExtension = FALSE; + } + else if ( strcmp( argv[i], "-xinerama") == 0){ + noPanoramiXExtension = TRUE; + } +#endif + else if ( strcmp( argv[i], "-x") == 0) + { + if(++i >= argc) + UseMsg(); + /* For U**x, which doesn't support dynamic loading, there's nothing + * to do when we see a -x. Either the extension is linked in or + * it isn't */ + } + else if ( strcmp( argv[i], "-I") == 0) + { + /* ignore all remaining arguments */ + break; + } + else if (strncmp (argv[i], "tty", 3) == 0) + { + /* just in case any body is interested */ + dev_tty_from_init = argv[i]; + } +#ifdef XDMCP + else if ((skip = XdmcpOptions(argc, argv, i)) != i) + { + i = skip - 1; + } +#endif +#ifdef XPRINT + else if ((skip = XprintOptions(argc, argv, i)) != i) + { + i = skip - 1; + } +#endif +#ifdef XCSECURITY + else if ((skip = XSecurityOptions(argc, argv, i)) != i) + { + i = skip - 1; + } +#endif +#ifdef AIXV3 + else if ( strcmp( argv[i], "-timeout") == 0) + { + if(++i < argc) + SelectWaitTime = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-sync") == 0) + { + SyncOn++; + } +#endif + else + { + UseMsg(); + exit (1); + } + } +} + +#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS +static void +InsertFileIntoCommandLine(resargc, resargv, prefix_argc, prefix_argv, + filename, suffix_argc, suffix_argv) + int *resargc; + char ***resargv; + int prefix_argc; + char **prefix_argv; + char *filename; + int suffix_argc; + char **suffix_argv; +{ + struct stat st; + FILE *f; + char *p; + char *q; + int insert_argc; + char *buf; + int len; + int i; + + f = fopen(filename, "r"); + if (!f) + FatalError("Can't open option file %s\n", filename); + + fstat(fileno(f), &st); + + buf = (char *) xalloc((unsigned) st.st_size + 1); + if (!buf) + FatalError("Out of Memory\n"); + + len = fread(buf, 1, (unsigned) st.st_size, f); + + fclose(f); + + if (len < 0) + FatalError("Error reading option file %s\n", filename); + + buf[len] = '\0'; + + p = buf; + q = buf; + insert_argc = 0; + + while (*p) + { + while (isspace(*p)) + p++; + if (!*p) + break; + if (*p == '#') + { + while (*p && *p != '\n') + p++; + } else + { + while (*p && !isspace(*p)) + *q++ = *p++; + /* Since p and q might still be pointing at the same place, we */ + /* need to step p over the whitespace now before we add the null. */ + if (*p) + p++; + *q++ = '\0'; + insert_argc++; + } + } + + buf = (char *) xrealloc(buf, q - buf); + if (!buf) + FatalError("Out of memory reallocing option buf\n"); + + *resargc = prefix_argc + insert_argc + suffix_argc; + *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *)); + if (!*resargv) + FatalError("Out of Memory\n"); + + memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *)); + + p = buf; + for (i = 0; i < insert_argc; i++) + { + (*resargv)[prefix_argc + i] = p; + p += strlen(p) + 1; + } + + memcpy(*resargv + prefix_argc + insert_argc, + suffix_argv, suffix_argc * sizeof(char *)); + + (*resargv)[*resargc] = NULL; +} /* end InsertFileIntoCommandLine */ + + +void +ExpandCommandLine(pargc, pargv) + int *pargc; + char ***pargv; +{ + int i; + for (i = 1; i < *pargc; i++) + { + if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) ) + { + InsertFileIntoCommandLine(pargc, pargv, + i, *pargv, + (*pargv)[i+1], /* filename */ + *pargc - i - 2, *pargv + i + 2); + i--; + } + } +} /* end ExpandCommandLine */ +#endif + +/* Implement a simple-minded font authorization scheme. The authorization + name is "hp-hostname-1", the contents are simply the host name. */ +int +set_font_authorizations(authorizations, authlen, client) +char **authorizations; +int *authlen; +pointer client; +{ +#define AUTHORIZATION_NAME "hp-hostname-1" +#if defined(TCPCONN) || defined(STREAMSCONN) + static char result[1024]; + static char *p = NULL; + + if (p == NULL) + { + char hname[1024], *hnameptr; + struct hostent *host; + int len; + _Xgethostbynameparams hparams; + + gethostname(hname, 1024); + host = _XGethostbyname(hname, hparams); + if (host == NULL) + hnameptr = hname; + else + hnameptr = host->h_name; + + p = result; + *p++ = sizeof(AUTHORIZATION_NAME) >> 8; + *p++ = sizeof(AUTHORIZATION_NAME) & 0xff; + *p++ = (len = strlen(hnameptr) + 1) >> 8; + *p++ = (len & 0xff); + + memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME)); + p += sizeof(AUTHORIZATION_NAME); + memmove(p, hnameptr, len); + p += len; + } + *authlen = p - result; + *authorizations = result; + return 1; +#else /* TCPCONN */ + return 0; +#endif /* TCPCONN */ +} + +/* XALLOC -- X's internal memory allocator. Why does it return unsigned + * long * instead of the more common char *? Well, if you read K&R you'll + * see they say that alloc must return a pointer "suitable for conversion" + * to whatever type you really want. In a full-blown generic allocator + * there's no way to solve the alignment problems without potentially + * wasting lots of space. But we have a more limited problem. We know + * we're only ever returning pointers to structures which will have to + * be long word aligned. So we are making a stronger guarantee. It might + * have made sense to make Xalloc return char * to conform with people's + * expectations of malloc, but this makes lint happier. + */ + +unsigned long * +Xalloc (amount) + unsigned long amount; +{ + char *malloc(); + register pointer ptr; + + if ((long)amount <= 0) + return (unsigned long *)NULL; + /* aligned extra on long word boundary */ + amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); +#ifdef MEMBUG + if (!Must_have_memory && Memory_fail && + ((random() % MEM_FAIL_SCALE) < Memory_fail)) + return (unsigned long *)NULL; +#endif + if (ptr = (pointer)malloc(amount)) + return (unsigned long *)ptr; + if (Must_have_memory) + FatalError("Out of memory"); + return (unsigned long *)NULL; +} + +/***************** + * XNFalloc + * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory + *****************/ + +unsigned long * +XNFalloc (amount) + unsigned long amount; +{ + char *malloc(); + register pointer ptr; + + if ((long)amount <= 0) + { + return (unsigned long *)NULL; + } + /* aligned extra on long word boundary */ + amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); + ptr = (pointer)malloc(amount); + if (!ptr) + { + FatalError("Out of memory"); + } + return ((unsigned long *)ptr); +} + +/***************** + * Xcalloc + *****************/ + +unsigned long * +Xcalloc (amount) + unsigned long amount; +{ + unsigned long *ret; + + ret = Xalloc (amount); + if (ret) + bzero ((char *) ret, (int) amount); + return ret; +} + +/***************** + * Xrealloc + *****************/ + +unsigned long * +Xrealloc (ptr, amount) + register pointer ptr; + unsigned long amount; +{ + char *malloc(); + char *realloc(); + +#ifdef MEMBUG + if (!Must_have_memory && Memory_fail && + ((random() % MEM_FAIL_SCALE) < Memory_fail)) + return (unsigned long *)NULL; +#endif + if ((long)amount <= 0) + { + if (ptr && !amount) + free(ptr); + return (unsigned long *)NULL; + } + amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); + if (ptr) + ptr = (pointer)realloc((char *)ptr, amount); + else + ptr = (pointer)malloc(amount); + if (ptr) + return (unsigned long *)ptr; + if (Must_have_memory) + FatalError("Out of memory"); + return (unsigned long *)NULL; +} + +/***************** + * XNFrealloc + * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory + *****************/ + +unsigned long * +XNFrealloc (ptr, amount) + register pointer ptr; + unsigned long amount; +{ + if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL) + { + FatalError( "Out of memory" ); + } + return ((unsigned long *)ptr); +} + +/***************** + * Xfree + * calls free + *****************/ + +void +Xfree(ptr) + register pointer ptr; +{ + if (ptr) + free((char *)ptr); +} + +OsInitAllocator () +{ +#ifdef MEMBUG + static int been_here; + + /* Check the memory system after each generation */ + if (been_here) + CheckMemory (); + else + been_here = 1; +#endif +} + +void +AuditPrefix(f) + char *f; +{ +#ifdef X_NOT_STDC_ENV + long tm; +#else + time_t tm; +#endif + char *autime, *s; + if (*f != ' ') + { + time(&tm); + autime = ctime(&tm); + if (s = strchr(autime, '\n')) + *s = '\0'; + if (s = strrchr(argvGlobal[0], '/')) + s++; + else + s = argvGlobal[0]; + ErrorF("AUDIT: %s: %d %s: ", autime, getpid(), s); + } +} + +/*VARARGS1*/ +void +AuditF( +#if NeedVarargsPrototypes + char * f, ...) +#else + f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */ + char *f; + char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9; +#endif +{ +#if NeedVarargsPrototypes + va_list args; +#endif + + AuditPrefix(f); + +#if NeedVarargsPrototypes + va_start(args, f); + VErrorF(f, args); + va_end(args); +#else + ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); +#endif +} + +/*VARARGS1*/ +void +FatalError( +#if NeedVarargsPrototypes + char *f, ...) +#else +f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */ + char *f; + char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9; +#endif +{ +#if NeedVarargsPrototypes + va_list args; +#endif + ErrorF("\nFatal server error:\n"); +#if NeedVarargsPrototypes + va_start(args, f); + VErrorF(f, args); + va_end(args); +#else + ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); +#endif + ErrorF("\n"); + AbortServer(); + /*NOTREACHED*/ +} + +#if NeedVarargsPrototypes +void +VErrorF(f, args) + char *f; + va_list args; +{ +#ifdef AIXV3 + if (SyncOn) + sync(); +#else + vfprintf(stderr, f, args); +#endif /* AIXV3 */ +} +#endif + +/*VARARGS1*/ +void +ErrorF( +#if NeedVarargsPrototypes + char * f, ...) +#else + f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */ + char *f; + char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9; +#endif +{ +#if NeedVarargsPrototypes + va_list args; + va_start(args, f); + VErrorF(f, args); + va_end(args); +#else +#ifdef AIXV3 + if (SyncOn) + sync(); +#else /* not AIXV3 */ + fprintf( stderr, f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); +#endif /* AIXV3 */ +#endif +} diff --git a/os/xdmauth.c b/os/xdmauth.c new file mode 100644 index 000000000..d6abd6a14 --- /dev/null +++ b/os/xdmauth.c @@ -0,0 +1,518 @@ +/* $Xorg: xdmauth.c,v 1.4 2001/02/09 02:05:24 xorgcvs Exp $ */ +/* + +Copyright 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * XDM-AUTHENTICATION-1 (XDMCP authentication) and + * XDM-AUTHORIZATION-1 (client authorization) protocols + * + * Author: Keith Packard, MIT X Consortium + */ + +#include +#include "X.h" +#include "Xtrans.h" +#include "os.h" +#include "osdep.h" +#include "dixstruct.h" + +#ifdef HASXDMAUTH + +static Bool authFromXDMCP; + +#ifdef XDMCP +#include "Xmd.h" +#undef REQUEST +#include "Xdmcp.h" + +/* XDM-AUTHENTICATION-1 */ + +static XdmAuthKeyRec privateKey; +static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1"; +#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1) +static XdmAuthKeyRec rho; + +static Bool XdmAuthenticationValidator (privateData, incomingData, packet_type) + ARRAY8Ptr privateData, incomingData; + xdmOpCode packet_type; +{ + XdmAuthKeyPtr incoming; + + XdmcpUnwrap (incomingData->data, &privateKey, + incomingData->data,incomingData->length); + switch (packet_type) + { + case ACCEPT: + if (incomingData->length != 8) + return FALSE; + incoming = (XdmAuthKeyPtr) incomingData->data; + XdmcpDecrementKey (incoming); + return XdmcpCompareKeys (incoming, &rho); + } + return FALSE; +} + +static Bool +XdmAuthenticationGenerator (privateData, outgoingData, packet_type) + ARRAY8Ptr privateData, outgoingData; + xdmOpCode packet_type; +{ + outgoingData->length = 0; + outgoingData->data = 0; + switch (packet_type) + { + case REQUEST: + if (XdmcpAllocARRAY8 (outgoingData, 8)) + XdmcpWrap (&rho, &privateKey, outgoingData->data, 8); + } + return TRUE; +} + +static Bool +XdmAuthenticationAddAuth (name_len, name, data_len, data) + int name_len, data_len; + char *name, *data; +{ + Bool ret; + XdmcpUnwrap (data, &privateKey, data, data_len); + authFromXDMCP = TRUE; + ret = AddAuthorization (name_len, name, data_len, data); + authFromXDMCP = FALSE; + return ret; +} + + +#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \ + 'a' <= c && c <= 'f' ? c - 'a' + 10 : \ + 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1) + +static int +HexToBinary (in, out, len) + char *out, *in; + int len; +{ + int top, bottom; + + while (len > 0) + { + top = atox(in[0]); + if (top == -1) + return 0; + bottom = atox(in[1]); + if (bottom == -1) + return 0; + *out++ = (top << 4) | bottom; + in += 2; + len -= 2; + } + if (len) + return 0; + *out++ = '\0'; + return 1; +} + +void +XdmAuthenticationInit (cookie, cookie_len) + char *cookie; + int cookie_len; +{ + bzero (privateKey.data, 8); + if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2)) + { + if (cookie_len > 2 + 2 * 8) + cookie_len = 2 + 2 * 8; + HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2); + } + else + { + if (cookie_len > 7) + cookie_len = 7; + memmove (privateKey.data + 1, cookie, cookie_len); + } + XdmcpGenerateKey (&rho); + XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen, + &rho, + sizeof (rho), + XdmAuthenticationValidator, + XdmAuthenticationGenerator, + XdmAuthenticationAddAuth); +} + +#endif /* XDMCP */ + +/* XDM-AUTHORIZATION-1 */ +typedef struct _XdmAuthorization { + struct _XdmAuthorization *next; + XdmAuthKeyRec rho; + XdmAuthKeyRec key; + XID id; +} XdmAuthorizationRec, *XdmAuthorizationPtr; + +static XdmAuthorizationPtr xdmAuth; + +typedef struct _XdmClientAuth { + struct _XdmClientAuth *next; + XdmAuthKeyRec rho; + char client[6]; + long time; +} XdmClientAuthRec, *XdmClientAuthPtr; + +static XdmClientAuthPtr xdmClients; +static long clockOffset; +static Bool gotClock; + +#define TwentyMinutes (20 * 60) +#define TwentyFiveMinutes (25 * 60) + +static Bool +XdmClientAuthCompare (a, b) + XdmClientAuthPtr a, b; +{ + int i; + + if (!XdmcpCompareKeys (&a->rho, &b->rho)) + return FALSE; + for (i = 0; i < 6; i++) + if (a->client[i] != b->client[i]) + return FALSE; + return a->time == b->time; +} + +static void +XdmClientAuthDecode (plain, auth) + unsigned char *plain; + XdmClientAuthPtr auth; +{ + int i, j; + + j = 0; + for (i = 0; i < 8; i++) + { + auth->rho.data[i] = plain[j]; + ++j; + } + for (i = 0; i < 6; i++) + { + auth->client[i] = plain[j]; + ++j; + } + auth->time = 0; + for (i = 0; i < 4; i++) + { + auth->time |= plain[j] << ((3 - i) << 3); + j++; + } +} + +static void +XdmClientAuthTimeout (now) + long now; +{ + XdmClientAuthPtr client, next, prev; + + prev = 0; + for (client = xdmClients; client; client=next) + { + next = client->next; + if (abs (now - client->time) > TwentyFiveMinutes) + { + if (prev) + prev->next = next; + else + xdmClients = next; + xfree (client); + } + else + prev = client; + } +} + +static XdmClientAuthPtr +XdmAuthorizationValidate (plain, length, rho, xclient, reason) + unsigned char *plain; + int length; + XdmAuthKeyPtr rho; + ClientPtr xclient; + char **reason; +{ + XdmClientAuthPtr client, existing; + long now; + int i; + + if (length != (192 / 8)) { + if (reason) + *reason = "Bad XDM authorization key length"; + return NULL; + } + client = (XdmClientAuthPtr) xalloc (sizeof (XdmClientAuthRec)); + if (!client) + return NULL; + XdmClientAuthDecode (plain, client); + if (!XdmcpCompareKeys (&client->rho, rho)) + { + xfree (client); + if (reason) + *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)"; + return NULL; + } + for (i = 18; i < 24; i++) + if (plain[i] != 0) { + xfree (client); + if (reason) + *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)"; + return NULL; + } + if (xclient) { + int family, addr_len; + Xtransaddr *addr; + + if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn, + &family, &addr_len, &addr) == 0 + && _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) { +#if defined(TCPCONN) || defined(STREAMSCONN) + if (family == FamilyInternet && + memcmp((char *)addr, client->client, 4) != 0) { + xfree (client); + xfree (addr); + if (reason) + *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)"; + return NULL; + + } +#endif + xfree (addr); + } + } + now = time(0); + if (!gotClock) + { + clockOffset = client->time - now; + gotClock = TRUE; + } + now += clockOffset; + XdmClientAuthTimeout (now); + if (abs (client->time - now) > TwentyMinutes) + { + xfree (client); + if (reason) + *reason = "Excessive XDM-AUTHORIZATION-1 time offset"; + return NULL; + } + for (existing = xdmClients; existing; existing=existing->next) + { + if (XdmClientAuthCompare (existing, client)) + { + xfree (client); + if (reason) + *reason = "XDM authorization key matches an existing client!"; + return NULL; + } + } + return client; +} + +int +XdmAddCookie (data_length, data, id) +unsigned short data_length; +char *data; +XID id; +{ + XdmAuthorizationPtr new; + unsigned char *rho_bits, *key_bits; + + switch (data_length) + { + case 16: /* auth from files is 16 bytes long */ + if (authFromXDMCP) + { + /* R5 xdm sent bogus authorization data in the accept packet, + * but we can recover */ + rho_bits = rho.data; + key_bits = (unsigned char *) data; + key_bits[0] = '\0'; + } + else + { + rho_bits = (unsigned char *) data; + key_bits = (unsigned char *) (data + 8); + } + break; + case 8: /* auth from XDMCP is 8 bytes long */ + rho_bits = rho.data; + key_bits = (unsigned char *) data; + break; + default: + return 0; + } + /* the first octet of the key must be zero */ + if (key_bits[0] != '\0') + return 0; + new = (XdmAuthorizationPtr) xalloc (sizeof (XdmAuthorizationRec)); + if (!new) + return 0; + new->next = xdmAuth; + xdmAuth = new; + memmove (new->key.data, key_bits, (int) 8); + memmove (new->rho.data, rho_bits, (int) 8); + new->id = id; + return 1; +} + +XID +XdmCheckCookie (cookie_length, cookie, xclient, reason) + unsigned short cookie_length; + char *cookie; + ClientPtr xclient; + char **reason; +{ + XdmAuthorizationPtr auth; + XdmClientAuthPtr client; + unsigned char *plain; + + /* Auth packets must be a multiple of 8 bytes long */ + if (cookie_length & 7) + return (XID) -1; + plain = (unsigned char *) xalloc (cookie_length); + if (!plain) + return (XID) -1; + for (auth = xdmAuth; auth; auth=auth->next) { + XdmcpUnwrap (cookie, &auth->key, plain, cookie_length); + if (client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) + { + client->next = xdmClients; + xdmClients = client; + xfree (plain); + return auth->id; + } + } + xfree (plain); + return (XID) -1; +} + +int +XdmResetCookie () +{ + XdmAuthorizationPtr auth, next_auth; + XdmClientAuthPtr client, next_client; + + for (auth = xdmAuth; auth; auth=next_auth) + { + next_auth = auth->next; + xfree (auth); + } + xdmAuth = 0; + for (client = xdmClients; client; client=next_client) + { + next_client = client->next; + xfree (client); + } + xdmClients = (XdmClientAuthPtr) 0; + return 1; +} + +XID +XdmToID (cookie_length, cookie) +unsigned short cookie_length; +char *cookie; +{ + XdmAuthorizationPtr auth; + XdmClientAuthPtr client; + unsigned char *plain; + + plain = (unsigned char *) xalloc (cookie_length); + if (!plain) + return (XID) -1; + for (auth = xdmAuth; auth; auth=auth->next) { + XdmcpUnwrap (cookie, &auth->key, plain, cookie_length); + if (client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) + { + xfree (client); + xfree (cookie); + return auth->id; + } + } + xfree (cookie); + return (XID) -1; +} + +int +XdmFromID (id, data_lenp, datap) +XID id; +unsigned short *data_lenp; +char **datap; +{ + XdmAuthorizationPtr auth; + + for (auth = xdmAuth; auth; auth=auth->next) { + if (id == auth->id) { + *data_lenp = 16; + *datap = (char *) &auth->rho; + return 1; + } + } + return 0; +} + +int +XdmRemoveCookie (data_length, data) +unsigned short data_length; +char *data; +{ + XdmAuthorizationPtr auth, prev; + XdmAuthKeyPtr key_bits, rho_bits; + + prev = 0; + switch (data_length) + { + case 16: + rho_bits = (XdmAuthKeyPtr) data; + key_bits = (XdmAuthKeyPtr) (data + 8); + break; + case 8: + rho_bits = ρ + key_bits = (XdmAuthKeyPtr) data; + break; + default: + return 0; + } + for (auth = xdmAuth; auth; auth=auth->next) { + if (XdmcpCompareKeys (rho_bits, &auth->rho) && + XdmcpCompareKeys (key_bits, &auth->key)) + { + if (prev) + prev->next = auth->next; + else + xdmAuth = auth->next; + xfree (auth); + return 1; + } + } + return 0; +} + +#endif diff --git a/os/xdmcp.c b/os/xdmcp.c new file mode 100644 index 000000000..6d683b66d --- /dev/null +++ b/os/xdmcp.c @@ -0,0 +1,1341 @@ +/* $Xorg: xdmcp.c,v 1.4 2001/01/31 13:37:19 pookie Exp $ */ +/* + * Copyright 1989 Network Computing Devices, Inc., Mountain View, California. + * + * 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 name of N.C.D. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. N.C.D. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + */ + +#ifdef WIN32 +/* avoid conflicting definitions */ +#define BOOL wBOOL +#define ATOM wATOM +#define FreeResource wFreeResource +#include +#undef BOOL +#undef ATOM +#undef FreeResource +#undef CreateWindowA +#undef RT_FONT +#undef RT_CURSOR +#endif +#include "Xos.h" +#ifndef WIN32 +#include +#include +#include +#include +#endif +#include +#include "X.h" +#include "Xmd.h" +#include "misc.h" +#include "Xpoll.h" +#include "osdep.h" +#include "input.h" +#include "dixstruct.h" +#include "opaque.h" + +#ifdef STREAMSCONN +#include +#include +#include +#endif + +#ifdef XDMCP +#undef REQUEST +#include "Xdmcp.h" + +#define X_INCLUDE_NETDB_H +#include + +extern char *display; +extern fd_set EnabledDevices; +extern fd_set AllClients; +extern char *defaultDisplayClass; + +static int xdmcpSocket, sessionSocket; +static xdmcp_states state; +static struct sockaddr_in req_sockaddr; +static int req_socklen; +static CARD32 SessionID; +static CARD32 timeOutTime; +static int timeOutRtx; +static CARD32 defaultKeepaliveDormancy = XDM_DEF_DORMANCY; +static CARD32 keepaliveDormancy = XDM_DEF_DORMANCY; +static CARD16 DisplayNumber; +static xdmcp_states XDM_INIT_STATE = XDM_OFF; +#ifdef HASXDMAUTH +static char *xdmAuthCookie; +#endif + +static XdmcpBuffer buffer; + +static struct sockaddr_in ManagerAddress; + +static void get_xdmcp_sock( +#if NeedFunctionPrototypes + void +#endif +); + +static void send_query_msg( +#if NeedFunctionPrototypes + void +#endif +); + +static void recv_willing_msg( +#if NeedFunctionPrototypes + struct sockaddr_in */*from*/, + int /*fromlen*/, + unsigned /*length*/ +#endif +); + +static void send_request_msg( +#if NeedFunctionPrototypes + void +#endif +); + +static void recv_accept_msg( +#if NeedFunctionPrototypes + unsigned /*length*/ +#endif +); + +static void recv_decline_msg( +#if NeedFunctionPrototypes + unsigned /*length*/ +#endif +); + +static void send_manage_msg( +#if NeedFunctionPrototypes + void +#endif +); + +static void recv_refuse_msg( +#if NeedFunctionPrototypes + unsigned /*length*/ +#endif +); + +static void recv_failed_msg( +#if NeedFunctionPrototypes + unsigned /*length*/ +#endif +); + +static void send_keepalive_msg( +#if NeedFunctionPrototypes + void +#endif +); + +static void recv_alive_msg( +#if NeedFunctionPrototypes + unsigned /*length*/ +#endif +); + +static XdmcpFatal( +#if NeedFunctionPrototypes + char */*type*/, + ARRAY8Ptr /*status*/ +#endif +); + +static XdmcpWarning( +#if NeedFunctionPrototypes + char */*str*/ +#endif +); + +static get_manager_by_name( +#if NeedFunctionPrototypes + int /*argc*/, + char **/*argv*/, + int /*i*/ +#endif +); + +static void receive_packet( +#if NeedFunctionPrototypes + void +#endif +); + +static send_packet( +#if NeedFunctionPrototypes + void +#endif +); + +extern int XdmcpDeadSession( +#if NeedFunctionPrototypes + char */*reason*/ +#endif +); + +static void timeout( +#if NeedFunctionPrototypes + void +#endif +); + +static restart( +#if NeedFunctionPrototypes + void +#endif +); + +static void XdmcpBlockHandler( +#if NeedFunctionPrototypes + pointer /*data*/, + struct timeval **/*wt*/, + pointer /*LastSelectMask*/ +#endif +); + +static void XdmcpWakeupHandler( +#if NeedFunctionPrototypes + pointer /*data*/, + int /*i*/, + pointer /*LastSelectMask*/ +#endif +); + +void XdmcpRegisterManufacturerDisplayID( +#if NeedFunctionPrototypes + char * /*name*/, + int /*length*/ +#endif +); + +static short xdm_udp_port = XDM_UDP_PORT; +static Bool OneSession = FALSE; + +XdmcpUseMsg () +{ + ErrorF("-query host-name contact named host for XDMCP\n"); + ErrorF("-broadcast broadcast for XDMCP\n"); + ErrorF("-indirect host-name contact named host for indirect XDMCP\n"); + ErrorF("-port port-num UDP port number to send messages to\n"); + ErrorF("-once Terminate server after one session\n"); + ErrorF("-class display-class specify display class to send in manage\n"); +#ifdef HASXDMAUTH + ErrorF("-cookie xdm-auth-bits specify the magic cookie for XDMCP\n"); +#endif + ErrorF("-displayID display-id manufacturer display ID for request\n"); +} + +int +XdmcpOptions(argc, argv, i) + int argc, i; + char **argv; +{ + if (strcmp(argv[i], "-query") == 0) { + get_manager_by_name(argc, argv, ++i); + XDM_INIT_STATE = XDM_QUERY; + AccessUsingXdmcp (); + return (i + 1); + } + if (strcmp(argv[i], "-broadcast") == 0) { + XDM_INIT_STATE = XDM_BROADCAST; + AccessUsingXdmcp (); + return (i + 1); + } + if (strcmp(argv[i], "-indirect") == 0) { + get_manager_by_name(argc, argv, ++i); + XDM_INIT_STATE = XDM_INDIRECT; + AccessUsingXdmcp (); + return (i + 1); + } + if (strcmp(argv[i], "-port") == 0) { + ++i; + xdm_udp_port = atoi(argv[i]); + return (i + 1); + } + if (strcmp(argv[i], "-once") == 0) { + OneSession = TRUE; + return (i + 1); + } + if (strcmp(argv[i], "-class") == 0) { + ++i; + defaultDisplayClass = argv[i]; + return (i + 1); + } +#ifdef HASXDMAUTH + if (strcmp(argv[i], "-cookie") == 0) { + ++i; + xdmAuthCookie = argv[i]; + return (i + 1); + } +#endif + if (strcmp(argv[i], "-displayID") == 0) { + ++i; + XdmcpRegisterManufacturerDisplayID (argv[i], strlen (argv[i])); + return (i + 1); + } + return (i); +} + +/* + * This section is a collection of routines for + * registering server-specific data with the XDMCP + * state machine. + */ + + +/* + * Save all broadcast addresses away so BroadcastQuery + * packets get sent everywhere + */ + +#define MAX_BROADCAST 10 + +static struct sockaddr_in BroadcastAddresses[MAX_BROADCAST]; +static int NumBroadcastAddresses; + +void +XdmcpRegisterBroadcastAddress (addr) + struct sockaddr_in *addr; +{ + struct sockaddr_in *bcast; + if (NumBroadcastAddresses >= MAX_BROADCAST) + return; + bcast = &BroadcastAddresses[NumBroadcastAddresses++]; + bzero (bcast, sizeof (struct sockaddr_in)); +#ifdef BSD44SOCKETS + bcast->sin_len = addr->sin_len; +#endif + bcast->sin_family = addr->sin_family; + bcast->sin_port = htons (xdm_udp_port); + bcast->sin_addr = addr->sin_addr; +} + +/* + * Each authentication type is registered here; Validator + * will be called to check all access attempts using + * the specified authentication type + */ + +static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas; +typedef struct _AuthenticationFuncs { + Bool (*Validator)(); + Bool (*Generator)(); + Bool (*AddAuth)(); +} AuthenticationFuncsRec, *AuthenticationFuncsPtr; + +static AuthenticationFuncsPtr AuthenticationFuncsList; + +void +XdmcpRegisterAuthentication (name, namelen, data, datalen, Validator, Generator, AddAuth) + char *name; + int namelen; + char *data; + int datalen; + Bool (*Validator)(); + Bool (*Generator)(); + Bool (*AddAuth)(); +{ + int i; + ARRAY8 AuthenticationName, AuthenticationData; + static AuthenticationFuncsPtr newFuncs; + + if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen)) + return; + if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen)) + { + XdmcpDisposeARRAY8 (&AuthenticationName); + return; + } + for (i = 0; i < namelen; i++) + AuthenticationName.data[i] = name[i]; + for (i = 0; i < datalen; i++) + AuthenticationData.data[i] = data[i]; + if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames, + AuthenticationNames.length + 1) && + XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas, + AuthenticationDatas.length + 1) && + (newFuncs = (AuthenticationFuncsPtr) xalloc ( + (AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec))))) + { + XdmcpDisposeARRAY8 (&AuthenticationName); + XdmcpDisposeARRAY8 (&AuthenticationData); + return; + } + for (i = 0; i < AuthenticationNames.length - 1; i++) + newFuncs[i] = AuthenticationFuncsList[i]; + newFuncs[AuthenticationNames.length-1].Validator = Validator; + newFuncs[AuthenticationNames.length-1].Generator = Generator; + newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth; + xfree (AuthenticationFuncsList); + AuthenticationFuncsList = newFuncs; + AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName; + AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData; +} + +/* + * Select the authentication type to be used; this is + * set by the manager of the host to be connected to. + */ + +ARRAY8 noAuthenticationName = {(CARD16) 0, (CARD8Ptr) 0}; +ARRAY8 noAuthenticationData = {(CARD16) 0, (CARD8Ptr) 0}; +ARRAY8Ptr AuthenticationName = &noAuthenticationName; +ARRAY8Ptr AuthenticationData = &noAuthenticationData; +AuthenticationFuncsPtr AuthenticationFuncs; + +void +XdmcpSetAuthentication (name) + ARRAY8Ptr name; +{ + int i; + + for (i = 0; i < AuthenticationNames.length; i++) + if (XdmcpARRAY8Equal (&AuthenticationNames.data[i], name)) + { + AuthenticationName = &AuthenticationNames.data[i]; + AuthenticationData = &AuthenticationDatas.data[i]; + AuthenticationFuncs = &AuthenticationFuncsList[i]; + break; + } +} + +/* + * Register the host address for the display + */ + +static ARRAY16 ConnectionTypes; +static ARRAYofARRAY8 ConnectionAddresses; +static long xdmcpGeneration; + +void +XdmcpRegisterConnection (type, address, addrlen) + int type; + char *address; + int addrlen; +{ + int i; + CARD8 *newAddress; + + if (xdmcpGeneration != serverGeneration) + { + XdmcpDisposeARRAY16 (&ConnectionTypes); + XdmcpDisposeARRAYofARRAY8 (&ConnectionAddresses); + xdmcpGeneration = serverGeneration; + } + newAddress = (CARD8 *) xalloc (addrlen * sizeof (CARD8)); + if (!newAddress) + return; + if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1)) + { + xfree (newAddress); + return; + } + if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses, + ConnectionAddresses.length + 1)) + { + xfree (newAddress); + return; + } + ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type; + for (i = 0; i < addrlen; i++) + newAddress[i] = address[i]; + ConnectionAddresses.data[ConnectionAddresses.length-1].data = newAddress; + ConnectionAddresses.data[ConnectionAddresses.length-1].length = addrlen; +} + +/* + * Register an Authorization Name. XDMCP advertises this list + * to the manager. + */ + +static ARRAYofARRAY8 AuthorizationNames; + +void +XdmcpRegisterAuthorizations () +{ + XdmcpDisposeARRAYofARRAY8 (&AuthorizationNames); + RegisterAuthorizations (); +} + +void +XdmcpRegisterAuthorization (name, namelen) + char *name; + int namelen; +{ + ARRAY8 authName; + int i; + + authName.data = (CARD8 *) xalloc (namelen * sizeof (CARD8)); + if (!authName.data) + return; + if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1)) + { + xfree (authName.data); + return; + } + for (i = 0; i < namelen; i++) + authName.data[i] = (CARD8) name[i]; + authName.length = namelen; + AuthorizationNames.data[AuthorizationNames.length-1] = authName; +} + +/* + * Register the DisplayClass string + */ + +ARRAY8 DisplayClass; + +void +XdmcpRegisterDisplayClass (name, length) + char *name; + int length; +{ + int i; + + XdmcpDisposeARRAY8 (&DisplayClass); + if (!XdmcpAllocARRAY8 (&DisplayClass, length)) + return; + for (i = 0; i < length; i++) + DisplayClass.data[i] = (CARD8) name[i]; +} + +/* + * Register the Manufacturer display ID + */ + +ARRAY8 ManufacturerDisplayID; + +void +XdmcpRegisterManufacturerDisplayID (name, length) + char *name; + int length; +{ + int i; + + XdmcpDisposeARRAY8 (&ManufacturerDisplayID); + if (!XdmcpAllocARRAY8 (&ManufacturerDisplayID, length)) + return; + for (i = 0; i < length; i++) + ManufacturerDisplayID.data[i] = (CARD8) name[i]; +} + +/* + * initialize XDMCP; create the socket, compute the display + * number, set up the state machine + */ + +void +XdmcpInit() +{ + state = XDM_INIT_STATE; +#ifdef HASXDMAUTH + if (xdmAuthCookie) + XdmAuthenticationInit (xdmAuthCookie, strlen (xdmAuthCookie)); +#endif + if (state != XDM_OFF) + { + XdmcpRegisterAuthorizations(); + XdmcpRegisterDisplayClass (defaultDisplayClass, strlen (defaultDisplayClass)); + AccessUsingXdmcp(); + RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler, + (pointer) 0); + timeOutRtx = 0; + DisplayNumber = (CARD16) atoi(display); + get_xdmcp_sock(); + send_packet(); + } +} + +void +XdmcpReset () +{ + state = XDM_INIT_STATE; + if (state != XDM_OFF) + { + RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler, + (pointer) 0); + timeOutRtx = 0; + send_packet(); + } +} + +/* + * Called whenever a new connection is created; notices the + * first connection and saves it to terminate the session + * when it is closed + */ + +void +XdmcpOpenDisplay(sock) + int sock; +{ + if (state != XDM_AWAIT_MANAGE_RESPONSE) + return; + state = XDM_RUN_SESSION; + sessionSocket = sock; +} + +void +XdmcpCloseDisplay(sock) + int sock; +{ + if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE) + || sessionSocket != sock) + return; + state = XDM_INIT_STATE; + if (OneSession) + dispatchException |= DE_TERMINATE; + else + dispatchException |= DE_RESET; + isItTimeToYield = TRUE; +} + +/* + * called before going to sleep, this routine + * may modify the timeout value about to be sent + * to select; in this way XDMCP can do appropriate things + * dynamically while starting up + */ + +/*ARGSUSED*/ +static void +XdmcpBlockHandler(data, wt, pReadmask) + pointer data; /* unused */ + struct timeval **wt; + pointer pReadmask; +{ + fd_set *LastSelectMask = (fd_set*)pReadmask; + CARD32 millisToGo, wtMillis; + static struct timeval waittime; + + if (state == XDM_OFF) + return; + FD_SET(xdmcpSocket, LastSelectMask); + if (timeOutTime == 0) + return; + millisToGo = GetTimeInMillis(); + if (millisToGo < timeOutTime) + millisToGo = timeOutTime - millisToGo; + else + millisToGo = 0; + if (*wt == NULL) + { + waittime.tv_sec = (millisToGo) / 1000; + waittime.tv_usec = 1000 * (millisToGo % 1000); + *wt = &waittime; + } + else + { + wtMillis = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000; + if (millisToGo < wtMillis) + { + (*wt)->tv_sec = (millisToGo) / 1000; + (*wt)->tv_usec = 1000 * (millisToGo % 1000); + } + } +} + +/* + * called after select returns; this routine will + * recognise when XDMCP packets await and + * process them appropriately + */ + +/*ARGSUSED*/ +static void +XdmcpWakeupHandler(data, i, pReadmask) + pointer data; /* unused */ + int i; + pointer pReadmask; +{ + fd_set* LastSelectMask = (fd_set*)pReadmask; + fd_set devicesReadable; + + if (state == XDM_OFF) + return; + if (i > 0) + { + if (FD_ISSET(xdmcpSocket, LastSelectMask)) + { + receive_packet(); + FD_CLR(xdmcpSocket, LastSelectMask); + } + XFD_ANDSET(&devicesReadable, LastSelectMask, &EnabledDevices); + if (XFD_ANYSET(&devicesReadable)) + { + if (state == XDM_AWAIT_USER_INPUT) + restart(); + else if (state == XDM_RUN_SESSION) + keepaliveDormancy = defaultKeepaliveDormancy; + } + if (XFD_ANYSET(&AllClients) && state == XDM_RUN_SESSION) + timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000; + } + else if (timeOutTime && GetTimeInMillis() >= timeOutTime) + { + if (state == XDM_RUN_SESSION) + { + state = XDM_KEEPALIVE; + send_packet(); + } + else + timeout(); + } +} + +/* + * This routine should be called from the routine that drives the + * user's host menu when the user selects a host + */ + +XdmcpSelectHost(host_sockaddr, host_len, AuthenticationName) + struct sockaddr_in *host_sockaddr; + int host_len; + ARRAY8Ptr AuthenticationName; +{ + state = XDM_START_CONNECTION; + memmove(&req_sockaddr, host_sockaddr, host_len); + req_socklen = host_len; + XdmcpSetAuthentication (AuthenticationName); + send_packet(); +} + +/* + * !!! this routine should be replaced by a routine that adds + * the host to the user's host menu. the current version just + * selects the first host to respond with willing message. + */ + +/*ARGSUSED*/ +XdmcpAddHost(from, fromlen, AuthenticationName, hostname, status) + struct sockaddr_in *from; + ARRAY8Ptr AuthenticationName, hostname, status; +{ + XdmcpSelectHost(from, fromlen, AuthenticationName); +} + +/* + * A message is queued on the socket; read it and + * do the appropriate thing + */ + +ARRAY8 UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" }; + +static void +receive_packet() +{ + struct sockaddr_in from; + int fromlen = sizeof(struct sockaddr_in); + XdmcpHeader header; + + /* read message off socket */ + if (!XdmcpFill (xdmcpSocket, &buffer, (struct sockaddr *) &from, &fromlen)) + return; + + /* reset retransmission backoff */ + timeOutRtx = 0; + + if (!XdmcpReadHeader (&buffer, &header)) + return; + + if (header.version != XDM_PROTOCOL_VERSION) + return; + + switch (header.opcode) { + case WILLING: + recv_willing_msg(&from, fromlen, header.length); + break; + case UNWILLING: + XdmcpFatal("Manager unwilling", &UnwillingMessage); + break; + case ACCEPT: + recv_accept_msg(header.length); + break; + case DECLINE: + recv_decline_msg(header.length); + break; + case REFUSE: + recv_refuse_msg(header.length); + break; + case FAILED: + recv_failed_msg(header.length); + break; + case ALIVE: + recv_alive_msg(header.length); + break; + } +} + +/* + * send the appropriate message given the current state + */ + +static +send_packet() +{ + int rtx; + switch (state) { + case XDM_QUERY: + case XDM_BROADCAST: + case XDM_INDIRECT: + send_query_msg(); + break; + case XDM_START_CONNECTION: + send_request_msg(); + break; + case XDM_MANAGE: + send_manage_msg(); + break; + case XDM_KEEPALIVE: + send_keepalive_msg(); + break; + } + rtx = (XDM_MIN_RTX << timeOutRtx); + if (rtx > XDM_MAX_RTX) + rtx = XDM_MAX_RTX; + timeOutTime = GetTimeInMillis() + rtx * 1000; +} + +/* + * The session is declared dead for some reason; too many + * timeouts, or Keepalive failure. + */ + +XdmcpDeadSession (reason) + char *reason; +{ + ErrorF ("XDM: %s, declaring session dead\n", reason); + state = XDM_INIT_STATE; + isItTimeToYield = TRUE; + dispatchException |= DE_RESET; + timeOutTime = 0; + timeOutRtx = 0; + send_packet(); +} + +/* + * Timeout waiting for an XDMCP response. + */ + +static void +timeout() +{ + timeOutRtx++; + if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT ) + { + XdmcpDeadSession ("too many keepalive retransmissions"); + return; + } + else if (timeOutRtx >= XDM_RTX_LIMIT) + { + ErrorF("XDM: too many retransmissions\n"); + state = XDM_AWAIT_USER_INPUT; + timeOutTime = 0; + timeOutRtx = 0; + return; + } + + switch (state) { + case XDM_COLLECT_QUERY: + state = XDM_QUERY; + break; + case XDM_COLLECT_BROADCAST_QUERY: + state = XDM_BROADCAST; + break; + case XDM_COLLECT_INDIRECT_QUERY: + state = XDM_INDIRECT; + break; + case XDM_AWAIT_REQUEST_RESPONSE: + state = XDM_START_CONNECTION; + break; + case XDM_AWAIT_MANAGE_RESPONSE: + state = XDM_MANAGE; + break; + case XDM_AWAIT_ALIVE_RESPONSE: + state = XDM_KEEPALIVE; + break; + } + send_packet(); +} + +static +restart() +{ + state = XDM_INIT_STATE; + timeOutRtx = 0; + send_packet(); +} + +XdmcpCheckAuthentication (Name, Data, packet_type) + ARRAY8Ptr Name, Data; + int packet_type; +{ + return (XdmcpARRAY8Equal (Name, AuthenticationName) && + (AuthenticationName->length == 0 || + (*AuthenticationFuncs->Validator) (AuthenticationData, Data, packet_type))); +} + +XdmcpAddAuthorization (name, data) + ARRAY8Ptr name, data; +{ + Bool (*AddAuth)(), AddAuthorization(); + + if (AuthenticationFuncs && AuthenticationFuncs->AddAuth) + AddAuth = AuthenticationFuncs->AddAuth; + else + AddAuth = AddAuthorization; + return (*AddAuth) ((unsigned short)name->length, + (char *)name->data, + (unsigned short)data->length, + (char *)data->data); +} + +/* + * from here to the end of this file are routines private + * to the state machine. + */ + +static void +get_xdmcp_sock() +{ + int soopts = 1; + +#ifdef STREAMSCONN + struct netconfig *nconf; + + if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) { + XdmcpWarning("t_open() of /dev/udp failed"); + return; + } + + if( t_bind(xdmcpSocket,NULL,NULL) < 0 ) { + XdmcpWarning("UDP socket creation failed"); + t_error("t_bind(xdmcpSocket) failed" ); + t_close(xdmcpSocket); + return; + } + + /* + * This part of the code looks contrived. It will actually fit in nicely + * when the CLTS part of Xtrans is implemented. + */ + + if( (nconf=getnetconfigent("udp")) == NULL ) { + XdmcpWarning("UDP socket creation failed: getnetconfigent()"); + t_unbind(xdmcpSocket); + t_close(xdmcpSocket); + return; + } + + if( netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL) ) { + XdmcpWarning("UDP set broadcast option failed: netdir_options()"); + freenetconfigent(nconf); + t_unbind(xdmcpSocket); + t_close(xdmcpSocket); + return; + } + + freenetconfigent(nconf); +#else + if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + XdmcpWarning("UDP socket creation failed"); +#ifdef SO_BROADCAST + else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *)&soopts, + sizeof(soopts)) < 0) + XdmcpWarning("UDP set broadcast socket-option failed"); +#endif /* SO_BROADCAST */ +#endif /* STREAMSCONN */ +} + +static void +send_query_msg() +{ + XdmcpHeader header; + Bool broadcast = FALSE; + int i; + + header.version = XDM_PROTOCOL_VERSION; + switch(state){ + case XDM_QUERY: + header.opcode = (CARD16) QUERY; + state = XDM_COLLECT_QUERY; + break; + case XDM_BROADCAST: + header.opcode = (CARD16) BROADCAST_QUERY; + state = XDM_COLLECT_BROADCAST_QUERY; + broadcast = TRUE; + break; + case XDM_INDIRECT: + header.opcode = (CARD16) INDIRECT_QUERY; + state = XDM_COLLECT_INDIRECT_QUERY; + break; + } + header.length = 1; + for (i = 0; i < AuthenticationNames.length; i++) + header.length += 2 + AuthenticationNames.data[i].length; + + XdmcpWriteHeader (&buffer, &header); + XdmcpWriteARRAYofARRAY8 (&buffer, &AuthenticationNames); + if (broadcast) + { + int i; + + for (i = 0; i < NumBroadcastAddresses; i++) + XdmcpFlush (xdmcpSocket, &buffer, &BroadcastAddresses[i], + sizeof (struct sockaddr_in)); + } + else + { + XdmcpFlush (xdmcpSocket, &buffer, &ManagerAddress, + sizeof (ManagerAddress)); + } +} + +static void +recv_willing_msg(from, fromlen, length) + struct sockaddr_in *from; + int fromlen; + unsigned length; +{ + ARRAY8 authenticationName; + ARRAY8 hostname; + ARRAY8 status; + + authenticationName.data = 0; + hostname.data = 0; + status.data = 0; + if (XdmcpReadARRAY8 (&buffer, &authenticationName) && + XdmcpReadARRAY8 (&buffer, &hostname) && + XdmcpReadARRAY8 (&buffer, &status)) + { + if (length == 6 + authenticationName.length + + hostname.length + status.length) + { + switch (state) + { + case XDM_COLLECT_QUERY: + XdmcpSelectHost(from, fromlen, &authenticationName); + break; + case XDM_COLLECT_BROADCAST_QUERY: + case XDM_COLLECT_INDIRECT_QUERY: + XdmcpAddHost(from, fromlen, &authenticationName, &hostname, &status); + break; + } + } + } + XdmcpDisposeARRAY8 (&authenticationName); + XdmcpDisposeARRAY8 (&hostname); + XdmcpDisposeARRAY8 (&status); +} + +static void +send_request_msg() +{ + XdmcpHeader header; + int length; + int i; + ARRAY8 authenticationData; + + header.version = XDM_PROTOCOL_VERSION; + header.opcode = (CARD16) REQUEST; + + length = 2; /* display number */ + length += 1 + 2 * ConnectionTypes.length; /* connection types */ + length += 1; /* connection addresses */ + for (i = 0; i < ConnectionAddresses.length; i++) + length += 2 + ConnectionAddresses.data[i].length; + authenticationData.length = 0; + authenticationData.data = 0; + if (AuthenticationFuncs) + { + (*AuthenticationFuncs->Generator) (AuthenticationData, + &authenticationData, + REQUEST); + } + length += 2 + AuthenticationName->length; /* authentication name */ + length += 2 + authenticationData.length; /* authentication data */ + length += 1; /* authorization names */ + for (i = 0; i < AuthorizationNames.length; i++) + length += 2 + AuthorizationNames.data[i].length; + length += 2 + ManufacturerDisplayID.length; /* display ID */ + header.length = length; + + if (!XdmcpWriteHeader (&buffer, &header)) + { + XdmcpDisposeARRAY8 (&authenticationData); + return; + } + XdmcpWriteCARD16 (&buffer, DisplayNumber); + XdmcpWriteARRAY16 (&buffer, &ConnectionTypes); + XdmcpWriteARRAYofARRAY8 (&buffer, &ConnectionAddresses); + + XdmcpWriteARRAY8 (&buffer, AuthenticationName); + XdmcpWriteARRAY8 (&buffer, &authenticationData); + XdmcpDisposeARRAY8 (&authenticationData); + XdmcpWriteARRAYofARRAY8 (&buffer, &AuthorizationNames); + XdmcpWriteARRAY8 (&buffer, &ManufacturerDisplayID); + if (XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen)) + state = XDM_AWAIT_REQUEST_RESPONSE; +} + +static void +recv_accept_msg(length) + unsigned length; +{ + CARD32 AcceptSessionID; + ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData; + ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData; + + if (state != XDM_AWAIT_REQUEST_RESPONSE) + return; + AcceptAuthenticationName.data = 0; + AcceptAuthenticationData.data = 0; + AcceptAuthorizationName.data = 0; + AcceptAuthorizationData.data = 0; + if (XdmcpReadCARD32 (&buffer, &AcceptSessionID) && + XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationName) && + XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationData) && + XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationName) && + XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationData)) + { + if (length == 12 + AcceptAuthenticationName.length + + AcceptAuthenticationData.length + + AcceptAuthorizationName.length + + AcceptAuthorizationData.length) + { + if (!XdmcpCheckAuthentication (&AcceptAuthenticationName, + &AcceptAuthenticationData, ACCEPT)) + { + XdmcpFatal ("Authentication Failure", &AcceptAuthenticationName); + } + /* permit access control manipulations from this host */ + AugmentSelf (&req_sockaddr, req_socklen); + /* if the authorization specified in the packet fails + * to be acceptable, enable the local addresses + */ + if (!XdmcpAddAuthorization (&AcceptAuthorizationName, + &AcceptAuthorizationData)) + { + AddLocalHosts (); + } + SessionID = AcceptSessionID; + state = XDM_MANAGE; + send_packet(); + } + } + XdmcpDisposeARRAY8 (&AcceptAuthenticationName); + XdmcpDisposeARRAY8 (&AcceptAuthenticationData); + XdmcpDisposeARRAY8 (&AcceptAuthorizationName); + XdmcpDisposeARRAY8 (&AcceptAuthorizationData); +} + +static void +recv_decline_msg(length) + unsigned length; +{ + ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData; + + status.data = 0; + DeclineAuthenticationName.data = 0; + DeclineAuthenticationData.data = 0; + if (XdmcpReadARRAY8 (&buffer, &status) && + XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationName) && + XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationData)) + { + if (length == 6 + status.length + + DeclineAuthenticationName.length + + DeclineAuthenticationData.length && + XdmcpCheckAuthentication (&DeclineAuthenticationName, + &DeclineAuthenticationData, DECLINE)) + { + XdmcpFatal ("Session declined", &status); + } + } + XdmcpDisposeARRAY8 (&status); + XdmcpDisposeARRAY8 (&DeclineAuthenticationName); + XdmcpDisposeARRAY8 (&DeclineAuthenticationData); +} + +static void +send_manage_msg() +{ + XdmcpHeader header; + + header.version = XDM_PROTOCOL_VERSION; + header.opcode = (CARD16) MANAGE; + header.length = 8 + DisplayClass.length; + + if (!XdmcpWriteHeader (&buffer, &header)) + return; + XdmcpWriteCARD32 (&buffer, SessionID); + XdmcpWriteCARD16 (&buffer, DisplayNumber); + XdmcpWriteARRAY8 (&buffer, &DisplayClass); + state = XDM_AWAIT_MANAGE_RESPONSE; + XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen); +} + +static void +recv_refuse_msg(length) + unsigned length; +{ + CARD32 RefusedSessionID; + + if (state != XDM_AWAIT_MANAGE_RESPONSE) + return; + if (length != 4) + return; + if (XdmcpReadCARD32 (&buffer, &RefusedSessionID)) + { + if (RefusedSessionID == SessionID) + { + state = XDM_START_CONNECTION; + send_packet(); + } + } +} + +static void +recv_failed_msg(length) + unsigned length; +{ + CARD32 FailedSessionID; + ARRAY8 status; + + if (state != XDM_AWAIT_MANAGE_RESPONSE) + return; + status.data = 0; + if (XdmcpReadCARD32 (&buffer, &FailedSessionID) && + XdmcpReadARRAY8 (&buffer, &status)) + { + if (length == 6 + status.length && + SessionID == FailedSessionID) + { + XdmcpFatal ("Session failed", &status); + } + } + XdmcpDisposeARRAY8 (&status); +} + +static void +send_keepalive_msg() +{ + XdmcpHeader header; + + header.version = XDM_PROTOCOL_VERSION; + header.opcode = (CARD16) KEEPALIVE; + header.length = 6; + + XdmcpWriteHeader (&buffer, &header); + XdmcpWriteCARD16 (&buffer, DisplayNumber); + XdmcpWriteCARD32 (&buffer, SessionID); + + state = XDM_AWAIT_ALIVE_RESPONSE; + XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen); +} + +static void +recv_alive_msg (length) + unsigned length; +{ + CARD8 SessionRunning; + CARD32 AliveSessionID; + int dormancy; + + if (state != XDM_AWAIT_ALIVE_RESPONSE) + return; + if (length != 5) + return; + if (XdmcpReadCARD8 (&buffer, &SessionRunning) && + XdmcpReadCARD32 (&buffer, &AliveSessionID)) + { + if (SessionRunning && AliveSessionID == SessionID) + { + /* backoff dormancy period */ + state = XDM_RUN_SESSION; + if ((GetTimeInMillis() - lastDeviceEventTime.milliseconds) > + keepaliveDormancy * 1000) + { + keepaliveDormancy <<= 1; + if (keepaliveDormancy > XDM_MAX_DORMANCY) + keepaliveDormancy = XDM_MAX_DORMANCY; + } + timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000; + } + else + { + XdmcpDeadSession ("Alive respose indicates session dead"); + } + } +} + +static +XdmcpFatal (type, status) + char *type; + ARRAY8Ptr status; +{ + extern void AbortDDX(); + + ErrorF ("XDMCP fatal error: %s %*.*s\n", type, + status->length, status->length, status->data); + AbortDDX (); + exit (1); +} + +static +XdmcpWarning(str) + char *str; +{ + ErrorF("XDMCP warning: %s\n", str); +} + +static +get_manager_by_name(argc, argv, i) + int argc, i; + char **argv; +{ + struct hostent *hep; + _Xgethostbynameparams hparams; + + if (i == argc) + { + ErrorF("Xserver: missing host name in command line\n"); + exit(1); + } + if (!(hep = _XGethostbyname(argv[i], hparams))) + { + ErrorF("Xserver: unknown host: %s\n", argv[i]); + exit(1); + } + if (hep->h_length == sizeof (struct in_addr)) + { + memmove(&ManagerAddress.sin_addr, hep->h_addr, hep->h_length); +#ifdef BSD44SOCKETS + ManagerAddress.sin_len = sizeof(ManagerAddress); +#endif + ManagerAddress.sin_family = AF_INET; + ManagerAddress.sin_port = htons (xdm_udp_port); + } + else + { + ErrorF ("Xserver: host on strange network %s\n", argv[i]); + exit (1); + } +} +#else +static int xdmcp_non_empty; /* avoid complaint by ranlib */ +#endif /* XDMCP */ diff --git a/record/record.c b/record/record.c new file mode 100644 index 000000000..bcc019f27 --- /dev/null +++ b/record/record.c @@ -0,0 +1,3021 @@ +/* $Xorg: record.c,v 1.4 2001/02/09 02:05:27 xorgcvs Exp $ */ + +/* + +Copyright 1995, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +Author: David P. Wiggins, The Open Group + +This work benefited from earlier work done by Martha Zimet of NCD +and Jim Haggerty of Metheus. + +*/ + +#include +#include +#define NEED_EVENTS +#include "dixstruct.h" +#include "extnsionst.h" +#define _XRECORD_SERVER_ +#include "X11/extensions/recordstr.h" +#include "set.h" + +static RESTYPE RTContext; /* internal resource type for Record contexts */ +static int RecordErrorBase; /* first Record error number */ + +/* How many bytes of protocol data to buffer in a context. Don't set to less + * than 32. + */ +#define REPLY_BUF_SIZE 1024 + +/* Record Context structure */ + +typedef struct { + XID id; /* resource id of context */ + ClientPtr pRecordingClient; /* client that has context enabled */ + struct _RecordClientsAndProtocolRec *pListOfRCAP; /* all registered info */ + ClientPtr pBufClient; /* client whose protocol is in replyBuffer*/ + unsigned int continuedReply:1; /* recording a reply that is split up? */ + char elemHeaders; /* element header flags (time/seq no.) */ + char bufCategory; /* category of protocol in replyBuffer */ + int numBufBytes; /* number of bytes in replyBuffer */ + char replyBuffer[REPLY_BUF_SIZE]; /* buffered recorded protocol */ +} RecordContextRec, *RecordContextPtr; + +/* RecordMinorOpRec - to hold minor opcode selections for extension requests + * and replies + */ + +typedef union { + int count; /* first element of array: how many "major" structs to follow */ + struct { /* rest of array elements are this */ + short first; /* first major opcode */ + short last; /* last major opcode */ + RecordSetPtr pMinOpSet; /* minor opcode set for above major range */ + } major; +} RecordMinorOpRec, *RecordMinorOpPtr; + + +/* RecordClientsAndProtocolRec, nicknamed RCAP - holds all the client and + * protocol selections passed in a single CreateContext or RegisterClients. + * Generally, a context will have one of these from the create and an + * additional one for each RegisterClients. RCAPs are freed when all their + * clients are unregistered. + */ + +typedef struct _RecordClientsAndProtocolRec { + RecordContextPtr pContext; /* context that owns this RCAP */ + struct _RecordClientsAndProtocolRec *pNextRCAP; /* next RCAP on context */ + RecordSetPtr pRequestMajorOpSet; /* requests to record */ + RecordMinorOpPtr pRequestMinOpInfo; /* extension requests to record */ + RecordSetPtr pReplyMajorOpSet; /* replies to record */ + RecordMinorOpPtr pReplyMinOpInfo; /* extension replies to record */ + RecordSetPtr pDeviceEventSet; /* device events to record */ + RecordSetPtr pDeliveredEventSet; /* delivered events to record */ + RecordSetPtr pErrorSet; /* errors to record */ + XID * pClientIDs; /* array of clients to record */ + short numClients; /* number of clients in pClientIDs */ + short sizeClients; /* size of pClientIDs array */ + unsigned int clientStarted:1; /* record new client connections? */ + unsigned int clientDied:1; /* record client disconnections? */ + unsigned int clientIDsSeparatelyAllocated:1; /* pClientIDs malloced? */ +} RecordClientsAndProtocolRec, *RecordClientsAndProtocolPtr; + +/* how much bigger to make pRCAP->pClientIDs when reallocing */ +#define CLIENT_ARRAY_GROWTH_INCREMENT 4 + +/* counts the total number of RCAPs belonging to enabled contexts. */ +static int numEnabledRCAPs; + +/* void VERIFY_CONTEXT(RecordContextPtr, XID, ClientPtr) + * In the spirit of the VERIFY_* macros in dix.h, this macro fills in + * the context pointer if the given ID is a valid Record Context, else it + * returns an error. + */ +#define VERIFY_CONTEXT(_pContext, _contextid, _client) { \ + (_pContext) = (RecordContextPtr)LookupIDByType((_contextid), RTContext); \ + if (!(_pContext)) { \ + (_client)->errorValue = (_contextid); \ + return RecordErrorBase + XRecordBadContext; \ + } \ +} + +static int RecordDeleteContext( +#if NeedFunctionPrototypes + pointer /*value*/, + XID /*id*/ +#endif +); + + +/***************************************************************************/ + +/* client private stuff */ + +/* To make declarations less obfuscated, have a typedef for a pointer to a + * Proc function. + */ +typedef int (*ProcFunctionPtr)( +#if NeedFunctionPrototypes + ClientPtr /*pClient*/ +#endif +); + +/* Record client private. Generally a client only has one of these if + * any of its requests are being recorded. + */ +typedef struct { +/* ptr to client's proc vector before Record stuck its nose in */ + ProcFunctionPtr *originalVector; + +/* proc vector with pointers for recorded requests redirected to the + * function RecordARequest + */ + ProcFunctionPtr recordVector[256]; +} RecordClientPrivateRec, *RecordClientPrivatePtr; + +static int RecordClientPrivateIndex; + +/* RecordClientPrivatePtr RecordClientPrivate(ClientPtr) + * gets the client private of the given client. Syntactic sugar. + */ +#define RecordClientPrivate(_pClient) (RecordClientPrivatePtr) \ + ((_pClient)->devPrivates[RecordClientPrivateIndex].ptr) + + +/***************************************************************************/ + +/* global list of all contexts */ + +static RecordContextPtr *ppAllContexts; + +static int numContexts;/* number of contexts in ppAllContexts */ + +/* number of currently enabled contexts. All enabled contexts are bunched + * up at the front of the ppAllContexts array, from ppAllContexts[0] to + * ppAllContexts[numEnabledContexts-1], to eliminate time spent skipping + * past disabled contexts. + */ +static int numEnabledContexts; + +/* RecordFindContextOnAllContexts + * + * Arguments: + * pContext is the context to search for. + * + * Returns: + * The index into the array ppAllContexts at which pContext is stored. + * If pContext is not found in ppAllContexts, returns -1. + * + * Side Effects: none. + */ +static int +RecordFindContextOnAllContexts(pContext) + RecordContextPtr pContext; +{ + int i; + + assert(numContexts >= numEnabledContexts); + for (i = 0; i < numContexts; i++) + { + if (ppAllContexts[i] == pContext) + return i; + } + return -1; +} /* RecordFindContextOnAllContexts */ + + +/***************************************************************************/ + +/* RecordFlushReplyBuffer + * + * Arguments: + * pContext is the context to flush. + * data1 is a pointer to additional data, and len1 is its length in bytes. + * data2 is a pointer to additional data, and len2 is its length in bytes. + * + * Returns: nothing. + * + * Side Effects: + * If the context is enabled, any buffered (recorded) protocol is written + * to the recording client, and the number of buffered bytes is set to + * zero. If len1 is not zero, data1/len1 are then written to the + * recording client, and similarly for data2/len2 (written after + * data1/len1). + */ +static void +RecordFlushReplyBuffer(pContext, data1, len1, data2, len2) + RecordContextPtr pContext; + pointer data1; + int len1; + pointer data2; + int len2; +{ + if (!pContext->pRecordingClient || pContext->pRecordingClient->clientGone) + return; + if (pContext->numBufBytes) + WriteToClient(pContext->pRecordingClient, pContext->numBufBytes, + (char *)pContext->replyBuffer); + pContext->numBufBytes = 0; + if (len1) + WriteToClient(pContext->pRecordingClient, len1, (char *)data1); + if (len2) + WriteToClient(pContext->pRecordingClient, len2, (char *)data2); +} /* RecordFlushReplyBuffer */ + + +/* RecordAProtocolElement + * + * Arguments: + * pContext is the context that is recording a protocol element. + * pClient is the client whose protocol is being recorded. For + * device events and EndOfData, pClient is NULL. + * category is the category of the protocol element, as defined + * by the RECORD spec. + * data is a pointer to the protocol data, and datalen is its length + * in bytes. + * futurelen is the number of bytes that will be sent in subsequent + * calls to this function to complete this protocol element. + * In those subsequent calls, futurelen will be -1 to indicate + * that the current data is a continuation of the same protocol + * element. + * + * Returns: nothing. + * + * Side Effects: + * The context may be flushed. The new protocol element will be + * added to the context's protocol buffer with appropriate element + * headers prepended (sequence number and timestamp). If the data + * is continuation data (futurelen == -1), element headers won't + * be added. If the protocol element and headers won't fit in + * the context's buffer, it is sent directly to the recording + * client (after any buffered data). + */ +static void +RecordAProtocolElement(pContext, pClient, category, data, datalen, futurelen) + RecordContextPtr pContext; + ClientPtr pClient; + int category; + pointer data; + int datalen; + int futurelen; +{ + CARD32 elemHeaderData[2]; + int numElemHeaders = 0; + Bool recordingClientSwapped = pContext->pRecordingClient->swapped; + int n; + CARD32 serverTime; + Bool gotServerTime = FALSE; + int replylen; + + if (futurelen >= 0) + { /* start of new protocol element */ + xRecordEnableContextReply *pRep = (xRecordEnableContextReply *) + pContext->replyBuffer; + if (pContext->pBufClient != pClient || + pContext->bufCategory != category) + { + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + pContext->pBufClient = pClient; + pContext->bufCategory = category; + } + + if (!pContext->numBufBytes) + { + serverTime = GetTimeInMillis(); + gotServerTime = TRUE; + pRep->type = X_Reply; + pRep->category = category; + pRep->sequenceNumber = pContext->pRecordingClient->sequence; + pRep->length = 0; + pRep->elementHeader = pContext->elemHeaders; + pRep->serverTime = serverTime; + if (pClient) + { + pRep->clientSwapped = + (pClient->swapped != recordingClientSwapped); + pRep->idBase = pClient->clientAsMask; + pRep->recordedSequenceNumber = pClient->sequence; + } + else /* it's a device event, StartOfData, or EndOfData */ + { + pRep->clientSwapped = (category != XRecordFromServer) && + recordingClientSwapped; + pRep->idBase = 0; + pRep->recordedSequenceNumber = 0; + } + + if (recordingClientSwapped) + { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->idBase, n); + swapl(&pRep->serverTime, n); + swapl(&pRep->recordedSequenceNumber, n); + } + pContext->numBufBytes = SIZEOF(xRecordEnableContextReply); + } + + /* generate element headers if needed */ + + if ( ( (pContext->elemHeaders & XRecordFromClientTime) + && category == XRecordFromClient) + || + ( (pContext->elemHeaders & XRecordFromServerTime) + && category == XRecordFromServer)) + { + if (gotServerTime) + elemHeaderData[numElemHeaders] = serverTime; + else + elemHeaderData[numElemHeaders] = GetTimeInMillis(); + if (recordingClientSwapped) + swapl(&elemHeaderData[numElemHeaders], n); + numElemHeaders++; + } + + if ( (pContext->elemHeaders & XRecordFromClientSequence) + && + (category == XRecordFromClient || category == XRecordClientDied)) + { + elemHeaderData[numElemHeaders] = pClient->sequence; + if (recordingClientSwapped) + swapl(&elemHeaderData[numElemHeaders], n); + numElemHeaders++; + } + + /* adjust reply length */ + + replylen = pRep->length; + if (recordingClientSwapped) swapl(&replylen, n); + replylen += numElemHeaders + (datalen >> 2) + (futurelen >> 2); + if (recordingClientSwapped) swapl(&replylen, n); + pRep->length = replylen; + } /* end if not continued reply */ + + numElemHeaders *= 4; + + /* if space available >= space needed, buffer the data */ + + if (REPLY_BUF_SIZE - pContext->numBufBytes >= datalen + numElemHeaders) + { + if (numElemHeaders) + { + memcpy(pContext->replyBuffer + pContext->numBufBytes, + elemHeaderData, numElemHeaders); + pContext->numBufBytes += numElemHeaders; + } + if (datalen) + { + memcpy(pContext->replyBuffer + pContext->numBufBytes, + data, datalen); + pContext->numBufBytes += datalen; + } + } + else + RecordFlushReplyBuffer(pContext, (pointer)elemHeaderData, + numElemHeaders, (pointer)data, datalen); + +} /* RecordAProtocolElement */ + + +/* RecordFindClientOnContext + * + * Arguments: + * pContext is the context to search. + * clientspec is the resource ID mask identifying the client to search + * for, or XRecordFutureClients. + * pposition is a pointer to an int, or NULL. See Returns. + * + * Returns: + * The RCAP on which clientspec was found, or NULL if not found on + * any RCAP on the given context. + * If pposition was not NULL and the returned RCAP is not NULL, + * *pposition will be set to the index into the returned the RCAP's + * pClientIDs array that holds clientspec. + * + * Side Effects: none. + */ +static RecordClientsAndProtocolPtr +RecordFindClientOnContext(pContext, clientspec, pposition) + RecordContextPtr pContext; + XID clientspec; + int *pposition; +{ + RecordClientsAndProtocolPtr pRCAP; + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + int i; + for (i = 0; i < pRCAP->numClients; i++) + { + if (pRCAP->pClientIDs[i] == clientspec) + { + if (pposition) + *pposition = i; + return pRCAP; + } + } + } + return NULL; +} /* RecordFindClientOnContext */ + + +/* RecordABigRequest + * + * Arguments: + * pContext is the recording context. + * client is the client being recorded. + * stuff is a pointer to the big request of client (see the Big Requests + * extension for details.) + * + * Returns: nothing. + * + * Side Effects: + * The big request is recorded with the correct length field re-inserted. + * + * Note: this function exists mainly to make RecordARequest smaller. + */ +static void +RecordABigRequest(pContext, client, stuff) + RecordContextPtr pContext; + ClientPtr client; + xReq *stuff; +{ + CARD32 bigLength; + char n; + int bytesLeft; + + /* note: client->req_len has been frobbed by ReadRequestFromClient + * (os/io.c) to discount the extra 4 bytes taken by the extended length + * field in a big request. The actual request length to record is + * client->req_len + 1 (measured in CARD32s). + */ + + /* record the request header */ + bytesLeft = client->req_len << 2; + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)stuff, SIZEOF(xReq), bytesLeft); + + /* reinsert the extended length field that was squished out */ + bigLength = client->req_len + (sizeof(bigLength) >> 2); + if (client->swapped) + swapl(&bigLength, n); + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)&bigLength, sizeof(bigLength), /* continuation */ -1); + bytesLeft -= sizeof(bigLength); + + /* record the rest of the request after the length */ + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)(stuff + 1), bytesLeft, /* continuation */ -1); +} /* RecordABigRequest */ + + +/* RecordARequest + * + * Arguments: + * client is a client that the server has dispatched a request to by + * calling client->requestVector[request opcode] . + * The request is in client->requestBuffer. + * + * Returns: + * Whatever is returned by the "real" Proc function for this request. + * The "real" Proc function is the function that was in + * client->requestVector[request opcode] before it was replaced by + * RecordARequest. (See the function RecordInstallHooks.) + * + * Side Effects: + * The request is recorded by all contexts that have registered this + * request for this client. The real Proc function is called. + */ +static int +RecordARequest(client) + ClientPtr client; +{ + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int i; + RecordClientPrivatePtr pClientPriv; + REQUEST(xReq); + int majorop; + + majorop = stuff->reqType; + for (i = 0; i < numEnabledContexts; i++) + { + pContext = ppAllContexts[i]; + pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, + NULL); + if (pRCAP && pRCAP->pRequestMajorOpSet && + RecordIsMemberOfSet(pRCAP->pRequestMajorOpSet, majorop)) + { + if (majorop <= 127) + { /* core request */ + + if (stuff->length == 0) + RecordABigRequest(pContext, client, stuff); + else + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)stuff, client->req_len << 2, 0); + } + else /* extension, check minor opcode */ + { + int minorop = MinorOpcodeOfRequest(client); + int numMinOpInfo; + RecordMinorOpPtr pMinorOpInfo = pRCAP->pRequestMinOpInfo; + + assert (pMinorOpInfo); + numMinOpInfo = pMinorOpInfo->count; + pMinorOpInfo++; + assert (numMinOpInfo); + for ( ; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) + { + if (majorop >= pMinorOpInfo->major.first && + majorop <= pMinorOpInfo->major.last && + RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet, + minorop)) + { + if (stuff->length == 0) + RecordABigRequest(pContext, client, stuff); + else + RecordAProtocolElement(pContext, client, + XRecordFromClient, (pointer)stuff, + client->req_len << 2, 0); + break; + } + } /* end for each minor op info */ + } /* end extension request */ + } /* end this RCAP wants this major opcode */ + } /* end for each context */ + pClientPriv = RecordClientPrivate(client); + assert(pClientPriv); + return (* pClientPriv->originalVector[majorop])(client); +} /* RecordARequest */ + + +/* RecordASkippedRequest + * + * Arguments: + * pcbl is &SkippedRequestCallback. + * nulldata is NULL. + * calldata is a pointer to a SkippedRequestInfoRec (include/os.h) + * which provides information about requests that the server is + * skipping. The client's proc vector won't be called for skipped + * requests, so that's why we have to catch them here. + * + * Returns: nothing. + * + * Side Effects: + * The skipped requests are recorded by all contexts that have + * registered those requests for this client. + * + * Note: most servers don't skip requests, so calls to this will probably + * be rare. For more information on skipped requests, search for + * the word skip in ddx.tbl.ms (the porting layer document). + */ +static void +RecordASkippedRequest(pcbl , nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + SkippedRequestInfoRec *psi = (SkippedRequestInfoRec *)calldata; + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + xReqPtr stuff = psi->req; + ClientPtr client = psi->client; + int numSkippedRequests = psi->numskipped; + int reqlen; + int i; + int majorop; + + while (numSkippedRequests--) + { + majorop = stuff->reqType; + reqlen = ReqLen(stuff, client); + /* handle big request */ + if (stuff->length == 0) + reqlen += 4; + for (i = 0; i < numEnabledContexts; i++) + { + pContext = ppAllContexts[i]; + pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, + NULL); + if (pRCAP && pRCAP->pRequestMajorOpSet && + RecordIsMemberOfSet(pRCAP->pRequestMajorOpSet, majorop)) + { + if (majorop <= 127) + { /* core request */ + + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)stuff, reqlen, 0); + } + else /* extension, check minor opcode */ + { + int minorop = MinorOpcodeOfRequest(client); + int numMinOpInfo; + RecordMinorOpPtr pMinorOpInfo = pRCAP->pRequestMinOpInfo; + + assert (pMinorOpInfo); + numMinOpInfo = pMinorOpInfo->count; + pMinorOpInfo++; + assert (numMinOpInfo); + for ( ; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) + { + if (majorop >= pMinorOpInfo->major.first && + majorop <= pMinorOpInfo->major.last && + RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet, + minorop)) + { + RecordAProtocolElement(pContext, client, + XRecordFromClient, (pointer)stuff, + reqlen, 0); + break; + } + } /* end for each minor op info */ + } /* end extension request */ + } /* end this RCAP wants this major opcode */ + } /* end for each context */ + + /* go to next request */ + stuff = (xReqPtr)( ((char *)stuff) + reqlen); + + } /* end for each skipped request */ +} /* RecordASkippedRequest */ + + +/* RecordAReply + * + * Arguments: + * pcbl is &ReplyCallback. + * nulldata is NULL. + * calldata is a pointer to a ReplyInfoRec (include/os.h) + * which provides information about replies that are being sent + * to clients. + * + * Returns: nothing. + * + * Side Effects: + * The reply is recorded by all contexts that have registered this + * reply type for this client. If more data belonging to the same + * reply is expected, and if the reply is being recorded by any + * context, pContext->continuedReply is set to 1. + * If pContext->continuedReply was already 1 and this is the last + * chunk of data belonging to this reply, it is set to 0. + */ +static void +RecordAReply(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int eci; + int majorop; + ReplyInfoRec *pri = (ReplyInfoRec *)calldata; + ClientPtr client = pri->client; + REQUEST(xReq); + + majorop = stuff->reqType; + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, + NULL); + if (pRCAP) + { + if (pContext->continuedReply) + { + RecordAProtocolElement(pContext, client, XRecordFromServer, + pri->replyData, pri->dataLenBytes, /* continuation */ -1); + if (!pri->bytesRemaining) + pContext->continuedReply = 0; + } + else if (pri->startOfReply && pRCAP->pReplyMajorOpSet && + RecordIsMemberOfSet(pRCAP->pReplyMajorOpSet, majorop)) + { + if (majorop <= 127) + { /* core reply */ + RecordAProtocolElement(pContext, client, XRecordFromServer, + pri->replyData, pri->dataLenBytes, pri->bytesRemaining); + if (pri->bytesRemaining) + pContext->continuedReply = 1; + } + else /* extension, check minor opcode */ + { + int minorop = MinorOpcodeOfRequest(client); + int numMinOpInfo; + RecordMinorOpPtr pMinorOpInfo = pRCAP->pReplyMinOpInfo; + assert (pMinorOpInfo); + numMinOpInfo = pMinorOpInfo->count; + pMinorOpInfo++; + assert (numMinOpInfo); + for ( ; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) + { + if (majorop >= pMinorOpInfo->major.first && + majorop <= pMinorOpInfo->major.last && + RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet, + minorop)) + { + RecordAProtocolElement(pContext, client, + XRecordFromServer, pri->replyData, + pri->dataLenBytes, pri->bytesRemaining); + if (pri->bytesRemaining) + pContext->continuedReply = 1; + break; + } + } /* end for each minor op info */ + } /* end extension reply */ + } /* end continued reply vs. start of reply */ + } /* end client is registered on this context */ + } /* end for each context */ +} /* RecordAReply */ + + +/* RecordADeliveredEventOrError + * + * Arguments: + * pcbl is &EventCallback. + * nulldata is NULL. + * calldata is a pointer to a EventInfoRec (include/dix.h) + * which provides information about events that are being sent + * to clients. + * + * Returns: nothing. + * + * Side Effects: + * The event or error is recorded by all contexts that have registered + * it for this client. + */ +static void +RecordADeliveredEventOrError(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + EventInfoRec *pei = (EventInfoRec *)calldata; + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int eci; /* enabled context index */ + ClientPtr pClient = pei->client; + + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + pRCAP = RecordFindClientOnContext(pContext, pClient->clientAsMask, + NULL); + if (pRCAP && (pRCAP->pDeliveredEventSet || pRCAP->pErrorSet)) + { + int ev; /* event index */ + xEvent *pev = pei->events; + for (ev = 0; ev < pei->count; ev++, pev++) + { + int recordit; + if (pev->u.u.type == X_Error) + { + recordit = RecordIsMemberOfSet(pRCAP->pErrorSet, + ((xError *)(pev))->errorCode); + } + else + { + recordit = RecordIsMemberOfSet(pRCAP->pDeliveredEventSet, + pev->u.u.type & 0177); + } + if (recordit) + { + xEvent swappedEvent; + xEvent *pEvToRecord = pev; + + if (pClient->swapped) + { + (*EventSwapVector[pev->u.u.type & 0177]) + (pev, &swappedEvent); + pEvToRecord = &swappedEvent; + + } + RecordAProtocolElement(pContext, pClient, + XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); + } + } /* end for each event */ + } /* end this client is on this context */ + } /* end for each enabled context */ +} /* RecordADeliveredEventOrError */ + + +/* RecordADeviceEvent + * + * Arguments: + * pcbl is &DeviceEventCallback. + * nulldata is NULL. + * calldata is a pointer to a DeviceEventInfoRec (include/dix.h) + * which provides information about device events that occur. + * + * Returns: nothing. + * + * Side Effects: + * The device event is recorded by all contexts that have registered + * it for this client. + */ +static void +RecordADeviceEvent(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + DeviceEventInfoRec *pei = (DeviceEventInfoRec *)calldata; + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int eci; /* enabled context index */ + + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + if (pRCAP->pDeviceEventSet) + { + int ev; /* event index */ + xEvent *pev = pei->events; + for (ev = 0; ev < pei->count; ev++, pev++) + { + if (RecordIsMemberOfSet(pRCAP->pDeviceEventSet, + pev->u.u.type & 0177)) + { + xEvent swappedEvent; + xEvent *pEvToRecord = pev; + + if (pContext->pRecordingClient->swapped) + { + (*EventSwapVector[pev->u.u.type & 0177]) + (pev, &swappedEvent); + pEvToRecord = &swappedEvent; + } + + RecordAProtocolElement(pContext, NULL, + XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); + /* make sure device events get flushed in the absence + * of other client activity + */ + SetCriticalOutputPending(); + } + } /* end for each event */ + } /* end this RCAP selects device events */ + } /* end for each RCAP on this context */ + } /* end for each enabled context */ +} /* RecordADeviceEvent */ + + +/* RecordFlushAllContexts + * + * Arguments: + * pcbl is &FlushCallback. + * nulldata and calldata are NULL. + * + * Returns: nothing. + * + * Side Effects: + * All buffered reply data of all enabled contexts is written to + * the recording clients. + */ +static void +RecordFlushAllContexts(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + int eci; /* enabled context index */ + RecordContextPtr pContext; + + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + + /* In most cases we leave it to RecordFlushReplyBuffer to make + * this check, but this function could be called very often, so we + * check before calling hoping to save the function call cost + * most of the time. + */ + if (pContext->numBufBytes) + RecordFlushReplyBuffer(ppAllContexts[eci], NULL, 0, NULL, 0); + } +} /* RecordFlushAllContexts */ + + +/* RecordInstallHooks + * + * Arguments: + * pRCAP is an RCAP on an enabled or being-enabled context. + * oneclient can be zero or the resource ID mask identifying a client. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * Recording hooks needed by RCAP are installed. + * If oneclient is zero, recording hooks needed for all clients and + * protocol on the RCAP are installed. If oneclient is non-zero, + * only those hooks needed for the specified client are installed. + * + * Client requestVectors may be altered. numEnabledRCAPs will be + * incremented if oneclient == 0. Callbacks may be added to + * various callback lists. + */ +static int +RecordInstallHooks(pRCAP, oneclient) + RecordClientsAndProtocolPtr pRCAP; + XID oneclient; +{ + int i = 0; + XID client; + + if (oneclient) + client = oneclient; + else + client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0; + + while (client) + { + if (client != XRecordFutureClients) + { + if (pRCAP->pRequestMajorOpSet) + { + RecordSetIteratePtr pIter = NULL; + RecordSetInterval interval; + ClientPtr pClient = clients[CLIENT_ID(client)]; + + if (pClient && !RecordClientPrivate(pClient)) + { + RecordClientPrivatePtr pClientPriv; + /* no Record proc vector; allocate one */ + pClientPriv = (RecordClientPrivatePtr) + xalloc(sizeof(RecordClientPrivateRec)); + if (!pClientPriv) + return BadAlloc; + /* copy old proc vector to new */ + memcpy(pClientPriv->recordVector, pClient->requestVector, + sizeof (pClientPriv->recordVector)); + pClientPriv->originalVector = pClient->requestVector; + pClient->devPrivates[RecordClientPrivateIndex].ptr = + (pointer)pClientPriv; + pClient->requestVector = pClientPriv->recordVector; + } + while (pIter = RecordIterateSet(pRCAP->pRequestMajorOpSet, + pIter, &interval)) + { + unsigned int j; + for (j = interval.first; j <= interval.last; j++) + pClient->requestVector[j] = RecordARequest; + } + } + } + if (oneclient) + client = 0; + else + client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0; + } + + assert(numEnabledRCAPs >= 0); + if (!oneclient && ++numEnabledRCAPs == 1) + { /* we're enabling the first context */ + if (!AddCallback(&EventCallback, RecordADeliveredEventOrError, NULL)) + return BadAlloc; + if (!AddCallback(&DeviceEventCallback, RecordADeviceEvent, NULL)) + return BadAlloc; + if (!AddCallback(&ReplyCallback, RecordAReply, NULL)) + return BadAlloc; + if (!AddCallback(&SkippedRequestsCallback, RecordASkippedRequest, + NULL)) + return BadAlloc; + if (!AddCallback(&FlushCallback, RecordFlushAllContexts, NULL)) + return BadAlloc; + /* Alternate context flushing scheme: delete the line above + * and call RegisterBlockAndWakeupHandlers here passing + * RecordFlushAllContexts. Is this any better? + */ + } + return Success; +} /* RecordInstallHooks */ + + +/* RecordUninstallHooks + * + * Arguments: + * pRCAP is an RCAP on an enabled or being-disabled context. + * oneclient can be zero or the resource ID mask identifying a client. + * + * Returns: nothing. + * + * Side Effects: + * Recording hooks needed by RCAP may be uninstalled. + * If oneclient is zero, recording hooks needed for all clients and + * protocol on the RCAP may be uninstalled. If oneclient is non-zero, + * only those hooks needed for the specified client may be uninstalled. + * + * Client requestVectors may be altered. numEnabledRCAPs will be + * decremented if oneclient == 0. Callbacks may be deleted from + * various callback lists. + */ +static void +RecordUninstallHooks(pRCAP, oneclient) + RecordClientsAndProtocolPtr pRCAP; + XID oneclient; +{ + int i = 0; + XID client; + + if (oneclient) + client = oneclient; + else + client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0; + + while (client) + { + if (client != XRecordFutureClients) + { + if (pRCAP->pRequestMajorOpSet) + { + ClientPtr pClient = clients[CLIENT_ID(client)]; + int c; + Bool otherRCAPwantsProcVector = FALSE; + RecordClientPrivatePtr pClientPriv = + RecordClientPrivate(pClient); + + assert (pClient && RecordClientPrivate(pClient)); + memcpy(pClientPriv->recordVector, pClientPriv->originalVector, + sizeof (pClientPriv->recordVector)); + + for (c = 0; c < numEnabledContexts; c++) + { + RecordClientsAndProtocolPtr pOtherRCAP; + RecordContextPtr pContext = ppAllContexts[c]; + + if (pContext == pRCAP->pContext) continue; + pOtherRCAP = RecordFindClientOnContext(pContext, client, + NULL); + if (pOtherRCAP && pOtherRCAP->pRequestMajorOpSet) + { + RecordSetIteratePtr pIter = NULL; + RecordSetInterval interval; + + otherRCAPwantsProcVector = TRUE; + while (pIter = RecordIterateSet( + pOtherRCAP->pRequestMajorOpSet, + pIter, &interval)) + { + unsigned int j; + for (j = interval.first; j <= interval.last; j++) + pClient->requestVector[j] = RecordARequest; + } + } + } + if (!otherRCAPwantsProcVector) + { /* nobody needs it, so free it */ + pClient->requestVector = pClientPriv->originalVector; + pClient->devPrivates[RecordClientPrivateIndex].ptr = NULL; + xfree(pClientPriv); + } + } /* end if this RCAP specifies any requests */ + } /* end if not future clients */ + if (oneclient) + client = 0; + else + client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0; + } + + assert(numEnabledRCAPs >= 1); + if (!oneclient && --numEnabledRCAPs == 0) + { /* we're disabling the last context */ + DeleteCallback(&EventCallback, RecordADeliveredEventOrError, NULL); + DeleteCallback(&DeviceEventCallback, RecordADeviceEvent, NULL); + DeleteCallback(&ReplyCallback, RecordAReply, NULL); + DeleteCallback(&SkippedRequestsCallback, RecordASkippedRequest, NULL); + DeleteCallback(&FlushCallback, RecordFlushAllContexts, NULL); + /* Alternate context flushing scheme: delete the line above + * and call RemoveBlockAndWakeupHandlers here passing + * RecordFlushAllContexts. Is this any better? + */ + /* Having deleted the callback, call it one last time. -gildea */ + RecordFlushAllContexts(&FlushCallback, NULL, NULL); + } +} /* RecordUninstallHooks */ + + +/* RecordDeleteClientFromRCAP + * + * Arguments: + * pRCAP is an RCAP to delete the client from. + * position is the index into the array pRCAP->pClientIDs of the + * client to delete. + * + * Returns: nothing. + * + * Side Effects: + * Recording hooks needed by client will be uninstalled if the context + * is enabled. The designated client will be removed from the + * pRCAP->pClientIDs array. If it was the only client on the RCAP, + * the RCAP is removed from the context and freed. (Invariant: RCAPs + * have at least one client.) + */ +static void +RecordDeleteClientFromRCAP(pRCAP, position) + RecordClientsAndProtocolPtr pRCAP; + int position; +{ + if (pRCAP->pContext->pRecordingClient) + RecordUninstallHooks(pRCAP, pRCAP->pClientIDs[position]); + if (position != pRCAP->numClients - 1) + pRCAP->pClientIDs[position] = pRCAP->pClientIDs[pRCAP->numClients - 1]; + if (--pRCAP->numClients == 0) + { /* no more clients; remove RCAP from context's list */ + RecordContextPtr pContext = pRCAP->pContext; + if (pContext->pRecordingClient) + RecordUninstallHooks(pRCAP, 0); + if (pContext->pListOfRCAP == pRCAP) + pContext->pListOfRCAP = pRCAP->pNextRCAP; + else + { + RecordClientsAndProtocolPtr prevRCAP; + for (prevRCAP = pContext->pListOfRCAP; + prevRCAP->pNextRCAP != pRCAP; + prevRCAP = prevRCAP->pNextRCAP) + ; + prevRCAP->pNextRCAP = pRCAP->pNextRCAP; + } + /* free the RCAP */ + if (pRCAP->clientIDsSeparatelyAllocated) + xfree(pRCAP->pClientIDs); + xfree(pRCAP); + } +} /* RecordDeleteClientFromRCAP */ + + +/* RecordAddClientToRCAP + * + * Arguments: + * pRCAP is an RCAP to add the client to. + * clientspec is the resource ID mask identifying a client, or + * XRecordFutureClients. + * + * Returns: nothing. + * + * Side Effects: + * Recording hooks needed by client will be installed if the context + * is enabled. The designated client will be added to the + * pRCAP->pClientIDs array, which may be realloced. + * pRCAP->clientIDsSeparatelyAllocated may be set to 1 if there + * is no more room to hold clients internal to the RCAP. + */ +static void +RecordAddClientToRCAP(pRCAP, clientspec) + RecordClientsAndProtocolPtr pRCAP; + XID clientspec; +{ + if (pRCAP->numClients == pRCAP->sizeClients) + { + if (pRCAP->clientIDsSeparatelyAllocated) + { + XID *pNewIDs = (XID *)xrealloc(pRCAP->pClientIDs, + (pRCAP->sizeClients + CLIENT_ARRAY_GROWTH_INCREMENT) * + sizeof(XID)); + if (!pNewIDs) + return; + pRCAP->pClientIDs = pNewIDs; + pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT; + } + else + { + XID *pNewIDs = (XID *)xalloc((pRCAP->sizeClients + + CLIENT_ARRAY_GROWTH_INCREMENT) * sizeof(XID)); + if (!pNewIDs) + return; + memcpy(pNewIDs, pRCAP->pClientIDs, pRCAP->numClients *sizeof(XID)); + pRCAP->pClientIDs = pNewIDs; + pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT; + pRCAP->clientIDsSeparatelyAllocated = 1; + } + } + pRCAP->pClientIDs[pRCAP->numClients++] = clientspec; + if (pRCAP->pContext->pRecordingClient) + RecordInstallHooks(pRCAP, clientspec); +} /* RecordDeleteClientFromRCAP */ + + +/* RecordDeleteClientFromContext + * + * Arguments: + * pContext is the context to delete from. + * clientspec is the resource ID mask identifying a client, or + * XRecordFutureClients. + * + * Returns: nothing. + * + * Side Effects: + * If clientspec is on any RCAP of the context, it is deleted from that + * RCAP. (A given clientspec can only be on one RCAP of a context.) + */ +static void +RecordDeleteClientFromContext(pContext, clientspec) + RecordContextPtr pContext; + XID clientspec; +{ + RecordClientsAndProtocolPtr pRCAP; + int position; + + if (pRCAP = RecordFindClientOnContext(pContext, clientspec, &position)) + RecordDeleteClientFromRCAP(pRCAP, position); +} /* RecordDeleteClientFromContext */ + + +/* RecordSanityCheckClientSpecifiers + * + * Arguments: + * clientspecs is an array of alleged CLIENTSPECs passed by the client. + * nspecs is the number of elements in clientspecs. + * errorspec, if non-zero, is the resource id base of a client that + * must not appear in clienspecs. + * + * Returns: BadMatch if any of the clientspecs are invalid, else Success. + * + * Side Effects: none. + */ +static int +RecordSanityCheckClientSpecifiers(clientspecs, nspecs, errorspec) + XID *clientspecs; + int nspecs; + XID errorspec; +{ + int i; + int clientIndex; + + for (i = 0; i < nspecs; i++) + { + if (clientspecs[i] == XRecordCurrentClients || + clientspecs[i] == XRecordFutureClients || + clientspecs[i] == XRecordAllClients) + continue; + if (errorspec && (CLIENT_BITS(clientspecs[i]) == errorspec) ) + return BadMatch; + clientIndex = CLIENT_ID(clientspecs[i]); + if (clientIndex && clients[clientIndex] && + clients[clientIndex]->clientState == ClientStateRunning) + { + if (clientspecs[i] == clients[clientIndex]->clientAsMask) + continue; + if (!LookupIDByClass(clientspecs[i], RC_ANY)) + return BadMatch; + } + else + return BadMatch; + } + return Success; +} /* RecordSanityCheckClientSpecifiers */ + + +/* RecordCanonicalizeClientSpecifiers + * + * Arguments: + * pClientspecs is an array of CLIENTSPECs that have been sanity + * checked. + * pNumClientspecs is a pointer to the number of elements in pClientspecs. + * excludespec, if non-zero, is the resource id base of a client that + * should not be included in the expansion of XRecordAllClients or + * XRecordCurrentClients. + * + * Returns: + * A pointer to an array of CLIENTSPECs that is the same as the + * passed array with the following modifications: + * - all but the client id bits of resource IDs are stripped off. + * - duplicates removed. + * - XRecordAllClients expanded to a list of all currently connected + * clients + XRecordFutureClients - excludespec (if non-zero) + * - XRecordCurrentClients expanded to a list of all currently + * connected clients - excludespec (if non-zero) + * The returned array may be the passed array modified in place, or + * it may be an Xalloc'ed array. The caller should keep a pointer to the + * original array and free the returned array if it is different. + * + * *pNumClientspecs is set to the number of elements in the returned + * array. + * + * Side Effects: + * pClientspecs may be modified in place. + */ +static XID * +RecordCanonicalizeClientSpecifiers(pClientspecs, pNumClientspecs, excludespec) + XID *pClientspecs; + int *pNumClientspecs; + XID excludespec; +{ + int i; + int numClients = *pNumClientspecs; + + /* first pass strips off the resource index bits, leaving just the + * client id bits. This makes searching for a particular client simpler + * (and faster.) + */ + for (i = 0; i < numClients; i++) + { + XID cs = pClientspecs[i]; + if (cs > XRecordAllClients) + pClientspecs[i] = CLIENT_BITS(cs); + } + + for (i = 0; i < numClients; i++) + { + if (pClientspecs[i] == XRecordAllClients || + pClientspecs[i] == XRecordCurrentClients) + { /* expand All/Current */ + int j, nc; + XID *pCanon = (XID *)xalloc(sizeof(XID) * (currentMaxClients + 1)); + if (!pCanon) return NULL; + for (nc = 0, j = 1; j < currentMaxClients; j++) + { + ClientPtr client = clients[j]; + if (client != NullClient && + client->clientState == ClientStateRunning && + client->clientAsMask != excludespec) + { + pCanon[nc++] = client->clientAsMask; + } + } + if (pClientspecs[i] == XRecordAllClients) + pCanon[nc++] = XRecordFutureClients; + *pNumClientspecs = nc; + return pCanon; + } + else /* not All or Current */ + { + int j; + for (j = i + 1; j < numClients; ) + { + if (pClientspecs[i] == pClientspecs[j]) + { + pClientspecs[j] = pClientspecs[--numClients]; + } + else + j++; + } + } + } /* end for each clientspec */ + *pNumClientspecs = numClients; + return pClientspecs; +} /* RecordCanonicalizeClientSpecifiers */ + + +/****************************************************************************/ + +/* stuff for RegisterClients */ + +/* RecordPadAlign + * + * Arguments: + * size is the number of bytes taken by an object. + * align is a byte boundary (e.g. 4, 8) + * + * Returns: + * the number of pad bytes to add at the end of an object of the + * given size so that an object placed immediately behind it will + * begin on an -byte boundary. + * + * Side Effects: none. + */ +static int +RecordPadAlign(size, align) + int size; + int align; +{ + return (align - (size & (align - 1))) & (align - 1); +} /* RecordPadAlign */ + + +/* RecordSanityCheckRegisterClients + * + * Arguments: + * pContext is the context being registered on. + * client is the client that issued a RecordCreateContext or + * RecordRegisterClients request. + * stuff is a pointer to the request. + * + * Returns: + * Any one of several possible error values if any of the request + * arguments are invalid. Success if everything is OK. + * + * Side Effects: none. + */ +static int +RecordSanityCheckRegisterClients(pContext, client, stuff) + RecordContextPtr pContext; + ClientPtr client; + xRecordRegisterClientsReq *stuff; +{ + int err; + xRecordRange *pRange; + int i; + XID recordingClient; + + if (((client->req_len << 2) - SIZEOF(xRecordRegisterClientsReq)) != + 4 * stuff->nClients + SIZEOF(xRecordRange) * stuff->nRanges) + return BadLength; + + if (stuff->elementHeader & + ~(XRecordFromClientSequence|XRecordFromClientTime|XRecordFromServerTime)) + { + client->errorValue = stuff->elementHeader; + return BadValue; + } + + recordingClient = pContext->pRecordingClient ? + pContext->pRecordingClient->clientAsMask : 0; + err = RecordSanityCheckClientSpecifiers((XID *)&stuff[1], stuff->nClients, + recordingClient); + if (err != Success) return err; + + pRange = (xRecordRange *)(((XID *)&stuff[1]) + stuff->nClients); + for (i = 0; i < stuff->nRanges; i++, pRange++) + { + if (pRange->coreRequestsFirst > pRange->coreRequestsLast) + { + client->errorValue = pRange->coreRequestsFirst; + return BadValue; + } + if (pRange->coreRepliesFirst > pRange->coreRepliesLast) + { + client->errorValue = pRange->coreRepliesFirst; + return BadValue; + } + if ((pRange->extRequestsMajorFirst || pRange->extRequestsMajorLast) && + (pRange->extRequestsMajorFirst < 128 || + pRange->extRequestsMajorLast < 128 || + pRange->extRequestsMajorFirst > pRange->extRequestsMajorLast)) + { + client->errorValue = pRange->extRequestsMajorFirst; + return BadValue; + } + if (pRange->extRequestsMinorFirst > pRange->extRequestsMinorLast) + { + client->errorValue = pRange->extRequestsMinorFirst; + return BadValue; + } + if ((pRange->extRepliesMajorFirst || pRange->extRepliesMajorLast) && + (pRange->extRepliesMajorFirst < 128 || + pRange->extRepliesMajorLast < 128 || + pRange->extRepliesMajorFirst > pRange->extRepliesMajorLast)) + { + client->errorValue = pRange->extRepliesMajorFirst; + return BadValue; + } + if (pRange->extRepliesMinorFirst > pRange->extRepliesMinorLast) + { + client->errorValue = pRange->extRepliesMinorFirst; + return BadValue; + } + if ((pRange->deliveredEventsFirst || pRange->deliveredEventsLast) && + (pRange->deliveredEventsFirst < 2 || + pRange->deliveredEventsLast < 2 || + pRange->deliveredEventsFirst > pRange->deliveredEventsLast)) + { + client->errorValue = pRange->deliveredEventsFirst; + return BadValue; + } + if ((pRange->deviceEventsFirst || pRange->deviceEventsLast) && + (pRange->deviceEventsFirst < 2 || + pRange->deviceEventsLast < 2 || + pRange->deviceEventsFirst > pRange->deviceEventsLast)) + { + client->errorValue = pRange->deviceEventsFirst; + return BadValue; + } + if (pRange->errorsFirst > pRange->errorsLast) + { + client->errorValue = pRange->errorsFirst; + return BadValue; + } + if (pRange->clientStarted != xFalse && pRange->clientStarted != xTrue) + { + client->errorValue = pRange->clientStarted; + return BadValue; + } + if (pRange->clientDied != xFalse && pRange->clientDied != xTrue) + { + client->errorValue = pRange->clientDied; + return BadValue; + } + } /* end for each range */ + return Success; +} /* end RecordSanityCheckRegisterClients */ + +/* This is a tactical structure used to gather information about all the sets + * (RecordSetPtr) that need to be created for an RCAP in the process of + * digesting a list of RECORDRANGEs (converting it to the internal + * representation). + */ +typedef struct +{ + int nintervals; /* number of intervals in following array */ + RecordSetInterval *intervals; /* array of intervals for this set */ + int size; /* size of intevals array; >= nintervals */ + int align; /* alignment restriction for set */ + int offset; /* where to store set pointer rel. to start of RCAP */ + short first, last; /* if for extension, major opcode interval */ +} SetInfoRec, *SetInfoPtr; + +/* These constant are used to index into an array of SetInfoRec. */ +enum {REQ, /* set info for requests */ + REP, /* set info for replies */ + ERR, /* set info for errors */ + DEV, /* set info for device events */ + DLEV, /* set info for delivered events */ + PREDEFSETS}; /* number of predefined array entries */ + + +/* RecordAllocIntervals + * + * Arguments: + * psi is a pointer to a SetInfoRec whose intervals pointer is NULL. + * nIntervals is the desired size of the intervals array. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, psi->intervals is a pointer to size + * RecordSetIntervals, all zeroed, and psi->size is set to size. + */ +static int +RecordAllocIntervals(psi, nIntervals) + SetInfoPtr psi; + int nIntervals; +{ + assert(!psi->intervals); + psi->intervals = (RecordSetInterval *) + xalloc(nIntervals * sizeof(RecordSetInterval)); + if (!psi->intervals) + return BadAlloc; + bzero(psi->intervals, nIntervals * sizeof(RecordSetInterval)); + psi->size = nIntervals; + return Success; +} /* end RecordAllocIntervals */ + + +/* RecordConvertRangesToIntervals + * + * Arguments: + * psi is a pointer to the SetInfoRec we are building. + * pRanges is an array of xRecordRanges. + * nRanges is the number of elements in pRanges. + * byteoffset is the offset from the start of an xRecordRange of the + * two bytes (1 for first, 1 for last) we are interested in. + * pExtSetInfo, if non-NULL, indicates that the two bytes mentioned + * above are followed by four bytes (2 for first, 2 for last) + * representing a minor opcode range, and this information should be + * stored in one of the SetInfoRecs starting at pExtSetInfo. + * pnExtSetInfo is the number of elements in the pExtSetInfo array. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * The slice of pRanges indicated by byteoffset is stored in psi. + * If pExtSetInfo is non-NULL, minor opcode intervals are stored + * in an existing SetInfoRec if the major opcode interval matches, else + * they are stored in a new SetInfoRec, and *pnExtSetInfo is + * increased accordingly. + */ +static int +RecordConvertRangesToIntervals(psi, pRanges, nRanges, byteoffset, + pExtSetInfo, pnExtSetInfo) + SetInfoPtr psi; + xRecordRange *pRanges; + int nRanges; + int byteoffset; + SetInfoPtr pExtSetInfo; + int *pnExtSetInfo; +{ + int i; + CARD8 *pCARD8; + int first, last; + int err; + + for (i = 0; i < nRanges; i++, pRanges++) + { + pCARD8 = ((CARD8 *)pRanges) + byteoffset; + first = pCARD8[0]; + last = pCARD8[1]; + if (first || last) + { + if (!psi->intervals) + { + err = RecordAllocIntervals(psi, 2 * (nRanges - i)); + if (err != Success) + return err; + } + psi->intervals[psi->nintervals].first = first; + psi->intervals[psi->nintervals].last = last; + psi->nintervals++; + assert(psi->nintervals <= psi->size); + if (pExtSetInfo) + { + SetInfoPtr pesi = pExtSetInfo; + CARD16 *pCARD16 = (CARD16 *)(pCARD8 + 2); + int j; + + for (j = 0; j < *pnExtSetInfo; j++, pesi++) + { + if ( (first == pesi->first) && (last == pesi->last) ) + break; + } + if (j == *pnExtSetInfo) + { + err = RecordAllocIntervals(pesi, 2 * (nRanges - i)); + if (err != Success) + return err; + pesi->first = first; + pesi->last = last; + (*pnExtSetInfo)++; + } + pesi->intervals[pesi->nintervals].first = pCARD16[0]; + pesi->intervals[pesi->nintervals].last = pCARD16[1]; + pesi->nintervals++; + assert(pesi->nintervals <= pesi->size); + } + } + } + return Success; +} /* end RecordConvertRangesToIntervals */ + +#define offset_of(_structure, _field) \ + ((char *)(& (_structure . _field)) - (char *)(&_structure)) + +/* RecordRegisterClients + * + * Arguments: + * pContext is the context on which to register the clients. + * client is the client that issued the RecordCreateContext or + * RecordRegisterClients request. + * stuff is a pointer to the request. + * + * Returns: + * Any one of several possible error values defined by the protocol. + * Success if everything is OK. + * + * Side Effects: + * If different element headers are specified, the context is flushed. + * If any of the specified clients are already registered on the + * context, they are first unregistered. A new RCAP is created to + * hold the specified protocol and clients, and it is linked onto the + * context. If the context is enabled, appropriate hooks are installed + * to record the new clients and protocol. + */ +static int +RecordRegisterClients(pContext, client, stuff) + RecordContextPtr pContext; + ClientPtr client; + xRecordRegisterClientsReq *stuff; +{ + int err; + int i; + SetInfoPtr si; + int maxSets; + int nExtReqSets = 0; + int nExtRepSets = 0; + int extReqSetsOffset; + int extRepSetsOffset; + SetInfoPtr pExtReqSets, pExtRepSets; + int clientListOffset; + XID *pCanonClients; + int clientStarted = 0, clientDied = 0; + xRecordRange *pRanges, rr; + int nClients; + int sizeClients; + int totRCAPsize; + RecordClientsAndProtocolPtr pRCAP; + int pad; + XID recordingClient; + + /* do all sanity checking up front */ + + err = RecordSanityCheckRegisterClients(pContext, client, stuff); + if (err != Success) + return err; + + /* if element headers changed, flush buffer */ + + if (pContext->elemHeaders != stuff->elementHeader) + { + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + pContext->elemHeaders = stuff->elementHeader; + } + + nClients = stuff->nClients; + if (!nClients) + /* if empty clients list, we're done. */ + return Success; + + recordingClient = pContext->pRecordingClient ? + pContext->pRecordingClient->clientAsMask : 0; + pCanonClients = RecordCanonicalizeClientSpecifiers((XID *)&stuff[1], + &nClients, recordingClient); + if (!pCanonClients) + return BadAlloc; + + /* We may have to create as many as one set for each "predefined" + * protocol types, plus one per range for extension reuests, plus one per + * range for extension replies. + */ + maxSets = PREDEFSETS + 2 * stuff->nRanges; + si = (SetInfoPtr)ALLOCATE_LOCAL(sizeof(SetInfoRec) * maxSets); + if (!si) + { + err = BadAlloc; + goto bailout; + } + bzero(si, sizeof(SetInfoRec) * maxSets); + + /* theoretically you must do this because NULL may not be all-bits-zero */ + for (i = 0; i < maxSets; i++) + si[i].intervals = NULL; + + pExtReqSets = si + PREDEFSETS; + pExtRepSets = pExtReqSets + stuff->nRanges; + + pRanges = (xRecordRange *)(((XID *)&stuff[1]) + stuff->nClients); + + err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges, + offset_of(rr, coreRequestsFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges, + offset_of(rr, extRequestsMajorFirst), pExtReqSets, &nExtReqSets); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges, + offset_of(rr, coreRepliesFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges, + offset_of(rr, extRepliesMajorFirst), pExtRepSets, &nExtRepSets); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[ERR], pRanges, stuff->nRanges, + offset_of(rr, errorsFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[DLEV], pRanges, stuff->nRanges, + offset_of(rr, deliveredEventsFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[DEV], pRanges, stuff->nRanges, + offset_of(rr, deviceEventsFirst), NULL, NULL); + if (err != Success) goto bailout; + + /* collect client-started and client-died */ + + for (i = 0; i < stuff->nRanges; i++) + { + if (pRanges[i].clientStarted) clientStarted = TRUE; + if (pRanges[i].clientDied) clientDied = TRUE; + } + + /* We now have all the information collected to create all the sets, + * and we can compute the total memory required for the RCAP. + */ + + totRCAPsize = sizeof(RecordClientsAndProtocolRec); + + /* leave a little room to grow before forcing a separate allocation */ + sizeClients = nClients + CLIENT_ARRAY_GROWTH_INCREMENT; + pad = RecordPadAlign(totRCAPsize, sizeof(XID)); + clientListOffset = totRCAPsize + pad; + totRCAPsize += pad + sizeClients * sizeof(XID); + + if (nExtReqSets) + { + pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr)); + extReqSetsOffset = totRCAPsize + pad; + totRCAPsize += pad + (nExtReqSets + 1) * sizeof(RecordMinorOpRec); + } + if (nExtRepSets) + { + pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr)); + extRepSetsOffset = totRCAPsize + pad; + totRCAPsize += pad + (nExtRepSets + 1) * sizeof(RecordMinorOpRec); + } + + for (i = 0; i < maxSets; i++) + { + if (si[i].nintervals) + { + si[i].size = RecordSetMemoryRequirements( + si[i].intervals, si[i].nintervals, &si[i].align); + pad = RecordPadAlign(totRCAPsize, si[i].align); + si[i].offset = pad + totRCAPsize; + totRCAPsize += pad + si[i].size; + } + } + + /* allocate memory for the whole RCAP */ + + pRCAP = (RecordClientsAndProtocolPtr)xalloc(totRCAPsize); + if (!pRCAP) + { + err = BadAlloc; + goto bailout; + } + + /* fill in the RCAP */ + + pRCAP->pContext = pContext; + pRCAP->pClientIDs = (XID *)((char *)pRCAP + clientListOffset); + pRCAP->numClients = nClients; + pRCAP->sizeClients = sizeClients; + pRCAP->clientIDsSeparatelyAllocated = 0; + for (i = 0; i < nClients; i++) + { + RecordDeleteClientFromContext(pContext, pCanonClients[i]); + pRCAP->pClientIDs[i] = pCanonClients[i]; + } + + /* create all the sets */ + + if (si[REQ].intervals) + { + pRCAP->pRequestMajorOpSet = + RecordCreateSet(si[REQ].intervals, si[REQ].nintervals, + (RecordSetPtr)((char *)pRCAP + si[REQ].offset), si[REQ].size); + } + else pRCAP->pRequestMajorOpSet = NULL; + + if (si[REP].intervals) + { + pRCAP->pReplyMajorOpSet = + RecordCreateSet(si[REP].intervals, si[REP].nintervals, + (RecordSetPtr)((char *)pRCAP + si[REP].offset), si[REP].size); + } + else pRCAP->pReplyMajorOpSet = NULL; + + if (si[ERR].intervals) + { + pRCAP->pErrorSet = + RecordCreateSet(si[ERR].intervals, si[ERR].nintervals, + (RecordSetPtr)((char *)pRCAP + si[ERR].offset), si[ERR].size); + } + else pRCAP->pErrorSet = NULL; + + if (si[DEV].intervals) + { + pRCAP->pDeviceEventSet = + RecordCreateSet(si[DEV].intervals, si[DEV].nintervals, + (RecordSetPtr)((char *)pRCAP + si[DEV].offset), si[DEV].size); + } + else pRCAP->pDeviceEventSet = NULL; + + if (si[DLEV].intervals) + { + pRCAP->pDeliveredEventSet = + RecordCreateSet(si[DLEV].intervals, si[DLEV].nintervals, + (RecordSetPtr)((char *)pRCAP + si[DLEV].offset), si[DLEV].size); + } + else pRCAP->pDeliveredEventSet = NULL; + + if (nExtReqSets) + { + pRCAP->pRequestMinOpInfo = (RecordMinorOpPtr) + ((char *)pRCAP + extReqSetsOffset); + pRCAP->pRequestMinOpInfo[0].count = nExtReqSets; + for (i = 0; i < nExtReqSets; i++, pExtReqSets++) + { + pRCAP->pRequestMinOpInfo[i+1].major.first = pExtReqSets->first; + pRCAP->pRequestMinOpInfo[i+1].major.last = pExtReqSets->last; + pRCAP->pRequestMinOpInfo[i+1].major.pMinOpSet = + RecordCreateSet(pExtReqSets->intervals, + pExtReqSets->nintervals, + (RecordSetPtr)((char *)pRCAP + pExtReqSets->offset), + pExtReqSets->size); + } + } + else pRCAP->pRequestMinOpInfo = NULL; + + if (nExtRepSets) + { + pRCAP->pReplyMinOpInfo = (RecordMinorOpPtr) + ((char *)pRCAP + extRepSetsOffset); + pRCAP->pReplyMinOpInfo[0].count = nExtRepSets; + for (i = 0; i < nExtRepSets; i++, pExtRepSets++) + { + pRCAP->pReplyMinOpInfo[i+1].major.first = pExtRepSets->first; + pRCAP->pReplyMinOpInfo[i+1].major.last = pExtRepSets->last; + pRCAP->pReplyMinOpInfo[i+1].major.pMinOpSet = + RecordCreateSet(pExtRepSets->intervals, + pExtRepSets->nintervals, + (RecordSetPtr)((char *)pRCAP + pExtRepSets->offset), + pExtRepSets->size); + } + } + else pRCAP->pReplyMinOpInfo = NULL; + + pRCAP->clientStarted = clientStarted; + pRCAP->clientDied = clientDied; + + /* link the RCAP onto the context */ + + pRCAP->pNextRCAP = pContext->pListOfRCAP; + pContext->pListOfRCAP = pRCAP; + + if (pContext->pRecordingClient) /* context enabled */ + RecordInstallHooks(pRCAP, 0); + +bailout: + if (si) + { + for (i = 0; i < maxSets; i++) + if (si[i].intervals) + xfree(si[i].intervals); + DEALLOCATE_LOCAL(si); + } + if (pCanonClients && pCanonClients != (XID *)&stuff[1]) + xfree(pCanonClients); + return err; +} /* RecordRegisterClients */ + + +/* Proc functions all take a client argument, execute the request in + * client->requestBuffer, and return a protocol error status. + */ + +static int +ProcRecordQueryVersion(client) + ClientPtr client; +{ + REQUEST(xRecordQueryVersionReq); + xRecordQueryVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xRecordQueryVersionReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.majorVersion = RECORD_MAJOR_VERSION; + rep.minorVersion = RECORD_MINOR_VERSION; + if(client->swapped) + { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + (void)WriteToClient(client, sizeof(xRecordQueryVersionReply), + (char *)&rep); + return (client->noClientException); +} /* ProcRecordQueryVersion */ + + +static int +ProcRecordCreateContext(client) + ClientPtr client; +{ + REQUEST(xRecordCreateContextReq); + RecordContextPtr pContext; + RecordContextPtr *ppNewAllContexts = NULL; + int err = BadAlloc; + + REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq); + LEGAL_NEW_RESOURCE(stuff->context, client); + + pContext = (RecordContextPtr)xalloc(sizeof(RecordContextRec)); + if (!pContext) + goto bailout; + + /* make sure there is room in ppAllContexts to store the new context */ + + ppNewAllContexts = (RecordContextPtr *) + xrealloc(ppAllContexts, sizeof(RecordContextPtr) * (numContexts + 1)); + if (!ppNewAllContexts) + goto bailout; + ppAllContexts = ppNewAllContexts; + + pContext->id = stuff->context; + pContext->pRecordingClient = NULL; + pContext->pListOfRCAP = NULL; + pContext->elemHeaders = 0; + pContext->bufCategory = 0; + pContext->numBufBytes = 0; + pContext->pBufClient = NULL; + pContext->continuedReply = 0; + + err = RecordRegisterClients(pContext, client, + (xRecordRegisterClientsReq *)stuff); + if (err != Success) + goto bailout; + + if (AddResource(pContext->id, RTContext, pContext)) + { + ppAllContexts[numContexts++] = pContext; + return Success; + } + else + { + RecordDeleteContext((pointer)pContext, pContext->id); + err = BadAlloc; + } +bailout: + if (pContext) + xfree(pContext); + return err; +} /* ProcRecordCreateContext */ + + +static int +ProcRecordRegisterClients(client) + ClientPtr client; +{ + RecordContextPtr pContext; + REQUEST(xRecordRegisterClientsReq); + + REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + + return RecordRegisterClients(pContext, client, stuff); +} /* ProcRecordRegisterClients */ + + +static int +ProcRecordUnregisterClients(client) + ClientPtr client; +{ + RecordContextPtr pContext; + int err; + REQUEST(xRecordUnregisterClientsReq); + XID *pCanonClients; + int nClients; + int i; + + REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq); + if ((client->req_len << 2) - SIZEOF(xRecordUnregisterClientsReq) != + 4 * stuff->nClients) + return BadLength; + VERIFY_CONTEXT(pContext, stuff->context, client); + err = RecordSanityCheckClientSpecifiers((XID *)&stuff[1], + stuff->nClients, 0); + if (err != Success) + return err; + + nClients = stuff->nClients; + pCanonClients = RecordCanonicalizeClientSpecifiers((XID *)&stuff[1], + &nClients, 0); + if (!pCanonClients) + return BadAlloc; + + for (i = 0; i < nClients; i++) + { + RecordDeleteClientFromContext(pContext, pCanonClients[i]); + } + if (pCanonClients != (XID *)&stuff[1]) + xfree(pCanonClients); + return Success; +} /* ProcRecordUnregisterClients */ + + +/****************************************************************************/ + +/* stuff for GetContext */ + +/* This is a tactical structure used to hold the xRecordRanges as they are + * being reconstituted from the sets in the RCAPs. + */ + +typedef struct { + xRecordRange *pRanges; /* array of xRecordRanges for one RCAP */ + int size; /* number of elements in pRanges, >= nRanges */ + int nRanges; /* number of occupied element of pRanges */ +} GetContextRangeInfoRec, *GetContextRangeInfoPtr; + + +/* RecordAllocRanges + * + * Arguments: + * pri is a pointer to a GetContextRangeInfoRec to allocate for. + * nRanges is the number of xRecordRanges desired for pri. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, pri->pRanges points to at least nRanges + * ranges. pri->nRanges is set to nRanges. pri->size is the actual + * number of ranges. Newly allocated ranges are zeroed. + */ +static int +RecordAllocRanges(pri, nRanges) + GetContextRangeInfoPtr pri; + int nRanges; +{ + int newsize; + xRecordRange *pNewRange; +#define SZINCR 8 + + newsize = max(pri->size + SZINCR, nRanges); + pNewRange = (xRecordRange *)xrealloc(pri->pRanges, + newsize * sizeof(xRecordRange)); + if (!pNewRange) + return BadAlloc; + + pri->pRanges = pNewRange; + pri->size = newsize; + bzero(&pri->pRanges[pri->size - SZINCR], SZINCR * sizeof(xRecordRange)); + if (pri->nRanges < nRanges) + pri->nRanges = nRanges; + return Success; +} /* RecordAllocRanges */ + + +/* RecordConvertSetToRanges + * + * Arguments: + * pSet is the set to be converted. + * pri is where the result should be stored. + * byteoffset is the offset from the start of an xRecordRange of the + * two vales (first, last) we are interested in. + * card8 is TRUE if the vales are one byte each and FALSE if two bytes + * each. + * imax is the largest set value to store in pri->pRanges. + * pStartIndex, if non-NULL, is the index of the first range in + * pri->pRanges that should be stored to. If NULL, + * start at index 0. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, the slice of pri->pRanges indicated by + * byteoffset and card8 is filled in with the intervals from pSet. + * if pStartIndex was non-NULL, *pStartIndex is filled in with one + * more than the index of the last xRecordRange that was touched. + */ +static int +RecordConvertSetToRanges(pSet, pri, byteoffset, card8, imax, pStartIndex) + RecordSetPtr pSet; + GetContextRangeInfoPtr pri; + int byteoffset; + Bool card8; + unsigned int imax; + int *pStartIndex; +{ + int nRanges; + RecordSetIteratePtr pIter = NULL; + RecordSetInterval interval; + CARD8 *pCARD8; + CARD16 *pCARD16; + int err; + + if (!pSet) + return Success; + + nRanges = pStartIndex ? *pStartIndex : 0; + while (pIter = RecordIterateSet(pSet, pIter, &interval)) + { + if (interval.first > imax) break; + if (interval.last > imax) interval.last = imax; + nRanges++; + if (nRanges > pri->size) + { + err = RecordAllocRanges(pri, nRanges); + if (err != Success) + return err; + } + else + pri->nRanges = max(pri->nRanges, nRanges); + if (card8) + { + pCARD8 = ((CARD8 *)&pri->pRanges[nRanges-1]) + byteoffset; + *pCARD8++ = interval.first; + *pCARD8 = interval.last; + } + else + { + pCARD16 = (CARD16 *) + (((char *)&pri->pRanges[nRanges-1]) + byteoffset); + *pCARD16++ = interval.first; + *pCARD16 = interval.last; + } + } + if (pStartIndex) + *pStartIndex = nRanges; + return Success; +} /* RecordConvertSetToRanges */ + + +/* RecordConvertMinorOpInfoToRanges + * + * Arguments: + * pMinOpInfo is the minor opcode info to convert to xRecordRanges. + * pri is where the result should be stored. + * byteoffset is the offset from the start of an xRecordRange of the + * four vales (CARD8 major_first, CARD8 major_last, + * CARD16 minor_first, CARD16 minor_last) we are going to store. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, the slice of pri->pRanges indicated by + * byteoffset is filled in with the information from pMinOpInfo. + */ +static int +RecordConvertMinorOpInfoToRanges(pMinOpInfo, pri, byteoffset) + RecordMinorOpPtr pMinOpInfo; + GetContextRangeInfoPtr pri; + int byteoffset; +{ + int nsets; + int start; + int i; + int err; + + if (!pMinOpInfo) + return Success; + + nsets = pMinOpInfo->count; + pMinOpInfo++; + start = 0; + for (i = 0; i < nsets; i++) + { + int j, s; + s = start; + err = RecordConvertSetToRanges(pMinOpInfo[i].major.pMinOpSet, pri, + byteoffset + 2, FALSE, 65535, &start); + if (err != Success) return err; + for (j = s; j < start; j++) + { + CARD8 *pCARD8 = ((CARD8 *)&pri->pRanges[j]) + byteoffset; + *pCARD8++ = pMinOpInfo[i].major.first; + *pCARD8 = pMinOpInfo[i].major.last; + } + } + return Success; +} /* RecordConvertMinorOpInfoToRanges */ + + +/* RecordSwapRanges + * + * Arguments: + * pRanges is an array of xRecordRanges. + * nRanges is the number of elements in pRanges. + * + * Returns: nothing. + * + * Side Effects: + * The 16 bit fields of each xRecordRange are byte swapped. + */ +static void +RecordSwapRanges(pRanges, nRanges) + xRecordRange *pRanges; + int nRanges; +{ + int i; + register char n; + for (i = 0; i < nRanges; i++, pRanges++) + { + swaps(&pRanges->extRequestsMinorFirst, n); + swaps(&pRanges->extRequestsMinorLast, n); + swaps(&pRanges->extRepliesMinorFirst, n); + swaps(&pRanges->extRepliesMinorLast, n); + } +} /* RecordSwapRanges */ + + +static int +ProcRecordGetContext(client) + ClientPtr client; +{ + RecordContextPtr pContext; + REQUEST(xRecordGetContextReq); + xRecordGetContextReply rep; + int n; + RecordClientsAndProtocolPtr pRCAP; + int nRCAPs = 0; + GetContextRangeInfoPtr pRangeInfo; + GetContextRangeInfoPtr pri; + int i; + int err; + + REQUEST_SIZE_MATCH(xRecordGetContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + + /* how many RCAPs are there on this context? */ + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + nRCAPs++; + + /* allocate and initialize space for record range info */ + + pRangeInfo = (GetContextRangeInfoPtr)ALLOCATE_LOCAL( + nRCAPs * sizeof(GetContextRangeInfoRec)); + if (!pRangeInfo && nRCAPs > 0) + return BadAlloc; + for (i = 0; i < nRCAPs; i++) + { + pRangeInfo[i].pRanges = NULL; + pRangeInfo[i].size = 0; + pRangeInfo[i].nRanges = 0; + } + + /* convert the RCAP (internal) representation of the recorded protocol + * to the wire protocol (external) representation, storing the information + * for the ith RCAP in pri[i] + */ + + for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; + pRCAP; + pRCAP = pRCAP->pNextRCAP, pri++) + { + xRecordRange rr; + + err = RecordConvertSetToRanges(pRCAP->pRequestMajorOpSet, pri, + offset_of(rr, coreRequestsFirst), TRUE, 127, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pReplyMajorOpSet, pri, + offset_of(rr, coreRepliesFirst), TRUE, 127, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pDeliveredEventSet, pri, + offset_of(rr, deliveredEventsFirst), TRUE, 255, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pDeviceEventSet, pri, + offset_of(rr, deviceEventsFirst), TRUE, 255, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pErrorSet, pri, + offset_of(rr, errorsFirst), TRUE, 255, NULL); + if (err != Success) goto bailout; + + err = RecordConvertMinorOpInfoToRanges(pRCAP->pRequestMinOpInfo, + pri, offset_of(rr, extRequestsMajorFirst)); + if (err != Success) goto bailout; + + err = RecordConvertMinorOpInfoToRanges(pRCAP->pReplyMinOpInfo, + pri, offset_of(rr, extRepliesMajorFirst)); + if (err != Success) goto bailout; + + if (pRCAP->clientStarted || pRCAP->clientDied) + { + if (pri->nRanges == 0) + RecordAllocRanges(pri, 1); + pri->pRanges[0].clientStarted = pRCAP->clientStarted; + pri->pRanges[0].clientDied = pRCAP->clientDied; + } + } + + /* calculate number of clients and reply length */ + + rep.nClients = 0; + rep.length = 0; + for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; + pRCAP; + pRCAP = pRCAP->pNextRCAP, pri++) + { + rep.nClients += pRCAP->numClients; + rep.length += pRCAP->numClients * + ( (sizeof(xRecordClientInfo) >> 2) + + pri->nRanges * (sizeof(xRecordRange) >> 2)); + } + + /* write the reply header */ + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.enabled = pContext->pRecordingClient != NULL; + rep.elementHeader = pContext->elemHeaders; + if(client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.nClients, n); + } + (void)WriteToClient(client, sizeof(xRecordGetContextReply), + (char *)&rep); + + /* write all the CLIENT_INFOs */ + + for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; + pRCAP; + pRCAP = pRCAP->pNextRCAP, pri++) + { + xRecordClientInfo rci; + rci.nRanges = pri->nRanges; + if (client->swapped) + { + swapl(&rci.nRanges, n); + RecordSwapRanges(pri->pRanges, pri->nRanges); + } + for (i = 0; i < pRCAP->numClients; i++) + { + rci.clientResource = pRCAP->pClientIDs[i]; + if (client->swapped) swapl(&rci.clientResource, n); + WriteToClient(client, sizeof(xRecordClientInfo), (char *)&rci); + WriteToClient(client, sizeof(xRecordRange) * pri->nRanges, + (char *)pri->pRanges); + } + } + err = client->noClientException; + +bailout: + for (i = 0; i < nRCAPs; i++) + { + if (pRangeInfo[i].pRanges) xfree(pRangeInfo[i].pRanges); + } + DEALLOCATE_LOCAL(pRangeInfo); + return err; +} /* ProcRecordGetContext */ + + +static int +ProcRecordEnableContext(client) + ClientPtr client; +{ + RecordContextPtr pContext; + REQUEST(xRecordEnableContextReq); + int i; + RecordClientsAndProtocolPtr pRCAP; + + REQUEST_SIZE_MATCH(xRecordGetContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + if (pContext->pRecordingClient) + return BadMatch; /* already enabled */ + + /* install record hooks for each RCAP */ + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + int err = RecordInstallHooks(pRCAP, 0); + if (err != Success) + { /* undo the previous installs */ + RecordClientsAndProtocolPtr pUninstallRCAP; + for (pUninstallRCAP = pContext->pListOfRCAP; + pUninstallRCAP != pRCAP; + pUninstallRCAP = pUninstallRCAP->pNextRCAP) + { + RecordUninstallHooks(pUninstallRCAP, 0); + } + return err; + } + } + + /* Disallow further request processing on this connection until + * the context is disabled. + */ + IgnoreClient(client); + pContext->pRecordingClient = client; + + /* Don't allow the data connection to record itself; unregister it. */ + RecordDeleteClientFromContext(pContext, + pContext->pRecordingClient->clientAsMask); + + /* move the newly enabled context to the front part of ppAllContexts, + * where all the enabled contexts are + */ + i = RecordFindContextOnAllContexts(pContext); + assert(i >= numEnabledContexts); + if (i != numEnabledContexts) + { + ppAllContexts[i] = ppAllContexts[numEnabledContexts]; + ppAllContexts[numEnabledContexts] = pContext; + } + + ++numEnabledContexts; + assert(numEnabledContexts > 0); + + /* send StartOfData */ + RecordAProtocolElement(pContext, NULL, XRecordStartOfData, NULL, 0, 0); + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + return Success; +} /* ProcRecordEnableContext */ + + +/* RecordDisableContext + * + * Arguments: + * pContext is the context to disable. + * nRanges is the number of elements in pRanges. + * + * Returns: nothing. + * + * Side Effects: + * If the context was enabled, it is disabled. An EndOfData + * message is sent to the recording client. Recording hooks for + * this context are uninstalled. The context is moved to the + * rear part of the ppAllContexts array. numEnabledContexts is + * decremented. Request processing for the formerly recording client + * is resumed. + */ +static void +RecordDisableContext(pContext) + RecordContextPtr pContext; +{ + RecordClientsAndProtocolPtr pRCAP; + int i; + + if (!pContext->pRecordingClient) return; + if (!pContext->pRecordingClient->clientGone) + { + RecordAProtocolElement(pContext, NULL, XRecordEndOfData, NULL, 0, 0); + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + /* Re-enable request processing on this connection. */ + AttendClient(pContext->pRecordingClient); + } + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + RecordUninstallHooks(pRCAP, 0); + } + + pContext->pRecordingClient = NULL; + + /* move the newly disabled context to the rear part of ppAllContexts, + * where all the disabled contexts are + */ + i = RecordFindContextOnAllContexts(pContext); + assert( (i != -1) && (i < numEnabledContexts) ); + if (i != (numEnabledContexts - 1) ) + { + ppAllContexts[i] = ppAllContexts[numEnabledContexts-1]; + ppAllContexts[numEnabledContexts-1] = pContext; + } + --numEnabledContexts; + assert(numEnabledContexts >= 0); +} /* RecordDisableContext */ + + +static int +ProcRecordDisableContext(client) + ClientPtr client; +{ + RecordContextPtr pContext; + REQUEST(xRecordDisableContextReq); + + REQUEST_SIZE_MATCH(xRecordDisableContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + RecordDisableContext(pContext); + return Success; +} /* ProcRecordDisableContext */ + + +/* RecordDeleteContext + * + * Arguments: + * value is the context to delete. + * id is its resource ID. + * + * Returns: Success. + * + * Side Effects: + * Disables the context, frees all associated memory, and removes + * it from the ppAllContexts array. + */ +static int +RecordDeleteContext(value, id) + pointer value; + XID id; +{ + int i; + RecordContextPtr pContext = (RecordContextPtr)value; + RecordClientsAndProtocolPtr pRCAP; + + RecordDisableContext(pContext); + + /* Remove all the clients from all the RCAPs. + * As a result, the RCAPs will be freed. + */ + + while (pRCAP = pContext->pListOfRCAP) + { + int numClients = pRCAP->numClients; + /* when the last client is deleted, the RCAP will go away. */ + while(numClients--) + { + RecordDeleteClientFromRCAP(pRCAP, numClients); + } + } + + xfree(pContext); + + /* remove context from AllContexts list */ + + if (-1 != (i = RecordFindContextOnAllContexts(pContext))) + { + ppAllContexts[i] = ppAllContexts[numContexts - 1]; + if (--numContexts == 0) + { + xfree(ppAllContexts); + ppAllContexts = NULL; + } + } + return Success; +} /* RecordDeleteContext */ + + +static int +ProcRecordFreeContext(client) + ClientPtr client; +{ + RecordContextPtr pContext; + REQUEST(xRecordFreeContextReq); + + REQUEST_SIZE_MATCH(xRecordFreeContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + FreeResource(stuff->context, RT_NONE); + return Success; +} /* ProcRecordFreeContext */ + + +static int +ProcRecordDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_RecordQueryVersion: + return ProcRecordQueryVersion(client); + case X_RecordCreateContext: + return ProcRecordCreateContext(client); + case X_RecordRegisterClients: + return ProcRecordRegisterClients(client); + case X_RecordUnregisterClients: + return ProcRecordUnregisterClients(client); + case X_RecordGetContext: + return ProcRecordGetContext(client); + case X_RecordEnableContext: + return ProcRecordEnableContext(client); + case X_RecordDisableContext: + return ProcRecordDisableContext(client); + case X_RecordFreeContext: + return ProcRecordFreeContext(client); + default: + return BadRequest; + } +} /* ProcRecordDispatch */ + + +static int +SProcRecordQueryVersion(client) + ClientPtr client; +{ + REQUEST(xRecordQueryVersionReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordQueryVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion,n); + return ProcRecordQueryVersion(client); +} /* SProcRecordQueryVersion */ + + +static void +SwapCreateRegister(stuff) + xRecordRegisterClientsReq *stuff; +{ + register char n; + int i; + XID *pClientID; + xRecordRange *pRange; + + swapl(&stuff->context, n); + swapl(&stuff->nClients, n); + swapl(&stuff->nRanges, n); + pClientID = (XID *)&stuff[1]; + for (i = 0; i < stuff->nClients; i++, pClientID++) + { + swapl(pClientID, n); + } + pRange = (xRecordRange *)pClientID; + RecordSwapRanges((xRecordRange *)pClientID, stuff->nRanges); +} /* SwapCreateRegister */ + + +static int +SProcRecordCreateContext(client) + ClientPtr client; +{ + REQUEST(xRecordCreateContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq); + SwapCreateRegister(stuff); + return ProcRecordCreateContext(client); +} /* SProcRecordCreateContext */ + + +static int +SProcRecordRegisterClients(client) + ClientPtr client; +{ + REQUEST(xRecordRegisterClientsReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq); + SwapCreateRegister(stuff); + return ProcRecordRegisterClients(client); +} /* SProcRecordRegisterClients */ + + +static int +SProcRecordUnregisterClients(client) + ClientPtr client; +{ + REQUEST(xRecordUnregisterClientsReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq); + swapl(&stuff->context, n); + swapl(&stuff->nClients, n); + SwapRestL(stuff); + return ProcRecordUnregisterClients(client); +} /* SProcRecordUnregisterClients */ + + +static int +SProcRecordGetContext(client) + ClientPtr client; +{ + REQUEST(xRecordGetContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordGetContextReq); + swapl(&stuff->context, n); + return ProcRecordGetContext(client); +} /* SProcRecordGetContext */ + +static int +SProcRecordEnableContext(client) + ClientPtr client; +{ + REQUEST(xRecordEnableContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordEnableContextReq); + swapl(&stuff->context, n); + return ProcRecordEnableContext(client); +} /* SProcRecordEnableContext */ + + +static int +SProcRecordDisableContext(client) + ClientPtr client; +{ + REQUEST(xRecordDisableContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordDisableContextReq); + swapl(&stuff->context, n); + return ProcRecordDisableContext(client); +} /* SProcRecordDisableContext */ + + +static int +SProcRecordFreeContext(client) + ClientPtr client; +{ + REQUEST(xRecordFreeContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordFreeContextReq); + swapl(&stuff->context, n); + return ProcRecordFreeContext(client); +} /* SProcRecordFreeContext */ + + +static int +SProcRecordDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_RecordQueryVersion: + return SProcRecordQueryVersion(client); + case X_RecordCreateContext: + return SProcRecordCreateContext(client); + case X_RecordRegisterClients: + return SProcRecordRegisterClients(client); + case X_RecordUnregisterClients: + return SProcRecordUnregisterClients(client); + case X_RecordGetContext: + return SProcRecordGetContext(client); + case X_RecordEnableContext: + return SProcRecordEnableContext(client); + case X_RecordDisableContext: + return SProcRecordDisableContext(client); + case X_RecordFreeContext: + return SProcRecordFreeContext(client); + default: + return BadRequest; + } +} /* SProcRecordDispatch */ + +/* XXX goes in header file */ +extern void SwapConnSetupInfo(), SwapConnSetupPrefix(); + +/* RecordConnectionSetupInfo + * + * Arguments: + * pContext is an enabled context that specifies recording of + * connection setup info. + * pci holds the connection setup info. + * + * Returns: nothing. + * + * Side Effects: + * The connection setup info is sent to the recording client. + */ +static void +RecordConnectionSetupInfo(pContext, pci) + RecordContextPtr pContext; + NewClientInfoRec *pci; +{ + int prefixsize = SIZEOF(xConnSetupPrefix); + int restsize = pci->prefix->length * 4; + + if (pci->client->swapped) + { + char * pConnSetup = (char *)ALLOCATE_LOCAL(prefixsize + restsize); + if (!pConnSetup) + return; + SwapConnSetupPrefix(pci->prefix, pConnSetup); + SwapConnSetupInfo(pci->setup, pConnSetup + prefixsize); + RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, + (pointer)pConnSetup, prefixsize + restsize, 0); + DEALLOCATE_LOCAL(pConnSetup); + } + else + { + /* don't alloc and copy as in the swapped case; just send the + * data in two pieces + */ + RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, + (pointer)pci->prefix, prefixsize, restsize); + RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, + (pointer)pci->setup, restsize, /* continuation */ -1); + } +} /* RecordConnectionSetupInfo */ + + +/* RecordDeleteContext + * + * Arguments: + * pcbl is &ClientStateCallback. + * nullata is NULL. + * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) + * which contains information about client state changes. + * + * Returns: nothing. + * + * Side Effects: + * If a new client has connected and any contexts have specified + * XRecordFutureClients, the new client is registered on those contexts. + * If any of those contexts specify recording of the connection setup + * info, it is recorded. + * + * If an existing client has disconnected, it is deleted from any + * contexts that it was registered on. If any of those contexts + * specified XRecordClientDied, they record a ClientDied protocol element. + * If the disconnectiong client happened to be the data connection of an + * enabled context, the context is disabled. + */ + +static void +RecordAClientStateChange(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + NewClientInfoRec *pci = (NewClientInfoRec *)calldata; + int i; + ClientPtr pClient = pci->client; + + switch (pClient->clientState) + { + case ClientStateRunning: /* new client */ + for (i = 0; i < numContexts; i++) + { + RecordClientsAndProtocolPtr pRCAP; + RecordContextPtr pContext = ppAllContexts[i]; + + if (pRCAP = RecordFindClientOnContext(pContext, + XRecordFutureClients, NULL)) + { + RecordAddClientToRCAP(pRCAP, pClient->clientAsMask); + if (pContext->pRecordingClient && pRCAP->clientStarted) + RecordConnectionSetupInfo(pContext, pci); + } + } + break; + + case ClientStateGone: + case ClientStateRetained: /* client disconnected */ + for (i = 0; i < numContexts; i++) + { + RecordClientsAndProtocolPtr pRCAP; + RecordContextPtr pContext = ppAllContexts[i]; + int pos; + + if (pContext->pRecordingClient == pClient) + RecordDisableContext(pContext); + if (pRCAP = RecordFindClientOnContext(pContext, + pClient->clientAsMask, &pos)) + { + if (pContext->pRecordingClient && pRCAP->clientDied) + RecordAProtocolElement(pContext, pClient, + XRecordClientDied, NULL, 0, 0); + RecordDeleteClientFromRCAP(pRCAP, pos); + } + } + break; + + } /* end switch on client state */ +} /* RecordAClientStateChange */ + + +/* RecordCloseDown + * + * Arguments: + * extEntry is the extension information for RECORD. + * + * Returns: nothing. + * + * Side Effects: + * Performs any cleanup needed by RECORD at server shutdown time. + * + */ +static void +RecordCloseDown(extEntry) + ExtensionEntry *extEntry; +{ + DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL); +} /* RecordCloseDown */ + + +/* RecordExtensionInit + * + * Arguments: none. + * + * Returns: nothing. + * + * Side Effects: + * Enables the RECORD extension if possible. + */ +void +RecordExtensionInit() +{ + ExtensionEntry *extentry; + + RTContext = CreateNewResourceType(RecordDeleteContext); + if (!RTContext) + return; + + RecordClientPrivateIndex = AllocateClientPrivateIndex(); + if (!AllocateClientPrivate(RecordClientPrivateIndex, 0)) + return; + + ppAllContexts = NULL; + numContexts = numEnabledContexts = numEnabledRCAPs = 0; + + if (!AddCallback(&ClientStateCallback, RecordAClientStateChange, NULL)) + return; + + extentry = AddExtension(RECORD_NAME, RecordNumEvents, RecordNumErrors, + ProcRecordDispatch, SProcRecordDispatch, + RecordCloseDown, StandardMinorOpcode); + if (!extentry) + { + DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL); + return; + } + RecordErrorBase = extentry->errorBase; + +} /* RecordExtensionInit */ diff --git a/record/set.c b/record/set.c new file mode 100644 index 000000000..dbaac4f54 --- /dev/null +++ b/record/set.c @@ -0,0 +1,702 @@ +/* $Xorg: set.c,v 1.4 2001/02/09 02:05:27 xorgcvs Exp $ */ + +/* + +Copyright 1995, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + + See the header set.h for a description of the set ADT. + + Implementation Strategy + + A bit vector is an obvious choice to represent the set, but may take + too much memory, depending on the numerically largest member in the + set. One expected common case is for the client to ask for *all* + protocol. This means it would ask for minor opcodes 0 through 65535. + Representing this as a bit vector takes 8K -- and there may be + multiple minor opcode intervals, as many as one per major (extension) + opcode). In such cases, a list-of-intervals representation would be + preferable to reduce memory consumption. Both representations will be + implemented, and RecordCreateSet will decide heuristically which one + to use based on the set members. + + Note: When compiling for use in the server, do not use -DTESTING. + When compiling for stand-alone testing of the set ADT, use -DTESTING. + +*/ + +#ifndef TESTING +#include "misc.h" +#else +#include +#include +#include + +/* stuff that you normally get from the X Server's environment */ + +typedef int Bool; +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef unsigned short CARD16; + +#define xalloc malloc +#define xfree free +#define ALLOCATE_LOCAL malloc +#define DEALLOCATE_LOCAL free + +void *Xcalloc(size) + int size; +{ + void *p = malloc(size); + if (p) memset(p, 0, size); + return p; +} + +#ifndef max +#define max(_a, _b) ( ((_a) > (_b)) ? (_a) : (_b) ) +#endif + +#endif /* TESTING */ + +#include "set.h" + +static int +maxMemberInInterval(pIntervals, nIntervals) + RecordSetInterval *pIntervals; + int nIntervals; +{ + int i; + int maxMember = -1; + for (i = 0; i < nIntervals; i++) + { + if (maxMember < (int)pIntervals[i].last) + maxMember = pIntervals[i].last; + } + return maxMember; +} + +static void +NoopDestroySet(pSet) + RecordSetPtr pSet; +{ +} + +/***************************************************************************/ + +/* set operations for bit vector representation */ + +typedef struct { + RecordSetRec baseSet; + int maxMember; + /* followed by the bit vector itself */ +} BitVectorSet, *BitVectorSetPtr; + +#define BITS_PER_LONG (sizeof(unsigned long) * 8) + +static void +BitVectorDestroySet(pSet) + RecordSetPtr pSet; +{ + xfree(pSet); +} + +static unsigned long +BitVectorIsMemberOfSet(pSet, pm) + RecordSetPtr pSet; + int pm; +{ + BitVectorSetPtr pbvs = (BitVectorSetPtr)pSet; + unsigned long *pbitvec; + + if ((int)pm > pbvs->maxMember) return FALSE; + pbitvec = (unsigned long *)(&pbvs[1]); + return (pbitvec[pm / BITS_PER_LONG] & ((unsigned long)1 << (pm % BITS_PER_LONG))); +} + + +static int +BitVectorFindBit(pSet, iterbit, bitval) + RecordSetPtr pSet; + int iterbit; + Bool bitval; +{ + BitVectorSetPtr pbvs = (BitVectorSetPtr)pSet; + unsigned long *pbitvec = (unsigned long *)(&pbvs[1]); + int startlong; + int startbit; + int walkbit; + int maxMember; + unsigned long skipval; + unsigned long bits; + unsigned long usefulbits; + + startlong = iterbit / BITS_PER_LONG; + pbitvec += startlong; + startbit = startlong * BITS_PER_LONG; + skipval = bitval ? 0L : ~0L; + maxMember = pbvs->maxMember; + + + if (startbit > maxMember) return -1; + bits = *pbitvec; + usefulbits = ~(((unsigned long)1 << (iterbit - startbit)) - 1); + if ( (bits & usefulbits) == (skipval & usefulbits) ) + { + pbitvec++; + startbit += BITS_PER_LONG; + + while (startbit <= maxMember && *pbitvec == skipval) + { + pbitvec++; + startbit += BITS_PER_LONG; + } + if (startbit > maxMember) return -1; + } + + walkbit = (startbit < iterbit) ? iterbit - startbit : 0; + + bits = *pbitvec; + while (walkbit < BITS_PER_LONG && ((!(bits & ((unsigned long)1 << walkbit))) == bitval)) + walkbit++; + + return startbit + walkbit; +} + + +static RecordSetIteratePtr +BitVectorIterateSet(pSet, pIter, pInterval) + RecordSetPtr pSet; + RecordSetIteratePtr pIter; + RecordSetInterval *pInterval; +{ + int iterbit = (int)pIter; + int b; + + b = BitVectorFindBit(pSet, iterbit, TRUE); + if (b == -1) return (RecordSetIteratePtr)0; + pInterval->first = b; + + b = BitVectorFindBit(pSet, b, FALSE); + pInterval->last = (b < 0) ? ((BitVectorSetPtr)pSet)->maxMember : b - 1; + return (RecordSetIteratePtr)(pInterval->last + 1); +} + +RecordSetOperations BitVectorSetOperations = { + BitVectorDestroySet, BitVectorIsMemberOfSet, BitVectorIterateSet }; + +RecordSetOperations BitVectorNoFreeOperations = { + NoopDestroySet, BitVectorIsMemberOfSet, BitVectorIterateSet }; + +static int +BitVectorSetMemoryRequirements(pIntervals, nIntervals, maxMember, alignment) + RecordSetInterval *pIntervals; + int nIntervals; + int maxMember; + int *alignment; +{ + int nlongs; + + *alignment = sizeof(unsigned long); + nlongs = (maxMember + BITS_PER_LONG) / BITS_PER_LONG; + return (sizeof(BitVectorSet) + nlongs * sizeof(unsigned long)); +} + +static RecordSetPtr +BitVectorCreateSet(pIntervals, nIntervals, pMem, memsize) + RecordSetInterval *pIntervals; + int nIntervals; + void *pMem; + int memsize; +{ + BitVectorSetPtr pbvs; + int i, j; + unsigned long *pbitvec; + + /* allocate all storage needed by this set in one chunk */ + + if (pMem) + { + memset(pMem, 0, memsize); + pbvs = (BitVectorSetPtr)pMem; + pbvs->baseSet.ops = &BitVectorNoFreeOperations; + } + else + { + pbvs = (BitVectorSetPtr)Xcalloc(memsize); + if (!pbvs) return NULL; + pbvs->baseSet.ops = &BitVectorSetOperations; + } + + pbvs->maxMember = maxMemberInInterval(pIntervals, nIntervals); + + /* fill in the set */ + + pbitvec = (unsigned long *)(&pbvs[1]); + for (i = 0; i < nIntervals; i++) + { + for (j = pIntervals[i].first; j <= (int)pIntervals[i].last; j++) + { + pbitvec[j/BITS_PER_LONG] |= ((unsigned long)1 << (j % BITS_PER_LONG)); + } + } + return (RecordSetPtr)pbvs; +} + + +/***************************************************************************/ + +/* set operations for interval list representation */ + +typedef struct { + RecordSetRec baseSet; + int nIntervals; + /* followed by the intervals (RecordSetInterval) */ +} IntervalListSet, *IntervalListSetPtr; + +static void +IntervalListDestroySet(pSet) + RecordSetPtr pSet; +{ + xfree(pSet); +} + +static unsigned long +IntervalListIsMemberOfSet(pSet, pm) + RecordSetPtr pSet; + int pm; +{ + IntervalListSetPtr prls = (IntervalListSetPtr)pSet; + RecordSetInterval *pInterval = (RecordSetInterval *)(&prls[1]); + int hi, lo, probe; + + /* binary search */ + lo = 0; hi = prls->nIntervals - 1; + while (lo <= hi) + { + probe = (hi + lo) / 2; + if (pm >= pInterval[probe].first && pm <= pInterval[probe].last) return 1; + else if (pm < pInterval[probe].first) hi = probe - 1; + else lo = probe + 1; + } + return 0; +} + + +static RecordSetIteratePtr +IntervalListIterateSet(pSet, pIter, pIntervalReturn) + RecordSetPtr pSet; + RecordSetIteratePtr pIter; + RecordSetInterval *pIntervalReturn; +{ + RecordSetInterval *pInterval = (RecordSetInterval *)pIter; + IntervalListSetPtr prls = (IntervalListSetPtr)pSet; + + if (pInterval == NULL) + { + pInterval = (RecordSetInterval *)(&prls[1]); + } + + if ( (pInterval - (RecordSetInterval *)(&prls[1])) < prls->nIntervals ) + { + *pIntervalReturn = *pInterval; + return (RecordSetIteratePtr)(++pInterval); + } + else + return (RecordSetIteratePtr)NULL; +} + +RecordSetOperations IntervalListSetOperations = { + IntervalListDestroySet, IntervalListIsMemberOfSet, IntervalListIterateSet }; + +RecordSetOperations IntervalListNoFreeOperations = { + NoopDestroySet, IntervalListIsMemberOfSet, IntervalListIterateSet }; + +static int +IntervalListMemoryRequirements(pIntervals, nIntervals, maxMember, alignment) + RecordSetInterval *pIntervals; + int nIntervals; + int maxMember; + int *alignment; +{ + *alignment = sizeof(unsigned long); + return sizeof(IntervalListSet) + nIntervals * sizeof(RecordSetInterval); +} + +static RecordSetPtr +IntervalListCreateSet(pIntervals, nIntervals, pMem, memsize) + RecordSetInterval *pIntervals; + int nIntervals; + void *pMem; + int memsize; +{ + IntervalListSetPtr prls; + int i, j, k; + RecordSetInterval *stackIntervals = NULL; + CARD16 first; + + if (nIntervals > 0) + { + stackIntervals = (RecordSetInterval *)ALLOCATE_LOCAL( + sizeof(RecordSetInterval) * nIntervals); + if (!stackIntervals) return NULL; + + /* sort intervals, store in stackIntervals (insertion sort) */ + + for (i = 0; i < nIntervals; i++) + { + first = pIntervals[i].first; + for (j = 0; j < i; j++) + { + if (first < stackIntervals[j].first) + break; + } + for (k = i; k > j; k--) + { + stackIntervals[k] = stackIntervals[k-1]; + } + stackIntervals[j] = pIntervals[i]; + } + + /* merge abutting/overlapping intervals */ + + for (i = 0; i < nIntervals - 1; ) + { + if ( (stackIntervals[i].last + (unsigned int)1) < + stackIntervals[i + 1].first) + { + i++; /* disjoint intervals */ + } + else + { + stackIntervals[i].last = max(stackIntervals[i].last, + stackIntervals[i + 1].last); + nIntervals--; + for (j = i + 1; j < nIntervals; j++) + stackIntervals[j] = stackIntervals[j + 1]; + } + } + } + + /* allocate and fill in set structure */ + + if (pMem) + { + prls = (IntervalListSetPtr)pMem; + prls->baseSet.ops = &IntervalListNoFreeOperations; + } + else + { + prls = (IntervalListSetPtr) + xalloc(sizeof(IntervalListSet) + nIntervals * sizeof(RecordSetInterval)); + if (!prls) goto bailout; + prls->baseSet.ops = &IntervalListSetOperations; + } + memcpy(&prls[1], stackIntervals, nIntervals * sizeof(RecordSetInterval)); + prls->nIntervals = nIntervals; +bailout: + if (stackIntervals) DEALLOCATE_LOCAL(stackIntervals); + return (RecordSetPtr)prls; +} + +#ifdef TESTING +typedef enum { + BitVectorImplementation, IntervalListImplementation} RecordSetImplementation; + +RecordSetImplementation _RecordSetImpl; + +static void +_RecordForceSetImplementation(setimpl) + RecordSetImplementation setimpl; +{ + _RecordSetImpl = setimpl; +} +#endif + +typedef RecordSetPtr (*RecordCreateSetProcPtr)( +#if NeedNestedPrototypes + RecordSetInterval *pIntervals, + int nIntervals, + void *pMem, + int memsize +#endif +); + +static int +_RecordSetMemoryRequirements(pIntervals, nIntervals, alignment, ppCreateSet) + RecordSetInterval *pIntervals; + int nIntervals; + int *alignment; + RecordCreateSetProcPtr *ppCreateSet; +{ + int bmsize, rlsize, bma, rla; + int maxMember; + + /* find maximum member of set so we know how big to make the bit vector */ + maxMember = maxMemberInInterval(pIntervals, nIntervals); + + bmsize = BitVectorSetMemoryRequirements(pIntervals, nIntervals, maxMember, + &bma); + rlsize = IntervalListMemoryRequirements(pIntervals, nIntervals, maxMember, + &rla); +#ifdef TESTING + if (_RecordSetImpl == BitVectorImplementation) +#else + if ( ( (nIntervals > 1) && (maxMember <= 255) ) + || (bmsize < rlsize) ) +#endif + { + *alignment = bma; + *ppCreateSet = BitVectorCreateSet; + return bmsize; + } + else + { + *alignment = rla; + *ppCreateSet = IntervalListCreateSet; + return rlsize; + } +} + +/***************************************************************************/ + +/* user-visible functions */ + +int +RecordSetMemoryRequirements(pIntervals, nIntervals, alignment) + RecordSetInterval *pIntervals; + int nIntervals; + int *alignment; +{ + RecordCreateSetProcPtr pCreateSet; + return _RecordSetMemoryRequirements(pIntervals, nIntervals, alignment, + &pCreateSet); +} + +RecordSetPtr +RecordCreateSet(pIntervals, nIntervals, pMem, memsize) + RecordSetInterval *pIntervals; + int nIntervals; + void *pMem; + int memsize; +{ + RecordCreateSetProcPtr pCreateSet; + int alignment; + int size; + + size = _RecordSetMemoryRequirements(pIntervals, nIntervals, &alignment, + &pCreateSet); + if (pMem) + { + if ( ((int)pMem & (alignment-1) ) || memsize < size) + return NULL; + } + return (*pCreateSet)(pIntervals, nIntervals, pMem, size); +} + +/***************************************************************************/ + +#ifdef TESTING + +/* + +Test Strategy + +Having two set representations is convenient for testing because we +can play them against each other. The test code will be able to +specify which implementation to use. This breaks the encapsulation, +but that seems acceptable for testing. The crux of the test loop +looks like this: + +loop: + generate random list of Intervals + + create set A using bit vector implementation + create set B using Interval list implementation + + for each possible set member + if set A and set B disagree on whether this is a member error; + + iterate over both sets, comparing the intervals returned by each. + if intervals or number of intervals are different error; + + iterate over intervals of set A + for i = interval.first to interval.last + if i is not a member of set B error; + + iterate over intervals of set B + for i = interval.first to interval.last + if i is not a member of set A error; + + destroy sets A, B + +*/ + +int GenerateRandomIntervals(pIntervals, maxintervals) + RecordSetInterval *pIntervals; + int maxintervals; +{ + int i, nIntervals; + + nIntervals = rand() % maxintervals; + + for (i = 0; i < nIntervals; i++) + { + pIntervals[i].first = rand(); + pIntervals[i].last = pIntervals[i].first + rand(); + } + return nIntervals; +} + +#define MAXINTERVALS 100 + +int main(argc, argv) + int argc; + char **argv; +{ + RecordSetPtr bs, rs; + RecordSetInterval br, rr; + RecordSetIteratePtr bi, ri; + CARD16 i; + int testcount; + RecordSetInterval intervals[MAXINTERVALS]; + int nIntervals; + int bsize, rsize; + int balign, ralign; + int pad; + + for (testcount = 0; 1; testcount++) + { + nIntervals = GenerateRandomIntervals(intervals, MAXINTERVALS); + printf("%d nIntervals %d\n", testcount, nIntervals); + + if (testcount & 1) + { + _RecordForceSetImplementation(BitVectorImplementation); + bsize = RecordSetMemoryRequirements(intervals, nIntervals, &balign); + _RecordForceSetImplementation(IntervalListImplementation); + rsize = RecordSetMemoryRequirements(intervals, nIntervals, &ralign); + pad = (ralign - (bsize & (ralign - 1))) & (ralign - 1); + bs = (RecordSetPtr)xalloc(bsize + pad + rsize ); + if (!bs) + { + fprintf(stderr, "%d: failed to alloc memory for sets\n", + testcount); + continue; + } + rs = (RecordSetPtr)(((char *)bs) + bsize + pad); + } + else + { + bs = rs = NULL; + bsize = rsize = 0; + } + + _RecordForceSetImplementation(BitVectorImplementation); + bs = RecordCreateSet(intervals, nIntervals, bs, bsize); + _RecordForceSetImplementation(IntervalListImplementation); + rs = RecordCreateSet(intervals, nIntervals, rs, rsize); + + if (!bs || !rs) + { + fprintf(stderr, "%d: failed to create sets\n", testcount); + continue; + } + + for (i = 0; i < 65535; i++) + { + unsigned long b, r; + + b = RecordIsMemberOfSet(bs, i); + r = RecordIsMemberOfSet(rs, i); + if ( (b && !r) || (!b && r) ) + { + fprintf(stderr, "%d: isMemberOfSet %d\n", + testcount, (int)i); + } + } + + bi = RecordIterateSet(bs, NULL, &br); + ri = RecordIterateSet(rs, NULL, &rr); + + while (bi && ri) + { + if ( (rr.first != br.first) || (rr.last != br.last) ) + { + fprintf(stderr, "%d: iterateSet interval value mismatch\n", + testcount); + } + bi = RecordIterateSet(bs, bi, &br); + ri = RecordIterateSet(rs, ri, &rr); + } + if (bi != ri) + { + fprintf(stderr, "%d: iterateSet interval count mismatch\n", + testcount); + } + + + bi = NULL; + while (bi = RecordIterateSet(bs, bi, &br)) + { + for (i = br.first; i <= br.last; i++) + { + if (!RecordIsMemberOfSet(rs, i)) + { + fprintf(stderr, "%d: iterateSet b / isMemberOfSet r %d\n", + testcount, (int)i); + } + } + } + + ri = NULL; + while (ri = RecordIterateSet(rs, ri, &rr)) + { + for (i = rr.first; i <= rr.last; i++) + { + if (!RecordIsMemberOfSet(bs, i) ) + { + fprintf(stderr, "%d: iterateSet r / isMemberOfSet b %d\n", + testcount, (int)i); + } + } + } + + RecordDestroySet(bs); + RecordDestroySet(rs); + + if (testcount & 1) + { + xfree(bs); + } + } +} + +#endif /* TESTING */ diff --git a/record/set.h b/record/set.h new file mode 100644 index 000000000..ba4ffccd3 --- /dev/null +++ b/record/set.h @@ -0,0 +1,159 @@ +/* $Xorg: set.h,v 1.4 2001/02/09 02:05:27 xorgcvs Exp $ */ + +/* + +Copyright 1995, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + A Set Abstract Data Type (ADT) for the RECORD Extension + David P. Wiggins + 7/25/95 + + The RECORD extension server code needs to maintain sets of numbers + that designate protocol message types. In most cases the interval of + numbers starts at 0 and does not exceed 255, but in a few cases (minor + opcodes of extension requests) the maximum is 65535. This disparity + suggests that a single set representation may not be suitable for all + sets, especially given that server memory is precious. We introduce a + set ADT to hide implementation differences so that multiple + simultaneous set representations can exist. A single interface is + presented to the set user regardless of the implementation in use for + a particular set. + + The existing RECORD SI appears to require only four set operations: + create (given a list of members), destroy, see if a particular number + is a member of the set, and iterate over the members of a set. Though + many more set operations are imaginable, to keep the code space down, + we won't provide any more operations than are needed. + + The following types and functions/macros define the ADT. +*/ + +/* an interval of set members */ +typedef struct { + CARD16 first; + CARD16 last; +} RecordSetInterval; + +typedef struct _RecordSetRec *RecordSetPtr; /* primary set type */ + +typedef void *RecordSetIteratePtr; + +/* table of function pointers for set operations. + set users should never declare a variable of this type. +*/ +typedef struct { + void (*DestroySet)( +#if NeedNestedPrototypes + RecordSetPtr pSet +#endif +); + unsigned long (*IsMemberOfSet)( +#if NeedNestedPrototypes + RecordSetPtr pSet, + int possible_member +#endif +); + RecordSetIteratePtr (*IterateSet)( +#if NeedNestedPrototypes +RecordSetPtr pSet, + RecordSetIteratePtr pIter, + RecordSetInterval *interval +#endif +); +} RecordSetOperations; + +/* "base class" for sets. + set users should never declare a variable of this type. + */ +typedef struct _RecordSetRec { + RecordSetOperations *ops; +} RecordSetRec; + +RecordSetPtr RecordCreateSet( +#if NeedFunctionPrototypes + RecordSetInterval *intervals, + int nintervals, + void *pMem, + int memsize +#endif +); +/* + RecordCreateSet creates and returns a new set having members specified + by intervals and nintervals. nintervals is the number of RecordSetInterval + structures pointed to by intervals. The elements belonging to the new + set are determined as follows. For each RecordSetInterval structure, the + elements between first and last inclusive are members of the new set. + If a RecordSetInterval's first field is greater than its last field, the + results are undefined. It is valid to create an empty set (nintervals == + 0). If RecordCreateSet returns NULL, the set could not be created due + to resource constraints. +*/ + +int RecordSetMemoryRequirements( +#if NeedFunctionPrototypes + RecordSetInterval * /*pIntervals*/, + int /*nintervals*/, + int * /*alignment*/ +#endif +); + +#define RecordDestroySet(_pSet) \ + /* void */ (*_pSet->ops->DestroySet)(/* RecordSetPtr */ _pSet) +/* + RecordDestroySet frees all resources used by _pSet. _pSet should not be + used after it is destroyed. +*/ + +#define RecordIsMemberOfSet(_pSet, _m) \ + /* unsigned long */ (*_pSet->ops->IsMemberOfSet)(/* RecordSetPtr */ _pSet, \ + /* int */ _m) +/* + RecordIsMemberOfSet returns a non-zero value if _m is a member of + _pSet, else it returns zero. +*/ + +#define RecordIterateSet(_pSet, _pIter, _interval) \ + /* RecordSetIteratePtr */ (*_pSet->ops->IterateSet)(/* RecordSetPtr */ _pSet,\ + /* RecordSetIteratePtr */ _pIter, /* RecordSetInterval */ _interval) +/* + RecordIterateSet returns successive intervals of members of _pSet. If + _pIter is NULL, the first interval of set members is copied into _interval. + The return value should be passed as _pIter in the next call to + RecordIterateSet to obtain the next interval. When the return value is + NULL, there were no more intervals in the set, and nothing is copied into + the _interval parameter. Intervals appear in increasing numerical order + with no overlap between intervals. As such, the list of intervals produced + by RecordIterateSet may not match the list of intervals that were passed + in RecordCreateSet. Typical usage: + + pIter = NULL; + while (pIter = RecordIterateSet(pSet, pIter, &interval)) + { + process interval; + } +*/ diff --git a/xkb/README.compiled b/xkb/README.compiled new file mode 100644 index 000000000..71caa2f63 --- /dev/null +++ b/xkb/README.compiled @@ -0,0 +1,13 @@ + +The X server uses this directory to store the compiled version of the +current keymap and/or any scratch keymaps used by clients. The X server +or some other tool might destroy or replace the files in this directory, +so it is not a safe place to store compiled keymaps for long periods of +time. The default keymap for any server is usually stored in: + X-default.xkm +where is the display number of the server in question, which makes +it possible for several servers *on the same host* to share the same +directory. + +Unless the X server is modified, sharing this directory between servers on +different hosts could cause problems. diff --git a/xkb/XKBAlloc.c b/xkb/XKBAlloc.c new file mode 100644 index 000000000..82e98f4bc --- /dev/null +++ b/xkb/XKBAlloc.c @@ -0,0 +1,587 @@ +/* $Xorg: XKBAlloc.c,v 1.4 2000/08/17 19:44:59 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#ifndef XKB_IN_SERVER + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xlibint.h" +#include "XKBlibint.h" +#include +#include +#include "XKBlibint.h" + +#else + +#include +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include "XKBgeom.h" + +#endif /* XKB_IN_SERVER */ + +/***===================================================================***/ + +/*ARGSUSED*/ +Status +#if NeedFunctionPrototypes +XkbAllocCompatMap(XkbDescPtr xkb,unsigned which,unsigned nSI) +#else +XkbAllocCompatMap(xkb,which,nSI) + XkbDescPtr xkb; + unsigned which; + unsigned nSI; +#endif +{ +XkbCompatMapPtr compat; +XkbSymInterpretRec *prev_interpret; + + if (!xkb) + return BadMatch; + if (xkb->compat) { + if (xkb->compat->size_si>=nSI) + return Success; + compat= xkb->compat; + compat->size_si= nSI; + if (compat->sym_interpret==NULL) + compat->num_si= 0; + prev_interpret = compat->sym_interpret; + compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret, + nSI,XkbSymInterpretRec); + if (compat->sym_interpret==NULL) { + _XkbFree(prev_interpret); + compat->size_si= compat->num_si= 0; + return BadAlloc; + } + if (compat->num_si!=0) { + _XkbClearElems(compat->sym_interpret,compat->num_si, + compat->size_si-1,XkbSymInterpretRec); + } + return Success; + } + compat= _XkbTypedCalloc(1,XkbCompatMapRec); + if (compat==NULL) + return BadAlloc; + if (nSI>0) { + compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec); + if (!compat->sym_interpret) { + _XkbFree(compat); + return BadAlloc; + } + } + compat->size_si= nSI; + compat->num_si= 0; + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + xkb->compat= compat; + return Success; +} + + +void +#if NeedFunctionPrototypes +XkbFreeCompatMap(XkbDescPtr xkb,unsigned which,Bool freeMap) +#else +XkbFreeCompatMap(xkb,which,freeMap) + XkbDescPtr xkb; + unsigned which; + Bool freeMap; +#endif +{ +register XkbCompatMapPtr compat; + + if ((xkb==NULL)||(xkb->compat==NULL)) + return; + compat= xkb->compat; + if (freeMap) + which= XkbAllCompatMask; + if (which&XkbGroupCompatMask) + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + if (which&XkbSymInterpMask) { + if ((compat->sym_interpret)&&(compat->size_si>0)) + _XkbFree(compat->sym_interpret); + compat->size_si= compat->num_si= 0; + compat->sym_interpret= NULL; + } + if (freeMap) { + _XkbFree(compat); + xkb->compat= NULL; + } + return; +} + +/***===================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbAllocNames(XkbDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases) +#else +XkbAllocNames(xkb,which,nTotalRG,nTotalAliases) + XkbDescPtr xkb; + unsigned which; + int nTotalRG; + int nTotalAliases; +#endif +{ +XkbNamesPtr names; + + if (xkb==NULL) + return BadMatch; + if (xkb->names==NULL) { + xkb->names = _XkbTypedCalloc(1,XkbNamesRec); + if (xkb->names==NULL) + return BadAlloc; + } + names= xkb->names; + if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){ + register int i; + XkbKeyTypePtr type; + + type= xkb->map->types; + for (i=0;imap->num_types;i++,type++) { + if (type->level_names==NULL) { + type->level_names= _XkbTypedCalloc(type->num_levels,Atom); + if (type->level_names==NULL) + return BadAlloc; + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code)) + return BadValue; + names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec); + if (names->keys==NULL) + return BadAlloc; + } + if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) { + if (names->key_aliases==NULL) { + names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec); + } + else if (nTotalAliases>names->num_key_aliases) { + XkbKeyAliasRec *prev_aliases = names->key_aliases; + + names->key_aliases= _XkbTypedRealloc(names->key_aliases, + nTotalAliases,XkbKeyAliasRec); + if (names->key_aliases!=NULL) { + _XkbClearElems(names->key_aliases,names->num_key_aliases, + nTotalAliases-1,XkbKeyAliasRec); + } else { + _XkbFree(prev_aliases); + } + } + if (names->key_aliases==NULL) { + names->num_key_aliases= 0; + return BadAlloc; + } + names->num_key_aliases= nTotalAliases; + } + if ((which&XkbRGNamesMask)&&(nTotalRG>0)) { + if (names->radio_groups==NULL) { + names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom); + } + else if (nTotalRG>names->num_rg) { + Atom *prev_radio_groups = names->radio_groups; + + names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG, + Atom); + if (names->radio_groups!=NULL) { + _XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1, + Atom); + } else { + _XkbFree(prev_radio_groups); + } + } + if (names->radio_groups==NULL) + return BadAlloc; + names->num_rg= nTotalRG; + } + return Success; +} + +void +#if NeedFunctionPrototypes +XkbFreeNames(XkbDescPtr xkb,unsigned which,Bool freeMap) +#else +XkbFreeNames(xkb,which,freeMap) + XkbDescPtr xkb; + unsigned which; + Bool freeMap; +#endif +{ +XkbNamesPtr names; + + if ((xkb==NULL)||(xkb->names==NULL)) + return; + names= xkb->names; + if (freeMap) + which= XkbAllNamesMask; + if (which&XkbKTLevelNamesMask) { + XkbClientMapPtr map= xkb->map; + if ((map!=NULL)&&(map->types!=NULL)) { + register int i; + register XkbKeyTypePtr type; + type= map->types; + for (i=0;inum_types;i++,type++) { + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) { + _XkbFree(names->keys); + names->keys= NULL; + names->num_keys= 0; + } + if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){ + _XkbFree(names->key_aliases); + names->key_aliases=NULL; + names->num_key_aliases=0; + } + if ((which&XkbRGNamesMask)&&(names->radio_groups)) { + _XkbFree(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + if (freeMap) { + _XkbFree(names); + xkb->names= NULL; + } + return; +} + +/***===================================================================***/ + +/*ARGSUSED*/ +Status +#if NeedFunctionPrototypes +XkbAllocControls(XkbDescPtr xkb,unsigned which) +#else +XkbAllocControls(xkb,which) + XkbDescPtr xkb; + unsigned which; +#endif +{ + if (xkb==NULL) + return BadMatch; + + if (xkb->ctrls==NULL) { + xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec); + if (!xkb->ctrls) + return BadAlloc; + } + return Success; +} + +/*ARGSUSED*/ +void +#if NeedFunctionPrototypes +XkbFreeControls(XkbDescPtr xkb,unsigned which,Bool freeMap) +#else +XkbFreeControls(xkb,which,freeMap) + XkbDescPtr xkb; + unsigned which; + Bool freeMap; +#endif +{ + if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) { + _XkbFree(xkb->ctrls); + xkb->ctrls= NULL; + } + return; +} + +/***===================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbAllocIndicatorMaps(XkbDescPtr xkb) +#else +XkbAllocIndicatorMaps(xkb) + XkbDescPtr xkb; +#endif +{ + if (xkb==NULL) + return BadMatch; + if (xkb->indicators==NULL) { + xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec); + if (!xkb->indicators) + return BadAlloc; + } + return Success; +} + +void +#if NeedFunctionPrototypes +XkbFreeIndicatorMaps(XkbDescPtr xkb) +#else +XkbFreeIndicatorMaps(xkb) + XkbDescPtr xkb; +#endif +{ + if ((xkb!=NULL)&&(xkb->indicators!=NULL)) { + _XkbFree(xkb->indicators); + xkb->indicators= NULL; + } + return; +} + +/***====================================================================***/ + +XkbDescRec * +#if NeedFunctionPrototypes +XkbAllocKeyboard(void) +#else +XkbAllocKeyboard() +#endif +{ +XkbDescRec *xkb; + + xkb = _XkbTypedCalloc(1,XkbDescRec); + if (xkb) + xkb->device_spec= XkbUseCoreKbd; + return xkb; +} + +void +#if NeedFunctionPrototypes +XkbFreeKeyboard(XkbDescPtr xkb,unsigned which,Bool freeAll) +#else +XkbFreeKeyboard(xkb,which,freeAll) + XkbDescPtr xkb; + unsigned which; + Bool freeAll; +#endif +{ + if (xkb==NULL) + return; + if (freeAll) + which= XkbAllComponentsMask; + if (which&XkbClientMapMask) + XkbFreeClientMap(xkb,XkbAllClientInfoMask,True); + if (which&XkbServerMapMask) + XkbFreeServerMap(xkb,XkbAllServerInfoMask,True); + if (which&XkbCompatMapMask) + XkbFreeCompatMap(xkb,XkbAllCompatMask,True); + if (which&XkbIndicatorMapMask) + XkbFreeIndicatorMaps(xkb); + if (which&XkbNamesMask) + XkbFreeNames(xkb,XkbAllNamesMask,True); + if ((which&XkbGeometryMask) && (xkb->geom!=NULL)) + XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True); + if (which&XkbControlsMask) + XkbFreeControls(xkb,XkbAllControlsMask,True); + if (freeAll) + _XkbFree(xkb); + return; +} + +/***====================================================================***/ + +XkbDeviceLedInfoPtr +#if NeedFunctionPrototypes +XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi,unsigned ledClass,unsigned ledId) +#else +XkbAddDeviceLedInfo(devi,ledClass,ledId) + XkbDeviceInfoPtr devi; + unsigned ledClass; + unsigned ledId; +#endif +{ +XkbDeviceLedInfoPtr devli; +register int i; + + if ((!devi)||(!XkbSingleXIClass(ledClass))||(!XkbSingleXIId(ledId))) + return NULL; + for (i=0,devli=devi->leds;inum_leds;i++,devli++) { + if ((devli->led_class==ledClass)&&(devli->led_id==ledId)) + return devli; + } + if (devi->num_leds>=devi->sz_leds) { + XkbDeviceLedInfoRec *prev_leds = devi->leds; + + if (devi->sz_leds>0) devi->sz_leds*= 2; + else devi->sz_leds= 1; + devi->leds= _XkbTypedRealloc(devi->leds,devi->sz_leds, + XkbDeviceLedInfoRec); + if (!devi->leds) { + _XkbFree(prev_leds); + devi->sz_leds= devi->num_leds= 0; + return NULL; + } + i= devi->num_leds; + for (devli=&devi->leds[i];isz_leds;i++,devli++) { + bzero(devli,sizeof(XkbDeviceLedInfoRec)); + devli->led_class= XkbXINone; + devli->led_id= XkbXINone; + } + } + devli= &devi->leds[devi->num_leds++]; + bzero(devli,sizeof(XkbDeviceLedInfoRec)); + devli->led_class= ledClass; + devli->led_id= ledId; + return devli; +} + +Status +#if NeedFunctionPrototypes +XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi,unsigned newTotal) +#else +XkbResizeDeviceButtonActions(devi,newTotal) + XkbDeviceInfoPtr devi; + unsigned newTotal; +#endif +{ + XkbAction *prev_btn_acts; + + if ((!devi)||(newTotal>255)) + return BadValue; + if ((devi->btn_acts!=NULL)&&(newTotal==devi->num_btns)) + return Success; + if (newTotal==0) { + if (devi->btn_acts!=NULL) { + _XkbFree(devi->btn_acts); + devi->btn_acts= NULL; + } + devi->num_btns= 0; + return Success; + } + prev_btn_acts = devi->btn_acts; + devi->btn_acts= _XkbTypedRealloc(devi->btn_acts,newTotal,XkbAction); + if (devi->btn_acts==NULL) { + _XkbFree(prev_btn_acts); + devi->num_btns= 0; + return BadAlloc; + } + if (newTotal>devi->num_btns) { + XkbAction *act; + act= &devi->btn_acts[devi->num_btns]; + bzero((char *)act,(newTotal-devi->num_btns)*sizeof(XkbAction)); + } + devi->num_btns= newTotal; + return Success; +} + +/*ARGSUSED*/ +XkbDeviceInfoPtr +#if NeedFunctionPrototypes +XkbAllocDeviceInfo(unsigned deviceSpec,unsigned nButtons,unsigned szLeds) +#else +XkbAllocDeviceInfo(deviceSpec,nButtons,szLeds) + unsigned deviceSpec; + unsigned nButtons; + unsigned szLeds; +#endif +{ +XkbDeviceInfoPtr devi; + + devi= _XkbTypedCalloc(1,XkbDeviceInfoRec); + if (devi!=NULL) { + devi->device_spec= deviceSpec; + devi->has_own_state= False; + devi->num_btns= 0; + devi->btn_acts= NULL; + if (nButtons>0) { + devi->num_btns= nButtons; + devi->btn_acts= _XkbTypedCalloc(nButtons,XkbAction); + if (!devi->btn_acts) { + _XkbFree(devi); + return NULL; + } + } + devi->dflt_kbd_fb= XkbXINone; + devi->dflt_led_fb= XkbXINone; + devi->num_leds= 0; + devi->sz_leds= 0; + devi->leds= NULL; + if (szLeds>0) { + devi->sz_leds= szLeds; + devi->leds= _XkbTypedCalloc(szLeds,XkbDeviceLedInfoRec); + if (!devi->leds) { + if (devi->btn_acts) + _XkbFree(devi->btn_acts); + _XkbFree(devi); + return NULL; + } + } + } + return devi; +} + + +void +#if NeedFunctionPrototypes +XkbFreeDeviceInfo(XkbDeviceInfoPtr devi,unsigned which,Bool freeDevI) +#else +XkbFreeDeviceInfo(devi,which,freeDevI) + XkbDeviceInfoPtr devi; + unsigned which; + Bool freeDevI; +#endif +{ + if (devi) { + if (freeDevI) { + which= XkbXI_AllDeviceFeaturesMask; + if (devi->name) { + _XkbFree(devi->name); + devi->name= NULL; + } + } + if ((which&XkbXI_ButtonActionsMask)&&(devi->btn_acts)) { + _XkbFree(devi->btn_acts); + devi->num_btns= 0; + devi->btn_acts= NULL; + } + if ((which&XkbXI_IndicatorsMask)&&(devi->leds)) { + register int i; + if ((which&XkbXI_IndicatorsMask)==XkbXI_IndicatorsMask) { + _XkbFree(devi->leds); + devi->sz_leds= devi->num_leds= 0; + devi->leds= NULL; + } + else { + XkbDeviceLedInfoPtr devli; + for (i=0,devli=devi->leds;inum_leds;i++,devli++) { + if (which&XkbXI_IndicatorMapsMask) + bzero((char *)&devli->maps[0],sizeof(devli->maps)); + else bzero((char *)&devli->names[0],sizeof(devli->names)); + } + } + } + if (freeDevI) + _XkbFree(devi); + } + return; +} diff --git a/xkb/XKBGAlloc.c b/xkb/XKBGAlloc.c new file mode 100644 index 000000000..c89e1197c --- /dev/null +++ b/xkb/XKBGAlloc.c @@ -0,0 +1,1377 @@ +/* $Xorg: XKBGAlloc.c,v 1.3 2000/08/17 19:45:01 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#ifndef XKB_IN_SERVER + +#include +#include "Xlibint.h" +#include "XKBlibint.h" +#include +#include + +#else + +#include +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include "XKBgeom.h" + +#endif /* XKB_IN_SERVER */ + +#ifdef X_NOT_POSIX +#define Size_t unsigned int +#else +#define Size_t size_t +#endif + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbFreeGeomLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz) +#else +_XkbFreeGeomLeafElems(freeAll,first,count,num_inout,sz_inout,elems,elem_sz) + Bool freeAll; + int first; + int count; + unsigned short * num_inout; + unsigned short * sz_inout; + char ** elems; + unsigned int elem_sz; +#endif +{ + if ((freeAll)||(*elems==NULL)) { + *num_inout= *sz_inout= 0; + if (*elems!=NULL) { + _XkbFree(*elems); + *elems= NULL; + } + return; + } + + if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + + if (first+count>=(*num_inout)) { + /* truncating the array is easy */ + (*num_inout)= first; + } + else { + char * ptr; + int extra; + ptr= *elems; + extra= ((*num_inout)-(first+count))*elem_sz; + if (extra>0) + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra); + (*num_inout)-= count; + } + return; +} + +typedef void (*ContentsClearFunc)( +#if NeedFunctionPrototypes + char * /* priv */ +#endif +); + +static void +#if NeedFunctionPrototypes +_XkbFreeGeomNonLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz, + ContentsClearFunc freeFunc) +#else +_XkbFreeGeomNonLeafElems(freeAll,first,count,num_inout,sz_inout,elems,elem_sz, + freeFunc) + Bool freeAll; + int first; + int count; + unsigned short * num_inout; + unsigned short * sz_inout; + char ** elems; + unsigned int elem_sz; + ContentsClearFunc freeFunc; +#endif +{ +register int i; +register char *ptr; + + if (freeAll) { + first= 0; + count= (*num_inout); + } + else if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + else if (first+count>(*num_inout)) + count= (*num_inout)-first; + if (*elems==NULL) + return; + + if (freeFunc) { + ptr= *elems; + ptr+= first*elem_sz; + for (i=0;i=(*num_inout)) + *num_inout= first; + else { + i= ((*num_inout)-(first+count))*elem_sz; + ptr= *elems; + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i); + (*num_inout)-= count; + } + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearProperty(char *prop_in) +#else +_XkbClearProperty(prop_in) + char * prop_in; +#endif +{ +XkbPropertyPtr prop= (XkbPropertyPtr)prop_in; + + if (prop->name) { + _XkbFree(prop->name); + prop->name= NULL; + } + if (prop->value) { + _XkbFree(prop->value); + prop->value= NULL; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomProperties( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +#else +XkbFreeGeomProperties(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_properties,&geom->sz_properties, + (char **)&geom->properties, + sizeof(XkbPropertyRec),_XkbClearProperty); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomKeyAliases( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +#else +XkbFreeGeomKeyAliases(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &geom->num_key_aliases,&geom->sz_key_aliases, + (char **)&geom->key_aliases, + sizeof(XkbKeyAliasRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearColor(char *color_in) +#else +_XkbClearColor(color_in) + char * color_in; +#endif +{ +XkbColorPtr color= (XkbColorPtr)color_in; + + if (color->spec) + _XkbFree(color->spec); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll) +#else +XkbFreeGeomColors(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_colors,&geom->sz_colors, + (char **)&geom->colors, + sizeof(XkbColorRec),_XkbClearColor); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll) +#else +XkbFreeGeomPoints(outline,first,count,freeAll) + XkbOutlinePtr outline; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &outline->num_points,&outline->sz_points, + (char **)&outline->points, + sizeof(XkbPointRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearOutline(char *outline_in) +#else +_XkbClearOutline(outline_in) + char * outline_in; +#endif +{ +XkbOutlinePtr outline= (XkbOutlinePtr)outline_in; + + if (outline->points!=NULL) + XkbFreeGeomPoints(outline,0,outline->num_points,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll) +#else +XkbFreeGeomOutlines(shape,first,count,freeAll) + XkbShapePtr shape; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &shape->num_outlines,&shape->sz_outlines, + (char **)&shape->outlines, + sizeof(XkbOutlineRec),_XkbClearOutline); + + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearShape(char *shape_in) +#else +_XkbClearShape(shape_in) + char * shape_in; +#endif +{ +XkbShapePtr shape= (XkbShapePtr)shape_in; + + if (shape->outlines) + XkbFreeGeomOutlines(shape,0,shape->num_outlines,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll) +#else +XkbFreeGeomShapes(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_shapes,&geom->sz_shapes, + (char **)&geom->shapes, + sizeof(XkbShapeRec),_XkbClearShape); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll) +#else +XkbFreeGeomOverlayKeys(row,first,count,freeAll) + XkbOverlayRowPtr row; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbOverlayKeyRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearOverlayRow(char *row_in) +#else +_XkbClearOverlayRow(row_in) + char * row_in; +#endif +{ +XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomOverlayKeys(row,0,row->num_keys,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll) +#else +XkbFreeGeomOverlayRows(overlay,first,count,freeAll) + XkbOverlayPtr overlay; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &overlay->num_rows,&overlay->sz_rows, + (char **)&overlay->rows, + sizeof(XkbOverlayRowRec),_XkbClearOverlayRow); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearOverlay(char *overlay_in) +#else +_XkbClearOverlay(overlay_in) + char * overlay_in; +#endif +{ +XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in; + + if (overlay->rows!=NULL) + XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll) +#else +XkbFreeGeomOverlays(section,first,count,freeAll) + XkbSectionPtr section; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_overlays,§ion->sz_overlays, + (char **)§ion->overlays, + sizeof(XkbOverlayRec),_XkbClearOverlay); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll) +#else +XkbFreeGeomKeys(row,first,count,freeAll) + XkbRowPtr row; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbKeyRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearRow(char *row_in) +#else +_XkbClearRow(row_in) + char * row_in; +#endif +{ +XkbRowPtr row= (XkbRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomKeys(row,0,row->num_keys,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll) +#else +XkbFreeGeomRows(section,first,count,freeAll) + XkbSectionPtr section; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_rows,§ion->sz_rows, + (char **)§ion->rows, + sizeof(XkbRowRec),_XkbClearRow); +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearSection(char *section_in) +#else +_XkbClearSection(section_in) + char * section_in; +#endif +{ +XkbSectionPtr section= (XkbSectionPtr)section_in; + + if (section->rows!=NULL) + XkbFreeGeomRows(section,0,section->num_rows,True); + if (section->doodads!=NULL) { + XkbFreeGeomDoodads(section->doodads,section->num_doodads,True); + section->doodads= NULL; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll) +#else +XkbFreeGeomSections(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_sections,&geom->sz_sections, + (char **)&geom->sections, + sizeof(XkbSectionRec),_XkbClearSection); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearDoodad(char *doodad_in) +#else +_XkbClearDoodad(doodad_in) + char * doodad_in; +#endif +{ +XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in; + + switch (doodad->any.type) { + case XkbTextDoodad: + { + if (doodad->text.text!=NULL) { + _XkbFree(doodad->text.text); + doodad->text.text= NULL; + } + if (doodad->text.font!=NULL) { + _XkbFree(doodad->text.font); + doodad->text.font= NULL; + } + } + break; + case XkbLogoDoodad: + { + if (doodad->logo.logo_name!=NULL) { + _XkbFree(doodad->logo.logo_name); + doodad->logo.logo_name= NULL; + } + } + break; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll) +#else +XkbFreeGeomDoodads(doodads,nDoodads,freeAll) + XkbDoodadPtr doodads; + int nDoodads; + Bool freeAll; +#endif +{ +register int i; +register XkbDoodadPtr doodad; + + if (doodads) { + for (i=0,doodad= doodads;iproperties!=NULL)) + XkbFreeGeomProperties(geom,0,geom->num_properties,True); + if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL)) + XkbFreeGeomColors(geom,0,geom->num_colors,True); + if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL)) + XkbFreeGeomShapes(geom,0,geom->num_shapes,True); + if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL)) + XkbFreeGeomSections(geom,0,geom->num_sections,True); + if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) { + XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,True); + geom->doodads= NULL; + geom->num_doodads= geom->sz_doodads= 0; + } + if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL)) + XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True); + if (freeMap) { + if (geom->label_font!=NULL) { + _XkbFree(geom->label_font); + geom->label_font= NULL; + } + _XkbFree(geom); + } + return; +} + +/***====================================================================***/ + +static Status +#if NeedFunctionPrototypes +_XkbGeomAlloc( XPointer * old, + unsigned short * num, + unsigned short * total, + int num_new, + Size_t sz_elem) +#else +_XkbGeomAlloc(old,num,total,num_new,sz_elem) + XPointer * old; + unsigned short * num; + unsigned short * total; + int num_new; + Size_t sz_elem; +#endif +{ + if (num_new<1) + return Success; + if ((*old)==NULL) + *num= *total= 0; + + if ((*num)+num_new<=(*total)) + return Success; + + *total= (*num)+num_new; + if ((*old)!=NULL) + (*old)= (XPointer)_XkbRealloc((*old),(*total)*sz_elem); + else (*old)= (XPointer)_XkbCalloc((*total),sz_elem); + if ((*old)==NULL) { + *total= *num= 0; + return BadAlloc; + } + + if (*num>0) { + char *tmp= (char *)(*old); + bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem)); + } + return Success; +} + +#define _XkbAllocProps(g,n) _XkbGeomAlloc((XPointer *)&(g)->properties,\ + &(g)->num_properties,&(g)->sz_properties,\ + (n),sizeof(XkbPropertyRec)) +#define _XkbAllocColors(g,n) _XkbGeomAlloc((XPointer *)&(g)->colors,\ + &(g)->num_colors,&(g)->sz_colors,\ + (n),sizeof(XkbColorRec)) +#define _XkbAllocShapes(g,n) _XkbGeomAlloc((XPointer *)&(g)->shapes,\ + &(g)->num_shapes,&(g)->sz_shapes,\ + (n),sizeof(XkbShapeRec)) +#define _XkbAllocSections(g,n) _XkbGeomAlloc((XPointer *)&(g)->sections,\ + &(g)->num_sections,&(g)->sz_sections,\ + (n),sizeof(XkbSectionRec)) +#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((XPointer *)&(g)->doodads,\ + &(g)->num_doodads,&(g)->sz_doodads,\ + (n),sizeof(XkbDoodadRec)) +#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((XPointer *)&(g)->key_aliases,\ + &(g)->num_key_aliases,&(g)->sz_key_aliases,\ + (n),sizeof(XkbKeyAliasRec)) + +#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((XPointer *)&(s)->outlines,\ + &(s)->num_outlines,&(s)->sz_outlines,\ + (n),sizeof(XkbOutlineRec)) +#define _XkbAllocRows(s,n) _XkbGeomAlloc((XPointer *)&(s)->rows,\ + &(s)->num_rows,&(s)->sz_rows,\ + (n),sizeof(XkbRowRec)) +#define _XkbAllocPoints(o,n) _XkbGeomAlloc((XPointer *)&(o)->points,\ + &(o)->num_points,&(o)->sz_points,\ + (n),sizeof(XkbPointRec)) +#define _XkbAllocKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbKeyRec)) +#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((XPointer *)&(s)->overlays,\ + &(s)->num_overlays,&(s)->sz_overlays,\ + (n),sizeof(XkbOverlayRec)) +#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((XPointer *)&(o)->rows,\ + &(o)->num_rows,&(o)->sz_rows,\ + (n),sizeof(XkbOverlayRowRec)) +#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbOverlayKeyRec)) + +Status +#if NeedFunctionPrototypes +XkbAllocGeomProps(XkbGeometryPtr geom,int nProps) +#else +XkbAllocGeomProps(geom,nProps) + XkbGeometryPtr geom; + int nProps; +#endif +{ + return _XkbAllocProps(geom,nProps); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomColors(XkbGeometryPtr geom,int nColors) +#else +XkbAllocGeomColors(geom,nColors) + XkbGeometryPtr geom; + int nColors; +#endif +{ + return _XkbAllocColors(geom,nColors); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases) +#else +XkbAllocGeomKeyAliases(geom,nKeyAliases) + XkbGeometryPtr geom; + int nKeyAliases; +#endif +{ + return _XkbAllocKeyAliases(geom,nKeyAliases); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes) +#else +XkbAllocGeomShapes(geom,nShapes) + XkbGeometryPtr geom; + int nShapes; +#endif +{ + return _XkbAllocShapes(geom,nShapes); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomSections(XkbGeometryPtr geom,int nSections) +#else +XkbAllocGeomSections(geom,nSections) + XkbGeometryPtr geom; + int nSections; +#endif +{ + return _XkbAllocSections(geom,nSections); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays) +#else +XkbAllocGeomOverlays(section,nOverlays) + XkbSectionPtr section; + int nOverlays; +#endif +{ + return _XkbAllocOverlays(section,nOverlays); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows) +#else +XkbAllocGeomOverlayRows(overlay,nRows) + XkbOverlayPtr overlay; + int nRows; +#endif +{ + return _XkbAllocOverlayRows(overlay,nRows); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys) +#else +XkbAllocGeomOverlayKeys(row,nKeys) + XkbOverlayRowPtr row; + int nKeys; +#endif +{ + return _XkbAllocOverlayKeys(row,nKeys); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads) +#else +XkbAllocGeomDoodads(geom,nDoodads) + XkbGeometryPtr geom; + int nDoodads; +#endif +{ + return _XkbAllocDoodads(geom,nDoodads); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads) +#else +XkbAllocGeomSectionDoodads(section,nDoodads) + XkbSectionPtr section; + int nDoodads; +#endif +{ + return _XkbAllocDoodads(section,nDoodads); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOutlines(XkbShapePtr shape,int nOL) +#else +XkbAllocGeomOutlines(shape,nOL) + XkbShapePtr shape; + int nOL; +#endif +{ + return _XkbAllocOutlines(shape,nOL); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomRows(XkbSectionPtr section,int nRows) +#else +XkbAllocGeomRows(section,nRows) + XkbSectionPtr section; + int nRows; +#endif +{ + return _XkbAllocRows(section,nRows); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts) +#else +XkbAllocGeomPoints(ol,nPts) + XkbOutlinePtr ol; + int nPts; +#endif +{ + return _XkbAllocPoints(ol,nPts); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomKeys(XkbRowPtr row,int nKeys) +#else +XkbAllocGeomKeys(row,nKeys) + XkbRowPtr row; + int nKeys; +#endif +{ + return _XkbAllocKeys(row,nKeys); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes) +#else +XkbAllocGeometry(xkb,sizes) + XkbDescPtr xkb; + XkbGeometrySizesPtr sizes; +#endif +{ +XkbGeometryPtr geom; +Status rtrn; + + if (xkb->geom==NULL) { + xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec); + if (!xkb->geom) + return BadAlloc; + } + geom= xkb->geom; + if ((sizes->which&XkbGeomPropertiesMask)&& + ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomColorsMask)&& + ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomShapesMask)&& + ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomSectionsMask)&& + ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomDoodadsMask)&& + ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomKeyAliasesMask)&& + ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) { + goto BAIL; + } + return Success; +BAIL: + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= NULL; + return rtrn; +} + +/***====================================================================***/ + +XkbPropertyPtr +#if NeedFunctionPrototypes +XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value) +#else +XkbAddGeomProperty(geom,name,value) + XkbGeometryPtr geom; + char * name; + char * value; +#endif +{ +register int i; +register XkbPropertyPtr prop; + + if ((!geom)||(!name)||(!value)) + return NULL; + for (i=0,prop=geom->properties;inum_properties;i++,prop++) { + if ((prop->name)&&(strcmp(name,prop->name)==0)) { + if (prop->value) + _XkbFree(prop->value); + prop->value= (char *)_XkbAlloc(strlen(value)+1); + if (prop->value) + strcpy(prop->value,value); + return prop; + } + } + if ((geom->num_properties>=geom->sz_properties)&& + (_XkbAllocProps(geom,1)!=Success)) { + return NULL; + } + prop= &geom->properties[geom->num_properties]; + prop->name= (char *)_XkbAlloc(strlen(name)+1); + if (!name) + return NULL; + strcpy(prop->name,name); + prop->value= (char *)_XkbAlloc(strlen(value)+1); + if (!value) { + _XkbFree(prop->name); + prop->name= NULL; + return NULL; + } + strcpy(prop->value,value); + geom->num_properties++; + return prop; +} + +XkbKeyAliasPtr +#if NeedFunctionPrototypes +XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr) +#else +XkbAddGeomKeyAlias(geom,aliasStr,realStr) + XkbGeometryPtr geom; + char * aliasStr; + char * realStr; +#endif +{ +register int i; +register XkbKeyAliasPtr alias; + + if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0])) + return NULL; + for (i=0,alias=geom->key_aliases;inum_key_aliases;i++,alias++) { + if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) { + bzero(alias->real,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + return alias; + } + } + if ((geom->num_key_aliases>=geom->sz_key_aliases)&& + (_XkbAllocKeyAliases(geom,1)!=Success)) { + return NULL; + } + alias= &geom->key_aliases[geom->num_key_aliases]; + bzero(alias,sizeof(XkbKeyAliasRec)); + strncpy(alias->alias,aliasStr,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + geom->num_key_aliases++; + return alias; +} + +XkbColorPtr +#if NeedFunctionPrototypes +XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel) +#else +XkbAddGeomColor(geom,spec,pixel) + XkbGeometryPtr geom; + char * spec; + unsigned int pixel; +#endif +{ +register int i; +register XkbColorPtr color; + + if ((!geom)||(!spec)) + return NULL; + for (i=0,color=geom->colors;inum_colors;i++,color++) { + if ((color->spec)&&(strcmp(color->spec,spec)==0)) { + color->pixel= pixel; + return color; + } + } + if ((geom->num_colors>=geom->sz_colors)&& + (_XkbAllocColors(geom,1)!=Success)) { + return NULL; + } + color= &geom->colors[geom->num_colors]; + color->pixel= pixel; + color->spec= (char *)_XkbAlloc(strlen(spec)+1); + if (!color->spec) + return NULL; + strcpy(color->spec,spec); + geom->num_colors++; + return color; +} + +XkbOutlinePtr +#if NeedFunctionPrototypes +XkbAddGeomOutline(XkbShapePtr shape,int sz_points) +#else +XkbAddGeomOutline(shape,sz_points) + XkbShapePtr shape; + int sz_points; +#endif +{ +XkbOutlinePtr outline; + + if ((!shape)||(sz_points<0)) + return NULL; + if ((shape->num_outlines>=shape->sz_outlines)&& + (_XkbAllocOutlines(shape,1)!=Success)) { + return NULL; + } + outline= &shape->outlines[shape->num_outlines]; + bzero(outline,sizeof(XkbOutlineRec)); + if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success)) + return NULL; + shape->num_outlines++; + return outline; +} + +XkbShapePtr +#if NeedFunctionPrototypes +XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines) +#else +XkbAddGeomShape(geom,name,sz_outlines) + XkbGeometryPtr geom; + Atom name; + int sz_outlines; +#endif +{ +XkbShapePtr shape; +register int i; + + if ((!geom)||(!name)||(sz_outlines<0)) + return NULL; + if (geom->num_shapes>0) { + for (shape=geom->shapes,i=0;inum_shapes;i++,shape++) { + if (name==shape->name) + return shape; + } + } + if ((geom->num_shapes>=geom->sz_shapes)&& + (_XkbAllocShapes(geom,1)!=Success)) + return NULL; + shape= &geom->shapes[geom->num_shapes]; + bzero(shape,sizeof(XkbShapeRec)); + if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success)) + return NULL; + shape->name= name; + shape->primary= shape->approx= NULL; + geom->num_shapes++; + return shape; +} + +XkbKeyPtr +#if NeedFunctionPrototypes +XkbAddGeomKey(XkbRowPtr row) +#else +XkbAddGeomKey(row) + XkbRowPtr row; +#endif +{ +XkbKeyPtr key; + if (!row) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys++]; + bzero(key,sizeof(XkbKeyRec)); + return key; +} + +XkbRowPtr +#if NeedFunctionPrototypes +XkbAddGeomRow(XkbSectionPtr section,int sz_keys) +#else +XkbAddGeomRow(section,sz_keys) + XkbSectionPtr section; + int sz_keys; +#endif +{ +XkbRowPtr row; + + if ((!section)||(sz_keys<0)) + return NULL; + if ((section->num_rows>=section->sz_rows)&& + (_XkbAllocRows(section,1)!=Success)) + return NULL; + row= §ion->rows[section->num_rows]; + bzero(row,sizeof(XkbRowRec)); + if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success)) + return NULL; + section->num_rows++; + return row; +} + +XkbSectionPtr +#if NeedFunctionPrototypes +XkbAddGeomSection( XkbGeometryPtr geom, + Atom name, + int sz_rows, + int sz_doodads, + int sz_over) +#else +XkbAddGeomSection(geom,name,sz_rows,sz_doodads,sz_over) + XkbGeometryPtr geom; + Atom name; + int sz_rows; + int sz_doodads; + int sz_over; +#endif +{ +register int i; +XkbSectionPtr section; + + if ((!geom)||(name==None)||(sz_rows<0)) + return NULL; + for (i=0,section=geom->sections;inum_sections;i++,section++) { + if (section->name!=name) + continue; + if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))|| + ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))|| + ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success))) + return NULL; + return section; + } + if ((geom->num_sections>=geom->sz_sections)&& + (_XkbAllocSections(geom,1)!=Success)) + return NULL; + section= &geom->sections[geom->num_sections]; + if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success)) + return NULL; + if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) { + if (section->rows) { + _XkbFree(section->rows); + section->rows= NULL; + section->sz_rows= section->num_rows= 0; + } + return NULL; + } + section->name= name; + geom->num_sections++; + return section; +} + +XkbDoodadPtr +#if NeedFunctionPrototypes +XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name) +#else +XkbAddGeomDoodad(geom,section,name) + XkbGeometryPtr geom; + XkbSectionPtr section; + Atom name; +#endif +{ +XkbDoodadPtr old,doodad; +register int i,nDoodads; + + if ((!geom)||(name==None)) + return NULL; + if ((section!=NULL)&&(section->num_doodads>0)) { + old= section->doodads; + nDoodads= section->num_doodads; + } + else { + old= geom->doodads; + nDoodads= geom->num_doodads; + } + for (i=0,doodad=old;iany.name==name) + return doodad; + } + if (section) { + if ((section->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(section,1)!=Success)) { + return NULL; + } + doodad= §ion->doodads[section->num_doodads++]; + } + else { + if ((geom->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(geom,1)!=Success)) + return NULL; + doodad= &geom->doodads[geom->num_doodads++]; + } + bzero(doodad,sizeof(XkbDoodadRec)); + doodad->any.name= name; + return doodad; +} + +XkbOverlayKeyPtr +#if NeedFunctionPrototypes +XkbAddGeomOverlayKey( XkbOverlayPtr overlay, + XkbOverlayRowPtr row, + char * over, + char * under) +#else +XkbAddGeomOverlayKey(overlay,row,over,under) + XkbOverlayPtr overlay; + XkbOverlayRowPtr row; + char * over; + char * under; +#endif +{ +register int i; +XkbOverlayKeyPtr key; +XkbSectionPtr section; +XkbRowPtr row_under; +Bool found; + + if ((!overlay)||(!row)||(!over)||(!under)) + return NULL; + section= overlay->section_under; + if (row->row_under>=section->num_rows) + return NULL; + row_under= §ion->rows[row->row_under]; + for (i=0,found=False;inum_keys;i++) { + if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) { + found= True; + break; + } + } + if (!found) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys]; + strncpy(key->under.name,under,XkbKeyNameLength); + strncpy(key->over.name,over,XkbKeyNameLength); + row->num_keys++; + return key; +} + +XkbOverlayRowPtr +#if NeedFunctionPrototypes +XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys) +#else +XkbAddGeomOverlayRow(overlay,row_under,sz_keys) + XkbOverlayPtr overlay; + int row_under; + int sz_keys; +#endif +{ +register int i; +XkbOverlayRowPtr row; + + if ((!overlay)||(sz_keys<0)) + return NULL; + if (row_under>=overlay->section_under->num_rows) + return NULL; + for (i=0;inum_rows;i++) { + if (overlay->rows[i].row_under==row_under) { + row= &overlay->rows[i]; + if ((row->sz_keysrows[i]; + } + } + if ((overlay->num_rows>=overlay->sz_rows)&& + (_XkbAllocOverlayRows(overlay,1)!=Success)) + return NULL; + row= &overlay->rows[overlay->num_rows]; + bzero(row,sizeof(XkbOverlayRowRec)); + if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) + return NULL; + row->row_under= row_under; + overlay->num_rows++; + return row; +} + +XkbOverlayPtr +#if NeedFunctionPrototypes +XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows) +#else +XkbAddGeomOverlay(section,name,sz_rows) + XkbSectionPtr section; + Atom name; + int sz_rows; +#endif +{ +register int i; +XkbOverlayPtr overlay; + + if ((!section)||(name==None)||(sz_rows==0)) + return NULL; + + for (i=0,overlay=section->overlays;inum_overlays;i++,overlay++) { + if (overlay->name==name) { + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + return overlay; + } + } + if ((section->num_overlays>=section->sz_overlays)&& + (_XkbAllocOverlays(section,1)!=Success)) + return NULL; + overlay= §ion->overlays[section->num_overlays]; + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + overlay->name= name; + overlay->section_under= section; + section->num_overlays++; + return overlay; +} diff --git a/xkb/XKBMAlloc.c b/xkb/XKBMAlloc.c new file mode 100644 index 000000000..ba2a70761 --- /dev/null +++ b/xkb/XKBMAlloc.c @@ -0,0 +1,1077 @@ +/* $Xorg: XKBMAlloc.c,v 1.4 2000/08/17 19:45:02 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#ifndef XKB_IN_SERVER + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xlibint.h" +#include +#include +#include "XKBlibint.h" + +#else + +#include +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" + +#endif /* XKB_IN_SERVER */ + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes) +#else +XkbAllocClientMap(xkb,which,nTotalTypes) + XkbDescPtr xkb; + unsigned which; + unsigned nTotalTypes; +#endif +{ +register int i; +XkbClientMapPtr map; + + if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypesmin_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code))) { +#ifdef DEBUG +fprintf(stderr,"bad keycode (%d,%d) in XkbAllocClientMap\n", + xkb->min_key_code,xkb->max_key_code); +#endif + return BadValue; + } + + if (xkb->map==NULL) { + map= _XkbTypedCalloc(1,XkbClientMapRec); + if (map==NULL) + return BadAlloc; + xkb->map= map; + } + else map= xkb->map; + + if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) { + if (map->types==NULL) { + map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec); + if (map->types==NULL) + return BadAlloc; + map->num_types= 0; + map->size_types= nTotalTypes; + } + else if (map->size_typestypes; + + map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec); + if (map->types==NULL) { + _XkbFree(prev_types); + map->num_types= map->size_types= 0; + return BadAlloc; + } + map->size_types= nTotalTypes; + bzero(&map->types[map->num_types], + ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec))); + } + } + if (which&XkbKeySymsMask) { + int nKeys= XkbNumKeys(xkb); + if (map->syms==NULL) { + map->size_syms= (nKeys*15)/10; + map->syms= _XkbTypedCalloc(map->size_syms,KeySym); + if (!map->syms) { + map->size_syms= 0; + return BadAlloc; + } + map->num_syms= 1; + map->syms[0]= NoSymbol; + } + if (map->key_sym_map==NULL) { + i= xkb->max_key_code+1; + map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec); + if (map->key_sym_map==NULL) + return BadAlloc; + } + } + if (which&XkbModifierMapMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code)) + return BadMatch; + if (map->modmap==NULL) { + i= xkb->max_key_code+1; + map->modmap= _XkbTypedCalloc(i,unsigned char); + if (map->modmap==NULL) + return BadAlloc; + } + } + return Success; +} + +Status +#if NeedFunctionPrototypes +XkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions) +#else +XkbAllocServerMap(xkb,which,nNewActions) + XkbDescPtr xkb; + unsigned which; + unsigned nNewActions; +#endif +{ +register int i; +XkbServerMapPtr map; + + if (xkb==NULL) + return BadMatch; + if (xkb->server==NULL) { + map= _XkbTypedCalloc(1,XkbServerMapRec); + if (map==NULL) + return BadAlloc; + for (i=0;ivmods[i]= XkbNoModifierMask; + } + xkb->server= map; + } + else map= xkb->server; + if (which&XkbExplicitComponentsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code)) + return BadMatch; + if (map->explicit==NULL) { + i= xkb->max_key_code+1; + map->explicit= _XkbTypedCalloc(i,unsigned char); + if (map->explicit==NULL) + return BadAlloc; + } + } + if (which&XkbKeyActionsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code)) + return BadMatch; + if (nNewActions<1) + nNewActions= 1; + if (map->acts==NULL) { + map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction); + if (map->acts==NULL) + return BadAlloc; + map->num_acts= 1; + map->size_acts= nNewActions+1; + } + else if ((map->size_acts-map->num_acts)acts; + need= map->num_acts+nNewActions; + map->acts= _XkbTypedRealloc(map->acts,need,XkbAction); + if (map->acts==NULL) { + _XkbFree(prev_acts); + map->num_acts= map->size_acts= 0; + return BadAlloc; + } + map->size_acts= need; + bzero(&map->acts[map->num_acts], + ((map->size_acts-map->num_acts)*sizeof(XkbAction))); + } + if (map->key_acts==NULL) { + i= xkb->max_key_code+1; + map->key_acts= _XkbTypedCalloc(i,unsigned short); + if (map->key_acts==NULL) + return BadAlloc; + } + } + if (which&XkbKeyBehaviorsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code)) + return BadMatch; + if (map->behaviors==NULL) { + i= xkb->max_key_code+1; + map->behaviors= _XkbTypedCalloc(i,XkbBehavior); + if (map->behaviors==NULL) + return BadAlloc; + } + } + if (which&XkbVirtualModMapMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code)) + return BadMatch; + if (map->vmodmap==NULL) { + i= xkb->max_key_code+1; + map->vmodmap= _XkbTypedCalloc(i,unsigned short); + if (map->vmodmap==NULL) + return BadAlloc; + } + } + return Success; +} + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into) +#else +XkbCopyKeyType(from,into) + XkbKeyTypePtr from; + XkbKeyTypePtr into; +#endif +{ + if ((!from)||(!into)) + return BadMatch; + if (into->map) { + _XkbFree(into->map); + into->map= NULL; + } + if (into->preserve) { + _XkbFree(into->preserve); + into->preserve= NULL; + } + if (into->level_names) { + _XkbFree(into->level_names); + into->level_names= NULL; + } + *into= *from; + if ((from->map)&&(into->map_count>0)) { + into->map= _XkbTypedCalloc(into->map_count,XkbKTMapEntryRec); + if (!into->map) + return BadAlloc; + memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec)); + } + if ((from->preserve)&&(into->map_count>0)) { + into->preserve= _XkbTypedCalloc(into->map_count,XkbModsRec); + if (!into->preserve) + return BadAlloc; + memcpy(into->preserve,from->preserve, + into->map_count*sizeof(XkbModsRec)); + } + if ((from->level_names)&&(into->num_levels>0)) { + into->level_names= _XkbTypedCalloc(into->num_levels,Atom); + if (!into->level_names) + return BadAlloc; + memcpy(into->level_names,from->level_names, + into->num_levels*sizeof(Atom)); + } + return Success; +} + +Status +#if NeedFunctionPrototypes +XkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types) +#else +XkbCopyKeyTypes(from,into,num_types) + XkbKeyTypePtr from; + XkbKeyTypePtr into; + int num_types; +#endif +{ +register int i,rtrn; + + if ((!from)||(!into)||(num_types<0)) + return BadMatch; + for (i=0;imap; + if ((map)&&(map->types)) { + for (i=0;inum_types;i++) { + if (map->types[i].name==name) { + Status status; + status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls); + return (status==Success?&map->types[i]:NULL); + } + } + } + if ((!map)||(!map->types)||(!map->num_typesnum_types<=XkbKeypadIndex) + tmp|= XkbKeypadMask; + if (map->num_types<=XkbAlphabeticIndex) + tmp|= XkbAlphabeticMask; + if (map->num_types<=XkbTwoLevelIndex) + tmp|= XkbTwoLevelMask; + if (map->num_types<=XkbOneLevelIndex) + tmp|= XkbOneLevelMask; + if (XkbInitCanonicalKeyTypes(xkb,tmp,XkbNoModifier)==Success) { + for (i=0;inum_types;i++) { + Status status; + if (map->types[i].name!=name) + continue; + status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls); + return (status==Success?&map->types[i]:NULL); + } + } + } + if ((map->num_types<=map->size_types)&& + (XkbAllocClientMap(xkb,XkbKeyTypesMask,map->num_types+1)!=Success)) { + return NULL; + } + type= &map->types[map->num_types]; + map->num_types++; + bzero((char *)type,sizeof(XkbKeyTypeRec)); + type->num_levels= num_lvls; + type->map_count= map_count; + type->name= name; + if (map_count>0) { + type->map= _XkbTypedCalloc(map_count,XkbKTMapEntryRec); + if (!type->map) { + map->num_types--; + return NULL; + } + if (want_preserve) { + type->preserve= _XkbTypedCalloc(map_count,XkbModsRec); + if (!type->preserve) { + _XkbFree(type->map); + map->num_types--; + return NULL; + } + } + } + return type; +} + +Status +#if NeedFunctionPrototypes +XkbResizeKeyType( XkbDescPtr xkb, + int type_ndx, + int map_count, + Bool want_preserve, + int new_num_lvls) +#else +XkbResizeKeyType(xkb,type_ndx,map_count,want_preserve,new_num_lvls) + XkbDescPtr xkb; + int type_ndx; + int map_count; + Bool want_preserve; + int new_num_lvls; +#endif +{ +XkbKeyTypePtr type; +KeyCode matchingKeys[XkbMaxKeyCount],nMatchingKeys; + + if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)|| + (new_num_lvls<1)) + return BadValue; + switch (type_ndx) { + case XkbOneLevelIndex: + if (new_num_lvls!=1) + return BadMatch; + break; + case XkbTwoLevelIndex: + case XkbAlphabeticIndex: + case XkbKeypadIndex: + if (new_num_lvls!=2) + return BadMatch; + break; + } + type= &xkb->map->types[type_ndx]; + if (map_count==0) { + if (type->map!=NULL) + _XkbFree(type->map); + type->map= NULL; + if (type->preserve!=NULL) + _XkbFree(type->preserve); + type->preserve= NULL; + type->map_count= 0; + } + else { + XkbKTMapEntryRec *prev_map = type->map; + + if ((map_count>type->map_count)||(type->map==NULL)) + type->map=_XkbTypedRealloc(type->map,map_count,XkbKTMapEntryRec); + if (!type->map) { + if (prev_map) + _XkbFree(prev_map); + return BadAlloc; + } + if (want_preserve) { + XkbModsRec *prev_preserve = type->preserve; + + if ((map_count>type->map_count)||(type->preserve==NULL)) { + type->preserve= _XkbTypedRealloc(type->preserve,map_count, + XkbModsRec); + } + if (!type->preserve) { + if (prev_preserve) + _XkbFree(prev_preserve); + return BadAlloc; + } + } + else if (type->preserve!=NULL) { + _XkbFree(type->preserve); + type->preserve= NULL; + } + type->map_count= map_count; + } + + if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) { + Atom * prev_level_names = type->level_names; + + type->level_names=_XkbTypedRealloc(type->level_names,new_num_lvls,Atom); + if (!type->level_names) { + if (prev_level_names) + _XkbFree(prev_level_names); + return BadAlloc; + } + } + /* + * Here's the theory: + * If the width of the type changed, we might have to resize the symbol + * maps for any keys that use the type for one or more groups. This is + * expensive, so we'll try to cull out any keys that are obviously okay: + * In any case: + * - keys that have a group width <= the old width are okay (because + * they could not possibly have been associated with the old type) + * If the key type increased in size: + * - keys that already have a group width >= to the new width are okay + * + keys that have a group width >= the old width but < the new width + * might have to be enlarged. + * If the key type decreased in size: + * - keys that have a group width > the old width don't have to be + * resized (because they must have some other wider type associated + * with some group). + * + keys that have a group width == the old width might have to be + * shrunk. + * The possibilities marked with '+' require us to examine the key types + * associated with each group for the key. + */ + bzero(matchingKeys,XkbMaxKeyCount*sizeof(KeyCode)); + nMatchingKeys= 0; + if (new_num_lvls>type->num_levels) { + int nTotal; + KeySym * newSyms; + int width,match,nResize; + register int i,g,nSyms; + + nResize= 0; + for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + width= XkbKeyGroupsWidth(xkb,i); + if (widthnum_levels) + continue; + for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { + if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { + matchingKeys[nMatchingKeys++]= i; + match= 1; + } + } + if ((!match)||(width>=new_num_lvls)) + nTotal+= XkbKeyNumSyms(xkb,i); + else { + nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls; + nResize++; + } + } + if (nResize>0) { + int nextMatch; + xkb->map->size_syms= (nTotal*12)/10; + newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym); + if (newSyms==NULL) + return BadAlloc; + nextMatch= 0; + nSyms= 1; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (matchingKeys[nextMatch]==i) { + KeySym *pOld; + nextMatch++; + width= XkbKeyGroupsWidth(xkb,i); + pOld= XkbKeySymsPtr(xkb,i); + for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) { + memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g], + width*sizeof(KeySym)); + } + xkb->map->key_sym_map[i].offset= nSyms; + nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls; + } + else { + memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i), + XkbKeyNumSyms(xkb,i)*sizeof(KeySym)); + xkb->map->key_sym_map[i].offset= nSyms; + nSyms+= XkbKeyNumSyms(xkb,i); + } + } + type->num_levels= new_num_lvls; + _XkbFree(xkb->map->syms); + xkb->map->syms= newSyms; + xkb->map->num_syms= nSyms; + return Success; + } + } + else if (new_num_lvlsnum_levels) { + int width,match; + register int g,i; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + width= XkbKeyGroupsWidth(xkb,i); + if (widthnum_levels) + continue; + for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { + if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { + matchingKeys[nMatchingKeys++]= i; + match= 1; + } + } + } + } + if (nMatchingKeys>0) { + int key,firstClear; + register int i,g; + if (new_num_lvls>type->num_levels) + firstClear= type->num_levels; + else firstClear= new_num_lvls; + for (i=0;i=0;g--) { + if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) { + if (nClear>0) + bzero(&pSyms[g*width+firstClear],nClear*sizeof(KeySym)); + } + } + } + } + type->num_levels= new_num_lvls; + return Success; +} + +KeySym * +#if NeedFunctionPrototypes +XkbResizeKeySyms(XkbDescPtr xkb,int key,int needed) +#else +XkbResizeKeySyms(xkb,key,needed) + XkbDescPtr xkb; + int key; + int needed; +#endif +{ +register int i,nSyms,nKeySyms; +unsigned nOldSyms; +KeySym *newSyms; + + if (needed==0) { + xkb->map->key_sym_map[key].offset= 0; + return xkb->map->syms; + } + nOldSyms= XkbKeyNumSyms(xkb,key); + if (nOldSyms>=(unsigned)needed) { + return XkbKeySymsPtr(xkb,key); + } + if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) { + if (nOldSyms>0) { + memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key), + nOldSyms*sizeof(KeySym)); + } + if ((needed-nOldSyms)>0) { + bzero(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb,key)], + (needed-nOldSyms)*sizeof(KeySym)); + } + xkb->map->key_sym_map[key].offset = xkb->map->num_syms; + xkb->map->num_syms+= needed; + return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; + } + xkb->map->size_syms+= (needed>32?needed:32); + newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym); + if (newSyms==NULL) + return NULL; + newSyms[0]= NoSymbol; + nSyms = 1; + for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { + int nCopy; + + nCopy= nKeySyms= XkbKeyNumSyms(xkb,i); + if ((nKeySyms==0)&&(i!=key)) + continue; + if (i==key) + nKeySyms= needed; + if (nCopy!=0) + memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym)); + if (nKeySyms>nCopy) + bzero(&newSyms[nSyms+nCopy],(nKeySyms-nCopy)*sizeof(KeySym)); + xkb->map->key_sym_map[i].offset = nSyms; + nSyms+= nKeySyms; + } + _XkbFree(xkb->map->syms); + xkb->map->syms = newSyms; + xkb->map->num_syms = nSyms; + return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; +} + +static unsigned +#if NeedFunctionPrototypes +_ExtendRange( unsigned int old_flags, + unsigned int flag, + KeyCode newKC, + KeyCode * old_min, + unsigned char * old_num) +#else +_ExtendRange(old_flags,flag,newKC,old_min,old_num) + unsigned int old_flags; + unsigned int flag; + KeyCode newKC; + KeyCode * old_min; + unsigned char * old_num; +#endif +{ + if ((old_flags&flag)==0) { + old_flags|= flag; + *old_min= newKC; + *old_num= 1; + } + else { + int last= (*old_min)+(*old_num)-1; + if (newKC<*old_min) { + *old_min= newKC; + *old_num= (last-newKC)+1; + } + else if (newKC>last) { + *old_num= (newKC-(*old_min))+1; + } + } + return old_flags; +} + +Status +#if NeedFunctionPrototypes +XkbChangeKeycodeRange( XkbDescPtr xkb, + int minKC, + int maxKC, + XkbChangesPtr changes) +#else +XkbChangeKeycodeRange(xkb,minKC,maxKC,changes) + XkbDescPtr xkb; + int minKC; + int maxKC; + XkbChangesPtr changes; +#endif +{ +int tmp; + + if ((!xkb)||(minKCXkbMaxLegalKeyCode)) + return BadValue; + if (minKC>maxKC) + return BadMatch; + if (minKCmin_key_code) { + if (changes) + changes->map.min_key_code= minKC; + tmp= xkb->min_key_code-minKC; + if (xkb->map) { + if (xkb->map->key_sym_map) { + bzero((char *)&xkb->map->key_sym_map[minKC], + tmp*sizeof(XkbSymMapRec)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeySymsMask,minKC, + &changes->map.first_key_sym, + &changes->map.num_key_syms); + } + } + if (xkb->map->modmap) { + bzero((char *)&xkb->map->modmap[minKC],tmp); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbModifierMapMask,minKC, + &changes->map.first_modmap_key, + &changes->map.num_modmap_keys); + } + } + } + if (xkb->server) { + if (xkb->server->behaviors) { + bzero((char *)&xkb->server->behaviors[minKC], + tmp*sizeof(XkbBehavior)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyBehaviorsMask,minKC, + &changes->map.first_key_behavior, + &changes->map.num_key_behaviors); + } + } + if (xkb->server->key_acts) { + bzero((char *)&xkb->server->key_acts[minKC], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyActionsMask,minKC, + &changes->map.first_key_act, + &changes->map.num_key_acts); + } + } + if (xkb->server->vmodmap) { + bzero((char *)&xkb->server->vmodmap[minKC], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbVirtualModMapMask,minKC, + &changes->map.first_modmap_key, + &changes->map.num_vmodmap_keys); + } + } + } + if ((xkb->names)&&(xkb->names->keys)) { + bzero((char *)&xkb->names->keys[minKC],tmp*sizeof(XkbKeyNameRec)); + if (changes) { + changes->names.changed= _ExtendRange(changes->names.changed, + XkbKeyNamesMask,minKC, + &changes->names.first_key, + &changes->names.num_keys); + } + } + xkb->min_key_code= minKC; + } + if (maxKC>xkb->max_key_code) { + if (changes) + changes->map.max_key_code= maxKC; + tmp= maxKC-xkb->max_key_code; + if (xkb->map) { + if (xkb->map->key_sym_map) { + XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map; + + xkb->map->key_sym_map= _XkbTypedRealloc(xkb->map->key_sym_map, + (maxKC+1),XkbSymMapRec); + if (!xkb->map->key_sym_map) { + _XkbFree(prev_key_sym_map); + return BadAlloc; + } + bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code], + tmp*sizeof(XkbSymMapRec)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeySymsMask,maxKC, + &changes->map.first_key_sym, + &changes->map.num_key_syms); + } + } + if (xkb->map->modmap) { + unsigned char *prev_modmap = xkb->map->modmap; + + xkb->map->modmap= _XkbTypedRealloc(xkb->map->modmap, + (maxKC+1),unsigned char); + if (!xkb->map->modmap) { + _XkbFree(prev_modmap); + return BadAlloc; + } + bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbModifierMapMask,maxKC, + &changes->map.first_modmap_key, + &changes->map.num_modmap_keys); + } + } + } + if (xkb->server) { + if (xkb->server->behaviors) { + XkbBehavior *prev_behaviors = xkb->server->behaviors; + + xkb->server->behaviors=_XkbTypedRealloc(xkb->server->behaviors, + (maxKC+1),XkbBehavior); + if (!xkb->server->behaviors) { + _XkbFree(prev_behaviors); + return BadAlloc; + } + bzero((char *)&xkb->server->behaviors[xkb->max_key_code], + tmp*sizeof(XkbBehavior)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyBehaviorsMask,maxKC, + &changes->map.first_key_behavior, + &changes->map.num_key_behaviors); + } + } + if (xkb->server->key_acts) { + unsigned short *prev_key_acts = xkb->server->key_acts; + + xkb->server->key_acts= _XkbTypedRealloc(xkb->server->key_acts, + (maxKC+1),unsigned short); + if (!xkb->server->key_acts) { + _XkbFree(prev_key_acts); + return BadAlloc; + } + bzero((char *)&xkb->server->key_acts[xkb->max_key_code], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyActionsMask,maxKC, + &changes->map.first_key_act, + &changes->map.num_key_acts); + } + } + if (xkb->server->vmodmap) { + unsigned short *prev_vmodmap = xkb->server->vmodmap; + + xkb->server->vmodmap= _XkbTypedRealloc(xkb->server->vmodmap, + (maxKC+1),unsigned short); + if (!xkb->server->vmodmap) { + _XkbFree(prev_vmodmap); + return BadAlloc; + } + bzero((char *)&xkb->server->vmodmap[xkb->max_key_code], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbVirtualModMapMask,maxKC, + &changes->map.first_modmap_key, + &changes->map.num_vmodmap_keys); + } + } + } + if ((xkb->names)&&(xkb->names->keys)) { + XkbKeyNameRec *prev_keys = xkb->names->keys; + + xkb->names->keys= _XkbTypedRealloc(xkb->names->keys, + (maxKC+1),XkbKeyNameRec); + if (!xkb->names->keys) { + _XkbFree(prev_keys); + return BadAlloc; + } + bzero((char *)&xkb->names->keys[xkb->max_key_code], + tmp*sizeof(XkbKeyNameRec)); + if (changes) { + changes->names.changed= _ExtendRange(changes->names.changed, + XkbKeyNamesMask,maxKC, + &changes->names.first_key, + &changes->names.num_keys); + } + } + xkb->max_key_code= maxKC; + } + return Success; +} + +XkbAction * +#if NeedFunctionPrototypes +XkbResizeKeyActions(XkbDescPtr xkb,int key,int needed) +#else +XkbResizeKeyActions(xkb,key,needed) + XkbDescPtr xkb; + int key; + int needed; +#endif +{ +register int i,nActs; +XkbAction *newActs; + + if (needed==0) { + xkb->server->key_acts[key]= 0; + return NULL; + } + if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed)) + return XkbKeyActionsPtr(xkb,key); + if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) { + xkb->server->key_acts[key]= xkb->server->num_acts; + xkb->server->num_acts+= needed; + return &xkb->server->acts[xkb->server->key_acts[key]]; + } + xkb->server->size_acts= xkb->server->num_acts+needed+8; + newActs = _XkbTypedCalloc(xkb->server->size_acts,XkbAction); + if (newActs==NULL) + return NULL; + newActs[0].type = XkbSA_NoAction; + nActs = 1; + for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { + int nKeyActs,nCopy; + + if ((xkb->server->key_acts[i]==0)&&(i!=key)) + continue; + + nCopy= nKeyActs= XkbKeyNumActions(xkb,i); + if (i==key) { + nKeyActs= needed; + if (needed0) + memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i), + nCopy*sizeof(XkbAction)); + if (nCopyserver->key_acts[i]= nActs; + nActs+= nKeyActs; + } + _XkbFree(xkb->server->acts); + xkb->server->acts = newActs; + xkb->server->num_acts= nActs; + return &xkb->server->acts[xkb->server->key_acts[key]]; +} + +void +#if NeedFunctionPrototypes +XkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap) +#else +XkbFreeClientMap(xkb,what,freeMap) + XkbDescPtr xkb; + unsigned what; + Bool freeMap; +#endif +{ +XkbClientMapPtr map; + + if ((xkb==NULL)||(xkb->map==NULL)) + return; + if (freeMap) + what= XkbAllClientInfoMask; + map= xkb->map; + if (what&XkbKeyTypesMask) { + if (map->types!=NULL) { + if (map->num_types>0) { + register int i; + XkbKeyTypePtr type; + for (i=0,type=map->types;inum_types;i++,type++) { + if (type->map!=NULL) { + _XkbFree(type->map); + type->map= NULL; + } + if (type->preserve!=NULL) { + _XkbFree(type->preserve); + type->preserve= NULL; + } + type->map_count= 0; + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + _XkbFree(map->types); + map->num_types= map->size_types= 0; + map->types= NULL; + } + } + if (what&XkbKeySymsMask) { + if (map->key_sym_map!=NULL) { + _XkbFree(map->key_sym_map); + map->key_sym_map= NULL; + } + if (map->syms!=NULL) { + _XkbFree(map->syms); + map->size_syms= map->num_syms= 0; + map->syms= NULL; + } + } + if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) { + _XkbFree(map->modmap); + map->modmap= NULL; + } + if (freeMap) { + _XkbFree(xkb->map); + xkb->map= NULL; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap) +#else +XkbFreeServerMap(xkb,what,freeMap) + XkbDescPtr xkb; + unsigned what; + Bool freeMap; +#endif +{ +XkbServerMapPtr map; + + if ((xkb==NULL)||(xkb->server==NULL)) + return; + if (freeMap) + what= XkbAllServerInfoMask; + map= xkb->server; + if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) { + _XkbFree(map->explicit); + map->explicit= NULL; + } + if (what&XkbKeyActionsMask) { + if (map->key_acts!=NULL) { + _XkbFree(map->key_acts); + map->key_acts= NULL; + } + if (map->acts!=NULL) { + _XkbFree(map->acts); + map->num_acts= map->size_acts= 0; + map->acts= NULL; + } + } + if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) { + _XkbFree(map->behaviors); + map->behaviors= NULL; + } + if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) { + _XkbFree(map->vmodmap); + map->vmodmap= NULL; + } + + if (freeMap) { + _XkbFree(xkb->server); + xkb->server= NULL; + } + return; +} diff --git a/xkb/XKBMisc.c b/xkb/XKBMisc.c new file mode 100644 index 000000000..45c00692a --- /dev/null +++ b/xkb/XKBMisc.c @@ -0,0 +1,1071 @@ +/* $Xorg: XKBMisc.c,v 1.4 2000/08/17 19:45:02 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#ifndef XKB_IN_SERVER + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xlibint.h" +#include +#include +#include "XKBlibint.h" + +#else + +#include +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" + +#endif /* XKB_IN_SERVER */ + +/***====================================================================***/ + +#define mapSize(m) (sizeof(m)/sizeof(XkbKTMapEntryRec)) +static XkbKTMapEntryRec map2Level[]= { + { True, ShiftMask, 1, ShiftMask, 0 } +}; + +static XkbKTMapEntryRec mapAlpha[]= { + { True, ShiftMask, 1, ShiftMask, 0 }, + { True, LockMask, 0, LockMask, 0 } +}; + +static XkbModsRec preAlpha[]= { + { 0, 0, 0 }, + { LockMask, LockMask, 0 } +}; + +#define NL_VMOD_MASK 0 +static XkbKTMapEntryRec mapKeypad[]= { + { True, ShiftMask, 1, ShiftMask, 0 }, + { False, 0, 1, 0, NL_VMOD_MASK } +}; + +static XkbKeyTypeRec canonicalTypes[XkbNumRequiredTypes] = { + { { 0, 0, 0 }, + 1, /* num_levels */ + 0, /* map_count */ + NULL, NULL, + None, NULL + }, + { { ShiftMask, ShiftMask, 0 }, + 2, /* num_levels */ + mapSize(map2Level), /* map_count */ + map2Level, NULL, + None, NULL + }, + { { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, + 2, /* num_levels */ + mapSize(mapAlpha), /* map_count */ + mapAlpha, preAlpha, + None, NULL + }, + { { ShiftMask, ShiftMask, NL_VMOD_MASK }, + 2, /* num_levels */ + mapSize(mapKeypad), /* map_count */ + mapKeypad, NULL, + None, NULL + } +}; + +Status +#if NeedFunctionPrototypes +XkbInitCanonicalKeyTypes(XkbDescPtr xkb,unsigned which,int keypadVMod) +#else +XkbInitCanonicalKeyTypes(xkb,which,keypadVMod) + XkbDescPtr xkb; + unsigned which; + int keypadVMod; +#endif +{ +XkbClientMapPtr map; +XkbKeyTypePtr from,to; +Status rtrn; + + if (!xkb) + return BadMatch; + rtrn= XkbAllocClientMap(xkb,XkbKeyTypesMask,XkbNumRequiredTypes); + if (rtrn!=Success) + return rtrn; + map= xkb->map; + if ((which&XkbAllRequiredTypes)==0) + return Success; + rtrn= Success; + from= canonicalTypes; + to= map->types; + if (which&XkbOneLevelMask) + rtrn= XkbCopyKeyType(&from[XkbOneLevelIndex],&to[XkbOneLevelIndex]); + if ((which&XkbTwoLevelMask)&&(rtrn==Success)) + rtrn= XkbCopyKeyType(&from[XkbTwoLevelIndex],&to[XkbTwoLevelIndex]); + if ((which&XkbAlphabeticMask)&&(rtrn==Success)) + rtrn= XkbCopyKeyType(&from[XkbAlphabeticIndex],&to[XkbAlphabeticIndex]); + if ((which&XkbKeypadMask)&&(rtrn==Success)) { + XkbKeyTypePtr type; + rtrn= XkbCopyKeyType(&from[XkbKeypadIndex],&to[XkbKeypadIndex]); + type= &to[XkbKeypadIndex]; + if ((keypadVMod>=0)&&(keypadVModmods.vmods= (1<map[0].active= True; + type->map[0].mods.mask= ShiftMask; + type->map[0].mods.real_mods= ShiftMask; + type->map[0].mods.vmods= 0; + type->map[0].level= 1; + type->map[1].active= False; + type->map[1].mods.mask= 0; + type->map[1].mods.real_mods= 0; + type->map[1].mods.vmods= (1<map[1].level= 1; + } + } + return Success; +} + +/***====================================================================***/ + +#define CORE_SYM(i) (imap->num_types)) { + nSyms[i]= xkb->map->types[types_inout[i]].num_levels; + if (nSyms[i]>groupsWidth) + groupsWidth= nSyms[i]; + } + else { + types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ + nSyms[i]= 2; + } + } + if (nSyms[XkbGroup1Index]<2) + nSyms[XkbGroup1Index]= 2; + if (nSyms[XkbGroup2Index]<2) + nSyms[XkbGroup2Index]= 2; + /* Step 2: Copy the symbols from the core ordering to XKB ordering */ + /* symbols in the core are in the order: */ + /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); + for (i=2;i=map_width)&& + ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { + nSyms[XkbGroup3Index]= 0; + nSyms[XkbGroup4Index]= 0; + nGroups= 2; + } + else { + nGroups= 3; + for (i=0;i1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { + KeySym upper,lower; + XConvertCase(syms[0],&lower,&upper); + if (upper!=lower) { + xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; + xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; + if ((protected&(1<=0;i--) { + if (((empty&(1<1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { + if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { + nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; + types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; + memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, + 2*sizeof(KeySym)); + } + else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { + memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], + (char *)xkb_syms_rtrn, + nSyms[XkbGroup1Index]*sizeof(KeySym)); + } + } + + /* step 7: check for all groups identical or all width 1 */ + if (nGroups>1) { + Bool sameType,allOneLevel; + allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); + for (i=1,sameType=True;(allOneLevel||sameType)&&(imap->types[types_inout[i]].num_levels==1); + } + if ((sameType)&& + (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ + register int s; + Bool identical; + for (i=1,identical=True;identical&&(i1)) { + KeySym *syms; + syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; + nSyms[XkbGroup1Index]= 1; + for (i=1;icompat->sym_interpret; + for (i=0;icompat->num_si;i++,interp++) { + if ((interp->sym==NoSymbol)||(sym==interp->sym)) { + int match; + if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) + mods= real_mods; + else mods= 0; + switch (interp->match&XkbSI_OpMask) { + case XkbSI_NoneOf: + match= ((interp->mods&mods)==0); + break; + case XkbSI_AnyOfOrNone: + match= ((mods==0)||((interp->mods&mods)!=0)); + break; + case XkbSI_AnyOf: + match= ((interp->mods&mods)!=0); + break; + case XkbSI_AllOf: + match= ((interp->mods&mods)==interp->mods); + break; + case XkbSI_Exactly: + match= (interp->mods==mods); + break; + default: + match= 0; + break; + } + if (match) { + if (interp->sym!=NoSymbol) { + return interp; + } + else if (rtrn==NULL) { + rtrn= interp; + } + } + } + } + return rtrn; +} + +static void +#if NeedFunctionPrototypes +_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) +#else +_XkbAddKeyChange(pFirst,pNum,newKey) + KeyCode * pFirst; + unsigned char * pNum; + KeyCode newKey; +#endif +{ +KeyCode last; + + last= (*pFirst)+(*pNum); + if (newKey<*pFirst) { + *pFirst= newKey; + *pNum= (last-newKey)+1; + } + else if (newKey>last) { + *pNum= (last-*pFirst)+1; + } + return; +} + +static void +#if NeedFunctionPrototypes +_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) +#else +_XkbSetActionKeyMods(xkb,act,mods) + XkbDescPtr xkb; + XkbAction * act; + unsigned mods; +#endif +{ +unsigned tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (act->mods.flags&XkbSA_UseModMapMods) + act->mods.real_mods= act->mods.mask= mods; + if ((tmp= XkbModActionVMods(&act->mods))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask|= tmp; + } + break; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_UseModMapMods) + act->iso.real_mods= act->iso.mask= mods; + if ((tmp= XkbModActionVMods(&act->iso))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask|= tmp; + } + break; + } + return; +} + +#define IBUF_SIZE 8 + +Bool +#if NeedFunctionPrototypes +XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) +#else +XkbApplyCompatMapToKey(xkb,key,changes) + XkbDescPtr xkb; + KeyCode key; + XkbChangesPtr changes; +#endif +{ +KeySym * syms; +unsigned char explicit,mods; +XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; +int n,nSyms,found; +unsigned changed,tmp; + + if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| + (!xkb->compat)||(!xkb->compat->sym_interpret)|| + (keymin_key_code)||(key>xkb->max_key_code)) { + return False; + } + if (((!xkb->server)||(!xkb->server->key_acts))&& + (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { + return False; + } + changed= 0; /* keeps track of what has changed in _this_ call */ + explicit= xkb->server->explicit[key]; + if (explicit&XkbExplicitInterpretMask) /* nothing to do */ + return True; + mods= (xkb->map->modmap?xkb->map->modmap[key]:0); + nSyms= XkbKeyNumSyms(xkb,key); + syms= XkbKeySymsPtr(xkb,key); + if (nSyms>IBUF_SIZE) { + interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr); + if (interps==NULL) { + interps= ibuf; + nSyms= IBUF_SIZE; + } + } + else { + interps= ibuf; + } + found= 0; + for (n=0;nact.type!=XkbSA_NoAction) + found++; + else interps[n]= NULL; + } + } + /* 1/28/96 (ef) -- XXX! WORKING HERE */ + if (!found) { + if (xkb->server->key_acts[key]!=0) { + xkb->server->key_acts[key]= 0; + changed|= XkbKeyActionsMask; + } + } + else { + XkbAction *pActs; + unsigned int new_vmodmask; + changed|= XkbKeyActionsMask; + pActs= XkbResizeKeyActions(xkb,key,nSyms); + if (!pActs) + return False; + new_vmodmask= 0; + for (n=0;nact); + if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { + effMods= mods; + if (interps[n]->virtual_mod!=XkbNoModifier) + new_vmodmask|= (1<virtual_mod); + } + else effMods= 0; + _XkbSetActionKeyMods(xkb,&pActs[n],effMods); + } + else pActs[n].type= XkbSA_NoAction; + } + if (((explicit&XkbExplicitVModMapMask)==0)&& + (xkb->server->vmodmap[key]!=new_vmodmask)) { + changed|= XkbVirtualModMapMask; + xkb->server->vmodmap[key]= new_vmodmask; + } + if (interps[0]) { + if ((interps[0]->flags&XkbSI_LockingKey)&& + ((explicit&XkbExplicitBehaviorMask)==0)) { + xkb->server->behaviors[key].type= XkbKB_Lock; + changed|= XkbKeyBehaviorsMask; + } + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; + if (interps[0]->flags&XkbSI_AutoRepeat) + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + } + } + if ((!found)||(interps[0]==NULL)) { + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; +#if RETURN_SHOULD_REPEAT + if (*XkbKeySymsPtr(xkb,key) != XK_Return) +#endif + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + if (((explicit&XkbExplicitBehaviorMask)==0)&& + (xkb->server->behaviors[key].type==XkbKB_Lock)) { + xkb->server->behaviors[key].type= XkbKB_Default; + changed|= XkbKeyBehaviorsMask; + } + } + if (changes) { + XkbMapChangesPtr mc; + mc= &changes->map; + tmp= (changed&mc->changed); + if (tmp&XkbKeyActionsMask) + _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); + else if (changed&XkbKeyActionsMask) { + mc->changed|= XkbKeyActionsMask; + mc->first_key_act= key; + mc->num_key_acts= 1; + } + if (tmp&XkbKeyBehaviorsMask) { + _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, + key); + } + else if (changed&XkbKeyBehaviorsMask) { + mc->changed|= XkbKeyBehaviorsMask; + mc->first_key_behavior= key; + mc->num_key_behaviors= 1; + } + if (tmp&XkbVirtualModMapMask) + _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); + else if (changed&XkbVirtualModMapMask) { + mc->changed|= XkbVirtualModMapMask; + mc->first_vmodmap_key= key; + mc->num_vmodmap_keys= 1; + } + mc->changed|= changed; + } + if (interps!=ibuf) + _XkbFree(interps); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbUpdateMapFromCore( XkbDescPtr xkb, + KeyCode first_key, + int num_keys, + int map_width, + KeySym * core_keysyms, + XkbChangesPtr changes) +#else +XkbUpdateMapFromCore(xkb,first_key,num_keys,map_width,core_keysyms,changes) + XkbDescPtr xkb; + KeyCode first_key; + int num_keys; + int map_width; + KeySym * core_keysyms; + XkbChangesPtr changes; +#endif +{ +register int key,last_key; +KeySym * syms; + + syms= &core_keysyms[(first_key-xkb->min_key_code)*map_width]; + if (changes) { + if (changes->map.changed&XkbKeySymsMask) { + _XkbAddKeyChange(&changes->map.first_key_sym, + &changes->map.num_key_syms,first_key); + if (num_keys>1) { + _XkbAddKeyChange(&changes->map.first_key_sym, + &changes->map.num_key_syms, + first_key+num_keys-1); + } + } + else { + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym= first_key; + changes->map.num_key_syms= num_keys; + } + } + last_key= first_key+num_keys-1; + for (key=first_key;key<=last_key;key++,syms+= map_width) { + XkbMapChangesPtr mc; + unsigned explicit; + KeySym tsyms[XkbMaxSymsPerKey]; + int types[XkbNumKbdGroups]; + int nG; + + explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; + types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); + types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); + types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); + nG= XkbKeyTypesForCoreSymbols(xkb,map_width,syms,explicit,types,tsyms); + if (changes) + mc= &changes->map; + else mc= NULL; + XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); + memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, + XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + XkbApplyCompatMapToKey(xkb,key,changes); + } + + if ((xkb->server->vmods!=NULL)&&(xkb->map->modmap!=NULL)&&(changes)&& + (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask))) { + unsigned char newVMods[XkbNumVirtualMods]; + register unsigned bit,i; + unsigned present; + + bzero(newVMods,XkbNumVirtualMods); + present= 0; + for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { + if (xkb->server->vmodmap[key]==0) + continue; + for (i=0,bit=1;iserver->vmodmap[key]) { + present|= bit; + newVMods[i]|= xkb->map->modmap[key]; + } + } + } + for (i=0,bit=1;iserver->vmods[i])) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + xkb->server->vmods[i]= newVMods[i]; + } + } + } + if (changes && (changes->map.changed&XkbVirtualModsMask)) + XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); + return True; +} + +Status +#if NeedFunctionPrototypes +XkbChangeTypesOfKey( XkbDescPtr xkb, + int key, + int nGroups, + unsigned groups, + int * newTypesIn, + XkbMapChangesPtr changes) +#else +XkbChangeTypesOfKey(xkb,key,nGroups,groups,newTypesIn,changes) + XkbDescPtr xkb; + int key; + int nGroups; + unsigned groups; + int * newTypesIn; + XkbMapChangesPtr changes; +#endif +{ +XkbKeyTypePtr pOldType,pNewType; +register int i; +int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; + + if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || + (!xkb->map->types)||(!newTypes)||((groups&XkbAllGroupsMask)==0)|| + (nGroups>XkbNumKbdGroups)) { + return BadMatch; + } + if (nGroups==0) { + for (i=0;imap->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,0); + xkb->map->key_sym_map[key].group_info= i; + XkbResizeKeySyms(xkb,key,0); + return Success; + } + + nOldGroups= XkbKeyNumGroups(xkb,key); + oldWidth= XkbKeyGroupsWidth(xkb,key); + for (width=i=0;i0) + newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + else newTypes[i]= XkbTwoLevelIndex; + if (newTypes[i]>xkb->map->num_types) + return BadMatch; + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>width) + width= pNewType->num_levels; + } + if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) + xkb->ctrls->num_groups= nGroups; + if ((width!=oldWidth)||(nGroups!=nOldGroups)) { + KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; + int nCopy; + + if (nOldGroups==0) { + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms!=NULL) { + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + for (i=0;imap->key_sym_map[key].kt_index[i]= newTypes[i]; + } + return Success; + } + return BadAlloc; + } + pSyms= XkbKeySymsPtr(xkb,key); + memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms==NULL) + return BadAlloc; + bzero(pSyms,width*nGroups*sizeof(KeySym)); + for (i=0;(imap->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); + } + if (XkbKeyHasActions(xkb,key)) { + XkbAction oldActs[XkbMaxSymsPerKey],*pActs; + pActs= XkbKeyActionsPtr(xkb,key); + memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); + pActs= XkbResizeKeyActions(xkb,key,width*nGroups); + if (pActs==NULL) + return BadAlloc; + bzero(pActs,width*nGroups*sizeof(XkbAction)); + for (i=0;(imap->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pActs[i*width],&oldActs[i*oldWidth], + nCopy*sizeof(XkbAction)); + } + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + } + width= 0; + for (i=0;imap->key_sym_map[key].kt_index[i]= newTypes[i]; + if (xkb->map->types[newTypes[i]].num_levels>width) + width= xkb->map->types[newTypes[i]].num_levels; + } + xkb->map->key_sym_map[key].width= width; + if (changes!=NULL) { + if (changes->changed&XkbKeySymsMask) { + _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, + key); + } + else { + changes->changed|= XkbKeySymsMask; + changes->first_key_sym= key; + changes->num_key_syms= 1; + } + } + return Success; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) +#else +XkbVirtualModsToReal(xkb,virtual_mask,mask_rtrn) + XkbDescPtr xkb; + unsigned virtual_mask; + unsigned * mask_rtrn; +#endif +{ +register int i,bit; +register unsigned mask; + + if (xkb==NULL) + return False; + if (virtual_mask==0) { + *mask_rtrn= 0; + return True; + } + if (xkb->server==NULL) + return False; + for (i=mask=0,bit=1;iserver->vmods[i]; + } + *mask_rtrn= mask; + return True; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) +#else +XkbUpdateActionVirtualMods(xkb,act,changed) + XkbDescPtr xkb; + XkbAction * act; + unsigned changed; +#endif +{ +unsigned int tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask= act->mods.real_mods; + act->mods.mask|= tmp; + return True; + } + break; + case XkbSA_ISOLock: + if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask= act->iso.real_mods; + act->iso.mask|= tmp; + return True; + } + break; + } + return False; +} + +void +#if NeedFunctionPrototypes +XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, + XkbKeyTypePtr type, + unsigned int changed, + XkbChangesPtr changes) +#else +XkbUpdateKeyTypeVirtualMods(xkb,type,changed,changes) + XkbDescPtr xkb; + XkbKeyTypePtr type; + unsigned int changed; + XkbChangesPtr changes; +#endif +{ +register unsigned int i; +unsigned int mask; + + XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); + type->mods.mask= type->mods.real_mods|mask; + if ((type->map_count>0)&&(type->mods.vmods!=0)) { + XkbKTMapEntryPtr entry; + for (i=0,entry=type->map;imap_count;i++,entry++) { + if (entry->mods.vmods!=0) { + XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); + entry->mods.mask=entry->mods.real_mods|mask; + /* entry is active if vmods are bound*/ + entry->active= (mask!=0); + } + else entry->active= 1; + } + } + if (changes) { + int type_ndx; + type_ndx= type-xkb->map->types; + if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) + return; + if (changes->map.changed&XkbKeyTypesMask) { + int last; + last= changes->map.first_type+changes->map.num_types-1; + if (type_ndxmap.first_type) { + changes->map.first_type= type_ndx; + changes->map.num_types= (last-type_ndx)+1; + } + else if (type_ndx>last) { + changes->map.num_types= (type_ndx-changes->map.first_type)+1; + } + } + else { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= type_ndx; + changes->map.num_types= 1; + } + } + return; +} + +Bool +#if NeedFunctionPrototypes +XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) +#else +XkbApplyVirtualModChanges(xkb,changed,changes) + XkbDescPtr xkb; + unsigned changed; + XkbChangesPtr changes; +#endif +{ +register int i; +unsigned checkState; + + if ((!xkb) || (!xkb->map) || (changed==0)) + return False; + for (i=0;imap->num_types;i++) { + if (xkb->map->types[i].mods.vmods & changed) + XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); + } + if (changed&xkb->ctrls->internal.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); + newMask|= xkb->ctrls->internal.real_mods; + if (xkb->ctrls->internal.mask!=newMask) { + xkb->ctrls->internal.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbInternalModsMask; + checkState= True; + } + } + } + if (changed&xkb->ctrls->ignore_lock.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); + newMask|= xkb->ctrls->ignore_lock.real_mods; + if (xkb->ctrls->ignore_lock.mask!=newMask) { + xkb->ctrls->ignore_lock.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; + checkState= True; + } + } + } + if (xkb->indicators!=NULL) { + XkbIndicatorMapPtr map; + map= &xkb->indicators->maps[0]; + for (i=0;imods.vmods&changed) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); + newMask|= map->mods.real_mods; + if (newMask!=map->mods.mask) { + map->mods.mask= newMask; + if (changes) { + changes->indicators.map_changes|= (1<compat!=NULL) { + XkbCompatMapPtr compat; + compat= xkb->compat; + for (i=0;igroups[i].vmods,&newMask); + newMask|= compat->groups[i].real_mods; + if (compat->groups[i].mask!=newMask) { + compat->groups[i].mask= newMask; + if (changes) { + changes->compat.changed_groups|= (1<map && xkb->server) { + int highChange,lowChange; + lowChange= -1; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyHasActions(xkb,i)) { + register XkbAction *pAct; + register int n; + + pAct= XkbKeyActionsPtr(xkb,i); + for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { + if ((pAct->type!=XkbSA_NoAction)&& + XkbUpdateActionVirtualMods(xkb,pAct,changed)) { + if (lowChange<0) + lowChange= i; + highChange= i; + } + } + } + } + if (changes && (lowChange>0)) { /* something changed */ + if (changes->map.changed&XkbKeyActionsMask) { + int last; + if (changes->map.first_key_actmap.first_key_act; + last= changes->map.first_key_act+changes->map.num_key_acts-1; + if (last>highChange) + highChange= last; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= lowChange; + changes->map.num_key_acts= (highChange-lowChange)+1; + } + } + return checkState; +} diff --git a/xkb/ddxBeep.c b/xkb/ddxBeep.c new file mode 100644 index 000000000..3f3ae57a0 --- /dev/null +++ b/xkb/ddxBeep.c @@ -0,0 +1,359 @@ +/* $Xorg: ddxBeep.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +#if (defined(__osf__) && defined(__alpha)) +#include +#include +#include +#endif + +/*#define FALLING_TONE 1*/ +/*#define RISING_TONE 1*/ +#define FALLING_TONE 10 +#define RISING_TONE 10 +#define SHORT_TONE 50 +#define SHORT_DELAY 60 +#define LONG_TONE 75 +#define VERY_LONG_TONE 100 +#define LONG_DELAY 85 +#define CLICK_DURATION 1 + +#define DEEP_PITCH 250 +#define LOW_PITCH 500 +#define MID_PITCH 1000 +#define HIGH_PITCH 2000 +#define CLICK_PITCH 1500 + +static unsigned long atomGeneration= -1; +static Atom featureOn; +static Atom featureOff; +static Atom featureChange; +static Atom ledOn; +static Atom ledOff; +static Atom ledChange; +static Atom slowWarn; +static Atom slowPress; +static Atom slowReject; +static Atom slowAccept; +static Atom slowRelease; +static Atom stickyLatch; +static Atom stickyLock; +static Atom stickyUnlock; +static Atom bounceReject; +static char doesPitch = 1; + +#define FEATURE_ON "AX_FeatureOn" +#define FEATURE_OFF "AX_FeatureOff" +#define FEATURE_CHANGE "AX_FeatureChange" +#define LED_ON "AX_IndicatorOn" +#define LED_OFF "AX_IndicatorOff" +#define LED_CHANGE "AX_IndicatorChange" +#define SLOW_WARN "AX_SlowKeysWarning" +#define SLOW_PRESS "AX_SlowKeyPress" +#define SLOW_REJECT "AX_SlowKeyReject" +#define SLOW_ACCEPT "AX_SlowKeyAccept" +#define SLOW_RELEASE "AX_SlowKeyRelease" +#define STICKY_LATCH "AX_StickyLatch" +#define STICKY_LOCK "AX_StickyLock" +#define STICKY_UNLOCK "AX_StickyUnlock" +#define BOUNCE_REJECT "AX_BounceKeyReject" + +#define MAKE_ATOM(a) MakeAtom(a,sizeof(a)-1,True) + +static void +#if NeedFunctionPrototypes +_XkbDDXBeepInitAtoms(void) +#else +_XkbDDXBeepInitAtoms() +#endif +{ + featureOn= MAKE_ATOM(FEATURE_ON); + featureOff= MAKE_ATOM(FEATURE_OFF); + featureChange= MAKE_ATOM(FEATURE_CHANGE); + ledOn= MAKE_ATOM(LED_ON); + ledOff= MAKE_ATOM(LED_OFF); + ledChange= MAKE_ATOM(LED_CHANGE); + slowWarn= MAKE_ATOM(SLOW_WARN); + slowPress= MAKE_ATOM(SLOW_PRESS); + slowReject= MAKE_ATOM(SLOW_REJECT); + slowAccept= MAKE_ATOM(SLOW_ACCEPT); + slowRelease= MAKE_ATOM(SLOW_RELEASE); + stickyLatch= MAKE_ATOM(STICKY_LATCH); + stickyLock= MAKE_ATOM(STICKY_LOCK); + stickyUnlock= MAKE_ATOM(STICKY_UNLOCK); + bounceReject= MAKE_ATOM(BOUNCE_REJECT); +#if (defined(__osf__) && defined(__alpha)) + /* [[[ WDW - Some bells do not allow for pitch changes. + * Maybe this could become part of the keymap? ]]] + */ + { + char keyboard[8]; + + /* Find the class of keyboard being used. + */ + keyboard[0] = '\0'; + if (-1 == getsysinfo(GSI_KEYBOARD, + keyboard, sizeof(keyboard), + 0, NULL)) + keyboard[0] = '\0'; + + if ((strcmp(keyboard,"LK201") == 0) || + (strcmp(keyboard,"LK401") == 0) || + (strcmp(keyboard,"LK421") == 0) || + (strcmp(keyboard,"LK443") == 0)) + doesPitch = 0; + } +#endif + return; +} + +static CARD32 +#if NeedFunctionPrototypes +_XkbDDXBeepExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +_XkbDDXBeepExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +DeviceIntPtr dev= (DeviceIntPtr)arg; +KbdFeedbackPtr feed; +KeybdCtrl * ctrl; +XkbSrvInfoPtr xkbInfo; +CARD32 next; +int pitch,duration; +int oldPitch,oldDuration; +Atom name; + + if ((dev==NULL)||(dev->key==NULL)||(dev->key->xkbInfo==NULL)|| + (dev->kbdfeed==NULL)) + return 0; + if (atomGeneration!=serverGeneration) { + _XkbDDXBeepInitAtoms(); + atomGeneration= serverGeneration; + } + + feed= dev->kbdfeed; + ctrl= &feed->ctrl; + xkbInfo= dev->key->xkbInfo; + next= 0; + pitch= oldPitch= ctrl->bell_pitch; + duration= oldDuration= ctrl->bell_duration; +#ifdef DEBUG + if (xkbDebugFlags>1) + ErrorF("beep: %d (count= %d)\n",xkbInfo->beepType,xkbInfo->beepCount); +#endif + name= None; + switch (xkbInfo->beepType) { + default: + ErrorF("Unknown beep type %d\n",xkbInfo->beepType); + case _BEEP_NONE: + duration= 0; + break; + + /* When an LED is turned on, we want a high-pitched beep. + * When the LED it turned off, we want a low-pitched beep. + * If we cannot do pitch, we want a single beep for on and two + * beeps for off. + */ + case _BEEP_LED_ON: + if (name==None) name= ledOn; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + break; + case _BEEP_LED_OFF: + if (name==None) name= ledOff; + duration= SHORT_TONE; + pitch= LOW_PITCH; + if (!doesPitch && xkbInfo->beepCount<1) + next = SHORT_DELAY; + break; + + /* When a Feature is turned on, we want an up-siren. + * When a Feature is turned off, we want a down-siren. + * If we cannot do pitch, we want a single beep for on and two + * beeps for off. + */ + case _BEEP_FEATURE_ON: + if (name==None) name= featureOn; + if (xkbInfo->beepCount<1) { + pitch= LOW_PITCH; + duration= VERY_LONG_TONE; + if (doesPitch) + next= SHORT_DELAY; + } + else { + pitch= MID_PITCH; + duration= SHORT_TONE; + } + break; + + case _BEEP_FEATURE_OFF: + if (name==None) name= featureOff; + if (xkbInfo->beepCount<1) { + pitch= MID_PITCH; + if (doesPitch) + duration= VERY_LONG_TONE; + else duration= SHORT_TONE; + next= SHORT_DELAY; + } + else { + pitch= LOW_PITCH; + duration= SHORT_TONE; + } + break; + + /* Two high beeps indicate an LED or Feature changed + * state, but that another LED or Feature is also on. + * [[[WDW - This is not in AccessDOS ]]] + */ + case _BEEP_LED_CHANGE: + if (name==None) name= ledChange; + case _BEEP_FEATURE_CHANGE: + if (name==None) name= featureChange; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + if (xkbInfo->beepCount<1) { + next= SHORT_DELAY; + } + break; + + /* Three high-pitched beeps are the warning that SlowKeys + * is going to be turned on or off. + */ + case _BEEP_SLOW_WARN: + if (name==None) name= slowWarn; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + if (xkbInfo->beepCount<2) + next= SHORT_DELAY; + break; + + /* Click on SlowKeys press and accept. + * Deep pitch when a SlowKey or BounceKey is rejected. + * [[[WDW - Rejects are not in AccessDOS ]]] + * If we cannot do pitch, we want single beeps. + */ + case _BEEP_SLOW_PRESS: + if (name==None) name= slowPress; + case _BEEP_SLOW_ACCEPT: + if (name==None) name= slowAccept; + case _BEEP_SLOW_RELEASE: + if (name==None) name= slowRelease; + duration= CLICK_DURATION; + pitch= CLICK_PITCH; + break; + case _BEEP_BOUNCE_REJECT: + if (name==None) name= bounceReject; + case _BEEP_SLOW_REJECT: + if (name==None) name= slowReject; + duration= SHORT_TONE; + pitch= DEEP_PITCH; + break; + + /* Low followed by high pitch when a StickyKey is latched. + * High pitch when a StickyKey is locked. + * Low pitch when unlocked. + * If we cannot do pitch, two beeps for latch, nothing for + * lock, and two for unlock. + */ + case _BEEP_STICKY_LATCH: + if (name==None) name= stickyLatch; + duration= SHORT_TONE; + if (xkbInfo->beepCount<1) { + next= SHORT_DELAY; + pitch= LOW_PITCH; + } + else pitch= HIGH_PITCH; + break; + case _BEEP_STICKY_LOCK: + if (name==None) name= stickyLock; + if (doesPitch) { + duration= SHORT_TONE; + pitch= HIGH_PITCH; + } + break; + case _BEEP_STICKY_UNLOCK: + if (name==None) name= stickyUnlock; + duration= SHORT_TONE; + pitch= LOW_PITCH; + if (!doesPitch && xkbInfo->beepCount<1) + next = SHORT_DELAY; + break; + } + if (duration>0) { + ctrl->bell_duration= duration; + ctrl->bell_pitch= pitch; + if (xkbInfo->beepCount==0) { + XkbHandleBell(0,0,dev,ctrl->bell,(pointer)ctrl,KbdFeedbackClass,name,None, + NULL); + } + else if (xkbInfo->desc->ctrls->enabled_ctrls&XkbAudibleBellMask) { + (*dev->kbdfeed->BellProc)(ctrl->bell,dev,(pointer)ctrl,KbdFeedbackClass); + } + ctrl->bell_duration= oldDuration; + ctrl->bell_pitch= oldPitch; + xkbInfo->beepCount++; + } + return next; +} + +int +#if NeedFunctionPrototypes +XkbDDXAccessXBeep(DeviceIntPtr dev,unsigned what,unsigned which) +#else +XkbDDXAccessXBeep(dev,what,which) + DeviceIntPtr dev; + unsigned what; + unsigned which; +#endif +{ +XkbSrvInfoRec *xkbInfo= dev->key->xkbInfo; +CARD32 next; + + xkbInfo->beepType= what; + xkbInfo->beepCount= 0; + next= _XkbDDXBeepExpire(NULL,0,(pointer)dev); + if (next>0) { + xkbInfo->beepTimer= TimerSet(xkbInfo->beepTimer, + 0, next, + _XkbDDXBeepExpire, (pointer)dev); + } + return 1; +} diff --git a/xkb/ddxConfig.c b/xkb/ddxConfig.c new file mode 100644 index 000000000..f3635902f --- /dev/null +++ b/xkb/ddxConfig.c @@ -0,0 +1,217 @@ +/* $Xorg: ddxConfig.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "os.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include + +Bool +#if NeedFunctionPrototypes +XkbDDXApplyConfig(XPointer cfg_in,XkbSrvInfoPtr info) +#else +XkbDDXApplyConfig(cfg_in,info) + XPointer cfg_in; + XkbSrvInfoPtr info; +#endif +{ +XkbConfigRtrnPtr rtrn; +XkbDescPtr xkb; +Bool ok; +XkbEventCauseRec cause; + + xkb= info->desc; + rtrn= (XkbConfigRtrnPtr)cfg_in; + if (rtrn==NULL) + return True; + ok= XkbCFApplyRtrnValues(rtrn,XkbCFDflts,xkb); + if (rtrn->initial_mods.replace) { + info->state.locked_mods= rtrn->initial_mods.mods; + } + else { + info->state.locked_mods|= rtrn->initial_mods.mods; + if (rtrn->initial_mods.mods_clear) + info->state.locked_mods&= ~rtrn->initial_mods.mods_clear; + } + XkbComputeDerivedState(info); + XkbSetCauseUnknown(&cause); + XkbUpdateIndicators(info->device,XkbAllIndicatorsMask,False,NULL,&cause); + if (info->device && info->device->kbdfeed) { + DeviceIntPtr dev; + KeybdCtrl newCtrl; + dev= info->device; + newCtrl= dev->kbdfeed->ctrl; + if (rtrn->click_volume>=0) + newCtrl.click= rtrn->click_volume; + if (rtrn->bell_volume>=0) + newCtrl.bell= rtrn->bell_volume; + if (rtrn->bell_pitch>0) + newCtrl.bell_pitch= rtrn->bell_pitch; + if (rtrn->bell_duration>0) + newCtrl.bell_duration= rtrn->bell_duration; + if (dev->kbdfeed->CtrlProc) + (*dev->kbdfeed->CtrlProc)(dev,&newCtrl); + } + XkbCFFreeRtrn(rtrn,XkbCFDflts,xkb); + return ok; +} + +XPointer +#if NeedFunctionPrototypes +XkbDDXPreloadConfig( char ** rulesRtrn, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names, + DeviceIntPtr dev) +#else +XkbDDXPreloadConfig(rulesRtrn,defs,names,dev) + char ** rulesRtrn; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; + DeviceIntPtr dev; +#endif +{ +char buf[PATH_MAX]; +char * dName; +FILE * file; +XkbConfigRtrnPtr rtrn; +extern char * display; + +#if defined(MetroLink) + if (dev && dev->name) + dName= dev->name; + else dName= ""; + /* It doesn't appear that XkbBaseDirectory could ever get set to NULL */ + sprintf(buf,"%s/X%s-config%s%s",XkbBaseDirectory,display, + (dName[0]?".":""),dName); +#else + if (dev && dev->name) + dName= dev->name; + else dName= ""; + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)+strlen(display) + +strlen(dName)+10+(dName[0]?1:0) > PATH_MAX) + { +#ifdef DEBUG + ErrorF("path exceeds max length\n"); +#endif + return NULL; + } + sprintf(buf,"%s/X%s-config%s%s",XkbBaseDirectory,display, + (dName[0]?".":""),dName); + } + else { + if (strlen(display)+strlen(dName)+10+(dName[0]?1:0) > PATH_MAX) + { +#ifdef DEBUG + ErrorF("path exceeds max length\n"); +#endif + return NULL; + } + sprintf(buf,"X%s-config%s%s",display,(dName[0]?".":""),dName); + } +#endif +#ifdef DEBUG + ErrorF("Looking for keyboard configuration in %s...",buf); +#endif + file= fopen(buf,"r"); + if (file==NULL) { +#ifdef DEBUG + ErrorF("file not found\n"); +#endif + return NULL; + } + rtrn= _XkbTypedCalloc(1,XkbConfigRtrnRec); + if (rtrn!=NULL) { + if (!XkbCFParse(file,XkbCFDflts,NULL,rtrn)) { +#ifdef DEBUG + ErrorF("error\n"); +#endif + ErrorF("Error parsing config file: "); + XkbCFReportError(stderr,buf,rtrn->error,rtrn->line); + _XkbFree(rtrn); + fclose(file); + return NULL; + } +#ifdef DEBUG + ErrorF("found it\n"); +#endif + if (rtrn->rules_file) { + *rulesRtrn= rtrn->rules_file; + rtrn->rules_file= NULL; + } + if (rtrn->model) { + defs->model= rtrn->model; + rtrn->model= NULL; + } + if (rtrn->layout) { + defs->layout= rtrn->layout; + rtrn->layout= NULL; + } + if (rtrn->variant) { + defs->variant= rtrn->variant; + rtrn->variant= NULL; + } + if (rtrn->options) { + defs->options= rtrn->options; + rtrn->options= NULL; + } + XkbSetRulesUsed(defs); + + if (rtrn->keycodes!=NULL) { + names->keycodes= rtrn->keycodes; + rtrn->keycodes= NULL; + } + if (rtrn->geometry!=NULL) { + names->geometry= rtrn->geometry; + rtrn->geometry= NULL; + } + if (rtrn->symbols!=NULL) { + if (rtrn->phys_symbols==NULL) + rtrn->phys_symbols= _XkbDupString(names->symbols); + names->symbols= rtrn->symbols; + rtrn->symbols= NULL; + } + if (rtrn->types!=NULL) { + names->types= rtrn->types; + rtrn->types= NULL; + } + if (rtrn->compat!=NULL) { + names->compat= rtrn->compat; + rtrn->compat= NULL; + } + } + fclose(file); + return (XPointer)rtrn; +} diff --git a/xkb/ddxCtrls.c b/xkb/ddxCtrls.c new file mode 100644 index 000000000..da599fbf2 --- /dev/null +++ b/xkb/ddxCtrls.c @@ -0,0 +1,133 @@ +/* $Xorg: ddxCtrls.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXKeybdCtrlProc(DeviceIntPtr dev,KeybdCtrl *ctrl) +#else +XkbDDXKeybdCtrlProc(dev,ctrl) + DeviceIntPtr dev; + KeybdCtrl * ctrl; +#endif +{ +int realRepeat; + + realRepeat= ctrl->autoRepeat; + if ((dev->kbdfeed)&&(XkbDDXUsesSoftRepeat(dev))) + ctrl->autoRepeat= 0; +#ifdef DEBUG +if (xkbDebugFlags&0x4) { + ErrorF("XkbDDXKeybdCtrlProc: setting repeat to %d (real repeat is %d)\n", + ctrl->autoRepeat,realRepeat); +} +#endif + if (dev->key && dev->key->xkbInfo && dev->key->xkbInfo->kbdProc) + (*dev->key->xkbInfo->kbdProc)(dev,ctrl); + ctrl->autoRepeat= realRepeat; + return; +} + + +int +#if NeedFunctionPrototypes +XkbDDXUsesSoftRepeat(DeviceIntPtr pXDev) +#else +XkbDDXUsesSoftRepeat(pXDev) + DeviceIntPtr pXDev; +#endif +{ +#ifndef XKB_ALWAYS_USES_SOFT_REPEAT + if (pXDev && pXDev->kbdfeed ) { + if (pXDev->kbdfeed->ctrl.autoRepeat) { + if (pXDev->key && pXDev->key->xkbInfo) { + XkbDescPtr xkb; + xkb= pXDev->key->xkbInfo->desc; + if ((xkb->ctrls->repeat_delay == 660) && + (xkb->ctrls->repeat_interval == 40) && + ((xkb->ctrls->enabled_ctrls&(XkbSlowKeysMask| + XkbBounceKeysMask| + XkbMouseKeysMask))==0)) { + return 0; + } + return ((xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0); + } + } + } + return 0; +#else + return 1; +#endif +} + +void +#if NeedFunctionPrototypes +XkbDDXChangeControls(DeviceIntPtr dev,XkbControlsPtr old,XkbControlsPtr new) +#else +XkbDDXChangeControls(dev,old,new) + DeviceIntPtr dev; + XkbControlsPtr old; + XkbControlsPtr new; +#endif +{ +unsigned changed; + + changed= new->enabled_ctrls^old->enabled_ctrls; +#ifdef NOTDEF + if (changed&XkbRepeatKeysMask) { + if (dev->kbdfeed) { + int realRepeat; + + if (new->enabled_ctrls&XkbRepeatKeysMask) + dev->kbdfeed->ctrl.autoRepeat= realRepeat= 1; + else dev->kbdfeed->ctrl.autoRepeat= realRepeat= 0; + + if (XkbDDXUsesSoftRepeat(dev)) + dev->kbdfeed->ctrl.autoRepeat= FALSE; + if (dev->kbdfeed->CtrlProc) + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + dev->kbdfeed->ctrl.autoRepeat= realRepeat; + } + } +#endif + if (changed&XkbPerKeyRepeatMask) { + if (dev->kbdfeed->CtrlProc) + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + } + return; +} + diff --git a/xkb/ddxDevBtn.c b/xkb/ddxDevBtn.c new file mode 100644 index 000000000..7d641358f --- /dev/null +++ b/xkb/ddxDevBtn.c @@ -0,0 +1,104 @@ +/* $Xorg: ddxDevBtn.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" +#include "XIproto.h" + +extern int DeviceButtonPress,DeviceButtonRelease,DeviceValuator; + +void +#if NeedFunctionPrototypes +XkbDDXFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) +#else +XkbDDXFakeDeviceButton(dev,press,button) + DeviceIntPtr dev; + Bool press; + int button; +#endif +{ +int * devVal; +INT32 * evVal; +xEvent events[2]; +deviceKeyButtonPointer *btn; +deviceValuator * val; +int x,y; +int nAxes, i, count; + + if ((dev==(DeviceIntPtr)LookupPointerDevice())||(!dev->public.on)) + return; + + nAxes = (dev->valuator?dev->valuator->numAxes:0); + if (nAxes > 6) + nAxes = 6; + + GetSpritePosition(&x,&y); + btn= (deviceKeyButtonPointer *) &events[0]; + val= (deviceValuator *) &events[1]; + if (press) btn->type= DeviceButtonPress; + else btn->type= DeviceButtonRelease; + btn->detail= button; + btn->time= GetTimeInMillis(); + btn->root_x= x; + btn->root_y= y; + btn->deviceid= dev->id; + count= 1; + if (nAxes>0) { + btn->deviceid|= 0x80; + val->type = DeviceValuator; + val->deviceid = dev->id; + val->first_valuator = 0; + + evVal= &val->valuator0; + devVal= dev->valuator->axisVal; + for (i=nAxes;i>0;i--) { + *evVal++ = *devVal++; + if (evVal > &val->valuator5) { + int tmp = val->first_valuator+6; + val->num_valuators = 6; + val++; + evVal= &val->valuator0; + val->first_valuator= tmp; + } + } + if ((nAxes % 6) != 0) { + val->num_valuators = (nAxes % 6); + } + count= 1+((nAxes+5)/6); + } + + (*dev->public.processInputProc)((xEventPtr)btn, dev, count); + return; +} diff --git a/xkb/ddxFakeBtn.c b/xkb/ddxFakeBtn.c new file mode 100644 index 000000000..9394c4772 --- /dev/null +++ b/xkb/ddxFakeBtn.c @@ -0,0 +1,62 @@ +/* $Xorg: ddxFakeBtn.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXFakePointerButton(int event,int button) +#else +XkbDDXFakePointerButton(event,button) + int event; + int button; +#endif +{ +xEvent ev; +int x,y; +DevicePtr ptr; + + if ((ptr = LookupPointerDevice())==NULL) + return; + GetSpritePosition(&x,&y); + ev.u.u.type = event; + ev.u.u.detail = button; + ev.u.keyButtonPointer.time = GetTimeInMillis(); + ev.u.keyButtonPointer.rootX = x; + ev.u.keyButtonPointer.rootY = y; + (*ptr->processInputProc)( &ev, (DeviceIntPtr)ptr, 1 ); + return; +} diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c new file mode 100644 index 000000000..04a8c80e9 --- /dev/null +++ b/xkb/ddxFakeMtn.c @@ -0,0 +1,76 @@ +/* $Xorg: ddxFakeMtn.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +extern WindowPtr GetSpriteWindow( +#if NeedFunctionPrototypes + void +#endif +); + +void +#if NeedFunctionPrototypes +XkbDDXFakePointerMotion(unsigned flags,int x,int y) +#else +XkbDDXFakePointerMotion(flags,x,y) + unsigned flags; + int x; + int y; +#endif +{ +ScreenPtr pScreen; +int oldX,oldY; + + pScreen= GetSpriteWindow()->drawable.pScreen; + GetSpritePosition(&oldX,&oldY); + if (flags&XkbSA_MoveAbsoluteX) + oldX= x; + else oldX+= x; + if (flags&XkbSA_MoveAbsoluteY) + oldY= y; + else oldY+= y; + + if (oldX<0) oldX= 0; + else if (oldX>=pScreen->width) oldX= pScreen->width-1; + if (oldY<0) oldY= 0; + else if (oldY>=pScreen->height) oldY= pScreen->height-1; + + if (pScreen->SetCursorPosition) + (*pScreen->SetCursorPosition)(pScreen, oldX, oldY, TRUE); + return; +} + diff --git a/xkb/ddxInit.c b/xkb/ddxInit.c new file mode 100644 index 000000000..12dbfe838 --- /dev/null +++ b/xkb/ddxInit.c @@ -0,0 +1,48 @@ +/* $Xorg: ddxInit.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +int +#if NeedFunctionPrototypes +XkbDDXInitDevice(DeviceIntPtr dev) +#else +XkbDDXInitDevice(dev) + DeviceIntPtr dev; +#endif +{ + return 1; +} diff --git a/xkb/ddxKeyClick.c b/xkb/ddxKeyClick.c new file mode 100644 index 000000000..af1185f72 --- /dev/null +++ b/xkb/ddxKeyClick.c @@ -0,0 +1,54 @@ +/* $Xorg: ddxKeyClick.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXKeyClick(DeviceIntPtr pXDev,int keycode,int synthetic) +#else +XkbDDXKeyClick(pXDev,keycode,synthetic) + DeviceIntPtr pXDev; + int keycode; + int synthetic; +#endif +{ +#ifdef DEBUG + if (xkbDebugFlags) + ErrorF("Click.\n"); +#endif + return; +} diff --git a/xkb/ddxKillSrv.c b/xkb/ddxKillSrv.c new file mode 100644 index 000000000..50fc9b24c --- /dev/null +++ b/xkb/ddxKillSrv.c @@ -0,0 +1,51 @@ +/* $Xorg: ddxKillSrv.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +int +#if NeedFunctionPrototypes +XkbDDXTerminateServer(DeviceIntPtr dev,KeyCode key,XkbAction *act) +#else +XkbDDXTerminateServer(dev,key,act) + DeviceIntPtr dev; + KeyCode key; + XkbAction *act; +#endif +{ + GiveUp(1); + return 0; +} diff --git a/xkb/ddxLEDs.c b/xkb/ddxLEDs.c new file mode 100644 index 000000000..f6ea86965 --- /dev/null +++ b/xkb/ddxLEDs.c @@ -0,0 +1,82 @@ +/* $Xorg: ddxLEDs.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXUpdateIndicators(DeviceIntPtr dev,CARD32 new) +#else +XkbDDXUpdateIndicators(dev,new) + DeviceIntPtr dev; + CARD32 new; +#endif +{ + dev->kbdfeed->ctrl.leds= new; + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + return; +} + +void +#if NeedFunctionPrototypes +XkbDDXUpdateDeviceIndicators( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + CARD32 new) +#else +XkbDDXUpdateDeviceIndicators(dev,sli,new) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + CARD32 new; +#endif +{ + if (sli->fb.kf==dev->kbdfeed) + XkbDDXUpdateIndicators(dev,new); + else if (sli->class==KbdFeedbackClass) { + KbdFeedbackPtr kf; + kf= sli->fb.kf; + if (kf && kf->CtrlProc) { + (*kf->CtrlProc)(dev,&kf->ctrl); + } + } + else if (sli->class==LedFeedbackClass) { + LedFeedbackPtr lf; + lf= sli->fb.lf; + if (lf && lf->CtrlProc) { + (*lf->CtrlProc)(dev,&lf->ctrl); + } + } + return; +} diff --git a/xkb/ddxList.c b/xkb/ddxList.c new file mode 100644 index 000000000..9f1ad4406 --- /dev/null +++ b/xkb/ddxList.c @@ -0,0 +1,309 @@ +/* $Xorg: ddxList.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XI.h" + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +/***====================================================================***/ + +static char *componentDirs[_XkbListNumComponents] = { + "keymap", "keycodes", "types", "compat", "symbols", "geometry" +}; + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +_AddListComponent( XkbSrvListInfoPtr list, + int what, + unsigned flags, + char * str, + ClientPtr client) +#else +_AddListComponent(list,what,flags,str,client) + XkbSrvListInfoPtr list; + int what; + unsigned flags; + char * str; + ClientPtr client; +#endif +{ +int slen,wlen; +unsigned char * wire8; +unsigned short *wire16; +char * tmp; + + if (list->nTotal>=list->maxRtrn) { + list->nTotal++; + return Success; + } + tmp= strchr(str,')'); + if ((tmp==NULL)&&((tmp=strchr(str,'('))==NULL)) { + slen= strlen(str); + while ((slen>0) && isspace(str[slen-1])) { + slen--; + } + } + else { + slen= (tmp-str+1); + } + wlen= (((slen+1)/2)*2)+4; /* four bytes for flags and length, pad to */ + /* 2-byte boundary */ + if ((list->szPool-list->nPool)1024) list->szPool+= XkbPaddedSize(wlen*2); + else list->szPool+= 1024; + list->pool= _XkbTypedRealloc(list->pool,list->szPool,char); + if (!list->pool) + return BadAlloc; + } + wire16= (unsigned short *)&list->pool[list->nPool]; + wire8= (unsigned char *)&wire16[2]; + wire16[0]= flags; + wire16[1]= slen; + memcpy(wire8,str,slen); + if (client->swapped) { + register int n; + swaps(&wire16[0],n); + swaps(&wire16[1],n); + } + list->nPool+= wlen; + list->nFound[what]++; + list->nTotal++; + return Success; +} + +/***====================================================================***/ +static Status +#if NeedFunctionPrototypes +XkbDDXListComponent( DeviceIntPtr dev, + int what, + XkbSrvListInfoPtr list, + ClientPtr client) +#else +XkbDDXListComponent(dev,what,list,client) + DeviceIntPtr dev; + int what; + XkbSrvListInfoPtr list; + ClientPtr client; +#endif +{ +char *file,*map,*tmp,buf[PATH_MAX]; +FILE *in; +Status status; +int rval; +Bool haveDir; +#ifdef WIN32 +char tmpname[32]; +#endif + + if ((list->pattern[what]==NULL)||(list->pattern[what][0]=='\0')) + return Success; + file= list->pattern[what]; + map= strrchr(file,'('); + if (map!=NULL) { + char *tmp; + map++; + tmp= strrchr(map,')'); + if ((tmp==NULL)||(tmp[1]!='\0')) { + /* illegal pattern. No error, but no match */ + return Success; + } + } + + in= NULL; + haveDir= True; +#ifdef WIN32 + strcpy(tmpname, "\\temp\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)+strlen(componentDirs[what])+6 > PATH_MAX) + return BadImplementation; + if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) { + sprintf(buf,"%s/%s.dir",XkbBaseDirectory,componentDirs[what]); + in= fopen(buf,"r"); + } + if (!in) { + haveDir= False; + if (strlen(XkbBaseDirectory)*2+strlen(componentDirs[what]) + +(xkbDebugFlags>9?2:1)+strlen(file)+31 > PATH_MAX) + return BadImplementation; +#ifndef WIN32 + sprintf(buf,"%s/xkbcomp -R%s/%s -w %d -l -vlfhpR '%s'", + XkbBaseDirectory,XkbBaseDirectory,componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file); +#else + sprintf(buf,"%s/xkbcomp -R%s/%s -w %d -l -vlfhpR '%s' %s", + XkbBaseDirectory,XkbBaseDirectory,componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file, tmpname); +#endif + } + } + else { + if (strlen(XkbBaseDirectory)+strlen(componentDirs[what])+6 > PATH_MAX) + return BadImplementation; + if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) { + sprintf(buf,"%s.dir",componentDirs[what]); + in= fopen(buf,"r"); + } + if (!in) { + haveDir= False; + if (strlen(componentDirs[what]) + +(xkbDebugFlags>9?2:1)+strlen(file)+29 > PATH_MAX) + return BadImplementation; +#ifndef WIN32 + sprintf(buf,"xkbcomp -R%s -w %d -l -vlfhpR '%s'", + componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file); +#else + sprintf(buf,"xkbcomp -R%s -w %d -l -vlfhpR '%s' %s", + componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file, tmpname); +#endif + } + } + status= Success; + if (!haveDir) +#ifndef WIN32 + in= popen(buf,"r"); +#else + { + if (system(buf) < 0) + ErrorF("Could not invoke keymap compiler\n"); + else + in= fopen(tmpname, "r"); + } +#endif + if (!in) + return BadImplementation; + list->nFound[what]= 0; + while ((status==Success)&&((tmp=fgets(buf,PATH_MAX,in))!=NULL)) { + unsigned flags; + register unsigned int i; + if (*tmp=='#') /* comment, skip it */ + continue; + if (!strncmp(tmp, "Warning:", 8) || !strncmp(tmp, " ", 8)) + /* skip warnings too */ + continue; + flags= 0; + /* each line in the listing is supposed to start with two */ + /* groups of eight characters, which specify the general */ + /* flags and the flags that are specific to the component */ + /* if they're missing, fail with BadImplementation */ + for (i=0;(i<8)&&(status==Success);i++) { /* read the general flags */ + if (isalpha(*tmp)) flags|= (1L< +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XI.h" + +#if defined(CSRG_BASED) || defined(linux) || defined(__sgi) || defined(AIXV3) || defined(__osf__) +#include +#endif + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + + /* + * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is + * relative to the top-level XKB configuration directory. + * Making the server write to a subdirectory of that directory + * requires some work in the general case (install procedure + * has to create links to /var or somesuch on many machines), + * so we just compile into /usr/tmp for now. + */ +#ifndef XKM_OUTPUT_DIR +#define XKM_OUTPUT_DIR "compiled/" +#endif + +#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\"" +#define ERROR_PREFIX "\"> \"" +#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\"" +#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\"" + +static void +OutputDirectory (outdir) + char* outdir; +{ +#ifndef WIN32 + if (getuid() == 0 || geteuid() == 0) { + /* if server running as root it'll be able to write */ + (void) strcpy (outdir, XKM_OUTPUT_DIR); + } else +#endif + { +#ifdef _PATH_VARTMP + (void) strcpy (outdir, _PATH_VARTMP); + if (outdir[strlen(outdir) - 1] != '/') /* Hi IBM, Digital */ + (void) strcat (outdir, "/"); +#else + (void) strcpy (outdir, "/tmp/"); +#endif + } +} + +Bool +#if NeedFunctionPrototypes +XkbDDXCompileNamedKeymap( XkbDescPtr xkb, + XkbComponentNamesPtr names, + char * nameRtrn, + int nameRtrnLen) +#else +XkbDDXCompileNamedKeymap(xkb,names,nameRtrn,nameRtrnLen) + XkbDescPtr xkb; + XkbComponentNamesPtr names; + char * nameRtrn; + int nameRtrnLen; +#endif +{ +char cmd[PATH_MAX],file[PATH_MAX],xkm_output_dir[PATH_MAX],*map,*outFile; + + if (names->keymap==NULL) + return False; + strncpy(file,names->keymap,PATH_MAX); file[PATH_MAX-1]= '\0'; + if ((map= strrchr(file,'('))!=NULL) { + char *tmp; + if ((tmp= strrchr(map,')'))!=NULL) { + *map++= '\0'; + *tmp= '\0'; + } + else { + map= NULL; + } + } + if ((outFile= strrchr(file,'/'))!=NULL) + outFile= _XkbDupString(&outFile[1]); + else outFile= _XkbDupString(file); + XkbEnsureSafeMapName(outFile); + OutputDirectory(xkm_output_dir); + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)*2+(xkbDebugFlags>9?2:1) + +(map?strlen(map)+3:0)+strlen(PRE_ERROR_MSG) + +strlen(ERROR_PREFIX)+strlen(POST_ERROR_MSG1) + +strlen(file)+strlen(xkm_output_dir) + +strlen(outFile)+53 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } + sprintf(cmd,"%s/xkbcomp -w %d -R%s -xkm %s%s -em1 %s -emp %s -eml %s keymap/%s %s%s.xkm", + XkbBaseDirectory, + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + XkbBaseDirectory,(map?"-m ":""),(map?map:""), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,file, + xkm_output_dir,outFile); + } + else { + if ((xkbDebugFlags>9?2:1)+(map?strlen(map)+3:0)+strlen(PRE_ERROR_MSG) + +strlen(ERROR_PREFIX)+strlen(POST_ERROR_MSG1) + +strlen(file)+strlen(xkm_output_dir) + +strlen(outFile)+49 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } + sprintf(cmd,"xkbcomp -w %d -xkm %s%s -em1 %s -emp %s -eml %s keymap/%s %s%s.xkm", + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + (map?"-m ":""),(map?map:""), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,file, + xkm_output_dir,outFile); + } +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("XkbDDXCompileNamedKeymap compiling keymap using:\n"); + ErrorF(" \"cmd\"\n"); + } +#endif + if (system(cmd)==0) { + if (nameRtrn) { + strncpy(nameRtrn,outFile,nameRtrnLen); + nameRtrn[nameRtrnLen-1]= '\0'; + } + if (outFile!=NULL) + Xfree(outFile); + return True; + } +#ifdef DEBUG + ErrorF("Error compiling keymap (%s)\n",names->keymap); +#endif + if (outFile!=NULL) + Xfree(outFile); + return False; +} + +Bool +#if NeedFunctionPrototypes +XkbDDXCompileKeymapByNames( XkbDescPtr xkb, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + char * nameRtrn, + int nameRtrnLen) +#else +XkbDDXCompileKeymapByNames(xkb,names,want,need,nameRtrn,nameRtrnLen) + XkbDescPtr xkb; + XkbComponentNamesPtr names; + unsigned want; + unsigned need; + char * nameRtrn; + int nameRtrnLen; +#endif +{ +FILE * out; +char buf[PATH_MAX],keymap[PATH_MAX],xkm_output_dir[PATH_MAX]; +#ifdef WIN32 +char tmpname[32]; +#endif + if ((names->keymap==NULL)||(names->keymap[0]=='\0')) { + extern char *display; + sprintf(keymap,"server-%s",display); + } + else { + strcpy(keymap,names->keymap); + } + + XkbEnsureSafeMapName(keymap); + OutputDirectory(xkm_output_dir); +#ifdef WIN32 + strcpy(tmpname, "\\temp\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)*2+(xkbDebugFlags>9?2:1) + +strlen(PRE_ERROR_MSG)+strlen(ERROR_PREFIX) + +strlen(POST_ERROR_MSG1)+strlen(xkm_output_dir) + +strlen(keymap)+48 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } +#ifndef WIN32 + sprintf(buf, + "%s/xkbcomp -w %d -R%s -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\"", + XkbBaseDirectory, + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + XkbBaseDirectory, + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap); +#else + sprintf(buf, + "%s/xkbcomp -w %d -R%s -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\" < %s", + XkbBaseDirectory, + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + XkbBaseDirectory, + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap,tmpname); +#endif + } + else { + if ((xkbDebugFlags>9?2:1)+strlen(PRE_ERROR_MSG) + +strlen(ERROR_PREFIX)+strlen(POST_ERROR_MSG1) + +strlen(xkm_output_dir)+strlen(keymap)+44 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } +#ifndef WIN32 + sprintf(buf, + "xkbcomp -w %d -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\"", + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap); +#else + sprintf(buf, + "xkbcomp -w %d -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\" < %s", + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap,tmpname); +#endif + } +#ifndef WIN32 + out= popen(buf,"w"); +#else + out= fopen(tmpname, "w"); +#endif + if (out!=NULL) { +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("XkbDDXCompileKeymapByNames compiling keymap:\n"); + XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need); + } +#endif + XkbWriteXKBKeymapForNames(out,names,NULL,xkb,want,need); +#ifndef WIN32 + if (pclose(out)==0) +#else + if (fclose(out)==0) +#endif + { +#ifdef WIN32 + if (system(buf) < 0) + ErrorF("Could not invoke keymap compiler\n"); + else { +#endif + if (nameRtrn) { + strncpy(nameRtrn,keymap,nameRtrnLen); + nameRtrn[nameRtrnLen-1]= '\0'; + } + return True; +#ifdef WIN32 + } +#endif + } +#ifdef DEBUG + else + ErrorF("Error compiling keymap (%s)\n",keymap); +#endif + } +#ifdef DEBUG + else { +#ifndef WIN32 + ErrorF("Could not invoke keymap compiler\n"); +#else + ErrorF("Could not open file %s\n", tmpname); +#endif + } +#endif + if (nameRtrn) + nameRtrn[0]= '\0'; + return False; +} + +FILE * +#if NeedFunctionPrototypes +XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen) +#else +XkbDDXOpenConfigFile(mapName,fileNameRtrn,fileNameRtrnLen) + char * mapName; + char * fileNameRtrn; + int fileNameRtrnLen; +#endif +{ +char buf[PATH_MAX],xkm_output_dir[PATH_MAX]; +FILE * file; + + buf[0]= '\0'; + if (mapName!=NULL) { + OutputDirectory(xkm_output_dir); + if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/')) { + if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir) + +strlen(mapName)+6 <= PATH_MAX) + { + sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory, + xkm_output_dir,mapName); + } + } + else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX) + sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName); + if (buf[0] != '\0') + file= fopen(buf,"r"); + else file= NULL; + } + else file= NULL; + if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) { + strncpy(fileNameRtrn,buf,fileNameRtrnLen); + buf[fileNameRtrnLen-1]= '\0'; + } + return file; +} + +unsigned +#if NeedFunctionPrototypes +XkbDDXLoadKeymapByNames( DeviceIntPtr keybd, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + XkbFileInfo * finfoRtrn, + char * nameRtrn, + int nameRtrnLen) +#else +XkbDDXLoadKeymapByNames(keybd,names,want,need,finfoRtrn,nameRtrn,nameRtrnLen) + DeviceIntPtr keybd; + XkbComponentNamesPtr names; + unsigned want; + unsigned need; + XkbFileInfo * finfoRtrn; + char * nameRtrn; + int nameRtrnLen; +#endif +{ +XkbDescPtr xkb; +FILE * file; +char fileName[PATH_MAX]; +unsigned missing; + + bzero(finfoRtrn,sizeof(XkbFileInfo)); + if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL)) + xkb= NULL; + else xkb= keybd->key->xkbInfo->desc; + if ((names->keycodes==NULL)&&(names->types==NULL)&& + (names->compat==NULL)&&(names->symbols==NULL)&& + (names->geometry==NULL)) { + if (names->keymap==NULL) { + bzero(finfoRtrn,sizeof(XkbFileInfo)); + if (xkb && XkbDetermineFileType(finfoRtrn,XkbXKMFile,NULL) && + ((finfoRtrn->defined&need)==need) ) { + finfoRtrn->xkb= xkb; + nameRtrn[0]= '\0'; + return finfoRtrn->defined; + } + return 0; + } + else if (!XkbDDXCompileNamedKeymap(xkb,names,nameRtrn,nameRtrnLen)) { +#ifdef NOISY + ErrorF("Couldn't compile keymap file\n"); +#endif + return 0; + } + } + else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need, + nameRtrn,nameRtrnLen)){ +#ifdef NOISY + ErrorF("Couldn't compile keymap file\n"); +#endif + return 0; + } + file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX); + if (file==NULL) { + ErrorF("Couldn't open compiled keymap file %s\n",fileName); + return 0; + } + missing= XkmReadFile(file,need,want,finfoRtrn); + if (finfoRtrn->xkb==NULL) { + ErrorF("Error loading keymap %s\n",fileName); + fclose(file); + (void) unlink (fileName); + return 0; + } +#ifdef DEBUG + else if (xkbDebugFlags) { + ErrorF("Loaded %s, defined=0x%x\n",fileName,finfoRtrn->defined); + } +#endif + fclose(file); + (void) unlink (fileName); + return (need|want)&(~missing); +} + +Bool +#if NeedFunctionPrototypes +XkbDDXNamesFromRules( DeviceIntPtr keybd, + char * rules_name, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbDDXNamesFromRules(keybd,rules_name,defs,names) + DeviceIntPtr keybd; + char * rules_name; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +char buf[PATH_MAX]; +FILE * file; +Bool complete; +XkbRF_RulesPtr rules; + + if (!rules_name) + return False; + if (XkbBaseDirectory==NULL) { + if (strlen(rules_name)+7 > PATH_MAX) + return False; + sprintf(buf,"rules/%s",rules_name); + } + else { + if (strlen(XkbBaseDirectory)+strlen(rules_name)+8 > PATH_MAX) + return False; + sprintf(buf,"%s/rules/%s",XkbBaseDirectory,rules_name); + } + if ((file= fopen(buf,"r"))==NULL) + return False; + if ((rules= XkbRF_Create(0,0))==NULL) { + fclose(file); + return False; + } + if (!XkbRF_LoadRules(file,rules)) { + fclose(file); + XkbRF_Free(rules,True); + return False; + } + bzero((char *)names,sizeof(XkbComponentNamesRec)); + complete= XkbRF_GetComponents(rules,defs,names); + fclose(file); + XkbRF_Free(rules,True); + return complete; +} diff --git a/xkb/ddxVT.c b/xkb/ddxVT.c new file mode 100644 index 000000000..e1978d88b --- /dev/null +++ b/xkb/ddxVT.c @@ -0,0 +1,50 @@ +/* $Xorg: ddxVT.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +int +#if NeedFunctionPrototypes +XkbDDXSwitchScreen(DeviceIntPtr dev,KeyCode key,XkbAction *act) +#else +XkbDDXSwitchScreen(dev,key,act) + DeviceIntPtr dev; + KeyCode key; + XkbAction *act; +#endif +{ + return 1; +} diff --git a/xkb/maprules.c b/xkb/maprules.c new file mode 100644 index 000000000..559dc9c7f --- /dev/null +++ b/xkb/maprules.c @@ -0,0 +1,1382 @@ +/* $Xorg: maprules.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc. + + 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 name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS 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. + + ********************************************************/ + +#include +#include +#ifndef X_NOT_STDC_ENV +#include +#endif + + +#define X_INCLUDE_STRING_H +#define XOS_USE_NO_LOCKING +#include + +#ifndef XKB_IN_SERVER + +#include +#include +#include +#include +#include +#include +#include +#include +#include "XKMformat.h" +#include "XKBfileInt.h" +#include "XKBrules.h" + +#else + +#define NEED_EVENTS +#include +#include +#include +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" + +#endif + +#ifdef DEBUG +#define PR_DEBUG(s) fprintf(stderr,s) +#define PR_DEBUG1(s,a) fprintf(stderr,s,a) +#else +#define PR_DEBUG(s) +#define PR_DEBUG1(s,a) +#endif + +/***====================================================================***/ + +#define DFLT_LINE_SIZE 128 + +typedef struct { + int line_num; + int sz_line; + int num_line; + char buf[DFLT_LINE_SIZE]; + char * line; +} InputLine; + +static void +#if NeedFunctionPrototypes +InitInputLine(InputLine *line) +#else +InitInputLine(line) + InputLine * line; +#endif +{ + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static void +#if NeedFunctionPrototypes +FreeInputLine(InputLine *line) +#else +FreeInputLine(line) + InputLine *line; +#endif +{ + if (line->line!=line->buf) + _XkbFree(line->line); + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static int +#if NeedFunctionPrototypes +InputLineAddChar(InputLine *line,int ch) +#else +InputLineAddChar(line,ch) + InputLine * line; + int ch; +#endif +{ + if (line->num_line>=line->sz_line) { + if (line->line==line->buf) { + line->line= (char *)_XkbAlloc(line->sz_line*2); + memcpy(line->line,line->buf,line->sz_line); + } + else { + line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2); + } + line->sz_line*= 2; + } + line->line[line->num_line++]= ch; + return ch; +} + +#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ + (int)((l)->line[(l)->num_line++]= (c)):\ + InputLineAddChar(l,c)) + +static Bool +#if NeedFunctionPrototypes +GetInputLine(FILE *file,InputLine *line,Bool checkbang) +#else +GetInputLine(file,line,checkbang) + FILE * file; + InputLine * line; + Bool checkbang; +#endif +{ +int ch; +Bool endOfFile,spacePending,slashPending,inComment; + + endOfFile= False; + while ((!endOfFile)&&(line->num_line==0)) { + spacePending= slashPending= inComment= False; + while (((ch=getc(file))!='\n')&&(ch!=EOF)) { + if (ch=='\\') { + if ((ch=getc(file))==EOF) + break; + if (ch=='\n') { + inComment= False; + ch= ' '; + line->line_num++; + } + } + if (inComment) + continue; + if (ch=='/') { + if (slashPending) { + inComment= True; + slashPending= False; + } + else { + slashPending= True; + } + continue; + } + else if (slashPending) { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= False; + } + ADD_CHAR(line,'/'); + slashPending= False; + } + if (isspace(ch)) { + while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) { + ch= getc(file); + } + if (ch==EOF) + break; + if ((ch!='\n')&&(line->num_line>0)) + spacePending= True; + ungetc(ch,file); + } + else { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= False; + } + if (checkbang && ch=='!') { + if (line->num_line!=0) { + PR_DEBUG("The '!' legal only at start of line\n"); + PR_DEBUG("Line containing '!' ignored\n"); + line->num_line= 0; + inComment= 0; + break; + } + + } + ADD_CHAR(line,ch); + } + } + if (ch==EOF) + endOfFile= True; +/* else line->num_line++;*/ + } + if ((line->num_line==0)&&(endOfFile)) + return False; + ADD_CHAR(line,'\0'); + return True; +} + +/***====================================================================***/ + +#define MODEL 0 +#define LAYOUT 1 +#define VARIANT 2 +#define OPTION 3 +#define KEYCODES 4 +#define SYMBOLS 5 +#define TYPES 6 +#define COMPAT 7 +#define GEOMETRY 8 +#define KEYMAP 9 +#define MAX_WORDS 10 + +#define PART_MASK 0x000F +#define COMPONENT_MASK 0x03F0 + +static char * cname[MAX_WORDS] = { + "model", "layout", "variant", "option", + "keycodes", "symbols", "types", "compat", "geometry", "keymap" +}; + +typedef struct _RemapSpec { + int num_remap; + int remap[MAX_WORDS]; +} RemapSpec; + +typedef struct _FileSpec { + char * name[MAX_WORDS]; + struct _FileSpec * pending; +} FileSpec; + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +SetUpRemap(InputLine *line,RemapSpec *remap) +#else +SetUpRemap(line,remap) + InputLine * line; + RemapSpec * remap; +#endif +{ +char * tok,*str; +unsigned present; +register int i; +#ifdef DEBUG +Bool found; +#endif +_Xstrtokparams strtok_buf; + + present= 0; + str= &line->line[1]; + bzero((char *)remap,sizeof(RemapSpec)); + while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { +#ifdef DEBUG + found= False; +#endif + str= NULL; + if (strcmp(tok,"=")==0) + continue; + for (i=0;iremap[remap->num_remap++]= i; + break; + } + } +#ifdef DEBUG + if (!found) { + fprintf(stderr,"Unknown component \"%s\" ignored\n",tok); + } +#endif + } + if ((present&PART_MASK)==0) { +#ifdef DEBUG + unsigned mask= PART_MASK; + fprintf(stderr,"Mapping needs at one of "); + for (i=0;(inum_remap= 0; + return; + } + if ((present&COMPONENT_MASK)==0) { + PR_DEBUG("Mapping needs at least one component\n"); + PR_DEBUG("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + if (((present&PART_MASK)&(1<num_remap= 0; + return; + } + if (((present&COMPONENT_MASK)&(1<num_remap= 0; + return; + } + return; +} + +static Bool +#if NeedFunctionPrototypes +MatchOneOf(char *wanted,char *vals_defined) +#else +MatchOneOf(wanted,vals_defined) + char * wanted; + char * vals_defined; +#endif +{ +char *str,*next; +int want_len= strlen(wanted); + + for (str=vals_defined,next=NULL;str!=NULL;str=next) { + int len; + next= strchr(str,','); + if (next) { + len= next-str; + next++; + } + else { + len= strlen(str); + } + if ((len==want_len)&&(strncmp(wanted,str,len)==0)) + return True; + } + return False; +} + +/***====================================================================***/ + +static Bool +#if NeedFunctionPrototypes +CheckLine( InputLine * line, + RemapSpec * remap, + XkbRF_RulePtr rule) +#else +CheckLine(line,remap,rule) + InputLine * line; + RemapSpec * remap; + XkbRF_RulePtr rule; +#endif +{ +char * str,*tok; +register int nread; +FileSpec tmp; +_Xstrtokparams strtok_buf; + + if (line->line[0]=='!') { + SetUpRemap(line,remap); + return False; + } + if (remap->num_remap==0) { + PR_DEBUG("Must have a mapping before first line of data\n"); + PR_DEBUG("Illegal line of data ignored\n"); + return False; + } + bzero((char *)&tmp,sizeof(FileSpec)); + str= line->line; + for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) { + str= NULL; + if (strcmp(tok,"=")==0) { + nread--; + continue; + } + if (nread>remap->num_remap) { + PR_DEBUG("Too many words on a line\n"); + PR_DEBUG1("Extra word \"%s\" ignored\n",tok); + continue; + } + tmp.name[remap->remap[nread]]= tok; + } + if (nreadnum_remap) { + PR_DEBUG("Too few words on a line\n"); + PR_DEBUG("line ignored\n"); + return False; + } + if ((tmp.name[MODEL]!=NULL)&&(strcmp(tmp.name[MODEL],"*")==0)) + tmp.name[MODEL]= NULL; + if ((tmp.name[LAYOUT]!=NULL)&&(strcmp(tmp.name[LAYOUT],"*")==0)) + tmp.name[LAYOUT]= NULL; + if ((tmp.name[VARIANT]!=NULL)&&(strcmp(tmp.name[VARIANT],"*")==0)) + tmp.name[VARIANT]= NULL; + + rule->flags= 0; + if (tmp.name[OPTION]) + rule->flags|= XkbRF_Delayed|XkbRF_Append; + rule->model= _XkbDupString(tmp.name[MODEL]); + rule->layout= _XkbDupString(tmp.name[LAYOUT]); + rule->variant= _XkbDupString(tmp.name[VARIANT]); + rule->option= _XkbDupString(tmp.name[OPTION]); + + rule->keycodes= _XkbDupString(tmp.name[KEYCODES]); + rule->symbols= _XkbDupString(tmp.name[SYMBOLS]); + rule->types= _XkbDupString(tmp.name[TYPES]); + rule->compat= _XkbDupString(tmp.name[COMPAT]); + rule->geometry= _XkbDupString(tmp.name[GEOMETRY]); + rule->keymap= _XkbDupString(tmp.name[KEYMAP]); + return True; +} + +static char * +#if NeedFunctionPrototypes +_Concat(char *str1,char *str2) +#else +_Concat(str1,str2) + char * str1; + char * str2; +#endif +{ +int len; + + if ((!str1)||(!str2)) + return str1; + len= strlen(str1)+strlen(str2)+1; + str1= _XkbTypedRealloc(str1,len,char); + if (str1) + strcat(str1,str2); + return str1; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_ApplyRule( XkbRF_RulePtr rule, + XkbComponentNamesPtr names) +#else +XkbRF_ApplyRule(rule,names) + XkbRF_RulePtr rule; + XkbComponentNamesPtr names; +#endif +{ + rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ + if ((rule->flags&XkbRF_Append)==0) { + if ((names->keycodes==NULL)&&(rule->keycodes!=NULL)) + names->keycodes= _XkbDupString(rule->keycodes); + + if ((names->symbols==NULL)&&(rule->symbols!=NULL)) + names->symbols= _XkbDupString(rule->symbols); + + if ((names->types==NULL)&&(rule->types!=NULL)) + names->types= _XkbDupString(rule->types); + + if ((names->compat==NULL)&&(rule->compat!=NULL)) + names->compat= _XkbDupString(rule->compat); + + if ((names->geometry==NULL)&&(rule->geometry!=NULL)) + names->geometry= _XkbDupString(rule->geometry); + + if ((names->keymap==NULL)&&(rule->keymap!=NULL)) + names->keymap= _XkbDupString(rule->keymap); + } + else { + if (rule->keycodes) + names->keycodes= _Concat(names->keycodes,rule->keycodes); + if (rule->symbols) + names->symbols= _Concat(names->symbols,rule->symbols); + if (rule->types) + names->types= _Concat(names->types,rule->types); + if (rule->compat) + names->compat= _Concat(names->compat,rule->compat); + if (rule->geometry) + names->geometry= _Concat(names->geometry,rule->geometry); + if (rule->keymap) + names->keymap= _Concat(names->keymap,rule->keymap); + } + return (names->keycodes && names->symbols && names->types && + names->compat && names->geometry ) || names->keymap; +} + +#define CHECK_MATCH(r,d) ((((r)[0]=='?')&&((r)[1]=='\0'))||(strcmp(r,d)==0)) + +Bool +#if NeedFunctionPrototypes +XkbRF_CheckApplyRule( XkbRF_RulePtr rule, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_CheckApplyRule(rule,defs,names) + XkbRF_RulePtr rule; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ + if (rule->model!=NULL) { + if ((!defs->model)||(!CHECK_MATCH(rule->model,defs->model))) + return False; + } + if (rule->layout!=NULL) { + if ((!defs->layout)||(!CHECK_MATCH(rule->layout,defs->layout))) + return False; + } + if (rule->variant!=NULL) { + if ((!defs->variant)||(!CHECK_MATCH(rule->variant,defs->variant))) + return False; + } + if (rule->option!=NULL) { + if ((!defs->options)||(!MatchOneOf(rule->option,defs->options))) + return False; + } + + if ((!rule->option)&& + ((!rule->model)||(!rule->layout)||(!rule->variant))) { + /* partial map -- partial maps are applied in the order they */ + /* appear, but all partial maps come before any options. */ + rule->flags|= XkbRF_PendingMatch; + return False; + } + /* exact match, apply it now */ + return XkbRF_ApplyRule(rule,names); +} + +void +#if NeedFunctionPrototypes +XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) +#else +XkbRF_ClearPartialMatches(rules) + XkbRF_RulesPtr rules; +#endif +{ +register int i; +XkbRF_RulePtr rule; + + for (i=0,rule=rules->rules;inum_rules;i++,rule++) { + rule->flags&= ~XkbRF_PendingMatch; + } +} + +Bool +#if NeedFunctionPrototypes +XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) +#else +XkbRF_ApplyPartialMatches(rules,names) + XkbRF_RulesPtr rules; + XkbComponentNamesPtr names; +#endif +{ +int i; +XkbRF_RulePtr rule; +Bool complete; + + complete= False; + for (rule=rules->rules,i=0;(inum_rules)&&(!complete);i++,rule++) { + if ((rule->flags&XkbRF_PendingMatch)==0) + continue; + complete= XkbRF_ApplyRule(rule,names); + } + return complete; +} + +void +#if NeedFunctionPrototypes +XkbRF_CheckApplyDelayedRules( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_CheckApplyDelayedRules(rules,defs,names) + XkbRF_RulesPtr rules; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +int i; +XkbRF_RulePtr rule; + + for (rule=rules->rules,i=0;(inum_rules);i++,rule++) { + if ((rule->flags&XkbRF_Delayed)==0) + continue; + XkbRF_CheckApplyRule(rule,defs,names); + } + return; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_CheckApplyRules( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_CheckApplyRules(rules,defs,names) + XkbRF_RulesPtr rules; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +int i; +XkbRF_RulePtr rule; +Bool complete; + + complete= False; + for (rule=rules->rules,i=0;(inum_rules)&&(!complete);i++,rule++) { + if ((rule->flags&XkbRF_Delayed)!=0) + continue; + complete= XkbRF_CheckApplyRule(rule,defs,names); + } + return complete; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbRF_SubstituteVars(char *name,XkbRF_VarDefsPtr defs) +#else +XkbRF_SubstituteVars(name,defs) + char * name; + XkbRF_VarDefsPtr defs; +#endif +{ +char *str,*outstr,*orig; +int len; + + orig= name; + str= index(name,'%'); + if (str==NULL) + return name; + len= strlen(name); + while (str!=NULL) { + char pfx= str[1]; + int extra_len= 0; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + extra_len= 1; + str++; + } + else if (pfx=='(') { + extra_len= 2; + str++; + } + + if ((str[1]=='l')&&defs->layout) + len+= strlen(defs->layout)+extra_len; + else if ((str[1]=='m')&&defs->model) + len+= strlen(defs->model)+extra_len; + else if ((str[1]=='v')&&defs->variant) + len+= strlen(defs->variant)+extra_len; + if ((pfx=='(')&&(str[2]==')')) { + str++; + } + str= index(&str[1],'%'); + } + name= (char *)_XkbAlloc(len+1); + str= orig; + outstr= name; + while (*str!='\0') { + if (str[0]=='%') { + char pfx,sfx; + str++; + pfx= str[0]; + sfx= '\0'; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + str++; + } + else if (pfx=='(') { + sfx= ')'; + str++; + } + else pfx= '\0'; + + if ((str[0]=='l')&&(defs->layout)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,defs->layout); + outstr+= strlen(defs->layout); + if (sfx) *outstr++= sfx; + } + else if ((str[0]=='m')&&(defs->model)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,defs->model); + outstr+= strlen(defs->model); + if (sfx) *outstr++= sfx; + } + else if ((str[0]=='v')&&(defs->variant)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,defs->variant); + outstr+= strlen(defs->variant); + if (sfx) *outstr++= sfx; + } + str++; + if ((pfx=='(')&&(str[0]==')')) + str++; + } + else { + *outstr++= *str++; + } + } + *outstr++= '\0'; + if (orig!=name) + _XkbFree(orig); + return name; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbRF_GetComponents( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_GetComponents(rules,defs,names) + XkbRF_RulesPtr rules; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +Bool complete; + + bzero((char *)names,sizeof(XkbComponentNamesRec)); + XkbRF_ClearPartialMatches(rules); + complete= XkbRF_CheckApplyRules(rules,defs,names); + if (!complete) + complete= XkbRF_ApplyPartialMatches(rules,names); + XkbRF_CheckApplyDelayedRules(rules,defs,names); + if (names->keycodes) + names->keycodes= XkbRF_SubstituteVars(names->keycodes,defs); + if (names->symbols) + names->symbols= XkbRF_SubstituteVars(names->symbols,defs); + if (names->types) + names->types= XkbRF_SubstituteVars(names->types,defs); + if (names->compat) + names->compat= XkbRF_SubstituteVars(names->compat,defs); + if (names->geometry) + names->geometry= XkbRF_SubstituteVars(names->geometry,defs); + if (names->keymap) + names->keymap= XkbRF_SubstituteVars(names->keymap,defs); + return (names->keycodes && names->symbols && names->types && + names->compat && names->geometry ) || names->keymap; +} + +XkbRF_RulePtr +#if NeedFunctionPrototypes +XkbRF_AddRule(XkbRF_RulesPtr rules) +#else +XkbRF_AddRule(rules) + XkbRF_RulesPtr rules; +#endif +{ + if (rules->sz_rules<1) { + rules->sz_rules= 16; + rules->num_rules= 0; + rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); + } + else if (rules->num_rules>=rules->sz_rules) { + rules->sz_rules*= 2; + rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules, + XkbRF_RuleRec); + } + if (!rules->rules) { + rules->sz_rules= rules->num_rules= 0; +#ifdef DEBUG + fprintf(stderr,"Allocation failure in XkbRF_AddRule\n"); +#endif + return NULL; + } + bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec)); + return &rules->rules[rules->num_rules++]; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) +#else +XkbRF_LoadRules(file,rules) + FILE * file; + XkbRF_RulesPtr rules; +#endif +{ +InputLine line; +RemapSpec remap; +XkbRF_RuleRec trule,*rule; + + if (!(rules && file)) + return False; + bzero((char *)&remap,sizeof(RemapSpec)); + InitInputLine(&line); + while (GetInputLine(file,&line,True)) { + if (CheckLine(&line,&remap,&trule)) { + if ((rule= XkbRF_AddRule(rules))!=NULL) { + *rule= trule; + bzero((char *)&trule,sizeof(XkbRF_RuleRec)); + } + } + line.num_line= 0; + } + FreeInputLine(&line); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) +#else +XkbRF_LoadRulesByName(base,locale,rules) + char * base; + char * locale; + XkbRF_RulesPtr rules; +#endif +{ +FILE * file; +char buf[PATH_MAX]; +Bool ok; + + if ((!base)||(!rules)) + return False; + if (locale) { + if (strlen(base)+strlen(locale)+2 > PATH_MAX) + return False; + sprintf(buf,"%s-%s", base, locale); + } + else { + if (strlen(base)+1 > PATH_MAX) + return False; + strcpy(buf,base); + } + + file= fopen(buf, "r"); + if ((!file)&&(locale)) { /* fallback if locale was specified */ + strcpy(buf,base); + file= fopen(buf, "r"); + } + if (!file) + return False; + ok= XkbRF_LoadRules(file,rules); + fclose(file); + return ok; +} + +/***====================================================================***/ + +#define HEAD_NONE 0 +#define HEAD_MODEL 1 +#define HEAD_LAYOUT 2 +#define HEAD_VARIANT 3 +#define HEAD_OPTION 4 +#define HEAD_EXTRA 5 + +XkbRF_VarDescPtr +#if NeedFunctionPrototypes +XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars) +#else +XkbRF_AddVarDesc(vars) + XkbRF_DescribeVarsPtr vars; +#endif +{ + if (vars->sz_desc<1) { + vars->sz_desc= 16; + vars->num_desc= 0; + vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec); + } + else if (vars->num_desc>=vars->sz_desc) { + vars->sz_desc*= 2; + vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec); + } + if (!vars->desc) { + vars->sz_desc= vars->num_desc= 0; + PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n"); + return NULL; + } + vars->desc[vars->num_desc].name= NULL; + vars->desc[vars->num_desc].desc= NULL; + return &vars->desc[vars->num_desc++]; +} + +XkbRF_VarDescPtr +#if NeedFunctionPrototypes +XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from) +#else +XkbRF_AddVarDescCopy(vars,from) + XkbRF_DescribeVarsPtr vars; + XkbRF_VarDescPtr from; +#endif +{ +XkbRF_VarDescPtr nd; + + if ((nd=XkbRF_AddVarDesc(vars))!=NULL) { + nd->name= _XkbDupString(from->name); + nd->desc= _XkbDupString(from->desc); + } + return nd; +} + +XkbRF_DescribeVarsPtr +#if NeedFunctionPrototypes +XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name) +#else +XkbRF_AddVarToDescribe(rules,name) + XkbRF_RulesPtr rules; + char * name; +#endif +{ + if (rules->sz_extra<1) { + rules->num_extra= 0; + rules->sz_extra= 1; + rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *); + rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec); + } + else if (rules->num_extra>=rules->sz_extra) { + rules->sz_extra*= 2; + rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra, + char *); + rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra, + XkbRF_DescribeVarsRec); + } + if ((!rules->extra_names)||(!rules->extra)) { + PR_DEBUG("allocation error in extra parts\n"); + rules->sz_extra= rules->num_extra= 0; + rules->extra_names= NULL; + rules->extra= NULL; + return NULL; + } + rules->extra_names[rules->num_extra]= _XkbDupString(name); + bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec)); + return &rules->extra[rules->num_extra++]; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules) +#else +XkbRF_LoadDescriptions(file,rules) + FILE * file; + XkbRF_RulesPtr rules; +#endif +{ +InputLine line; +XkbRF_VarDescRec tmp; +char *tok; +int len,headingtype,extra_ndx; + + bzero((char *)&tmp, sizeof(XkbRF_VarDescRec)); + headingtype = HEAD_NONE; + InitInputLine(&line); + for ( ; GetInputLine(file,&line,False); line.num_line= 0) { + if (line.line[0]=='!') { + tok = strtok(&(line.line[1]), " \t"); + if (!_XkbStrCaseCmp(tok,"model")) + headingtype = HEAD_MODEL; + else if (!_XkbStrCaseCmp(tok,"layout")) + headingtype = HEAD_LAYOUT; + else if (!_XkbStrCaseCmp(tok,"variant")) + headingtype = HEAD_VARIANT; + else if (!_XkbStrCaseCmp(tok,"option")) + headingtype = HEAD_OPTION; + else { + int i; + headingtype = HEAD_EXTRA; + extra_ndx= -1; + for (i=0;(inum_extra)&&(extra_ndx<0);i++) { + if (!_XkbStrCaseCmp(tok,rules->extra_names[i])) + extra_ndx= i; + } + if (extra_ndx<0) { + XkbRF_DescribeVarsPtr var; + PR_DEBUG1("Extra heading \"%s\" encountered\n",tok); + var= XkbRF_AddVarToDescribe(rules,tok); + if (var) + extra_ndx= var-rules->extra; + else headingtype= HEAD_NONE; + } + } + continue; + } + + if (headingtype == HEAD_NONE) { + PR_DEBUG("Must have a heading before first line of data\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + + len = strlen(line.line); + if ((tmp.name= strtok(line.line, " \t")) == NULL) { + PR_DEBUG("Huh? No token on line\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + if (strlen(tmp.name) == len) { + PR_DEBUG("No description found\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + + tok = line.line + strlen(tmp.name) + 1; + while ((*tok!='\n')&&isspace(*tok)) + tok++; + if (*tok == '\0') { + PR_DEBUG("No description found\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + tmp.desc= tok; + switch (headingtype) { + case HEAD_MODEL: + XkbRF_AddVarDescCopy(&rules->models,&tmp); + break; + case HEAD_LAYOUT: + XkbRF_AddVarDescCopy(&rules->layouts,&tmp); + break; + case HEAD_VARIANT: + XkbRF_AddVarDescCopy(&rules->variants,&tmp); + break; + case HEAD_OPTION: + XkbRF_AddVarDescCopy(&rules->options,&tmp); + break; + case HEAD_EXTRA: + XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp); + break; + } + } + FreeInputLine(&line); + if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) && + (rules->variants.num_desc==0) && (rules->options.num_desc==0) && + (rules->num_extra==0)) { + return False; + } + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules) +#else +XkbRF_LoadDescriptionsByName(base,locale,rules) + char * base; + char * locale; + XkbRF_RulesPtr rules; +#endif +{ +FILE * file; +char buf[PATH_MAX]; +Bool ok; + + if ((!base)||(!rules)) + return False; + if (locale) { + if (strlen(base)+strlen(locale)+6 > PATH_MAX) + return False; + sprintf(buf,"%s-%s.lst", base, locale); + } + else { + if (strlen(base)+5 > PATH_MAX) + return False; + sprintf(buf,"%s.lst", base); + } + + file= fopen(buf, "r"); + if ((!file)&&(locale)) { /* fallback if locale was specified */ + sprintf(buf,"%s.lst", base); + + file= fopen(buf, "r"); + } + if (!file) + return False; + ok= XkbRF_LoadDescriptions(file,rules); + fclose(file); + return ok; +} + +/***====================================================================***/ + +XkbRF_RulesPtr +#if NeedFunctionPrototypes +XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules) +#else +XkbRF_Load(base,locale,wantDesc,wantRules) + char *base; + char *locale; + Bool wantDesc; + Bool wantRules; +#endif +{ +XkbRF_RulesPtr rules; + + if ((!base)||((!wantDesc)&&(!wantRules))) + return NULL; + if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) + return NULL; + if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) { + XkbRF_Free(rules,True); + return NULL; + } + if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) { + XkbRF_Free(rules,True); + return NULL; + } + return rules; +} + +XkbRF_RulesPtr +XkbRF_Create(int szRules,int szExtra) +{ +XkbRF_RulesPtr rules; + + if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) + return NULL; + if (szRules>0) { + rules->sz_rules= szRules; + rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); + if (!rules->rules) { + _XkbFree(rules); + return NULL; + } + } + if (szExtra>0) { + rules->sz_extra= szExtra; + rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec); + if (!rules->extra) { + if (rules->rules) + _XkbFree(rules->rules); + _XkbFree(rules); + return NULL; + } + } + return rules; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var) +#else +XkbRF_ClearVarDescriptions(var) + XkbRF_DescribeVarsPtr var; +#endif +{ +register int i; + + for (i=0;inum_desc;i++) { + if (var->desc[i].name) + _XkbFree(var->desc[i].name); + if (var->desc[i].desc) + _XkbFree(var->desc[i].desc); + var->desc[i].name= var->desc[i].desc= NULL; + } + if (var->desc) + _XkbFree(var->desc); + var->desc= NULL; + return; +} + +void +#if NeedFunctionPrototypes +XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) +#else +XkbRF_Free(rules,freeRules) + XkbRF_RulesPtr rules; + Bool freeRules; +#endif +{ +int i; +XkbRF_RulePtr rule; + + if (!rules) + return; + XkbRF_ClearVarDescriptions(&rules->models); + XkbRF_ClearVarDescriptions(&rules->layouts); + XkbRF_ClearVarDescriptions(&rules->variants); + XkbRF_ClearVarDescriptions(&rules->options); + if (rules->extra) { + for (i = 0; i < rules->num_extra; i++) { + XkbRF_ClearVarDescriptions(&rules->extra[i]); + } + _XkbFree(rules->extra); + rules->num_extra= rules->sz_extra= 0; + rules->extra= NULL; + } + if (rules->rules) { + for (i=0,rule=rules->rules;inum_rules;i++,rule++) { + if (rule->model) _XkbFree(rule->model); + if (rule->layout) _XkbFree(rule->layout); + if (rule->variant) _XkbFree(rule->variant); + if (rule->option) _XkbFree(rule->option); + if (rule->keycodes) _XkbFree(rule->keycodes); + if (rule->symbols) _XkbFree(rule->symbols); + if (rule->types) _XkbFree(rule->types); + if (rule->compat) _XkbFree(rule->compat); + if (rule->geometry) _XkbFree(rule->geometry); + if (rule->keymap) _XkbFree(rule->keymap); + bzero((char *)rule,sizeof(XkbRF_RuleRec)); + } + _XkbFree(rules->rules); + rules->num_rules= rules->sz_rules= 0; + rules->rules= NULL; + } + if (freeRules) + _XkbFree(rules); + return; +} + +#ifndef XKB_IN_SERVER + +Bool +#if NeedFunctionPrototypes +XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn) +#else +XkbRF_GetNamesProp(dpy,rf_rtrn,vd_rtrn) + Display * dpy; + char ** rf_rtrn; + XkbRF_VarDefsPtr vd_rtrn; +#endif +{ +Atom rules_atom,actual_type; +int fmt; +unsigned long nitems,bytes_after; +char *data,*out; +Status rtrn; + + rules_atom= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,True); + if (rules_atom==None) /* property cannot exist */ + return False; + rtrn= XGetWindowProperty(dpy,DefaultRootWindow(dpy),rules_atom, + 0L,_XKB_RF_NAMES_PROP_MAXLEN,False, + XA_STRING,&actual_type, + &fmt,&nitems,&bytes_after, + (unsigned char **)&data); + if (rtrn!=Success) + return False; + if (rf_rtrn) + *rf_rtrn= NULL; + (void)bzero((char *)vd_rtrn,sizeof(XkbRF_VarDefsRec)); + if ((bytes_after>0)||(actual_type!=XA_STRING)||(fmt!=8)) { + if (data) XFree(data); + return (fmt==0?True:False); + } + + out= data; + if (out && (*out) && rf_rtrn) + *rf_rtrn= _XkbDupString(out); + out+=strlen(out)+1; + + if ((out-data)model= _XkbDupString(out); + out+=strlen(out)+1; + } + + if ((out-data)layout= _XkbDupString(out); + out+=strlen(out)+1; + } + + if ((out-data)variant= _XkbDupString(out); + out+=strlen(out)+1; + } + + + if ((out-data)options= _XkbDupString(out); + out+=strlen(out)+1; + } + XFree(data); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs) +#else +XkbRF_SetNamesProp(dpy,rules_file,var_defs) + Display * dpy; + char * rules_file; + XkbRF_VarDefsPtr var_defs; +#endif +{ +int len,out; +Atom name; +char * pval; + + len= (rules_file?strlen(rules_file):0); + len+= (var_defs->model?strlen(var_defs->model):0); + len+= (var_defs->layout?strlen(var_defs->layout):0); + len+= (var_defs->variant?strlen(var_defs->variant):0); + len+= (var_defs->options?strlen(var_defs->options):0); + if (len<1) + return True; + + len+= 5; /* trailing NULs */ + + name= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,False); + if (name==None) { /* should never happen */ + _XkbLibError(_XkbErrXReqFailure,"XkbRF_SetNamesProp",X_InternAtom); + return False; + } + pval= (char *)_XkbAlloc(len); + if (!pval) { + _XkbLibError(_XkbErrBadAlloc,"XkbRF_SetNamesProp",len); + return False; + } + out= 0; + if (rules_file) { + strcpy(&pval[out],rules_file); + out+= strlen(rules_file); + } + pval[out++]= '\0'; + if (var_defs->model) { + strcpy(&pval[out],var_defs->model); + out+= strlen(var_defs->model); + } + pval[out++]= '\0'; + if (var_defs->layout) { + strcpy(&pval[out],var_defs->layout); + out+= strlen(var_defs->layout); + } + pval[out++]= '\0'; + if (var_defs->variant) { + strcpy(&pval[out],var_defs->variant); + out+= strlen(var_defs->variant); + } + pval[out++]= '\0'; + if (var_defs->options) { + strcpy(&pval[out],var_defs->options); + out+= strlen(var_defs->options); + } + pval[out++]= '\0'; + if (out!=len) { + _XkbLibError(_XkbErrBadLength,"XkbRF_SetNamesProp",out); + _XkbFree(pval); + return False; + } + + XChangeProperty(dpy,DefaultRootWindow(dpy),name,XA_STRING,8,PropModeReplace, + (unsigned char *)pval,len); + _XkbFree(pval); + return True; +} + +#endif diff --git a/xkb/xkb.c b/xkb/xkb.c new file mode 100644 index 000000000..6f75e8146 --- /dev/null +++ b/xkb/xkb.c @@ -0,0 +1,6929 @@ +/* $Xorg: xkb.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "extnsionst.h" + +#include "XI.h" + + int XkbEventBase; + int XkbErrorBase; + int XkbReqCode; + int XkbKeyboardErrorCode; +Atom xkbONE_LEVEL; +Atom xkbTWO_LEVEL; +Atom xkbKEYPAD; +CARD32 xkbDebugFlags = 0; +CARD32 xkbDebugCtrls = 0; + +#ifndef XKB_SRV_UNSUPPORTED_XI_FEATURES +#define XKB_SRV_UNSUPPORTED_XI_FEATURES XkbXI_KeyboardsMask +#endif + +unsigned XkbXIUnsupported= XKB_SRV_UNSUPPORTED_XI_FEATURES; + +RESTYPE RT_XKBCLIENT; + +/***====================================================================***/ + +#define CHK_DEVICE(d,sp,lf) {\ + int why;\ + d = (DeviceIntPtr)lf((sp),&why);\ + if (!dev) {\ + client->errorValue = _XkbErrCode2(why,(sp));\ + return XkbKeyboardErrorCode;\ + }\ +} + +#define CHK_KBD_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupKeyboard) +#define CHK_LED_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupLedDevice) +#define CHK_BELL_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupBellDevice) +#define CHK_ANY_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupAnyDevice) + +#define CHK_ATOM_ONLY2(a,ev,er) {\ + if (((a)==None)||(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_ONLY(a) \ + CHK_ATOM_ONLY2(a,client->errorValue,BadAtom) + +#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + (er)= BadAtom;\ + return ret;\ + }\ +} +#define CHK_ATOM_OR_NONE2(a,ev,er) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_OR_NONE(a) \ + CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom) + +#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + (er)= BadValue;\ + return ret;\ + }\ +} +#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + return er;\ + }\ +} +#define CHK_MASK_LEGAL(err,mask,legal) \ + CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue) + +#define CHK_MASK_MATCH(err,affect,value) {\ + if ((value)&(~(affect))) { \ + client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\ + return BadMatch;\ + }\ +} +#define CHK_MASK_OVERLAP(err,m1,m2) {\ + if ((m1)&(m2)) { \ + client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\ + return BadMatch;\ + }\ +} +#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\ + (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\ + return er;\ + }\ + else if ( (first)<(x)->min_key_code ) {\ + (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\ + return er;\ + }\ +} +#define CHK_KEY_RANGE(err,first,num,x) \ + CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue) + +#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\ + (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\ + return er;\ + }\ + else if ( (first)<(r)->minKeyCode ) {\ + (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\ + return er;\ + }\ +} +#define CHK_REQ_KEY_RANGE(err,first,num,r) \ + CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbUseExtension(ClientPtr client) +#else +ProcXkbUseExtension(client) + ClientPtr client; +#endif +{ + REQUEST(xkbUseExtensionReq); + xkbUseExtensionReply rep; + register int n; + int supported; + + REQUEST_SIZE_MATCH(xkbUseExtensionReq); + if (stuff->wantedMajor != XkbMajorVersion) { + /* pre-release version 0.65 is compatible with 1.00 */ + supported= ((XkbMajorVersion==1)&& + (stuff->wantedMajor==0)&&(stuff->wantedMinor==65)); + } + else supported = 1; + +#ifdef XKB_SWAPPING_BUSTED + if (client->swapped) + supported= 0; +#endif + + if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) { + client->xkbClientFlags= _XkbClientInitialized; + client->vMajor= stuff->wantedMajor; + client->vMinor= stuff->wantedMinor; + } + else if (xkbDebugFlags&0x1) { + ErrorF("Rejecting client %d (0x%x) (wants %d.%02d, have %d.%02d)\n", + client->index, client->clientAsMask, + stuff->wantedMajor,stuff->wantedMinor, + XkbMajorVersion,XkbMinorVersion); + } + rep.type = X_Reply; + rep.supported = supported; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.serverMajor = XkbMajorVersion; + rep.serverMinor = XkbMinorVersion; + if ( client->swapped ) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.serverMajor, n); + swaps(&rep.serverMinor, n); + } + WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbSelectEvents(ClientPtr client) +#else +ProcXkbSelectEvents(client) + ClientPtr client; +#endif +{ + unsigned legal; + DeviceIntPtr dev; + XkbInterestPtr masks; + REQUEST(xkbSelectEventsReq); + + REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_ANY_DEVICE(dev,stuff->deviceSpec); + + if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) { + client->mapNotifyMask&= ~stuff->affectMap; + client->mapNotifyMask|= (stuff->affectMap&stuff->map); + } + if (stuff->affectWhich&(~XkbMapNotifyMask)==0) + return client->noClientException; + + masks = XkbFindClientResource((DevicePtr)dev,client); + if (!masks){ + XID id = FakeClientID(client->index); + AddResource(id,RT_XKBCLIENT,dev); + masks= XkbAddClientResource((DevicePtr)dev,client,id); + } + if (masks) { + union { + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } from,to; + register unsigned bit,ndx,maskLeft,dataLeft,size; + + from.c8= (CARD8 *)&stuff[1]; + dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq); + maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask)); + for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) { + if ((bit&maskLeft)==0) + continue; + maskLeft&= ~bit; + switch (ndx) { + case XkbNewKeyboardNotify: + to.c16= &client->newKeyboardNotifyMask; + legal= XkbAllNewKeyboardEventsMask; + size= 2; + break; + case XkbStateNotify: + to.c16= &masks->stateNotifyMask; + legal= XkbAllStateEventsMask; + size= 2; + break; + case XkbControlsNotify: + to.c32= &masks->ctrlsNotifyMask; + legal= XkbAllControlEventsMask; + size= 4; + break; + case XkbIndicatorStateNotify: + to.c32= &masks->iStateNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbIndicatorMapNotify: + to.c32= &masks->iMapNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbNamesNotify: + to.c16= &masks->namesNotifyMask; + legal= XkbAllNameEventsMask; + size= 2; + break; + case XkbCompatMapNotify: + to.c8= &masks->compatNotifyMask; + legal= XkbAllCompatMapEventsMask; + size= 1; + break; + case XkbBellNotify: + to.c8= &masks->bellNotifyMask; + legal= XkbAllBellEventsMask; + size= 1; + break; + case XkbActionMessage: + to.c8= &masks->actionMessageMask; + legal= XkbAllActionMessagesMask; + size= 1; + break; + case XkbAccessXNotify: + to.c16= &masks->accessXNotifyMask; + legal= XkbAllAccessXEventsMask; + size= 2; + break; + case XkbExtensionDeviceNotify: + to.c16= &masks->extDevNotifyMask; + legal= XkbAllExtensionDeviceEventsMask; + size= 2; + break; + default: + client->errorValue = _XkbErrCode2(33,bit); + return BadValue; + } + + if (stuff->clear&bit) { + if (size==2) to.c16[0]= 0; + else if (size==4) to.c32[0]= 0; + else to.c8[0]= 0; + } + else if (stuff->selectAll&bit) { + if (size==2) to.c16[0]= ~0; + else if (size==4) to.c32[0]= ~0; + else to.c8[0]= ~0; + } + else { + if (dataLeft<(size*2)) + return BadLength; + if (size==2) { + CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]); + CHK_MASK_LEGAL(ndx,from.c16[0],legal); + to.c16[0]&= ~from.c16[0]; + to.c16[0]|= (from.c16[0]&from.c16[1]); + } + else if (size==4) { + CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]); + CHK_MASK_LEGAL(ndx,from.c32[0],legal); + to.c32[0]&= ~from.c32[0]; + to.c32[0]|= (from.c32[0]&from.c32[1]); + } + else { + CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]); + CHK_MASK_LEGAL(ndx,from.c8[0],legal); + to.c8[0]&= ~from.c8[0]; + to.c8[0]|= (from.c8[0]&from.c8[1]); + size= 2; + } + from.c8+= (size*2); + dataLeft-= (size*2); + } + } + if (dataLeft>2) { + ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + return client->noClientException; + } + return BadAlloc; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbBell(ClientPtr client) +#else +ProcXkbBell(client) + ClientPtr client; +#endif +{ + REQUEST(xkbBellReq); + DeviceIntPtr dev; + WindowPtr pWin; + int base; + int newPercent,oldPitch,oldDuration; + pointer ctrl; + + REQUEST_SIZE_MATCH(xkbBellReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_BELL_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_OR_NONE(stuff->name); + + if ((stuff->forceSound)&&(stuff->eventOnly)) { + client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly); + return BadMatch; + } + if (stuff->percent < -100 || stuff->percent > 100) { + client->errorValue = _XkbErrCode2(0x2,stuff->percent); + return BadValue; + } + if (stuff->duration<-1) { + client->errorValue = _XkbErrCode2(0x3,stuff->duration); + return BadValue; + } + if (stuff->pitch<-1) { + client->errorValue = _XkbErrCode2(0x4,stuff->pitch); + return BadValue; + } + + if (stuff->bellClass == XkbDfltXIClass) { + if (dev->kbdfeed!=NULL) + stuff->bellClass= KbdFeedbackClass; + else stuff->bellClass= BellFeedbackClass; + } + if (stuff->bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + if (stuff->bellID==XkbDfltXIId) + k= dev->kbdfeed; + else { + for (k=dev->kbdfeed; k; k=k->next) { + if (k->ctrl.id == stuff->bellID) + break; + } + } + if (!k) { + client->errorValue= _XkbErrCode2(0x5,stuff->bellID); + return BadValue; + } + base = k->ctrl.bell; + ctrl = (pointer) &(k->ctrl); + oldPitch= k->ctrl.bell_pitch; + oldDuration= k->ctrl.bell_duration; + if (stuff->pitch!=0) { + if (stuff->pitch==-1) + k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch; + else k->ctrl.bell_pitch= stuff->pitch; + } + if (stuff->duration!=0) { + if (stuff->duration==-1) + k->ctrl.bell_duration= defaultKeyboardControl.bell_duration; + else k->ctrl.bell_duration= stuff->duration; + } + } + else if (stuff->bellClass == BellFeedbackClass) { + BellFeedbackPtr b; + if (stuff->bellID==XkbDfltXIId) + b= dev->bell; + else { + for (b=dev->bell; b; b=b->next) { + if (b->ctrl.id == stuff->bellID) + break; + } + } + if (!b) { + client->errorValue = _XkbErrCode2(0x6,stuff->bellID); + return BadValue; + } + base = b->ctrl.percent; + ctrl = (pointer) &(b->ctrl); + oldPitch= b->ctrl.pitch; + oldDuration= b->ctrl.duration; + if (stuff->pitch!=0) { + if (stuff->pitch==-1) + b->ctrl.pitch= defaultKeyboardControl.bell_pitch; + else b->ctrl.pitch= stuff->pitch; + } + if (stuff->duration!=0) { + if (stuff->duration==-1) + b->ctrl.duration= defaultKeyboardControl.bell_duration; + else b->ctrl.duration= stuff->duration; + } + } + else { + client->errorValue = _XkbErrCode2(0x7,stuff->bellClass);; + return BadValue; + } + if (stuff->window!=None) { + pWin= (WindowPtr)LookupIDByType(stuff->window,RT_WINDOW); + if (pWin==NULL) { + client->errorValue= stuff->window; + return BadValue; + } + } + else pWin= NULL; + + newPercent= (base*stuff->percent)/100; + if (stuff->percent < 0) + newPercent= base+newPercent; + else newPercent= base-newPercent+stuff->percent; + XkbHandleBell(stuff->forceSound, stuff->eventOnly, + dev, newPercent, ctrl, stuff->bellClass, + stuff->name, pWin, client); + if ((stuff->pitch!=0)||(stuff->duration!=0)) { + if (stuff->bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + k= (KbdFeedbackPtr)ctrl; + if (stuff->pitch!=0) + k->ctrl.bell_pitch= oldPitch; + if (stuff->duration!=0) + k->ctrl.bell_duration= oldDuration; + } + else { + BellFeedbackPtr b; + b= (BellFeedbackPtr)ctrl; + if (stuff->pitch!=0) + b->ctrl.pitch= oldPitch; + if (stuff->duration!=0) + b->ctrl.duration= oldDuration; + } + } + return Success; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetState(ClientPtr client) +#else +ProcXkbGetState(client) + ClientPtr client; +#endif +{ + REQUEST(xkbGetStateReq); + DeviceIntPtr dev; + xkbGetStateReply rep; + XkbStateRec *xkb; + + REQUEST_SIZE_MATCH(xkbGetStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb= &dev->key->xkbInfo->state; + bzero(&rep,sizeof(xkbGetStateReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.mods = dev->key->state&0xff; + rep.baseMods = xkb->base_mods; + rep.lockedMods = xkb->locked_mods; + rep.latchedMods = xkb->latched_mods; + rep.group = xkb->group; + rep.baseGroup = xkb->base_group; + rep.latchedGroup = xkb->latched_group; + rep.lockedGroup = xkb->locked_group; + rep.compatState = xkb->compat_state; + rep.ptrBtnState = xkb->ptr_buttons; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swaps(&rep.ptrBtnState,n); + } + WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbLatchLockState(ClientPtr client) +#else +ProcXkbLatchLockState(client) + ClientPtr client; +#endif +{ + int status; + DeviceIntPtr dev; + XkbStateRec oldState,*newState; + CARD16 changed; + + REQUEST(xkbLatchLockStateReq); + REQUEST_SIZE_MATCH(xkbLatchLockStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_MATCH(0x01,stuff->affectModLocks,stuff->modLocks); + CHK_MASK_MATCH(0x01,stuff->affectModLatches,stuff->modLatches); + + status = Success; + oldState= dev->key->xkbInfo->state; + newState= &dev->key->xkbInfo->state; + if ( stuff->affectModLocks ) { + newState->locked_mods&= ~stuff->affectModLocks; + newState->locked_mods|= (stuff->affectModLocks&stuff->modLocks); + } + if (( status == Success ) && stuff->lockGroup ) + newState->locked_group = stuff->groupLock; + if (( status == Success ) && stuff->affectModLatches ) + status=XkbLatchModifiers(dev,stuff->affectModLatches,stuff->modLatches); + if (( status == Success ) && stuff->latchGroup ) + status=XkbLatchGroup(dev,stuff->groupLatch); + + if ( status != Success ) + return status; + + XkbComputeDerivedState(dev->key->xkbInfo); + dev->key->state= XkbStateFieldFromRec(newState); + + changed = XkbStateChangedFlags(&oldState,newState); + if (changed) { + xkbStateNotify sn; + sn.keycode= 0; + sn.eventType= 0; + sn.requestMajor = XkbReqCode; + sn.requestMinor = X_kbLatchLockState; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + changed= XkbIndicatorsToUpdate(dev,changed,False); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseXkbReq(&cause,X_kbLatchLockState,client); + XkbUpdateIndicators(dev,changed,True,NULL,&cause); + } + } + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetControls(ClientPtr client) +#else +ProcXkbGetControls(client) + ClientPtr client; +#endif +{ + xkbGetControlsReply rep; + XkbControlsPtr xkb; + DeviceIntPtr dev; + register int n; + + REQUEST(xkbGetControlsReq); + REQUEST_SIZE_MATCH(xkbGetControlsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb = dev->key->xkbInfo->desc->ctrls; + rep.type = X_Reply; + rep.length = (SIZEOF(xkbGetControlsReply)- + SIZEOF(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.deviceID = ((DeviceIntPtr)dev)->id; + rep.numGroups = xkb->num_groups; + rep.groupsWrap = xkb->groups_wrap; + rep.internalMods = xkb->internal.mask; + rep.ignoreLockMods = xkb->ignore_lock.mask; + rep.internalRealMods = xkb->internal.real_mods; + rep.ignoreLockRealMods = xkb->ignore_lock.real_mods; + rep.internalVMods = xkb->internal.vmods; + rep.ignoreLockVMods = xkb->ignore_lock.vmods; + rep.enabledCtrls = xkb->enabled_ctrls; + rep.repeatDelay = xkb->repeat_delay; + rep.repeatInterval = xkb->repeat_interval; + rep.slowKeysDelay = xkb->slow_keys_delay; + rep.debounceDelay = xkb->debounce_delay; + rep.mkDelay = xkb->mk_delay; + rep.mkInterval = xkb->mk_interval; + rep.mkTimeToMax = xkb->mk_time_to_max; + rep.mkMaxSpeed = xkb->mk_max_speed; + rep.mkCurve = xkb->mk_curve; + rep.mkDfltBtn = xkb->mk_dflt_btn; + rep.axTimeout = xkb->ax_timeout; + rep.axtCtrlsMask = xkb->axt_ctrls_mask; + rep.axtCtrlsValues = xkb->axt_ctrls_values; + rep.axtOptsMask = xkb->axt_opts_mask; + rep.axtOptsValues = xkb->axt_opts_values; + rep.axOptions = xkb->ax_options; + memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length,n); + swaps(&rep.internalVMods, n); + swaps(&rep.ignoreLockVMods, n); + swapl(&rep.enabledCtrls, n); + swaps(&rep.repeatDelay, n); + swaps(&rep.repeatInterval, n); + swaps(&rep.slowKeysDelay, n); + swaps(&rep.debounceDelay, n); + swaps(&rep.mkDelay, n); + swaps(&rep.mkInterval, n); + swaps(&rep.mkTimeToMax, n); + swaps(&rep.mkMaxSpeed, n); + swaps(&rep.mkCurve, n); + swaps(&rep.axTimeout, n); + swapl(&rep.axtCtrlsMask, n); + swapl(&rep.axtCtrlsValues, n); + swaps(&rep.axtOptsMask, n); + swaps(&rep.axtOptsValues, n); + swaps(&rep.axOptions, n); + } + WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep); + return(client->noClientException); +} + +int +#if NeedFunctionPrototypes +ProcXkbSetControls(ClientPtr client) +#else +ProcXkbSetControls(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + XkbControlsPtr ctrl; + XkbControlsRec new,old; + xkbControlsNotify cn; + XkbEventCauseRec cause; + XkbSrvLedInfoPtr sli; + + REQUEST(xkbSetControlsReq); + REQUEST_SIZE_MATCH(xkbSetControlsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->changeCtrls,XkbAllControlsMask); + + xkbi = dev->key->xkbInfo; + ctrl = xkbi->desc->ctrls; + new = *ctrl; + XkbSetCauseXkbReq(&cause,X_kbSetControls,client); + if (stuff->changeCtrls&XkbInternalModsMask) { + CHK_MASK_MATCH(0x02,stuff->affectInternalMods,stuff->internalMods); + CHK_MASK_MATCH(0x03,stuff->affectInternalVMods,stuff->internalVMods); + new.internal.real_mods&=~stuff->affectInternalMods; + new.internal.real_mods|=(stuff->affectInternalMods&stuff->internalMods); + new.internal.vmods&=~stuff->affectInternalVMods; + new.internal.vmods|= (stuff->affectInternalVMods&stuff->internalVMods); + new.internal.mask= new.internal.real_mods| + XkbMaskForVMask(xkbi->desc,new.internal.vmods); + } + if (stuff->changeCtrls&XkbIgnoreLockModsMask) { + CHK_MASK_MATCH(0x4,stuff->affectIgnoreLockMods,stuff->ignoreLockMods); + CHK_MASK_MATCH(0x5,stuff->affectIgnoreLockVMods,stuff->ignoreLockVMods); + new.ignore_lock.real_mods&=~stuff->affectIgnoreLockMods; + new.ignore_lock.real_mods|= + (stuff->affectIgnoreLockMods&stuff->ignoreLockMods); + new.ignore_lock.vmods&= ~stuff->affectIgnoreLockVMods; + new.ignore_lock.vmods|= + (stuff->affectIgnoreLockVMods&stuff->ignoreLockVMods); + new.ignore_lock.mask= new.ignore_lock.real_mods| + XkbMaskForVMask(xkbi->desc,new.ignore_lock.vmods); + } + CHK_MASK_MATCH(0x06,stuff->affectEnabledCtrls,stuff->enabledCtrls); + if (stuff->affectEnabledCtrls) { + CHK_MASK_LEGAL(0x07,stuff->affectEnabledCtrls,XkbAllBooleanCtrlsMask); + new.enabled_ctrls&= ~stuff->affectEnabledCtrls; + new.enabled_ctrls|= (stuff->affectEnabledCtrls&stuff->enabledCtrls); + } + if (stuff->changeCtrls&XkbRepeatKeysMask) { + if ((stuff->repeatDelay<1)||(stuff->repeatInterval<1)) { + client->errorValue = _XkbErrCode3(0x08,stuff->repeatDelay, + stuff->repeatInterval); + return BadValue; + } + new.repeat_delay = stuff->repeatDelay; + new.repeat_interval = stuff->repeatInterval; + } + if (stuff->changeCtrls&XkbSlowKeysMask) { + if (stuff->slowKeysDelay<1) { + client->errorValue = _XkbErrCode2(0x09,stuff->slowKeysDelay); + return BadValue; + } + new.slow_keys_delay = stuff->slowKeysDelay; + } + if (stuff->changeCtrls&XkbBounceKeysMask) { + if (stuff->debounceDelay<1) { + client->errorValue = _XkbErrCode2(0x0A,stuff->debounceDelay); + return BadValue; + } + new.debounce_delay = stuff->debounceDelay; + } + if (stuff->changeCtrls&XkbMouseKeysMask) { + if (stuff->mkDfltBtn>XkbMaxMouseKeysBtn) { + client->errorValue = _XkbErrCode2(0x0B,stuff->mkDfltBtn); + return BadValue; + } + new.mk_dflt_btn = stuff->mkDfltBtn; + } + if (stuff->changeCtrls&XkbMouseKeysAccelMask) { + if ((stuff->mkDelay<1) || (stuff->mkInterval<1) || + (stuff->mkTimeToMax<1) || (stuff->mkMaxSpeed<1)|| + (stuff->mkCurve<-1000)) { + client->errorValue = _XkbErrCode2(0x0C,0); + return BadValue; + } + new.mk_delay = stuff->mkDelay; + new.mk_interval = stuff->mkInterval; + new.mk_time_to_max = stuff->mkTimeToMax; + new.mk_max_speed = stuff->mkMaxSpeed; + new.mk_curve = stuff->mkCurve; + AccessXComputeCurveFactor(xkbi,&new); + } + if (stuff->changeCtrls&XkbGroupsWrapMask) { + unsigned act,num; + act= XkbOutOfRangeGroupAction(stuff->groupsWrap); + switch (act) { + case XkbRedirectIntoRange: + num= XkbOutOfRangeGroupNumber(stuff->groupsWrap); + if (num>=new.num_groups) { + client->errorValue= _XkbErrCode3(0x0D,new.num_groups,num); + return BadValue; + } + case XkbWrapIntoRange: + case XkbClampIntoRange: + break; + default: + client->errorValue= _XkbErrCode2(0x0E,act); + return BadValue; + } + new.groups_wrap= stuff->groupsWrap; + } + CHK_MASK_LEGAL(0x0F,stuff->axOptions,XkbAX_AllOptionsMask); + if (stuff->changeCtrls&XkbAccessXKeysMask) + new.ax_options = stuff->axOptions&XkbAX_AllOptionsMask; + else { + if (stuff->changeCtrls&XkbStickyKeysMask) { + new.ax_options&= ~XkbAX_SKOptionsMask; + new.ax_options|= stuff->axOptions&XkbAX_SKOptionsMask; + } + if (stuff->changeCtrls&XkbAccessXFeedbackMask) { + new.ax_options&= ~XkbAX_FBOptionsMask; + new.ax_options|= stuff->axOptions&XkbAX_FBOptionsMask; + } + } + + if (stuff->changeCtrls&XkbAccessXTimeoutMask) { + if (stuff->axTimeout<1) { + client->errorValue = _XkbErrCode2(0x10,stuff->axTimeout); + return BadValue; + } + CHK_MASK_MATCH(0x11,stuff->axtCtrlsMask,stuff->axtCtrlsValues); + CHK_MASK_LEGAL(0x12,stuff->axtCtrlsMask,XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x13,stuff->axtOptsMask,stuff->axtOptsValues); + CHK_MASK_LEGAL(0x14,stuff->axtOptsMask,XkbAX_AllOptionsMask); + new.ax_timeout = stuff->axTimeout; + new.axt_ctrls_mask = stuff->axtCtrlsMask; + new.axt_ctrls_values = (stuff->axtCtrlsValues&stuff->axtCtrlsMask); + new.axt_opts_mask = stuff->axtOptsMask; + new.axt_opts_values= (stuff->axtOptsValues&stuff->axtOptsMask); + } + if (stuff->changeCtrls&XkbPerKeyRepeatMask) { + memcpy(new.per_key_repeat,stuff->perKeyRepeat,XkbPerKeyBitArraySize); + } + old= *ctrl; + *ctrl= new; + XkbDDXChangeControls(dev,&old,ctrl); + if (XkbComputeControlsNotify(dev,&old,ctrl,&cn,False)) { + cn.keycode= 0; + cn.eventType = 0; + cn.requestMajor = XkbReqCode; + cn.requestMinor = X_kbSetControls; + XkbSendControlsNotify(dev,&cn); + } + if ((sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0))!=NULL) + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); +#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrl->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(dev,xkbi,True,&cause); + } +#endif + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +XkbSetRepeatRate(DeviceIntPtr dev,int timeout,int interval,int major,int minor) +#else +XkbSetRepeatRate(dev,timeout,interval,major,minor) + DeviceIntPtr dev; + int timeout; + int interval; + int major; + int minor; +#endif +{ +int changed= 0; +XkbControlsRec old,*xkb; + + if ((!dev)||(!dev->key)||(!dev->key->xkbInfo)) + return 0; + xkb= dev->key->xkbInfo->desc->ctrls; + old= *xkb; + if ((timeout!=0) && (xkb->repeat_delay!=timeout)) { + xkb->repeat_delay= timeout; + changed++; + } + if ((interval!=0) && (xkb->repeat_interval!=interval)) { + xkb->repeat_interval= interval; + changed++; + } + if (changed) { + xkbControlsNotify cn; + XkbDDXChangeControls(dev,&old,xkb); + if (XkbComputeControlsNotify(dev,&old,xkb,&cn,False)) { + cn.keycode= 0; + cn.eventType = 0; + cn.requestMajor = major; + cn.requestMinor = minor; + XkbSendControlsNotify(dev,&cn); + } + } + return 1; +} + +int +#if NeedFunctionPrototypes +XkbGetRepeatRate(DeviceIntPtr dev,int *timeout,int *interval) +#else +XkbGetRepeatRate(dev,timeout,interval) + DeviceIntPtr dev; + int * timeout; + int * interval; +#endif +{ +XkbControlsPtr xkb; + + if ((!dev)||(!dev->key)||(!dev->key->xkbInfo)) + return 0; + xkb= dev->key->xkbInfo->desc->ctrls; + if (timeout) *timeout= xkb->repeat_delay; + if (interval) *interval= xkb->repeat_interval; + return 1; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeyTypes(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + XkbKeyTypeRec *type; + unsigned i,len; + + len= 0; + if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->types)) { + rep->present&= ~XkbKeyTypesMask; + rep->firstType= rep->nTypes= 0; + return 0; + } + type= &xkb->map->types[rep->firstType]; + for (i=0;inTypes;i++,type++){ + len+= SIZEOF(xkbKeyTypeWireDesc); + if (type->map_count>0) { + len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc)); + if (type->preserve) + len+= (type->map_count*SIZEOF(xkbModsWireDesc)); + } + } + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeyTypes( XkbDescPtr xkb, + xkbGetMapReply * rep, + char * buf, + ClientPtr client) +#else +XkbWriteKeyTypes(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply * rep; + char * buf; + ClientPtr client; +#endif +{ + XkbKeyTypePtr type; + unsigned i; + xkbKeyTypeWireDesc *wire; + + type= &xkb->map->types[rep->firstType]; + for (i=0;inTypes;i++,type++) { + register unsigned n; + wire= (xkbKeyTypeWireDesc *)buf; + wire->mask = type->mods.mask; + wire->realMods = type->mods.real_mods; + wire->virtualMods = type->mods.vmods; + wire->numLevels = type->num_levels; + wire->nMapEntries = type->map_count; + wire->preserve = (type->preserve!=NULL); + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + + buf= (char *)&wire[1]; + if (wire->nMapEntries>0) { + xkbKTMapEntryWireDesc * wire; + XkbKTMapEntryPtr entry; + wire= (xkbKTMapEntryWireDesc *)buf; + entry= type->map; + for (n=0;nmap_count;n++,wire++,entry++) { + wire->active= entry->active; + wire->mask= entry->mods.mask; + wire->level= entry->level; + wire->realMods= entry->mods.real_mods; + wire->virtualMods= entry->mods.vmods; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + } + buf= (char *)wire; + if (type->preserve!=NULL) { + xkbModsWireDesc * pwire; + XkbModsPtr preserve; + pwire= (xkbModsWireDesc *)buf; + preserve= type->preserve; + for (n=0;nmap_count;n++,pwire++,preserve++) { + pwire->mask= preserve->mask; + pwire->realMods= preserve->real_mods; + pwire->virtualMods= preserve->vmods; + if (client->swapped) { + register int n; + swaps(&pwire->virtualMods,n); + } + } + buf= (char *)pwire; + } + } + } + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeySyms(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + XkbSymMapPtr symMap; + unsigned i,len; + unsigned nSyms,nSymsThisKey; + + if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) { + rep->present&= ~XkbKeySymsMask; + rep->firstKeySym= rep->nKeySyms= 0; + rep->totalSyms= 0; + return 0; + } + len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc); + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=nSyms=0;inKeySyms;i++,symMap++) { + if (symMap->offset!=0) { + nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width; + nSyms+= nSymsThisKey; + } + } + len+= nSyms*4; + rep->totalSyms= nSyms; + return len; +} + +static int +#if NeedFunctionPrototypes +XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeVirtualMods(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ +register unsigned i,nMods,bit; + + if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)|| + (!xkb)||(!xkb->server)) { + rep->present&= ~XkbVirtualModsMask; + rep->virtualMods= 0; + return 0; + } + for (i=nMods=0,bit=1;ivirtualMods&bit) + nMods++; + } + return XkbPaddedSize(nMods); +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +#else +XkbWriteKeySyms(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply * rep; + char * buf; + ClientPtr client; +#endif +{ +register KeySym * pSym; +XkbSymMapPtr symMap; +xkbSymMapWireDesc * outMap; +register unsigned i; + + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=0;inKeySyms;i++,symMap++) { + outMap = (xkbSymMapWireDesc *)buf; + outMap->ktIndex[0] = symMap->kt_index[0]; + outMap->ktIndex[1] = symMap->kt_index[1]; + outMap->ktIndex[2] = symMap->kt_index[2]; + outMap->ktIndex[3] = symMap->kt_index[3]; + outMap->groupInfo = symMap->group_info; + outMap->width= symMap->width; + outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info); + buf= (char *)&outMap[1]; + if (outMap->nSyms==0) + continue; + + pSym = &xkb->map->syms[symMap->offset]; + memcpy((char *)buf,(char *)pSym,outMap->nSyms*4); + if (client->swapped) { + register int n,nSyms= outMap->nSyms; + swaps(&outMap->nSyms,n); + while (nSyms-->0) { + swapl(buf,n); + buf+= 4; + } + } + else buf+= outMap->nSyms*4; + } + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeyActions(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nActs; + register KeyCode firstKey; + + if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->key_acts)) { + rep->present&= ~XkbKeyActionsMask; + rep->firstKeyAct= rep->nKeyActs= 0; + rep->totalActs= 0; + return 0; + } + firstKey= rep->firstKeyAct; + for (nActs=i=0;inKeyActs;i++) { + if (xkb->server->key_acts[i+firstKey]!=0) + nActs+= XkbKeyNumActions(xkb,i+firstKey); + } + len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc)); + rep->totalActs= nActs; + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteKeyActions(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply * rep; + char * buf; + ClientPtr client; +#endif +{ + unsigned i; + CARD8 * numDesc; + XkbAnyAction * actDesc; + + numDesc = (CARD8 *)buf; + for (i=0;inKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]==0) + numDesc[i] = 0; + else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + } + buf+= XkbPaddedSize(rep->nKeyActs); + + actDesc = (XkbAnyAction *)buf; + for (i=0;inKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) { + unsigned int num; + num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + memcpy((char *)actDesc, + (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)), + num*SIZEOF(xkbActionWireDesc)); + actDesc+= num; + } + } + buf = (char *)actDesc; + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeyBehaviors(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nBhvr; + XkbBehavior * bhv; + + if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->behaviors)) { + rep->present&= ~XkbKeyBehaviorsMask; + rep->firstKeyBehavior= rep->nKeyBehaviors= 0; + rep->totalKeyBehaviors= 0; + return 0; + } + bhv= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (nBhvr=i=0;inKeyBehaviors;i++,bhv++) { + if (bhv->type!=XkbKB_Default) + nBhvr++; + } + len= nBhvr*SIZEOF(xkbBehaviorWireDesc); + rep->totalKeyBehaviors= nBhvr; + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteKeyBehaviors(xkb,rep,buf,client) + XkbDescRec *xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ + unsigned i; + xkbBehaviorWireDesc *wire; + XkbBehavior *pBhvr; + + wire = (xkbBehaviorWireDesc *)buf; + pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (i=0;inKeyBehaviors;i++,pBhvr++) { + if (pBhvr->type!=XkbKB_Default) { + wire->key= i+rep->firstKeyBehavior; + wire->type= pBhvr->type; + wire->data= pBhvr->data; + wire++; + } + } + buf = (char *)wire; + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeExplicit(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->explicit)) { + rep->present&= ~XkbExplicitComponentsMask; + rep->firstKeyExplicit= rep->nKeyExplicit= 0; + rep->totalKeyExplicit= 0; + return 0; + } + for (nRtrn=i=0;inKeyExplicit;i++) { + if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0) + nRtrn++; + } + rep->totalKeyExplicit= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */ + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +#else +XkbWriteExplicit(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ +unsigned i; +char * start; +unsigned char * pExp; + + start= buf; + pExp= &xkb->server->explicit[rep->firstKeyExplicit]; + for (i=0;inKeyExplicit;i++,pExp++) { + if (*pExp!=0) { + *buf++= i+rep->firstKeyExplicit; + *buf++= *pExp; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +#if NeedFunctionPrototypes +XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeModifierMap(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->modmap)) { + rep->present&= ~XkbModifierMapMask; + rep->firstModMapKey= rep->nModMapKeys= 0; + rep->totalModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;inModMapKeys;i++) { + if (xkb->map->modmap[i+rep->firstModMapKey]!=0) + nRtrn++; + } + rep->totalModMapKeys= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */ + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteModifierMap(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ +unsigned i; +char * start; +unsigned char * pMap; + + start= buf; + pMap= &xkb->map->modmap[rep->firstModMapKey]; + for (i=0;inModMapKeys;i++,pMap++) { + if (*pMap!=0) { + *buf++= i+rep->firstModMapKey; + *buf++= *pMap; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +#if NeedFunctionPrototypes +XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeVirtualModMap(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) { + rep->present&= ~XkbVirtualModMapMask; + rep->firstVModMapKey= rep->nVModMapKeys= 0; + rep->totalVModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;inVModMapKeys;i++) { + if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0) + nRtrn++; + } + rep->totalVModMapKeys= nRtrn; + len= nRtrn*SIZEOF(xkbVModMapWireDesc); + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteVirtualModMap(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ +unsigned i; +xkbVModMapWireDesc * wire; +unsigned short * pMap; + + wire= (xkbVModMapWireDesc *)buf; + pMap= &xkb->server->vmodmap[rep->firstVModMapKey]; + for (i=0;inVModMapKeys;i++,pMap++) { + if (*pMap!=0) { + wire->key= i+rep->firstVModMapKey; + wire->vmods= *pMap; + wire++; + } + } + return (char *)wire; +} + +static Status +#if NeedFunctionPrototypes +XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbComputeGetMapReplySize(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ +int len; + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + len= XkbSizeKeyTypes(xkb,rep); + len+= XkbSizeKeySyms(xkb,rep); + len+= XkbSizeKeyActions(xkb,rep); + len+= XkbSizeKeyBehaviors(xkb,rep); + len+= XkbSizeVirtualMods(xkb,rep); + len+= XkbSizeExplicit(xkb,rep); + len+= XkbSizeModifierMap(xkb,rep); + len+= XkbSizeVirtualModMap(xkb,rep); + rep->length+= (len/4); + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSendMap(client,xkb,rep) + ClientPtr client; + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ +unsigned i,len; +char *desc,*start; + + len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply)); + start= desc= (char *)ALLOCATE_LOCAL(len); + if (!start) + return BadAlloc; + if ( rep->nTypes>0 ) + desc = XkbWriteKeyTypes(xkb,rep,desc,client); + if ( rep->nKeySyms>0 ) + desc = XkbWriteKeySyms(xkb,rep,desc,client); + if ( rep->nKeyActs>0 ) + desc = XkbWriteKeyActions(xkb,rep,desc,client); + if ( rep->totalKeyBehaviors>0 ) + desc = XkbWriteKeyBehaviors(xkb,rep,desc,client); + if ( rep->virtualMods ) { + register int sz,bit; + for (i=sz=0,bit=1;ivirtualMods&bit) { + desc[sz++]= xkb->server->vmods[i]; + } + } + desc+= XkbPaddedSize(sz); + } + if ( rep->totalKeyExplicit>0 ) + desc= XkbWriteExplicit(xkb,rep,desc,client); + if ( rep->totalModMapKeys>0 ) + desc= XkbWriteModifierMap(xkb,rep,desc,client); + if ( rep->totalVModMapKeys>0 ) + desc= XkbWriteVirtualModMap(xkb,rep,desc,client); + if ((desc-start)!=(len)) { + ErrorF("BOGUS LENGTH in write keyboard desc, expected %d, got %d\n", + len, desc-start); + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->present,n); + swaps(&rep->totalSyms,n); + swaps(&rep->totalActs,n); + } + WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep); + WriteToClient(client, len, start); + DEALLOCATE_LOCAL((char *)start); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetMap(ClientPtr client) +#else +ProcXkbGetMap(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbGetMapReply rep; + XkbDescRec *xkb; + int n,status; + + REQUEST(xkbGetMapReq); + REQUEST_SIZE_MATCH(xkbGetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial); + CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask); + CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask); + + xkb= dev->key->xkbInfo->desc; + bzero(&rep,sizeof(xkbGetMapReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2; + rep.deviceID = dev->id; + rep.present = stuff->partial|stuff->full; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + if ( stuff->full&XkbKeyTypesMask ) { + rep.firstType = 0; + rep.nTypes = xkb->map->num_types; + } + else if (stuff->partial&XkbKeyTypesMask) { + if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types, + stuff->firstType,stuff->nTypes); + return BadValue; + } + rep.firstType = stuff->firstType; + rep.nTypes = stuff->nTypes; + } + else rep.nTypes = 0; + rep.totalTypes = xkb->map->num_types; + + n= XkbNumKeys(xkb); + if ( stuff->full&XkbKeySymsMask ) { + rep.firstKeySym = xkb->min_key_code; + rep.nKeySyms = n; + } + else if (stuff->partial&XkbKeySymsMask) { + CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb); + rep.firstKeySym = stuff->firstKeySym; + rep.nKeySyms = stuff->nKeySyms; + } + else rep.nKeySyms = 0; + rep.totalSyms= 0; + + if ( stuff->full&XkbKeyActionsMask ) { + rep.firstKeyAct= xkb->min_key_code; + rep.nKeyActs= n; + } + else if (stuff->partial&XkbKeyActionsMask) { + CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb); + rep.firstKeyAct= stuff->firstKeyAct; + rep.nKeyActs= stuff->nKeyActs; + } + else rep.nKeyActs= 0; + rep.totalActs= 0; + + if ( stuff->full&XkbKeyBehaviorsMask ) { + rep.firstKeyBehavior = xkb->min_key_code; + rep.nKeyBehaviors = n; + } + else if (stuff->partial&XkbKeyBehaviorsMask) { + CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb); + rep.firstKeyBehavior= stuff->firstKeyBehavior; + rep.nKeyBehaviors= stuff->nKeyBehaviors; + } + else rep.nKeyBehaviors = 0; + rep.totalKeyBehaviors= 0; + + if (stuff->full&XkbVirtualModsMask) + rep.virtualMods= ~0; + else if (stuff->partial&XkbVirtualModsMask) + rep.virtualMods= stuff->virtualMods; + + if (stuff->full&XkbExplicitComponentsMask) { + rep.firstKeyExplicit= xkb->min_key_code; + rep.nKeyExplicit= n; + } + else if (stuff->partial&XkbExplicitComponentsMask) { + CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb); + rep.firstKeyExplicit= stuff->firstKeyExplicit; + rep.nKeyExplicit= stuff->nKeyExplicit; + } + else rep.nKeyExplicit = 0; + rep.totalKeyExplicit= 0; + + if (stuff->full&XkbModifierMapMask) { + rep.firstModMapKey= xkb->min_key_code; + rep.nModMapKeys= n; + } + else if (stuff->partial&XkbModifierMapMask) { + CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb); + rep.firstModMapKey= stuff->firstModMapKey; + rep.nModMapKeys= stuff->nModMapKeys; + } + else rep.nModMapKeys = 0; + rep.totalModMapKeys= 0; + + if (stuff->full&XkbVirtualModMapMask) { + rep.firstVModMapKey= xkb->min_key_code; + rep.nVModMapKeys= n; + } + else if (stuff->partial&XkbVirtualModMapMask) { + CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb); + rep.firstVModMapKey= stuff->firstVModMapKey; + rep.nVModMapKeys= stuff->nVModMapKeys; + } + else rep.nVModMapKeys = 0; + rep.totalVModMapKeys= 0; + + if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success) + return status; + return XkbSendMap(client,xkb,&rep); +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +CheckKeyTypes( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc **wireRtrn, + int * nMapsRtrn, + CARD8 * mapWidthRtrn) +#else +CheckKeyTypes(client,xkb,req,wireRtrn,nMapsRtrn,mapWidthRtrn) + ClientPtr client; + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbKeyTypeWireDesc **wireRtrn; + int * nMapsRtrn; + CARD8 * mapWidthRtrn; +#endif +{ +unsigned nMaps; +register unsigned i,n; +register CARD8 * map; +register xkbKeyTypeWireDesc *wire = *wireRtrn; + + if (req->firstType>((unsigned)xkb->map->num_types)) { + *nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types); + return 0; + } + if (req->flags&XkbSetMapResizeTypes) { + nMaps = req->firstType+req->nTypes; + if (nMapsfirstType,req->nTypes,4); + return 0; + } + } + else if (req->present&XkbKeyTypesMask) { + nMaps = xkb->map->num_types; + if ((req->firstType+req->nTypes)>nMaps) { + *nMapsRtrn = req->firstType+req->nTypes; + return 0; + } + } + else { + *nMapsRtrn = xkb->map->num_types; + for (i=0;imap->num_types;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + return 1; + } + + for (i=0;ifirstType;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + for (i=0;inTypes;i++) { + unsigned width; + if (client->swapped) { + register int s; + swaps(&wire->virtualMods,s); + } + n= i+req->firstType; + width= wire->numLevels; + if (width<1) { + *nMapsRtrn= _XkbErrCode3(0x04,n,width); + return 0; + } + else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + else if ((width!=2)&& + ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)|| + (n==XkbAlphabeticIndex))) { + /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + if (wire->nMapEntries>0) { + xkbKTSetMapEntryWireDesc * mapWire; + xkbModsWireDesc * preWire; + mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1]; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;nnMapEntries;n++) { + if (client->swapped) { + register int s; + swaps(&mapWire[n].virtualMods,s); + } + if (mapWire[n].realMods&(~wire->realMods)) { + *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods, + wire->realMods); + return 0; + } + if (mapWire[n].virtualMods&(~wire->virtualMods)) { + *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods); + return 0; + } + if (mapWire[n].level>=wire->numLevels) { + *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels, + mapWire[n].level); + return 0; + } + if (wire->preserve) { + if (client->swapped) { + register int s; + swaps(&preWire[n].virtualMods,s); + } + if (preWire[n].realMods&(~mapWire[n].realMods)) { + *nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods, + mapWire[n].realMods); + return 0; + } + if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) { + *nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods); + return 0; + } + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + mapWidthRtrn[i+req->firstType] = wire->numLevels; + wire= (xkbKeyTypeWireDesc *)map; + } + for (i=req->firstType+req->nTypes;imap->types[i].num_levels; + } + *nMapsRtrn = nMaps; + *wireRtrn = wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + xkbSymMapWireDesc ** wireRtrn, + int * errorRtrn) +#else +CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,wireRtrn,errorRtrn) + ClientPtr client; + XkbDescPtr xkb; + xkbSetMapReq * req; + int nTypes; + CARD8 * mapWidths; + CARD16 * symsPerKey; + xkbSymMapWireDesc **wireRtrn; + int * errorRtrn; +#endif +{ +register unsigned i; +XkbSymMapPtr map; +xkbSymMapWireDesc* wire = *wireRtrn; + + if (!(XkbKeySymsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0); + map = &xkb->map->key_sym_map[xkb->min_key_code]; + for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) { + register int g,ng,w; + ng= XkbNumGroups(map->group_info); + for (w=g=0;gkt_index[g]>=(unsigned)nTypes) { + *errorRtrn = _XkbErrCode4(0x13,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*ng; + } + for (i=0;inKeySyms;i++) { + KeySym *pSyms; + register unsigned nG; + if (client->swapped) { + swaps(&wire->nSyms,nG); + } + nG = XkbNumGroups(wire->groupInfo); + if (nG>XkbNumKbdGroups) { + *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG); + return 0; + } + if (nG>0) { + register int g,w; + for (g=w=0;gktIndex[g]>=(unsigned)nTypes) { + *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g, + wire->ktIndex[g]); + return 0; + } + if (mapWidths[wire->ktIndex[g]]>w) + w= mapWidths[wire->ktIndex[g]]; + } + if (wire->width!=w) { + *errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width); + return 0; + } + w*= nG; + symsPerKey[i+req->firstKeySym] = w; + if (w!=wire->nSyms) { + *errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w); + return 0; + } + } + else if (wire->nSyms!=0) { + *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms); + return 0; + } + pSyms = (KeySym *)&wire[1]; + wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + + map = &xkb->map->key_sym_map[i]; + for (;i<=(unsigned)xkb->max_key_code;i++,map++) { + register int g,nG,w; + nG= XkbKeyNumGroups(xkb,i); + for (w=g=0;gkt_index[g]>=(unsigned)nTypes) { + *errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*nG; + } + *wireRtrn = wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + CARD8 ** wireRtrn, + int * nActsRtrn) +#else +CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,wireRtrn,nActsRtrn) + XkbDescRec *xkb; + xkbSetMapReq *req; + int nTypes; + CARD8 *mapWidths; + CARD16 *symsPerKey; + CARD8 **wireRtrn; + int *nActsRtrn; +#endif +{ +int nActs; +CARD8 * wire = *wireRtrn; +register unsigned i; + + if (!(XkbKeyActionsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0); + for (nActs=i=0;inKeyActs;i++) { + if (wire[0]!=0) { + if (wire[0]==symsPerKey[i+req->firstKeyAct]) + nActs+= wire[0]; + else { + *nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]); + return 0; + } + } + wire++; + } + if (req->nKeyActs%4) + wire+= 4-(req->nKeyActs%4); + *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs); + *nActsRtrn = nActs; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeyBehaviors( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbBehaviorWireDesc ** wireRtrn, + int * errorRtrn) +#else +CheckKeyBehaviors(xkb,req,wireRtrn,errorRtrn) + XkbDescRec *xkb; + xkbSetMapReq *req; + xkbBehaviorWireDesc **wireRtrn; + int *errorRtrn; +#endif +{ +register xkbBehaviorWireDesc * wire = *wireRtrn; +register XkbServerMapPtr server = xkb->server; +register unsigned i; +unsigned first,last; + + if ((req->present&XkbKeyBehaviorsMask==0)||(req->nKeyBehaviors<1)) { + req->present&= ~XkbKeyBehaviorsMask; + req->nKeyBehaviors= 0; + return 1; + } + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + if (firstminKeyCode) { + *errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode); + return 0; + } + + for (i=0;itotalKeyBehaviors;i++,wire++) { + if ((wire->keykey>last)) { + *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key); + return 0; + } + if ((wire->type&XkbKB_Permanent)&& + ((server->behaviors[wire->key].type!=wire->type)|| + (server->behaviors[wire->key].data!=wire->data))) { + *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type); + return 0; + } + if ((wire->type==XkbKB_RadioGroup)&& + ((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) { + *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data, + XkbMaxRadioGroups); + return 0; + } + if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) { + CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0); + } + } + *wireRtrn = wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckVirtualMods( XkbDescRec * xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +#else +CheckVirtualMods(xkb,req,wireRtrn,errorRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 ** wireRtrn; + int * errorRtrn; +#endif +{ +register CARD8 *wire = *wireRtrn; +register unsigned i,nMods,bit; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return 1; + for (i=nMods=0,bit=1;ivirtualMods&bit) + nMods++; + } + *wireRtrn= (wire+XkbPaddedSize(nMods)); + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeyExplicit( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +#else +CheckKeyExplicit(xkb,req,wireRtrn,errorRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 ** wireRtrn; + int * errorRtrn; +#endif +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) { + req->present&= ~XkbExplicitComponentsMask; + req->nKeyExplicit= 0; + return 1; + } + first= req->firstKeyExplicit; + last= first+req->nKeyExplicit-1; + if (firstminKeyCode) { + *errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;itotalKeyExplicit;i++,wire+=2) { + if ((wire[0]last)) { + *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]); + return 0; + } + if (wire[1]&(~XkbAllExplicitMask)) { + *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn) +#else +CheckModifierMap(xkb,req,wireRtrn,errRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 ** wireRtrn; + int * errRtrn; +#endif +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) { + req->present&= ~XkbModifierMapMask; + req->nModMapKeys= 0; + return 1; + } + first= req->firstModMapKey; + last= first+req->nModMapKeys-1; + if (firstminKeyCode) { + *errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;itotalModMapKeys;i++,wire+=2) { + if ((wire[0]last)) { + *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckVirtualModMap( XkbDescPtr xkb, + xkbSetMapReq *req, + xkbVModMapWireDesc **wireRtrn, + int *errRtrn) +#else +CheckVirtualModMap(xkb,req,wireRtrn,errRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbVModMapWireDesc ** wireRtrn; + int * errRtrn; +#endif +{ +register xkbVModMapWireDesc * wire = *wireRtrn; +register unsigned i; +int first,last; + + if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) { + req->present&= ~XkbVirtualModMapMask; + req->nVModMapKeys= 0; + return 1; + } + first= req->firstVModMapKey; + last= first+req->nVModMapKeys-1; + if (firstminKeyCode) { + *errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode); + return 0; + } + for (i=0;itotalVModMapKeys;i++,wire++) { + if ((wire->keykey>last)) { + *errRtrn = _XkbErrCode4(0x73,first,last,wire->key); + return 0; + } + } + *wireRtrn= wire; + return 1; +} + +static char * +#if NeedFunctionPrototypes +SetKeyTypes( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc * wire, + XkbChangesPtr changes) +#else +SetKeyTypes(xkb,req,wire,changes) + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbKeyTypeWireDesc *wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i; +unsigned first,last; +CARD8 *map; + + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) { + i= req->firstType+req->nTypes; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) { + return NULL; + } + } + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types) + xkb->map->num_types= req->firstType+req->nTypes; + + for (i=0;inTypes;i++) { + XkbKeyTypePtr pOld; + register unsigned n; + + if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries, + wire->preserve,wire->numLevels)!=Success) { + return NULL; + } + pOld = &xkb->map->types[i+req->firstType]; + map = (CARD8 *)&wire[1]; + + pOld->mods.real_mods = wire->realMods; + pOld->mods.vmods= wire->virtualMods; + pOld->num_levels = wire->numLevels; + pOld->map_count= wire->nMapEntries; + + pOld->mods.mask= pOld->mods.real_mods| + XkbMaskForVMask(xkb,pOld->mods.vmods); + + if (wire->nMapEntries) { + xkbKTSetMapEntryWireDesc *mapWire; + xkbModsWireDesc *preWire; + unsigned tmp; + mapWire= (xkbKTSetMapEntryWireDesc *)map; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;nnMapEntries;n++) { + pOld->map[n].active= 1; + pOld->map[n].mods.mask= mapWire[n].realMods; + pOld->map[n].mods.real_mods= mapWire[n].realMods; + pOld->map[n].mods.vmods= mapWire[n].virtualMods; + pOld->map[n].level= mapWire[n].level; + if (mapWire[n].virtualMods!=0) { + tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods); + pOld->map[n].active= (tmp!=0); + pOld->map[n].mods.mask|= tmp; + } + if (wire->preserve) { + pOld->preserve[n].real_mods= preWire[n].realMods; + pOld->preserve[n].vmods= preWire[n].virtualMods; + tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods); + pOld->preserve[n].mask= preWire[n].realMods|tmp; + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + wire = (xkbKeyTypeWireDesc *)map; + } + first= req->firstType; + last= first+req->nTypes-1; /* last changed type */ + if (changes->map.changed&XkbKeyTypesMask) { + int oldLast; + oldLast= changes->map.first_type+changes->map.num_types-1; + if (changes->map.first_typemap.first_type; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type = first; + changes->map.num_types = (last-first)+1; + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbSymMapWireDesc * wire, + XkbChangesPtr changes, + DeviceIntPtr dev) +#else +SetKeySyms(client,xkb,req,wire,changes,dev) + ClientPtr client; + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbSymMapWireDesc * wire; + XkbChangesPtr changes; + DeviceIntPtr dev; +#endif +{ +register unsigned i,s; +XkbSymMapPtr oldMap; +KeySym * newSyms; +KeySym * pSyms; +unsigned first,last; + + oldMap = &xkb->map->key_sym_map[req->firstKeySym]; + for (i=0;inKeySyms;i++,oldMap++) { + pSyms = (KeySym *)&wire[1]; + if (wire->nSyms>0) { + newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms); + for (s=0;snSyms;s++) { + newSyms[s]= pSyms[s]; + } + if (client->swapped) { + int n; + for (s=0;snSyms;s++) { + swapl(&newSyms[s],n); + } + } + } + oldMap->kt_index[0] = wire->ktIndex[0]; + oldMap->kt_index[1] = wire->ktIndex[1]; + oldMap->kt_index[2] = wire->ktIndex[2]; + oldMap->kt_index[3] = wire->ktIndex[3]; + oldMap->group_info = wire->groupInfo; + oldMap->width = wire->width; + wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + first= req->firstKeySym; + last= first+req->nKeySyms-1; + if (changes->map.changed&XkbKeySymsMask) { + int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1); + if (changes->map.first_key_symmap.first_key_sym; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym = first; + changes->map.num_key_syms = (last-first+1); + + s= 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyNumGroups(xkb,i)>s) + s= XkbKeyNumGroups(xkb,i); + } + if (s!=xkb->ctrls->num_groups) { + xkbControlsNotify cn; + XkbControlsRec old; + cn.keycode= 0; + cn.eventType= 0; + cn.requestMajor= XkbReqCode; + cn.requestMinor= X_kbSetMap; + old= *xkb->ctrls; + xkb->ctrls->num_groups= s; + if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,False)) + XkbSendControlsNotify(dev,&cn); + } + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +#else +SetKeyActions(xkb,req,wire,changes) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +CARD8 * nActs = wire; +XkbAction * newActs; + + wire+= XkbPaddedSize(req->nKeyActs); + for (i=0;inKeyActs;i++) { + if (nActs[i]==0) + xkb->server->key_acts[i+req->firstKeyAct]= 0; + else { + newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]); + memcpy((char *)newActs,(char *)wire, + nActs[i]*SIZEOF(xkbActionWireDesc)); + wire+= nActs[i]*SIZEOF(xkbActionWireDesc); + } + } + first= req->firstKeyAct; + last= (first+req->nKeyActs-1); + if (changes->map.changed&XkbKeyActionsMask) { + int oldLast; + oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; + if (changes->map.first_key_actmap.first_key_act; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= first; + changes->map.num_key_acts= (last-first+1); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetKeyBehaviors( XkbSrvInfoPtr xkbi, + xkbSetMapReq *req, + xkbBehaviorWireDesc *wire, + XkbChangesPtr changes) +#else +SetKeyBehaviors(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + xkbBehaviorWireDesc*wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i; +int maxRG = -1; +XkbDescPtr xkb = xkbi->desc; +XkbServerMapPtr server = xkb->server; +unsigned first,last; + + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior)); + for (i=0;itotalKeyBehaviors;i++) { + if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) { + server->behaviors[wire->key].type= wire->type; + server->behaviors[wire->key].data= wire->data; + if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG)) + maxRG= wire->data; + } + wire++; + } + + if (maxRG>(int)xkbi->nRadioGroups) { + int sz = (maxRG+1)*sizeof(XkbRadioGroupRec); + if (xkbi->radioGroups) + xkbi->radioGroups=(XkbRadioGroupPtr)Xrealloc(xkbi->radioGroups,sz); + else xkbi->radioGroups= (XkbRadioGroupPtr)Xcalloc(sz); + if (xkbi->radioGroups) { + if (xkbi->nRadioGroups) + bzero(&xkbi->radioGroups[xkbi->nRadioGroups], + (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec)); + xkbi->nRadioGroups= maxRG+1; + } + else xkbi->nRadioGroups= 0; + /* should compute members here */ + } + if (changes->map.changed&XkbKeyBehaviorsMask) { + unsigned oldLast; + oldLast= changes->map.first_key_behavior+ + changes->map.num_key_behaviors-1; + if (changes->map.first_key_behaviorfirstKeyBehavior) + first= changes->map.first_key_behavior; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyBehaviorsMask; + changes->map.first_key_behavior = first; + changes->map.num_key_behaviors = (last-first+1); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +#else +SetVirtualMods(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register int i,bit,nMods; +XkbServerMapPtr srv = xkbi->desc->server; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return (char *)wire; + for (i=nMods=0,bit=1;ivirtualMods&bit) { + if (srv->vmods[i]!=wire[nMods]) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + srv->vmods[i]= wire[nMods]; + } + nMods++; + } + } + return (char *)(wire+XkbPaddedSize(nMods)); +} + +static char * +#if NeedFunctionPrototypes +SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +#else +SetKeyExplicit(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +XkbServerMapPtr xkb = xkbi->desc->server; +CARD8 * start; + + start= wire; + first= req->firstKeyExplicit; + last= req->firstKeyExplicit+req->nKeyExplicit-1; + bzero(&xkb->explicit[first],req->nKeyExplicit); + for (i=0;itotalKeyExplicit;i++,wire+= 2) { + xkb->explicit[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbExplicitComponentsMask) { + int oldLast; + oldLast= changes->map.first_key_explicit+ + changes->map.num_key_explicit-1; + if (changes->map.first_key_explicitmap.first_key_explicit; + if (oldLast>last) + last= oldLast; + } + changes->map.first_key_explicit= first; + changes->map.num_key_explicit= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetModifierMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +#else +SetModifierMap(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +XkbClientMapPtr xkb = xkbi->desc->map; +CARD8 * start; + + start= wire; + first= req->firstModMapKey; + last= req->firstModMapKey+req->nModMapKeys-1; + bzero(&xkb->modmap[first],req->nModMapKeys); + for (i=0;itotalModMapKeys;i++,wire+= 2) { + xkb->modmap[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbModifierMapMask) { + int oldLast; + oldLast= changes->map.first_modmap_key+ + changes->map.num_modmap_keys-1; + if (changes->map.first_modmap_keymap.first_modmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_modmap_key= first; + changes->map.num_modmap_keys= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetVirtualModMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + xkbVModMapWireDesc * wire, + XkbChangesPtr changes) +#else +SetVirtualModMap(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + xkbVModMapWireDesc *wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +XkbServerMapPtr srv = xkbi->desc->server; + + first= req->firstVModMapKey; + last= req->firstVModMapKey+req->nVModMapKeys-1; + bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short)); + for (i=0;itotalVModMapKeys;i++,wire++) { + srv->vmodmap[wire->key]= wire->vmods; + } + if (first>0) { + if (changes->map.changed&XkbVirtualModMapMask) { + int oldLast; + oldLast= changes->map.first_vmodmap_key+ + changes->map.num_vmodmap_keys-1; + if (changes->map.first_vmodmap_keymap.first_vmodmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_vmodmap_key= first; + changes->map.num_vmodmap_keys= (last-first)+1; + } + return (char *)wire; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetMap(ClientPtr client) +#else +ProcXkbSetMap(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbChangesRec change; + XkbEventCauseRec cause; + int nTypes,nActions,error; + char * tmp; + CARD8 mapWidths[XkbMaxLegalKeyCode+1]; + CARD16 symsPerKey[XkbMaxLegalKeyCode+1]; + Bool sentNKN; + + REQUEST(xkbSetMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask); + + XkbSetCauseXkbReq(&cause,X_kbSetMap,client); + xkbi= dev->key->xkbInfo; + xkb = xkbi->desc; + + if ((xkb->min_key_code!=stuff->minKeyCode)|| + (xkb->max_key_code!=stuff->maxKeyCode)) { + if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */ + stuff->minKeyCode= xkb->min_key_code; + stuff->maxKeyCode= xkb->max_key_code; + } + else { + if ((stuff->minKeyCodemaxKeyCode>XkbMaxLegalKeyCode)) { + client->errorValue= _XkbErrCode3(2,stuff->minKeyCode, + stuff->maxKeyCode); + return BadValue; + } + if (stuff->minKeyCode>stuff->maxKeyCode) { + client->errorValue= _XkbErrCode3(3,stuff->minKeyCode, + stuff->maxKeyCode); + return BadMatch; + } + } + } + + tmp = (char *)&stuff[1]; + if ((stuff->present&XkbKeyTypesMask)&& + (!CheckKeyTypes(client,xkb,stuff,(xkbKeyTypeWireDesc **)&tmp, + &nTypes,mapWidths))) { + client->errorValue = nTypes; + return BadValue; + } + if ((stuff->present&XkbKeySymsMask)&& + (!CheckKeySyms(client,xkb,stuff,nTypes,mapWidths,symsPerKey, + (xkbSymMapWireDesc **)&tmp,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((stuff->present&XkbKeyActionsMask)&& + (!CheckKeyActions(xkb,stuff,nTypes,mapWidths,symsPerKey, + (CARD8 **)&tmp,&nActions))) { + client->errorValue = nActions; + return BadValue; + } + + if ((stuff->present&XkbKeyBehaviorsMask)&& + (!CheckKeyBehaviors(xkb,stuff,(xkbBehaviorWireDesc**)&tmp,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((stuff->present&XkbVirtualModsMask)&& + (!CheckVirtualMods(xkb,stuff,(CARD8 **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if ((stuff->present&XkbExplicitComponentsMask)&& + (!CheckKeyExplicit(xkb,stuff,(CARD8 **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if ((stuff->present&XkbModifierMapMask)&& + (!CheckModifierMap(xkb,stuff,(CARD8 **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if ((stuff->present&XkbVirtualModMapMask)&& + (!CheckVirtualModMap(xkb,stuff,(xkbVModMapWireDesc **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if (((tmp-((char *)stuff))/4)!=stuff->length) { + ErrorF("Internal error! Bad length in XkbSetMap (after check)\n"); + client->errorValue = tmp-((char *)&stuff[1]); + return BadLength; + } + bzero(&change,sizeof(change)); + sentNKN= False; + if ((xkb->min_key_code!=stuff->minKeyCode)|| + (xkb->max_key_code!=stuff->maxKeyCode)) { + Status status; + xkbNewKeyboardNotify nkn; + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.oldMinKeyCode= xkb->min_key_code; + nkn.oldMaxKeyCode= xkb->max_key_code; + status= XkbChangeKeycodeRange(xkb,stuff->minKeyCode,stuff->maxKeyCode, + &change); + if (status!=Success) + return status; + nkn.minKeyCode= xkb->min_key_code; + nkn.maxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbSetMap; + nkn.changed= XkbNKN_KeycodesMask; + XkbSendNewKeyboardNotify(dev,&nkn); + sentNKN= True; + } + tmp = (char *)&stuff[1]; + if (stuff->present&XkbKeyTypesMask) { + tmp = SetKeyTypes(xkb,stuff,(xkbKeyTypeWireDesc *)tmp,&change); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbKeySymsMask) { + tmp = SetKeySyms(client,xkb,stuff,(xkbSymMapWireDesc *)tmp,&change,dev); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbKeyActionsMask) { + tmp = SetKeyActions(xkb,stuff,(CARD8 *)tmp,&change); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbKeyBehaviorsMask) { + tmp= SetKeyBehaviors(xkbi,stuff,(xkbBehaviorWireDesc *)tmp,&change); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbVirtualModsMask) + tmp= SetVirtualMods(xkbi,stuff,(CARD8 *)tmp,&change); + if (stuff->present&XkbExplicitComponentsMask) + tmp= SetKeyExplicit(xkbi,stuff,(CARD8 *)tmp,&change); + if (stuff->present&XkbModifierMapMask) + tmp= SetModifierMap(xkbi,stuff,(CARD8 *)tmp,&change); + if (stuff->present&XkbVirtualModMapMask) + tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change); + if (((tmp-((char *)stuff))/4)!=stuff->length) { + ErrorF("Internal error! Bad length in XkbSetMap (after set)\n"); + client->errorValue = tmp-((char *)&stuff[1]); + return BadLength; + } + if (stuff->flags&XkbSetMapRecomputeActions) { + KeyCode first,last,firstMM,lastMM; + if (change.map.num_key_syms>0) { + first= change.map.first_key_sym; + last= first+change.map.num_key_syms-1; + } + else first= last= 0; + if (change.map.num_modmap_keys>0) { + firstMM= change.map.first_modmap_key; + lastMM= first+change.map.num_modmap_keys-1; + } + else firstMM= lastMM= 0; + if ((last>0) && (lastMM>0)) { + if (firstMMlast) + last= lastMM; + } + else if (lastMM>0) { + first= firstMM; + last= lastMM; + } + if (last>0) { + unsigned check= 0; + XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + } + } + if (!sentNKN) + XkbSendNotification(dev,&change,&cause); + + XkbUpdateCoreDescription(dev,False); + return client->noClientException; +allocFailure: + return BadAlloc; +} + +/***====================================================================***/ + +static Status +#if NeedFunctionPrototypes +XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +#else +XkbComputeGetCompatMapReplySize(compat,rep) + XkbCompatMapPtr compat; + xkbGetCompatMapReply * rep; +#endif +{ +unsigned size,nGroups; + + nGroups= 0; + if (rep->groups!=0) { + register int i,bit; + for (i=0,bit=1;igroups&bit) + nGroups++; + } + } + size= nGroups*SIZEOF(xkbModsWireDesc); + size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc)); + rep->length= size/4; + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendCompatMap( ClientPtr client, + XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +#else +XkbSendCompatMap(client,compat,rep) + ClientPtr client; + XkbCompatMapPtr compat; + xkbGetCompatMapReply * rep; +#endif +{ +char * data; +int size; + + size= rep->length*4; + if (size>0) { + data = (char *)ALLOCATE_LOCAL(size); + if (data) { + register unsigned i,bit; + xkbModsWireDesc * grp; + XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI]; + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + for (i=0;inSI;i++,sym++,wire++) { + wire->sym= sym->sym; + wire->mods= sym->mods; + wire->match= sym->match; + wire->virtualMod= sym->virtual_mod; + wire->flags= sym->flags; + memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc); + if (client->swapped) { + register int n; + swapl(&wire->sym,n); + } + } + if (rep->groups) { + grp = (xkbModsWireDesc *)wire; + for (i=0,bit=1;igroups&bit) { + grp->mask= compat->groups[i].mask; + grp->realMods= compat->groups[i].real_mods; + grp->virtualMods= compat->groups[i].vmods; + if (client->swapped) { + register int n; + swaps(&grp->virtualMods,n); + } + grp++; + } + } + wire= (xkbSymInterpretWireDesc*)grp; + } + } + else return BadAlloc; + } + else data= NULL; + + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->firstSI,n); + swaps(&rep->nSI,n); + swaps(&rep->nTotalSI,n); + } + + WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep); + if (data) { + WriteToClient(client, size, data); + DEALLOCATE_LOCAL((char *)data); + } + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetCompatMap(ClientPtr client) +#else +ProcXkbGetCompatMap(client) + ClientPtr client; +#endif +{ + xkbGetCompatMapReply rep; + DeviceIntPtr dev; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + + REQUEST(xkbGetCompatMapReq); + REQUEST_SIZE_MATCH(xkbGetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb = dev->key->xkbInfo->desc; + compat= xkb->compat; + + rep.type = X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.firstSI = stuff->firstSI; + rep.nSI = stuff->nSI; + if (stuff->getAllSI) { + rep.firstSI = 0; + rep.nSI = compat->num_si; + } + else if ((((unsigned)stuff->nSI)>0)&& + ((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) { + client->errorValue = _XkbErrCode2(0x05,compat->num_si); + return BadValue; + } + rep.nTotalSI = compat->num_si; + rep.groups= stuff->groups; + XkbComputeGetCompatMapReplySize(compat,&rep); + return XkbSendCompatMap(client,compat,&rep); +} + +int +#if NeedFunctionPrototypes +ProcXkbSetCompatMap(ClientPtr client) +#else +ProcXkbSetCompatMap(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + char * data; + int nGroups; + register unsigned i,bit; + + REQUEST(xkbSetCompatMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + data = (char *)&stuff[1]; + xkbi = dev->key->xkbInfo; + xkb= xkbi->desc; + compat= xkb->compat; + if ((stuff->nSI>0)||(stuff->truncateSI)) { + xkbSymInterpretWireDesc *wire; + if (stuff->firstSI>compat->num_si) { + client->errorValue = _XkbErrCode2(0x02,compat->num_si); + return BadValue; + } + wire= (xkbSymInterpretWireDesc *)data; + wire+= stuff->nSI; + data = (char *)wire; + } + nGroups= 0; + if (stuff->groups!=0) { + for (i=0,bit=1;igroups&bit ) + nGroups++; + } + } + data+= nGroups*SIZEOF(xkbModsWireDesc); + if (((data-((char *)stuff))/4)!=stuff->length) { + return BadLength; + } + data = (char *)&stuff[1]; + if (stuff->nSI>0) { + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + XkbSymInterpretPtr sym; + if ((unsigned)(stuff->firstSI+stuff->nSI)>compat->num_si) { + compat->num_si= stuff->firstSI+stuff->nSI; + compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret, + compat->num_si, + XkbSymInterpretRec); + if (!compat->sym_interpret) { + compat->num_si= 0; + return BadAlloc; + } + } + else if (stuff->truncateSI) { + compat->num_si = stuff->firstSI+stuff->nSI; + } + sym = &compat->sym_interpret[stuff->firstSI]; + for (i=0;inSI;i++,wire++,sym++) { + if (client->swapped) { + register int n; + swapl(&wire->sym,n); + } + sym->sym= wire->sym; + sym->mods= wire->mods; + sym->match= wire->match; + sym->flags= wire->flags; + sym->virtual_mod= wire->virtualMod; + memcpy((char *)&sym->act,(char *)&wire->act, + SIZEOF(xkbActionWireDesc)); + } + data = (char *)wire; + } + else if (stuff->truncateSI) { + compat->num_si = stuff->firstSI; + } + + if (stuff->groups!=0) { + register unsigned i,bit; + xkbModsWireDesc *wire = (xkbModsWireDesc *)data; + for (i=0,bit=1;igroups&bit) { + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + compat->groups[i].mask= wire->realMods; + compat->groups[i].real_mods= wire->realMods; + compat->groups[i].vmods= wire->virtualMods; + if (wire->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkb,wire->virtualMods); + compat->groups[i].mask|= tmp; + } + data+= SIZEOF(xkbModsWireDesc); + wire= (xkbModsWireDesc *)data; + } + } + } + i= XkbPaddedSize((data-((char *)stuff))); + if ((i/4)!=stuff->length) { + ErrorF("Internal length error on read in ProcXkbSetCompatMap\n"); + return BadLength; + } + + if (dev->xkb_interest) { + xkbCompatMapNotify ev; + ev.deviceID = dev->id; + ev.changedGroups = stuff->groups; + ev.firstSI = stuff->firstSI; + ev.nSI = stuff->nSI; + ev.nTotalSI = compat->num_si; + XkbSendCompatMapNotify(dev,&ev); + } + + if (stuff->recomputeActions) { + XkbChangesRec change; + unsigned check; + XkbEventCauseRec cause; + + XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client); + bzero(&change,sizeof(XkbChangesRec)); + XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check, + &cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + XkbUpdateCoreDescription(dev,False); + XkbSendNotification(dev,&change,&cause); + } + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetIndicatorState(ClientPtr client) +#else +ProcXkbGetIndicatorState(client) + ClientPtr client; +#endif +{ + xkbGetIndicatorStateReply rep; + XkbSrvLedInfoPtr sli; + DeviceIntPtr dev; + register int i; + + REQUEST(xkbGetIndicatorStateReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorStateMask); + if (!sli) + return BadAlloc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.state = sli->effectiveState; + + if (client->swapped) { + swaps(&rep.sequenceNumber,i); + swapl(&rep.state,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbComputeGetIndicatorMapReplySize( + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply *rep) +#else +XkbComputeGetIndicatorMapReplySize(indicators,rep) + XkbIndicatorPtr indicators; + xkbGetIndicatorMapReply *rep; +#endif +{ +register int i,bit; +int nIndicators; + + rep->realIndicators = indicators->phys_indicators; + for (i=nIndicators=0,bit=1;iwhich&bit) + nIndicators++; + } + rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4; + return Success; +} + +int +#if NeedFunctionPrototypes +XkbSendIndicatorMap( ClientPtr client, + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply * rep) +#else +XkbSendIndicatorMap(client,indicators,rep) + ClientPtr client; + XkbIndicatorPtr indicators; + xkbGetIndicatorMapReply * rep; +#endif +{ +int length; +CARD8 * map; +register int i; +register unsigned bit; + + length = rep->length*4; + if (length>0) { + CARD8 *to; + to= map= (CARD8 *)ALLOCATE_LOCAL(length); + if (map) { + xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to; + for (i=0,bit=1;iwhich&bit) { + wire->flags= indicators->maps[i].flags; + wire->whichGroups= indicators->maps[i].which_groups; + wire->groups= indicators->maps[i].groups; + wire->whichMods= indicators->maps[i].which_mods; + wire->mods= indicators->maps[i].mods.mask; + wire->realMods= indicators->maps[i].mods.real_mods; + wire->virtualMods= indicators->maps[i].mods.vmods; + wire->ctrls= indicators->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + swapl(&wire->ctrls,n); + } + wire++; + } + } + to = (CARD8 *)wire; + if ((to-map)!=length) { + client->errorValue = _XkbErrCode2(0xff,length); + return BadLength; + } + } + else return BadAlloc; + } + else map = NULL; + if (client->swapped) { + swaps(&rep->sequenceNumber,i); + swapl(&rep->length,i); + swapl(&rep->which,i); + swapl(&rep->realIndicators,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep); + if (map) { + WriteToClient(client, length, (char *)map); + DEALLOCATE_LOCAL((char *)map); + } + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetIndicatorMap(ClientPtr client) +#else +ProcXkbGetIndicatorMap(client) + ClientPtr client; +#endif +{ +xkbGetIndicatorMapReply rep; +DeviceIntPtr dev; +XkbDescPtr xkb; +XkbIndicatorPtr leds; + + REQUEST(xkbGetIndicatorMapReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb= dev->key->xkbInfo->desc; + leds= xkb->indicators; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + XkbComputeGetIndicatorMapReplySize(leds,&rep); + return XkbSendIndicatorMap(client,leds,&rep); +} + +int +#if NeedFunctionPrototypes +ProcXkbSetIndicatorMap(ClientPtr client) +#else +ProcXkbSetIndicatorMap(client) + ClientPtr client; +#endif +{ + register int i,bit; + int nIndicators,why; + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + xkbIndicatorMapWireDesc *from; + XkbSrvLedInfoPtr sli; + XkbEventCauseRec cause; + + REQUEST(xkbSetIndicatorMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + dev = _XkbLookupKeyboard(stuff->deviceSpec,&why); + if (!dev) { + client->errorValue = _XkbErrCode2(why,stuff->deviceSpec); + return XkbKeyboardErrorCode; + } + xkbi= dev->key->xkbInfo; + + if (stuff->which==0) + return client->noClientException; + + for (nIndicators=i=0,bit=1;iwhich&bit) + nIndicators++; + } + if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+ + (nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) { + return BadLength; + } + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorMapsMask); + if (!sli) + return BadAlloc; + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;iwhich&bit) { + if (client->swapped) { + register int n; + swaps(&from->virtualMods,n); + swapl(&from->ctrls,n); + } + CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods); + from++; + } + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;iwhich&bit) { + sli->maps[i].flags = from->flags; + sli->maps[i].which_groups = from->whichGroups; + sli->maps[i].groups = from->groups; + sli->maps[i].which_mods = from->whichMods; + sli->maps[i].mods.mask = from->mods; + sli->maps[i].mods.real_mods = from->mods; + sli->maps[i].mods.vmods= from->virtualMods; + sli->maps[i].ctrls = from->ctrls; + if (from->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkbi->desc,from->virtualMods); + sli->maps[i].mods.mask= from->mods|tmp; + } + from++; + } + } + + XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client); + XkbApplyLedMapChanges(dev,sli,stuff->which,NULL,NULL,&cause); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetNamedIndicator(ClientPtr client) +#else +ProcXkbGetNamedIndicator(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbGetNamedIndicatorReply rep; + register int i; + XkbSrvLedInfoPtr sli; + XkbIndicatorMapPtr map; + Bool supported; + + REQUEST(xkbGetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_ONLY(stuff->indicator); + + sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0); + if (!sli) + return BadAlloc; + + supported= True; + if (XkbXIUnsupported&XkbXI_IndicatorsMask) { + if ((dev!=(DeviceIntPtr)LookupKeyboardDevice())|| + ((sli->flags&XkbSLI_IsDefault)==0)) { + supported= False; + } + } + + if (supported) { + i= 0; + map= NULL; + if ((sli->names)&&(sli->maps)) { + for (i=0;iindicator==sli->names[i]) { + map= &sli->maps[i]; + break; + } + } + } + } + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.deviceID = dev->id; + rep.indicator= stuff->indicator; + if ((map!=NULL)&&(supported)) { + rep.found= True; + rep.on= ((sli->effectiveState&(1<physIndicators&(1<flags; + rep.whichGroups= map->which_groups; + rep.groups= map->groups; + rep.whichMods= map->which_mods; + rep.mods= map->mods.mask; + rep.realMods= map->mods.real_mods; + rep.virtualMods= map->mods.vmods; + rep.ctrls= map->ctrls; + rep.supported= True; + } + else { + rep.found= False; + rep.on= False; + rep.realIndicator= False; + rep.ndx= XkbNoIndicator; + rep.flags= 0; + rep.whichGroups= 0; + rep.groups= 0; + rep.whichMods= 0; + rep.mods= 0; + rep.realMods= 0; + rep.virtualMods= 0; + rep.ctrls= 0; + rep.supported= supported; + } + if ( client->swapped ) { + register int n; + swapl(&rep.length,n); + swaps(&rep.sequenceNumber,n); + swapl(&rep.indicator,n); + swaps(&rep.virtualMods,n); + swapl(&rep.ctrls,n); + } + + WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep); + if (!supported) { + xkbExtensionDeviceNotify edev; + + bzero(&edev,sizeof(xkbExtensionDeviceNotify)); + edev.reason= XkbXI_UnsupportedFeatureMask; + edev.ledClass= stuff->ledClass; + edev.ledID= stuff->ledID; + edev.ledsDefined= sli->namesPresent|sli->mapsPresent; + edev.ledState= sli->effectiveState; + edev.firstBtn= 0; + edev.nBtns= 0; + edev.unsupported= XkbXIUnsupported&XkbXI_IndicatorsMask; + edev.supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + XkbSendExtensionDeviceNotify(dev,client,&edev); + } + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetNamedIndicator(ClientPtr client) +#else +ProcXkbSetNamedIndicator(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev,kbd; + XkbIndicatorMapPtr map; + XkbSrvLedInfoPtr sli; + register int led; + unsigned extDevReason; + unsigned statec,namec,mapc; + XkbEventCauseRec cause; + xkbExtensionDeviceNotify ed; + XkbChangesRec changes; + + REQUEST(xkbSetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_ONLY(stuff->indicator); + CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods); + + extDevReason= 0; + + sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID, + XkbXI_IndicatorsMask); + if (!sli) + return BadAlloc; + + if (XkbXIUnsupported&XkbXI_IndicatorsMask) { + if ((dev!=(DeviceIntPtr)LookupKeyboardDevice())|| + ((sli->flags&XkbSLI_IsDefault)==0)) { + bzero(&ed,sizeof(xkbExtensionDeviceNotify)); + ed.reason= XkbXI_UnsupportedFeatureMask; + ed.ledClass= stuff->ledClass; + ed.ledID= stuff->ledID; + ed.ledsDefined= sli->namesPresent|sli->mapsPresent; + ed.ledState= sli->effectiveState; + ed.firstBtn= 0; + ed.nBtns= 0; + ed.unsupported= XkbXIUnsupported&XkbXI_IndicatorsMask; + ed.supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + XkbSendExtensionDeviceNotify(dev,client,&ed); + return client->noClientException; + } + } + + statec= mapc= namec= 0; + map= NULL; + if (sli->names && sli->maps) { + for (led=0;(lednames[led]==stuff->indicator) { + map= &sli->maps[led]; + break; + } + } + } + if (map==NULL) { + if (!stuff->createMap) + return client->noClientException; + for (led=0,map=NULL;(lednames[led]==None)&&(!XkbIM_InUse(&sli->maps[led]))) { + map= &sli->maps[led]; + sli->names[led]= stuff->indicator; + break; + } + } + if (map==NULL) + return client->noClientException; + namec|= (1<namesPresent|= ((stuff->indicator!=None)?(1<setMap) { + map->flags = stuff->flags; + map->which_groups = stuff->whichGroups; + map->groups = stuff->groups; + map->which_mods = stuff->whichMods; + map->mods.mask = stuff->realMods; + map->mods.real_mods = stuff->realMods; + map->mods.vmods= stuff->virtualMods; + map->ctrls = stuff->ctrls; + mapc|= (1<setState)&&((map->flags&XkbIM_NoExplicit)==0)) { + if (stuff->on) sli->explicitState|= (1<explicitState&= ~(1<effectiveState^sli->explicitState)&(1<flags&XkbSLI_HasOwnState)==0) + kbd= (DeviceIntPtr)LookupKeyboardDevice(); + XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); + return client->noClientException; +} + +/***====================================================================***/ + +static CARD32 +#if NeedFunctionPrototypes +_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count) +#else +_XkbCountAtoms(atoms,maxAtoms,count) + Atom *atoms; + int maxAtoms; + int *count; +#endif +{ +register unsigned int i,bit,nAtoms; +register CARD32 atomsPresent; + + for (i=nAtoms=atomsPresent=0,bit=1;iminKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + which= rep->which; + length= 0; + if (xkb->names!=NULL) { + if (which&XkbKeycodesNameMask) length++; + if (which&XkbGeometryNameMask) length++; + if (which&XkbSymbolsNameMask) length++; + if (which&XkbPhysSymbolsNameMask) length++; + if (which&XkbTypesNameMask) length++; + if (which&XkbCompatNameMask) length++; + } + else which&= ~XkbComponentNamesMask; + + if (xkb->map!=NULL) { + if (which&XkbKeyTypeNamesMask) + length+= xkb->map->num_types; + rep->nTypes= xkb->map->num_types; + if (which&XkbKTLevelNamesMask) { + XkbKeyTypePtr pType = xkb->map->types; + int nKTLevels = 0; + + length+= XkbPaddedSize(xkb->map->num_types)/4; + for (i=0;imap->num_types;i++,pType++) { + if (pType->level_names!=NULL) + nKTLevels+= pType->num_levels; + } + rep->nKTLevels= nKTLevels; + length+= nKTLevels; + } + } + else { + rep->nTypes= 0; + rep->nKTLevels= 0; + which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask); + } + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + rep->indicators= 0; + rep->virtualMods= 0; + rep->groupNames= 0; + if (xkb->names!=NULL) { + if (which&XkbIndicatorNamesMask) { + int nLeds; + rep->indicators= + _XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds); + length+= nLeds; + if (nLeds==0) + which&= ~XkbIndicatorNamesMask; + } + + if (which&XkbVirtualModNamesMask) { + int nVMods; + rep->virtualMods= + _XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods); + length+= nVMods; + if (nVMods==0) + which&= ~XkbVirtualModNamesMask; + } + + if (which&XkbGroupNamesMask) { + int nGroups; + rep->groupNames= + _XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups); + length+= nGroups; + if (nGroups==0) + which&= ~XkbGroupNamesMask; + } + + if ((which&XkbKeyNamesMask)&&(xkb->names->keys)) + length+= rep->nKeys; + else which&= ~XkbKeyNamesMask; + + if ((which&XkbKeyAliasesMask)&& + (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) { + rep->nKeyAliases= xkb->names->num_key_aliases; + length+= rep->nKeyAliases*2; + } + else { + which&= ~XkbKeyAliasesMask; + rep->nKeyAliases= 0; + } + + if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0)) + length+= xkb->names->num_rg; + else which&= ~XkbRGNamesMask; + } + else { + which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask); + which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask); + which&= ~XkbRGNamesMask; + } + + rep->length= length; + rep->which= which; + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep) +#else +XkbSendNames(client,xkb,rep) + ClientPtr client; + XkbDescPtr xkb; + xkbGetNamesReply * rep; +#endif +{ +register unsigned i,length,which; +char * start; +char * desc; + + length= rep->length*4; + which= rep->which; + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->which,n); + swaps(&rep->virtualMods,n); + swapl(&rep->indicators,n); + } + + start = desc = (char *)ALLOCATE_LOCAL(length); + if ( !start ) + return BadAlloc; + if (which&XkbKeycodesNameMask) { + *((CARD32 *)desc)= xkb->names->keycodes; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbGeometryNameMask) { + *((CARD32 *)desc)= xkb->names->geometry; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbSymbolsNameMask) { + *((CARD32 *)desc)= xkb->names->symbols; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbPhysSymbolsNameMask) { + register CARD32 *atm= (CARD32 *)desc; + atm[0]= (CARD32)xkb->names->phys_symbols; + if (client->swapped) { + register int n; + swapl(&atm[0],n); + } + desc+= 4; + } + if (which&XkbTypesNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->types; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbCompatNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->compat; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbKeyTypeNamesMask) { + register CARD32 *atm= (CARD32 *)desc; + register XkbKeyTypePtr type= xkb->map->types; + + for (i=0;imap->num_types;i++,atm++,type++) { + *atm= (CARD32)type->name; + if (client->swapped) { + register int n; + swapl(atm,n); + } + } + desc= (char *)atm; + } + if (which&XkbKTLevelNamesMask) { + XkbKeyTypePtr type = xkb->map->types; + register CARD32 *atm; + for (i=0;inTypes;i++,type++) { + *desc++ = type->num_levels; + } + desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes; + + atm= (CARD32 *)desc; + type = xkb->map->types; + for (i=0;imap->num_types;i++,type++) { + register unsigned l; + if (type->level_names) { + for (l=0;lnum_levels;l++,atm++) { + *atm= type->level_names[l]; + if (client->swapped) { + register unsigned n; + swapl(atm,n); + } + } + desc+= type->num_levels*4; + } + } + } + if (which&XkbIndicatorNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators, + client->swapped); + } + if (which&XkbVirtualModNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods, + client->swapped); + } + if (which&XkbGroupNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups, + client->swapped); + } + if (which&XkbKeyNamesMask) { + for (i=0;inKeys;i++,desc+= sizeof(XkbKeyNameRec)) { + *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey]; + } + } + if (which&XkbKeyAliasesMask) { + XkbKeyAliasPtr pAl; + pAl= xkb->names->key_aliases; + for (i=0;inKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) { + *((XkbKeyAliasPtr)desc)= *pAl; + } + } + if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) { + register CARD32 *atm= (CARD32 *)desc; + for (i=0;inRadioGroups;i++,atm++) { + *atm= (CARD32)xkb->names->radio_groups[i]; + if (client->swapped) { + register unsigned n; + swapl(atm,n); + } + } + desc+= rep->nRadioGroups*4; + } + if ((desc-start)!=(length)) { + ErrorF("BOGUS LENGTH in write names, expected %d, got %d\n", + length, desc-start); + } + WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep); + WriteToClient(client, length, start); + DEALLOCATE_LOCAL((char *)start); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetNames(ClientPtr client) +#else +ProcXkbGetNames(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbDescPtr xkb; + xkbGetNamesReply rep; + + REQUEST(xkbGetNamesReq); + REQUEST_SIZE_MATCH(xkbGetNamesReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + xkb = dev->key->xkbInfo->desc; + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + rep.nTypes = xkb->map->num_types; + rep.firstKey = xkb->min_key_code; + rep.nKeys = XkbNumKeys(xkb); + if (xkb->names!=NULL) { + rep.nKeyAliases= xkb->names->num_key_aliases; + rep.nRadioGroups = xkb->names->num_rg; + } + else { + rep.nKeyAliases= rep.nRadioGroups= 0; + } + XkbComputeGetNamesReplySize(xkb,&rep); + return XkbSendNames(client,xkb,&rep); +} + +/***====================================================================***/ + +static CARD32 * +#if NeedFunctionPrototypes +_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError) +#else +_XkbCheckAtoms(wire,nAtoms,swapped,pError) + CARD32 *wire; + int nAtoms; + int swapped; + Atom *pError; +#endif +{ +register int i; + + for (i=0;ixkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + xkb = dev->key->xkbInfo->desc; + names = xkb->names; + tmp = (CARD32 *)&stuff[1]; + + if (stuff->which&XkbKeycodesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGeometryNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbPhysSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbTypesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbCompatNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbKeyTypeNamesMask) { + register int i; + CARD32 *old; + if ( stuff->nTypes<1 ) { + client->errorValue = _XkbErrCode2(0x02,stuff->nTypes); + return BadValue; + } + if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x03,stuff->firstType, + stuff->nTypes, + xkb->map->num_types); + return BadValue; + } + if (((unsigned)stuff->firstType)<=XkbLastRequiredType) { + client->errorValue = _XkbErrCode2(0x04,stuff->firstType); + return BadAccess; + } + old= tmp; + tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + for (i=0;inTypes;i++,old++) { + if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i)) + client->errorValue= _XkbErrCode2(0x05,i); + } + } + if (stuff->which&XkbKTLevelNamesMask) { + register unsigned i; + XkbKeyTypePtr type; + CARD8 * width; + if ( stuff->nKTLevels<1 ) { + client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels); + return BadValue; + } + if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>= + xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel, + stuff->nKTLevels,xkb->map->num_types); + return BadValue; + } + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type = &xkb->map->types[stuff->firstKTLevel]; + for (i=0;inKTLevels;i++,type++) { + if (width[i]==0) + continue; + else if (width[i]!=type->num_levels) { + client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel, + type->num_levels,width[i]); + return BadMatch; + } + tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + } + if (stuff->which&XkbIndicatorNamesMask) { + if (stuff->indicators==0) { + client->errorValue= 0x08; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators, + client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbVirtualModNamesMask) { + if (stuff->virtualMods==0) { + client->errorValue= 0x09; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods, + (CARD32)stuff->virtualMods, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGroupNamesMask) { + if (stuff->groupNames==0) { + client->errorValue= 0x0a; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups, + (CARD32)stuff->groupNames, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbKeyNamesMask) { + if (stuff->firstKey<(unsigned)xkb->min_key_code) { + client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code, + stuff->firstKey); + return BadValue; + } + if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)|| + (stuff->nKeys<1)) { + client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code, + stuff->firstKey,stuff->nKeys); + return BadValue; + } + tmp+= stuff->nKeys; + } + if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) { + tmp+= stuff->nKeyAliases*2; + } + if (stuff->which&XkbRGNamesMask) { + if ( stuff->nRadioGroups<1 ) { + client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups); + return BadValue; + } + tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if ((tmp-((CARD32 *)stuff))!=stuff->length) { + client->errorValue = stuff->length; + return BadLength; + } + if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups, + stuff->nKeyAliases)!=Success) { + return BadAlloc; + } + + /* everything is okay -- update names */ + bzero(&nn,sizeof(xkbNamesNotify)); + nn.changed= stuff->which; + tmp = (CARD32 *)&stuff[1]; + if (stuff->which&XkbKeycodesNameMask) + names->keycodes= *tmp++; + if (stuff->which&XkbGeometryNameMask) + names->geometry= *tmp++; + if (stuff->which&XkbSymbolsNameMask) + names->symbols= *tmp++; + if (stuff->which&XkbPhysSymbolsNameMask) + names->phys_symbols= *tmp++; + if (stuff->which&XkbTypesNameMask) + names->types= *tmp++; + if (stuff->which&XkbCompatNameMask) + names->compat= *tmp++; + if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) { + register unsigned i; + register XkbKeyTypePtr type; + + type= &xkb->map->types[stuff->firstType]; + for (i=0;inTypes;i++,type++) { + type->name= *tmp++; + } + nn.firstType= stuff->firstType; + nn.nTypes= stuff->nTypes; + } + if (stuff->which&XkbKTLevelNamesMask) { + register XkbKeyTypePtr type; + register unsigned i; + CARD8 *width; + + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type= &xkb->map->types[stuff->firstKTLevel]; + for (i=0;inKTLevels;i++,type++) { + if (width[i]>0) { + if (type->level_names) { + register unsigned n; + for (n=0;nlevel_names[n]= tmp[n]; + } + } + tmp+= width[i]; + } + } + nn.firstLevelName= 0; + nn.nLevelNames= stuff->nTypes; + } + if (stuff->which&XkbIndicatorNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators, + stuff->indicators); + nn.changedIndicators= stuff->indicators; + } + if (stuff->which&XkbVirtualModNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods, + stuff->virtualMods); + nn.changedVirtualMods= stuff->virtualMods; + } + if (stuff->which&XkbGroupNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups, + stuff->groupNames); + nn.changedVirtualMods= stuff->groupNames; + } + if (stuff->which&XkbKeyNamesMask) { + memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp, + stuff->nKeys*XkbKeyNameLength); + tmp+= stuff->nKeys; + nn.firstKey= stuff->firstKey; + nn.nKeys= stuff->nKeys; + } + if (stuff->which&XkbKeyAliasesMask) { + if (stuff->nKeyAliases>0) { + register int na= stuff->nKeyAliases; + if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success) + return BadAlloc; + memcpy((char *)names->key_aliases,(char *)tmp, + stuff->nKeyAliases*sizeof(XkbKeyAliasRec)); + tmp+= stuff->nKeyAliases*2; + } + else if (names->key_aliases!=NULL) { + _XkbFree(names->key_aliases); + names->key_aliases= NULL; + names->num_key_aliases= 0; + } + nn.nAliases= names->num_key_aliases; + } + if (stuff->which&XkbRGNamesMask) { + if (stuff->nRadioGroups>0) { + register unsigned i,nrg; + nrg= stuff->nRadioGroups; + if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success) + return BadAlloc; + + for (i=0;inRadioGroups;i++) { + names->radio_groups[i]= tmp[i]; + } + tmp+= stuff->nRadioGroups; + } + else if (names->radio_groups) { + Xfree(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + nn.nRadioGroups= names->num_rg; + } + if (nn.changed) { + Bool needExtEvent; + needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0; + XkbSendNamesNotify(dev,&nn); + if (needExtEvent) { + XkbSrvLedInfoPtr sli; + xkbExtensionDeviceNotify edev; + register int i; + register unsigned bit; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorsMask); + sli->namesPresent= 0; + for (i=0,bit=1;iindicators[i]!=None) + sli->namesPresent|= bit; + } + bzero(&edev,sizeof(xkbExtensionDeviceNotify)); + edev.reason= XkbXI_IndicatorNamesMask; + edev.ledClass= KbdFeedbackClass; + edev.ledID= dev->kbdfeed->ctrl.id; + edev.ledsDefined= sli->namesPresent|sli->mapsPresent; + edev.ledState= sli->effectiveState; + edev.firstBtn= 0; + edev.nBtns= 0; + edev.supported= XkbXI_AllFeaturesMask; + edev.unsupported= 0; + XkbSendExtensionDeviceNotify(dev,client,&edev); + } + } + return client->noClientException; +} + +/***====================================================================***/ + +#include "XKBgeom.h" + +#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) + +static char * +#if NeedFunctionPrototypes +XkbWriteCountedString(char *wire,char *str,Bool swap) +#else +XkbWriteCountedString(wire,str,swap) + char * wire; + char * str; + Bool swap; +#endif +{ +CARD16 len,*pLen; + + len= (str?strlen(str):0); + pLen= (CARD16 *)wire; + *pLen= len; + if (swap) { + register int n; + swaps(pLen,n); + } + memcpy(&wire[2],str,len); + wire+= ((2+len+3)/4)*4; + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomProperties(XkbGeometryPtr geom) +#else +XkbSizeGeomProperties(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +XkbPropertyPtr prop; + + for (size=i=0,prop=geom->properties;inum_properties;i++,prop++) { + size+= XkbSizeCountedString(prop->name); + size+= XkbSizeCountedString(prop->value); + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomProperties(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int i; +register XkbPropertyPtr prop; + + for (i=0,prop=geom->properties;inum_properties;i++,prop++) { + wire= XkbWriteCountedString(wire,prop->name,swap); + wire= XkbWriteCountedString(wire,prop->value,swap); + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomKeyAliases(XkbGeometryPtr geom) +#else +XkbSizeGeomKeyAliases(geom) + XkbGeometryPtr geom; +#endif +{ + return geom->num_key_aliases*(2*XkbKeyNameLength); +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomKeyAliases(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int sz; + + sz= geom->num_key_aliases*(XkbKeyNameLength*2); + if (sz>0) { + memcpy(wire,(char *)geom->key_aliases,sz); + wire+= sz; + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomColors(XkbGeometryPtr geom) +#else +XkbSizeGeomColors(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +register XkbColorPtr color; + + for (i=size=0,color=geom->colors;inum_colors;i++,color++) { + size+= XkbSizeCountedString(color->spec); + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomColors(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int i; +register XkbColorPtr color; + + for (i=0,color=geom->colors;inum_colors;i++,color++) { + wire= XkbWriteCountedString(wire,color->spec,swap); + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomShapes(XkbGeometryPtr geom) +#else +XkbSizeGeomShapes(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +register XkbShapePtr shape; + + for (i=size=0,shape=geom->shapes;inum_shapes;i++,shape++) { + register int n; + register XkbOutlinePtr ol; + size+= SIZEOF(xkbShapeWireDesc); + for (n=0,ol=shape->outlines;nnum_outlines;n++,ol++) { + size+= SIZEOF(xkbOutlineWireDesc); + size+= ol->num_points*SIZEOF(xkbPointWireDesc); + } + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomShapes(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +int i; +XkbShapePtr shape; +xkbShapeWireDesc * shapeWire; + + for (i=0,shape=geom->shapes;inum_shapes;i++,shape++) { + register int o; + XkbOutlinePtr ol; + xkbOutlineWireDesc * olWire; + shapeWire= (xkbShapeWireDesc *)wire; + shapeWire->name= shape->name; + shapeWire->nOutlines= shape->num_outlines; + if (shape->primary!=NULL) + shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary); + else shapeWire->primaryNdx= XkbNoShape; + if (shape->approx!=NULL) + shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx); + else shapeWire->approxNdx= XkbNoShape; + if (swap) { + register int n; + swapl(&shapeWire->name,n); + } + wire= (char *)&shapeWire[1]; + for (o=0,ol=shape->outlines;onum_outlines;o++,ol++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + olWire= (xkbOutlineWireDesc *)wire; + olWire->nPoints= ol->num_points; + olWire->cornerRadius= ol->corner_radius; + wire= (char *)&olWire[1]; + ptWire= (xkbPointWireDesc *)wire; + for (p=0,pt=ol->points;pnum_points;p++,pt++) { + ptWire[p].x= pt->x; + ptWire[p].y= pt->y; + if (swap) { + register int n; + swaps(&ptWire[p].x,n); + swaps(&ptWire[p].y,n); + } + } + wire= (char *)&ptWire[ol->num_points]; + } + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad) +#else +XkbSizeGeomDoodads(num_doodads,doodad) + int num_doodads; + XkbDoodadPtr doodad; +#endif +{ +register int i,size; + + for (i=size=0;iany.type==XkbTextDoodad) { + size+= XkbSizeCountedString(doodad->text.text); + size+= XkbSizeCountedString(doodad->text.font); + } + else if (doodad->any.type==XkbLogoDoodad) { + size+= XkbSizeCountedString(doodad->logo.logo_name); + } + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap) +#else +XkbWriteGeomDoodads(wire,num_doodads,doodad,swap) + char * wire; + int num_doodads; + XkbDoodadPtr doodad; + Bool swap; +#endif +{ +register int i; +xkbDoodadWireDesc * doodadWire; + + for (i=0;iany.name= doodad->any.name; + doodadWire->any.type= doodad->any.type; + doodadWire->any.priority= doodad->any.priority; + doodadWire->any.top= doodad->any.top; + doodadWire->any.left= doodad->any.left; + if (swap) { + register int n; + swapl(&doodadWire->any.name,n); + swaps(&doodadWire->any.top,n); + swaps(&doodadWire->any.left,n); + } + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodadWire->shape.angle= doodad->shape.angle; + doodadWire->shape.colorNdx= doodad->shape.color_ndx; + doodadWire->shape.shapeNdx= doodad->shape.shape_ndx; + if (swap) { + register int n; + swaps(&doodadWire->shape.angle,n); + } + break; + case XkbTextDoodad: + doodadWire->text.angle= doodad->text.angle; + doodadWire->text.width= doodad->text.width; + doodadWire->text.height= doodad->text.height; + doodadWire->text.colorNdx= doodad->text.color_ndx; + if (swap) { + register int n; + swaps(&doodadWire->text.angle,n); + swaps(&doodadWire->text.width,n); + swaps(&doodadWire->text.height,n); + } + wire= XkbWriteCountedString(wire,doodad->text.text,swap); + wire= XkbWriteCountedString(wire,doodad->text.font,swap); + break; + case XkbIndicatorDoodad: + doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx; + doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx; + doodadWire->indicator.offColorNdx= + doodad->indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodadWire->logo.angle= doodad->logo.angle; + doodadWire->logo.colorNdx= doodad->logo.color_ndx; + doodadWire->logo.shapeNdx= doodad->logo.shape_ndx; + wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap); + break; + default: + ErrorF("Unknown doodad type %d in XkbWriteGeomDoodads\n"); + ErrorF("Ignored\n"); + break; + } + } + return wire; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap) +#else +XkbWriteGeomOverlay(wire,ol,swap) + char * wire; + XkbOverlayPtr ol; + Bool swap; +#endif +{ +register int r; +XkbOverlayRowPtr row; +xkbOverlayWireDesc * olWire; + + olWire= (xkbOverlayWireDesc *)wire; + olWire->name= ol->name; + olWire->nRows= ol->num_rows; + if (swap) { + register int n; + swapl(&olWire->name,n); + } + wire= (char *)&olWire[1]; + for (r=0,row=ol->rows;rnum_rows;r++,row++) { + unsigned int k; + XkbOverlayKeyPtr key; + xkbOverlayRowWireDesc * rowWire; + rowWire= (xkbOverlayRowWireDesc *)wire; + rowWire->rowUnder= row->row_under; + rowWire->nKeys= row->num_keys; + wire= (char *)&rowWire[1]; + for (k=0,key=row->keys;knum_keys;k++,key++) { + xkbOverlayKeyWireDesc * keyWire; + keyWire= (xkbOverlayKeyWireDesc *)wire; + memcpy(keyWire->over,key->over.name,XkbKeyNameLength); + memcpy(keyWire->under,key->under.name,XkbKeyNameLength); + wire= (char *)&keyWire[1]; + } + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomSections(XkbGeometryPtr geom) +#else +XkbSizeGeomSections(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +XkbSectionPtr section; + + for (i=size=0,section=geom->sections;inum_sections;i++,section++) { + size+= SIZEOF(xkbSectionWireDesc); + if (section->rows) { + int r; + XkbRowPtr row; + for (r=0,row=section->rows;rnum_rows;row++,r++) { + size+= SIZEOF(xkbRowWireDesc); + size+= row->num_keys*SIZEOF(xkbKeyWireDesc); + } + } + if (section->doodads) + size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads); + if (section->overlays) { + int o; + XkbOverlayPtr ol; + for (o=0,ol=section->overlays;onum_overlays;o++,ol++) { + int r; + XkbOverlayRowPtr row; + size+= SIZEOF(xkbOverlayWireDesc); + for (r=0,row=ol->rows;rnum_rows;r++,row++) { + size+= SIZEOF(xkbOverlayRowWireDesc); + size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc); + } + } + } + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomSections(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int i; +XkbSectionPtr section; +xkbSectionWireDesc * sectionWire; + + for (i=0,section=geom->sections;inum_sections;i++,section++) { + sectionWire= (xkbSectionWireDesc *)wire; + sectionWire->name= section->name; + sectionWire->top= section->top; + sectionWire->left= section->left; + sectionWire->width= section->width; + sectionWire->height= section->height; + sectionWire->angle= section->angle; + sectionWire->priority= section->priority; + sectionWire->nRows= section->num_rows; + sectionWire->nDoodads= section->num_doodads; + sectionWire->nOverlays= section->num_overlays; + sectionWire->pad= 0; + if (swap) { + register int n; + swapl(§ionWire->name,n); + swaps(§ionWire->top,n); + swaps(§ionWire->left,n); + swaps(§ionWire->width,n); + swaps(§ionWire->height,n); + swaps(§ionWire->angle,n); + } + wire= (char *)§ionWire[1]; + if (section->rows) { + int r; + XkbRowPtr row; + xkbRowWireDesc * rowWire; + for (r=0,row=section->rows;rnum_rows;r++,row++) { + rowWire= (xkbRowWireDesc *)wire; + rowWire->top= row->top; + rowWire->left= row->left; + rowWire->nKeys= row->num_keys; + rowWire->vertical= row->vertical; + rowWire->pad= 0; + if (swap) { + register int n; + swaps(&rowWire->top,n); + swaps(&rowWire->left,n); + } + wire= (char *)&rowWire[1]; + if (row->keys) { + int k; + XkbKeyPtr key; + xkbKeyWireDesc * keyWire; + keyWire= (xkbKeyWireDesc *)wire; + for (k=0,key=row->keys;knum_keys;k++,key++) { + memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength); + keyWire[k].gap= key->gap; + keyWire[k].shapeNdx= key->shape_ndx; + keyWire[k].colorNdx= key->color_ndx; + if (swap) { + register int n; + swaps(&keyWire[k].gap,n); + } + } + wire= (char *)&keyWire[row->num_keys]; + } + } + } + if (section->doodads) { + wire= XkbWriteGeomDoodads(wire, + section->num_doodads,section->doodads, + swap); + } + if (section->overlays) { + register int o; + for (o=0;onum_overlays;o++) { + wire= XkbWriteGeomOverlay(wire,§ion->overlays[o],swap); + } + } + } + return wire; +} + +static Status +#if NeedFunctionPrototypes +XkbComputeGetGeometryReplySize( XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Atom name) +#else +XkbComputeGetGeometryReplySize(geom,rep,name) + XkbGeometryPtr geom; + xkbGetGeometryReply * rep; + Atom name; +#endif +{ +int len; + + if (geom!=NULL) { + len= XkbSizeCountedString(geom->label_font); + len+= XkbSizeGeomProperties(geom); + len+= XkbSizeGeomColors(geom); + len+= XkbSizeGeomShapes(geom); + len+= XkbSizeGeomSections(geom); + len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads); + len+= XkbSizeGeomKeyAliases(geom); + rep->length= len/4; + rep->found= True; + rep->name= geom->name; + rep->widthMM= geom->width_mm; + rep->heightMM= geom->height_mm; + rep->nProperties= geom->num_properties; + rep->nColors= geom->num_colors; + rep->nShapes= geom->num_shapes; + rep->nSections= geom->num_sections; + rep->nDoodads= geom->num_doodads; + rep->nKeyAliases= geom->num_key_aliases; + rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color); + rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color); + } + else { + rep->length= 0; + rep->found= False; + rep->name= name; + rep->widthMM= rep->heightMM= 0; + rep->nProperties= rep->nColors= rep->nShapes= 0; + rep->nSections= rep->nDoodads= 0; + rep->nKeyAliases= 0; + rep->labelColorNdx= rep->baseColorNdx= 0; + } + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendGeometry( ClientPtr client, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Bool freeGeom) +#else +XkbSendGeometry(client,geom,rep,freeGeom) + ClientPtr client; + XkbGeometryPtr geom; + xkbGetGeometryReply *rep; + Bool freeGeom; +#endif +{ + char *desc,*start; + int len; + + if (geom!=NULL) { + len= rep->length*4; + start= desc= (char *)ALLOCATE_LOCAL(len); + if (!start) + return BadAlloc; + desc= XkbWriteCountedString(desc,geom->label_font,client->swapped); + if ( rep->nProperties>0 ) + desc = XkbWriteGeomProperties(desc,geom,client->swapped); + if ( rep->nColors>0 ) + desc = XkbWriteGeomColors(desc,geom,client->swapped); + if ( rep->nShapes>0 ) + desc = XkbWriteGeomShapes(desc,geom,client->swapped); + if ( rep->nSections>0 ) + desc = XkbWriteGeomSections(desc,geom,client->swapped); + if ( rep->nDoodads>0 ) + desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads, + client->swapped); + if ( rep->nKeyAliases>0 ) + desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped); + if ((desc-start)!=(len)) { + ErrorF("BOGUS LENGTH in XkbSendGeometry, expected %d, got %d\n", + len, desc-start); + } + } + else { + len= 0; + start= NULL; + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->name,n); + swaps(&rep->widthMM,n); + swaps(&rep->heightMM,n); + swaps(&rep->nProperties,n); + swaps(&rep->nColors,n); + swaps(&rep->nShapes,n); + swaps(&rep->nSections,n); + swaps(&rep->nDoodads,n); + swaps(&rep->nKeyAliases,n); + } + WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep); + if (len>0) + WriteToClient(client, len, start); + if (start!=NULL) + DEALLOCATE_LOCAL((char *)start); + if (freeGeom) + XkbFreeGeometry(geom,XkbGeomAllMask,True); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetGeometry(ClientPtr client) +#else +ProcXkbGetGeometry(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbGetGeometryReply rep; + XkbGeometryPtr geom; + Bool shouldFree; + Status status; + + REQUEST(xkbGetGeometryReq); + REQUEST_SIZE_MATCH(xkbGetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_OR_NONE(stuff->name); + + geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree); + rep.type= X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber= client->sequence; + rep.length= 0; + status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name); + if (status!=Success) + return status; + else return XkbSendGeometry(client,geom,&rep,shouldFree); +} + +/***====================================================================***/ + +static char * +#if NeedFunctionPrototypes +_GetCountedString(char **wire_inout,Bool swap) +#else +_GetCountedString(wire_inout,swap) + char ** wire_inout; + Bool swap; +#endif +{ +char * wire,*str; +CARD16 len,*plen; + + wire= *wire_inout; + plen= (CARD16 *)wire; + if (swap) { + register int n; + swaps(plen,n); + } + len= *plen; + str= (char *)_XkbAlloc(len+1); + if (str) { + memcpy(str,&wire[2],len); + str[len]= '\0'; + } + wire+= XkbPaddedSize(len+2); + *wire_inout= wire; + return str; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetDoodad( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +#else +_CheckSetDoodad(wire_inout,geom,section,client) + char ** wire_inout; + XkbGeometryPtr geom; + XkbSectionPtr section; + ClientPtr client; +#endif +{ +char * wire; +xkbDoodadWireDesc * dWire; +XkbDoodadPtr doodad; + + dWire= (xkbDoodadWireDesc *)(*wire_inout); + wire= (char *)&dWire[1]; + if (client->swapped) { + register int n; + swapl(&dWire->any.name,n); + swaps(&dWire->any.top,n); + swaps(&dWire->any.left,n); + swaps(&dWire->any.angle,n); + } + CHK_ATOM_ONLY(dWire->any.name); + doodad= XkbAddGeomDoodad(geom,section,dWire->any.name); + if (!doodad) + return BadAlloc; + doodad->any.type= dWire->any.type; + doodad->any.priority= dWire->any.priority; + doodad->any.top= dWire->any.top; + doodad->any.left= dWire->any.left; + doodad->any.angle= dWire->any.angle; + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if (dWire->shape.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x40,geom->num_colors, + dWire->shape.colorNdx); + return BadMatch; + } + if (dWire->shape.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x41,geom->num_shapes, + dWire->shape.shapeNdx); + return BadMatch; + } + doodad->shape.color_ndx= dWire->shape.colorNdx; + doodad->shape.shape_ndx= dWire->shape.shapeNdx; + break; + case XkbTextDoodad: + if (dWire->text.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x42,geom->num_colors, + dWire->text.colorNdx); + return BadMatch; + } + if (client->swapped) { + register int n; + swaps(&dWire->text.width,n); + swaps(&dWire->text.height,n); + } + doodad->text.width= dWire->text.width; + doodad->text.height= dWire->text.height; + doodad->text.color_ndx= dWire->text.colorNdx; + doodad->text.text= _GetCountedString(&wire,client->swapped); + doodad->text.font= _GetCountedString(&wire,client->swapped); + break; + case XkbIndicatorDoodad: + if (dWire->indicator.onColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x43,geom->num_colors, + dWire->indicator.onColorNdx); + return BadMatch; + } + if (dWire->indicator.offColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x44,geom->num_colors, + dWire->indicator.offColorNdx); + return BadMatch; + } + if (dWire->indicator.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x45,geom->num_shapes, + dWire->indicator.shapeNdx); + return BadMatch; + } + doodad->indicator.shape_ndx= dWire->indicator.shapeNdx; + doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx; + doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx; + break; + case XkbLogoDoodad: + if (dWire->logo.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x46,geom->num_colors, + dWire->logo.colorNdx); + return BadMatch; + } + if (dWire->logo.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x47,geom->num_shapes, + dWire->logo.shapeNdx); + return BadMatch; + } + doodad->logo.color_ndx= dWire->logo.colorNdx; + doodad->logo.shape_ndx= dWire->logo.shapeNdx; + doodad->logo.logo_name= _GetCountedString(&wire,client->swapped); + break; + default: + client->errorValue= _XkbErrCode2(0x4F,dWire->any.type); + return BadValue; + } + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetOverlay( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +#else +_CheckSetOverlay(wire_inout,geom,section,client) + char ** wire_inout; + XkbGeometryPtr geom; + XkbSectionPtr section; + ClientPtr client; +#endif +{ +register int r; +char * wire; +XkbOverlayPtr ol; +xkbOverlayWireDesc * olWire; +xkbOverlayRowWireDesc * rWire; + + wire= *wire_inout; + olWire= (xkbOverlayWireDesc *)wire; + if (client->swapped) { + register int n; + swapl(&olWire->name,n); + } + CHK_ATOM_ONLY(olWire->name); + ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows); + rWire= (xkbOverlayRowWireDesc *)&olWire[1]; + for (r=0;rnRows;r++) { + register int k; + xkbOverlayKeyWireDesc * kWire; + XkbOverlayRowPtr row; + + if (rWire->rowUnder>section->num_rows) { + client->errorValue= _XkbErrCode4(0x20,r,section->num_rows, + rWire->rowUnder); + return BadMatch; + } + row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys); + kWire= (xkbOverlayKeyWireDesc *)&rWire[1]; + for (k=0;knKeys;k++,kWire++) { + if (XkbAddGeomOverlayKey(ol,row, + (char *)kWire->over,(char *)kWire->under)==NULL) { + client->errorValue= _XkbErrCode3(0x21,r,k); + return BadMatch; + } + } + rWire= (xkbOverlayRowWireDesc *)kWire; + } + olWire= (xkbOverlayWireDesc *)rWire; + wire= (char *)olWire; + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetSections( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +#else +_CheckSetSections(geom,req,wire_inout,client) + XkbGeometryPtr geom; + xkbSetGeometryReq * req; + char ** wire_inout; + ClientPtr client; +#endif +{ +Status status; +register int s; +char * wire; +xkbSectionWireDesc * sWire; +XkbSectionPtr section; + + wire= *wire_inout; + if (req->nSections<1) + return Success; + sWire= (xkbSectionWireDesc *)wire; + for (s=0;snSections;s++) { + register int r; + xkbRowWireDesc * rWire; + if (client->swapped) { + register int n; + swapl(&sWire->name,n); + swaps(&sWire->top,n); + swaps(&sWire->left,n); + swaps(&sWire->width,n); + swaps(&sWire->height,n); + swaps(&sWire->angle,n); + } + CHK_ATOM_ONLY(sWire->name); + section= XkbAddGeomSection(geom,sWire->name,sWire->nRows, + sWire->nDoodads,sWire->nOverlays); + if (!section) + return BadAlloc; + section->priority= sWire->priority; + section->top= sWire->top; + section->left= sWire->left; + section->width= sWire->width; + section->height= sWire->height; + section->angle= sWire->angle; + rWire= (xkbRowWireDesc *)&sWire[1]; + for (r=0;rnRows;r++) { + register int k; + XkbRowPtr row; + xkbKeyWireDesc * kWire; + if (client->swapped) { + register int n; + swaps(&rWire->top,n); + swaps(&rWire->left,n); + } + row= XkbAddGeomRow(section,rWire->nKeys); + if (!row) + return BadAlloc; + row->top= rWire->top; + row->left= rWire->left; + row->vertical= rWire->vertical; + kWire= (xkbKeyWireDesc *)&rWire[1]; + for (k=0;knKeys;k++) { + XkbKeyPtr key; + key= XkbAddGeomKey(row); + if (!key) + return BadAlloc; + memcpy(key->name.name,kWire[k].name,XkbKeyNameLength); + key->gap= kWire[k].gap; + key->shape_ndx= kWire[k].shapeNdx; + key->color_ndx= kWire[k].colorNdx; + if (key->shape_ndx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x10,key->shape_ndx, + geom->num_shapes); + return BadMatch; + } + if (key->color_ndx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x11,key->color_ndx, + geom->num_colors); + return BadMatch; + } + } + rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys]; + } + wire= (char *)rWire; + if (sWire->nDoodads>0) { + register int d; + for (d=0;dnDoodads;d++) { + status=_CheckSetDoodad(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + if (sWire->nOverlays>0) { + register int o; + for (o=0;onOverlays;o++) { + status= _CheckSetOverlay(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + sWire= (xkbSectionWireDesc *)wire; + } + wire= (char *)sWire; + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetShapes( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +#else +_CheckSetShapes(geom,req,wire_inout,client) + XkbGeometryPtr geom; + xkbSetGeometryReq * req; + char ** wire_inout; + ClientPtr client; +#endif +{ +register int i; +char * wire; + + wire= *wire_inout; + if (req->nShapes<1) { + client->errorValue= _XkbErrCode2(0x06,req->nShapes); + return BadValue; + } + else { + xkbShapeWireDesc * shapeWire; + XkbShapePtr shape; + register int o; + shapeWire= (xkbShapeWireDesc *)wire; + for (i=0;inShapes;i++) { + xkbOutlineWireDesc * olWire; + XkbOutlinePtr ol; + shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines); + if (!shape) + return BadAlloc; + olWire= (xkbOutlineWireDesc *)(&shapeWire[1]); + for (o=0;onOutlines;o++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + + ol= XkbAddGeomOutline(shape,olWire->nPoints); + if (!ol) + return BadAlloc; + ol->corner_radius= olWire->cornerRadius; + ptWire= (xkbPointWireDesc *)&olWire[1]; + for (p=0,pt=ol->points;pnPoints;p++,pt++) { + pt->x= ptWire[p].x; + pt->y= ptWire[p].y; + if (client->swapped) { + register int n; + swaps(&pt->x,n); + swaps(&pt->y,n); + } + } + ol->num_points= olWire->nPoints; + olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]); + } + if (shapeWire->primaryNdx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire->primaryNdx]; + if (shapeWire->approxNdx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire->approxNdx]; + shapeWire= (xkbShapeWireDesc *)olWire; + } + wire= (char *)shapeWire; + } + if (geom->num_shapes!=req->nShapes) { + client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes); + return BadMatch; + } + + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetGeom( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + ClientPtr client) +#else +_CheckSetGeom(geom,req,client) + XkbGeometryPtr geom; + xkbSetGeometryReq * req; + ClientPtr client; +#endif +{ +register int i; +Status status; +char * wire; + + wire= (char *)&req[1]; + geom->label_font= _GetCountedString(&wire,client->swapped); + + for (i=0;inProperties;i++) { + char *name,*val; + name= _GetCountedString(&wire,client->swapped); + val= _GetCountedString(&wire,client->swapped); + if ((!name)||(!val)||(XkbAddGeomProperty(geom,name,val)==NULL)) + return BadAlloc; + } + + if (req->nColors<2) { + client->errorValue= _XkbErrCode3(0x01,2,req->nColors); + return BadValue; + } + if (req->baseColorNdx>req->nColors) { + client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx); + return BadMatch; + } + if (req->labelColorNdx>req->nColors) { + client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx); + return BadMatch; + } + if (req->labelColorNdx==req->baseColorNdx) { + client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx, + req->labelColorNdx); + return BadMatch; + } + + for (i=0;inColors;i++) { + char *name; + name= _GetCountedString(&wire,client->swapped); + if ((!name)||(!XkbAddGeomColor(geom,name,geom->num_colors))) + return BadAlloc; + } + if (req->nColors!=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors); + return BadMatch; + } + geom->label_color= &geom->colors[req->labelColorNdx]; + geom->base_color= &geom->colors[req->baseColorNdx]; + + if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success) + return status; + + if ((status=_CheckSetSections(geom,req,&wire,client))!=Success) + return status; + + for (i=0;inDoodads;i++) { + status=_CheckSetDoodad(&wire,geom,NULL,client); + if (status!=Success) + return status; + } + + for (i=0;inKeyAliases;i++) { + if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL) + return BadAlloc; + wire+= 2*XkbKeyNameLength; + } + return Success; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetGeometry(ClientPtr client) +#else +ProcXkbSetGeometry(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbGeometryPtr geom,old; + XkbGeometrySizesRec sizes; + Status status; + XkbDescPtr xkb; + Bool new_name; + xkbNewKeyboardNotify nkn; + + REQUEST(xkbSetGeometryReq); + REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_OR_NONE(stuff->name); + + xkb= dev->key->xkbInfo->desc; + old= xkb->geom; + xkb->geom= NULL; + + sizes.which= XkbGeomAllMask; + sizes.num_properties= stuff->nProperties; + sizes.num_colors= stuff->nColors; + sizes.num_shapes= stuff->nShapes; + sizes.num_sections= stuff->nSections; + sizes.num_doodads= stuff->nDoodads; + sizes.num_key_aliases= stuff->nKeyAliases; + if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) { + xkb->geom= old; + return status; + } + geom= xkb->geom; + geom->name= stuff->name; + geom->width_mm= stuff->widthMM; + geom->height_mm= stuff->heightMM; + if ((status= _CheckSetGeom(geom,stuff,client))!=Success) { + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= old; + return status; + } + new_name= (xkb->names->geometry!=geom->name); + xkb->names->geometry= geom->name; + if (old) + XkbFreeGeometry(old,XkbGeomAllMask,True); + if (new_name) { + xkbNamesNotify nn; + bzero(&nn,sizeof(xkbNamesNotify)); + nn.changed= XkbGeometryNameMask; + XkbSendNamesNotify(dev,&nn); + } + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code; + nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbSetGeometry; + nkn.changed= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + return Success; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbPerClientFlags(ClientPtr client) +#else +ProcXkbPerClientFlags(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbPerClientFlagsReply rep; + XkbInterestPtr interest; + + REQUEST(xkbPerClientFlagsReq); + REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask); + CHK_MASK_MATCH(0x02,stuff->change,stuff->value); + + interest = XkbFindClientResource((DevicePtr)dev,client); + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (stuff->change) { + client->xkbClientFlags&= ~stuff->change; + client->xkbClientFlags|= stuff->value; + } + if (stuff->change&XkbPCF_AutoResetControlsMask) { + Bool want; + want= stuff->value&XkbPCF_AutoResetControlsMask; + if (interest && !want) { + interest->autoCtrls= interest->autoCtrlValues= 0; + } + else if (want && (!interest)) { + XID id = FakeClientID(client->index); + AddResource(id,RT_XKBCLIENT,dev); + interest= XkbAddClientResource((DevicePtr)dev,client,id); + if (!interest) + return BadAlloc; + } + if (interest && want ) { + register unsigned affect; + affect= stuff->ctrlsToChange; + + CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls); + CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues); + + interest->autoCtrls&= ~affect; + interest->autoCtrlValues&= ~affect; + interest->autoCtrls|= stuff->autoCtrls&affect; + interest->autoCtrlValues|= stuff->autoCtrlValues&affect; + } + } + rep.supported = XkbPCF_AllFlagsMask; + rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask; + if (interest) { + rep.autoCtrls= interest->autoCtrls; + rep.autoCtrlValues= interest->autoCtrlValues; + } + else { + rep.autoCtrls= rep.autoCtrlValues= 0; + } + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.supported,n); + swapl(&rep.value,n); + swapl(&rep.autoCtrls,n); + swapl(&rep.autoCtrlValues,n); + } + WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ +/* and wildcards */ +static unsigned char componentSpecLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +/* same as above but accepts percent, plus and bar too */ +static unsigned char componentExprLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +static char * +#if NeedFunctionPrototypes +GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn) +#else +GetComponentSpec(pWire,allowExpr,errRtrn) + unsigned char ** pWire; + Bool allowExpr; + int * errRtrn; +#endif +{ +int len; +register int i; +unsigned char *wire,*str,*tmp,*legal; + + if (allowExpr) legal= &componentExprLegal[0]; + else legal= &componentSpecLegal[0]; + + wire= *pWire; + len= (*(unsigned char *)wire++); + if (len>0) { + str= (unsigned char *)Xcalloc(len+1); + if (str) { + tmp= str; + for (i=0;ixkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + status= Success; + str= (unsigned char *)&stuff[1]; + bzero(&list,sizeof(XkbSrvListInfoRec)); + list.maxRtrn= stuff->maxNames; + list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + if ((status=XkbDDXList(dev,&list,client))!=Success) { + if (list.pool) { + _XkbFree(list.pool); + list.pool= NULL; + } + return status; + } + bzero(&rep,sizeof(xkbListComponentsReply)); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = XkbPaddedSize(list.nPool)/4; + rep.nKeymaps = list.nFound[_XkbListKeymaps]; + rep.nKeycodes = list.nFound[_XkbListKeycodes]; + rep.nTypes = list.nFound[_XkbListTypes]; + rep.nCompatMaps = list.nFound[_XkbListCompat]; + rep.nSymbols = list.nFound[_XkbListSymbols]; + rep.nGeometries = list.nFound[_XkbListGeometry]; + rep.extra= 0; + if (list.nTotal>list.maxRtrn) + rep.extra = (list.nTotal-list.maxRtrn); + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.nKeymaps,n); + swaps(&rep.nKeycodes,n); + swaps(&rep.nTypes,n); + swaps(&rep.nCompatMaps,n); + swaps(&rep.nSymbols,n); + swaps(&rep.nGeometries,n); + swaps(&rep.extra,n); + } + WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep); + if (list.nPool && list.pool) { + WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool); + _XkbFree(list.pool); + list.pool= NULL; + } + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetKbdByName(ClientPtr client) +#else +ProcXkbGetKbdByName(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbFileInfo finfo; + xkbGetKbdByNameReply rep; + xkbGetMapReply mrep; + xkbGetCompatMapReply crep; + xkbGetIndicatorMapReply irep; + xkbGetNamesReply nrep; + xkbGetGeometryReply grep; + XkbComponentNamesRec names; + XkbDescPtr xkb; + unsigned char * str; + char mapFile[PATH_MAX]; + unsigned len; + unsigned fwant,fneed,reported; + int status; + Bool geom_changed; + + REQUEST(xkbGetKbdByNameReq); + REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb = dev->key->xkbInfo->desc; + status= Success; + str= (unsigned char *)&stuff[1]; + names.keymap= GetComponentSpec(&str,True,&status); + names.keycodes= GetComponentSpec(&str,True,&status); + names.types= GetComponentSpec(&str,True,&status); + names.compat= GetComponentSpec(&str,True,&status); + names.symbols= GetComponentSpec(&str,True,&status); + names.geometry= GetComponentSpec(&str,True,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + + CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask); + CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask); + + if (stuff->load) + fwant= XkbGBN_AllComponentsMask; + else fwant= stuff->want|stuff->need; + if (!names.keymap) { + if ((!names.compat)&& + (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) { + names.compat= _XkbDupString("%"); + } + if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) { + names.types= _XkbDupString("%"); + } + if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) { + names.symbols= _XkbDupString("%"); + } + geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0)); + if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) { + names.geometry= _XkbDupString("%"); + geom_changed= False; + } + } + else { + geom_changed= True; + } + + bzero(mapFile,PATH_MAX); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + rep.loaded= False; + fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask; + fneed= XkbConvertGetByNameComponents(True,stuff->need); + rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed); + if (stuff->load) { + fneed|= XkmKeymapRequired; + fwant|= XkmKeymapLegal; + } + if ((fwant|fneed)&XkmSymbolsMask) { + fneed|= XkmKeyNamesIndex|XkmTypesIndex; + fwant|= XkmIndicatorsIndex; + } + rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&finfo, + mapFile,PATH_MAX); + rep.newKeyboard= False; + rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0; + + stuff->want|= stuff->need; + if (finfo.xkb==NULL) + rep.reported= 0; + else { + if (stuff->load) + rep.loaded= True; + if (stuff->load || + ((rep.reported&XkbGBN_SymbolsMask) && (finfo.xkb->compat))) { + XkbChangesRec changes; + bzero(&changes,sizeof(changes)); + XkbUpdateDescActions(finfo.xkb, + finfo.xkb->min_key_code,XkbNumKeys(finfo.xkb), + &changes); + } + + if (finfo.xkb->map==NULL) + rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask); + else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) { + mrep.type= X_Reply; + mrep.deviceID = dev->id; + mrep.sequenceNumber= client->sequence; + mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2); + mrep.minKeyCode = finfo.xkb->min_key_code; + mrep.maxKeyCode = finfo.xkb->max_key_code; + mrep.present = 0; + mrep.totalSyms = mrep.totalActs = + mrep.totalKeyBehaviors= mrep.totalKeyExplicit= + mrep.totalModMapKeys= 0; + if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) { + mrep.present|= XkbKeyTypesMask; + mrep.firstType = 0; + mrep.nTypes = mrep.totalTypes= finfo.xkb->map->num_types; + } + else { + mrep.firstType = mrep.nTypes= 0; + mrep.totalTypes= 0; + } + if (rep.reported&XkbGBN_ClientSymbolsMask) { + mrep.present|= (XkbKeySymsMask|XkbModifierMapMask); + mrep.firstKeySym = mrep.firstModMapKey= finfo.xkb->min_key_code; + mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(finfo.xkb); + } + else { + mrep.firstKeySym= mrep.firstModMapKey= 0; + mrep.nKeySyms= mrep.nModMapKeys= 0; + } + if (rep.reported&XkbGBN_ServerSymbolsMask) { + mrep.present|= XkbAllServerInfoMask; + mrep.virtualMods= ~0; + mrep.firstKeyAct = mrep.firstKeyBehavior = + mrep.firstKeyExplicit = finfo.xkb->min_key_code; + mrep.nKeyActs = mrep.nKeyBehaviors = + mrep.nKeyExplicit = XkbNumKeys(finfo.xkb); + } + else { + mrep.virtualMods= 0; + mrep.firstKeyAct= mrep.firstKeyBehavior= + mrep.firstKeyExplicit = 0; + mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0; + } + XkbComputeGetMapReplySize(finfo.xkb,&mrep); + rep.length+= SIZEOF(xGenericReply)/4+mrep.length; + } + if (finfo.xkb->compat==NULL) + rep.reported&= ~XkbGBN_CompatMapMask; + else if (rep.reported&XkbGBN_CompatMapMask) { + crep.type= X_Reply; + crep.deviceID= dev->id; + crep.sequenceNumber= client->sequence; + crep.length= 0; + crep.groups= XkbAllGroupsMask; + crep.firstSI= 0; + crep.nSI= crep.nTotalSI= finfo.xkb->compat->num_si; + XkbComputeGetCompatMapReplySize(finfo.xkb->compat,&crep); + rep.length+= SIZEOF(xGenericReply)/4+crep.length; + } + if (finfo.xkb->indicators==NULL) + rep.reported&= ~XkbGBN_IndicatorMapMask; + else if (rep.reported&XkbGBN_IndicatorMapMask) { + irep.type= X_Reply; + irep.deviceID= dev->id; + irep.sequenceNumber= client->sequence; + irep.length= 0; + irep.which= XkbAllIndicatorsMask; + XkbComputeGetIndicatorMapReplySize(finfo.xkb->indicators,&irep); + rep.length+= SIZEOF(xGenericReply)/4+irep.length; + } + if (finfo.xkb->names==NULL) + rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask); + else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) { + nrep.type= X_Reply; + nrep.deviceID= dev->id; + nrep.sequenceNumber= client->sequence; + nrep.length= 0; + nrep.minKeyCode= finfo.xkb->min_key_code; + nrep.maxKeyCode= finfo.xkb->max_key_code; + if (rep.reported&XkbGBN_OtherNamesMask) { + nrep.which= XkbAllNamesMask; + if (finfo.xkb->map!=NULL) + nrep.nTypes= finfo.xkb->map->num_types; + else nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= XkbAllGroupsMask; + nrep.virtualMods= XkbAllVirtualModsMask; + nrep.indicators= XkbAllIndicatorsMask; + nrep.nRadioGroups= finfo.xkb->names->num_rg; + } + else { + nrep.which= 0; + nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= 0; + nrep.virtualMods= 0; + nrep.indicators= 0; + nrep.nRadioGroups= 0; + } + if (rep.reported&XkbGBN_KeyNamesMask) { + nrep.which|= XkbKeyNamesMask; + nrep.firstKey= finfo.xkb->min_key_code; + nrep.nKeys= XkbNumKeys(finfo.xkb); + nrep.nKeyAliases= finfo.xkb->names->num_key_aliases; + if (nrep.nKeyAliases) + nrep.which|= XkbKeyAliasesMask; + } + else { + nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask); + nrep.firstKey= nrep.nKeys= 0; + nrep.nKeyAliases= 0; + } + XkbComputeGetNamesReplySize(finfo.xkb,&nrep); + rep.length+= SIZEOF(xGenericReply)/4+nrep.length; + } + if (finfo.xkb->geom==NULL) + rep.reported&= ~XkbGBN_GeometryMask; + else if (rep.reported&XkbGBN_GeometryMask) { + grep.type= X_Reply; + grep.deviceID= dev->id; + grep.sequenceNumber= client->sequence; + grep.length= 0; + grep.found= True; + grep.pad= 0; + grep.widthMM= grep.heightMM= 0; + grep.nProperties= grep.nColors= grep.nShapes= 0; + grep.nSections= grep.nDoodads= 0; + grep.baseColorNdx= grep.labelColorNdx= 0; + XkbComputeGetGeometryReplySize(finfo.xkb->geom,&grep,None); + rep.length+= SIZEOF(xGenericReply)/4+grep.length; + } + } + + reported= rep.reported; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.found,n); + swaps(&rep.reported,n); + } + WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep); + if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) + XkbSendMap(client,finfo.xkb,&mrep); + if (reported&XkbGBN_CompatMapMask) + XkbSendCompatMap(client,finfo.xkb->compat,&crep); + if (reported&XkbGBN_IndicatorMapMask) + XkbSendIndicatorMap(client,finfo.xkb->indicators,&irep); + if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask)) + XkbSendNames(client,finfo.xkb,&nrep); + if (reported&XkbGBN_GeometryMask) + XkbSendGeometry(client,finfo.xkb->geom,&grep,False); + if (rep.loaded) { + XkbDescPtr old_xkb; + xkbNewKeyboardNotify nkn; + int i,nG,nTG; + old_xkb= xkb; + xkb= finfo.xkb; + dev->key->xkbInfo->desc= xkb; + finfo.xkb= old_xkb; /* so it'll get freed automatically */ + + if (dev->kbdfeed && dev->kbdfeed->xkb_sli) { + XkbFreeSrvLedInfo(dev->kbdfeed->xkb_sli); + dev->kbdfeed->xkb_sli= NULL; + } + *xkb->ctrls= *old_xkb->ctrls; + for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + nG= XkbKeyNumGroups(xkb,i); + if (nG>=XkbNumKbdGroups) { + nTG= XkbNumKbdGroups; + break; + } + if (nG>nTG) { + nTG= nG; + } + } + xkb->ctrls->num_groups= nTG; + + memcpy(dev->key->modifierMap,xkb->map->modmap,xkb->max_key_code+1); + XkbUpdateCoreDescription(dev,True); + + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= finfo.xkb->min_key_code; + nkn.maxKeyCode= finfo.xkb->max_key_code; + nkn.oldMinKeyCode= xkb->min_key_code; + nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbGetKbdByName; + nkn.changed= XkbNKN_KeycodesMask; + if (geom_changed) + nkn.changed|= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + } + if ((finfo.xkb!=NULL)&&(finfo.xkb!=xkb)) { + XkbFreeKeyboard(finfo.xkb,XkbAllComponentsMask,True); + finfo.xkb= NULL; + } + if (names.keymap) { Xfree(names.keymap); names.keymap= NULL; } + if (names.keycodes) { Xfree(names.keycodes); names.keycodes= NULL; } + if (names.types) { Xfree(names.types); names.types= NULL; } + if (names.compat) { Xfree(names.compat); names.compat= NULL; } + if (names.symbols) { Xfree(names.symbols); names.symbols= NULL; } + if (names.geometry) { Xfree(names.geometry); names.geometry= NULL; } + return client->noClientException; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ComputeDeviceLedInfoSize( DeviceIntPtr dev, + unsigned int what, + XkbSrvLedInfoPtr sli) +#else +ComputeDeviceLedInfoSize(dev,what,sli) + DeviceIntPtr dev; + unsigned int what; + XkbSrvLedInfoPtr sli; +#endif +{ +int nNames,nMaps; +register unsigned n,bit; + + if (sli==NULL) + return 0; + nNames= nMaps= 0; + if ((what&XkbXI_IndicatorNamesMask)==0) + sli->namesPresent= 0; + if ((what&XkbXI_IndicatorMapsMask)==0) + sli->mapsPresent= 0; + + for (n=0,bit=1;nnames && sli->names[n]!=None) { + sli->namesPresent|= bit; + nNames++; + } + if (sli->maps && XkbIM_InUse(&sli->maps[n])) { + sli->mapsPresent|= bit; + nMaps++; + } + } + return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc)); +} + +static int +#if NeedFunctionPrototypes +CheckDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + xkbGetDeviceInfoReply * rep, + ClientPtr client) +#else +CheckDeviceLedFBs(dev,class,id,rep,client) + DeviceIntPtr dev; + int class; + int id; + xkbGetDeviceInfoReply * rep; + ClientPtr client; +#endif +{ +int nFBs= 0; +int length= 0; +Bool classOk; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + else { + client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; + } + } + classOk= False; + if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + classOk= True; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!kf->xkb_sli) + kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + classOk= True; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!lf->xkb_sli) + lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if (nFBs>0) { + if (rep->supported&XkbXI_IndicatorsMask) { + rep->nDeviceLedFBs= nFBs; + rep->length+= (length/4); + } + return Success; + } + if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id); + else client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; +} + +static int +#if NeedFunctionPrototypes +SendDeviceLedInfo( XkbSrvLedInfoPtr sli, + ClientPtr client) +#else +SendDeviceLedInfo(sli,client) + XkbSrvLedInfoPtr sli; + ClientPtr client; +#endif +{ +xkbDeviceLedsWireDesc wire; +int length; + + length= 0; + wire.ledClass= sli->class; + wire.ledID= sli->id; + wire.namesPresent= sli->namesPresent; + wire.mapsPresent= sli->mapsPresent; + wire.physIndicators= sli->physIndicators; + wire.state= sli->effectiveState; + if (client->swapped) { + register int n; + swaps(&wire.ledClass,n); + swaps(&wire.ledID,n); + swapl(&wire.namesPresent,n); + swapl(&wire.mapsPresent,n); + swapl(&wire.physIndicators,n); + swapl(&wire.state,n); + } + WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire); + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (sli->namesPresent|sli->mapsPresent) { + register unsigned i,bit; + if (sli->namesPresent) { + CARD32 awire; + for (i=0,bit=1;inamesPresent&bit) { + awire= (CARD32)sli->names[i]; + if (client->swapped) { + register int n; + swapl(&awire,n); + } + WriteToClient(client,4,(char *)&awire); + length+= 4; + } + } + } + if (sli->mapsPresent) { + for (i=0,bit=1;imapsPresent&bit) { + iwire.flags= sli->maps[i].flags; + iwire.whichGroups= sli->maps[i].which_groups; + iwire.groups= sli->maps[i].groups; + iwire.whichMods= sli->maps[i].which_mods; + iwire.mods= sli->maps[i].mods.mask; + iwire.realMods= sli->maps[i].mods.real_mods; + iwire.virtualMods= sli->maps[i].mods.vmods; + iwire.ctrls= sli->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&iwire.virtualMods,n); + swapl(&iwire.ctrls,n); + } + WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc), + (char *)&iwire); + length+= SIZEOF(xkbIndicatorMapWireDesc); + } + } + } + } + return length; +} + +static int +#if NeedFunctionPrototypes +SendDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + unsigned wantLength, + ClientPtr client) +#else +SendDeviceLedFBs(dev,class,id,wantLength,client) + DeviceIntPtr dev; + int class; + int id; + unsigned wantLength; + ClientPtr client; +#endif +{ +int length= 0; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + } + if ((dev->kbdfeed)&& + ((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) { + length+= SendDeviceLedInfo(kf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if ((dev->leds)&& + ((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) { + length+= SendDeviceLedInfo(lf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if (length==wantLength) + return Success; + else return BadLength; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetDeviceInfo(ClientPtr client) +#else +ProcXkbGetDeviceInfo(client) + ClientPtr client; +#endif +{ +DeviceIntPtr dev; +xkbGetDeviceInfoReply rep; +int status,nDeviceLedFBs; +unsigned length,nameLen; +CARD16 ledClass,ledID; +unsigned wanted,supported; +char * str; + + REQUEST(xkbGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + wanted= stuff->wanted; + + CHK_ANY_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask); + + if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns))) + wanted&= ~XkbXI_ButtonActionsMask; + if ((!dev->kbdfeed)&&(!dev->leds)) + wanted&= ~XkbXI_IndicatorsMask; + wanted&= ~XkbXIUnsupported; + + nameLen= XkbSizeCountedString(dev->name); + bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply)); + rep.type = X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber = client->sequence; + rep.length = nameLen/4; + rep.present = wanted; + rep.supported = XkbXI_AllDeviceFeaturesMask&(~XkbXIUnsupported); + rep.unsupported = XkbXIUnsupported; + rep.firstBtnWanted = rep.nBtnsWanted = 0; + rep.firstBtnRtrn = rep.nBtnsRtrn = 0; + if (dev->button) + rep.totalBtns= dev->button->numButtons; + else rep.totalBtns= 0; + rep.devType= dev->type; + rep.hasOwnState= (dev->key && dev->key->xkbInfo); + rep.nDeviceLedFBs = 0; + if (dev->kbdfeed) rep.dfltKbdFB= dev->kbdfeed->ctrl.id; + else rep.dfltKbdFB= XkbXINone; + if (dev->leds) rep.dfltLedFB= dev->leds->ctrl.id; + else rep.dfltLedFB= XkbXINone; + + ledClass= stuff->ledClass; + ledID= stuff->ledID; + + rep.firstBtnWanted= rep.nBtnsWanted= 0; + rep.firstBtnRtrn= rep.nBtnsRtrn= 0; + if (wanted&XkbXI_ButtonActionsMask) { + if (stuff->allBtns) { + stuff->firstBtn= 0; + stuff->nBtns= dev->button->numButtons; + } + + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons, + stuff->firstBtn, + stuff->nBtns); + return BadValue; + } + else { + rep.firstBtnWanted= stuff->firstBtn; + rep.nBtnsWanted= stuff->nBtns; + if (dev->button->xkb_acts!=NULL) { + XkbAction *act; + register int i; + + rep.firstBtnRtrn= stuff->firstBtn; + rep.nBtnsRtrn= stuff->nBtns; + act= &dev->button->xkb_acts[rep.firstBtnWanted]; + for (i=0;itype!=XkbSA_NoAction) + break; + } + rep.firstBtnRtrn+= i; + rep.nBtnsRtrn-= i; + act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1]; + for (i=0;itype!=XkbSA_NoAction) + break; + } + rep.nBtnsRtrn-= i; + } + rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4; + } + } + + if (wanted&XkbXI_IndicatorsMask) { + status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client); + if (status!=Success) + return status; + } + length= rep.length*4; + supported= rep.supported; + nDeviceLedFBs = rep.nDeviceLedFBs; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.present,n); + swaps(&rep.supported,n); + swaps(&rep.unsupported,n); + swaps(&rep.nDeviceLedFBs,n); + swapl(&rep.type,n); + } + WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep); + + str= (char*) ALLOCATE_LOCAL(nameLen); + if (!str) + return BadAlloc; + XkbWriteCountedString(str,dev->name,client->swapped); + WriteToClient(client,nameLen,str); + DEALLOCATE_LOCAL(str); + length-= nameLen; + + if (rep.nBtnsRtrn>0) { + int sz; + xkbActionWireDesc * awire; + sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc); + awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn]; + WriteToClient(client,sz,(char *)awire); + length-= sz; + } + if (nDeviceLedFBs>0) { + status= SendDeviceLedFBs(dev,ledClass,ledID,length,client); + if (status!=Success) + return status; + } + else if (length!=0) { +#ifdef DEBUG + ErrorF("Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); + ErrorF(" Wrote %d fewer bytes than expected\n",length); +#endif + return BadLength; + } + if (stuff->wanted&(~supported)) { + xkbExtensionDeviceNotify ed; + bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify)); + ed.ledClass= ledClass; + ed.ledID= ledID; + ed.ledsDefined= 0; + ed.ledState= 0; + ed.firstBtn= ed.nBtns= 0; + ed.reason= XkbXI_UnsupportedFeatureMask; + ed.supported= supported; + ed.unsupported= stuff->wanted&(~supported); + XkbSendExtensionDeviceNotify(dev,client,&ed); + } + return client->noClientException; +} + +static char * +#if NeedFunctionPrototypes +CheckSetDeviceIndicators( char * wire, + DeviceIntPtr dev, + int num, + int * status_rtrn, + ClientPtr client) +#else +CheckSetDeviceIndicators(wire,dev,num,status_rtrn,client) + char * wire; + DeviceIntPtr dev; + int num; + int * status_rtrn; + ClientPtr client; +#endif +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbSrvLedInfoPtr sli; + + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;iswapped) { + register int n; + swaps(&ledWire->ledClass,n); + swaps(&ledWire->ledID,n); + swapl(&ledWire->namesPresent,n); + swapl(&ledWire->mapsPresent,n); + swapl(&ledWire->physIndicators,n); + } + + sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID, + XkbXI_IndicatorsMask); + if (sli!=NULL) { + register int n; + register unsigned bit; + int nMaps,nNames; + CARD32 *atomWire; + xkbIndicatorMapWireDesc *mapWire; + + nMaps= nNames= 0; + for (n=0,bit=1;nnamesPresent&bit) + nNames++; + if (ledWire->mapsPresent&bit) + nMaps++; + } + atomWire= (CARD32 *)&ledWire[1]; + if (nNames>0) { + for (n=0;nswapped) { + register int t; + swapl(atomWire,t); + } + CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue, + *status_rtrn,NULL); + atomWire++; + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (nMaps>0) { + for (n=0;nswapped) { + register int t; + swaps(&mapWire->virtualMods,t); + swapl(&mapWire->ctrls,t); + } + CHK_MASK_LEGAL3(0x21,mapWire->whichGroups, + XkbIM_UseAnyGroup, + client->errorValue, + *status_rtrn,NULL); + CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods, + client->errorValue, + *status_rtrn,NULL); + mapWire++; + } + } + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + else { + /* SHOULD NEVER HAPPEN */ + return (char *)ledWire; + } + } + return (char *)ledWire; +} + +static char * +#if NeedFunctionPrototypes +SetDeviceIndicators( char * wire, + DeviceIntPtr dev, + unsigned changed, + int num, + int * status_rtrn, + ClientPtr client, + xkbExtensionDeviceNotify *ev) +#else +SetDeviceIndicators(wire,dev,changed,num,status_rtrn,client,ev) + char * wire; + DeviceIntPtr dev; + unsigned changed; + int num; + ClientPtr client; + int * status_rtrn; + xkbExtensionDeviceNotify *ev; +#endif +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbEventCauseRec cause; +unsigned namec,mapc,statec; +xkbExtensionDeviceNotify ed; +XkbChangesRec changes; +DeviceIntPtr kbd; + + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + bzero((char *)&changes,sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client); + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;iledClass,ledWire->ledID, + XkbXI_IndicatorMapsMask); + if (!sli) { + /* SHOULD NEVER HAPPEN!! */ + return (char *)ledWire; + } + + atomWire= (CARD32 *)&ledWire[1]; + if (changed&XkbXI_IndicatorNamesMask) { + namec= sli->namesPresent|ledWire->namesPresent; + bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom)); + } + if (ledWire->namesPresent) { + sli->namesPresent= ledWire->namesPresent; + bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom)); + for (n=0,bit=1;nnamesPresent&bit) { + sli->names[n]= (Atom)*atomWire; + if (sli->names[n]==None) + ledWire->namesPresent&= ~bit; + atomWire++; + } + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (changed&XkbXI_IndicatorMapsMask) { + mapc= sli->mapsPresent|ledWire->mapsPresent; + sli->mapsPresent= ledWire->mapsPresent; + bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec)); + } + if (ledWire->mapsPresent) { + for (n=0,bit=1;nmapsPresent&bit) { + sli->maps[n].flags= mapWire->flags; + sli->maps[n].which_groups= mapWire->whichGroups; + sli->maps[n].groups= mapWire->groups; + sli->maps[n].which_mods= mapWire->whichMods; + sli->maps[n].mods.mask= mapWire->mods; + sli->maps[n].mods.real_mods=mapWire->realMods; + sli->maps[n].mods.vmods= mapWire->virtualMods; + sli->maps[n].ctrls= mapWire->ctrls; + mapWire++; + } + } + } + if (changed&XkbXI_IndicatorStateMask) { + statec= sli->effectiveState^ledWire->state; + sli->explicitState&= ~statec; + sli->explicitState|= (ledWire->state&statec); + } + if (namec) + XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) + XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) + XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + + kbd= dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) + kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + return (char *)ledWire; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetDeviceInfo(ClientPtr client) +#else +ProcXkbSetDeviceInfo(client) + ClientPtr client; +#endif +{ +DeviceIntPtr dev; +unsigned change; +char * wire; +xkbExtensionDeviceNotify ed; + + REQUEST(xkbSetDeviceInfoReq); + REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + change= stuff->change; + + CHK_ANY_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,change,(XkbXI_AllFeaturesMask&(~XkbXI_KeyboardsMask))); + + wire= (char *)&stuff[1]; + if (change&XkbXI_ButtonActionsMask) { + if (!dev->button) { + client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass); + return XkbKeyboardErrorCode; + } + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns, + dev->button->numButtons); + return BadMatch; + } + wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc)); + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs, + &status,client); + if (status!=Success) + return status; + } + if (((wire-((char *)stuff))/4)!=stuff->length) + return BadLength; + + bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify)); + ed.deviceID= dev->id; + wire= (char *)&stuff[1]; + if (change&XkbXI_ButtonActionsMask) { + int nBtns,sz,i; + XkbAction * acts; + DeviceIntPtr kbd; + + nBtns= dev->button->numButtons; + acts= dev->button->xkb_acts; + if (acts==NULL) { + acts= _XkbTypedCalloc(nBtns,XkbAction); + if (!acts) + return BadAlloc; + dev->button->xkb_acts= acts; + } + sz= stuff->nBtns*SIZEOF(xkbActionWireDesc); + memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz); + wire+= sz; + ed.reason|= XkbXI_ButtonActionsMask; + ed.firstBtn= stuff->firstBtn; + ed.nBtns= stuff->nBtns; + + if (dev->key) kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + acts= &dev->button->xkb_acts[stuff->firstBtn]; + for (i=0;inBtns;i++,acts++) { + if (acts->type!=XkbSA_NoAction) + XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0); + } + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= SetDeviceIndicators(wire,dev,change,stuff->nDeviceLedFBs, + &status,client,&ed); + if (status!=Success) + return status; + } + if ((stuff->change)&&(ed.reason)) + XkbSendExtensionDeviceNotify(dev,client,&ed); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbSetDebuggingFlags(ClientPtr client) +#else +ProcXkbSetDebuggingFlags(client) + ClientPtr client; +#endif +{ +CARD32 newFlags,newCtrls,extraLength; +xkbSetDebuggingFlagsReply rep; + + REQUEST(xkbSetDebuggingFlagsReq); + REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); + + newFlags= xkbDebugFlags&(~stuff->affectFlags); + newFlags|= (stuff->flags&stuff->affectFlags); + newCtrls= xkbDebugCtrls&(~stuff->affectCtrls); + newCtrls|= (stuff->ctrls&stuff->affectCtrls); + if (xkbDebugFlags || newFlags || stuff->msgLength) { + ErrorF("XkbDebug: Setting debug flags to 0x%x\n",newFlags); + if (newCtrls!=xkbDebugCtrls) + ErrorF("XkbDebug: Setting debug controls to 0x%x\n",newCtrls); + } + extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq; + if (stuff->msgLength>0) { + char *msg; + if (extraLengthmsgLength)) { + ErrorF("XkbDebug: msgLength= %d, length= %d (should be %d)\n", + stuff->msgLength,extraLength, + XkbPaddedSize(stuff->msgLength)); + return BadLength; + } + msg= (char *)&stuff[1]; + if (msg[stuff->msgLength-1]!='\0') { + ErrorF("XkbDebug: message not null-terminated\n"); + return BadValue; + } + ErrorF("XkbDebug: %s\n",msg); + } + xkbDebugFlags = newFlags; + xkbDebugCtrls = newCtrls; + + XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks); + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.currentFlags = newFlags; + rep.currentCtrls = newCtrls; + rep.supportedFlags = ~0; + rep.supportedCtrls = ~0; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.currentFlags, n); + swapl(&rep.currentCtrls, n); + swapl(&rep.supportedFlags, n); + swapl(&rep.supportedCtrls, n); + } + WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ProcXkbDispatch (ClientPtr client) +#else +ProcXkbDispatch (client) + ClientPtr client; +#endif +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_kbUseExtension: + return ProcXkbUseExtension(client); + case X_kbSelectEvents: + return ProcXkbSelectEvents(client); + case X_kbBell: + return ProcXkbBell(client); + case X_kbGetState: + return ProcXkbGetState(client); + case X_kbLatchLockState: + return ProcXkbLatchLockState(client); + case X_kbGetControls: + return ProcXkbGetControls(client); + case X_kbSetControls: + return ProcXkbSetControls(client); + case X_kbGetMap: + return ProcXkbGetMap(client); + case X_kbSetMap: + return ProcXkbSetMap(client); + case X_kbGetCompatMap: + return ProcXkbGetCompatMap(client); + case X_kbSetCompatMap: + return ProcXkbSetCompatMap(client); + case X_kbGetIndicatorState: + return ProcXkbGetIndicatorState(client); + case X_kbGetIndicatorMap: + return ProcXkbGetIndicatorMap(client); + case X_kbSetIndicatorMap: + return ProcXkbSetIndicatorMap(client); + case X_kbGetNamedIndicator: + return ProcXkbGetNamedIndicator(client); + case X_kbSetNamedIndicator: + return ProcXkbSetNamedIndicator(client); + case X_kbGetNames: + return ProcXkbGetNames(client); + case X_kbSetNames: + return ProcXkbSetNames(client); + case X_kbGetGeometry: + return ProcXkbGetGeometry(client); + case X_kbSetGeometry: + return ProcXkbSetGeometry(client); + case X_kbPerClientFlags: + return ProcXkbPerClientFlags(client); + case X_kbListComponents: + return ProcXkbListComponents(client); + case X_kbGetKbdByName: + return ProcXkbGetKbdByName(client); + case X_kbGetDeviceInfo: + return ProcXkbGetDeviceInfo(client); + case X_kbSetDeviceInfo: + return ProcXkbSetDeviceInfo(client); + case X_kbSetDebuggingFlags: + return ProcXkbSetDebuggingFlags(client); + default: + return BadRequest; + } +} + +static int +#if NeedFunctionPrototypes +XkbClientGone(pointer data,XID id) +#else +XkbClientGone(data,id) + pointer data; + XID id; +#endif +{ + DevicePtr pXDev = (DevicePtr)data; + + if (!XkbRemoveResourceClient(pXDev,id)) { + ErrorF("Internal Error! bad RemoveResourceClient in XkbClientGone\n"); + } + return 1; +} + +/*ARGSUSED*/ +static void +#if NeedFunctionPrototypes +XkbResetProc(ExtensionEntry *extEntry) +#else +XkbResetProc(extEntry) + ExtensionEntry *extEntry; +#endif +{ +} + +void +#if NeedFunctionPrototypes +XkbExtensionInit(void) +#else +XkbExtensionInit() +#endif +{ + ExtensionEntry *extEntry; + + if (extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, + ProcXkbDispatch, SProcXkbDispatch, + XkbResetProc, StandardMinorOpcode)) { + XkbReqCode = (unsigned char)extEntry->base; + XkbEventBase = (unsigned char)extEntry->eventBase; + XkbErrorBase = (unsigned char)extEntry->errorBase; + XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard; + RT_XKBCLIENT = CreateNewResourceType(XkbClientGone); + } + return; +} + + diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c new file mode 100644 index 000000000..7596d068b --- /dev/null +++ b/xkb/xkbAccessX.c @@ -0,0 +1,856 @@ +/* $Xorg: xkbAccessX.c,v 1.4 2001/02/05 18:50:20 coskrey Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "inputstr.h" +#include "XKBsrv.h" +#ifndef WIN32 +#include +#endif + +int XkbDfltRepeatDelay= 660; +int XkbDfltRepeatInterval= 40; +pointer XkbLastRepeatEvent= NULL; + +#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask) +#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask) + +unsigned short XkbDfltAccessXTimeout= 120; +unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS; +unsigned int XkbDfltAccessXTimeoutValues= 0; +unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS; +unsigned int XkbDfltAccessXTimeoutOptionsValues= 0; +unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask; +unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask); + +void +#if NeedFunctionPrototypes +AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls) +#else +AccessXComputeCurveFactor(xkbi,ctrls) + XkbSrvInfoPtr xkbi; + XkbControlsPtr ctrls; +#endif +{ + xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001); + xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/ + pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve)); + return; +} + +void +#if NeedFunctionPrototypes +AccessXInit(DeviceIntPtr keybd) +#else +AccessXInit(keybd) + DeviceIntPtr keybd; +#endif +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; + + xkbi->shiftKeyCount= 0; + xkbi->mouseKeysCounter= 0; + xkbi->inactiveKey= 0; + xkbi->slowKey= 0; + xkbi->repeatKey= 0; + xkbi->krgTimerActive= _OFF_TIMER; + xkbi->beepType= _BEEP_NONE; + xkbi->beepCount= 0; + xkbi->mouseKeyTimer= NULL; + xkbi->slowKeysTimer= NULL; + xkbi->bounceKeysTimer= NULL; + xkbi->repeatKeyTimer= NULL; + xkbi->krgTimer= NULL; + xkbi->beepTimer= NULL; + ctrls->repeat_delay = XkbDfltRepeatDelay; + ctrls->repeat_interval = XkbDfltRepeatInterval; + ctrls->debounce_delay = 300; + ctrls->slow_keys_delay = 300; + ctrls->mk_delay = 160; + ctrls->mk_interval = 40; + ctrls->mk_time_to_max = 30; + ctrls->mk_max_speed = 30; + ctrls->mk_curve = 500; + ctrls->mk_dflt_btn = 1; + ctrls->ax_timeout = XkbDfltAccessXTimeout; + ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask; + ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues; + ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask; + ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues; + if (XkbDfltAccessXTimeout) + ctrls->enabled_ctrls |= XkbAccessXTimeoutMask; + else + ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask; + ctrls->enabled_ctrls |= XkbDfltAccessXFeedback; + ctrls->ax_options = XkbDfltAccessXOptions; + AccessXComputeCurveFactor(xkbi,ctrls); + return; +} + +/************************************************************************/ +/* */ +/* AccessXKeyboardEvent */ +/* */ +/* Generate a synthetic keyboard event. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXKeyboardEvent(DeviceIntPtr keybd, + BYTE type, + BYTE keyCode, + Bool isRepeat) +#else +AccessXKeyboardEvent(keybd,type,keyCode,isRepeat) + DeviceIntPtr keybd; + BYTE type; + BYTE keyCode; + Bool isRepeat; +#endif +{ +xEvent xE; +#ifdef XINPUT +extern int DeviceKeyPress; +#endif + + xE.u.u.type = type; + xE.u.u.detail = keyCode; + xE.u.keyButtonPointer.time = GetTimeInMillis(); +#ifdef DEBUG + if (xkbDebugFlags&0x8) { + ErrorF("AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up")); + } +#endif + + if (_XkbIsPressEvent(type)) + XkbDDXKeyClick(keybd,keyCode,TRUE); + else if (isRepeat) + XkbLastRepeatEvent= (pointer)&xE; + XkbProcessKeyboardEvent(&xE,keybd,1L); + XkbLastRepeatEvent= NULL; + return; + +} /* AccessXKeyboardEvent */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOn */ +/* */ +/* Turn the keyboard response group on. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN) +#else +AccessXKRGTurnOn(dev,KRGControl,pCN) + DeviceIntPtr dev; + CARD16 KRGControl; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old= *ctrls; + ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask); + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl); + return; + +} /* AccessXKRGTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOff */ +/* */ +/* Turn the keyboard response group off. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +#else +AccessXKRGTurnOff(dev,pCN) + DeviceIntPtr dev; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbAX_KRGMask; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls; + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes); + } + return; + +} /* AccessXKRGTurnOff */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOn */ +/* */ +/* Turn StickyKeys on. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN) +#else +AccessXStickyKeysTurnOn(dev,pCN) + DeviceIntPtr dev; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls |= XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask); + } + return; + +} /* AccessXStickyKeysTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOff */ +/* */ +/* Turn StickyKeys off. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +#else +AccessXStickyKeysTurnOff(dev,pCN) + DeviceIntPtr dev; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask); + } +#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF + XkbClearAllLatchesAndLocks(dev,xkbi,False,&cause); +#endif + return; +} /* AccessXStickyKeysTurnOff */ + +static CARD32 +#if NeedFunctionPrototypes +AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXKRGExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; +xkbControlsNotify cn; + + if (xkbi->krgTimerActive==_KRG_WARN_TIMER) { + XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask); + xkbi->krgTimerActive= _KRG_TIMER; + return 4000; + } + xkbi->krgTimerActive= _OFF_TIMER; + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask) + AccessXKRGTurnOff((DeviceIntPtr)arg,&cn); + else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn); + return 0; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXRepeatKeyExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; +KeyCode key; + + if (xkbi->repeatKey==0) + return 0; + key= xkbi->repeatKey; + AccessXKeyboardEvent((DeviceIntPtr)arg,KeyRelease,key,True); + AccessXKeyboardEvent((DeviceIntPtr)arg,KeyPress,key,True); + return xkbi->desc->ctrls->repeat_interval; +} + +void +#if NeedFunctionPrototypes +AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key) +#else +AccessXCancelRepeatKey(xkbi,key) + XkbSrvInfoPtr xkbi; + KeyCode key; +#endif +{ + if (xkbi->repeatKey==key) + xkbi->repeatKey= 0; + return; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXSlowKeyExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +DeviceIntPtr keybd; +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +XkbControlsPtr ctrls; + + keybd= (DeviceIntPtr)arg; + xkbi= keybd->key->xkbInfo; + xkb= xkbi->desc; + ctrls= xkb->ctrls; + if (xkbi->slowKey!=0) { + xkbAccessXNotify ev; + KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey); + ev.detail= XkbAXN_SKAccept; + ev.keycode= xkbi->slowKey; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask); + AccessXKeyboardEvent(keybd,KeyPress,xkbi->slowKey,False); + /* check for magic sequences */ + if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) && + ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L))) + xkbi->shiftKeyCount++; + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (keybd->kbdfeed->ctrl.autoRepeat && + ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) && + (ctrls->enabled_ctrls&XkbRepeatKeysMask)) { +#ifndef AIXV3 + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) +#endif + { + xkbi->repeatKey = xkbi->slowKey; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + return 0; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXBounceKeyExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; + + xkbi->inactiveKey= 0; + return 0; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXTimeoutExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)arg; +XkbSrvInfoPtr xkbi= dev->key->xkbInfo; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +XkbControlsRec old; +xkbControlsNotify cn; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + if (xkbi->lastPtrEventTime) { + unsigned timeToWait = (ctrls->ax_timeout*1000); + unsigned timeElapsed = (now-xkbi->lastPtrEventTime); + + if (timeToWait > timeElapsed) + return (timeToWait - timeElapsed); + } + old= *ctrls; + xkbi->shiftKeyCount= 0; + ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask; + ctrls->enabled_ctrls|= + (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask); + if (ctrls->axt_opts_mask) { + ctrls->ax_options&= ~ctrls->axt_opts_mask; + ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask); + } + if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,False)) { + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(dev,&cn); + } + XkbSetCauseUnknown(&cause); + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (ctrls->ax_options!=old.ax_options) { + unsigned set,cleared,bell; + set= ctrls->ax_options&(~old.ax_options); + cleared= (~ctrls->ax_options)&old.ax_options; + if (set && cleared) bell= _BEEP_FEATURE_CHANGE; + else if (set) bell= _BEEP_FEATURE_ON; + else bell= _BEEP_FEATURE_OFF; + XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask); + } + xkbi->krgTimerActive= _OFF_TIMER; + return 0; +} + + +/************************************************************************/ +/* */ +/* AccessXFilterPressEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +#if NeedFunctionPrototypes +AccessXFilterPressEvent( register xEvent * xE, + register DeviceIntPtr keybd, + int count) +#else +AccessXFilterPressEvent(xE,keybd,count) + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +#endif +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +Bool ignoreKeyEvent = FALSE; +KeyCode key = xE->u.u.detail; +KeySym * sym = XkbKeySymsPtr(xkbi->desc,key); + + if (ctrls->enabled_ctrls&XkbAccessXKeysMask) { + /* check for magic sequences */ + if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) { + xkbi->krgTimerActive = _KRG_WARN_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000, + AccessXKRGExpire, (pointer)keybd); + } + else { + xkbi->krgTimerActive = _KRG_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000, + AccessXKRGExpire, (pointer)keybd); + } + if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) { + CARD32 now= GetTimeInMillis(); + if ((now-xkbi->lastShiftEventTime)>15000) + xkbi->shiftKeyCount= 1; + else xkbi->shiftKeyCount++; + xkbi->lastShiftEventTime= now; + } + } + else { + if (xkbi->krgTimerActive) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + } + } + + /* Don't transmit the KeyPress if SlowKeys is turned on; + * The wakeup handler will synthesize one for us if the user + * has held the key long enough. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + /* If key was already pressed, ignore subsequent press events + * from the server's autorepeat + */ + if(xkbi->slowKey == key) + return TRUE; + + ev.detail= XkbAXN_SKPress; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask); + xkbi->slowKey= key; + xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer, + 0, ctrls->slow_keys_delay, + AccessXSlowKeyExpire, (pointer)keybd); + ignoreKeyEvent = TRUE; + } + + /* Don't transmit the KeyPress if BounceKeys is turned on + * and the user pressed the same key within a given time period + * from the last release. + */ + else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) && + (key == xkbi->inactiveKey)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask); + ignoreKeyEvent = TRUE; + } + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (XkbDDXUsesSoftRepeat(keybd)) { + if ((keybd->kbdfeed->ctrl.autoRepeat) && + ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))== + XkbRepeatKeysMask)) { +#ifndef AIXV3 + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) +#endif + { +#ifdef DEBUG + if (xkbDebugFlags&0x10) + ErrorF("Starting software autorepeat...\n"); +#endif + xkbi->repeatKey = key; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + + /* Check for two keys being pressed at the same time. This section + * essentially says the following: + * + * If StickyKeys is on, and a modifier is currently being held down, + * and one of the following is true: the current key is not a modifier + * or the currentKey is a modifier, but not the only modifier being + * held down, turn StickyKeys off if the TwoKeys off ctrl is set. + */ + if ((ctrls->enabled_ctrls & XkbStickyKeysMask) && + (xkbi->state.base_mods!=0) && + (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + AccessXStickyKeysTurnOff(keybd,&cn); + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(xE,keybd,count); + return ignoreKeyEvent; +} /* AccessXFilterPressEvent */ + +/************************************************************************/ +/* */ +/* AccessXFilterReleaseEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +#if NeedFunctionPrototypes +AccessXFilterReleaseEvent( register xEvent * xE, + register DeviceIntPtr keybd, + int count) +#else +AccessXFilterReleaseEvent(xE,keybd,count) + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +#endif +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +KeyCode key = xE->u.u.detail; +Bool ignoreKeyEvent = FALSE; + + /* Don't transmit the KeyRelease if BounceKeys is on and + * this is the release of a key that was ignored due to + * BounceKeys. + */ + if (ctrls->enabled_ctrls & XkbBounceKeysMask) { + if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key))) + ignoreKeyEvent = TRUE; + xkbi->inactiveKey= key; + xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0, + ctrls->debounce_delay, + AccessXBounceKeyExpire, (pointer)keybd); + } + + /* Don't transmit the KeyRelease if SlowKeys is turned on and + * the user didn't hold the key long enough. We know we passed + * the key if the down bit was set by CoreProcessKeyboadEvent. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + unsigned beep_type; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + if (BitIsOn(keybd->key->down,key) | (xkbi->mouseKey == key)) { + ev.detail= XkbAXN_SKRelease; + beep_type= _BEEP_SLOW_RELEASE; + } + else { + ev.detail= XkbAXN_SKReject; + beep_type= _BEEP_SLOW_REJECT; + ignoreKeyEvent = TRUE; + } + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) { + XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask); + } + if (xkbi->slowKey==key) + xkbi->slowKey= 0; + } + + /* Stop Repeating if the user releases the key that is currently + * repeating. + */ + if (xkbi->repeatKey==key) { + xkbi->repeatKey= 0; + } + + if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) { + xkbi->lastPtrEventTime= 0; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, + ctrls->ax_timeout*1000, + AccessXTimeoutExpire, (pointer)keybd); + xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER; + } + else if (xkbi->krgTimerActive!=_OFF_TIMER) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + + /* Keep track of how many times the Shift key has been pressed. + * If it has been pressed and released 5 times in a row, toggle + * the state of StickyKeys. + */ + if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) { + KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key); + if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) { + xkbi->shiftKeyCount= 0; + } + else if (xkbi->shiftKeyCount>=5) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (ctrls->enabled_ctrls & XkbStickyKeysMask) + AccessXStickyKeysTurnOff(keybd,&cn); + else + AccessXStickyKeysTurnOn(keybd,&cn); + xkbi->shiftKeyCount= 0; + } + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(xE,keybd,count); + return ignoreKeyEvent; + +} /* AccessXFilterReleaseEvent */ + +/************************************************************************/ +/* */ +/* ProcessPointerEvent */ +/* */ +/* This routine merely sets the shiftKeyCount and clears the keyboard */ +/* response group timer (if necessary) on a mouse event. This is so */ +/* multiple shifts with just the mouse and shift-drags with the mouse */ +/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/ +/* */ +/************************************************************************/ +void +#if NeedFunctionPrototypes +ProcessPointerEvent( register xEvent * xE, + register DeviceIntPtr mouse, + int count) +#else +ProcessPointerEvent(xE,mouse,count) + register xEvent *xE; + register DeviceIntPtr mouse; + int count; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice(); +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +unsigned changed = 0; + + xkbi->shiftKeyCount = 0; + xkbi->lastPtrEventTime= xE->u.keyButtonPointer.time; + + if (xE->u.u.type==ButtonPress) { + changed |= XkbPointerButtonMask; + } + else if (xE->u.u.type==ButtonRelease) { + xkbi->lockedPtrButtons&= ~(1<<(xE->u.u.detail&0x7)); + changed |= XkbPointerButtonMask; + } + CoreProcessPointerEvent(xE,mouse,count); + + xkbi->state.ptr_buttons = mouse->button->state; + + /* clear any latched modifiers */ + if ( xkbi->state.latched_mods && (xE->u.u.type==ButtonRelease) ) { + unsigned changed_leds; + XkbStateRec oldState; + XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + oldState= xkbi->state; + XkbLatchModifiers(dev,0xFF,0x00); + + XkbComputeDerivedState(xkbi); + changed |= XkbStateChangedFlags(&oldState,&xkbi->state); + if (changed&sli->usedComponents) { + changed_leds= XkbIndicatorsToUpdate(dev,changed,False); + if (changed_leds) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause,(xE->u.u.detail&0x7),xE->u.u.type); + XkbUpdateIndicators(dev,changed_leds,True,NULL,&cause); + } + } + dev->key->state= XkbStateFieldFromRec(&xkbi->state); + } + + if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) { + xkbStateNotify sn; + sn.keycode= xE->u.u.detail; + sn.eventType= xE->u.u.type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + +} /* ProcessPointerEvent */ + + + + diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c new file mode 100644 index 000000000..fd8910841 --- /dev/null +++ b/xkb/xkbActions.c @@ -0,0 +1,1462 @@ +/* $Xorg: xkbActions.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include + +#ifdef XINPUT +extern void ProcessOtherEvent( +#if NeedFunctionPrototypes + xEvent * /* xE */, + DeviceIntPtr /* dev */, + int /* count */ +#endif +); +#endif + +/***====================================================================***/ + +static XkbAction +#if NeedFunctionPrototypes +_FixUpAction(XkbDescPtr xkb,XkbAction *act) +#else +_FixUpAction(xkb,act) + XkbDescPtr xkb; + XkbAction * act; +#endif +{ +static XkbAction fake; + + if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) { + fake.type = XkbSA_NoAction; + return fake; + } + if (XkbDisableLockActions) { + switch (act->type) { + case XkbSA_LockMods: + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->mods.mask; + return fake; + case XkbSA_LatchMods: + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->mods.mask; + return fake; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_ISODfltIsGroup) { + fake.group.type = XkbSA_SetGroup; + fake.group.flags = act->iso.flags&XkbSA_GroupAbsolute; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->iso)); + } + else { + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->iso.mask; + } + return fake; + case XkbSA_LockGroup: + case XkbSA_LatchGroup: + /* We want everything from the latch/lock action except the + * type should be changed to set. + */ + fake = *act; + fake.group.type = XkbSA_SetGroup; + return fake; + } + } + else + if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) { + if (act->any.type==XkbSA_SetMods) { + fake.mods.type = XkbSA_LatchMods; + fake.mods.mask = act->mods.mask; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.mods.flags= XkbSA_ClearLocks; + return fake; + } + if (act->any.type==XkbSA_SetGroup) { + fake.group.type = XkbSA_LatchGroup; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.group.flags= XkbSA_ClearLocks; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->group)); + return fake; + } + } + return *act; +} + +static XkbAction +#if NeedFunctionPrototypes +XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key) +#else +XkbGetKeyAction(xkbi,xkbState,key) + XkbSrvInfoPtr xkbi; + XkbStatePtr xkbState; + CARD8 key; +#endif +{ +int effectiveGroup; +int col; +XkbDescPtr xkb; +XkbKeyTypePtr type; +XkbAction * pActs; +static XkbAction fake; + + xkb= xkbi->desc; + if (!XkbKeyHasActions(xkb,key)) { + fake.type = XkbSA_NoAction; + return fake; + } + pActs= XkbKeyActionsPtr(xkb,key); + col= 0; + effectiveGroup= xkbState->group; + if (effectiveGroup!=XkbGroup1Index) { + if (XkbKeyNumGroups(xkb,key)>(unsigned)1) { + if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) { + unsigned gi= XkbKeyGroupInfo(xkb,key); + switch (XkbOutOfRangeGroupAction(gi)) { + default: + case XkbWrapIntoRange: + effectiveGroup %= XkbKeyNumGroups(xkb,key); + break; + case XkbClampIntoRange: + effectiveGroup = XkbKeyNumGroups(xkb,key)-1; + break; + case XkbRedirectIntoRange: + effectiveGroup= XkbOutOfRangeGroupInfo(gi); + if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) + effectiveGroup= 0; + break; + } + } + } + else effectiveGroup= XkbGroup1Index; + col+= (effectiveGroup*XkbKeyGroupsWidth(xkb,key)); + } + type= XkbKeyKeyType(xkb,key,effectiveGroup); + if (type->map!=NULL) { + register unsigned i,mods; + register XkbKTMapEntryPtr entry; + mods= xkbState->mods&type->mods.mask; + for (entry= type->map,i=0;imap_count;i++,entry++) { + if ((entry->active)&&(entry->mods.mask==mods)) { + col+= entry->level; + break; + } + } + } + if (pActs[col].any.type==XkbSA_NoAction) + return pActs[col]; + fake= _FixUpAction(xkb,&pActs[col]); + return fake; +} + +XkbAction +#if NeedFunctionPrototypes +XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button) +#else +XkbGetButtonAction(kbd,dev,button) + DeviceIntPtr kbd; + DeviceIntPtr dev; + int button; +#endif +{ +XkbAction fake; + if ((dev->button)&&(dev->button->xkb_acts)) { + if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) { + fake= _FixUpAction(kbd->key->xkbInfo->desc, + &dev->button->xkb_acts[button-1]); + return fake; + } + } + fake.any.type= XkbSA_NoAction; + return fake; +} + +/***====================================================================***/ + +#define SYNTHETIC_KEYCODE 1 +#define BTN_ACT_FLAG 0x100 + +typedef struct _XkbFilter { + CARD16 keycode; + CARD8 what; + CARD8 active; + CARD8 filterOthers; + CARD32 priv; + XkbAction upAction; + int (*filter)( +#if NeedFunctionPrototypes + XkbSrvInfoPtr /* xkbi */, + struct _XkbFilter * /* filter */, + unsigned /* keycode */, + XkbAction * /* action */ +#endif + ); + struct _XkbFilter *next; +} XkbFilterRec,*XkbFilterPtr; + +static int +#if NeedFunctionPrototypes +_XkbFilterSetState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction *pAction) +#else +_XkbFilterSetState(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0); + filter->priv = 0; + filter->filter = _XkbFilterSetState; + if (pAction->type==XkbSA_SetMods) { + filter->upAction = *pAction; + xkbi->setMods= pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if (filter->keycode==keycode) { + if (filter->upAction.type==XkbSA_SetMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if (filter->upAction.mods.flags&XkbSA_ClearLocks) { + xkbi->state.locked_mods&= ~filter->upAction.mods.mask; + } + } + else { + if (filter->upAction.group.flags&XkbSA_ClearLocks) { + xkbi->state.locked_group = 0; + } + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + } + filter->active = 0; + } + else { + filter->upAction.mods.flags&= ~XkbSA_ClearLocks; + filter->filterOthers = 0; + } + return 1; +} + +#define LATCH_KEY_DOWN 1 +#define LATCH_PENDING 2 +#define NO_LATCH 3 + +static int +#if NeedFunctionPrototypes +_XkbFilterLatchState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterLatchState(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = LATCH_KEY_DOWN; + filter->filter = _XkbFilterLatchState; + if (pAction->type==XkbSA_LatchMods) { + filter->upAction = *pAction; + xkbi->setMods = pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if ( pAction && (filter->priv==LATCH_PENDING) ) { + if (((1<type)&XkbSA_BreakLatch)!=0) { + filter->active = 0; + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + } + else if ((pAction->type==filter->upAction.type)&& + (pAction->mods.flags==filter->upAction.mods.flags)&& + (pAction->mods.mask==filter->upAction.mods.mask)) { + if (filter->upAction.mods.flags&XkbSA_LatchToLock) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_LockMods; + else pAction->group.type= XkbSA_LockGroup; + if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&& + (ctrls->enabled_ctrls&XkbStickyKeysMask)) { + XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK, + XkbStickyKeysMask); + } + } + else { + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_SetMods; + else pAction->group.type= XkbSA_SetGroup; + } + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + filter->active = 0; + } + } + else if (filter->keycode==keycode) { /* release */ + XkbControlsPtr ctrls= xkbi->desc->ctrls; + int needBeep; + int beepType= _BEEP_NONE; + + needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&& + XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)); + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&& + (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) { + xkbi->state.locked_mods&= ~xkbi->clearMods; + filter->priv= NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + else { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + if ((filter->upAction.group.flags&XkbSA_ClearLocks)&& + (xkbi->state.locked_group)) { + xkbi->state.locked_group = 0; + filter->priv = NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + if (filter->priv==NO_LATCH) { + filter->active= 0; + } + else { + filter->priv= LATCH_PENDING; + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->state.latched_mods |= filter->upAction.mods.mask; + needBeep = xkbi->state.latched_mods ? needBeep : 0; + xkbi->state.latched_mods |= filter->upAction.mods.mask; + } + else { + xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group); + } + if (needBeep && (beepType==_BEEP_NONE)) + beepType= _BEEP_STICKY_LATCH; + } + if (needBeep && (beepType!=_BEEP_NONE)) + XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask); + } + else if (filter->priv==LATCH_KEY_DOWN) { + filter->priv= NO_LATCH; + filter->filterOthers = 0; + } + return 1; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterLockState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterLockState(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (pAction&&(pAction->type==XkbSA_LockGroup)) { + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->state.locked_group= XkbSAGroup(&pAction->group); + else xkbi->state.locked_group+= XkbSAGroup(&pAction->group); + return 1; + } + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterLockState; + filter->upAction = *pAction; + xkbi->state.locked_mods^= pAction->mods.mask; + xkbi->setMods = pAction->mods.mask; + } + else if (filter->keycode==keycode) { + filter->active = 0; + xkbi->clearMods = filter->upAction.mods.mask; + } + return 1; +} + +#define ISO_KEY_DOWN 0 +#define NO_ISO_LOCK 1 + +static int +#if NeedFunctionPrototypes +_XkbFilterISOLock( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterISOLock(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (filter->keycode==0) { /* initial press */ + CARD8 flags= pAction->iso.flags; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = ISO_KEY_DOWN; + filter->upAction = *pAction; + filter->filter = _XkbFilterISOLock; + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = XkbSAGroup(&pAction->iso); + xkbi->setMods = 0; + } + else { + xkbi->setMods = pAction->iso.mask; + xkbi->groupChange = 0; + } + if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) { + filter->priv= NO_ISO_LOCK; + xkbi->state.locked_mods^= xkbi->state.base_mods; + } + if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) { +/* 6/22/93 (ef) -- lock groups if group key is down first */ + } + if (!(flags&XkbSA_ISONoAffectPtr)) { +/* 6/22/93 (ef) -- lock mouse buttons if they're down */ + } + } + else if (filter->keycode==keycode) { + CARD8 flags= filter->upAction.iso.flags; + + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso); + xkbi->clearMods = 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso); + } + else { + xkbi->clearMods= filter->upAction.iso.mask; + xkbi->groupChange= 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_mods^= filter->upAction.iso.mask; + } + filter->active = 0; + } + else if (pAction) { + CARD8 flags= filter->upAction.iso.flags; + + switch (pAction->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: + if (!(flags&XkbSA_ISONoAffectMods)) { + pAction->type= XkbSA_LockMods; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetGroup: case XkbSA_LatchGroup: + if (!(flags&XkbSA_ISONoAffectGroup)) { + pAction->type= XkbSA_LockGroup; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_PtrBtn: + if (!(flags&XkbSA_ISONoAffectPtr)) { + pAction->type= XkbSA_LockPtrBtn; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetControls: + if (!(flags&XkbSA_ISONoAffectCtrls)) { + pAction->type= XkbSA_LockControls; + filter->priv= NO_ISO_LOCK; + } + break; + } + } + return 1; +} + + +static CARD32 +#if NeedFunctionPrototypes +_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +_XkbPtrAccelExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +int dx,dy; + + if (xkbi->mouseKey==0) + return 0; + + if (xkbi->mouseKeysAccel) { + if ((xkbi->mouseKeysCounter)mk_time_to_max) { + double step; + xkbi->mouseKeysCounter++; + step= xkbi->mouseKeysCurveFactor* + pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve); + if (xkbi->mouseKeysDX<0) + dx= floor( ((double)xkbi->mouseKeysDX)*step ); + else dx= ceil( ((double)xkbi->mouseKeysDX)*step ); + if (xkbi->mouseKeysDY<0) + dy= floor( ((double)xkbi->mouseKeysDY)*step ); + else dy= ceil( ((double)xkbi->mouseKeysDY)*step ); + } + else { + dx= xkbi->mouseKeysDX*ctrls->mk_max_speed; + dy= xkbi->mouseKeysDY*ctrls->mk_max_speed; + } + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX) + dx= xkbi->mouseKeysDX; + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY) + dy= xkbi->mouseKeysDY; + } + else { + dx= xkbi->mouseKeysDX; + dy= xkbi->mouseKeysDY; + } + XkbDDXFakePointerMotion(xkbi->mouseKeysFlags,dx,dy); + return xkbi->desc->ctrls->mk_interval; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterPointerMove( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterPointerMove(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +int x,y; +Bool accel; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerMove; + filter->upAction= *pAction; + xkbi->mouseKeysCounter= 0; + xkbi->mouseKey= keycode; + accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0); + x= XkbPtrActionX(&pAction->ptr); + y= XkbPtrActionY(&pAction->ptr); + XkbDDXFakePointerMotion(pAction->ptr.flags,x,y); + AccessXCancelRepeatKey(xkbi,keycode); + xkbi->mouseKeysAccel= accel&& + (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask); + if (xkbi->mouseKeysAccel) { + xkbi->mouseKeysFlags= pAction->ptr.flags; + xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr); + xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr); + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, + xkbi->desc->ctrls->mk_delay, + _XkbPtrAccelExpire,(pointer)xkbi); + } + } + else if (filter->keycode==keycode) { + filter->active = 0; + if (xkbi->mouseKey==keycode) { + xkbi->mouseKey= 0; + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0, + NULL, NULL); + } + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterPointerBtn(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + if (filter->keycode==0) { /* initial press */ + int button= pAction->btn.button; + + if (button==XkbSA_UseDfltButton) + button = xkbi->desc->ctrls->mk_dflt_btn; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerBtn; + filter->upAction= *pAction; + filter->upAction.btn.button= button; + switch (pAction->type) { + case XkbSA_LockPtrBtn: + if (((xkbi->lockedPtrButtons&(1<btn.flags&XkbSA_LockNoLock)==0)) { + xkbi->lockedPtrButtons|= (1<upAction.type= XkbSA_NoAction; + } + break; + case XkbSA_PtrBtn: + { + register int i,nClicks; + AccessXCancelRepeatKey(xkbi,keycode); + if (pAction->btn.count>0) { + nClicks= pAction->btn.count; + for (i=0;iupAction.type= XkbSA_NoAction; + } + else XkbDDXFakePointerButton(ButtonPress,button); + } + break; + case XkbSA_SetPtrDflt: + { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + XkbControlsRec old; + xkbControlsNotify cn; + + old= *ctrls; + AccessXCancelRepeatKey(xkbi,keycode); + switch (pAction->dflt.affect) { + case XkbSA_AffectDfltBtn: + if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute) + ctrls->mk_dflt_btn= + XkbSAPtrDfltValue(&pAction->dflt); + else { + ctrls->mk_dflt_btn+= + XkbSAPtrDfltValue(&pAction->dflt); + if (ctrls->mk_dflt_btn>5) + ctrls->mk_dflt_btn= 5; + else if (ctrls->mk_dflt_btn<1) + ctrls->mk_dflt_btn= 1; + } + break; + default: + ErrorF( + "Attempt to change unknown pointer default (%d) ignored\n", + pAction->dflt.affect); + break; + } + if (XkbComputeControlsNotify(xkbi->device, + &old,xkbi->desc->ctrls, + &cn,False)) { + cn.keycode = keycode; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(xkbi->device,&cn); + } + } + break; + } + } + else if (filter->keycode==keycode) { + int button= filter->upAction.btn.button; + + switch (filter->upAction.type) { + case XkbSA_LockPtrBtn: + if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)|| + ((xkbi->lockedPtrButtons&(1<lockedPtrButtons&= ~(1<active = 0; + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterControls( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterControls(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +XkbControlsRec old; +XkbControlsPtr ctrls; +DeviceIntPtr kbd; +unsigned int change; +XkbEventCauseRec cause; + + kbd= xkbi->device; + ctrls= xkbi->desc->ctrls; + old= *ctrls; + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + change= XkbActionCtrls(&pAction->ctrls); + filter->priv = change; + filter->filter = _XkbFilterControls; + filter->upAction = *pAction; + + if (pAction->type==XkbSA_LockControls) { + filter->priv= (ctrls->enabled_ctrls&change); + change&= ~ctrls->enabled_ctrls; + } + + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls|= change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) { + cn.keycode = keycode; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyPress); + + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change); + } + } + else if (filter->keycode==keycode) { + change= filter->priv; + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls&= ~change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) { + cn.keycode = keycode; + cn.eventType = KeyRelease; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyRelease); + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change); + } + filter->keycode= 0; + filter->active= 0; + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterActionMessage(XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterActionMessage(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +XkbMessageAction * pMsg; +DeviceIntPtr kbd; + + kbd= xkbi->device; + if (filter->keycode==0) { /* initial press */ + pMsg= &pAction->msg; + if ((pMsg->flags&XkbSA_MessageOnRelease)|| + ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) { + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterActionMessage; + filter->upAction = *pAction; + } + if (pMsg->flags&XkbSA_MessageOnPress) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 1; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message, + (char *)pMsg->message,XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0); + } + else if (filter->keycode==keycode) { + pMsg= &filter->upAction.msg; + if (pMsg->flags&XkbSA_MessageOnRelease) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 0; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message,(char *)pMsg->message, + XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + filter->keycode= 0; + filter->active= 0; + return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterRedirectKey(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +unsigned realMods; +xEvent ev; +int x,y,kc; +XkbStateRec old; +unsigned mods,mask,oldCoreState,oldCorePrevState; + + if ((filter->keycode!=0)&&(filter->keycode!=keycode)) + return 0; + + GetSpritePosition(&x,&y); + ev.u.keyButtonPointer.time = GetTimeInMillis(); + ev.u.keyButtonPointer.rootX = x; + ev.u.keyButtonPointer.rootY = y; + + mask= XkbSARedirectVModsMask(&pAction->redirect); + mods= XkbSARedirectVMods(&pAction->redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= pAction->redirect.mods_mask; + mods|= pAction->redirect.mods; + + if (filter->keycode==0) { /* initial press */ + if ((pAction->redirect.new_keydesc->min_key_code)|| + (pAction->redirect.new_key>xkbi->desc->max_key_code)) { + return 1; + } + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterRedirectKey; + filter->upAction = *pAction; + + ev.u.u.type = KeyPress; + ev.u.u.detail = pAction->redirect.new_key; + + if ( mask || mods ) { + old= xkbi->state; + oldCoreState= xkbi->device->key->state; + oldCorePrevState= xkbi->device->key->prev_state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + xkbi->device->key->state= xkbi->device->key->prev_state= + xkbi->state.mods; + } + + realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; + xkbi->device->key->modifierMap[ev.u.u.detail] = 0; + CoreProcessKeyboardEvent(&ev,xkbi->device,1); + xkbi->device->key->modifierMap[ev.u.u.detail] = realMods; + + if ( mask || mods ) { + xkbi->device->key->state= oldCoreState; + xkbi->device->key->prev_state= oldCorePrevState; + xkbi->state= old; + } + + return 0; + } + else if (filter->keycode==keycode) { + + ev.u.u.type = KeyRelease; + ev.u.u.detail = filter->upAction.redirect.new_key; + + if ( mask || mods ) { + old= xkbi->state; + oldCoreState= xkbi->device->key->state; + oldCorePrevState= xkbi->device->key->prev_state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + xkbi->device->key->state= xkbi->device->key->prev_state= + xkbi->state.mods; + } + + realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; + xkbi->device->key->modifierMap[ev.u.u.detail] = 0; + CoreProcessKeyboardEvent(&ev,xkbi->device,1); + xkbi->device->key->modifierMap[ev.u.u.detail] = realMods; + + if ( mask || mods ) { + xkbi->device->key->state= oldCoreState; + xkbi->device->key->prev_state= oldCorePrevState; + xkbi->state= old; + } + + filter->keycode= 0; + filter->active= 0; + return 0; + } + return 0; +} + +#ifdef XINPUT + +static int +#if NeedFunctionPrototypes +_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterDeviceBtn(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +DeviceIntPtr dev; +int button; + + if (filter->keycode==0) { /* initial press */ + dev= _XkbLookupButtonDevice(pAction->devbtn.device,NULL); + if ((!dev)||(!dev->public.on)||(&dev->public==LookupPointerDevice())) + return 1; + + button= pAction->devbtn.button; + if ((button<1)||(button>dev->button->numButtons)) + return 1; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterDeviceBtn; + filter->upAction= *pAction; + switch (pAction->type) { + case XkbSA_LockDeviceBtn: + if ((pAction->devbtn.flags&XkbSA_LockNoLock)|| + (dev->button->down[button/8]&(1L<<(button%8)))) + return 0; + XkbDDXFakeDeviceButton(dev,True,button); + filter->upAction.type= XkbSA_NoAction; + break; + case XkbSA_DeviceBtn: + if (pAction->devbtn.count>0) { + int nClicks,i; + nClicks= pAction->btn.count; + for (i=0;iupAction.type= XkbSA_NoAction; + } + else XkbDDXFakeDeviceButton(dev,True,button); + break; + } + } + else if (filter->keycode==keycode) { + int button; + + filter->active= 0; + dev= _XkbLookupButtonDevice(filter->upAction.devbtn.device,NULL); + if ((!dev)||(!dev->public.on)||(&dev->public==LookupPointerDevice())) + return 1; + + button= filter->upAction.btn.button; + switch (filter->upAction.type) { + case XkbSA_LockDeviceBtn: + if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)|| + ((dev->button->down[button/8]&(1L<<(button%8)))==0)) + return 0; + XkbDDXFakeDeviceButton(dev,False,button); + break; + case XkbSA_DeviceBtn: + XkbDDXFakeDeviceButton(dev,False,button); + break; + } + filter->active = 0; + } + return 0; +} +#endif + +static int szFilters = 0; +static XkbFilterPtr filters = NULL; + +static XkbFilterPtr +_XkbNextFreeFilter( +#if NeedFunctionPrototypes + void +#endif +) +{ +register int i; + + if (szFilters==0) { + szFilters = 4; + filters = _XkbTypedCalloc(szFilters,XkbFilterRec); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + } + for (i=0;ikey; + xkbi= keyc->xkbInfo; + key= xE->u.u.detail; + if ((xkbi->flags&_XkbStateNotifyInProgress)==0) { + oldState= xkbi->state; + xkbi->flags|= _XkbStateNotifyInProgress; + genStateNotify= True; + } + else genStateNotify= False; + + xkbi->clearMods = xkbi->setMods = 0; + xkbi->groupChange = 0; + + sendEvent = 1; +#ifdef XINPUT + keyEvent= ((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)|| + (xE->u.u.type==KeyRelease)||(xE->u.u.type==DeviceKeyRelease)); + pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)|| + (xE->u.u.type==ButtonPress)||(xE->u.u.type==DeviceButtonPress); + xiEvent= (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease)|| + (xE->u.u.type==DeviceButtonPress)|| + (xE->u.u.type==DeviceButtonRelease); +#else + keyEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease); + pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==ButtonPress); +#endif + + if (pressEvent) { + if (keyEvent) + act = XkbGetKeyAction(xkbi,&xkbi->state,key); + else { + act = XkbGetButtonAction(kbd,dev,key); + key|= BTN_ACT_FLAG; + } + sendEvent = _XkbApplyFilters(xkbi,key,&act); + if (sendEvent) { + switch (act.type) { + case XkbSA_SetMods: + case XkbSA_SetGroup: + filter = _XkbNextFreeFilter(); + sendEvent = _XkbFilterSetState(xkbi,filter,key,&act); + break; + case XkbSA_LatchMods: + case XkbSA_LatchGroup: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act); + break; + case XkbSA_LockMods: + case XkbSA_LockGroup: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterLockState(xkbi,filter,key,&act); + break; + case XkbSA_ISOLock: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act); + break; + case XkbSA_MovePtr: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act); + break; + case XkbSA_PtrBtn: + case XkbSA_LockPtrBtn: + case XkbSA_SetPtrDflt: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act); + break; + case XkbSA_Terminate: + sendEvent= XkbDDXTerminateServer(dev,key,&act); + break; + case XkbSA_SwitchScreen: + sendEvent= XkbDDXSwitchScreen(dev,key,&act); + break; + case XkbSA_SetControls: + case XkbSA_LockControls: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterControls(xkbi,filter,key,&act); + break; + case XkbSA_ActionMessage: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act); + break; + case XkbSA_RedirectKey: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act); + break; +#ifdef XINPUT + case XkbSA_DeviceBtn: + case XkbSA_LockDeviceBtn: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act); + break; +#endif + } + } + } + else { + if (!keyEvent) + key|= BTN_ACT_FLAG; + sendEvent = _XkbApplyFilters(xkbi,key,NULL); + } + + if (xkbi->groupChange!=0) + xkbi->state.base_group+= xkbi->groupChange; + if (xkbi->setMods) { + for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) { + if (xkbi->setMods&bit) { + keyc->modifierKeyCount[i]++; + xkbi->state.base_mods|= bit; + xkbi->setMods&= ~bit; + } + } + } + if (xkbi->clearMods) { + for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) { + if (xkbi->clearMods&bit) { + keyc->modifierKeyCount[i]--; + if (keyc->modifierKeyCount[i]<=0) { + xkbi->state.base_mods&= ~bit; + keyc->modifierKeyCount[i] = 0; + } + xkbi->clearMods&= ~bit; + } + } + } + + if (sendEvent) { +#if XINPUT + if (xiEvent) + ProcessOtherEvent(xE,dev,count); + else +#endif + if (keyEvent) { + realMods = keyc->modifierMap[key]; + keyc->modifierMap[key] = 0; + CoreProcessKeyboardEvent(xE,dev,count); + keyc->modifierMap[key] = realMods; + } + else CoreProcessPointerEvent(xE,dev,count); + } + xkbi->prev_state= oldState; + XkbComputeDerivedState(xkbi); + keyc->prev_state= keyc->state; + keyc->state= XkbStateFieldFromRec(&xkbi->state); + changed = XkbStateChangedFlags(&oldState,&xkbi->state); + if (genStateNotify) { + if (changed) { + xkbStateNotify sn; + sn.keycode= key; + sn.eventType= xE->u.u.type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + xkbi->flags&= ~_XkbStateNotifyInProgress; + } + changed= XkbIndicatorsToUpdate(dev,changed,False); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause,key,xE->u.u.type); + XkbUpdateIndicators(dev,changed,True,NULL,&cause); + } + return; +} + +int +#if NeedFunctionPrototypes +XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches) +#else +XkbLatchModifiers(pXDev,mask,latches) + DeviceIntPtr pXDev; + CARD8 mask; + CARD8 latches; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; +unsigned clear; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + clear= (mask&(~latches)); + xkbi->state.latched_mods&= ~clear; + /* Clear any pending latch to locks. + */ + act.type = XkbSA_NoAction; + _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act); + act.type = XkbSA_LatchMods; + act.mods.flags = 0; + act.mods.mask = mask&latches; + filter = _XkbNextFreeFilter(); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +int +#if NeedFunctionPrototypes +XkbLatchGroup(DeviceIntPtr pXDev,int group) +#else +XkbLatchGroup(pXDev,group) + DeviceIntPtr pXDev; + int group; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + act.type = XkbSA_LatchGroup; + act.group.flags = 0; + XkbSASetGroup(&act.group,group); + filter = _XkbNextFreeFilter(); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbClearAllLatchesAndLocks( DeviceIntPtr dev, + XkbSrvInfoPtr xkbi, + Bool genEv, + XkbEventCausePtr cause) +#else +XkbClearAllLatchesAndLocks(dev,xkbi,genEv,cause) + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + Bool genEv; + XkbEventCausePtr cause; +#endif +{ +XkbStateRec os; +xkbStateNotify sn; + + sn.changed= 0; + os= xkbi->state; + if (os.latched_mods) { /* clear all latches */ + XkbLatchModifiers(dev,~0,0); + sn.changed|= XkbModifierLatchMask; + } + if (os.latched_group) { + XkbLatchGroup(dev,0); + sn.changed|= XkbGroupLatchMask; + } + if (os.locked_mods) { + xkbi->state.locked_mods= 0; + sn.changed|= XkbModifierLockMask; + } + if (os.locked_group) { + xkbi->state.locked_group= 0; + sn.changed|= XkbGroupLockMask; + } + if ( genEv && sn.changed) { + CARD32 changed; + + XkbComputeDerivedState(xkbi); + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + sn.changed= XkbStateChangedFlags(&os,&xkbi->state); + XkbSendStateNotify(dev,&sn); + changed= XkbIndicatorsToUpdate(dev,sn.changed,False); + if (changed) { + XkbUpdateIndicators(dev,changed,True,NULL,cause); + } + } + return; +} + diff --git a/xkb/xkbDflts.h b/xkb/xkbDflts.h new file mode 100644 index 000000000..a79202065 --- /dev/null +++ b/xkb/xkbDflts.h @@ -0,0 +1,519 @@ +/* $Xorg: xkbDflts.h,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/* This file generated automatically by xkbcomp */ +/* DO NOT EDIT */ +#ifndef DEFAULT_H +#define DEFAULT_H 1 + +#ifndef XKB_IN_SERVER +#define GET_ATOM(d,s) XInternAtom(d,s,0) +#define DPYTYPE Display * +#else +#define GET_ATOM(d,s) MakeAtom(s,strlen(s),1) +#define DPYTYPE char * +#endif +#define NUM_KEYS 1 + +#define vmod_NumLock 0 +#define vmod_Alt 1 +#define vmod_LevelThree 2 +#define vmod_AltGr 3 +#define vmod_ScrollLock 4 + +#define vmod_NumLockMask (1<<0) +#define vmod_AltMask (1<<1) +#define vmod_LevelThreeMask (1<<2) +#define vmod_AltGrMask (1<<3) +#define vmod_ScrollLockMask (1<<4) + +/* types name is "default" */ +static Atom lnames_ONE_LEVEL[1]; + +static XkbKTMapEntryRec map_TWO_LEVEL[1]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } } +}; +static Atom lnames_TWO_LEVEL[2]; + +static XkbKTMapEntryRec map_ALPHABETIC[2]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 1, 0, { LockMask, LockMask, 0 } } +}; +static XkbModsRec preserve_ALPHABETIC[2]= { + { 0, 0, 0 }, + { LockMask, LockMask, 0 } +}; +static Atom lnames_ALPHABETIC[2]; + +static XkbKTMapEntryRec map_KEYPAD[2]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 0, 1, { 0, 0, vmod_NumLockMask } } +}; +static Atom lnames_KEYPAD[2]; + +static XkbKTMapEntryRec map_PC_BREAK[1]= { + { 1, 1, { ControlMask, ControlMask, 0 } } +}; +static Atom lnames_PC_BREAK[2]; + +static XkbKTMapEntryRec map_PC_SYSRQ[1]= { + { 0, 1, { 0, 0, vmod_AltMask } } +}; +static Atom lnames_PC_SYSRQ[2]; + +static XkbKTMapEntryRec map_CTRL_ALT[1]= { + { 0, 1, { ControlMask, ControlMask, vmod_AltMask } } +}; +static Atom lnames_CTRL_ALT[2]; + +static XkbKTMapEntryRec map_THREE_LEVEL[3]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 0, 2, { 0, 0, vmod_LevelThreeMask } }, + { 0, 2, { ShiftMask, ShiftMask, vmod_LevelThreeMask } } +}; +static Atom lnames_THREE_LEVEL[3]; + +static XkbKTMapEntryRec map_SHIFT_ALT[1]= { + { 0, 1, { ShiftMask, ShiftMask, vmod_AltMask } } +}; +static Atom lnames_SHIFT_ALT[2]; + +static XkbKeyTypeRec dflt_types[]= { + { + { 0, 0, 0 }, + 1, + 0, NULL, NULL, + None, lnames_ONE_LEVEL + }, + { + { ShiftMask, ShiftMask, 0 }, + 2, + 1, map_TWO_LEVEL, NULL, + None, lnames_TWO_LEVEL + }, + { + { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, + 2, + 2, map_ALPHABETIC, preserve_ALPHABETIC, + None, lnames_ALPHABETIC + }, + { + { ShiftMask, ShiftMask, vmod_NumLockMask }, + 2, + 2, map_KEYPAD, NULL, + None, lnames_KEYPAD + }, + { + { ControlMask, ControlMask, 0 }, + 2, + 1, map_PC_BREAK, NULL, + None, lnames_PC_BREAK + }, + { + { 0, 0, vmod_AltMask }, + 2, + 1, map_PC_SYSRQ, NULL, + None, lnames_PC_SYSRQ + }, + { + { ControlMask, ControlMask, vmod_AltMask }, + 2, + 1, map_CTRL_ALT, NULL, + None, lnames_CTRL_ALT + }, + { + { ShiftMask, ShiftMask, vmod_LevelThreeMask }, + 3, + 3, map_THREE_LEVEL, NULL, + None, lnames_THREE_LEVEL + }, + { + { ShiftMask, ShiftMask, vmod_AltMask }, + 2, + 1, map_SHIFT_ALT, NULL, + None, lnames_SHIFT_ALT + } +}; +#define num_dflt_types (sizeof(dflt_types)/sizeof(XkbKeyTypeRec)) + + +static void +#if NeedFunctionPrototypes +initTypeNames(DPYTYPE dpy) +#else +initTypeNames(dpy) +DPYTYPE dpy; +#endif +{ + dflt_types[0].name= GET_ATOM(dpy,"ONE_LEVEL"); + lnames_ONE_LEVEL[0]= GET_ATOM(dpy,"Any"); + dflt_types[1].name= GET_ATOM(dpy,"TWO_LEVEL"); + lnames_TWO_LEVEL[0]= GET_ATOM(dpy,"Base"); + lnames_TWO_LEVEL[1]= GET_ATOM(dpy,"Shift"); + dflt_types[2].name= GET_ATOM(dpy,"ALPHABETIC"); + lnames_ALPHABETIC[0]= GET_ATOM(dpy,"Base"); + lnames_ALPHABETIC[1]= GET_ATOM(dpy,"Caps"); + dflt_types[3].name= GET_ATOM(dpy,"KEYPAD"); + lnames_KEYPAD[0]= GET_ATOM(dpy,"Base"); + lnames_KEYPAD[1]= GET_ATOM(dpy,"Number"); + dflt_types[4].name= GET_ATOM(dpy,"PC_BREAK"); + lnames_PC_BREAK[0]= GET_ATOM(dpy,"Base"); + lnames_PC_BREAK[1]= GET_ATOM(dpy,"Control"); + dflt_types[5].name= GET_ATOM(dpy,"PC_SYSRQ"); + lnames_PC_SYSRQ[0]= GET_ATOM(dpy,"Base"); + lnames_PC_SYSRQ[1]= GET_ATOM(dpy,"Alt"); + dflt_types[6].name= GET_ATOM(dpy,"CTRL+ALT"); + lnames_CTRL_ALT[0]= GET_ATOM(dpy,"Base"); + lnames_CTRL_ALT[1]= GET_ATOM(dpy,"Ctrl+Alt"); + dflt_types[7].name= GET_ATOM(dpy,"THREE_LEVEL"); + lnames_THREE_LEVEL[0]= GET_ATOM(dpy,"Base"); + lnames_THREE_LEVEL[1]= GET_ATOM(dpy,"Shift"); + lnames_THREE_LEVEL[2]= GET_ATOM(dpy,"Level3"); + dflt_types[8].name= GET_ATOM(dpy,"SHIFT+ALT"); + lnames_SHIFT_ALT[0]= GET_ATOM(dpy,"Base"); + lnames_SHIFT_ALT[1]= GET_ATOM(dpy,"Shift+Alt"); +} +/* compat name is "default" */ +static XkbSymInterpretRec dfltSI[69]= { + { XK_ISO_Level2_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_Exactly, ShiftMask, + 255, + { XkbSA_LatchMods, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Eisu_Shift, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Eisu_toggle, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Kana_Shift, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Kana_Lock, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Shift_Lock, 0x0000, + XkbSI_AnyOf, ShiftMask|LockMask, + 255, + { XkbSA_LockMods, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Num_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 0, + { XkbSA_LockMods, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } }, + { XK_Alt_L, 0x0000, + XkbSI_AnyOf, 0xff, + 1, + { XkbSA_SetMods, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Alt_R, 0x0000, + XkbSI_AnyOf, 0xff, + 1, + { XkbSA_SetMods, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Scroll_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 4, + { XkbSA_LockMods, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 255, + { XkbSA_ISOLock, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Level3_Shift, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOf, 0xff, + 2, + { XkbSA_SetMods, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } }, + { XK_ISO_Level3_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOf, 0xff, + 2, + { XkbSA_LatchMods, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } }, + { XK_Mode_switch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_SetGroup, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_1, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_End, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_2, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_Down, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_3, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_Next, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_4, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Left, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_6, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Right, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_7, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_Home, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_8, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_Up, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_9, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_Prior, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_5, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Begin, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_F1, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Divide, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_F2, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Multiply, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_F3, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Subtract, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Separator, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Add, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_0, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Insert, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Decimal, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Delete, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_EnableKeys, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00 } }, + { XK_Pointer_Accelerate, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 } }, + { XK_Pointer_DfltBtnNext, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DfltBtnPrev, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00 } }, + { XK_AccessX_Enable, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 } }, + { XK_Terminate_Server, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_Terminate, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Group_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LatchGroup, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Next_Group, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LockGroup, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Prev_Group, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LockGroup, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_First_Group, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockGroup, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Last_Group, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockGroup, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { NoSymbol, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_LockMods, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { NoSymbol, 0x0000, + XkbSI_AnyOf, 0xff, + 255, + { XkbSA_SetMods, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +}; +#define num_dfltSI (sizeof(dfltSI)/sizeof(XkbSymInterpretRec)) + +static XkbCompatMapRec compatMap= { + dfltSI, + { /* group compatibility */ + { 0, 0, 0 }, + { 0, 0, vmod_AltGrMask }, + { 0, 0, vmod_AltGrMask }, + { 0, 0, vmod_AltGrMask } + }, + num_dfltSI, num_dfltSI +}; + +static XkbIndicatorRec indicators= { + 0x0, + { + { 0x80, 0, 0x00, XkbIM_UseEffective, LockMask, LockMask, 0, 0 }, + { 0x80, 0, 0x00, XkbIM_UseEffective, 0, 0, vmod_NumLockMask, 0 }, + { 0x80, 0, 0x00, XkbIM_UseLocked, ShiftMask, ShiftMask, 0, 0 }, + { 0x80, 0, 0x00, 0, 0, 0, 0, XkbMouseKeysMask }, + { 0x80, 0, 0x00, XkbIM_UseLocked, 0, 0, vmod_ScrollLockMask, 0 }, + { 0x80, XkbIM_UseEffective, 0xfe, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 } + } +}; +static void +#if NeedFunctionPrototypes +initIndicatorNames(DPYTYPE dpy,XkbDescPtr xkb) +#else +initIndicatorNames(dpy,xkb) + DPYTYPE dpy; + XkbDescPtr xkb; +#endif +{ + xkb->names->indicators[ 0]= GET_ATOM(dpy,"Caps Lock"); + xkb->names->indicators[ 1]= GET_ATOM(dpy,"Num Lock"); + xkb->names->indicators[ 2]= GET_ATOM(dpy,"Shift Lock"); + xkb->names->indicators[ 3]= GET_ATOM(dpy,"Mouse Keys"); + xkb->names->indicators[ 4]= GET_ATOM(dpy,"Scroll Lock"); + xkb->names->indicators[ 5]= GET_ATOM(dpy,"Group 2"); +} +#endif /* DEFAULT_H */ diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c new file mode 100644 index 000000000..5a0f1d54b --- /dev/null +++ b/xkb/xkbEvents.c @@ -0,0 +1,1154 @@ +/* $Xorg: xkbEvents.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "XI.h" +#include "inputstr.h" +#include "windowstr.h" +#include "XKBsrv.h" + +extern int (*InitialVector[3])(); + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN) +#else +XkbSendNewKeyboardNotify(kbd,pNKN) + DeviceIntPtr kbd; + xkbNewKeyboardNotify * pNKN; +#endif +{ +register int i; +Time time; +CARD16 changed; +XkbChangesRec changes; + + pNKN->type = XkbEventCode + XkbEventBase; + pNKN->xkbType = XkbNewKeyboardNotify; + pNKN->time = time = GetTimeInMillis(); + changed = pNKN->changed; + + for (i=1; iclientGone || + (clients[i]->requestVector==InitialVector)) { + continue; + } + + if (clients[i]->xkbClientFlags&_XkbClientInitialized) { + if (clients[i]->newKeyboardNotifyMask&changed) { + pNKN->sequenceNumber = clients[i]->sequence; + pNKN->time = time; + pNKN->changed = changed; + if ( clients[i]->swapped ) { + register int n; + swaps(&pNKN->sequenceNumber,n); + swapl(&pNKN->time,n); + swaps(&pNKN->changed,n); + } + WriteToClient(clients[i],sizeof(xEvent),(char *)pNKN); + if (changed&XkbNKN_KeycodesMask) { + clients[i]->minKC= pNKN->minKeyCode; + clients[i]->maxKC= pNKN->maxKeyCode; + } + } + } + else if (changed&XkbNKN_KeycodesMask) { + xEvent event; + event.u.u.type= MappingNotify; + event.u.mappingNotify.request= MappingKeyboard; + event.u.mappingNotify.firstKeyCode= clients[i]->minKC; + event.u.mappingNotify.count= clients[i]->maxKC-clients[i]->minKC+1; + event.u.u.sequenceNumber= clients[i]->sequence; + if (clients[i]->swapped) { + int n; + swaps(&event.u.u.sequenceNumber,n); + } + WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); + event.u.mappingNotify.request= MappingModifier; + WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); + } + } + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN) +#else +XkbSendStateNotify(kbd,pSN) + DeviceIntPtr kbd; + xkbStateNotify *pSN; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbStatePtr state; +XkbInterestPtr interest; +Time time; +register CARD16 changed,bState; + + interest = kbd->xkb_interest; + if (!interest) + return; + xkbi = kbd->key->xkbInfo; + state= &xkbi->state; + + pSN->type = XkbEventCode + XkbEventBase; + pSN->xkbType = XkbStateNotify; + pSN->deviceID = kbd->id; + pSN->time = time = GetTimeInMillis(); + pSN->mods = state->mods; + pSN->baseMods = state->base_mods; + pSN->latchedMods = state->latched_mods; + pSN->lockedMods = state->locked_mods; + pSN->group = state->group; + pSN->baseGroup = state->base_group; + pSN->latchedGroup = state->latched_group; + pSN->lockedGroup = state->locked_group; + pSN->compatState = state->compat_state; + pSN->grabMods = state->grab_mods; + pSN->compatGrabMods = state->compat_grab_mods; + pSN->lookupMods = state->lookup_mods; + pSN->compatLookupMods = state->compat_lookup_mods; + pSN->ptrBtnState = state->ptr_buttons; + changed = pSN->changed; + bState= pSN->ptrBtnState; + + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->stateNotifyMask&changed)) { + pSN->sequenceNumber = interest->client->sequence; + pSN->time = time; + pSN->changed = changed; + pSN->ptrBtnState = bState; + if ( interest->client->swapped ) { + register int n; + swaps(&pSN->sequenceNumber,n); + swapl(&pSN->time,n); + swaps(&pSN->changed,n); + swaps(&pSN->ptrBtnState,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pSN); + } + interest= interest->next; + } + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify *pMN) +#else +XkbSendMapNotify(kbd,pMN) + DeviceIntPtr kbd; + xkbMapNotify *pMN; +#endif +{ +int i; +XkbSrvInfoPtr xkbi; +unsigned time,initialized; +CARD16 changed; + + xkbi = kbd->key->xkbInfo; + initialized= 0; + + changed = pMN->changed; + pMN->minKeyCode= xkbi->desc->min_key_code; + pMN->maxKeyCode= xkbi->desc->max_key_code; + for (i=1; iclientGone && + (clients[i]->requestVector != InitialVector) && + (clients[i]->xkbClientFlags&_XkbClientInitialized) && + (clients[i]->mapNotifyMask&changed)) + { + if (!initialized) { + pMN->type = XkbEventCode + XkbEventBase; + pMN->xkbType = XkbMapNotify; + pMN->deviceID = kbd->id; + time = GetTimeInMillis(); + initialized= 1; + } + pMN->time= time; + pMN->sequenceNumber = clients[i]->sequence; + pMN->changed = changed; + if ( clients[i]->swapped ) { + register int n; + swaps(&pMN->sequenceNumber,n); + swapl(&pMN->time,n); + swaps(&pMN->changed,n); + } + WriteToClient(clients[i],sizeof(xEvent),(char *)pMN); + } + } + return; +} + +int +#if NeedFunctionPrototypes +XkbComputeControlsNotify( DeviceIntPtr kbd, + XkbControlsPtr old, + XkbControlsPtr new, + xkbControlsNotify * pCN, + Bool forceCtrlProc) +#else +XkbComputeControlsNotify(kbd,old,new,pCN,forceCtrlProc) + DeviceIntPtr kbd; + XkbControlsPtr old; + XkbControlsPtr new; + xkbControlsNotify *pCN; + Bool forceCtrlProc; +#endif +{ +int i; +CARD32 changedControls; + + changedControls= 0; + if (old->enabled_ctrls!=new->enabled_ctrls) + changedControls|= XkbControlsEnabledMask; + if ((old->repeat_delay!=new->repeat_delay)|| + (old->repeat_interval!=new->repeat_interval)) + changedControls|= XkbRepeatKeysMask; + for (i = 0; i < XkbPerKeyBitArraySize; i++) + if (old->per_key_repeat[i] != new->per_key_repeat[i]) + changedControls|= XkbPerKeyRepeatMask; + if (old->slow_keys_delay!=new->slow_keys_delay) + changedControls|= XkbSlowKeysMask; + if (old->debounce_delay!=new->debounce_delay) + changedControls|= XkbBounceKeysMask; + if ((old->mk_delay!=new->mk_delay)|| + (old->mk_interval!=new->mk_interval)|| + (old->mk_dflt_btn!=new->mk_dflt_btn)) + changedControls|= XkbMouseKeysMask; + if ((old->mk_time_to_max!=new->mk_time_to_max)|| + (old->mk_curve!=new->mk_curve)|| + (old->mk_max_speed!=new->mk_max_speed)) + changedControls|= XkbMouseKeysAccelMask; + if (old->ax_options!=new->ax_options) + changedControls|= XkbAccessXKeysMask; + if ((old->ax_timeout!=new->ax_timeout)|| + (old->axt_ctrls_mask!=new->axt_ctrls_mask)|| + (old->axt_ctrls_values!=new->axt_ctrls_values)|| + (old->axt_opts_mask!=new->axt_opts_mask)|| + (old->axt_opts_values!= new->axt_opts_values)) { + changedControls|= XkbAccessXTimeoutMask; + } + if ((old->internal.mask!=new->internal.mask)|| + (old->internal.real_mods!=new->internal.real_mods)|| + (old->internal.vmods!=new->internal.vmods)) + changedControls|= XkbInternalModsMask; + if ((old->ignore_lock.mask!=new->ignore_lock.mask)|| + (old->ignore_lock.real_mods!=new->ignore_lock.real_mods)|| + (old->ignore_lock.vmods!=new->ignore_lock.vmods)) + changedControls|= XkbIgnoreLockModsMask; + + if (new->enabled_ctrls&XkbRepeatKeysMask) + kbd->kbdfeed->ctrl.autoRepeat=TRUE; + else kbd->kbdfeed->ctrl.autoRepeat=FALSE; + + if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc && + (changedControls || forceCtrlProc)) + (*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl); + + if ((!changedControls)&&(old->num_groups==new->num_groups)) + return 0; + + if (!kbd->xkb_interest) + return 0; + + pCN->changedControls = changedControls; + pCN->enabledControls = new->enabled_ctrls; + pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls); + pCN->numGroups = new->num_groups; + + return 1; +} + +void +#if NeedFunctionPrototypes +XkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN) +#else +XkbSendControlsNotify(kbd,pCN) + DeviceIntPtr kbd; + xkbControlsNotify *pCN; +#endif +{ +int initialized; +CARD32 changedControls,enabledControls,enabledChanges; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time; + + interest = kbd->xkb_interest; + if (!interest) + return; + xkbi = kbd->key->xkbInfo; + + initialized = 0; + enabledControls = xkbi->desc->ctrls->enabled_ctrls; + changedControls = pCN->changedControls; + pCN->numGroups= xkbi->desc->ctrls->num_groups; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->ctrlsNotifyMask&changedControls)) { + if (!initialized) { + pCN->type = XkbEventCode + XkbEventBase; + pCN->xkbType = XkbControlsNotify; + pCN->deviceID = kbd->id; + pCN->time = time = GetTimeInMillis(); + enabledChanges = pCN->enabledControlChanges; + initialized= 1; + } + pCN->changedControls = changedControls; + pCN->enabledControls = enabledControls; + pCN->enabledControlChanges = enabledChanges; + pCN->sequenceNumber = interest->client->sequence; + pCN->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pCN->sequenceNumber,n); + swapl(&pCN->changedControls,n); + swapl(&pCN->enabledControls,n); + swapl(&pCN->enabledControlChanges,n); + swapl(&pCN->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pCN); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv) +#else +XkbSendIndicatorNotify(kbd,xkbType,pEv) + DeviceIntPtr kbd; + int xkbType; + xkbIndicatorNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD32 state,changed; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + state = pEv->state; + changed = pEv->changed; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (((xkbType==XkbIndicatorStateNotify)&& + (interest->iStateNotifyMask&changed))|| + ((xkbType==XkbIndicatorMapNotify)&& + (interest->iMapNotifyMask&changed)))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = xkbType; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->state = state; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->changed,n); + swapl(&pEv->state,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + + +void +#if NeedFunctionPrototypes +XkbHandleBell( BOOL force, + BOOL eventOnly, + DeviceIntPtr kbd, + CARD8 percent, + pointer pCtrl, + CARD8 class, + Atom name, + WindowPtr pWin, + ClientPtr pClient) +#else +XkbHandleBell(force,eventOnly,kbd,percent,pCtrl,class,name,pWin,pClient) + BOOL force; + BOOL eventOnly; + DeviceIntPtr kbd; + CARD8 percent; + pointer *pCtrl; + CARD8 class; + Atom name; + WindowPtr pWin; + ClientPtr pClient; +#endif +{ +xkbBellNotify bn; +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +CARD8 id; +CARD16 pitch,duration; +Time time; +XID winID; + + xkbi = kbd->key->xkbInfo; + + if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&& + (!eventOnly)) { + (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class); + } + interest = kbd->xkb_interest; + if ((!interest)||(force)) + return; + + if ((class==0)||(class==KbdFeedbackClass)) { + KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl; + id= pKeyCtrl->id; + pitch= pKeyCtrl->bell_pitch; + duration= pKeyCtrl->bell_duration; + } + else if (class==BellFeedbackClass) { + BellCtrl *pBellCtrl= (BellCtrl *)pCtrl; + id= pBellCtrl->id; + pitch= pBellCtrl->pitch; + duration= pBellCtrl->duration; + } + else return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->bellNotifyMask)) { + if (!initialized) { + time = GetTimeInMillis(); + bn.type = XkbEventCode + XkbEventBase; + bn.xkbType = XkbBellNotify; + bn.deviceID = kbd->id; + bn.bellClass = class; + bn.bellID = id; + bn.percent= percent; + bn.eventOnly = (eventOnly!=0); + winID= (pWin?pWin->drawable.id:None); + initialized= 1; + } + bn.sequenceNumber = interest->client->sequence; + bn.time = time; + bn.pitch = pitch; + bn.duration = duration; + bn.name = name; + bn.window= winID; + if ( interest->client->swapped ) { + register int n; + swaps(&bn.sequenceNumber,n); + swapl(&bn.time,n); + swaps(&bn.pitch,n); + swaps(&bn.duration,n); + swapl(&bn.name,n); + swapl(&bn.window,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)&bn); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv) +#else +XkbSendAccessXNotify(kbd,pEv) + DeviceIntPtr kbd; + xkbAccessXNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD16 sk_delay,db_delay; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + sk_delay= pEv->slowKeysDelay; + db_delay= pEv->debounceDelay; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->accessXNotifyMask&(1<detail))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbAccessXNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->slowKeysDelay = sk_delay; + pEv->debounceDelay = db_delay; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->slowKeysDelay,n); + swaps(&pEv->debounceDelay,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv) +#else +XkbSendNamesNotify(kbd,pEv) + DeviceIntPtr kbd; + xkbNamesNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD16 changed,changedVirtualMods; +CARD32 changedIndicators; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + changed= pEv->changed; + changedIndicators= pEv->changedIndicators; + changedVirtualMods= pEv->changedVirtualMods; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->namesNotifyMask&pEv->changed)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbNamesNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->changedIndicators = changedIndicators; + pEv->changedVirtualMods= changedVirtualMods; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->changed,n); + swapl(&pEv->changedIndicators,n); + swaps(&pEv->changedVirtualMods,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv) +#else +XkbSendCompatMapNotify(kbd,pEv) + DeviceIntPtr kbd; + xkbCompatMapNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD16 firstSI,nSI,nTotalSI; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->compatNotifyMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbCompatMapNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + firstSI= pEv->firstSI; + nSI= pEv->nSI; + nTotalSI= pEv->nTotalSI; + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->firstSI = firstSI; + pEv->nSI = nSI; + pEv->nTotalSI = nTotalSI; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->firstSI,n); + swaps(&pEv->nSI,n); + swaps(&pEv->nTotalSI,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv) +#else +XkbSendActionMessage(kbd,pEv) + DeviceIntPtr kbd; + xkbActionMessage * pEv; +#endif +{ +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time; + + xkbi = kbd->key->xkbInfo; + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + pEv->mods= xkbi->state.mods; + pEv->group= xkbi->state.group; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->actionMessageMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbActionMessage; + pEv->deviceID = kbd->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendExtensionDeviceNotify( DeviceIntPtr dev, + ClientPtr client, + xkbExtensionDeviceNotify * pEv) +#else +XkbSendExtensionDeviceNotify(dev,client,pEv) + DeviceIntPtr dev; + ClientPtr client; + xkbExtensionDeviceNotify * pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD32 defined,state; +CARD16 reason,supported; + + interest = dev->xkb_interest; + if (!interest) + return; + + initialized = 0; + reason= pEv->reason; + defined= pEv->ledsDefined; + state= pEv->ledState; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->extDevNotifyMask&reason)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbExtensionDeviceNotify; + pEv->deviceID = dev->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + supported= pEv->supported; + initialized= 1; + } + else { + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->ledsDefined= defined; + pEv->ledState= state; + pEv->reason= reason; + pEv->supported= supported; + } + if (client!=interest->client) { + /* only report UnsupportedFeature to the client that */ + /* issued the failing request */ + pEv->reason&= ~XkbXI_UnsupportedFeatureMask; + if ((interest->extDevNotifyMask&reason)==0) + continue; + } + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->ledsDefined,n); + swapl(&pEv->ledState,n); + swaps(&pEv->reason,n); + swaps(&pEv->supported,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendNotification( DeviceIntPtr kbd, + XkbChangesPtr pChanges, + XkbEventCausePtr cause) +#else +XkbSendNotification(kbd,pChanges,cause) + DeviceIntPtr kbd; + XkbChangesPtr pChanges; + XkbEventCausePtr cause; +#endif +{ +XkbSrvLedInfoPtr sli; + + sli= NULL; + if (pChanges->state_changes) { + xkbStateNotify sn; + sn.changed= pChanges->state_changes; + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + XkbSendStateNotify(kbd,&sn); + } + if (pChanges->map.changed) { + xkbMapNotify mn; + mn.changed= pChanges->map.changed; + mn.firstType= pChanges->map.first_type; + mn.nTypes= pChanges->map.num_types; + mn.firstKeySym= pChanges->map.first_key_sym; + mn.nKeySyms= pChanges->map.num_key_syms; + mn.firstKeyAct= pChanges->map.first_key_act; + mn.nKeyActs= pChanges->map.num_key_acts; + mn.firstKeyBehavior= pChanges->map.first_key_behavior; + mn.nKeyBehaviors= pChanges->map.num_key_behaviors; + mn.virtualMods= pChanges->map.vmods; + mn.firstKeyExplicit= pChanges->map.first_key_explicit; + mn.nKeyExplicit= pChanges->map.num_key_explicit; + mn.firstModMapKey= pChanges->map.first_modmap_key; + mn.nModMapKeys= pChanges->map.num_modmap_keys; + mn.firstVModMapKey= pChanges->map.first_vmodmap_key; + mn.nVModMapKeys= pChanges->map.num_vmodmap_keys; + XkbSendMapNotify(kbd,&mn); + } + if ((pChanges->ctrls.changed_ctrls)|| + (pChanges->ctrls.enabled_ctrls_changes)) { + xkbControlsNotify cn; + cn.changedControls= pChanges->ctrls.changed_ctrls; + cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes; + cn.keycode= cause->kc; + cn.eventType= cause->event; + cn.requestMajor= cause->mjr; + cn.requestMinor= cause->mnr; + XkbSendControlsNotify(kbd,&cn); + } + if (pChanges->indicators.map_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.map_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in); + } + if (pChanges->indicators.state_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.state_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in); + } + if (pChanges->names.changed) { + xkbNamesNotify nn; + nn.changed= pChanges->names.changed; + nn.firstType= pChanges->names.first_type; + nn.nTypes= pChanges->names.num_types; + nn.firstLevelName= pChanges->names.first_lvl; + nn.nLevelNames= pChanges->names.num_lvls; + nn.nRadioGroups= pChanges->names.num_rg; + nn.changedVirtualMods= pChanges->names.changed_vmods; + nn.changedIndicators= pChanges->names.changed_indicators; + XkbSendNamesNotify(kbd,&nn); + } + if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) { + xkbCompatMapNotify cmn; + cmn.changedGroups= pChanges->compat.changed_groups; + cmn.firstSI= pChanges->compat.first_si; + cmn.nSI= pChanges->compat.num_si; + cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si; + XkbSendCompatMapNotify(kbd,&cmn); + } + return; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE) +#else +XkbFilterEvents(pClient,nEvents,xE) + ClientPtr pClient; + int nEvents; + xEvent *xE; +#endif +{ +int i; +DeviceIntPtr pXDev = (DeviceIntPtr)LookupKeyboardDevice(); +XkbSrvInfoPtr xkbi; + + xkbi= pXDev->key->xkbInfo; + if ( pClient->xkbClientFlags & _XkbClientInitialized ) { +#ifdef DEBUG + if ((xkbDebugFlags&0x10)&& + ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) { + ErrorF("XKbFilterWriteEvents:\n"); + ErrorF(" Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state); + ErrorF(" XkbLastRepeatEvent!=xE (0x%x!=0x%x) %s\n", + XkbLastRepeatEvent,xE, + ((XkbLastRepeatEvent!=(pointer)xE)?"True":"False")); + ErrorF(" (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n", + pClient->xkbClientFlags, + (_XkbWantsDetectableAutoRepeat(pClient)?"True":"False")); + ErrorF(" !IsRelease(%d) %s\n",xE[0].u.u.type, + (!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False"); + } +#endif /* DEBUG */ + if ( (XkbLastRepeatEvent==(pointer)xE) && + (_XkbWantsDetectableAutoRepeat(pClient)) && + (_XkbIsReleaseEvent(xE[0].u.u.type)) ) { + return False; + } + if ((pXDev->grab != NullGrab) && + ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) { + register unsigned state,flags; + + flags= pClient->xkbClientFlags; + state= xkbi->state.compat_grab_mods; + if (flags & XkbPCF_GrabsUseXKBStateMask) { + int group; + if (flags&XkbPCF_LookupStateWhenGrabbed) { + group= xkbi->state.group; + state= xkbi->state.lookup_mods; + } + else { + state= xkbi->state.grab_mods; + group= xkbi->state.base_group+xkbi->state.latched_group; + if ((group<0)||(group>=xkbi->desc->ctrls->num_groups)) { + group= XkbAdjustGroup(group,xkbi->desc->ctrls); + } + } + state = XkbBuildCoreState(state, group); + } + else if (flags&XkbPCF_LookupStateWhenGrabbed) + state= xkbi->state.compat_lookup_mods; + xE[0].u.keyButtonPointer.state= state; + } + } + else { + register CARD8 type; + + for (i=0;istate; + ErrorF("XKbFilterWriteEvents (non-XKB):\n"); + ErrorF("event= 0x%04x\n",xE[0].u.keyButtonPointer.state); + ErrorF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods, + s->grab_mods); + ErrorF("compat lookup= 0x%02x, grab= 0x%02x\n", + s->compat_lookup_mods, + s->compat_grab_mods); + } +#endif + if ( (type>=KeyPress)&&(type<=MotionNotify) ) { + CARD16 old,new; + + old= xE[i].u.keyButtonPointer.state&(~0x1f00); + new= xE[i].u.keyButtonPointer.state&0x1F00; + + if (old==XkbStateFieldFromRec(&xkbi->state)) + new|= xkbi->state.compat_lookup_mods; + else new|= xkbi->state.compat_grab_mods; + xE[i].u.keyButtonPointer.state= new; + } + else if ((type==EnterNotify)||(type==LeaveNotify)) { + xE->u.enterLeave.state&= 0x1F00; + xE->u.enterLeave.state|= xkbi->state.compat_grab_mods; + } + } + } + return True; +} + +/***====================================================================***/ + +XkbInterestPtr +#if NeedFunctionPrototypes +XkbFindClientResource(DevicePtr inDev,ClientPtr client) +#else +XkbFindClientResource(inDev,client) + DevicePtr inDev; + ClientPtr client; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + while (interest){ + if (interest->client==client) { + return interest; + } + interest = interest->next; + } + } + return NULL; +} + +XkbInterestPtr +#if NeedFunctionPrototypes +XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id) +#else +XkbAddClientResource(inDev,client,id) + DevicePtr inDev; + ClientPtr client; + XID id; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + interest = dev->xkb_interest; + while (interest) { + if (interest->client==client) + return ((interest->resource==id)?interest:NULL); + interest = interest->next; + } + interest = _XkbTypedAlloc(XkbInterestRec); + bzero(interest,sizeof(XkbInterestRec)); + if (interest) { + interest->dev = dev; + interest->client = client; + interest->resource = id; + interest->stateNotifyMask= 0; + interest->ctrlsNotifyMask= 0; + interest->namesNotifyMask= 0; + interest->compatNotifyMask= 0; + interest->bellNotifyMask= FALSE; + interest->accessXNotifyMask= 0; + interest->iStateNotifyMask= 0; + interest->iMapNotifyMask= 0; + interest->altSymsNotifyMask= 0; + interest->next = dev->xkb_interest; + dev->xkb_interest= interest; + return interest; + } + return NULL; +} + +int +#if NeedFunctionPrototypes +XkbRemoveClient(DevicePtr inDev,ClientPtr client) +#else +XkbRemoveClient(inDev,client) +DevicePtr inDev; +ClientPtr client; +#endif +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; +unsigned long autoCtrls,autoValues; +Bool found; + + found= False; + autoCtrls= autoValues= 0; + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + if (interest && (interest->client==client)){ + dev->xkb_interest = interest->next; + autoCtrls= interest->autoCtrls; + autoValues= interest->autoCtrlValues; + xfree(interest); + found= True; + } + while ((!found)&&(interest->next)) { + if (interest->next->client==client) { + XkbInterestPtr victim = interest->next; + interest->next = victim->next; + autoCtrls= victim->autoCtrls; + autoValues= victim->autoCtrlValues; + xfree(victim); + found= True; + } + interest = interest->next; + } + } + if (found && autoCtrls && dev->key && dev->key->xkbInfo ) { + XkbEventCauseRec cause; + + xkbi= dev->key->xkbInfo; + XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client); + XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause); + } + return found; +} + +int +#if NeedFunctionPrototypes +XkbRemoveResourceClient(DevicePtr inDev,XID id) +#else +XkbRemoveResourceClient(inDev,id) + DevicePtr inDev; + XID id; +#endif +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; +Bool found; +unsigned long autoCtrls,autoValues; +ClientPtr client; + + found= False; + autoCtrls= autoValues= 0; + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + if (interest && (interest->resource==id)){ + dev->xkb_interest = interest->next; + autoCtrls= interest->autoCtrls; + autoValues= interest->autoCtrlValues; + client= interest->client; + xfree(interest); + found= True; + } + while ((!found)&&(interest->next)) { + if (interest->next->resource==id) { + XkbInterestPtr victim = interest->next; + interest->next = victim->next; + autoCtrls= victim->autoCtrls; + autoValues= victim->autoCtrlValues; + client= victim->client; + xfree(victim); + found= True; + } + interest = interest->next; + } + } + if (found && autoCtrls && dev->key && dev->key->xkbInfo ) { + XkbEventCauseRec cause; + + xkbi= dev->key->xkbInfo; + XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client); + XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause); + } + return found; +} + + + diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c new file mode 100644 index 000000000..3ca52ebc5 --- /dev/null +++ b/xkb/xkbInit.c @@ -0,0 +1,994 @@ +/* + * @(#)$RCSfile$ $Revision$ (DEC) $Date$ + */ +/* $Xorg: xkbInit.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#include +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#include "property.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XKBgeom.h" +#include +#include + + +#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1) + +#ifdef sgi +#define LED_CAPS 5 +#define LED_NUM 6 +#define LED_SCROLL 7 +#define PHYS_LEDS 0x7f +#define LED_COMPOSE 8 +#else +#if defined(ultrix) || defined(__osf__) || defined(__alpha) +#define LED_COMPOSE 2 +#define LED_CAPS 3 +#define LED_SCROLL 4 +#define LED_NUM 5 +#define PHYS_LEDS 0x1f +#else +#ifdef sun +#define LED_NUM 1 +#define LED_SCROLL 2 +#define LED_COMPOSE 3 +#define LED_CAPS 4 +#define PHYS_LEDS 0x0f +#else +#define LED_CAPS 1 +#define LED_NUM 2 +#define LED_SCROLL 3 +#define PHYS_LEDS 0x07 +#endif +#endif +#endif + +#define MAX_TOC 16 +typedef struct _SrvXkmInfo { + DeviceIntPtr dev; + FILE * file; + XkbFileInfo xkbinfo; +} SrvXkmInfo; + + +/***====================================================================***/ + +#ifndef XKB_BASE_DIRECTORY +#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb" +#endif +#ifndef XKB_DFLT_RULES_FILE +#define XKB_DFLT_RULES_FILE "rules" +#endif +#ifndef XKB_DFLT_KB_LAYOUT +#define XKB_DFLT_KB_LAYOUT "us" +#endif +#ifndef XKB_DFLT_KB_MODEL +#define XKB_DFLT_KB_MODEL "dflt" +#endif +#ifndef XKB_DFLT_KB_VARIANT +#define XKB_DFLT_KB_VARIANT NULL +#endif +#ifndef XKB_DFLT_KB_OPTIONS +#define XKB_DFLT_KB_OPTIONS NULL +#endif +#ifndef XKB_DFLT_DISABLED +#define XKB_DFLT_DISABLED True +#endif +#ifndef XKB_DFLT_RULES_PROP +#define XKB_DFLT_RULES_PROP True +#endif + +char * XkbBaseDirectory= XKB_BASE_DIRECTORY; +char * XkbInitialMap= NULL; +int XkbWantAccessX= 0; +static XkbFileInfo * _XkbInitFileInfo= NULL; +char * XkbDB= NULL; +int XkbAutoLoad= 1; + +static Bool rulesDefined= False; +static char * XkbRulesFile= NULL; +static char * XkbModelDflt= NULL; +static char * XkbLayoutDflt= NULL; +static char * XkbVariantDflt= NULL; +static char * XkbOptionsDflt= NULL; + +char * XkbModelUsed= NULL; +char * XkbLayoutUsed= NULL; +char * XkbVariantUsed= NULL; +char * XkbOptionsUsed= NULL; + +int _XkbClientMajor= XkbMajorVersion; +int _XkbClientMinor= XkbMinorVersion; + +Bool noXkbExtension= XKB_DFLT_DISABLED; +Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP; + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbGetRulesDflts(XkbRF_VarDefsPtr defs) +#else +XkbGetRulesDflts(defs) + XkbRF_VarDefsPtr defs; +#endif +{ + if (XkbModelDflt) defs->model= XkbModelDflt; + else defs->model= XKB_DFLT_KB_MODEL; + if (XkbLayoutDflt) defs->layout= XkbLayoutDflt; + else defs->layout= XKB_DFLT_KB_LAYOUT; + if (XkbVariantDflt) defs->variant= XkbVariantDflt; + else defs->variant= XKB_DFLT_KB_VARIANT; + if (XkbOptionsDflt) defs->options= XkbOptionsDflt; + else defs->options= XKB_DFLT_KB_OPTIONS; + return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE); +} + +Bool +#if NeedFunctionPrototypes +XkbWriteRulesProp(ClientPtr client, pointer closure) +#else +XkbWriteRulesProp(client, closure) + ClientPtr client; + pointer closure; +#endif +{ +int len,out; +extern WindowPtr * WindowTable; +Atom name; +char * pval; + + if (rulesDefined && (!XkbRulesFile)) + return False; + len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE)); + len+= (XkbModelUsed?strlen(XkbModelUsed):0); + len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0); + len+= (XkbVariantUsed?strlen(XkbVariantUsed):0); + len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0); + if (len<1) + return True; + + len+= 5; /* trailing NULs */ + + name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1); + if (name==None) { + ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); + return True; + } + pval= (char*) ALLOCATE_LOCAL(len); + if (!pval) { + ErrorF("Allocation error: %s proprerty not created\n", + _XKB_RF_NAMES_PROP_ATOM); + return True; + } + out= 0; + if (XkbRulesFile) { + strcpy(&pval[out],XkbRulesFile); + out+= strlen(XkbRulesFile); + } + pval[out++]= '\0'; + if (XkbModelUsed) { + strcpy(&pval[out],XkbModelUsed); + out+= strlen(XkbModelUsed); + } + pval[out++]= '\0'; + if (XkbLayoutUsed) { + strcpy(&pval[out],XkbLayoutUsed); + out+= strlen(XkbLayoutUsed); + } + pval[out++]= '\0'; + if (XkbVariantUsed) { + strcpy(&pval[out],XkbVariantUsed); + out+= strlen(XkbVariantUsed); + } + pval[out++]= '\0'; + if (XkbOptionsUsed) { + strcpy(&pval[out],XkbOptionsUsed); + out+= strlen(XkbOptionsUsed); + } + pval[out++]= '\0'; + if (out!=len) { + ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", + out,len); + } + ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace, + len,pval,True); + DEALLOCATE_LOCAL(pval); + return True; +} + +void +#if NeedFunctionPrototypes +XkbSetRulesUsed(XkbRF_VarDefsPtr defs) +#else +XkbSetRulesUsed(defs) + XkbRF_VarDefsPtr defs; +#endif +{ + if (XkbModelUsed) + _XkbFree(XkbModelUsed); + XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL); + if (XkbLayoutUsed) + _XkbFree(XkbLayoutUsed); + XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL); + if (XkbVariantUsed) + _XkbFree(XkbVariantUsed); + XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL); + if (XkbOptionsUsed) + _XkbFree(XkbOptionsUsed); + XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL); + if (XkbWantRulesProp) + QueueWorkProc(XkbWriteRulesProp,NULL,NULL); + return; +} + +void +#if NeedFunctionPrototypes +XkbSetRulesDflts(char *rulesFile,char *model,char *layout, + char *variant,char *options) +#else +XkbSetRulesDflts(rulesFile,model,layout,variant,options) + char * rulesFile; + char * model; + char * layout; + char * variant; + char * options; +#endif +{ + if (XkbRulesFile) + _XkbFree(XkbRulesFile); + XkbRulesFile= _XkbDupString(rulesFile); + rulesDefined= True; + if (model) { + if (XkbModelDflt) + _XkbFree(XkbModelDflt); + XkbModelDflt= _XkbDupString(model); + } + if (layout) { + if (XkbLayoutDflt) + _XkbFree(XkbLayoutDflt); + XkbLayoutDflt= _XkbDupString(layout); + } + if (variant) { + if (XkbVariantDflt) + _XkbFree(XkbVariantDflt); + XkbVariantDflt= _XkbDupString(variant); + } + if (options) { + if (XkbOptionsDflt) + _XkbFree(XkbOptionsDflt); + XkbOptionsDflt= _XkbDupString(options); + } + return; +} + +/***====================================================================***/ + +#if defined(luna) +#define XKB_DDX_PERMANENT_LOCK 1 +#endif + +#include "xkbDflts.h" + +static Bool +#if NeedFunctionPrototypes +XkbInitKeyTypes(XkbDescPtr xkb,SrvXkmInfo *file) +#else +XkbInitKeyTypes(xkb,file) + XkbDescPtr xkb; + SrvXkmInfo * file; +#endif +{ + if (file->xkbinfo.defined&XkmTypesMask) + return True; + initTypeNames(NULL); + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success) + return False; + if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!= + Success) { + return False; + } + xkb->map->size_types= xkb->map->num_types= num_dflt_types; + return True; +} + +static void +#if NeedFunctionPrototypes +XkbInitRadioGroups(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitRadioGroups(xkbi,file) + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ + xkbi->nRadioGroups = 0; + xkbi->radioGroups = NULL; + return; +} + + +static Status +#if NeedFunctionPrototypes +XkbInitCompatStructs(XkbDescPtr xkb,SrvXkmInfo *file) +#else +XkbInitCompatStructs(xkb,file) + XkbDescPtr xkb; + SrvXkmInfo * file; +#endif +{ +register int i; +XkbCompatMapPtr compat; + + if (file->xkbinfo.defined&XkmCompatMapMask) + return Success; + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success) + return BadAlloc; + compat = xkb->compat; + if (compat->sym_interpret) { + compat->num_si = num_dfltSI; + memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI)); + } + for (i=0;igroups[i]= compatMap.groups[i]; + if (compat->groups[i].vmods!=0) { + unsigned mask; + mask= XkbMaskForVMask(xkb,compat->groups[i].vmods); + compat->groups[i].mask= compat->groups[i].real_mods|mask; + } + else compat->groups[i].mask= compat->groups[i].real_mods; + } + return Success; +} + +static void +#if NeedFunctionPrototypes +XkbInitSemantics(XkbDescPtr xkb,SrvXkmInfo *file) +#else +XkbInitSemantics(xkb,file) + XkbDescPtr xkb; + SrvXkmInfo * file; +#endif +{ + XkbInitKeyTypes(xkb,file); + XkbInitCompatStructs(xkb,file); + return; +} + +/***====================================================================***/ + +static Status +#if NeedFunctionPrototypes +XkbInitNames(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitNames(xkbi,file) + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ +XkbDescPtr xkb; +XkbNamesPtr names; +Status rtrn; +Atom unknown; + + xkb= xkbi->desc; + if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success) + return rtrn; + unknown= CREATE_ATOM("unknown"); + names = xkb->names; + if (names->keycodes==None) names->keycodes= unknown; + if (names->geometry==None) names->geometry= unknown; + if (names->phys_symbols==None) names->phys_symbols= unknown; + if (names->symbols==None) names->symbols= unknown; + if (names->types==None) names->types= unknown; + if (names->compat==None) names->compat= unknown; + if ((file->xkbinfo.defined&XkmVirtualModsMask)==0) { + if (names->vmods[vmod_NumLock]==None) + names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock"); + if (names->vmods[vmod_Alt]==None) + names->vmods[vmod_Alt]= CREATE_ATOM("Alt"); + if (names->vmods[vmod_AltGr]==None) + names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch"); + } + + if (((file->xkbinfo.defined&XkmIndicatorsMask)==0)|| + ((file->xkbinfo.defined&XkmGeometryMask)==0)) { + initIndicatorNames(NULL,xkb); + if (names->indicators[LED_CAPS-1]==None) + names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock"); + if (names->indicators[LED_NUM-1]==None) + names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock"); + if (names->indicators[LED_SCROLL-1]==None) + names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock"); +#ifdef LED_COMPOSE + if (names->indicators[LED_COMPOSE-1]==None) + names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose"); +#endif + } +#ifdef DEBUG_RADIO_GROUPS + if (names->num_rg<1) { + names->radio_groups= (Atom *)Xcalloc(RG_COUNT*sizeof(Atom)); + if (names->radio_groups) { + names->num_rg = RG_COUNT; + names->radio_groups[RG_BOGUS_FUNCTION_GROUP]= CREATE_ATOM("BOGUS"); + } + } +#endif + if (xkb->geom!=NULL) + names->geometry= xkb->geom->name; + else names->geometry= unknown; + return Success; +} + +static Status +#if NeedFunctionPrototypes +XkbInitIndicatorMap(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitIndicatorMap(xkbi,file) + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ +XkbDescPtr xkb; +XkbIndicatorPtr map; +XkbSrvLedInfoPtr sli; + + xkb= xkbi->desc; + if (XkbAllocIndicatorMaps(xkb)!=Success) + return BadAlloc; + if ((file->xkbinfo.defined&XkmIndicatorsMask)==0) { + map= xkb->indicators; + map->phys_indicators = PHYS_LEDS; + map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit; + map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked; + map->maps[LED_CAPS-1].mods.mask= LockMask; + map->maps[LED_CAPS-1].mods.real_mods= LockMask; + + map->maps[LED_NUM-1].flags= XkbIM_NoExplicit; + map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked; + map->maps[LED_NUM-1].mods.mask= 0; + map->maps[LED_NUM-1].mods.real_mods= 0; + map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask; + } + sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); + if (sli) + XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); + return Success; +} + +static Status +#if NeedFunctionPrototypes +XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitControls(pXDev,xkbi,file) + DeviceIntPtr pXDev; + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ +XkbDescPtr xkb; +XkbControlsPtr ctrls; + + xkb= xkbi->desc; + /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */ + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) + FatalError("Couldn't allocate keyboard controls\n"); + ctrls= xkb->ctrls; + if ((file->xkbinfo.defined&XkmSymbolsMask)==0) + ctrls->num_groups = 1; + ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0); + ctrls->internal.mask = 0; + ctrls->internal.real_mods = 0; + ctrls->internal.vmods = 0; + ctrls->ignore_lock.mask = 0; + ctrls->ignore_lock.real_mods = 0; + ctrls->ignore_lock.vmods = 0; + ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask| + XkbMouseKeysAccelMask|XkbAudibleBellMask| + XkbIgnoreGroupLockMask; + if (XkbWantAccessX) + ctrls->enabled_ctrls|= XkbAccessXKeysMask; + AccessXInit(pXDev); + return Success; +} + +void +#if NeedFunctionPrototypes +XkbInitDevice(DeviceIntPtr pXDev) +#else +XkbInitDevice(pXDev) + DeviceIntPtr pXDev; +#endif +{ +int i; +XkbSrvInfoPtr xkbi; +XkbChangesRec changes; +SrvXkmInfo file; +unsigned check; +XkbEventCauseRec cause; + + file.dev= pXDev; + file.file=NULL; + bzero(&file.xkbinfo,sizeof(XkbFileInfo)); + bzero(&changes,sizeof(XkbChangesRec)); + if (XkbAutoLoad && (XkbInitialMap!=NULL)) { + if ((file.file=XkbDDXOpenConfigFile(XkbInitialMap,NULL,0))!=NULL) { + XkmReadFile(file.file,0,XkmKeymapLegal,&file.xkbinfo); + if (file.xkbinfo.xkb==NULL) { + ErrorF("Error loading keymap file %s (%s in %s)\n", + XkbInitialMap, _XkbErrMessages[_XkbErrCode], + (_XkbErrLocation?_XkbErrLocation:"unknown")); + ErrorF(" reverting to defaults\n"); + fclose(file.file); + file.file= NULL; + bzero(&file.xkbinfo,sizeof(XkbFileInfo)); + } + else { + if (_XkbInitFileInfo!=NULL) { + XkbDescPtr tmp; + if ((tmp=_XkbInitFileInfo->xkb)!=NULL) { + XkbFreeKeyboard(tmp,XkbAllComponentsMask,True); + _XkbInitFileInfo->xkb= NULL; + } + } + _XkbInitFileInfo= &file.xkbinfo; + } + } + else { + ErrorF("Error opening keymap file %s, reverting to defaults\n", + XkbInitialMap); + } + } + pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec); + if ( xkbi ) { + XkbDescPtr xkb; + if ((_XkbInitFileInfo!=NULL)&&(_XkbInitFileInfo->xkb!=NULL)) { + file.xkbinfo= *_XkbInitFileInfo; + xkbi->desc= _XkbInitFileInfo->xkb; + _XkbInitFileInfo= NULL; + } + else { + xkbi->desc= XkbAllocKeyboard(); + if (!xkbi->desc) + FatalError("Couldn't allocate keyboard description\n"); + xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode; + xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode; + } + xkb= xkbi->desc; + if (xkb->min_key_code == 0) + xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode; + if (xkb->max_key_code == 0) + xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode; + if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)|| + (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) { + /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */ + /* the other here, but for now just complain */ + /* can't just update the core range without */ + /* reallocating the KeySymsRec (pain) */ + ErrorF("Internal Error!! XKB and core keymap have different range\n"); + } + if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) + FatalError("Couldn't allocate client map in XkbInitDevice\n"); + i= XkbNumKeys(xkb)/3+1; + if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success) + FatalError("Couldn't allocate server map in XkbInitDevice\n"); + + xkbi->dfltPtrDelta=1; + xkbi->device = pXDev; + + file.xkbinfo.xkb= xkb; + XkbInitSemantics(xkb,&file); + XkbInitNames(xkbi,&file); + XkbInitRadioGroups(xkbi,&file); + + /* 12/31/94 (ef) -- XXX! Should check if state loaded from file */ + bzero(&xkbi->state,sizeof(XkbStateRec)); + + XkbInitControls(pXDev,xkbi,&file); + + if (file.xkbinfo.defined&XkmSymbolsMask) + memcpy(pXDev->key->modifierMap,xkb->map->modmap,xkb->max_key_code+1); + else + memcpy(xkb->map->modmap,pXDev->key->modifierMap,xkb->max_key_code+1); + + XkbInitIndicatorMap(xkbi,&file); + + XkbDDXInitDevice(pXDev); + + if (!(file.xkbinfo.defined&XkmSymbolsMask)) { + XkbUpdateKeyTypesFromCore(pXDev,xkb->min_key_code,XkbNumKeys(xkb), + &changes); + } + else { + XkbUpdateCoreDescription(pXDev,True); + } + XkbSetCauseUnknown(&cause); + XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes, + &check,&cause); + /* For sanity. The first time the connection + * is opened, the client side min and max are set + * using QueryMinMaxKeyCodes() which grabs them + * from pXDev. + */ + pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code; + pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code; + } + if (file.file!=NULL) + fclose(file.file); + return; +} + + +Bool +#if NeedFunctionPrototypes +XkbInitKeyboardDeviceStruct( DeviceIntPtr dev, + XkbComponentNamesPtr names, + KeySymsPtr pSymsIn, + CARD8 pModsIn[], + void (*bellProc)(), + void (*ctrlProc)()) +#else +XkbInitKeyboardDeviceStruct( dev,names,pSymsIn,pModsIn,bellProc,ctrlProc ) + DeviceIntPtr dev; + XkbComponentNamesPtr names; + KeySymsPtr pSymsIn; + CARD8 pModsIn[]; + void (*bellProc)(); + void (*ctrlProc)(); +#endif +{ +XkbFileInfo finfo; +KeySymsRec tmpSyms,*pSyms; +CARD8 tmpMods[XkbMaxLegalKeyCode+1],*pMods; +char name[PATH_MAX],*rules; +Bool ok; +XPointer config; +XkbComponentNamesRec cfgNames; +XkbRF_VarDefsRec defs; + + if ((dev->key!=NULL)||(dev->kbdfeed!=NULL)) + return False; + pSyms= pSymsIn; + pMods= pModsIn; + bzero(&defs,sizeof(XkbRF_VarDefsRec)); + bzero(&cfgNames,sizeof(XkbComponentNamesRec)); + rules= XkbGetRulesDflts(&defs); + config= XkbDDXPreloadConfig(&rules,&defs,&cfgNames,dev); + + if (defs.model && defs.layout && rules) { + XkbComponentNamesRec rNames; + bzero(&rNames,sizeof(XkbComponentNamesRec)); + if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) { + if (rNames.keymap) names->keymap= rNames.keymap; + if (rNames.keycodes) names->keycodes= rNames.keycodes; + if (rNames.types) names->types= rNames.types; + if (rNames.compat) names->compat= rNames.compat; + if (rNames.symbols) names->symbols= rNames.symbols; + if (rNames.geometry) names->geometry= rNames.geometry; + XkbSetRulesUsed(&defs); + } + } + if (cfgNames.keymap) names->keymap= cfgNames.keymap; + if (cfgNames.keycodes) names->keycodes= cfgNames.keycodes; + if (cfgNames.types) names->types= cfgNames.types; + if (cfgNames.compat) names->compat= cfgNames.compat; + if (cfgNames.symbols) names->symbols= cfgNames.symbols; + if (cfgNames.geometry) names->geometry= cfgNames.geometry; + + if ((XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0, + &finfo,name,PATH_MAX))&& + (finfo.xkb!=NULL)) { + XkbDescPtr xkb; + int minKC,maxKC; + + xkb= finfo.xkb; + minKC= xkb->min_key_code; + maxKC= xkb->max_key_code; + if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&& + ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) { + if (xkb->map!=NULL) { + KeySym *inSym,*outSym; + int width= pSymsIn->mapWidth; + + tmpSyms.minKeyCode= minKC; + tmpSyms.maxKeyCode= maxKC; + + if (minKCminKeyCode) + minKC= pSymsIn->minKeyCode; + if (maxKC>pSymsIn->maxKeyCode) + maxKC= pSymsIn->maxKeyCode; + + tmpSyms.mapWidth= width; + tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym); + inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width]; + outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width]; + memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym)); + pSyms= &tmpSyms; + } + if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) { + bzero(tmpMods,XkbMaxKeyCount); + memcpy(tmpMods,xkb->map->modmap,maxKC+1); + pMods= tmpMods; + } + } + _XkbInitFileInfo= &finfo; + } + else { + ErrorF("Couldn't load XKB keymap, falling back to pre-XKB keymap\n"); + } + ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc); + if ((config!=NULL)&&(dev && dev->key && dev->key->xkbInfo)) + XkbDDXApplyConfig(config,dev->key->xkbInfo); + _XkbInitFileInfo= NULL; + if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) { + _XkbFree(pSyms->map); + pSyms->map= NULL; + } + return ok; +} + +/***====================================================================***/ + + /* + * InitKeyClassDeviceStruct initializes the key class before it + * initializes the keyboard feedback class for a device. + * UpdateActions can't set up the correct autorepeat for keyboard + * initialization because the keyboard feedback isn't created yet. + * Instead, UpdateActions notes the "correct" autorepeat in the + * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat + * to apply the computed autorepeat once the feedback class exists. + * + * DIX will apply the changed autorepeat, so there's no need to + * do so here. This function returns True if both RepeatKeys and + * the core protocol autorepeat ctrls are set (i.e. should use + * software autorepeat), false otherwise. + * + * This function also computes the autorepeat accelerators for the + * default indicator feedback. + */ +int +#if NeedFunctionPrototypes +XkbFinishDeviceInit(DeviceIntPtr pXDev) +#else +XkbFinishDeviceInit(pXDev) + DeviceIntPtr pXDev; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +int softRepeat; +XkbSrvLedInfoPtr sli; + + xkbi = NULL; + if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) { + xkbi= pXDev->key->xkbInfo; + xkb= xkbi->desc; + if (pXDev->kbdfeed) { + xkbi->kbdProc= pXDev->kbdfeed->CtrlProc; + pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc; + } + if (pXDev->kbdfeed->ctrl.autoRepeat) + xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask; + softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0; + if (pXDev->kbdfeed) { + memcpy(pXDev->kbdfeed->ctrl.autoRepeats, + xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize); + softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat; + } + } + else softRepeat= 0; + sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0); + if (sli && xkbi) + XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); +#ifdef DEBUG + else ErrorF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n"); +#endif + return softRepeat; +} + + /* + * Be very careful about what does and doesn't get freed by this + * function. To reduce fragmentation, XkbInitDevice allocates a + * single huge block per device and divides it up into most of the + * fixed-size structures for the device. Don't free anything that + * is part of this larger block. + */ +void +#if NeedFunctionPrototypes +XkbFreeInfo(XkbSrvInfoPtr xkbi) +#else +XkbFreeInfo(xkbi) + XkbSrvInfoPtr xkbi; +#endif +{ + if (xkbi->radioGroups) { + Xfree(xkbi->radioGroups); + xkbi->radioGroups= NULL; + } + if (xkbi->mouseKeyTimer) { + TimerFree(xkbi->mouseKeyTimer); + xkbi->mouseKeyTimer= NULL; + } + if (xkbi->slowKeysTimer) { + TimerFree(xkbi->slowKeysTimer); + xkbi->slowKeysTimer= NULL; + } + if (xkbi->bounceKeysTimer) { + TimerFree(xkbi->bounceKeysTimer); + xkbi->bounceKeysTimer= NULL; + } + if (xkbi->repeatKeyTimer) { + TimerFree(xkbi->repeatKeyTimer); + xkbi->repeatKeyTimer= NULL; + } + if (xkbi->krgTimer) { + TimerFree(xkbi->krgTimer); + xkbi->krgTimer= NULL; + } + xkbi->beepType= _BEEP_NONE; + if (xkbi->beepTimer) { + TimerFree(xkbi->beepTimer); + xkbi->beepTimer= NULL; + } + if (xkbi->desc) { + XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True); + xkbi->desc= NULL; + } + Xfree(xkbi); + return; +} + +/***====================================================================***/ + +extern int XkbDfltRepeatDelay; +extern int XkbDfltRepeatInterval; + +extern unsigned short XkbDfltAccessXTimeout; +extern unsigned int XkbDfltAccessXTimeoutMask; +extern unsigned int XkbDfltAccessXFeedback; +extern unsigned char XkbDfltAccessXOptions; + +int +#if NeedFunctionPrototypes +XkbProcessArguments(int argc,char *argv[],int i) +#else +XkbProcessArguments(argc,argv,i) + int argc; + char * argv[]; + int i; +#endif +{ + if (strcmp(argv[i],"-kb")==0) { + noXkbExtension= True; + return 1; + } + else if (strcmp(argv[i],"+kb")==0) { + noXkbExtension= False; + return 1; + } + else if (strncmp(argv[i], "-xkbmap", 7) == 0) { + if(++i < argc) { + XkbInitialMap= argv[i]; + return 2; + } + else { + return -1; + } + } + else if (strncmp(argv[i], "-xkbdb", 7) == 0) { + if(++i < argc) { + XkbDB= argv[i]; + return 2; + } + else { + return -1; + } + } + else if (strncmp(argv[i], "-noloadxkb", 7) == 0) { + XkbAutoLoad= 0; + return 1; + } + else if ((strncmp(argv[i],"-accessx",8)==0)|| + (strncmp(argv[i],"+accessx",8)==0)) { + int j=1; + if (argv[i][0]=='-') + XkbWantAccessX= 0; + else { + XkbWantAccessX= 1; + + if ( ((i+1)= argc) UseMsg (); + XkbDfltRepeatDelay = (long)atoi(argv[i]); + return 2; + } + if (strcmp (argv[i], "-ar2") == 0) { /* -ar2 int */ + if (++i >= argc) UseMsg (); + XkbDfltRepeatInterval = (long)atoi(argv[i]); + return 2; + } + return 0; +} + +void +#if NeedFunctionPrototypes +XkbUseMsg(void) +#else +XkbUseMsg() +#endif +{ + ErrorF("The X Keyboard Extension adds the following arguments:\n"); + ErrorF("-kb disable the X Keyboard Extension\n"); + ErrorF("+kb enable the X Keyboard Extension\n"); + ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n"); + ErrorF(" enable/disable accessx key sequences\n"); + ErrorF("-ar1 set XKB autorepeat delay\n"); + ErrorF("-ar2 set XKB autorepeat interval\n"); + ErrorF("-noloadxkb don't load XKB keymap description\n"); + ErrorF("-xkbcomp default keymap compiler\n"); + ErrorF("-xkbdb file that contains default XKB keymaps\n"); + ErrorF("-xkbmap XKB keyboard description to load on startup\n"); +} diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c new file mode 100644 index 000000000..d3be89af7 --- /dev/null +++ b/xkb/xkbLEDs.c @@ -0,0 +1,1212 @@ +/* $Xorg: xkbLEDs.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#include +#define NEED_EVENTS 1 +#include +#include +#include "misc.h" +#include "inputstr.h" + +#include "XI.h" +#include "XKBsrv.h" + +extern InputInfo inputInfo; + +/***====================================================================***/ + + /* + * unsigned + * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn) + * + * Given a keyboard and a set of state components that have changed, + * this function returns the indicators on the default keyboard + * feedback that might be affected. It also reports whether or not + * any extension devices might be affected in check_devs_rtrn. + */ + +unsigned +#if NeedFunctionPrototypes +XkbIndicatorsToUpdate( DeviceIntPtr dev, + unsigned long state_changes, + Bool enable_changes) +#else +XkbIndicatorsToUpdate(dev,state_changes,enable_changes) + DeviceIntPtr dev; + unsigned long state_changes; + Bool enable_changes; +#endif +{ +register unsigned update= 0; +XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + + if (state_changes&(XkbModifierStateMask|XkbGroupStateMask)) + update|= sli->usesEffective; + if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask)) + update|= sli->usesBase; + if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask)) + update|= sli->usesLatched; + if (state_changes&(XkbModifierLockMask|XkbGroupLockMask)) + update|= sli->usesLocked; + if (state_changes&XkbCompatStateMask) + update|= sli->usesCompat; + if (enable_changes) + update|= sli->usesControls; + return update; +} + +/***====================================================================***/ + + /* + * Bool + * XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) + * + * Some indicators "drive" the keyboard when their state is explicitly + * changed, as described in section 9.2.1 of the XKB protocol spec. + * This function updates the state and controls for the keyboard + * specified by 'xkbi' to reflect any changes that are required + * when the indicator described by 'map' is turned on or off. The + * extent of the changes is reported in change, which must be defined. + */ +Bool +#if NeedFunctionPrototypes +XkbApplyLEDChangeToKeyboard( XkbSrvInfoPtr xkbi, + XkbIndicatorMapPtr map, + Bool on, + XkbChangesPtr change) +#else +XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) + XkbSrvInfoPtr xkbi; + XkbIndicatorMapPtr map; + Bool on; + XkbChangesPtr change; +#endif +{ +Bool ctrlChange,stateChange; +XkbStatePtr state; + + if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0)) + return False; + ctrlChange= stateChange= False; + if (map->ctrls) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + unsigned old; + + old= ctrls->enabled_ctrls; + if (on) ctrls->enabled_ctrls|= map->ctrls; + else ctrls->enabled_ctrls&= ~map->ctrls; + if (old!=ctrls->enabled_ctrls) { + change->ctrls.changed_ctrls= XkbControlsEnabledMask; + change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls; + ctrlChange= True; + } + } + state= &xkbi->state; + if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) { + register int i; + register unsigned bit,match; + + if (on) match= (map->groups)&XkbAllGroupsMask; + else match= (~map->groups)&XkbAllGroupsMask; + if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) { + for (i=0,bit=1;iwhich_groups&XkbIM_UseLatched) + XkbLatchGroup(xkbi->device,0); /* unlatch group */ + state->locked_group= i; + stateChange= True; + } + else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) { + for (i=0,bit=1;ilocked_group= 0; + XkbLatchGroup(xkbi->device,i); + stateChange= True; + } + } + if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) { + if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) { + register unsigned long old; + old= state->locked_mods; + if (on) state->locked_mods|= map->mods.mask; + else state->locked_mods&= ~map->mods.mask; + if (state->locked_mods!=old) + stateChange= True; + } + if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) { + register unsigned long newmods; + newmods= state->latched_mods; + if (on) newmods|= map->mods.mask; + else newmods&= ~map->mods.mask; + if (newmods!=state->locked_mods) { + newmods&= map->mods.mask; + XkbLatchModifiers(xkbi->device,map->mods.mask,newmods); + stateChange= True; + } + } + } + return (stateChange || ctrlChange); +} + +/***====================================================================***/ + + /* + * void + * XkbSetIndicators(dev,affect,values,cause) + * + * Attempts to change the indicators specified in 'affect' to the + * states specified in 'values' for the default keyboard feedback + * on the keyboard specified by 'dev.' Attempts to change indicator + * state might be ignored or have no affect, depending on the XKB + * indicator map for any affected indicators, as described in section + * 9.2 of the XKB protocol specification. + * + * If 'changes' is non-NULL, this function notes any changes to the + * keyboard state, controls, or indicator state that result from this + * attempted change. If 'changes' is NULL, this function generates + * XKB events to report any such changes to interested clients. + * + * If 'cause' is non-NULL, it specifies the reason for the change, + * as reported in some XKB events. If it is NULL, this function + * assumes that the change is the result of a core protocol + * ChangeKeyboardMapping request. + */ + +void +#if NeedFunctionPrototypes +XkbSetIndicators( DeviceIntPtr dev, + CARD32 affect, + CARD32 values, + XkbEventCausePtr cause) +#else +XkbSetIndicators(dev,affect,values,cause) + DeviceIntPtr dev; + CARD32 affect; + CARD32 values; + XkbEventCausePtr cause; +#endif +{ +XkbSrvLedInfoPtr sli; +XkbChangesRec changes; +xkbExtensionDeviceNotify ed; +unsigned side_affected; + + bzero((char *)&changes,sizeof(XkbChangesRec)); + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + sli->explicitState&= ~affect; + sli->explicitState|= (affect&values); + XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause); + + side_affected= 0; + if (changes.state_changes!=0) + side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,False); + if (changes.ctrls.enabled_ctrls_changes) + side_affected|= sli->usesControls; + + if (side_affected) { + XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause); + affect|= side_affected; + } + XkbSendNotification(dev,&changes,cause); + if (ed.reason) + XkbSendExtensionDeviceNotify(dev,cause->client,&ed); + if (changes.state_changes || changes.ctrls.enabled_ctrls_changes) + XkbUpdateAllDeviceIndicators(NULL,cause); + return; +} + +/***====================================================================***/ + + /* + * Bool + * ComputeAutoState(map,state,ctrls) + * + * This function reports the effect of applying the specified + * indicator map given the specified state and controls, as + * described in section 9.2 of the XKB protocol specification. + */ + +static Bool +#if NeedFunctionPrototypes +ComputeAutoState( XkbIndicatorMapPtr map, + XkbStatePtr state, + XkbControlsPtr ctrls) +#else +ComputeAutoState(map,state,ctrls) + XkbIndicatorMapPtr map; + XkbStatePtr state; + XkbControlsPtr ctrls; +#endif +{ +Bool on; +CARD8 mods,group; + + on= False; + mods= group= 0; + if (map->which_mods&XkbIM_UseAnyMods) { + if (map->which_mods&XkbIM_UseBase) + mods|= state->base_mods; + if (map->which_mods&XkbIM_UseLatched) + mods|= state->latched_mods; + if (map->which_mods&XkbIM_UseLocked) + mods|= state->locked_mods; + if (map->which_mods&XkbIM_UseEffective) + mods|= state->mods; + if (map->which_mods&XkbIM_UseCompat) + mods|= state->compat_state; + on = ((map->mods.mask&mods)!=0); + on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0)); + } + if (map->which_groups&XkbIM_UseAnyGroup) { + if (map->which_groups&XkbIM_UseBase) + group|= (1L << state->base_group); + if (map->which_groups&XkbIM_UseLatched) + group|= (1L << state->latched_group); + if (map->which_groups&XkbIM_UseLocked) + group|= (1L << state->locked_group); + if (map->which_groups&XkbIM_UseEffective) + group|= (1L << state->group); + on = on||(((map->groups&group)!=0)||(map->groups==0)); + } + if (map->ctrls) + on = on||(ctrls->enabled_ctrls&map->ctrls); + return on; +} + +/***====================================================================***/ + + /* + * void + * XkbUpdateIndicators(dev,update,check_edevs,changes,cause) + * + * Applies the indicator maps for any indicators specified in + * 'update' from the default keyboard feedback on the device + * specified by 'dev.' + * + * If 'changes' is NULL, this function generates and XKB events + * required to report the necessary changes, otherwise it simply + * notes the indicators with changed state. + * + * If 'check_edevs' is True, this function also checks the indicator + * maps for any open extension devices that have them, and updates + * the state of any extension device indicators as necessary. + */ + +void +#if NeedFunctionPrototypes +XkbUpdateIndicators( DeviceIntPtr dev, + register CARD32 update, + Bool check_edevs, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbUpdateIndicators(dev,update,check_edevs,changes,cause) + DeviceIntPtr dev; + register CARD32 update; + Bool check_edevs; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause); + if (check_edevs) + XkbUpdateAllDeviceIndicators(changes,cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause) +#else +XkbUpdateAllDeviceIndicators(changes,cause) + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr edev; +XkbSrvLedInfoPtr sli; + + for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) { + if (edev->kbdfeed) { + KbdFeedbackPtr kf; + for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL)) + continue; + sli= kf->xkb_sli; + XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, + changes,cause); + + } + } + if (edev->leds) { + LedFeedbackPtr lf; + for (lf=edev->leds;lf!=NULL;lf=lf->next) { + if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL)) + continue; + sli= lf->xkb_sli; + XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, + changes,cause); + + } + } + } + return; +} + +/***====================================================================***/ + + /* + * void + * XkbCheckIndicatorMaps(dev,sli,which) + * + * Updates the 'indicator accelerators' for the indicators specified + * by 'which' in the feedback specified by 'sli.' The indicator + * accelerators are internal to the server and are used to simplify + * and speed up the process of figuring out which indicators might + * be affected by a particular change in keyboard state or controls. + */ + +void +#if NeedFunctionPrototypes +XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which) +#else +XkbCheckIndicatorMaps(dev,sli,which) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned which; +#endif +{ +register unsigned i,bit; +XkbIndicatorMapPtr map; +XkbDescPtr xkb; + + if ((sli->flags&XkbSLI_HasOwnState)==0) + dev= (DeviceIntPtr)LookupKeyboardDevice(); + + sli->usesBase&= ~which; + sli->usesLatched&= ~which; + sli->usesLocked&= ~which; + sli->usesEffective&= ~which; + sli->usesCompat&= ~which; + sli->usesControls&= ~which; + sli->mapsPresent&= ~which; + + xkb= dev->key->xkbInfo->desc; + for (i=0,bit=1,map=sli->maps;imapsPresent|= bit; + + what= (map->which_mods|map->which_groups); + if (what&XkbIM_UseBase) + sli->usesBase|= bit; + if (what&XkbIM_UseLatched) + sli->usesLatched|= bit; + if (what&XkbIM_UseLocked) + sli->usesLocked|= bit; + if (what&XkbIM_UseEffective) + sli->usesEffective|= bit; + if (what&XkbIM_UseCompat) + sli->usesCompat|= bit; + if (map->ctrls) + sli->usesControls|= bit; + + map->mods.mask= map->mods.real_mods; + if (map->mods.vmods!=0) { + map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods); + } + } + } + sli->usedComponents= 0; + if (sli->usesBase) + sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask; + if (sli->usesLatched) + sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask; + if (sli->usesLocked) + sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask; + if (sli->usesEffective) + sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask; + if (sli->usesCompat) + sli->usedComponents|= XkbCompatStateMask; + return; +} + +/***====================================================================***/ + + /* + * XkbSrvLedInfoPtr + * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) + * + * Allocates an XkbSrvLedInfoPtr for the feedback specified by either + * 'kf' or 'lf' on the keyboard specified by 'dev.' + * + * If 'needed_parts' is non-zero, this function makes sure that any + * of the parts speicified therein are allocated. + */ +XkbSrvLedInfoPtr +#if NeedFunctionPrototypes +XkbAllocSrvLedInfo( DeviceIntPtr dev, + KbdFeedbackPtr kf, + LedFeedbackPtr lf, + unsigned needed_parts) +#else +XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) + DeviceIntPtr dev; + KbdFeedbackPtr kf; + LedFeedbackPtr lf; + unsigned needed_parts; +#endif +{ +XkbSrvLedInfoPtr sli; +Bool checkAccel; +Bool checkNames; + + sli= NULL; + checkAccel= checkNames= False; + if ((kf!=NULL)&&(kf->xkb_sli==NULL)) { + kf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); + if (sli==NULL) + return NULL; /* ALLOCATION ERROR */ + if (dev->key && dev->key->xkbInfo) + sli->flags= XkbSLI_HasOwnState; + else sli->flags= 0; + sli->class= KbdFeedbackClass; + sli->id= kf->ctrl.id; + sli->fb.kf= kf; + + sli->autoState= 0; + sli->explicitState= kf->ctrl.leds; + sli->effectiveState= kf->ctrl.leds; + + if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) { + XkbDescPtr xkb; + xkb= dev->key->xkbInfo->desc; + sli->flags|= XkbSLI_IsDefault; + sli->physIndicators= xkb->indicators->phys_indicators; + sli->names= xkb->names->indicators; + sli->maps= xkb->indicators->maps; + checkNames= checkAccel= True; + } + else { + sli->physIndicators= XkbAllIndicatorsMask; + sli->names= NULL; + sli->maps= NULL; + } + } + else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) { + XkbDescPtr xkb; + xkb= dev->key->xkbInfo->desc; + sli->physIndicators= xkb->indicators->phys_indicators; + if (xkb->names->indicators!=sli->names) { + checkNames= True; + sli->names= xkb->names->indicators; + } + if (xkb->indicators->maps!=sli->maps) { + checkAccel= True; + sli->maps= xkb->indicators->maps; + } + } + else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) { + lf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); + if (sli==NULL) + return NULL; /* ALLOCATION ERROR */ + if (dev->key && dev->key->xkbInfo) + sli->flags= XkbSLI_HasOwnState; + else sli->flags= 0; + sli->class= LedFeedbackClass; + sli->id= lf->ctrl.id; + sli->fb.lf= lf; + + sli->physIndicators= lf->ctrl.led_mask; + sli->autoState= 0; + sli->explicitState= lf->ctrl.led_values; + sli->effectiveState= lf->ctrl.led_values; + sli->maps= NULL; + sli->names= NULL; + } + if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) + sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); + if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) + sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); + if (checkNames) { + register unsigned i,bit; + sli->namesPresent= 0; + for (i=0,bit=1;inames[i]!=None) + sli->namesPresent|= bit; + } + } + if (checkAccel) + XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask); + return sli; +} + +void +#if NeedFunctionPrototypes +XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli) +#else +XkbFreeSrvLedInfo(sli) + XkbSrvLedInfoPtr sli; +#endif +{ + if ((sli->flags&XkbSLI_IsDefault)==0) { + if (sli->maps) _XkbFree(sli->maps); + if (sli->names) _XkbFree(sli->names); + } + sli->maps= NULL; + sli->names= NULL; + _XkbFree(sli); + return; +} + + +/***====================================================================***/ + + /* + * XkbSrvLedInfoPtr + * XkbFindSrvLedInfo(dev,class,id,needed_parts) + * + * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id' + * on the device specified by 'dev.' If the class and id specify + * a valid device feedback, this function returns the existing + * feedback or allocates a new one. + * + */ + +XkbSrvLedInfoPtr +#if NeedFunctionPrototypes +XkbFindSrvLedInfo( DeviceIntPtr dev, + unsigned class, + unsigned id, + unsigned needed_parts) +#else +XkbFindSrvLedInfo(dev,class,id,needed_parts) + DeviceIntPtr dev; + unsigned class; + unsigned id; + unsigned needed_parts; +#endif +{ +XkbSrvLedInfoPtr sli; + + /* optimization to check for most common case */ + if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) { + XkbSrvLedInfoPtr sli; + sli= dev->kbdfeed->xkb_sli; + if (dev->kbdfeed->xkb_sli==NULL) { + sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts); + dev->kbdfeed->xkb_sli= sli; + } + return dev->kbdfeed->xkb_sli; + } + + sli= NULL; + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + else return NULL; + } + if (class==KbdFeedbackClass) { + KbdFeedbackPtr kf; + for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) { + if (kf->xkb_sli==NULL) + kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts); + sli= kf->xkb_sli; + break; + } + } + } + else if (class==LedFeedbackClass) { + LedFeedbackPtr lf; + for (lf=dev->leds;lf!=NULL;lf=lf->next) { + if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) { + if (lf->xkb_sli==NULL) + lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts); + sli= lf->xkb_sli; + break; + } + } + } + if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) + sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); + if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) + sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); + return sli; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFlushLedEvents( DeviceIntPtr dev, + DeviceIntPtr kbd, + XkbSrvLedInfoPtr sli, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause) + DeviceIntPtr dev; + DeviceIntPtr kbd; + XkbSrvLedInfoPtr sli; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ + if (changes) { + if (changes->indicators.state_changes) + XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); + XkbSendNotification(kbd,changes,cause); + bzero((char *)changes,sizeof(XkbChangesRec)); + } + if (ed && (ed->reason)) { + if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask)) + XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); + XkbSendExtensionDeviceNotify(dev,cause->client,ed); + } + bzero((char *)ed,sizeof(XkbExtensionDeviceNotify)); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbApplyLedNameChanges( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_names, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbApplyLedNameChanges(dev,sli,changed_names,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned changed_names; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; + + if (changed_names==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->names.changed|= XkbIndicatorNamesMask; + changes->names.changed_indicators|= changed_names; + } + + ed->reason|= (XkbXI_IndicatorNamesMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorNamesMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} +/***====================================================================***/ + + /* + * void + * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause) + * + * Handles all of the secondary effects of the changes to the + * feedback specified by 'sli' on the device specified by 'dev.' + * + * If 'changed_maps' specifies any indicators, this function generates + * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify + * events to report the changes, and recalculates the effective + * state of each indicator with a changed map. If any indicators + * change state, the server generates XkbExtensionDeviceNotify and + * XkbIndicatorStateNotify events as appropriate. + * + * If 'changes' is non-NULL, this function updates it to reflect + * any changes to the keyboard state or controls or to the 'core' + * indicator names, maps, or state. If 'changes' is NULL, this + * function generates XKB events as needed to report the changes. + * If 'dev' is not a keyboard device, any changes are reported + * for the core keyboard. + * + * The 'cause' specifies the reason for the event (key event or + * request) for the change, as reported in some XKB events. + */ + +void +#if NeedFunctionPrototypes +XkbApplyLedMapChanges( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_maps, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbApplyLedMapChanges(dev,sli,changed_maps,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned changed_maps; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; + + if (changed_maps==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->indicators.map_changes|= changed_maps; + } + + XkbCheckIndicatorMaps(dev,sli,changed_maps); + + ed->reason|= (XkbXI_IndicatorMapsMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorMapsMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + + XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause); + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbApplyLedStateChanges(DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_leds, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbApplyLedStateChanges(dev,sli,changed_leds,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned changed_leds; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; +register unsigned i,bit,affected; +XkbIndicatorMapPtr map; +unsigned oldState; +Bool kb_changed; + + if (changed_leds==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + xkbi= kbd->key->xkbInfo; + + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + + kb_changed= False; + affected= changed_leds; + oldState= sli->effectiveState; + for (i=0,bit=1;(imaps[i]; + if (map->flags&XkbIM_NoExplicit) { + sli->explicitState&= ~bit; + continue; + } + if (map->flags&XkbIM_LEDDrivesKB) { + Bool on= ((sli->explicitState&bit)!=0); + if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes)) + kb_changed= True; + } + } + sli->effectiveState= (sli->autoState|sli->explicitState); + affected= sli->effectiveState^oldState; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) + changes->indicators.state_changes|= affected; + if (affected) { + ed->reason|= (XkbXI_IndicatorStateMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorStateMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + } + + if (kb_changed) { + XkbComputeDerivedState(kbd->key->xkbInfo); + XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause); + } + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + if (kb_changed) + XkbUpdateAllDeviceIndicators(NULL,cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbUpdateLedAutoState( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned maps_to_check, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbUpdateLedAutoState(dev,sli,maps_to_check,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned maps_to_check; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr kbd; +XkbStatePtr state; +XkbControlsPtr ctrls; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; +register unsigned i,bit,affected; +register XkbIndicatorMapPtr map; +unsigned oldState; + + if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0)) + return; + + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + state= &kbd->key->xkbInfo->state; + ctrls= kbd->key->xkbInfo->desc->ctrls; + affected= maps_to_check; + oldState= sli->effectiveState; + sli->autoState&= ~affected; + for (i=0,bit=1;(imaps[i]; + if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls)) + sli->autoState|= bit; + } + sli->effectiveState= (sli->autoState|sli->explicitState); + affected= sli->effectiveState^oldState; + if (affected==0) + return; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->indicators.state_changes|= affected; + } + + ed->reason|= (XkbXI_IndicatorStateMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorStateMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_UpdateButtonVMods( XkbDescPtr xkb, + unsigned num_btns, + XkbAction * acts, + unsigned changed, + xkbExtensionDeviceNotify * ed_inout) +#else +_UpdateButtonVMods(xkb,num_btns,acts,changed,ed_inout) + XkbDescPtr xkb; + unsigned num_btns; + XkbAction * acts; + unsigned changed; + xkbExtensionDeviceNotify * ed_inout; +#endif +{ +register int i; + + for (i=0;iany.type!=XkbSA_NoAction)&& + XkbUpdateActionVirtualMods(xkb,acts,changed)) { + if ((ed_inout->reason&XkbXI_ButtonActionsMask)==0) { + ed_inout->reason|= XkbXI_ButtonActionsMask; + ed_inout->firstBtn= i; + ed_inout->nBtns= 1; + } + else { + ed_inout->nBtns= (i-ed_inout->firstBtn)+1; + } + } + } + return; +} + +static void +#if NeedFunctionPrototypes +_UpdateMapVMods( XkbDescPtr xkb, + register XkbIndicatorMapPtr map, + unsigned changed_vmods, + unsigned * changed_maps_rtrn) +#else +_UpdateMapVMods(xkb,map,changed_vmods,changed_maps_rtrn) + XkbDescPtr xkb; + register XkbIndicatorMapPtr map; + unsigned changed_vmods; + unsigned * changed_maps_rtrn; +#endif +{ +register int i; + + *changed_maps_rtrn= 0; + for (i=0;imods.vmods&changed_vmods) { + map->mods.mask= map->mods.real_mods; + map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods); + *changed_maps_rtrn|= (1L<id; + if ((dev->button)&&(dev->button->xkb_acts)) { + _UpdateButtonVMods(xkb,dev->button->numButtons, + dev->button->xkb_acts,changed,&ed); + } + if (dev->kbdfeed) { + KbdFeedbackPtr kf; + for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL)) + continue; + sli= kf->xkb_sli; + _UpdateMapVMods(xkb,sli->maps,changed,&changed_maps); + if (changed_maps) { + if (ed.reason&XkbXI_IndicatorsMask) { + XkbSendExtensionDeviceNotify(dev,NULL,&ed); + ed.reason= 0; + ed.firstBtn= ed.nBtns; + } + ed.ledClass= sli->class; + ed.ledID= sli->id; + ed.ledsDefined= sli->namesPresent|sli->mapsPresent; + ed.reason|= XkbXI_IndicatorMapsMask; + XkbUpdateLedAutoState(dev,sli,changed_maps,&ed,NULL,cause); + } + } + } + if (dev->leds) { + LedFeedbackPtr lf; + for (lf=dev->leds;lf!=NULL;lf=lf->next) { + if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL)) + continue; + sli= lf->xkb_sli; + _UpdateMapVMods(xkb,sli->maps,changed,&changed_maps); + if (changed_maps) { + if (ed.reason&XkbXI_IndicatorsMask) { + XkbSendExtensionDeviceNotify(dev,NULL,&ed); + ed.reason= 0; + ed.firstBtn= ed.nBtns; + } + ed.ledClass= sli->class; + ed.ledID= sli->id; + ed.ledsDefined= sli->namesPresent|sli->mapsPresent; + ed.reason|= XkbXI_IndicatorMapsMask; + XkbUpdateLedAutoState(dev,sli,changed_maps,&ed,NULL,cause); + } + } + } + if (ed.reason!=0) + XkbSendExtensionDeviceNotify(dev,NULL,&ed); + return; +} + +void +#if NeedFunctionPrototypes +XkbApplyVModChangesToAllDevices( DeviceIntPtr dev, + XkbDescPtr xkb, + unsigned changed, + XkbEventCausePtr cause) +#else +XkbApplyVModChangesToAllDevices(dev,xkb,changed,cause) + DeviceIntPtr dev; + XkbDescPtr xkb; + unsigned changed; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr edev; + if (dev!=(DeviceIntPtr)LookupKeyboardDevice()) + return; + for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) { + if (edev->key) + continue; + _UpdateDeviceVMods(edev,xkb,changed,cause); + } + for (edev=inputInfo.off_devices;edev!=NULL;edev=edev->next) { + if (edev->key) + continue; + _UpdateDeviceVMods(edev,xkb,changed,cause); + } + return; +} diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c new file mode 100644 index 000000000..907cc3ab5 --- /dev/null +++ b/xkb/xkbPrKeyEv.c @@ -0,0 +1,193 @@ +/* $Xorg: xkbPrKeyEv.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include + + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count) +#else +XkbProcessKeyboardEvent(xE,keybd,count) + xEvent * xE; + DeviceIntPtr keybd; + int count; +#endif +{ +KeyClassPtr keyc = keybd->key; +XkbSrvInfoPtr xkbi; +int key; +XkbBehavior behavior; + + xkbi= keyc->xkbInfo; + key= xE->u.u.detail; +#ifdef DEBUG + if (xkbDebugFlags&0x8) { + ErrorF("XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up")); + } +#endif + + if ( (xkbi->repeatKey==key) && (xE->u.u.type==KeyRelease) && + ((xkbi->desc->ctrls->enabled_ctrls&XkbRepeatKeysMask)==0) ) { + AccessXCancelRepeatKey(xkbi,key); + } + + behavior= xkbi->desc->server->behaviors[key]; + /* The "permanent" flag indicates a hard-wired behavior that occurs */ + /* below XKB, such as a key that physically locks. XKB does not */ + /* do anything to implement the behavior, but it *does* report that */ + /* key is hardwired */ + if ((behavior.type&XkbKB_Permanent)==0) { + switch (behavior.type) { + case XkbKB_Default: + if (( xE->u.u.type == KeyPress ) && + (keyc->down[key>>3] & (1<<(key&7)))) { + XkbLastRepeatEvent= (pointer)xE; + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + xE->u.u.type = KeyPress; + XkbHandleActions(keybd,keybd,xE,count); + XkbLastRepeatEvent= NULL; + return; + } + else if ((xE->u.u.type==KeyRelease) && + (!(keyc->down[key>>3]&(1<<(key&7))))) { + XkbLastRepeatEvent= (pointer)&xE; + xE->u.u.type = KeyPress; + XkbHandleActions(keybd,keybd,xE,count); + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + XkbLastRepeatEvent= NULL; + return; + } + break; + case XkbKB_Lock: + if ( xE->u.u.type == KeyRelease ) + return; + else { + int bit= 1<<(key&7); + if ( keyc->down[key>>3]&bit ) + xE->u.u.type= KeyRelease; + } + break; + case XkbKB_RadioGroup: + if ( xE->u.u.type == KeyRelease ) + return; + else { + unsigned ndx= (behavior.data&(~XkbKB_RGAllowNone)); + if ( ndxnRadioGroups ) { + XkbRadioGroupPtr rg; + + rg = &xkbi->radioGroups[ndx]; + if ( rg->currentDown == xE->u.u.detail ) { + if (behavior.data&XkbKB_RGAllowNone) { + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + rg->currentDown= 0; + } + return; + } + if ( rg->currentDown!=0 ) { + int key = xE->u.u.detail; + xE->u.u.type= KeyRelease; + xE->u.u.detail= rg->currentDown; + XkbHandleActions(keybd,keybd,xE,count); + xE->u.u.type= KeyPress; + xE->u.u.detail= key; + } + rg->currentDown= key; + } + else ErrorF("InternalError! Illegal radio group %d\n",ndx); + } + break; + case XkbKB_Overlay1: case XkbKB_Overlay2: + { + unsigned which; + if (behavior.type==XkbKB_Overlay1) which= XkbOverlay1Mask; + else which= XkbOverlay2Mask; + if ( (xkbi->desc->ctrls->enabled_ctrls&which)==0 ) + break; + if ((behavior.data>=xkbi->desc->min_key_code)&& + (behavior.data<=xkbi->desc->max_key_code)) { + xE->u.u.detail= behavior.data; + /* 9/11/94 (ef) -- XXX! need to match release with */ + /* press even if the state of the */ + /* corresponding overlay control */ + /* changes while the key is down */ + } + } + break; + default: + ErrorF("unknown key behavior 0x%04x\n",behavior.type); + break; + } + } + XkbHandleActions(keybd,keybd,xE,count); + return; +} + +void +#if NeedFunctionPrototypes +ProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count) +#else +ProcessKeyboardEvent(xE,keybd,count) + xEvent * xE; + DeviceIntPtr keybd; + int count; +#endif +{ +KeyClassPtr keyc = keybd->key; +XkbSrvInfoPtr xkbi; + + xkbi= keyc->xkbInfo; + +#ifdef DEBUG + if (xkbDebugFlags&0x8) { + int key= xE->u.u.detail; + ErrorF("PKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up")); + } +#endif + if ((xkbi->desc->ctrls->enabled_ctrls&XkbAllFilteredEventsMask)==0) + XkbProcessKeyboardEvent(xE,keybd,count); + else if (xE->u.u.type==KeyPress) + AccessXFilterPressEvent(xE,keybd,count); + else if (xE->u.u.type==KeyRelease) + AccessXFilterReleaseEvent(xE,keybd,count); + return; +} + diff --git a/xkb/xkbPrOtherEv.c b/xkb/xkbPrOtherEv.c new file mode 100644 index 000000000..fd24283f5 --- /dev/null +++ b/xkb/xkbPrOtherEv.c @@ -0,0 +1,88 @@ +/* $Xorg: xkbPrOtherEv.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#define NEED_EVENTS 1 +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" + +#include "XI.h" +#include "XIproto.h" + +extern void ProcessOtherEvent( +#if NeedFunctionPrototypes + xEvent * /* xE */, + DeviceIntPtr /* dev */, + int /* count */ +#endif +); + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbProcessOtherEvent(xEvent *xE,DeviceIntPtr dev,int count) +#else +XkbProcessOtherEvent(xE,dev,count) + xEvent * xE; + DeviceIntPtr dev; + int count; +#endif +{ +Bool xkbCares,isBtn; + + xkbCares= True; + isBtn= False; + switch ( xE->u.u.type ) { + case KeyPress: xE->u.u.type= DeviceKeyPress; break; + case KeyRelease: xE->u.u.type= DeviceKeyRelease; break; + case ButtonPress: xE->u.u.type= DeviceButtonPress; + isBtn= True; + break; + case ButtonRelease: xE->u.u.type= DeviceButtonRelease; + isBtn= True; + break; + default: xkbCares= False; break; + } + if (xkbCares) { + if ((!isBtn)||((dev->button)&&(dev->button->xkb_acts))) { + DeviceIntPtr kbd; + if (dev->key) kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + XkbHandleActions(dev,kbd,xE,count); + return; + } + } + ProcessOtherEvent(xE,dev,count); + return; +} + diff --git a/xkb/xkbSwap.c b/xkb/xkbSwap.c new file mode 100644 index 000000000..c9df88f7f --- /dev/null +++ b/xkb/xkbSwap.c @@ -0,0 +1,759 @@ +/* $Xorg: xkbSwap.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include "stdio.h" +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include "XKBstr.h" +#include "extnsionst.h" + +#if NeedFunctionPrototypes +#define PROC_EXTERN(pfunc) extern int pfunc(ClientPtr) +#else +#define PROC_EXTERN(pfunc) extern int pfunc() +#endif + +PROC_EXTERN(ProcXkbUseExtension); +PROC_EXTERN(ProcXkbSelectEvents); +PROC_EXTERN(ProcXkbBell); +PROC_EXTERN(ProcXkbGetState); +PROC_EXTERN(ProcXkbLatchLockState); +PROC_EXTERN(ProcXkbGetControls); +PROC_EXTERN(ProcXkbSetControls); +PROC_EXTERN(ProcXkbGetMap); +PROC_EXTERN(ProcXkbSetMap); +PROC_EXTERN(ProcXkbGetCompatMap); +PROC_EXTERN(ProcXkbSetCompatMap); +PROC_EXTERN(ProcXkbGetIndicatorState); +PROC_EXTERN(ProcXkbGetIndicatorMap); +PROC_EXTERN(ProcXkbSetIndicatorMap); +PROC_EXTERN(ProcXkbGetNamedIndicator); +PROC_EXTERN(ProcXkbSetNamedIndicator); +PROC_EXTERN(ProcXkbGetNames); +PROC_EXTERN(ProcXkbSetNames); +PROC_EXTERN(ProcXkbGetGeometry); +PROC_EXTERN(ProcXkbSetGeometry); +PROC_EXTERN(ProcXkbPerClientFlags); +PROC_EXTERN(ProcXkbListComponents); +PROC_EXTERN(ProcXkbGetKbdByName); +PROC_EXTERN(ProcXkbGetDeviceInfo); +PROC_EXTERN(ProcXkbSetDeviceInfo); +PROC_EXTERN(ProcXkbSetDebuggingFlags); + + /* + * REQUEST SWAPPING + */ +static int +#if NeedFunctionPrototypes +SProcXkbUseExtension(ClientPtr client) +#else +SProcXkbUseExtension(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbUseExtensionReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbUseExtensionReq); + swaps(&stuff->wantedMajor,n); + swaps(&stuff->wantedMinor,n); + return ProcXkbUseExtension(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSelectEvents(ClientPtr client) +#else +SProcXkbSelectEvents(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSelectEventsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->affectWhich,n); + swaps(&stuff->clear,n); + swaps(&stuff->selectAll,n); + swaps(&stuff->affectMap,n); + swaps(&stuff->map,n); + if (stuff->affectWhich&(~XkbMapNotifyMask)!=0) { + union { + BOOL *b; + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } from; + register unsigned bit,ndx,maskLeft,dataLeft,size; + + from.c8= (CARD8 *)&stuff[1]; + dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq); + maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask)); + for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) { + if (((bit&maskLeft)==0)||(ndx==XkbMapNotify)) + continue; + maskLeft&= ~bit; + if ((stuff->selectAll&bit)||(stuff->clear&bit)) + continue; + switch (ndx) { + case XkbNewKeyboardNotify: + case XkbStateNotify: + case XkbNamesNotify: + case XkbAccessXNotify: + case XkbExtensionDeviceNotify: + size= 2; + break; + case XkbControlsNotify: + case XkbIndicatorStateNotify: + case XkbIndicatorMapNotify: + size= 4; + break; + case XkbBellNotify: + case XkbActionMessage: + case XkbCompatMapNotify: + size= 1; + break; + default: + client->errorValue = _XkbErrCode2(0x1,bit); + return BadValue; + } + if (dataLeft<(size*2)) + return BadLength; + if (size==2) { + swaps(&from.c16[0],n); + swaps(&from.c16[1],n); + } + else if (size==4) { + swapl(from.c32[0],n); + swapl(from.c32[1],n); + } + else { + size= 2; + } + from.c8+= (size*2); + dataLeft-= (size*2); + } + if (dataLeft>2) { + ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + } + return ProcXkbSelectEvents(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbBell(ClientPtr client) +#else +SProcXkbBell(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbBellReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbBellReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->bellClass,n); + swaps(&stuff->bellID,n); + swapl(&stuff->name,n); + swapl(&stuff->window,n); + swaps(&stuff->pitch,n); + swaps(&stuff->duration,n); + return ProcXkbBell(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetState(ClientPtr client) +#else +SProcXkbGetState(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetStateReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetState(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbLatchLockState(ClientPtr client) +#else +SProcXkbLatchLockState(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbLatchLockStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbLatchLockStateReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->groupLatch,n); + return ProcXkbLatchLockState(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetControls(ClientPtr client) +#else +SProcXkbGetControls(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetControlsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetControlsReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetControls(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetControls(ClientPtr client) +#else +SProcXkbSetControls(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetControlsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbSetControlsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->affectInternalVMods,n); + swaps(&stuff->internalVMods,n); + swaps(&stuff->affectIgnoreLockVMods,n); + swaps(&stuff->ignoreLockVMods,n); + swaps(&stuff->axOptions,n); + swapl(&stuff->affectEnabledCtrls,n); + swapl(&stuff->enabledCtrls,n); + swapl(&stuff->changeCtrls,n); + swaps(&stuff->repeatDelay,n); + swaps(&stuff->repeatInterval,n); + swaps(&stuff->slowKeysDelay,n); + swaps(&stuff->debounceDelay,n); + swaps(&stuff->mkDelay,n); + swaps(&stuff->mkInterval,n); + swaps(&stuff->mkTimeToMax,n); + swaps(&stuff->mkMaxSpeed,n); + swaps(&stuff->mkCurve,n); + swaps(&stuff->axTimeout,n); + swapl(&stuff->axtCtrlsMask,n); + swapl(&stuff->axtCtrlsValues,n); + swaps(&stuff->axtOptsMask,n); + swaps(&stuff->axtOptsValues,n); + return ProcXkbSetControls(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetMap(ClientPtr client) +#else +SProcXkbGetMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->full,n); + swaps(&stuff->partial,n); + swaps(&stuff->virtualMods,n); + return ProcXkbGetMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetMap(ClientPtr client) +#else +SProcXkbSetMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->present,n); + swaps(&stuff->flags,n); + swaps(&stuff->totalSyms,n); + swaps(&stuff->totalActs,n); + swaps(&stuff->virtualMods,n); + return ProcXkbSetMap(client); +} + + +static int +#if NeedFunctionPrototypes +SProcXkbGetCompatMap(ClientPtr client) +#else +SProcXkbGetCompatMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetCompatMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetCompatMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->firstSI,n); + swaps(&stuff->nSI,n); + return ProcXkbGetCompatMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetCompatMap(ClientPtr client) +#else +SProcXkbSetCompatMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetCompatMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->firstSI,n); + swaps(&stuff->nSI,n); + return ProcXkbSetCompatMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetIndicatorState(ClientPtr client) +#else +SProcXkbGetIndicatorState(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetIndicatorStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetIndicatorState(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetIndicatorMap(ClientPtr client) +#else +SProcXkbGetIndicatorMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetIndicatorMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbGetIndicatorMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetIndicatorMap(ClientPtr client) +#else +SProcXkbSetIndicatorMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetIndicatorMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbSetIndicatorMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetNamedIndicator(ClientPtr client) +#else +SProcXkbGetNamedIndicator(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetNamedIndicatorReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + swapl(&stuff->indicator,n); + return ProcXkbGetNamedIndicator(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetNamedIndicator(ClientPtr client) +#else +SProcXkbSetNamedIndicator(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetNamedIndicatorReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + swapl(&stuff->indicator,n); + swaps(&stuff->virtualMods,n); + swapl(&stuff->ctrls,n); + return ProcXkbSetNamedIndicator(client); +} + + +static int +#if NeedFunctionPrototypes +SProcXkbGetNames(ClientPtr client) +#else +SProcXkbGetNames(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetNamesReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetNamesReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbGetNames(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetNames(ClientPtr client) +#else +SProcXkbSetNames(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetNamesReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->virtualMods,n); + swapl(&stuff->which,n); + swapl(&stuff->indicators,n); + swaps(&stuff->totalKTLevelNames,n); + return ProcXkbSetNames(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetGeometry(ClientPtr client) +#else +SProcXkbGetGeometry(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetGeometryReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetGeometryReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->name,n); + return ProcXkbGetGeometry(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetGeometry(ClientPtr client) +#else +SProcXkbSetGeometry(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetGeometryReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->name,n); + swaps(&stuff->widthMM,n); + swaps(&stuff->heightMM,n); + swaps(&stuff->nProperties,n); + swaps(&stuff->nColors,n); + swaps(&stuff->nDoodads,n); + swaps(&stuff->nKeyAliases,n); + return ProcXkbSetGeometry(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbPerClientFlags(ClientPtr client) +#else +SProcXkbPerClientFlags(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbPerClientFlagsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->change,n); + swapl(&stuff->value,n); + swapl(&stuff->ctrlsToChange,n); + swapl(&stuff->autoCtrls,n); + swapl(&stuff->autoCtrlValues,n); + return ProcXkbPerClientFlags(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbListComponents(ClientPtr client) +#else +SProcXkbListComponents(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbListComponentsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->maxNames,n); + return ProcXkbListComponents(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetKbdByName(ClientPtr client) +#else +SProcXkbGetKbdByName(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetKbdByNameReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->want,n); + swaps(&stuff->need,n); + return ProcXkbGetKbdByName(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetDeviceInfo(ClientPtr client) +#else +SProcXkbGetDeviceInfo(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetDeviceInfoReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->wanted,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + return ProcXkbGetDeviceInfo(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetDeviceInfo(ClientPtr client) +#else +SProcXkbSetDeviceInfo(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetDeviceInfoReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->change,n); + swaps(&stuff->nDeviceLedFBs,n); + return ProcXkbSetDeviceInfo(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetDebuggingFlags(ClientPtr client) +#else +SProcXkbSetDebuggingFlags(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetDebuggingFlagsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); + swapl(&stuff->affectFlags,n); + swapl(&stuff->flags,n); + swapl(&stuff->affectCtrls,n); + swapl(&stuff->ctrls,n); + swaps(&stuff->msgLength,n); + return ProcXkbSetDebuggingFlags(client); +} + +int +#if NeedFunctionPrototypes +SProcXkbDispatch (ClientPtr client) +#else +SProcXkbDispatch (client) + ClientPtr client; +#endif +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_kbUseExtension: + return SProcXkbUseExtension(client); + case X_kbSelectEvents: + return SProcXkbSelectEvents(client); + case X_kbBell: + return SProcXkbBell(client); + case X_kbGetState: + return SProcXkbGetState(client); + case X_kbLatchLockState: + return SProcXkbLatchLockState(client); + case X_kbGetControls: + return SProcXkbGetControls(client); + case X_kbSetControls: + return SProcXkbSetControls(client); + case X_kbGetMap: + return SProcXkbGetMap(client); + case X_kbSetMap: + return SProcXkbSetMap(client); + case X_kbGetCompatMap: + return SProcXkbGetCompatMap(client); + case X_kbSetCompatMap: + return SProcXkbSetCompatMap(client); + case X_kbGetIndicatorState: + return SProcXkbGetIndicatorState(client); + case X_kbGetIndicatorMap: + return SProcXkbGetIndicatorMap(client); + case X_kbSetIndicatorMap: + return SProcXkbSetIndicatorMap(client); + case X_kbGetNamedIndicator: + return SProcXkbGetNamedIndicator(client); + case X_kbSetNamedIndicator: + return SProcXkbSetNamedIndicator(client); + case X_kbGetNames: + return SProcXkbGetNames(client); + case X_kbSetNames: + return SProcXkbSetNames(client); + case X_kbGetGeometry: + return SProcXkbGetGeometry(client); + case X_kbSetGeometry: + return SProcXkbSetGeometry(client); + case X_kbPerClientFlags: + return SProcXkbPerClientFlags(client); + case X_kbListComponents: + return SProcXkbListComponents(client); + case X_kbGetKbdByName: + return SProcXkbGetKbdByName(client); + case X_kbGetDeviceInfo: + return SProcXkbGetDeviceInfo(client); + case X_kbSetDeviceInfo: + return SProcXkbSetDeviceInfo(client); + case X_kbSetDebuggingFlags: + return SProcXkbSetDebuggingFlags(client); + default: + return BadRequest; + } +} diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c new file mode 100644 index 000000000..05a817ba3 --- /dev/null +++ b/xkb/xkbUtils.c @@ -0,0 +1,1141 @@ +/* $Xorg: xkbUtils.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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. + +********************************************************/ + +#include +#include +#include +#define NEED_EVENTS 1 +#include +#include +#define XK_CYRILLIC +#include +#include "misc.h" +#include "inputstr.h" + +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "extensions/XKBgeom.h" + +#ifdef MODE_SWITCH +extern Bool noKME; /* defined in os/utils.c */ +#endif + + int XkbDisableLockActions = 0; + +/***====================================================================***/ + +#ifndef RETURN_SHOULD_REPEAT +#if (defined(__osf__) && defined(__alpha)) +#define RETURN_SHOULD_REPEAT 1 +#else +#define RETURN_SHOULD_REPEAT 0 +#endif +#endif + +/***====================================================================***/ + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupAnyDevice(int id,int *why_rtrn) +#else +_XkbLookupAnyDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + dev= (DeviceIntPtr)LookupKeyboardDevice(); + if ((id==XkbUseCoreKbd)||(dev->id==id)) + return dev; + + dev= (DeviceIntPtr)LookupPointerDevice(); + if ((id==XkbUseCorePtr)||(dev->id==id)) + return dev; + + if (id&(~0xff)) + dev = NULL; + + dev= (DeviceIntPtr)LookupDevice(id); + if (dev!=NULL) + return dev; + if ((!dev)&&(why_rtrn)) + *why_rtrn= XkbErr_BadDevice; + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupKeyboard(int id,int *why_rtrn) +#else +_XkbLookupKeyboard(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if ((!dev->key)||(!dev->key->xkbInfo)) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupBellDevice(int id,int *why_rtrn) +#else +_XkbLookupBellDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if ((!dev->kbdfeed)&&(!dev->bell)) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupLedDevice(int id,int *why_rtrn) +#else +_XkbLookupLedDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if ((!dev->kbdfeed)&&(!dev->leds)) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupButtonDevice(int id,int *why_rtrn) +#else +_XkbLookupButtonDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if (!dev->button) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +void +#if NeedFunctionPrototypes +XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) +#else +XkbSetActionKeyMods(xkb,act,mods) + XkbDescPtr xkb; + XkbAction * act; + unsigned mods; +#endif +{ +register unsigned tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (act->mods.flags&XkbSA_UseModMapMods) + act->mods.real_mods= act->mods.mask= mods; + if ((tmp= XkbModActionVMods(&act->mods))!=0) + act->mods.mask|= XkbMaskForVMask(xkb,tmp); + break; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_UseModMapMods) + act->iso.real_mods= act->iso.mask= mods; + if ((tmp= XkbModActionVMods(&act->iso))!=0) + act->iso.mask|= XkbMaskForVMask(xkb,tmp); + break; + } + return; +} + +unsigned +#if NeedFunctionPrototypes +XkbMaskForVMask(XkbDescPtr xkb,unsigned vmask) +#else +XkbMaskForVMask(xkb,vmask) + XkbDescPtr xkb; + unsigned vmask; +#endif +{ +register int i,bit; +register unsigned mask; + + for (mask=i=0,bit=1;iserver->vmods[i]; + } + return mask; +} + + +Bool +#if NeedFunctionPrototypes +XkbApplyVModChanges( XkbSrvInfoPtr xkbi, + unsigned changed, + XkbChangesPtr changes, + unsigned * needChecksRtrn, + XkbEventCausePtr cause) +#else +XkbApplyVModChanges(xkbi,changed,changes,needChecksRtrn,cause) + XkbSrvInfoPtr xkbi; + unsigned changed; + XkbChangesPtr changes; + unsigned * needChecksRtrn; + XkbEventCausePtr cause; +#endif +{ +XkbDescPtr xkb; +Bool check; + + xkb= xkbi->desc; +#ifdef DEBUG +{ +register unsigned i,bit; + for (i=0,bit=1;iserver->vmods[i]); + } +} +#endif + check= XkbApplyVirtualModChanges(xkb,changed,changes); + XkbApplyVModChangesToAllDevices(xkbi->device,xkb,changed,cause); + + if (needChecksRtrn!=NULL) { + if (check) + *needChecksRtrn= XkbStateNotifyMask|XkbIndicatorStateNotifyMask; + else *needChecksRtrn= 0; + } + else if (check) { + /* 7/12/95 (ef) -- XXX check compatibility and/or indicator state */ + } + return 1; +} + +/***====================================================================***/ + +#if NeedFunctionPrototypes +void +XkbUpdateKeyTypesFromCore( DeviceIntPtr pXDev, + KeyCode first, + CARD8 num, + XkbChangesPtr changes) +#else +void +XkbUpdateKeyTypesFromCore(pXDev,first,num,changes) + DeviceIntPtr pXDev; + KeyCode first; + CARD8 num; + XkbChangesPtr changes; +#endif +{ +XkbDescPtr xkb; +unsigned key,nG,explicit; +KeySymsPtr pCore; +int types[XkbNumKbdGroups]; +KeySym tsyms[XkbMaxSymsPerKey],*syms; +XkbMapChangesPtr mc; + + xkb= pXDev->key->xkbInfo->desc; +#ifdef NOTYET + if (firstmin_key_code) { + if (first>=XkbMinLegalKeyCode) { + xkb->min_key_code= first; + /* 1/12/95 (ef) -- XXX! should zero out the new maps */ + changes->map.changed|= XkbKeycodesMask; +generate a NewKeyboard notify here? + } + } +#endif + if (first+num-1>xkb->max_key_code) { + /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */ + num= xkb->max_key_code-first+1; + } + + mc= (changes?(&changes->map):NULL); + + pCore= &pXDev->key->curKeySyms; + syms= &pCore->map[(first-xkb->min_key_code)*pCore->mapWidth]; + for (key=first; key<(first+num); key++,syms+= pCore->mapWidth) { + explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; + types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); + types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); + types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); + nG= XkbKeyTypesForCoreSymbols(xkb,pCore->mapWidth,syms,explicit,types, + tsyms); + XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); + memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, + XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + } + if (changes->map.changed&XkbKeySymsMask) { + CARD8 oldLast,newLast; + oldLast = changes->map.first_key_sym+changes->map.num_key_syms-1; + newLast = first+num-1; + + if (firstmap.first_key_sym) + changes->map.first_key_sym = first; + if (oldLast>newLast) + newLast= oldLast; + changes->map.num_key_syms = newLast-changes->map.first_key_sym+1; + } + else { + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym = first; + changes->map.num_key_syms = num; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbUpdateDescActions( XkbDescPtr xkb, + KeyCode first, + CARD8 num, + XkbChangesPtr changes) +#else +XkbUpdateDescActions(xkb,first,num,changes) + XkbDescPtr xkb; + KeyCode first; + CARD8 num; + XkbChangesPtr changes; +#endif +{ +register unsigned key; + + for (key=first;key<(first+num);key++) { + XkbApplyCompatMapToKey(xkb,key,changes); + } + + if (changes->map.changed&XkbVirtualModMapMask|XkbModifierMapMask) { + unsigned char newVMods[XkbNumVirtualMods]; + register unsigned bit,i; + unsigned present; + + bzero(newVMods,XkbNumVirtualMods); + present= 0; + for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { + if (xkb->server->vmodmap[key]==0) + continue; + for (i=0,bit=1;iserver->vmodmap[key]) { + present|= bit; + newVMods[i]|= xkb->map->modmap[key]; + } + } + } + for (i=0,bit=1;iserver->vmods[i])) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + xkb->server->vmods[i]= newVMods[i]; + } + } + } + if (changes->map.changed&XkbVirtualModsMask) + XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); + + if (changes->map.changed&XkbKeyActionsMask) { + CARD8 oldLast,newLast; + oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; + newLast = first+num-1; + + if (firstmap.first_key_act) + changes->map.first_key_act = first; + if (newLast>oldLast) + newLast= oldLast; + changes->map.num_key_acts= newLast-changes->map.first_key_act+1; + } + else { + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act = first; + changes->map.num_key_acts = num; + } + return; +} + +#if NeedFunctionPrototypes +void +XkbUpdateActions( DeviceIntPtr pXDev, + KeyCode first, + CARD8 num, + XkbChangesPtr changes, + unsigned * needChecksRtrn, + XkbEventCausePtr cause) +#else +void +XkbUpdateActions(pXDev,first,num,changes,needChecksRtrn,cause) + DeviceIntPtr pXDev; + KeyCode first; + CARD8 num; + XkbChangesPtr changes; + unsigned * needChecksRtrn; + XkbEventCausePtr cause; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +CARD8 * repeat; + + if (needChecksRtrn) + *needChecksRtrn= 0; + xkbi= pXDev->key->xkbInfo; + xkb= xkbi->desc; + repeat= xkb->ctrls->per_key_repeat; + + if (pXDev->kbdfeed) + memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,32); + + XkbUpdateDescActions(xkb,first,num,changes); + + if ((pXDev->kbdfeed)&& + (changes->ctrls.enabled_ctrls_changes&XkbPerKeyRepeatMask)) { + memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, 32); + (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl); + } + return; +} + +void +#if NeedFunctionPrototypes +XkbUpdateCoreDescription(DeviceIntPtr keybd,Bool resize) +#else +XkbUpdateCoreDescription(keybd,resize) + DeviceIntPtr keybd; + Bool resize; +#endif +{ +register int key,tmp; +int maxSymsPerKey,maxKeysPerMod; +int first,last,firstCommon,lastCommon; +XkbDescPtr xkb; +KeyClassPtr keyc; +CARD8 keysPerMod[XkbNumModifiers]; + + if (!keybd || !keybd->key || !keybd->key->xkbInfo) + return; + xkb= keybd->key->xkbInfo->desc; + keyc= keybd->key; + maxSymsPerKey= maxKeysPerMod= 0; + bzero(keysPerMod,sizeof(keysPerMod)); + memcpy(keyc->modifierMap,xkb->map->modmap,xkb->max_key_code+1); + if ((xkb->min_key_code==keyc->curKeySyms.minKeyCode)&& + (xkb->max_key_code==keyc->curKeySyms.maxKeyCode)) { + first= firstCommon= xkb->min_key_code; + last= lastCommon= xkb->max_key_code; + } + else if (resize) { + keyc->curKeySyms.minKeyCode= xkb->min_key_code; + keyc->curKeySyms.maxKeyCode= xkb->max_key_code; + tmp= keyc->curKeySyms.mapWidth*_XkbCoreNumKeys(keyc); + keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); + if (!keyc->curKeySyms.map) + FatalError("Couldn't allocate keysyms\n"); + first= firstCommon= xkb->min_key_code; + last= lastCommon= xkb->max_key_code; + } + else { + if (xkb->min_key_codecurKeySyms.minKeyCode) { + first= xkb->min_key_code; + firstCommon= keyc->curKeySyms.minKeyCode; + } + else { + firstCommon= xkb->min_key_code; + first= keyc->curKeySyms.minKeyCode; + } + if (xkb->max_key_code>keyc->curKeySyms.maxKeyCode) { + lastCommon= keyc->curKeySyms.maxKeyCode; + last= xkb->max_key_code; + } + else { + lastCommon= xkb->max_key_code; + last= keyc->curKeySyms.maxKeyCode; + } + } + + /* determine sizes */ + for (key=first;key<=last;key++) { + if (XkbKeycodeInRange(xkb,key)) { + int nGroups; + int w; + nGroups= XkbKeyNumGroups(xkb,key); + tmp= 0; + if (nGroups>0) { + if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup1Index))<2) + tmp+= 2; + else tmp+= w; + } + if (nGroups>1) { + if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))<2) + tmp+= 2; + else tmp+= w; + } + if (nGroups>2) + tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup3Index); + if (nGroups>3) + tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup4Index); + if (tmp>maxSymsPerKey) + maxSymsPerKey= tmp; + } + if (_XkbCoreKeycodeInRange(keyc,key)) { + if (keyc->modifierMap[key]!=0) { + register unsigned bit,i,mask; + mask= keyc->modifierMap[key]; + for (i=0,bit=1;imaxKeysPerMod) + maxKeysPerMod= keysPerMod[i]; + } + } + } + } + } + + if (maxKeysPerMod>0) { + tmp= maxKeysPerMod*XkbNumModifiers; + if (keyc->modifierKeyMap==NULL) + keyc->modifierKeyMap= (KeyCode *)Xcalloc(tmp); + else if (keyc->maxKeysPerModifiermodifierKeyMap= (KeyCode *)Xrealloc(keyc->modifierKeyMap,tmp); + if (keyc->modifierKeyMap==NULL) + FatalError("Couldn't allocate modifierKeyMap in UpdateCore\n"); + bzero(keyc->modifierKeyMap,tmp); + } + else if ((keyc->maxKeysPerModifier>0)&&(keyc->modifierKeyMap!=NULL)) { + Xfree(keyc->modifierKeyMap); + keyc->modifierKeyMap= NULL; + } + keyc->maxKeysPerModifier= maxKeysPerMod; + + if (maxSymsPerKey>0) { + tmp= maxSymsPerKey*_XkbCoreNumKeys(keyc); + keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); + if (keyc->curKeySyms.map==NULL) + FatalError("Couldn't allocate symbols map in UpdateCore\n"); + } + else if ((keyc->curKeySyms.mapWidth>0)&&(keyc->curKeySyms.map!=NULL)) { + _XkbFree(keyc->curKeySyms.map); + keyc->curKeySyms.map= NULL; + } + keyc->curKeySyms.mapWidth= maxSymsPerKey; + + bzero(keysPerMod,sizeof(keysPerMod)); + for (key=firstCommon;key<=lastCommon;key++) { + if (keyc->curKeySyms.map!=NULL) { + KeySym *pCore,*pXKB; + unsigned nGroups,groupWidth,n,nOut; + + nGroups= XkbKeyNumGroups(xkb,key); + n= (key-keyc->curKeySyms.minKeyCode)*maxSymsPerKey; + pCore= &keyc->curKeySyms.map[n]; + bzero(pCore,maxSymsPerKey*sizeof(KeySym)); + pXKB= XkbKeySymsPtr(xkb,key); + nOut= 2; + if (nGroups>0) { + groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index); + if (groupWidth>0) pCore[0]= pXKB[0]; + if (groupWidth>1) pCore[1]= pXKB[1]; + for (n=2;n2) + nOut= groupWidth; + } + pXKB+= XkbKeyGroupsWidth(xkb,key); + nOut+= 2; + if (nGroups>1) { + groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index); + if (groupWidth>0) pCore[2]= pXKB[0]; + if (groupWidth>1) pCore[3]= pXKB[1]; + for (n=2;n2) + nOut+= (groupWidth-2); + } + pXKB+= XkbKeyGroupsWidth(xkb,key); + for (n=XkbGroup3Index;nmodifierMap[key]!=0) { + register unsigned bit,i,mask; + mask= keyc->modifierMap[key]; + for (i=0,bit=1;imodifierKeyMap[tmp]= key; + keysPerMod[i]++; + } + } + } + } +#ifdef MODE_SWITCH + /* Fix up any of the KME stuff if we changed the core description. + */ + if (!noKME) + HandleKeyBinding(keyc, &keyc->curKeySyms); +#endif + return; +} + +void +#if NeedFunctionPrototypes +XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff) +#else +XkbSetRepeatKeys(pXDev,key,onoff) + DeviceIntPtr pXDev; + int key; + int onoff; +#endif +{ + if (pXDev && pXDev->key && pXDev->key->xkbInfo) { + xkbControlsNotify cn; + XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls; + XkbControlsRec old; + old = *ctrls; + + if (key== -1) { /* global autorepeat setting changed */ + if (onoff) ctrls->enabled_ctrls |= XkbRepeatKeysMask; + else ctrls->enabled_ctrls &= ~XkbRepeatKeysMask; + } + else if (pXDev->kbdfeed) { + ctrls->per_key_repeat[key/8] = + pXDev->kbdfeed->ctrl.autoRepeats[key/8]; + } + + if (XkbComputeControlsNotify(pXDev,&old,ctrls,&cn,True)) + XkbSendControlsNotify(pXDev,&cn); + } + return; +} + +#if NeedFunctionPrototypes +void +XkbApplyMappingChange( DeviceIntPtr kbd, + CARD8 request, + KeyCode firstKey, + CARD8 num, + ClientPtr client) +#else +void +XkbApplyMappingChange(kbd,request,firstKey,num,client) + DeviceIntPtr kbd; + CARD8 request; + KeyCode firstKey; + CARD8 num; + ClientPtr client; +#endif +{ +XkbEventCauseRec cause; +XkbChangesRec changes; +unsigned check; + + if (kbd->key->xkbInfo==NULL) + XkbInitDevice(kbd); + bzero(&changes,sizeof(XkbChangesRec)); + check= 0; + if (request==MappingKeyboard) { + XkbSetCauseCoreReq(&cause,X_ChangeKeyboardMapping,client); + XkbUpdateKeyTypesFromCore(kbd,firstKey,num,&changes); + XkbUpdateActions(kbd,firstKey,num,&changes,&check,&cause); + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); + } + else if (request==MappingModifier) { + XkbDescPtr xkb= kbd->key->xkbInfo->desc; + + XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client); + + num = xkb->max_key_code-xkb->min_key_code+1; + memcpy(xkb->map->modmap,kbd->key->modifierMap,xkb->max_key_code+1); + + changes.map.changed|= XkbModifierMapMask; + changes.map.first_modmap_key= xkb->min_key_code; + changes.map.num_modmap_keys= num; + XkbUpdateActions(kbd,xkb->min_key_code,num,&changes,&check,&cause); + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); + } + /* 3/26/94 (ef) -- XXX! Doesn't deal with input extension requests */ + XkbSendNotification(kbd,&changes,&cause); + return; +} + +void +#if NeedFunctionPrototypes +XkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key) +#else +XkbDisableComputedAutoRepeats(dev,key) + DeviceIntPtr dev; + unsigned key; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +xkbMapNotify mn; + + xkbi->desc->server->explicit[key]|= XkbExplicitAutoRepeatMask; + bzero(&mn,sizeof(mn)); + mn.changed= XkbExplicitComponentsMask; + mn.firstKeyExplicit= key; + mn.nKeyExplicit= 1; + XkbSendMapNotify(dev,&mn); + return; +} + +unsigned +#if NeedFunctionPrototypes +XkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new) +#else +XkbStateChangedFlags(old,new) + XkbStatePtr old; + XkbStatePtr new; +#endif +{ +int changed; + + changed=(old->group!=new->group?XkbGroupStateMask:0); + changed|=(old->base_group!=new->base_group?XkbGroupBaseMask:0); + changed|=(old->latched_group!=new->latched_group?XkbGroupLatchMask:0); + changed|=(old->locked_group!=new->locked_group?XkbGroupLockMask:0); + changed|=(old->mods!=new->mods?XkbModifierStateMask:0); + changed|=(old->base_mods!=new->base_mods?XkbModifierBaseMask:0); + changed|=(old->latched_mods!=new->latched_mods?XkbModifierLatchMask:0); + changed|=(old->locked_mods!=new->locked_mods?XkbModifierLockMask:0); + changed|=(old->compat_state!=new->compat_state?XkbCompatStateMask:0); + changed|=(old->grab_mods!=new->grab_mods?XkbGrabModsMask:0); + if (old->compat_grab_mods!=new->compat_grab_mods) + changed|= XkbCompatGrabModsMask; + changed|=(old->lookup_mods!=new->lookup_mods?XkbLookupModsMask:0); + if (old->compat_lookup_mods!=new->compat_lookup_mods) + changed|= XkbCompatLookupModsMask; + changed|=(old->ptr_buttons!=new->ptr_buttons?XkbPointerButtonMask:0); + return changed; +} + +void +#if NeedFunctionPrototypes +XkbComputeCompatState(XkbSrvInfoPtr xkbi) +#else +XkbComputeCompatState(xkbi) + XkbSrvInfoPtr xkbi; +#endif +{ +CARD16 grp_mask; +XkbStatePtr state= &xkbi->state; +XkbCompatMapPtr map; + + map= xkbi->desc->compat; + grp_mask= map->groups[state->group].mask; + state->compat_state = state->mods|grp_mask; + state->compat_lookup_mods= state->lookup_mods|grp_mask; + + if (xkbi->desc->ctrls->enabled_ctrls&XkbIgnoreGroupLockMask) + grp_mask= map->groups[state->base_group].mask; + state->compat_grab_mods= state->grab_mods|grp_mask; + return; +} + +unsigned +#if NeedFunctionPrototypes +XkbAdjustGroup(int group,XkbControlsPtr ctrls) +#else +XkbAdjustGroup(group,ctrls) + int group; + XkbControlsPtr ctrls; +#endif +{ +unsigned act; + + act= XkbOutOfRangeGroupAction(ctrls->groups_wrap); + if (group<0) { + while ( group < 0 ) { + if (act==XkbClampIntoRange) { + group= XkbGroup1Index; + } + else if (act==XkbRedirectIntoRange) { + int newGroup; + newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); + if (newGroup>=ctrls->num_groups) + group= XkbGroup1Index; + else group= newGroup; + } + else { + group+= ctrls->num_groups; + } + } + } + else if (group>=ctrls->num_groups) { + if (act==XkbClampIntoRange) { + group= ctrls->num_groups-1; + } + else if (act==XkbRedirectIntoRange) { + int newGroup; + newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); + if (newGroup>=ctrls->num_groups) + group= XkbGroup1Index; + else group= newGroup; + } + else { + group%= ctrls->num_groups; + } + } + return group; +} + +void +#if NeedFunctionPrototypes +XkbComputeDerivedState(XkbSrvInfoPtr xkbi) +#else +XkbComputeDerivedState(xkbi) + XkbSrvInfoPtr xkbi; +#endif +{ +XkbStatePtr state= &xkbi->state; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +unsigned grp; + + state->mods= (state->base_mods|state->latched_mods); + state->mods|= state->locked_mods; + state->lookup_mods= state->mods&(~ctrls->internal.mask); + state->grab_mods= state->lookup_mods&(~ctrls->ignore_lock.mask); + state->grab_mods|= + (state->base_mods|state->latched_mods&ctrls->ignore_lock.mask); + + + grp= state->locked_group; + if (grp>=ctrls->num_groups) + state->locked_group= XkbAdjustGroup(grp,ctrls); + + grp= state->locked_group+state->base_group+state->latched_group; + if (grp>=ctrls->num_groups) + state->group= XkbAdjustGroup(grp,ctrls); + else state->group= grp; + XkbComputeCompatState(xkbi); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbCheckSecondaryEffects( XkbSrvInfoPtr xkbi, + unsigned which, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbCheckSecondaryEffects(xkbi,which,changes,cause) + XkbSrvInfoPtr xkbi; + unsigned which; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ + if (which&XkbStateNotifyMask) { + XkbStateRec old; + old= xkbi->state; + changes->state_changes|= XkbStateChangedFlags(&old,&xkbi->state); + XkbComputeDerivedState(xkbi); + } + if (which&XkbIndicatorStateNotifyMask) + XkbUpdateIndicators(xkbi->device,XkbAllIndicatorsMask,True,changes, + cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSetPhysicalLockingKey(DeviceIntPtr dev,unsigned key) +#else +XkbSetPhysicalLockingKey(dev,key) + DeviceIntPtr dev; + unsigned key; +#endif +{ +XkbDescPtr xkb; + + xkb= dev->key->xkbInfo->desc; + if ((key>=xkb->min_key_code) && (key<=xkb->max_key_code)) { + xkb->server->behaviors[key].type= XkbKB_Lock|XkbKB_Permanent; + } + else ErrorF("Internal Error! Bad XKB info in SetPhysicalLockingKey\n"); + return; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbEnableDisableControls( XkbSrvInfoPtr xkbi, + unsigned long change, + unsigned long newValues, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbEnableDisableControls(xkbi,change,newValues,changes,cause) + XkbSrvInfoPtr xkbi; + unsigned long change; + unsigned long newValues; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +XkbControlsPtr ctrls; +unsigned old; +XkbSrvLedInfoPtr sli; + + ctrls= xkbi->desc->ctrls; + old= ctrls->enabled_ctrls; + ctrls->enabled_ctrls&= ~change; + ctrls->enabled_ctrls|= (change&newValues); + if (old==ctrls->enabled_ctrls) + return False; + if (cause!=NULL) { + xkbControlsNotify cn; + cn.numGroups= ctrls->num_groups; + cn.changedControls|= XkbControlsEnabledMask; + cn.enabledControls= ctrls->enabled_ctrls; + cn.enabledControlChanges= (ctrls->enabled_ctrls^old); + cn.keycode= cause->kc; + cn.eventType= cause->event; + cn.requestMajor= cause->mjr; + cn.requestMinor= cause->mnr; + XkbSendControlsNotify(xkbi->device,&cn); + } + else { + /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes*/ + /* is non-zero, the controls in question changed already in "this" */ + /* request and this change merely undoes the previous one. By the */ + /* same token, we have to figure out whether or not ControlsEnabled */ + /* should be set or not in the changes structure */ + changes->ctrls.enabled_ctrls_changes^= (ctrls->enabled_ctrls^old); + if (changes->ctrls.enabled_ctrls_changes) + changes->ctrls.changed_ctrls|= XkbControlsEnabledMask; + else changes->ctrls.changed_ctrls&= ~XkbControlsEnabledMask; + } + sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(xkbi->device,sli->usesControls,True,changes,cause); + return True; +} + +/***====================================================================***/ + +#define MAX_TOC 16 + +XkbGeometryPtr +#if NeedFunctionPrototypes +XkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool *shouldFree) +#else +XkbLookupNamedGeometry(dev,name,shouldFree) + DeviceIntPtr dev; + Atom name; + Bool * shouldFree; +#endif +{ +XkbSrvInfoPtr xkbi= dev->key->xkbInfo; +XkbDescPtr xkb= xkbi->desc; + + *shouldFree= 0; + if (name==None) { + if (xkb->geom!=NULL) + return xkb->geom; + name= xkb->names->geometry; + } + if ((xkb->geom!=NULL)&&(xkb->geom->name==name)) + return xkb->geom; + else if ((name==xkb->names->geometry)&&(xkb->geom==NULL)) { + FILE *file= XkbDDXOpenConfigFile(XkbInitialMap,NULL,0); + if (file!=NULL) { + XkbFileInfo xkbFInfo; + xkmFileInfo finfo; + xkmSectionInfo toc[MAX_TOC],*entry; + bzero(&xkbFInfo,sizeof(xkbFInfo)); + xkbFInfo.xkb= xkb; + if (XkmReadTOC(file,&finfo,MAX_TOC,toc)) { + entry= XkmFindTOCEntry(&finfo,toc,XkmGeometryIndex); + if (entry!=NULL) + XkmReadFileSection(file,entry,&xkbFInfo,NULL); + } + fclose(file); + if (xkb->geom) { + *shouldFree= 0; + return xkb->geom; + } + } + } + *shouldFree= 1; + return NULL; +} + +void +#if NeedFunctionPrototypes +XkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper) +#else +XkbConvertCase(sym, lower, upper) + register KeySym sym; + KeySym *lower; + KeySym *upper; +#endif +{ + *lower = sym; + *upper = sym; + switch(sym >> 8) { + case 0: /* Latin 1 */ + if ((sym >= XK_A) && (sym <= XK_Z)) + *lower += (XK_a - XK_A); + else if ((sym >= XK_a) && (sym <= XK_z)) + *upper -= (XK_a - XK_A); + else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) + *lower += (XK_agrave - XK_Agrave); + else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) + *upper -= (XK_agrave - XK_Agrave); + else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) + *lower += (XK_oslash - XK_Ooblique); + else if ((sym >= XK_oslash) && (sym <= XK_thorn)) + *upper -= (XK_oslash - XK_Ooblique); + break; + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym == XK_Aogonek) + *lower = XK_aogonek; + else if (sym >= XK_Lstroke && sym <= XK_Sacute) + *lower += (XK_lstroke - XK_Lstroke); + else if (sym >= XK_Scaron && sym <= XK_Zacute) + *lower += (XK_scaron - XK_Scaron); + else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) + *lower += (XK_zcaron - XK_Zcaron); + else if (sym == XK_aogonek) + *upper = XK_Aogonek; + else if (sym >= XK_lstroke && sym <= XK_sacute) + *upper -= (XK_lstroke - XK_Lstroke); + else if (sym >= XK_scaron && sym <= XK_zacute) + *upper -= (XK_scaron - XK_Scaron); + else if (sym >= XK_zcaron && sym <= XK_zabovedot) + *upper -= (XK_zcaron - XK_Zcaron); + else if (sym >= XK_Racute && sym <= XK_Tcedilla) + *lower += (XK_racute - XK_Racute); + else if (sym >= XK_racute && sym <= XK_tcedilla) + *upper -= (XK_racute - XK_Racute); + break; + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) + *lower += (XK_hstroke - XK_Hstroke); + else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) + *lower += (XK_gbreve - XK_Gbreve); + else if (sym >= XK_hstroke && sym <= XK_hcircumflex) + *upper -= (XK_hstroke - XK_Hstroke); + else if (sym >= XK_gbreve && sym <= XK_jcircumflex) + *upper -= (XK_gbreve - XK_Gbreve); + else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) + *lower += (XK_cabovedot - XK_Cabovedot); + else if (sym >= XK_cabovedot && sym <= XK_scircumflex) + *upper -= (XK_cabovedot - XK_Cabovedot); + break; + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Rcedilla && sym <= XK_Tslash) + *lower += (XK_rcedilla - XK_Rcedilla); + else if (sym >= XK_rcedilla && sym <= XK_tslash) + *upper -= (XK_rcedilla - XK_Rcedilla); + else if (sym == XK_ENG) + *lower = XK_eng; + else if (sym == XK_eng) + *upper = XK_ENG; + else if (sym >= XK_Amacron && sym <= XK_Umacron) + *lower += (XK_amacron - XK_Amacron); + else if (sym >= XK_amacron && sym <= XK_umacron) + *upper -= (XK_amacron - XK_Amacron); + break; + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) + *lower -= (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) + *upper += (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) + *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); + else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) + *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); + break; + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) + *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && + sym != XK_Greek_iotaaccentdieresis && + sym != XK_Greek_upsilonaccentdieresis) + *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) + *lower += (XK_Greek_alpha - XK_Greek_ALPHA); + else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && + sym != XK_Greek_finalsmallsigma) + *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); + break; + } +} + + diff --git a/xkb/xkbconfig.c b/xkb/xkbconfig.c new file mode 100644 index 000000000..d2e67945e --- /dev/null +++ b/xkb/xkbconfig.c @@ -0,0 +1,1394 @@ +/* $Xorg: xkbconfig.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + + 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 name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS 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. + + ********************************************************/ + +#include +#include +#ifndef X_NOT_STDC_ENV +#include +#endif + +#include + +#include + +#ifndef XKB_IN_SERVER + +#include +#include +#include +#include +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#endif + +#include + +/***====================================================================***/ + +#define XKBCF_MAX_STR_LEN 100 +static char _XkbCF_rtrn[XKBCF_MAX_STR_LEN+1]; + +static int +#if NeedFunctionPrototypes +ScanIdent(FILE *file,int ch,XkbCFScanResultPtr val_rtrn) +#else +ScanIdent(file,ch,val_rtrn) + FILE * file; + int ch; + XkbCFScanResultPtr val_rtrn; +#endif +{ +register int i; +char * str; + + val_rtrn->str= str= _XkbCF_rtrn; + for (i=0;(isalpha(ch)||isdigit(ch)||(ch=='_'));ch=getc(file)) { + if (istr= _XkbCF_rtrn; + return XkbCF_String; + } + return XkbCF_UnterminatedString; +} + +static int +#if NeedFunctionPrototypes +ScanInteger(FILE *file,int ch,XkbCFScanResultPtr val_rtrn) +#else +ScanInteger(file,ch,val_rtrn) + FILE * file; + int ch; + XkbCFScanResultPtr val_rtrn; +#endif +{ +int i; + + if (isdigit(ch)) + ungetc(ch,file); + if (fscanf(file,"%i",&i)==1) { + val_rtrn->ival= i; + return XkbCF_Integer; + } + return XkbCF_Unknown; +} + +int +#if NeedFunctionPrototypes +XkbCFScan(FILE *file,XkbCFScanResultPtr val_rtrn,XkbConfigRtrnPtr rtrn) +#else +XkbCFScan(file,val_rtrn,rtrn) + FILE * file; + XkbCFScanResultPtr val_rtrn; + XkbConfigRtrnPtr rtrn; +#endif +{ +int ch; + + do { + ch= getc(file); + } while ((ch=='\t')||(ch==' ')); + if (isalpha(ch)) + return ScanIdent(file,ch,val_rtrn); + else if (isdigit(ch)) + return ScanInteger(file,ch,val_rtrn); + else if (ch=='"') + return ScanString(file,ch,val_rtrn); + else if (ch=='\n') { + rtrn->line++; + return XkbCF_EOL; + } + else if (ch==';') + return XkbCF_Semi; + else if (ch=='=') + return XkbCF_Equals; + else if (ch=='+') { + ch= getc(file); + if (ch=='=') + return XkbCF_PlusEquals; + if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) + ungetc(ch,file); + return XkbCF_Plus; + } + else if (ch=='-') { + ch= getc(file); + if (ch=='=') + return XkbCF_MinusEquals; + if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) + ungetc(ch,file); + return XkbCF_Minus; + } + else if (ch==EOF) + return XkbCF_EOF; + else if ((ch=='#')||((ch=='/')&&(getc(file)=='/'))) { + while ((ch!='\n')&&(ch!=EOF)) + ch= getc(file); + rtrn->line++; + return XkbCF_EOL; + } + return XkbCF_Unknown; +} + +/***====================================================================***/ + +#define _XkbCF_Illegal 0 +#define _XkbCF_Keymap 1 +#define _XkbCF_Keycodes 2 +#define _XkbCF_Geometry 3 +#define _XkbCF_PhysSymbols 4 +#define _XkbCF_Symbols 5 +#define _XkbCF_Types 6 +#define _XkbCF_CompatMap 7 + +#define _XkbCF_RulesFile 8 +#define _XkbCF_Model 9 +#define _XkbCF_Layout 10 +#define _XkbCF_Variant 11 +#define _XkbCF_Options 12 + +#define _XkbCF_InitialMods 13 +#define _XkbCF_InitialCtrls 14 + +#define _XkbCF_ClickVolume 15 +#define _XkbCF_BellVolume 16 +#define _XkbCF_BellPitch 17 +#define _XkbCF_BellDuration 18 +#define _XkbCF_RepeatDelay 19 +#define _XkbCF_RepeatInterval 20 +#define _XkbCF_SlowKeysDelay 21 +#define _XkbCF_DebounceDelay 22 +#define _XkbCF_MouseKeysDelay 23 +#define _XkbCF_MouseKeysInterval 24 +#define _XkbCF_MouseKeysTimeToMax 25 +#define _XkbCF_MouseKeysMaxSpeed 26 +#define _XkbCF_MouseKeysCurve 27 +#define _XkbCF_AccessXTimeout 28 +#define _XkbCF_AccessXTimeoutCtrlsOn 29 +#define _XkbCF_AccessXTimeoutCtrlsOff 30 +#define _XkbCF_AccessXTimeoutOptsOn 31 +#define _XkbCF_AccessXTimeoutOptsOff 32 + +#define _XkbCF_IgnoreLockMods 33 +#define _XkbCF_IgnoreGroupLock 34 +#define _XkbCF_InternalMods 35 + +#define _XkbCF_GroupsWrap 36 + +static Bool +#if NeedFunctionPrototypes +AddCtrlByName(XkbConfigRtrnPtr rtrn,char *name,unsigned long *ctrls_rtrn) +#else +AddCtrlByName(rtrn,name,ctrls_rtrn) + XkbConfigRtrnPtr rtrn; + char * name; + unsigned long * ctrls_rtrn; +#endif +{ + if ((_XkbStrCaseCmp(name,"repeat")==0)|| + (_XkbStrCaseCmp(name,"repeatkeys")==0)) + *ctrls_rtrn= XkbRepeatKeysMask; + else if (_XkbStrCaseCmp(name,"slowkeys")==0) + *ctrls_rtrn= XkbSlowKeysMask; + else if (_XkbStrCaseCmp(name,"bouncekeys")==0) + *ctrls_rtrn= XkbBounceKeysMask; + else if (_XkbStrCaseCmp(name,"stickykeys")==0) + *ctrls_rtrn= XkbStickyKeysMask; + else if (_XkbStrCaseCmp(name,"mousekeys")==0) + *ctrls_rtrn= XkbMouseKeysMask; + else if (_XkbStrCaseCmp(name,"mousekeysaccel")==0) + *ctrls_rtrn= XkbMouseKeysAccelMask; + else if (_XkbStrCaseCmp(name,"accessxkeys")==0) + *ctrls_rtrn= XkbAccessXKeysMask; + else if (_XkbStrCaseCmp(name,"accessxtimeout")==0) + *ctrls_rtrn= XkbAccessXTimeoutMask; + else if (_XkbStrCaseCmp(name,"accessxfeedback")==0) + *ctrls_rtrn= XkbAccessXFeedbackMask; + else if (_XkbStrCaseCmp(name,"audiblebell")==0) + *ctrls_rtrn= XkbAudibleBellMask; + else if (_XkbStrCaseCmp(name,"overlay1")==0) + *ctrls_rtrn= XkbOverlay1Mask; + else if (_XkbStrCaseCmp(name,"overlay2")==0) + *ctrls_rtrn= XkbOverlay2Mask; + else if (_XkbStrCaseCmp(name,"ignoregrouplock")==0) + *ctrls_rtrn= XkbIgnoreGroupLockMask; + else { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +AddAXTimeoutOptByName( XkbConfigRtrnPtr rtrn, + char * name, + unsigned short * opts_rtrn) +#else +AddAXTimeoutOptByName(rtrn,name,opts_rtrn) + XkbConfigRtrnPtr rtrn; + char * name; + unsigned short * opts_rtrn; +#endif +{ + if (_XkbStrCaseCmp(name,"slowkeyspress")==0) + *opts_rtrn= XkbAX_SKPressFBMask; + else if (_XkbStrCaseCmp(name,"slowkeysaccept")==0) + *opts_rtrn= XkbAX_SKAcceptFBMask; + else if (_XkbStrCaseCmp(name,"feature")==0) + *opts_rtrn= XkbAX_FeatureFBMask; + else if (_XkbStrCaseCmp(name,"slowwarn")==0) + *opts_rtrn= XkbAX_SlowWarnFBMask; + else if (_XkbStrCaseCmp(name,"indicator")==0) + *opts_rtrn= XkbAX_IndicatorFBMask; + else if (_XkbStrCaseCmp(name,"stickykeys")==0) + *opts_rtrn= XkbAX_StickyKeysFBMask; + else if (_XkbStrCaseCmp(name,"slowkeysrelease")==0) + *opts_rtrn= XkbAX_SKReleaseFBMask; + else if (_XkbStrCaseCmp(name,"slowkeysreject")==0) + *opts_rtrn= XkbAX_SKRejectFBMask; + else if (_XkbStrCaseCmp(name,"bouncekeysreject")==0) + *opts_rtrn= XkbAX_BKRejectFBMask; + else if (_XkbStrCaseCmp(name,"dumbbell")==0) + *opts_rtrn= XkbAX_DumbBellFBMask; + else { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + return True; +} + +XkbConfigUnboundModPtr +#if NeedFunctionPrototypes +XkbCFAddModByName( XkbConfigRtrnPtr rtrn, + int what, + char * name, + Bool merge, + XkbConfigUnboundModPtr last) +#else +XkbCFAddModByName(rtrn,what,name,merge,last) + XkbConfigRtrnPtr rtrn; + int what; + char * name; + Bool merge; + XkbConfigUnboundModPtr last; +#endif +{ + if (rtrn->num_unbound_mods>=rtrn->sz_unbound_mods) { + rtrn->sz_unbound_mods+= 5; + rtrn->unbound_mods= _XkbTypedRealloc(rtrn->unbound_mods, + rtrn->sz_unbound_mods, + XkbConfigUnboundModRec); + if (rtrn->unbound_mods==NULL) { + rtrn->error= XkbCF_BadAlloc; + return False; + } + } + if (last==NULL) { + last= &rtrn->unbound_mods[rtrn->num_unbound_mods++]; + last->what= what; + last->mods= 0; + last->vmods= 0; + last->merge= merge; + last->name= NULL; + } + if (_XkbStrCaseCmp(name,"shift")==0) + last->mods|= ShiftMask; + else if (_XkbStrCaseCmp(name,"lock")==0) + last->mods|= LockMask; + else if ((_XkbStrCaseCmp(name,"control")==0)|| + (_XkbStrCaseCmp(name,"ctrl")==0)) + last->mods|= ControlMask; + else if (_XkbStrCaseCmp(name,"mod1")==0) + last->mods|= Mod1Mask; + else if (_XkbStrCaseCmp(name,"mod2")==0) + last->mods|= Mod2Mask; + else if (_XkbStrCaseCmp(name,"mod3")==0) + last->mods|= Mod3Mask; + else if (_XkbStrCaseCmp(name,"mod4")==0) + last->mods|= Mod4Mask; + else if (_XkbStrCaseCmp(name,"mod5")==0) + last->mods|= Mod5Mask; + else { + if (last->name!=NULL) { + last= &rtrn->unbound_mods[rtrn->num_unbound_mods++]; + last->what= what; + last->mods= 0; + last->vmods= 0; + last->merge= merge; + last->name= NULL; + } + last->name= _XkbDupString(name); + } + return last; +} + +int +#if NeedFunctionPrototypes +XkbCFBindMods(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) +#else +XkbCFBindMods(rtrn,xkb) + XkbConfigRtrnPtr rtrn; + XkbDescPtr xkb; +#endif +{ +register int n,v; +Atom name; +XkbConfigUnboundModPtr mod; +int missing; + + if (rtrn->num_unbound_mods<1) + return 0; + if ((xkb==NULL) || (xkb->names==NULL)) + return -1; + + missing= 0; + for (n=0,mod=rtrn->unbound_mods;nnum_unbound_mods;n++,mod++) { + if (mod->name!=NULL) { + name= XkbInternAtom(xkb->dpy,mod->name,True); + if (name==None) + continue; + for (v=0;vnames->vmods[v]==name) { + mod->vmods= (1<name); + mod->name= NULL; + break; + } + } + if (mod->name!=NULL) + missing++; + } + } + return missing; +} + +Bool +#if NeedFunctionPrototypes +XkbCFApplyMods(XkbConfigRtrnPtr rtrn,int what,XkbConfigModInfoPtr info) +#else +XkbCFApplyMods(rtrn,what,info) + XkbConfigRtrnPtr rtrn; + int what; + XkbConfigModInfoPtr info; +#endif +{ +register int n; +XkbConfigUnboundModPtr mod; + + if (rtrn->num_unbound_mods<1) + return True; + + for (n=0,mod=rtrn->unbound_mods;nnum_unbound_mods;n++,mod++) { + if (mod->what!=what) + continue; + if (mod->merge==XkbCF_MergeRemove) { + info->mods_clear|= mod->mods; + info->vmods_clear|= mod->vmods; + } + else { + if (mod->merge==XkbCF_MergeSet) + info->replace= True; + info->mods|= mod->mods; + info->vmods|= mod->vmods; + } + if (mod->name==NULL) { + mod->what= _XkbCF_Illegal; + } + else { + mod->mods= 0; + mod->vmods= 0; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +DefaultParser( FILE * file, + XkbConfigFieldsPtr fields, + XkbConfigFieldPtr field, + XkbDescPtr xkb, + XkbConfigRtrnPtr rtrn) +#else +DefaultParser(file,fields,field,xkb,rtrn) + FILE * file; + XkbConfigFieldsPtr fields; + XkbConfigFieldPtr field; + XkbDescPtr xkb; + XkbConfigRtrnPtr rtrn; +#endif +{ +int tok; +XkbCFScanResultRec val; +char ** str; +int merge; +unsigned long * ctrls; +unsigned short * opts; +int * pival; +int onoff; +XkbConfigUnboundModPtr last; +unsigned what; + + tok= XkbCFScan(file,&val,rtrn); + str= NULL; + onoff= 0; + pival= NULL; + switch (field->field_id) { + case _XkbCF_RulesFile: if (!str) str= &rtrn->rules_file; + case _XkbCF_Model: if (!str) str= &rtrn->model; + case _XkbCF_Layout: if (!str) str= &rtrn->layout; + case _XkbCF_Variant: if (!str) str= &rtrn->variant; + case _XkbCF_Options: if (!str) str= &rtrn->options; + case _XkbCF_Keymap: if (!str) str= &rtrn->keymap; + case _XkbCF_Keycodes: if (!str) str= &rtrn->keycodes; + case _XkbCF_Geometry: if (!str) str= &rtrn->geometry; + case _XkbCF_PhysSymbols:if (!str) str= &rtrn->phys_symbols; + case _XkbCF_Symbols: if (!str) str= &rtrn->symbols; + case _XkbCF_Types: if (!str) str= &rtrn->types; + case _XkbCF_CompatMap: if (!str) str= &rtrn->compat; + if (tok!=XkbCF_Equals) { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_String)&&(tok!=XkbCF_Ident)) { + rtrn->error= XkbCF_ExpectedString; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedEOS; + return False; + } + if (*str!=NULL) + _XkbFree(*str); + *str= _XkbDupString(val.str); + break; + case _XkbCF_InitialMods: + case _XkbCF_IgnoreLockMods: + case _XkbCF_InternalMods: + what= XkbCF_InitialMods; + if (field->field_id==_XkbCF_InitialMods) + rtrn->defined|= (what=XkbCF_InitialMods); + else if (field->field_id==_XkbCF_InternalMods) + rtrn->defined|= (what=XkbCF_InternalMods); + else if (field->field_id==_XkbCF_IgnoreLockMods) + rtrn->defined|= (what=XkbCF_IgnoreLockMods); + if (tok==XkbCF_Equals) merge= XkbCF_MergeSet; + else if (tok==XkbCF_MinusEquals) merge= XkbCF_MergeRemove; + else if (tok==XkbCF_PlusEquals) merge= XkbCF_MergeAdd; + else { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedModifier; + return False; + } + last= NULL; + while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { + rtrn->error= XkbCF_ExpectedModifier; + return False; + } + last=XkbCFAddModByName(rtrn,what,val.str,merge,last); + if (last==NULL) + return False; + if (merge==XkbCF_MergeSet) + merge= XkbCF_MergeAdd; + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { + if (tok!=XkbCF_Plus) { + rtrn->error= XkbCF_ExpectedOperator; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + } + } + break; + case _XkbCF_InitialCtrls: + rtrn->defined|= XkbCF_InitialCtrls; + opts= NULL; + ctrls= NULL; + if (tok==XkbCF_PlusEquals) + ctrls= &rtrn->initial_ctrls; + else if (tok==XkbCF_MinusEquals) + ctrls= &rtrn->initial_ctrls_clear; + else if (tok==XkbCF_Equals) { + ctrls= &rtrn->initial_ctrls; + rtrn->replace_initial_ctrls= True; + *ctrls= 0; + } + else { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + if (!AddCtrlByName(rtrn,val.str,ctrls)) { + return False; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { + if (tok!=XkbCF_Plus) { + rtrn->error= XkbCF_ExpectedOperator; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + } + } + break; + case _XkbCF_AccessXTimeoutCtrlsOn: + case _XkbCF_AccessXTimeoutCtrlsOff: + case _XkbCF_AccessXTimeoutOptsOff: + case _XkbCF_AccessXTimeoutOptsOn: + if (field->field_id==_XkbCF_AccessXTimeoutOptsOff) + field->field_id= _XkbCF_AccessXTimeoutCtrlsOff; + else if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOn) + field->field_id= _XkbCF_AccessXTimeoutCtrlsOn; + + if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) + rtrn->defined|= XkbCF_AccessXTimeoutCtrlsOff; + else if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOn) + rtrn->defined|= XkbCF_AccessXTimeoutCtrlsOn; + + opts= NULL; + if (tok==XkbCF_MinusEquals) { + ctrls= &rtrn->axt_ctrls_ignore; + opts= &rtrn->axt_opts_ignore; + } + else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) { + if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) { + ctrls= &rtrn->axt_ctrls_off; + opts= &rtrn->axt_opts_off; + if (tok==XkbCF_Equals) + rtrn->replace_axt_ctrls_off= True; + } + else { + ctrls= &rtrn->axt_ctrls_on; + opts= &rtrn->axt_opts_on; + if (tok==XkbCF_Equals) + rtrn->replace_axt_ctrls_on= True; + } + *ctrls= 0; + } + else { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + if (!AddCtrlByName(rtrn,val.str,ctrls)) { + if (!AddAXTimeoutOptByName(rtrn,val.str,opts)) + return False; + if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) { + rtrn->defined|= XkbCF_AccessXTimeoutOptsOff; + if (rtrn->replace_axt_ctrls_off) + rtrn->replace_axt_opts_off= True; + } + else { + rtrn->defined|= XkbCF_AccessXTimeoutOptsOn; + if (rtrn->replace_axt_ctrls_on) + rtrn->replace_axt_opts_on= True; + } + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { + if (tok!=XkbCF_Plus) { + rtrn->error= XkbCF_ExpectedOperator; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + } + } + break; + case _XkbCF_ClickVolume: + if (!pival) { + pival= &rtrn->click_volume; + onoff= 100; + } + case _XkbCF_BellVolume: + if (!pival) { + pival= &rtrn->bell_volume; + onoff= 100; + } + case _XkbCF_BellPitch: + if (!pival) + pival= &rtrn->bell_pitch; + case _XkbCF_BellDuration: + if (!pival) + pival= &rtrn->bell_duration; + case _XkbCF_RepeatDelay: + if (!pival) + pival= &rtrn->repeat_delay; + case _XkbCF_RepeatInterval: + if (!pival) + pival= &rtrn->repeat_interval; + case _XkbCF_SlowKeysDelay: + if (!pival) + pival= &rtrn->slow_keys_delay; + case _XkbCF_DebounceDelay: + if (!pival) + pival= &rtrn->debounce_delay; + case _XkbCF_MouseKeysDelay: + if (!pival) + pival= &rtrn->mk_delay; + case _XkbCF_MouseKeysInterval: + if (!pival) + pival= &rtrn->mk_interval; + case _XkbCF_MouseKeysTimeToMax: + if (!pival) + pival= &rtrn->mk_time_to_max; + case _XkbCF_MouseKeysMaxSpeed: + if (!pival) + pival= &rtrn->mk_max_speed; + case _XkbCF_MouseKeysCurve: + if (!pival) + pival= &rtrn->mk_curve; + case _XkbCF_AccessXTimeout: + if (!pival) + pival= &rtrn->ax_timeout; + if (tok!=XkbCF_Equals) { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if (tok!=XkbCF_Integer) { + Bool ok= False; + if ((onoff)&&(tok==XkbCF_Ident)&&(val.str!=NULL)) { + if (_XkbStrCaseCmp(val.str,"on")) { + val.ival= onoff; + ok= True; + } + else if (_XkbStrCaseCmp(val.str,"off")) { + val.ival= 0; + ok= True; + } + } + if (!ok) { + rtrn->error= XkbCF_ExpectedInteger; + goto BAILOUT; + } + } + *pival= val.ival; + rtrn->defined|= XkbCF_AccessXTimeout; + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedEOS; + return False; + } + break; + case _XkbCF_GroupsWrap: + if (tok!=XkbCF_Equals) { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if (tok==XkbCF_Ident) { + if (_XkbStrCaseCmp(val.str,"wrap")==0) { + rtrn->groups_wrap= XkbSetGroupInfo(0,XkbWrapIntoRange,0); + } + else if (_XkbStrCaseCmp(val.str,"clamp")==0) { + rtrn->groups_wrap= XkbSetGroupInfo(0,XkbClampIntoRange,0); + } + else { + rtrn->error= XkbCF_ExpectedOORGroupBehavior; + return False; + } + } + else if ((tok==XkbCF_Integer)&&(XkbIsLegalGroup(val.ival-1))) { + rtrn->groups_wrap= XkbSetGroupInfo(0,XkbRedirectIntoRange, + val.ival-1); + } + else { + rtrn->error= XkbCF_ExpectedOORGroupBehavior; + return False; + } + rtrn->defined|= XkbCF_GroupsWrap; + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedEOS; + return False; + } + break; + default: + rtrn->error= XkbCF_ExpectedInteger; + goto BAILOUT; + + } + return True; +BAILOUT: + return False; +} + +static Bool +#if NeedFunctionPrototypes +DefaultCleanUp(XkbConfigRtrnPtr rtrn) +#else +DefaultCleanUp(rtrn) + XkbConfigRtrnPtr rtrn; +#endif +{ + if (rtrn->keymap) _XkbFree(rtrn->keymap); + if (rtrn->keycodes) _XkbFree(rtrn->keycodes); + if (rtrn->geometry) _XkbFree(rtrn->geometry); + if (rtrn->phys_symbols) _XkbFree(rtrn->phys_symbols); + if (rtrn->symbols) _XkbFree(rtrn->symbols); + if (rtrn->types) _XkbFree(rtrn->types); + if (rtrn->compat) _XkbFree(rtrn->compat); + rtrn->keycodes= rtrn->geometry= NULL; + rtrn->symbols= rtrn->phys_symbols= NULL; + rtrn->types= rtrn->compat= NULL; + if ((rtrn->unbound_mods!=NULL)&&(rtrn->num_unbound_mods>0)) { + register int i; + for (i=0;inum_unbound_mods;i++) { + if (rtrn->unbound_mods[i].name!=NULL) { + _XkbFree(rtrn->unbound_mods[i].name); + rtrn->unbound_mods[i].name= NULL; + } + } + _XkbFree(rtrn->unbound_mods); + rtrn->sz_unbound_mods= 0; + rtrn->num_unbound_mods= 0; + rtrn->unbound_mods= NULL; + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +DefaultApplyNames(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) +#else +DefaultApplyNames(rtrn,xkb) + XkbConfigRtrnPtr rtrn; + XkbDescPtr xkb; +#endif +{ +char *str; + + if (XkbAllocNames(xkb,XkbComponentNamesMask,0,0)!=Success) + return False; + if ((str=rtrn->keycodes)!=NULL) { + xkb->names->keycodes= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->keycodes= NULL; + } + if ((str=rtrn->geometry)!=NULL) { + xkb->names->geometry= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->geometry= NULL; + } + if ((str=rtrn->symbols)!=NULL) { + xkb->names->symbols= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->symbols= NULL; + } + if ((str=rtrn->phys_symbols)!=NULL) { + xkb->names->phys_symbols= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->phys_symbols= NULL; + } + if ((str=rtrn->types)!=NULL) { + xkb->names->types= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->types= NULL; + } + if ((str=rtrn->compat)!=NULL) { + xkb->names->compat= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->compat= NULL; + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +DefaultApplyControls(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) +#else +DefaultApplyControls(rtrn,xkb) + XkbConfigRtrnPtr rtrn; + XkbDescPtr xkb; +#endif +{ +unsigned on,off; +XkbControlsPtr ctrls; +unsigned int mask; + + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) + return False; + ctrls= xkb->ctrls; + if (rtrn->replace_initial_ctrls) + ctrls->enabled_ctrls= rtrn->initial_ctrls; + else ctrls->enabled_ctrls|= rtrn->initial_ctrls; + ctrls->enabled_ctrls&= ~rtrn->initial_ctrls_clear; + if (rtrn->internal_mods.replace) { + ctrls->internal.real_mods= rtrn->internal_mods.mods; + ctrls->internal.vmods= rtrn->internal_mods.vmods; + } + else { + ctrls->internal.real_mods&= ~rtrn->internal_mods.mods_clear; + ctrls->internal.vmods&= ~rtrn->internal_mods.vmods_clear; + ctrls->internal.real_mods|= rtrn->internal_mods.mods; + ctrls->internal.vmods|= rtrn->internal_mods.vmods; + } + mask= 0; + (void)XkbVirtualModsToReal(xkb,ctrls->internal.vmods,&mask); + ctrls->internal.mask= (ctrls->internal.real_mods|mask); + + if (rtrn->ignore_lock_mods.replace) { + ctrls->ignore_lock.real_mods= rtrn->ignore_lock_mods.mods; + ctrls->ignore_lock.vmods= rtrn->ignore_lock_mods.vmods; + } + else { + ctrls->ignore_lock.real_mods&= ~rtrn->ignore_lock_mods.mods_clear; + ctrls->ignore_lock.vmods&= ~rtrn->ignore_lock_mods.vmods_clear; + ctrls->ignore_lock.real_mods|= rtrn->ignore_lock_mods.mods; + ctrls->ignore_lock.vmods|= rtrn->ignore_lock_mods.vmods; + } + mask= 0; + (void)XkbVirtualModsToReal(xkb,ctrls->ignore_lock.vmods,&mask); + ctrls->ignore_lock.mask= (ctrls->ignore_lock.real_mods|mask); + + if (rtrn->repeat_delay>0) + ctrls->repeat_delay= rtrn->repeat_delay; + if (rtrn->repeat_interval>0) + ctrls->repeat_interval= rtrn->repeat_interval; + if (rtrn->slow_keys_delay>0) + ctrls->slow_keys_delay= rtrn->slow_keys_delay; + if (rtrn->debounce_delay>0) + ctrls->debounce_delay= rtrn->debounce_delay; + if (rtrn->mk_delay>0) + ctrls->mk_delay= rtrn->mk_delay; + if (rtrn->mk_interval>0) + ctrls->mk_interval= rtrn->mk_interval; + if (rtrn->mk_time_to_max>0) + ctrls->mk_time_to_max= rtrn->mk_time_to_max; + if (rtrn->mk_max_speed>0) + ctrls->mk_max_speed= rtrn->mk_max_speed; + if (rtrn->mk_curve>0) + ctrls->mk_curve= rtrn->mk_curve; + if (rtrn->defined&XkbCF_AccessXTimeout) + ctrls->ax_timeout= rtrn->ax_timeout; + + /* any value set to both off and on is reset to ignore */ + if ((off=(rtrn->axt_ctrls_on&rtrn->axt_ctrls_off))!=0) + rtrn->axt_ctrls_ignore|= off; + + /* ignore takes priority over on and off */ + rtrn->axt_ctrls_on&= ~rtrn->axt_ctrls_ignore; + rtrn->axt_ctrls_off&= ~rtrn->axt_ctrls_ignore; + + if (!rtrn->replace_axt_ctrls_off) { + off= (ctrls->axt_ctrls_mask&(~ctrls->axt_ctrls_values)); + off&= ~rtrn->axt_ctrls_on; + off|= rtrn->axt_ctrls_off; + } + else off= rtrn->axt_ctrls_off; + if (!rtrn->replace_axt_ctrls_on) { + on= (ctrls->axt_ctrls_mask&ctrls->axt_ctrls_values); + on&= ~rtrn->axt_ctrls_off; + on|= rtrn->axt_ctrls_on; + } + else on= rtrn->axt_ctrls_on; + ctrls->axt_ctrls_mask= (on|off)&~rtrn->axt_ctrls_ignore; + ctrls->axt_ctrls_values= on&~rtrn->axt_ctrls_ignore; + + /* any value set to both off and on is reset to ignore */ + if ((off=(rtrn->axt_opts_on&rtrn->axt_opts_off))!=0) + rtrn->axt_opts_ignore|= off; + + /* ignore takes priority over on and off */ + rtrn->axt_opts_on&= ~rtrn->axt_opts_ignore; + rtrn->axt_opts_off&= ~rtrn->axt_opts_ignore; + + if (rtrn->replace_axt_opts_off) { + off= (ctrls->axt_opts_mask&(~ctrls->axt_opts_values)); + off&= ~rtrn->axt_opts_on; + off|= rtrn->axt_opts_off; + } + else off= rtrn->axt_opts_off; + if (!rtrn->replace_axt_opts_on) { + on= (ctrls->axt_opts_mask&ctrls->axt_opts_values); + on&= ~rtrn->axt_opts_off; + on|= rtrn->axt_opts_on; + } + else on= rtrn->axt_opts_on; + ctrls->axt_opts_mask= (unsigned short)((on|off)&~rtrn->axt_ctrls_ignore); + ctrls->axt_opts_values= (unsigned short)(on&~rtrn->axt_ctrls_ignore); + + if (rtrn->defined&XkbCF_GroupsWrap) { + int n; + n= XkbNumGroups(ctrls->groups_wrap); + rtrn->groups_wrap= XkbSetNumGroups(rtrn->groups_wrap,n); + ctrls->groups_wrap= rtrn->groups_wrap; + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +DefaultFinish( XkbConfigFieldsPtr fields, + XkbDescPtr xkb, + XkbConfigRtrnPtr rtrn, + int what) +#else +DefaultFinish(fields,xkb,rtrn,what) + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; + XkbConfigRtrnPtr rtrn; + int what; +#endif +{ + if ((what==XkbCF_Destroy)||(what==XkbCF_CleanUp)) + return DefaultCleanUp(rtrn); + if (what==XkbCF_Check) { + if ((rtrn->symbols==NULL)&&(rtrn->phys_symbols!=NULL)) + rtrn->symbols= _XkbDupString(rtrn->phys_symbols); + } + if ((what==XkbCF_Apply)||(what==XkbCF_Check)) { + if (xkb && xkb->names && (rtrn->num_unbound_mods>0)) + XkbCFBindMods(rtrn,xkb); + XkbCFApplyMods(rtrn,XkbCF_InitialMods,&rtrn->initial_mods); + XkbCFApplyMods(rtrn,XkbCF_InternalMods,&rtrn->internal_mods); + XkbCFApplyMods(rtrn,XkbCF_IgnoreLockMods,&rtrn->ignore_lock_mods); + } + if (what==XkbCF_Apply) { + if (xkb!=NULL) { + DefaultApplyNames(rtrn,xkb); + DefaultApplyControls(rtrn,xkb); + XkbCFBindMods(rtrn,xkb); + } + } + return True; +} + +static XkbConfigFieldRec _XkbCFDfltFields[] = { + { "rules", _XkbCF_RulesFile }, + { "model", _XkbCF_Model }, + { "layout", _XkbCF_Layout }, + { "variant", _XkbCF_Variant }, + { "options", _XkbCF_Options }, + { "keymap", _XkbCF_Keymap }, + { "keycodes", _XkbCF_Keycodes }, + { "geometry", _XkbCF_Geometry }, + { "realsymbols",_XkbCF_PhysSymbols }, + { "actualsymbols",_XkbCF_PhysSymbols }, + { "symbols", _XkbCF_Symbols }, + { "symbolstouse",_XkbCF_Symbols }, + { "types", _XkbCF_Types }, + { "compat", _XkbCF_CompatMap }, + { "modifiers", _XkbCF_InitialMods }, + { "controls", _XkbCF_InitialCtrls }, + { "click", _XkbCF_ClickVolume }, + { "clickvolume",_XkbCF_ClickVolume }, + { "bell", _XkbCF_BellVolume }, + { "bellvolume", _XkbCF_BellVolume }, + { "bellpitch", _XkbCF_BellPitch }, + { "bellduration",_XkbCF_BellDuration }, + { "repeatdelay",_XkbCF_RepeatDelay }, + { "repeatinterval",_XkbCF_RepeatInterval }, + { "slowkeysdelay",_XkbCF_SlowKeysDelay }, + { "debouncedelay",_XkbCF_DebounceDelay }, + { "mousekeysdelay",_XkbCF_MouseKeysDelay }, + { "mousekeysinterval",_XkbCF_MouseKeysInterval }, + { "mousekeystimetomax",_XkbCF_MouseKeysTimeToMax }, + { "mousekeysmaxspeed",_XkbCF_MouseKeysMaxSpeed }, + { "mousekeyscurve",_XkbCF_MouseKeysCurve }, + { "accessxtimeout",_XkbCF_AccessXTimeout }, + { "axtimeout",_XkbCF_AccessXTimeout }, + { "accessxtimeoutctrlson",_XkbCF_AccessXTimeoutCtrlsOn }, + { "axtctrlson", _XkbCF_AccessXTimeoutCtrlsOn }, + { "accessxtimeoutctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff }, + { "axtctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff }, + { "ignorelockmods",_XkbCF_IgnoreLockMods }, + { "ignorelockmodifiers",_XkbCF_IgnoreLockMods }, + { "ignoregrouplock",_XkbCF_IgnoreGroupLock }, + { "internalmods",_XkbCF_InternalMods }, + { "internalmodifiers",_XkbCF_InternalMods }, + { "outofrangegroups",_XkbCF_GroupsWrap }, + { "groups", _XkbCF_GroupsWrap } +}; +#define _XkbCFNumDfltFields (sizeof(_XkbCFDfltFields)/sizeof(XkbConfigFieldRec)) + +static XkbConfigFieldsRec _XkbCFDflts = { + 0, /* cfg_id */ + _XkbCFNumDfltFields, /* num_fields */ + _XkbCFDfltFields, /* fields */ + DefaultParser, /* parser */ + DefaultFinish, /* finish */ + NULL, /* priv */ + NULL /* next */ +}; + +XkbConfigFieldsPtr XkbCFDflts= &_XkbCFDflts; + +/***====================================================================***/ + +XkbConfigFieldsPtr +#if NeedFunctionPrototypes +XkbCFDup(XkbConfigFieldsPtr fields) +#else +XkbCFDup(fields) + XkbConfigFieldsPtr fields; +#endif +{ +XkbConfigFieldsPtr pNew; + + pNew= _XkbTypedAlloc(XkbConfigFieldsRec); + if (pNew!=NULL) { + memcpy(pNew,fields,sizeof(XkbConfigFieldsRec)); + if ((pNew->fields!=NULL)&&(pNew->num_fields>0)) { + pNew->fields= _XkbTypedCalloc(pNew->num_fields,XkbConfigFieldRec); + if (pNew->fields) { + memcpy(fields->fields,pNew->fields, + (pNew->num_fields*sizeof(XkbConfigFieldRec))); + } + else { + _XkbFree(pNew); + return NULL; + } + } + else { + pNew->num_fields= 0; + pNew->fields= NULL; + } + pNew->next= NULL; + } + return pNew; +} + +XkbConfigFieldsPtr +#if NeedFunctionPrototypes +XkbCFFree(XkbConfigFieldsPtr fields,Bool all) +#else +XkbCFFree(fields,all) + XkbConfigFieldsPtr fields; + Bool all; +#endif +{ +XkbConfigFieldsPtr next; + + next= NULL; + while (fields!=NULL) { + next= fields->next; + if (fields!=XkbCFDflts) { + if (fields->fields) { + _XkbFree(fields->fields); + fields->fields= NULL; + fields->num_fields= 0; + } + _XkbFree(fields); + } + fields= (all?next:NULL); + } + return next; +} + +Bool +#if NeedFunctionPrototypes +XkbCFApplyRtrnValues( XkbConfigRtrnPtr rtrn, + XkbConfigFieldsPtr fields, + XkbDescPtr xkb) +#else +XkbCFApplyRtrnValues(rtrn,fields,xkb) + XkbConfigRtrnPtr rtrn; + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; +#endif +{ +Bool ok; + + if ((fields==NULL)||(rtrn==NULL)||(xkb==NULL)) + return False; + for (ok=True;fields!=NULL;fields=fields->next) { + if (fields->finish!=NULL) + ok= (*fields->finish)(fields,xkb,rtrn,XkbCF_Apply)&&ok; + } + return ok; +} + +XkbConfigRtrnPrivPtr +#if NeedFunctionPrototypes +XkbCFAddPrivate( XkbConfigRtrnPtr rtrn, + XkbConfigFieldsPtr fields, + XPointer ptr) +#else +XkbCFAddPrivate(rtrn,fields,ptr) + XkbConfigRtrnPtr rtrn; + XkbConfigFieldsPtr fields; + XPointer ptr; +#endif +{ +XkbConfigRtrnPrivPtr priv; + + if ((rtrn==NULL)||(fields==NULL)) + return NULL; + priv= _XkbTypedAlloc(XkbConfigRtrnPrivRec); + if (priv!=NULL) { + priv->cfg_id= fields->cfg_id; + priv->priv= ptr; + priv->next= rtrn->priv; + rtrn->priv= priv; + } + return priv; +} + +void +#if NeedFunctionPrototypes +XkbCFFreeRtrn( XkbConfigRtrnPtr rtrn, + XkbConfigFieldsPtr fields, + XkbDescPtr xkb) +#else +XkbCFFreeRtrn(rtrn,fields,xkb) + XkbConfigRtrnPtr rtrn; + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; +#endif +{ +XkbConfigRtrnPrivPtr tmp,next; + + if ((fields==NULL)||(rtrn==NULL)) + return; + while (fields!=NULL) { + if (fields->finish!=NULL) + (*fields->finish)(fields,xkb,rtrn,XkbCF_Destroy); + fields= fields->next; + } + for (tmp=rtrn->priv;tmp!=NULL;tmp=next) { + next= tmp->next; + bzero((char *)tmp,sizeof(XkbConfigRtrnPrivRec)); + _XkbFree(tmp); + } + bzero((char *)rtrn,sizeof(XkbConfigRtrnRec)); + return; +} + +Bool +#if NeedFunctionPrototypes +XkbCFParse( FILE * file, + XkbConfigFieldsPtr fields, + XkbDescPtr xkb, + XkbConfigRtrnPtr rtrn) +#else +XkbCFParse(file,fields,xkb,rtrn) + FILE * file; + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; + XkbConfigRtrnPtr rtrn; +#endif +{ +int tok; +XkbCFScanResultRec val; +XkbConfigFieldsPtr tmp; + + if ((file==NULL)||(fields==NULL)||(rtrn==NULL)) + return False; + for (tok=0,tmp=fields;tmp!=NULL;tmp=tmp->next,tok++) { + fields->cfg_id= tok; + } + bzero((char *)rtrn,sizeof(XkbConfigRtrnRec)); + rtrn->line= 1; + rtrn->click_volume= -1; + rtrn->bell_volume= -1; + while ((tok=XkbCFScan(file,&val,rtrn))!=XkbCF_EOF) { + if (tok==XkbCF_Ident) { + Bool done; + for (tmp=fields,done=False;(tmp!=NULL)&&(!done);tmp=tmp->next) { + register int i; + XkbConfigFieldPtr f; + + for (i=0,f=tmp->fields;(inum_fields)&&(!done);i++,f++) { + if (_XkbStrCaseCmp(val.str,f->field)!=0) + continue; + if ((*tmp->parser)(file,tmp,f,xkb,rtrn)) + done= True; + else goto BAILOUT; + } + } + } + else if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)) { + rtrn->error= XkbCF_MissingIdent; + goto BAILOUT; + } + } + for (tmp=fields;tmp!=NULL;tmp=tmp->next) { + if ((tmp->finish)&&(!(*tmp->finish)(tmp,xkb,rtrn,XkbCF_Check))) + goto BAILOUT; + } + return True; +BAILOUT: + for (tmp=fields;tmp!=NULL;tmp=tmp->next) { + if (tmp->finish) + (*tmp->finish)(tmp,xkb,rtrn,XkbCF_CleanUp); + } + return False; +} + +void +#if NeedFunctionPrototypes +XkbCFReportError(FILE *file,char *name,int error,int line) +#else +XkbCFReportError(file,name,error,line) + FILE * file; + char * name; + int error; + int line; +#endif +{ +char * msg; + + switch(error) { + case XkbCF_BadAlloc: + msg= "allocation failed\n"; break; + case XkbCF_UnterminatedString: + msg= "unterminated string on line %d"; break; + case XkbCF_MissingIdent: + msg= "expected identifier on line %d"; break; + case XkbCF_MissingEquals: + msg= "expected '=' on line %d"; break; + case XkbCF_ExpectedEOS: + msg= "expected ';' or newline on line %d"; break; + case XkbCF_ExpectedBoolean: + msg= "expected a boolean value on line %d"; break; + case XkbCF_ExpectedInteger: + msg= "expected a numeric value on line %d"; break; + case XkbCF_ExpectedString: + msg= "expected a string on line %d"; break; + case XkbCF_ExpectedModifier: + msg= "expected a modifier name on line %d"; break; + case XkbCF_ExpectedControl: + msg= "expected a control name on line %d"; break; + case XkbCF_ExpectedAXOption: + msg= "expected an AccessX option on line %d"; break; + case XkbCF_ExpectedOperator: + msg= "expected '+' or '-' on line %d"; break; + case XkbCF_ExpectedOORGroupBehavior: + msg= "expected wrap, clamp or group number on line %d"; break; + default: + msg= "unknown error on line %d"; break; + } + fprintf(file,msg,line); + if (name) fprintf(file," of %s\n",name); + else fprintf(file,"\n"); + return; +} diff --git a/xkb/xkberrs.c b/xkb/xkberrs.c new file mode 100644 index 000000000..41df420b8 --- /dev/null +++ b/xkb/xkberrs.c @@ -0,0 +1,70 @@ +/* $Xorg: xkberrs.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + + 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 name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS 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. + + ********************************************************/ + +#include +#include +#ifndef X_NOT_STDC_ENV +#include +#endif +#include +#include +#include + +char * _XkbErrMessages[] = { + "success", /* _XkbSuccess */ + "key names not defined", /* _XkbErrMissingNames */ + "key types not defined", /* _XkbErrMissingTypes */ + "required key types not present", /* _XkbErrMissingReqTypes */ + "symbols not defined", /* _XkbErrMissingSymbols */ + "virtual modifier bindings not defined",/* _XkbErrMissingVMods */ + "indicators not defined", /* _XkbErrMissingIndicators */ + "compatibility map not defined", /* _XkbErrMissingCompatMap */ + "symbol interpretations not defined", /* _XkbErrMissingSymInterps */ + "geometry not defined", /* _XkbErrMissingGeometry */ + "illegal doodad type", /* _XkbErrIllegalDoodad */ + "illegal TOC type", /* _XkbErrIllegalTOCType */ + "illegal contents", /* _XkbErrIllegalContents */ + "empty file", /* _XkbErrEmptyFile */ + "file not found", /* _XkbErrFileNotFound */ + "cannot open", /* _XkbErrFileCannotOpen */ + "bad value", /* _XkbErrBadValue */ + "bad match", /* _XkbErrBadMatch */ + "illegal name for type", /* _XkbErrBadTypeName */ + "illegal width for type", /* _XkbErrBadTypeWidth */ + "bad file type", /* _XkbErrBadFileType */ + "bad file version", /* _XkbErrBadFileVersion */ + "error in Xkm file", /* _XkbErrBadFileFormat */ + "allocation failed", /* _XkbErrBadAlloc */ + "bad length", /* _XkbErrBadLength */ + "X request failed", /* _XkbErrXReqFailure */ + "not implemented" /* _XkbErrBadImplementation */ +}; + +unsigned _XkbErrCode; +char * _XkbErrLocation= NULL; +unsigned _XkbErrData; + diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c new file mode 100644 index 000000000..d07a704c3 --- /dev/null +++ b/xkb/xkbfmisc.c @@ -0,0 +1,716 @@ +/* $Xorg: xkbmisc.c,v 1.4 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + + 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 name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS 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. + + ********************************************************/ + +#include +#include +#ifndef X_NOT_STDC_ENV +#include +#endif + +#define XK_CYRILLIC + +#include +#include + +#ifndef XKB_IN_SERVER + +#include +#include +#include +#include +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include "XKBsrv.h" +#include + +#endif + +unsigned +#if NeedFunctionPrototypes +_XkbKSCheckCase(KeySym ks) +#else +_XkbKSCheckCase(ks) + KeySym ks; +#endif +{ +unsigned set,rtrn; +unsigned char ch; + + set= (ks & (~0xff)); + ch= (char)(ks&0xff); + rtrn= 0; + switch (set) { + case 0: /* latin 1 */ + if (((ch>=XK_A)&&(ch<=XK_Z))|| + ((ch>=XK_Agrave)&&(ch<=XK_THORN)&&(ch!=XK_multiply))) { + rtrn|= _XkbKSUpper; + } + if (((ch>=XK_a)&&(ch<=XK_z))|| + ((ch>=XK_agrave)&&(ch<=XK_ydiaeresis))) { + rtrn|= _XkbKSLower; + } + break; + } + return rtrn; +} + +/***===================================================================***/ + +int +#if NeedFunctionPrototypes +_XkbStrCaseCmp(char *str1,char *str2) +#else +_XkbStrCaseCmp(str1,str2) + char * str1; + char * str2; +#endif +{ + char buf1[512],buf2[512]; + char c, *s; + register int n; + + for (n=0, s = buf1; (c = *str1++); n++) { + if (isupper(c)) + c = tolower(c); + if (n>510) + break; + *s++ = c; + } + *s = '\0'; + for (n=0, s = buf2; (c = *str2++); n++) { + if (isupper(c)) + c = tolower(c); + if (n>510) + break; + *s++ = c; + } + *s = '\0'; + return (strcmp(buf1, buf2)); +} + +/***===================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbLookupGroupAndLevel( XkbDescPtr xkb, + int key, + int * mods_inout, + int * grp_inout, + int * lvl_rtrn) +#else +XkbLookupGroupAndLevel(xkb,key,mods_inout,grp_inout,lvl_rtrn) + XkbDescPtr xkb; + int key; + int * mods_inout; + int * grp_inout; + int * lvl_rtrn; +#endif +{ +int nG,eG; + + if ((!xkb)||(!XkbKeycodeInRange(xkb,key))||(!grp_inout)) + return False; + + nG= XkbKeyNumGroups(xkb,key); + eG= *grp_inout; + + if ( nG==0 ) { + *grp_inout= 0; + if (lvl_rtrn!=NULL) + *lvl_rtrn= 0; + return False; + } + else if ( nG==1 ) { + eG= 0; + } + else if ( eG>=nG ) { + unsigned gI= XkbKeyGroupInfo(xkb,key); + switch (XkbOutOfRangeGroupAction(gI)) { + default: + eG %= nG; + break; + case XkbClampIntoRange: + eG = nG-1; + break; + case XkbRedirectIntoRange: + eG = XkbOutOfRangeGroupNumber(gI); + if (eG>=nG) + eG= 0; + break; + } + } + *grp_inout= eG; + if (mods_inout!=NULL) { + XkbKeyTypePtr type; + int preserve; + + type = XkbKeyKeyType(xkb,key,eG); + if (lvl_rtrn!=NULL) + *lvl_rtrn= 0; + preserve= 0; + if (type->map) { /* find the shift level */ + register int i; + register XkbKTMapEntryPtr entry; + for (i=0,entry=type->map;imap_count;i++,entry++) { + if ((entry->active)&& + (((*mods_inout)&type->mods.mask)==entry->mods.mask)){ + if (lvl_rtrn!=NULL) + *lvl_rtrn= entry->level; + if (type->preserve) + preserve= type->preserve[i].mask; + break; + } + } + } + (*mods_inout)&= ~(type->mods.mask&(~preserve)); + } + return True; +} + +/***===================================================================***/ + +static Bool +#if NeedFunctionPrototypes +XkbWriteSectionFromName(FILE *file,char *sectionName,char *name) +#else +XkbWriteSectionFromName(file,sectionName,name) + FILE * file; + char * sectionName; + char * name; +#endif +{ + fprintf(file," xkb_%-20s { include \"%s\" };\n",sectionName,name); + return True; +} + +#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%'))) +#define COMPLETE(n) ((n)&&(!NEED_DESC(n))) + +/* ARGSUSED */ +static void +#if NeedFunctionPrototypes +_AddIncl( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + int index, + void * priv) +#else +_AddIncl(file,result,topLevel,showImplicit,index,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + int index; + void * priv; +#endif +{ + if ((priv)&&(strcmp(priv,"%")!=0)) + fprintf(file," include \"%s\"\n",(char *)priv); + return; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeymapForNames( FILE * file, + XkbComponentNamesPtr names, + Display * dpy, + XkbDescPtr xkb, + unsigned want, + unsigned need) +#else +XkbWriteXKBKeymapForNames(file,names,dpy,xkb,want,need) + FILE * file; + XkbComponentNamesPtr names; + Display * dpy; + XkbDescPtr xkb; + unsigned want; + unsigned need; +#endif +{ +char * name,*tmp; +unsigned complete; +XkbNamesPtr old_names; +int multi_section; +unsigned wantNames,wantConfig,wantDflts; +XkbFileInfo finfo; + + bzero(&finfo,sizeof(XkbFileInfo)); + + complete= 0; + if ((name=names->keymap)==NULL) name= "default"; + if (COMPLETE(names->keycodes)) complete|= XkmKeyNamesMask; + if (COMPLETE(names->types)) complete|= XkmTypesMask; + if (COMPLETE(names->compat)) complete|= XkmCompatMapMask; + if (COMPLETE(names->symbols)) complete|= XkmSymbolsMask; + if (COMPLETE(names->geometry)) complete|= XkmGeometryMask; + want|= (complete|need); + if (want&XkmSymbolsMask) + want|= XkmKeyNamesMask|XkmTypesMask; + + if (want==0) + return False; + + if (xkb!=NULL) { + old_names= xkb->names; + finfo.type= 0; + finfo.defined= 0; + finfo.xkb= xkb; + if (!XkbDetermineFileType(&finfo,XkbXKBFile,NULL)) + return False; + } + else old_names= NULL; + + wantConfig= want&(~complete); + if (xkb!=NULL) { + if (wantConfig&XkmTypesMask) { + if ((!xkb->map) || (xkb->map->num_typescompat) || (xkb->compat->num_si<1)) + wantConfig&= ~XkmCompatMapMask; + } + if (wantConfig&XkmSymbolsMask) { + if ((!xkb->map) || (!xkb->map->key_sym_map)) + wantConfig&= ~XkmSymbolsMask; + } + if (wantConfig&XkmIndicatorsMask) { + if (!xkb->indicators) + wantConfig&= ~XkmIndicatorsMask; + } + if (wantConfig&XkmKeyNamesMask) { + if ((!xkb->names)||(!xkb->names->keys)) + wantConfig&= ~XkmKeyNamesMask; + } + if ((wantConfig&XkmGeometryMask)&&(!xkb->geom)) + wantConfig&= ~XkmGeometryMask; + } + else { + wantConfig= 0; + } + complete|= wantConfig; + + wantDflts= 0; + wantNames= want&(~complete); + if ((xkb!=NULL) && (old_names!=NULL)) { + if (wantNames&XkmTypesMask) { + if (old_names->types!=None) { + tmp= XkbAtomGetString(dpy,old_names->types); + names->types= _XkbDupString(tmp); + } + else { + wantDflts|= XkmTypesMask; + } + complete|= XkmTypesMask; + } + if (wantNames&XkmCompatMapMask) { + if (old_names->compat!=None) { + tmp= XkbAtomGetString(dpy,old_names->compat); + names->compat= _XkbDupString(tmp); + } + else wantDflts|= XkmCompatMapMask; + complete|= XkmCompatMapMask; + } + if (wantNames&XkmSymbolsMask) { + if (old_names->symbols==None) + return False; + tmp= XkbAtomGetString(dpy,old_names->symbols); + names->symbols= _XkbDupString(tmp); + complete|= XkmSymbolsMask; + } + if (wantNames&XkmKeyNamesMask) { + if (old_names->keycodes!=None) { + tmp= XkbAtomGetString(dpy,old_names->keycodes); + names->keycodes= _XkbDupString(tmp); + } + else wantDflts|= XkmKeyNamesMask; + complete|= XkmKeyNamesMask; + } + if (wantNames&XkmGeometryMask) { + if (old_names->geometry==None) + return False; + tmp= XkbAtomGetString(dpy,old_names->geometry); + names->geometry= _XkbDupString(tmp); + complete|= XkmGeometryMask; + wantNames&= ~XkmGeometryMask; + } + } + if (complete&XkmCompatMapMask) + complete|= XkmIndicatorsMask|XkmVirtualModsMask; + else if (complete&(XkmSymbolsMask|XkmTypesMask)) + complete|= XkmVirtualModsMask; + if (need & (~complete)) + return False; + if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete))) + return False; + + multi_section= 1; + if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&& + ((complete&(~XkmKeymapLegal))==0)) { + fprintf(file,"xkb_keymap \"%s\" {\n",name); + } + else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&& + ((complete&(~XkmSemanticsLegal))==0)) { + fprintf(file,"xkb_semantics \"%s\" {\n",name); + } + else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&& + ((complete&(~XkmLayoutLegal))==0)) { + fprintf(file,"xkb_layout \"%s\" {\n",name); + } + else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) { + multi_section= 0; + } + else { + return False; + } + + wantNames= complete&(~(wantConfig|wantDflts)); + name= names->keycodes; + if (wantConfig&XkmKeyNamesMask) + XkbWriteXKBKeycodes(file,&finfo,False,False,_AddIncl,name); + else if (wantDflts&XkmKeyNamesMask) + fprintf(stderr,"Default symbols not implemented yet!\n"); + else if (wantNames&XkmKeyNamesMask) + XkbWriteSectionFromName(file,"keycodes",name); + + name= names->types; + if (wantConfig&XkmTypesMask) + XkbWriteXKBKeyTypes(file,&finfo,False,False,_AddIncl,name); + else if (wantDflts&XkmTypesMask) + fprintf(stderr,"Default types not implemented yet!\n"); + else if (wantNames&XkmTypesMask) + XkbWriteSectionFromName(file,"types",name); + + name= names->compat; + if (wantConfig&XkmCompatMapMask) + XkbWriteXKBCompatMap(file,&finfo,False,False,_AddIncl,name); + else if (wantDflts&XkmCompatMapMask) + fprintf(stderr,"Default interps not implemented yet!\n"); + else if (wantNames&XkmCompatMapMask) + XkbWriteSectionFromName(file,"compatibility",name); + + name= names->symbols; + if (wantConfig&XkmSymbolsMask) + XkbWriteXKBSymbols(file,&finfo,False,False,_AddIncl,name); + else if (wantNames&XkmSymbolsMask) + XkbWriteSectionFromName(file,"symbols",name); + + name= names->geometry; + if (wantConfig&XkmGeometryMask) + XkbWriteXKBGeometry(file,&finfo,False,False,_AddIncl,name); + else if (wantNames&XkmGeometryMask) + XkbWriteSectionFromName(file,"geometry",name); + + if (multi_section) + fprintf(file,"};\n"); + return True; +} + +/***====================================================================***/ + +/*ARGSUSED*/ +Status +#if NeedFunctionPrototypes +XkbMergeFile(XkbDescPtr xkb,XkbFileInfo finfo) +#else +XkbMergeFile(xkb,finfo) + XkbDescPtr xkb; + XkbFileInfo *finfo; +#endif +{ + return BadImplementation; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases) +#else +XkbFindKeycodeByName(xkb,name,use_aliases) + XkbDescPtr xkb; + char * name; + Bool use_aliases; +#endif +{ +register int i; + + if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) + return 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0) + return i; + } + if (!use_aliases) + return 0; + if (xkb->geom && xkb->geom->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->geom->key_aliases; + for (i=0;igeom->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,False); + } + } + if (xkb->names && xkb->names->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->names->key_aliases; + for (i=0;inames->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,False); + } + } + return 0; +} + + +unsigned +#if NeedFunctionPrototypes +XkbConvertGetByNameComponents(Bool toXkm,unsigned orig) +#else +XkbConvertGetByNameComponents(toXkm,orig) + Bool toXkm; + unsigned orig; +#endif +{ +unsigned rtrn; + + rtrn= 0; + if (toXkm) { + if (orig&XkbGBN_TypesMask) rtrn|= XkmTypesMask; + if (orig&XkbGBN_CompatMapMask) rtrn|= XkmCompatMapMask; + if (orig&XkbGBN_SymbolsMask) rtrn|= XkmSymbolsMask; + if (orig&XkbGBN_IndicatorMapMask) rtrn|= XkmIndicatorsMask; + if (orig&XkbGBN_KeyNamesMask) rtrn|= XkmKeyNamesMask; + if (orig&XkbGBN_GeometryMask) rtrn|= XkmGeometryMask; + } + else { + if (orig&XkmTypesMask) rtrn|= XkbGBN_TypesMask; + if (orig&XkmCompatMapMask) rtrn|= XkbGBN_CompatMapMask; + if (orig&XkmSymbolsMask) rtrn|= XkbGBN_SymbolsMask; + if (orig&XkmIndicatorsMask) rtrn|= XkbGBN_IndicatorMapMask; + if (orig&XkmKeyNamesMask) rtrn|= XkbGBN_KeyNamesMask; + if (orig&XkmGeometryMask) rtrn|= XkbGBN_GeometryMask; + if (orig!=0) rtrn|= XkbGBN_OtherNamesMask; + } + return rtrn; +} + +unsigned +#if NeedFunctionPrototypes +XkbConvertXkbComponents(Bool toXkm,unsigned orig) +#else +XkbConvertXkbComponents(toXkm,orig) + Bool toXkm; + unsigned orig; +#endif +{ +unsigned rtrn; + + rtrn= 0; + if (toXkm) { + if (orig&XkbClientMapMask) rtrn|= XkmTypesMask|XkmSymbolsMask; + if (orig&XkbServerMapMask) rtrn|= XkmTypesMask|XkmSymbolsMask; + if (orig&XkbCompatMapMask) rtrn|= XkmCompatMapMask; + if (orig&XkbIndicatorMapMask) rtrn|= XkmIndicatorsMask; + if (orig&XkbNamesMask) rtrn|= XkmKeyNamesMask; + if (orig&XkbGeometryMask) rtrn|= XkmGeometryMask; + } + else { + if (orig!=0) rtrn|= XkbNamesMask; + if (orig&XkmTypesMask) rtrn|= XkbClientMapMask; + if (orig&XkmCompatMapMask) + rtrn|= XkbCompatMapMask|XkbIndicatorMapMask; + if (orig&XkmSymbolsMask) rtrn|=XkbClientMapMask|XkbServerMapMask; + if (orig&XkmIndicatorsMask) rtrn|= XkbIndicatorMapMask; + if (orig&XkmKeyNamesMask) + rtrn|= XkbNamesMask|XkbIndicatorMapMask; + if (orig&XkmGeometryMask) rtrn|= XkbGeometryMask; + } + return rtrn; +} + +Bool +#if NeedFunctionPrototypes +XkbDetermineFileType(XkbFileInfoPtr finfo,int format,int *opts_missing) +#else +XkbDetermineFileType(finfo,format,opts_missing) + XkbFileInfoPtr finfo; + int format; + int * opts_missing; +#endif +{ +unsigned present; +XkbDescPtr xkb; + + if ((!finfo)||(!finfo->xkb)) + return False; + if (opts_missing) + *opts_missing= 0; + xkb= finfo->xkb; + present= 0; + if ((xkb->names)&&(xkb->names->keys)) present|= XkmKeyNamesMask; + if ((xkb->map)&&(xkb->map->types)) present|= XkmTypesMask; + if (xkb->compat) present|= XkmCompatMapMask; + if ((xkb->map)&&(xkb->map->num_syms>1)) present|= XkmSymbolsMask; + if (xkb->indicators) present|= XkmIndicatorsMask; + if (xkb->geom) present|= XkmGeometryMask; + if (!present) + return False; + else switch (present) { + case XkmKeyNamesMask: + finfo->type= XkmKeyNamesIndex; + finfo->defined= present; + return True; + case XkmTypesMask: + finfo->type= XkmTypesIndex; + finfo->defined= present; + return True; + case XkmCompatMapMask: + finfo->type= XkmCompatMapIndex; + finfo->defined= present; + return True; + case XkmSymbolsMask: + if (format!=XkbXKMFile) { + finfo->type= XkmSymbolsIndex; + finfo->defined= present; + return True; + } + break; + case XkmGeometryMask: + finfo->type= XkmGeometryIndex; + finfo->defined= present; + return True; + } + if ((present&(~XkmSemanticsLegal))==0) { + if ((XkmSemanticsRequired&present)==XkmSemanticsRequired) { + if (opts_missing) + *opts_missing= XkmSemanticsOptional&(~present); + finfo->type= XkmSemanticsFile; + finfo->defined= present; + return True; + } + } + else if ((present&(~XkmLayoutLegal))==0) { + if ((XkmLayoutRequired&present)==XkmLayoutRequired) { + if (opts_missing) + *opts_missing= XkmLayoutOptional&(~present); + finfo->type= XkmLayoutFile; + finfo->defined= present; + return True; + } + } + else if ((present&(~XkmKeymapLegal))==0) { + if ((XkmKeymapRequired&present)==XkmKeymapRequired) { + if (opts_missing) + *opts_missing= XkmKeymapOptional&(~present); + finfo->type= XkmKeymapFile; + finfo->defined= present; + return True; + } + } + return False; +} + +/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */ +/* wildcards */ + +static unsigned char componentSpecLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +void +#if NeedFunctionPrototypes +XkbEnsureSafeMapName(char *name) +#else +XkbEnsureSafeMapName(name) + char *name; +#endif +{ + if (name==NULL) + return; + while (*name!='\0') { + if ((componentSpecLegal[(*name)/8]&(1<<((*name)%8)))==0) + *name= '_'; + name++; + } + return; +} + +/***====================================================================***/ + +#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/')) + +Bool +#if NeedFunctionPrototypes +XkbNameMatchesPattern(char *name,char *ptrn) +#else +XkbNameMatchesPattern(name,ptrn) + char * name; + char * ptrn; +#endif +{ + while (ptrn[0]!='\0') { + if (name[0]=='\0') { + if (ptrn[0]=='*') { + ptrn++; + continue; + } + return False; + } + if (ptrn[0]=='?') { + if (UNMATCHABLE(name[0])) + return False; + } + else if (ptrn[0]=='*') { + if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn)) + return True; + return XkbNameMatchesPattern(name,ptrn+1); + } + else if (ptrn[0]!=name[0]) + return False; + name++; + ptrn++; + } + /* if we get here, the pattern is exhausted (-:just like me:-) */ + return (name[0]=='\0'); +} diff --git a/xkb/xkbout.c b/xkb/xkbout.c new file mode 100644 index 000000000..845325358 --- /dev/null +++ b/xkb/xkbout.c @@ -0,0 +1,1216 @@ +/* $Xorg: xkbout.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + + 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 name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS 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. + + ********************************************************/ + +#include +#include +#ifndef X_NOT_STDC_ENV +#include +#endif +#include + +#ifndef XKB_IN_SERVER + +#include +#include +#include + +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include "XKBsrv.h" + +#include +#include "extensions/XKBfile.h" + +#endif + +#define VMOD_HIDE_VALUE 0 +#define VMOD_SHOW_VALUE 1 +#define VMOD_COMMENT_VALUE 2 + +static Bool +#if NeedFunctionPrototypes +WriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue) +#else +WriteXKBVModDecl(file,dpy,xkb,showValue) + FILE * file; + Display * dpy; + XkbDescPtr xkb; + int showValue; +#endif +{ +register int i,nMods; +Atom * vmodNames; + + if (xkb==NULL) + return False; + if (xkb->names!=NULL) + vmodNames= xkb->names->vmods; + else vmodNames= NULL; + + for (i=nMods=0;iserver)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) { + if (showValue==VMOD_COMMENT_VALUE) { + fprintf(file,"/* = %s */", + XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); + } + else { + fprintf(file,"= %s", + XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); + } + } + nMods++; + } + } + if (nMods>0) + fprintf(file,";\n\n"); + return True; +} + +/***====================================================================***/ + +static Bool +#if NeedFunctionPrototypes +WriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action) +#else +WriteXKBAction(file,result,action) + FILE * file; + XkbFileInfo * result; + XkbAnyAction * action; +#endif +{ +XkbDescPtr xkb; +Display * dpy; + + xkb= result->xkb; + dpy= xkb->dpy; + fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile)); + return True; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeycodes( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBKeycodes(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Atom kcName; +register unsigned i; +XkbDescPtr xkb; +Display * dpy; +char * alternate; + + xkb= result->xkb; + dpy= xkb->dpy; + if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) { + _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0); + return False; + } + kcName= xkb->names->keycodes; + if (kcName!=None) + fprintf(file,"xkb_keycodes \"%s\" {\n", + XkbAtomText(dpy,kcName,XkbXKBFile)); + else fprintf(file,"xkb_keycodes {\n"); + fprintf(file," minimum = %d;\n",xkb->min_key_code); + fprintf(file," maximum = %d;\n",xkb->max_key_code); + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (xkb->names->keys[i].name[0]!='\0') { + if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) + alternate= "alternate "; + else alternate= ""; + fprintf(file," %s%6s = %d;\n",alternate, + XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile), + i); + } + } + if (xkb->indicators!=NULL) { + for (i=0;iindicators->phys_indicators&(1<names->indicators[i]!=None) { + fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1, + XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile)); + } + } + } + if (xkb->names->key_aliases!=NULL) { + XkbKeyAliasPtr pAl; + pAl= xkb->names->key_aliases; + for (i=0;inames->num_key_aliases;i++,pAl++) { + fprintf(file," alias %6s = %6s;\n", + XkbKeyNameText(pAl->alias,XkbXKBFile), + XkbKeyNameText(pAl->real,XkbXKBFile)); + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeyTypes( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBKeyTypes(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i,n; +XkbKeyTypePtr type; +XkbKTMapEntryPtr entry; +XkbDescPtr xkb; + + xkb= result->xkb; + dpy= xkb->dpy; + if ((!xkb)||(!xkb->map)||(!xkb->map->types)) { + _XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0); + return False; + } + if (xkb->map->num_typesnames==NULL)||(xkb->names->types==None)) + fprintf(file,"xkb_types {\n\n"); + else fprintf(file,"xkb_types \"%s\" {\n\n", + XkbAtomText(dpy,xkb->names->types,XkbXKBFile)); + WriteXKBVModDecl(file,dpy,xkb, + (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); + + type= xkb->map->types; + for (i=0;imap->num_types;i++,type++) { + fprintf(file," type \"%s\" {\n", + XkbAtomText(dpy,type->name,XkbXKBFile)); + fprintf(file," modifiers= %s;\n", + XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods, + XkbXKBFile)); + entry= type->map; + for (n=0;nmap_count;n++,entry++) { + char *str; + str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods, + XkbXKBFile); + fprintf(file," map[%s]= Level%d;\n",str,entry->level+1); + if ((type->preserve)&&((type->preserve[n].real_mods)|| + (type->preserve[n].vmods))) { + fprintf(file," preserve[%s]= ",str); + fprintf(file,"%s;\n",XkbVModMaskText(dpy,xkb, + type->preserve[n].real_mods, + type->preserve[n].vmods, + XkbXKBFile)); + } + } + if (type->level_names!=NULL) { + Atom *name= type->level_names; + for (n=0;nnum_levels;n++,name++) { + if ((*name)==None) + continue; + fprintf(file," level_name[Level%d]= \"%s\";\n",n+1, + XkbAtomText(dpy,*name,XkbXKBFile)); + } + } + fprintf(file," };\n"); + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBIndicatorMap( FILE * file, + XkbFileInfo * result, + Atom name, + XkbIndicatorMapPtr led, + XkbFileAddOnFunc addOn, + void * priv) +#else +WriteXKBIndicatorMap(file,result,name,led,addOn,priv) + FILE * file; + XkbFileInfo * result; + Atom name; + XkbIndicatorMapPtr led; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +XkbDescPtr xkb; + + xkb= result->xkb; + fprintf(file," indicator \"%s\" {\n",XkbAtomGetString(xkb->dpy,name)); + if (led->flags&XkbIM_NoExplicit) + fprintf(file," !allowExplicit;\n"); + if (led->flags&XkbIM_LEDDrivesKB) + fprintf(file," indicatorDrivesKeyboard;\n"); + if (led->which_groups!=0) { + if (led->which_groups!=XkbIM_UseEffective) { + fprintf(file," whichGroupState= %s;\n", + XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile)); + } + fprintf(file," groups= 0x%02x;\n",led->groups); + } + if (led->which_mods!=0) { + if (led->which_mods!=XkbIM_UseEffective) { + fprintf(file," whichModState= %s;\n", + XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile)); + } + fprintf(file," modifiers= %s;\n", + XkbVModMaskText(xkb->dpy,xkb, + led->mods.real_mods,led->mods.vmods, + XkbXKBFile)); + } + if (led->ctrls!=0) { + fprintf(file," controls= %s;\n", + XkbControlsMaskText(led->ctrls,XkbXKBFile)); + } + if (addOn) + (*addOn)(file,result,False,True,XkmIndicatorsIndex,priv); + fprintf(file," };\n"); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBCompatMap( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBCompatMap(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i; +XkbSymInterpretPtr interp; +XkbDescPtr xkb; + + xkb= result->xkb; + dpy= xkb->dpy; + if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) { + _XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0); + return False; + } + if ((xkb->names==NULL)||(xkb->names->compat==None)) + fprintf(file,"xkb_compatibility {\n\n"); + else fprintf(file,"xkb_compatibility \"%s\" {\n\n", + XkbAtomText(dpy,xkb->names->compat,XkbXKBFile)); + WriteXKBVModDecl(file,dpy,xkb, + (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); + + fprintf(file," interpret.useModMapMods= AnyLevel;\n"); + fprintf(file," interpret.repeat= False;\n"); + fprintf(file," interpret.locking= False;\n"); + interp= xkb->compat->sym_interpret; + for (i=0;icompat->num_si;i++,interp++) { + fprintf(file," interpret %s+%s(%s) {\n", + ((interp->sym==NoSymbol)?"Any": + XkbKeysymText(interp->sym,XkbXKBFile)), + XkbSIMatchText(interp->match,XkbXKBFile), + XkbModMaskText(interp->mods,XkbXKBFile)); + if (interp->virtual_mod!=XkbNoModifier) { + fprintf(file," virtualModifier= %s;\n", + XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile)); + } + if (interp->match&XkbSI_LevelOneOnly) + fprintf(file," useModMapMods=level1;\n"); + if (interp->flags&XkbSI_LockingKey) + fprintf(file," locking= True;\n"); + if (interp->flags&XkbSI_AutoRepeat) + fprintf(file," repeat= True;\n"); + fprintf(file," action= "); + WriteXKBAction(file,result,&interp->act); + fprintf(file,";\n"); + fprintf(file," };\n"); + } + for (i=0;icompat->groups[i]; + if ((gc->real_mods==0)&&(gc->vmods==0)) + continue; + fprintf(file," group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb, + gc->real_mods,gc->vmods, + XkbXKBFile)); + } + if (xkb->indicators) { + for (i=0;iindicators->maps[i]; + if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)|| + (map->which_mods!=0)|| + (map->mods.real_mods!=0)||(map->mods.vmods!=0)|| + (map->ctrls!=0)) { + WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map, + addOn,priv); + } + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBSymbols( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBSymbols(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i,tmp; +XkbDescPtr xkb; +XkbClientMapPtr map; +XkbServerMapPtr srv; +Bool showActions; + + xkb= result->xkb; + map= xkb->map; + srv= xkb->server; + dpy= xkb->dpy; + if ((!xkb)||(!map)||(!map->syms)||(!map->key_sym_map)) { + _XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0); + return False; + } + if ((!xkb->names)||(!xkb->names->keys)) { + _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0); + return False; + } + if ((xkb->names==NULL)||(xkb->names->symbols==None)) + fprintf(file,"xkb_symbols {\n\n"); + else fprintf(file,"xkb_symbols \"%s\" {\n\n", + XkbAtomText(dpy,xkb->names->symbols,XkbXKBFile)); + for (tmp=i=0;inames->groups[i]!=None) { + fprintf(file," name[group%d]=\"%s\";\n",i+1, + XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile)); + tmp++; + } + } + if (tmp>0) + fprintf(file,"\n"); + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + Bool simple; + if ((int)XkbKeyNumSyms(xkb,i)<1) + continue; + if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) + continue; + simple= True; + fprintf(file," key %6s {", + XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile)); + if (srv->explicit) { + if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)|| + (showImplicit)) { + int typeNdx,g; + Bool multi; + char * comment=" "; + + if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0) + comment= "//"; + multi= False; + typeNdx= XkbKeyKeyTypeIndex(xkb,i,0); + for (g=1;(gexplicit[i]&(1<types[typeNdx].name, + XkbXKBFile)); + } + else if (showImplicit) { + fprintf(file,"\n// type[group%d]= \"%s\",",g+1, + XkbAtomText(dpy,map->types[typeNdx].name, + XkbXKBFile)); + } + } + } + else { + fprintf(file,"\n%s type= \"%s\",",comment, + XkbAtomText(dpy,map->types[typeNdx].name, + XkbXKBFile)); + } + simple= False; + } + if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&& + (xkb->ctrls!=NULL)) { + if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8))) + fprintf(file,"\n repeat= Yes,"); + else fprintf(file,"\n repeat= No,"); + simple= False; + } + if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&& + (xkb->server->vmodmap[i]!=0)) { + if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) { + fprintf(file,"\n virtualMods= %s,", + XkbVModMaskText(dpy,xkb,0, + xkb->server->vmodmap[i], + XkbXKBFile)); + } + else if (showImplicit) { + fprintf(file,"\n// virtualMods= %s,", + XkbVModMaskText(dpy,xkb,0, + xkb->server->vmodmap[i], + XkbXKBFile)); + } + } + } + switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) { + case XkbClampIntoRange: + fprintf(file,"\n groupsClamp,"); + break; + case XkbRedirectIntoRange: + fprintf(file,"\n groupsRedirect= Group%d,", + XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1); + break; + } + if (srv->behaviors!=NULL) { + unsigned type; + type= srv->behaviors[i].type&XkbKB_OpMask; + + if (type!=XkbKB_Default) { + simple= False; + fprintf(file,"\n %s,", + XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile)); + } + } + if ((srv->explicit==NULL) || showImplicit || + ((srv->explicit[i]&XkbExplicitInterpretMask)!=0)) + showActions= XkbKeyHasActions(xkb,i); + else showActions= False; + + if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions) + simple= False; + if (simple) { + KeySym *syms; + unsigned s; + + syms= XkbKeySymsPtr(xkb,i); + fprintf(file," [ "); + for (s=0;smodmap) { + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (map->modmap[i]!=0) { + register int n,bit; + for (bit=1,n=0;nmodmap[i]&bit) { + char buf[5]; + memcpy(buf,xkb->names->keys[i].name,4); + buf[4]= '\0'; + fprintf(file," modifier_map %s { <%s> };\n", + XkbModIndexText(n,XkbXKBFile),buf); + } + } + } + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBOutline( FILE * file, + XkbShapePtr shape, + XkbOutlinePtr outline, + int lastRadius, + int first, + int indent) +#else +WriteXKBOutline(file,shape,outline,lastRadius,first,indent) + FILE * file; + XkbShapePtr shape; + XkbOutlinePtr outline; + int lastRadius; + int first; + int indent; +#endif +{ +register int i; +XkbPointPtr pt; +char * iStr; + + fprintf(file,"%s",iStr= XkbIndentText(first)); + if (first!=indent) + iStr= XkbIndentText(indent); + if (outline->corner_radius!=lastRadius) { + fprintf(file,"corner= %s,", + XkbGeomFPText(outline->corner_radius,XkbMessage)); + if (shape!=NULL) { + fprintf(file,"\n%s",iStr); + } + } + if (shape) { + if (outline==shape->approx) + fprintf(file,"approx= "); + else if (outline==shape->primary) + fprintf(file,"primary= "); + } + fprintf(file,"{"); + for (pt=outline->points,i=0;inum_points;i++,pt++) { + if (i==0) fprintf(file," "); + else if ((i%4)==0) fprintf(file,",\n%s ",iStr); + else fprintf(file,", "); + fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile), + XkbGeomFPText(pt->y,XkbXKBFile)); + } + fprintf(file," }"); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBDoodad( FILE * file, + Display * dpy, + unsigned indent, + XkbGeometryPtr geom, + XkbDoodadPtr doodad) +#else +WriteXKBDoodad(file,dpy,indent,geom,doodad) + FILE * file; + Display * dpy; + unsigned indent; + XkbGeometryPtr geom; + XkbDoodadPtr doodad; +#endif +{ +register char * i_str; +XkbShapePtr shape; +XkbColorPtr color; + + i_str= XkbIndentText(indent); + fprintf(file,"%s%s \"%s\" {\n",i_str, + XkbDoodadTypeText(doodad->any.type,XkbMessage), + XkbAtomText(dpy,doodad->any.name,XkbMessage)); + fprintf(file,"%s top= %s;\n",i_str, + XkbGeomFPText(doodad->any.top,XkbXKBFile)); + fprintf(file,"%s left= %s;\n",i_str, + XkbGeomFPText(doodad->any.left,XkbXKBFile)); + fprintf(file,"%s priority= %d;\n",i_str,doodad->any.priority); + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if (doodad->shape.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->shape.angle,XkbXKBFile)); + } + if (doodad->shape.color_ndx!=0) { + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbShapeDoodadColor(geom,&doodad->shape)->spec); + } + shape= XkbShapeDoodadShape(geom,&doodad->shape); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(dpy,shape->name,XkbXKBFile)); + break; + case XkbTextDoodad: + if (doodad->text.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->text.angle,XkbXKBFile)); + } + if (doodad->text.width!=0) { + fprintf(file,"%s width= %s;\n",i_str, + XkbGeomFPText(doodad->text.width,XkbXKBFile)); + + } + if (doodad->text.height!=0) { + fprintf(file,"%s height= %s;\n",i_str, + XkbGeomFPText(doodad->text.height,XkbXKBFile)); + + } + if (doodad->text.color_ndx!=0) { + color= XkbTextDoodadColor(geom,&doodad->text); + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + } + fprintf(file,"%s XFont= \"%s\";\n",i_str, + XkbStringText(doodad->text.font,XkbXKBFile)); + fprintf(file,"%s text= \"%s\";\n",i_str, + XkbStringText(doodad->text.text,XkbXKBFile)); + break; + case XkbIndicatorDoodad: + shape= XkbIndicatorDoodadShape(geom,&doodad->indicator); + color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator); + fprintf(file,"%s onColor= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator); + fprintf(file,"%s offColor= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(dpy,shape->name,XkbXKBFile)); + break; + case XkbLogoDoodad: + fprintf(file,"%s logoName= \"%s\";\n",i_str, + XkbStringText(doodad->logo.logo_name,XkbXKBFile)); + if (doodad->shape.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->logo.angle,XkbXKBFile)); + } + if (doodad->shape.color_ndx!=0) { + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbLogoDoodadColor(geom,&doodad->logo)->spec); + } + shape= XkbLogoDoodadShape(geom,&doodad->logo); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(dpy,shape->name,XkbXKBFile)); + break; + } + fprintf(file,"%s};\n",i_str); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +WriteXKBOverlay( FILE * file, + Display * dpy, + unsigned indent, + XkbGeometryPtr geom, + XkbOverlayPtr ol) +#else +WriteXKBOverlay(file,dpy,indent,geom,ol) + FILE * file; + Display * dpy; + unsigned indent; + XkbGeometryPtr geom; + XkbOverlayPtr ol; +#endif +{ +register char * i_str; +int r,k,nOut; +XkbOverlayRowPtr row; +XkbOverlayKeyPtr key; + + i_str= XkbIndentText(indent); + if (ol->name!=None) { + fprintf(file,"%soverlay \"%s\" {\n",i_str, + XkbAtomText(dpy,ol->name,XkbMessage)); + } + else fprintf(file,"%soverlay {\n",i_str); + for (nOut=r=0,row=ol->rows;rnum_rows;r++,row++) { + for (k=0,key=row->keys;knum_keys;k++,key++) { + char *over,*under; + over= XkbKeyNameText(key->over.name,XkbXKBFile); + under= XkbKeyNameText(key->under.name,XkbXKBFile); + if (nOut==0) + fprintf(file,"%s %6s=%6s",i_str,under,over); + else if ((nOut%4)==0) + fprintf(file,",\n%s %6s=%6s",i_str,under,over); + else fprintf(file,", %6s=%6s",under,over); + nOut++; + } + } + fprintf(file,"\n%s};\n",i_str); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBSection( FILE * file, + Display * dpy, + XkbSectionPtr s, + XkbGeometryPtr geom) +#else +WriteXKBSection(file,dpy,s,geom) + FILE * file; + Display * dpy; + XkbSectionPtr s; + XkbGeometryPtr geom; +#endif +{ +register int i; +XkbRowPtr row; +int dfltKeyColor; + + fprintf(file," section \"%s\" {\n", + XkbAtomText(dpy,s->name,XkbXKBFile)); + if (s->rows&&(s->rows->num_keys>0)) { + dfltKeyColor= s->rows->keys[0].color_ndx; + fprintf(file," key.color= \"%s\";\n", + XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile)); + } + fprintf(file," priority= %d;\n",s->priority); + fprintf(file," top= %s;\n",XkbGeomFPText(s->top,XkbXKBFile)); + fprintf(file," left= %s;\n",XkbGeomFPText(s->left,XkbXKBFile)); + fprintf(file," width= %s;\n",XkbGeomFPText(s->width,XkbXKBFile)); + fprintf(file," height= %s;\n", + XkbGeomFPText(s->height,XkbXKBFile)); + if (s->angle!=0) { + fprintf(file," angle= %s;\n", + XkbGeomFPText(s->angle,XkbXKBFile)); + } + for (i=0,row=s->rows;inum_rows;i++,row++) { + fprintf(file," row {\n"); + fprintf(file," top= %s;\n", + XkbGeomFPText(row->top,XkbXKBFile)); + fprintf(file," left= %s;\n", + XkbGeomFPText(row->left,XkbXKBFile)); + if (row->vertical) + fprintf(file," vertical;\n"); + if (row->num_keys>0) { + register int k; + register XkbKeyPtr key; + int forceNL=0; + int nThisLine= 0; + fprintf(file," keys {\n"); + for (k=0,key=row->keys;knum_keys;k++,key++) { + XkbShapePtr shape; + if (key->color_ndx!=dfltKeyColor) + forceNL= 1; + if (k==0) { + fprintf(file," "); + nThisLine= 0; + } + else if (((nThisLine%2)==1)||(forceNL)) { + fprintf(file,",\n "); + forceNL= nThisLine= 0; + } + else { + fprintf(file,", "); + nThisLine++; + } + shape= XkbKeyShape(geom,key); + fprintf(file,"{ %6s, \"%s\", %3s", + XkbKeyNameText(key->name.name,XkbXKBFile), + XkbAtomText(dpy,shape->name,XkbXKBFile), + XkbGeomFPText(key->gap,XkbXKBFile)); + if (key->color_ndx!=dfltKeyColor) { + fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec); + forceNL= 1; + } + fprintf(file," }"); + } + fprintf(file,"\n };\n"); + } + fprintf(file," };\n"); + } + if (s->doodads!=NULL) { + XkbDoodadPtr doodad; + for (i=0,doodad=s->doodads;inum_doodads;i++,doodad++) { + WriteXKBDoodad(file,dpy,8,geom,doodad); + } + } + if (s->overlays!=NULL) { + XkbOverlayPtr ol; + for (i=0,ol=s->overlays;inum_overlays;i++,ol++) { + WriteXKBOverlay(file,dpy,8,geom,ol); + } + } + fprintf(file," }; // End of \"%s\" section\n\n", + XkbAtomText(dpy,s->name,XkbXKBFile)); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBGeometry( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBGeometry(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i,n; +XkbDescPtr xkb; +XkbGeometryPtr geom; + + xkb= result->xkb; + if ((!xkb)||(!xkb->geom)) { + _XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0); + return False; + } + dpy= xkb->dpy; + geom= xkb->geom; + if (geom->name==None) + fprintf(file,"xkb_geometry {\n\n"); + else fprintf(file,"xkb_geometry \"%s\" {\n\n", + XkbAtomText(dpy,geom->name,XkbXKBFile)); + fprintf(file," width= %s;\n", + XkbGeomFPText(geom->width_mm,XkbXKBFile)); + fprintf(file," height= %s;\n\n", + XkbGeomFPText(geom->height_mm,XkbXKBFile)); + + if (geom->key_aliases!=NULL) { + XkbKeyAliasPtr pAl; + pAl= geom->key_aliases; + for (i=0;inum_key_aliases;i++,pAl++) { + fprintf(file," alias %6s = %6s;\n", + XkbKeyNameText(pAl->alias,XkbXKBFile), + XkbKeyNameText(pAl->real,XkbXKBFile)); + } + fprintf(file,"\n"); + } + + if (geom->base_color!=NULL) + fprintf(file," baseColor= \"%s\";\n", + XkbStringText(geom->base_color->spec,XkbXKBFile)); + if (geom->label_color!=NULL) + fprintf(file," labelColor= \"%s\";\n", + XkbStringText(geom->label_color->spec,XkbXKBFile)); + if (geom->label_font!=NULL) + fprintf(file," xfont= \"%s\";\n", + XkbStringText(geom->label_font,XkbXKBFile)); + if ((geom->num_colors>0)&&(showImplicit)) { + XkbColorPtr color; + for (color=geom->colors,i=0;inum_colors;i++,color++) { + fprintf(file,"// color[%d]= \"%s\"\n",i, + XkbStringText(color->spec,XkbXKBFile)); + } + fprintf(file,"\n"); + } + if (geom->num_properties>0) { + XkbPropertyPtr prop; + for (prop=geom->properties,i=0;inum_properties;i++,prop++) { + fprintf(file," %s= \"%s\";\n",prop->name, + XkbStringText(prop->value,XkbXKBFile)); + } + fprintf(file,"\n"); + } + if (geom->num_shapes>0) { + XkbShapePtr shape; + XkbOutlinePtr outline; + int lastR; + for (shape=geom->shapes,i=0;inum_shapes;i++,shape++) { + lastR=0; + fprintf(file," shape \"%s\" {", + XkbAtomText(dpy,shape->name,XkbXKBFile)); + outline= shape->outlines; + if (shape->num_outlines>1) { + for (n=0;nnum_outlines;n++,outline++) { + if (n==0) fprintf(file,"\n"); + else fprintf(file,",\n"); + WriteXKBOutline(file,shape,outline,lastR,8,8); + lastR= outline->corner_radius; + } + fprintf(file,"\n };\n"); + } + else { + WriteXKBOutline(file,NULL,outline,lastR,1,8); + fprintf(file," };\n"); + } + } + } + if (geom->num_sections>0) { + XkbSectionPtr section; + for (section=geom->sections,i=0;inum_sections;i++,section++){ + WriteXKBSection(file,dpy,section,geom); + } + } + if (geom->num_doodads>0) { + XkbDoodadPtr doodad; + for (i=0,doodad=geom->doodads;inum_doodads;i++,doodad++) { + WriteXKBDoodad(file,dpy,4,geom,doodad); + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +/*ARGSUSED*/ +Bool +#if NeedFunctionPrototypes +XkbWriteXKBSemantics( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBSemantics(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; + + fprintf(file,"xkb_semantics {\n"); + ok= XkbWriteXKBKeyTypes(file,result,False,False,addOn,priv); + ok= ok&&XkbWriteXKBCompatMap(file,result,False,False,addOn,priv); + fprintf(file,"};\n"); + return ok; +} + +/*ARGSUSED*/ +Bool +#if NeedFunctionPrototypes +XkbWriteXKBLayout( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBLayout(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; +XkbDescPtr xkb; + + xkb= result->xkb; + fprintf(file,"xkb_layout {\n"); + ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv); + if (xkb->geom) + ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv); + fprintf(file,"};\n"); + return ok; +} + +/*ARGSUSED*/ +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeymap( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBKeymap(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; +XkbDescPtr xkb; + + xkb= result->xkb; + fprintf(file,"xkb_keymap {\n"); + ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBCompatMap(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv); + if (xkb->geom) + ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv); + fprintf(file,"};\n"); + return ok; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBFile( FILE * out, + XkbFileInfo * result, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBFile(out,result,showImplicit,addOn,priv) + FILE * out; + XkbFileInfo * result; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; +Bool (*func)( +#if NeedFunctionPrototypes + FILE * /* file */, + XkbFileInfo * /* result */, + Bool /* topLevel */, + Bool /* showImplicit */, + XkbFileAddOnFunc /* addOn */, + void * /* priv */ +#endif +); + + switch (result->type) { + case XkmSemanticsFile: + func= XkbWriteXKBSemantics; + break; + case XkmLayoutFile: + func= XkbWriteXKBLayout; + break; + case XkmKeymapFile: + func= XkbWriteXKBKeymap; + break; + case XkmTypesIndex: + func= XkbWriteXKBKeyTypes; + break; + case XkmCompatMapIndex: + func= XkbWriteXKBCompatMap; + break; + case XkmSymbolsIndex: + func= XkbWriteXKBSymbols; + break; + case XkmKeyNamesIndex: + func= XkbWriteXKBKeycodes; + break; + case XkmGeometryFile: + case XkmGeometryIndex: + func= XkbWriteXKBGeometry; + break; + case XkmVirtualModsIndex: + case XkmIndicatorsIndex: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(result->type,XkbMessage),0); + return False; + } + if (out==NULL) { + _XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXkbFile",0); + ok= False; + } + else { + ok= (*func)(out,result,True,showImplicit,addOn,priv); + } + if (!ok) { + return False; + } + return True; +} + diff --git a/xkb/xkbtext.c b/xkb/xkbtext.c new file mode 100644 index 000000000..18c07a18a --- /dev/null +++ b/xkb/xkbtext.c @@ -0,0 +1,1700 @@ +/* $Xorg: xkbtext.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + + 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 name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS 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. + + ********************************************************/ + +#include +#include +#ifndef X_NOT_STDC_ENV +#include +#endif + +#include + +#ifndef XKB_IN_SERVER + +#include +#include +#include + +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include "XKBsrv.h" +#include "XKBgeom.h" + +#endif + +/***====================================================================***/ + +#define BUFFER_SIZE 512 + +static char textBuffer[BUFFER_SIZE]; +static int tbNext= 0; + +static char * +#if NeedFunctionPrototypes +tbGetBuffer(unsigned size) +#else +tbGetBuffer(size) + unsigned size; +#endif +{ +char *rtrn; + + if (size>=BUFFER_SIZE) + return NULL; + if ((BUFFER_SIZE-tbNext)<=size) + tbNext= 0; + rtrn= &textBuffer[tbNext]; + tbNext+= size; + return rtrn; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbAtomText(Display *dpy,Atom atm,unsigned format) +#else +XkbAtomText(dpy,atm,format) + Display * dpy; + Atom atm; + unsigned format; +#endif +{ +char *rtrn,*tmp; + + tmp= XkbAtomGetString(dpy,atm); + if (tmp!=NULL) { + int len; + len= strlen(tmp)+1; + if (len>BUFFER_SIZE) + len= BUFFER_SIZE-2; + rtrn= tbGetBuffer(len); + strncpy(rtrn,tmp,len); + rtrn[len]= '\0'; + } + else { + rtrn= tbGetBuffer(1); + rtrn[0]= '\0'; + } + if (format==XkbCFile) { + for (tmp=rtrn;*tmp!='\0';tmp++) { + if ((tmp==rtrn)&&(!isalpha(*tmp))) + *tmp= '_'; + else if (!isalnum(*tmp)) + *tmp= '_'; + } + } + return XkbStringText(rtrn,format); +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbVModIndexText(Display *dpy,XkbDescPtr xkb,unsigned ndx,unsigned format) +#else +XkbVModIndexText(dpy,xkb,ndx,format) + Display * dpy; + XkbDescPtr xkb; + unsigned ndx; + unsigned format; +#endif +{ +register int len; +register Atom *vmodNames; +char *rtrn,*tmp; +char numBuf[20]; + + if (xkb && xkb->names) + vmodNames= xkb->names->vmods; + else vmodNames= NULL; + + tmp= NULL; + if (ndx>=XkbNumVirtualMods) + tmp= "illegal"; + else if (vmodNames&&(vmodNames[ndx]!=None)) + tmp= XkbAtomGetString(dpy,vmodNames[ndx]); + if (tmp==NULL) + sprintf(tmp=numBuf,"%d",ndx); + + len= strlen(tmp)+1; + if (format==XkbCFile) + len+= 4; + if (len>=BUFFER_SIZE) + len= BUFFER_SIZE-1; + rtrn= tbGetBuffer(len); + if (format==XkbCFile) { + strcpy(rtrn,"vmod_"); + strncpy(&rtrn[5],tmp,len-4); + } + else strncpy(rtrn,tmp,len); + return rtrn; +} + +char * +#if NeedFunctionPrototypes +XkbVModMaskText( Display * dpy, + XkbDescPtr xkb, + unsigned modMask, + unsigned mask, + unsigned format) +#else +XkbVModMaskText(dpy,xkb,modMask,mask,format) + Display * dpy; + XkbDescPtr xkb; + unsigned modMask; + unsigned mask; + unsigned format; +#endif +{ +register int i,bit; +int len; +char *mm,*rtrn; +char *str,buf[BUFFER_SIZE]; + + if ((modMask==0)&&(mask==0)) { + rtrn= tbGetBuffer(5); + if (format==XkbCFile) + sprintf(rtrn,"0"); + else sprintf(rtrn,"none"); + return rtrn; + } + if (modMask!=0) + mm= XkbModMaskText(modMask,format); + else mm= NULL; + + str= buf; + buf[0]= '\0'; + if (mask) { + char *tmp; + for (i=0,bit=1;i=BUFFER_SIZE) + len= BUFFER_SIZE-1; + rtrn= tbGetBuffer(len+1); + rtrn[0]= '\0'; + + if (mm!=NULL) { + i= strlen(mm); + if (i>len) + i= len; + strcpy(rtrn,mm); + } + else { + i=0; + } + if (str!=NULL) { + if (mm!=NULL) { + if (format==XkbCFile) strcat(rtrn,"|"); + else strcat(rtrn,"+"); + } + strncat(rtrn,str,len-i); + } + rtrn[len]= '\0'; + return rtrn; +} + +static char *modNames[XkbNumModifiers] = { + "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" +}; + +char * +#if NeedFunctionPrototypes +XkbModIndexText(unsigned ndx,unsigned format) +#else +XkbModIndexText(ndx,format) + unsigned ndx; + unsigned format; +#endif +{ +char * rtrn; +char buf[100]; + + if (format==XkbCFile) { + if (ndx0) { + len= strlen(from); + if (len<((*pLeft)-3)) { + strcat(to,from); + *pLeft-= len; + return True; + } + } + *pLeft= -1; + return False; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyNoActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int*sz) +#else +CopyNoActionArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ + return True; +} + +static Bool +#if NeedFunctionPrototypes +CopyModActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int* sz) +#else +CopyModActionArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbModAction * act; +unsigned tmp; + + act= &action->mods; + tmp= XkbModActionVMods(act); + TryCopyStr(buf,"modifiers=",sz); + if (act->flags&XkbSA_UseModMapMods) + TryCopyStr(buf,"modMapMods",sz); + else if (act->real_mods || tmp) { + TryCopyStr(buf, + XkbVModMaskText(dpy,xkb,act->real_mods,tmp,XkbXKBFile), + sz); + } + else TryCopyStr(buf,"none",sz); + if (act->type==XkbSA_LockMods) + return True; + if (act->flags&XkbSA_ClearLocks) + TryCopyStr(buf,",clearLocks",sz); + if (act->flags&XkbSA_LatchToLock) + TryCopyStr(buf,",latchToLock",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyGroupActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyGroupActionArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbGroupAction * act; +char tbuf[32]; + + act= &action->group; + TryCopyStr(buf,"group=",sz); + if (act->flags&XkbSA_GroupAbsolute) + sprintf(tbuf,"%d",XkbSAGroup(act)+1); + else if (XkbSAGroup(act)<0) + sprintf(tbuf,"%d",XkbSAGroup(act)); + else sprintf(tbuf,"+%d",XkbSAGroup(act)); + TryCopyStr(buf,tbuf,sz); + if (act->type==XkbSA_LockGroup) + return True; + if (act->flags&XkbSA_ClearLocks) + TryCopyStr(buf,",clearLocks",sz); + if (act->flags&XkbSA_LatchToLock) + TryCopyStr(buf,",latchToLock",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyMovePtrArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyMovePtrArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbPtrAction * act; +int x,y; +char tbuf[32]; + + act= &action->ptr; + x= XkbPtrActionX(act); + y= XkbPtrActionY(act); + if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0)) + sprintf(tbuf,"x=%d",x); + else sprintf(tbuf,"x=+%d",x); + TryCopyStr(buf,tbuf,sz); + + if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0)) + sprintf(tbuf,",y=%d",y); + else sprintf(tbuf,",y=+%d",y); + TryCopyStr(buf,tbuf,sz); + if (act->flags&XkbSA_NoAcceleration) + TryCopyStr(buf,",!accel",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyPtrBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyPtrBtnArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbPtrBtnAction * act; +char tbuf[32]; + + act= &action->btn; + TryCopyStr(buf,"button=",sz); + if ((act->button>0)&&(act->button<6)) { + sprintf(tbuf,"%d",act->button); + TryCopyStr(buf,tbuf,sz); + } + else TryCopyStr(buf,"default",sz); + if (act->count>0) { + sprintf(tbuf,",count=%d",act->count); + TryCopyStr(buf,tbuf,sz); + } + if (action->type==XkbSA_LockPtrBtn) { + switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { + case XkbSA_LockNoLock: + sprintf(tbuf,",affect=unlock"); break; + case XkbSA_LockNoUnlock: + sprintf(tbuf,",affect=lock"); break; + case XkbSA_LockNoUnlock|XkbSA_LockNoLock: + sprintf(tbuf,",affect=neither"); break; + default: + sprintf(tbuf,",affect=both"); break; + } + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopySetPtrDfltArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopySetPtrDfltArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbPtrDfltAction * act; +char tbuf[32]; + + act= &action->dflt; + if (act->affect==XkbSA_AffectDfltBtn) { + TryCopyStr(buf,"affect=button,button=",sz); + if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0)) + sprintf(tbuf,"%d",XkbSAPtrDfltValue(act)); + else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act)); + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +CopyISOLockArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyISOLockArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbISOAction * act; +char tbuf[64]; + + act= &action->iso; + if (act->flags&XkbSA_ISODfltIsGroup) { + TryCopyStr(tbuf,"group=",sz); + if (act->flags&XkbSA_GroupAbsolute) + sprintf(tbuf,"%d",XkbSAGroup(act)+1); + else if (XkbSAGroup(act)<0) + sprintf(tbuf,"%d",XkbSAGroup(act)); + else sprintf(tbuf,"+%d",XkbSAGroup(act)); + TryCopyStr(buf,tbuf,sz); + } + else { + unsigned tmp; + tmp= XkbModActionVMods(act); + TryCopyStr(buf,"modifiers=",sz); + if (act->flags&XkbSA_UseModMapMods) + TryCopyStr(buf,"modMapMods",sz); + else if (act->real_mods || tmp) { + if (act->real_mods) { + TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz); + if (tmp) + TryCopyStr(buf,"+",sz); + } + if (tmp) + TryCopyStr(buf,XkbVModMaskText(dpy,xkb,0,tmp,XkbXKBFile),sz); + } + else TryCopyStr(buf,"none",sz); + } + TryCopyStr(buf,",affect=",sz); + if ((act->affect&XkbSA_ISOAffectMask)==0) + TryCopyStr(buf,"all",sz); + else { + int nOut= 0; + if ((act->affect&XkbSA_ISONoAffectMods)==0) { + TryCopyStr(buf,"mods",sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectGroup)==0) { + sprintf(tbuf,"%sgroups",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectPtr)==0) { + sprintf(tbuf,"%spointer",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectCtrls)==0) { + sprintf(tbuf,"%scontrols",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopySwitchScreenArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopySwitchScreenArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbSwitchScreenAction * act; +char tbuf[32]; + + act= &action->screen; + if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0)) + sprintf(tbuf,"screen=%d",XkbSAScreen(act)); + else sprintf(tbuf,"screen=+%d",XkbSAScreen(act)); + TryCopyStr(buf,tbuf,sz); + if (act->flags&XkbSA_SwitchApplication) + TryCopyStr(buf,",!same",sz); + else TryCopyStr(buf,",same",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopySetLockControlsArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action, + char *buf,int *sz) +#else +CopySetLockControlsArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbCtrlsAction * act; +unsigned tmp; +char tbuf[32]; + + act= &action->ctrls; + tmp= XkbActionCtrls(act); + TryCopyStr(buf,"controls=",sz); + if (tmp==0) + TryCopyStr(buf,"none",sz); + else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask) + TryCopyStr(buf,"all",sz); + else { + int nOut= 0; + if (tmp&XkbRepeatKeysMask) { + sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbSlowKeysMask) { + sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbBounceKeysMask) { + sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbStickyKeysMask) { + sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbMouseKeysMask) { + sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbMouseKeysAccelMask) { + sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXKeysMask) { + sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXTimeoutMask) { + sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXFeedbackMask) { + sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAudibleBellMask) { + sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbOverlay1Mask) { + sprintf(tbuf,"%sOverlay1",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbOverlay2Mask) { + sprintf(tbuf,"%sOverlay2",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbIgnoreGroupLockMask) { + sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyActionMessageArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyActionMessageArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbMessageAction * act; +unsigned all; +char tbuf[32]; + + act= &action->msg; + all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease; + TryCopyStr(buf,"report=",sz); + if ((act->flags&all)==0) + TryCopyStr(buf,"none",sz); + else if ((act->flags&all)==all) + TryCopyStr(buf,"all",sz); + else if (act->flags&XkbSA_MessageOnPress) + TryCopyStr(buf,"KeyPress",sz); + else TryCopyStr(buf,"KeyRelease",sz); + sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz); + return True; +} + +static Bool +#if NeedFunctionPrototypes +CopyRedirectKeyArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyRedirectKeyArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbRedirectKeyAction * act; +char tbuf[32],*tmp; +unsigned kc; +unsigned vmods,vmods_mask; + + act= &action->redirect; + kc= act->new_key; + vmods= XkbSARedirectVMods(act); + vmods_mask= XkbSARedirectVModsMask(act); + if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) && + (xkb->names->keys[kc].name[0]!='\0')) { + char *kn; + kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); + sprintf(tbuf,"key=%s",kn); + } + else sprintf(tbuf,"key=%d",kc); + TryCopyStr(buf,tbuf,sz); + if ((act->mods_mask==0)&&(vmods_mask==0)) + return True; + if ((act->mods_mask==XkbAllModifiersMask)&& + (vmods_mask==XkbAllVirtualModsMask)) { + tmp= XkbVModMaskText(dpy,xkb,act->mods,vmods,XkbXKBFile); + TryCopyStr(buf,",mods=",sz); + TryCopyStr(buf,tmp,sz); + } + else { + if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) { + tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&act->mods, + vmods_mask&vmods,XkbXKBFile); + TryCopyStr(buf,",mods= ",sz); + TryCopyStr(buf,tmp,sz); + } + if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) { + tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&(~act->mods), + vmods_mask&(~vmods),XkbXKBFile); + TryCopyStr(buf,",clearMods= ",sz); + TryCopyStr(buf,tmp,sz); + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyDeviceBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyDeviceBtnArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbDeviceBtnAction * act; +char tbuf[32]; + + act= &action->devbtn; + sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz); + TryCopyStr(buf,",button=",sz); + sprintf(tbuf,"%d",act->button); + TryCopyStr(buf,tbuf,sz); + if (act->count>0) { + sprintf(tbuf,",count=%d",act->count); + TryCopyStr(buf,tbuf,sz); + } + if (action->type==XkbSA_LockDeviceBtn) { + switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { + case XkbSA_LockNoLock: + sprintf(tbuf,",affect=unlock"); break; + case XkbSA_LockNoUnlock: + sprintf(tbuf,",affect=lock"); break; + case XkbSA_LockNoUnlock|XkbSA_LockNoLock: + sprintf(tbuf,",affect=neither"); break; + default: + sprintf(tbuf,",affect=both"); break; + } + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyOtherArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyOtherArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbAnyAction * act; +char tbuf[32]; + + act= &action->any; + sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz); + return True; +} + +typedef Bool (*actionCopy)( +#if NeedFunctionPrototypes + Display * /* dpy */, + XkbDescPtr /* xkb */, + XkbAction * /* action */, + char * /* buf */, + int* /* sz */ +#endif +); +static actionCopy copyActionArgs[XkbSA_NumActions] = { + CopyNoActionArgs /* NoAction */, + CopyModActionArgs /* SetMods */, + CopyModActionArgs /* LatchMods */, + CopyModActionArgs /* LockMods */, + CopyGroupActionArgs /* SetGroup */, + CopyGroupActionArgs /* LatchGroup */, + CopyGroupActionArgs /* LockGroup */, + CopyMovePtrArgs /* MovePtr */, + CopyPtrBtnArgs /* PtrBtn */, + CopyPtrBtnArgs /* LockPtrBtn */, + CopySetPtrDfltArgs /* SetPtrDflt */, + CopyISOLockArgs /* ISOLock */, + CopyNoActionArgs /* Terminate */, + CopySwitchScreenArgs /* SwitchScreen */, + CopySetLockControlsArgs /* SetControls */, + CopySetLockControlsArgs /* LockControls */, + CopyActionMessageArgs /* ActionMessage*/, + CopyRedirectKeyArgs /* RedirectKey */, + CopyDeviceBtnArgs /* DeviceBtn */, + CopyDeviceBtnArgs /* LockDeviceBtn*/ +}; + +#define ACTION_SZ 256 + +char * +#if NeedFunctionPrototypes +XkbActionText(Display *dpy,XkbDescPtr xkb,XkbAction *action,unsigned format) +#else +XkbActionText(dpy,xkb,action,format) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + unsigned format; +#endif +{ +char buf[ACTION_SZ],*tmp; +int sz; + + if (format==XkbCFile) { + sprintf(buf, + "{ %20s, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x }", + XkbActionTypeText(action->type,XkbCFile), + action->any.data[0],action->any.data[1],action->any.data[2], + action->any.data[3],action->any.data[4],action->any.data[5], + action->any.data[6]); + } + else { + sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile)); + sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */ + if (action->type<(unsigned)XkbSA_NumActions) + (*copyActionArgs[action->type])(dpy,xkb,action,buf,&sz); + else CopyOtherArgs(dpy,xkb,action,buf,&sz); + TryCopyStr(buf,")",&sz); + } + tmp= tbGetBuffer(strlen(buf)+1); + if (tmp!=NULL) + strcpy(tmp,buf); + return tmp; +} + +char * +#if NeedFunctionPrototypes +XkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format) +#else +XkbBehaviorText(xkb,behavior,format) + XkbDescPtr xkb; + XkbBehavior * behavior; + unsigned format; +#endif +{ +char buf[256],*tmp; + + if (format==XkbCFile) { + if (behavior->type==XkbKB_Default) + sprintf(buf,"{ 0, 0 }"); + else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data); + } + else { + unsigned type,permanent; + type= behavior->type&XkbKB_OpMask; + permanent=((behavior->type&XkbKB_Permanent)!=0); + + if (type==XkbKB_Lock) { + sprintf(buf,"lock= %s,",(permanent?"Permanent":"True")); + } + else if (type==XkbKB_RadioGroup) { + int g; + char *tmp; + g= ((behavior->data)&(~XkbKB_RGAllowNone))+1; + if (XkbKB_RGAllowNone&behavior->data) { + sprintf(buf,"allowNone,"); + tmp= &buf[strlen(buf)]; + } + else tmp= buf; + if (permanent) + sprintf(tmp,"permanentRadioGroup= %d",g); + else sprintf(tmp,"radioGroup= %d",g); + } + else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) { + int ndx,kc; + char *kn; + + ndx= ((type==XkbKB_Overlay1)?1:2); + kc= behavior->data; + if ((xkb)&&(xkb->names)&&(xkb->names->keys)) + kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); + else { + static char tbuf[8]; + sprintf(tbuf,"%d",kc); + kn= tbuf; + } + if (permanent) + sprintf(buf,"permanentOverlay%d= %s",ndx,kn); + else sprintf(buf,"overlay%d= %s",ndx,kn); + } + } + tmp= tbGetBuffer(strlen(buf)+1); + if (tmp!=NULL) + strcpy(tmp,buf); + return tmp; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbIndentText(unsigned size) +#else +XkbIndentText(size) + unsigned size; +#endif +{ +static char buf[32]; +register int i; + + if (size>31) + size= 31; + + for (i=0;ired= color->green= color->blue= 0; + return True; + } + else if (_XkbStrCaseEqual(def,"white")) { + color->red= color->green= color->blue= PIXEL_MAX; + return True; + } + else if ((sscanf(def,"grey%d",&tmp)==1)|| + (sscanf(def,"gray%d",&tmp)==1)|| + (sscanf(def,"Grey%d",&tmp)==1)|| + (sscanf(def,"Gray%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->red= color->green= color->blue= tmp; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"red")*100))|| + (sscanf(def,"red%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->red= tmp; + color->green= color->blue= 0; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"green")*100))|| + (sscanf(def,"green%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->green= tmp; + color->red= color->blue= 0; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"blue")*100))|| + (sscanf(def,"blue%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->blue= tmp; + color->red= color->green= 0; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"magenta")*100))|| + (sscanf(def,"magenta%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->green= 0; + color->red= color->blue= tmp; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"cyan")*100))|| + (sscanf(def,"cyan%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->red= 0; + color->green= color->blue= tmp; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"yellow")*100))|| + (sscanf(def,"yellow%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->blue= 0; + color->red= color->green= tmp; + return True; + } + } + return False; +} + +#endif diff --git a/xkb/xkmread.c b/xkb/xkmread.c new file mode 100644 index 000000000..7a4a2b429 --- /dev/null +++ b/xkb/xkmread.c @@ -0,0 +1,1481 @@ +/* $Xorg: xkmread.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + + 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 name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS 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. + + ********************************************************/ + +#include + +#include +#include + +#ifndef XKB_IN_SERVER + +#ifndef X_NOT_STDC_ENV +#include +#endif +#include +#include + +#include + +#include +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include +#include "misc.h" +#include "inputstr.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XKBgeom.h" + +Atom +#if NeedFunctionPrototypes +XkbInternAtom(Display *dpy,char *str,Bool only_if_exists) +#else +XkbInternAtom(dpy,str,only_if_exists) + Display * dpy; + char * str; + Bool only_if_exists; +#endif +{ + if (str==NULL) + return None; + return MakeAtom(str,strlen(str),!only_if_exists); +} + +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +char * +#if NeedFunctionPrototypes +_XkbDupString(char *str) +#else +_XkbDupString(str) + char *str; +#endif +{ +char *new; + + if (str==NULL) + return NULL; + new= (char *)_XkbCalloc(strlen(str)+1,sizeof(char)); + if (new) + strcpy(new,str); + return new; +} + +/***====================================================================***/ + +static XPointer +#if NeedFunctionPrototypes +XkmInsureSize(XPointer oldPtr,int oldCount,int *newCountRtrn,int elemSize) +#else +XkmInsureSize(oldPtr,oldCount,newCountRtrn,elemSize) + XPointer oldPtr; + int oldCount; + int * newCountRtrn; + int elemSize; +#endif +{ +int newCount= *newCountRtrn; + + if (oldPtr==NULL) { + if (newCount==0) + return NULL; + oldPtr= (XPointer)_XkbCalloc(newCount,elemSize); + } + else if (oldCount0) { + int tmp; + if (count>max_len) { + tmp= fread(str,1,max_len,file); + while (tmp=max_len) str[max_len-1]= '\0'; + else str[count]= '\0'; + count= XkbPaddedSize(nRead)-nRead; + if (count>0) + nRead+= XkmSkipPadding(file,count); + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmVirtualMods(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmVirtualMods(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register unsigned int i,bit; +unsigned int bound,named,tmp; +int nRead=0; +XkbDescPtr xkb; + + xkb= result->xkb; + if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + bound= XkmGetCARD16(file,&nRead); + named= XkmGetCARD16(file,&nRead); + for (i=tmp=0,bit=1;iserver->vmods[i]= XkmGetCARD8(file,&nRead); + if (changes) + changes->map.vmods|= bit; + tmp++; + } + } + if ((i= XkbPaddedSize(tmp)-tmp)>0) + nRead+= XkmSkipPadding(file,i); + if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + for (i=0,bit=1;inames->vmods[i]= XkbInternAtom(xkb->dpy,name,False); + if (changes) + changes->names.changed_vmods|= bit; + } + } + } + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmKeycodes(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmKeycodes(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register int i; +unsigned minKC,maxKC,nAl; +int nRead=0; +char name[100]; +XkbKeyNamePtr pN; +XkbDescPtr xkb; + + xkb= result->xkb; + name[0]= '\0'; + nRead+= XkmGetCountedString(file,name,100); + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + if (xkb->min_key_code==0) { + xkb->min_key_code= minKC; + xkb->max_key_code= maxKC; + } + else { + if (minKCmin_key_code) + xkb->min_key_code= minKC; + if (maxKC>xkb->max_key_code) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC); + return -1; + } + } + nAl= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + +#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask) + if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); + return -1; + } + if (name[0]!='\0') { + xkb->names->keycodes= XkbInternAtom(xkb->dpy,name,False); + } + + for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) { + if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= XkbKeyNameLength; + } + if (nAl>0) { + XkbKeyAliasPtr pAl; + for (pAl= xkb->names->key_aliases,i=0;inames.changed|= XkbKeyAliasesMask; + } + if (changes) + changes->names.changed|= XkbKeyNamesMask; + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmKeyTypes(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmKeyTypes(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register unsigned i,n; +unsigned num_types; +int nRead=0; +int tmp; +XkbKeyTypePtr type; +xkmKeyTypeDesc wire; +XkbKTMapEntryPtr entry; +xkmKTMapEntryDesc wire_entry; +char buf[100]; +XkbDescPtr xkb; + + xkb= result->xkb; + if ((tmp= XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') { + if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return -1; + } + xkb->names->types= XkbInternAtom(xkb->dpy,buf,False); + } + num_types= XkmGetCARD16(file,&nRead); + nRead+= XkmSkipPadding(file,2); + if (num_types<1) + return nRead; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return nRead; + } + xkb->map->num_types= num_types; + if (num_typesmap->types; + for (i=0;imap,type->map_count,&tmp,XkbKTMapEntryRec); + if ((wire.nMapEntries>0)&&(type->map==NULL)) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries); + return -1; + } + for (n=0,entry= type->map;nactive= (wire_entry.virtualMods==0); + entry->level= wire_entry.level; + entry->mods.mask= wire_entry.realMods; + entry->mods.real_mods= wire_entry.realMods; + entry->mods.vmods= wire_entry.virtualMods; + } + nRead+= XkmGetCountedString(file,buf,100); + if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))|| + ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))|| + ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))|| + ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) { + _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0); + return -1; + } + if (buf[0]!='\0') { + type->name= XkbInternAtom(xkb->dpy,buf,False); + } + else type->name= None; + + if (wire.preserve) { + xkmModsDesc p_entry; + XkbModsPtr pre; + XkmInsureTypedSize(type->preserve,type->map_count,&tmp, + XkbModsRec); + if (type->preserve==NULL) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + for (n=0,pre=type->preserve;nmask= p_entry.realMods; + pre->real_mods= p_entry.realMods; + pre->vmods= p_entry.virtualMods; + } + } + if (wire.nLevelNames>0) { + int width= wire.numLevels; + if (wire.nLevelNames>(unsigned)width) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom); + if (type->level_names!=NULL) { + for (n=0;nlevel_names[n]= None; + else type->level_names[n]= XkbInternAtom(xkb->dpy,buf,0); + } + } + } + type->mods.mask= wire.realMods; + type->mods.real_mods= wire.realMods; + type->mods.vmods= wire.virtualMods; + type->num_levels= wire.numLevels; + type->map_count= wire.nMapEntries; + } + if (changes) { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= 0; + changes->map.num_types= xkb->map->num_types; + } + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmCompatMap(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmCompatMap(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register int i; +unsigned num_si,groups; +char name[100]; +XkbSymInterpretPtr interp; +xkmSymInterpretDesc wire; +unsigned tmp; +int nRead=0; +XkbDescPtr xkb; +XkbCompatMapPtr compat; + + xkb= result->xkb; + if ((tmp= XkmGetCountedString(file,name,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0); + return -1; + } + nRead+= tmp; + if (name[0]!='\0') { + if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0); + return -1; + } + xkb->names->compat= XkbInternAtom(xkb->dpy,name,False); + } + num_si= XkmGetCARD16(file,&nRead); + groups= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success) + return -1; + compat= xkb->compat; + compat->num_si= num_si; + interp= compat->sym_interpret; + for (i=0;isym= wire.sym; + interp->mods= wire.mods; + interp->match= wire.match; + interp->virtual_mod= wire.virtualMod; + interp->flags= wire.flags; + interp->act.type= wire.actionType; + interp->act.data[0]= wire.actionData[0]; + interp->act.data[1]= wire.actionData[1]; + interp->act.data[2]= wire.actionData[2]; + interp->act.data[3]= wire.actionData[3]; + interp->act.data[4]= wire.actionData[4]; + interp->act.data[5]= wire.actionData[5]; + interp->act.data[6]= wire.actionData[6]; + } + if ((num_si>0)&&(changes)) { + changes->compat.first_si= 0; + changes->compat.num_si= num_si; + } + if (groups) { + register unsigned bit; + for (i=0,bit=1;icompat->groups[i].real_mods= md.realMods; + xkb->compat->groups[i].vmods= md.virtualMods; + if (md.virtualMods != 0) { + unsigned mask; + if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask)) + xkb->compat->groups[i].mask= md.realMods|mask; + } + else xkb->compat->groups[i].mask= md.realMods; + } + } + if (changes) + changes->compat.changed_groups|= groups; + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmIndicators(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmIndicators(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register unsigned nLEDs; +xkmIndicatorMapDesc wire; +char buf[100]; +unsigned tmp; +int nRead=0; +XkbDescPtr xkb; + + xkb= result->xkb; + if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) { + _XkbLibError(_XkbErrBadAlloc,"indicator rec",0); + return -1; + } + if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"indicator names",0); + return -1; + } + nLEDs= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,3); + xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead); + while (nLEDs-->0) { + Atom name; + XkbIndicatorMapPtr map; + + if ((tmp=XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') + name= XkbInternAtom(xkb->dpy,buf,False); + else name= None; + if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmIndicatorMapDesc); + if (xkb->names) { + xkb->names->indicators[wire.indicator-1]= name; + if (changes) + changes->names.changed_indicators|= (1<<(wire.indicator-1)); + } + map= &xkb->indicators->maps[wire.indicator-1]; + map->flags= wire.flags; + map->which_groups= wire.which_groups; + map->groups= wire.groups; + map->which_mods= wire.which_mods; + map->mods.mask= wire.real_mods; + map->mods.real_mods= wire.real_mods; + map->mods.vmods= wire.vmods; + map->ctrls= wire.ctrls; + } + return nRead; +} + +static XkbKeyTypePtr +#if NeedFunctionPrototypes +FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms) +#else +FindTypeForKey(xkb,name,width,syms) + XkbDescPtr xkb; + Atom name; + unsigned width; + KeySym * syms; +#endif +{ + if ((!xkb)||(!xkb->map)) + return NULL; + if (name!=None) { + register unsigned i; + for (i=0;imap->num_types;i++) { + if (xkb->map->types[i].name==name) { +#ifdef DEBUG + if (xkb->map->types[i].num_levels!=width) + fprintf(stderr,"Group width mismatch between key and type\n"); +#endif + return &xkb->map->types[i]; + } + } + } + if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol))) + return &xkb->map->types[XkbOneLevelIndex]; + if (syms!=NULL) { + if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1])) + return &xkb->map->types[XkbAlphabeticIndex]; + else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1])) + return &xkb->map->types[XkbKeypadIndex]; + } + return &xkb->map->types[XkbTwoLevelIndex]; +} + +static int +#if NeedFunctionPrototypes +ReadXkmSymbols(FILE *file,XkbFileInfo *result) +#else +ReadXkmSymbols(file,result) + FILE * file; + XkbFileInfo * result; +#endif +{ +register int i,g,s,totalVModMaps; +xkmKeySymMapDesc wireMap; +char buf[100]; +unsigned minKC,maxKC,groupNames,tmp; +int nRead=0; +XkbDescPtr xkb; + + xkb= result->xkb; + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + groupNames= XkmGetCARD8(file,&nRead); + totalVModMaps= XkmGetCARD8(file,&nRead); + if (XkbAllocNames(xkb, + XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask, + 0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"physical names",0); + return -1; + } + if ((buf[0]!='\0')&&(xkb->names)) { + Atom name; + name= XkbInternAtom(xkb->dpy,buf,0); + xkb->names->symbols= name; + xkb->names->phys_symbols= name; + } + for (i=0,g=1;inames)) { + Atom name; + name= XkbInternAtom(xkb->dpy,buf,0); + xkb->names->groups[i]= name; + } + else xkb->names->groups[i]= None; + } + } + if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"server map",0); + return -1; + } + if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"client map",0); + return -1; + } + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"controls",0); + return -1; + } + if ((xkb->map==NULL)||(xkb->server==NULL)) + return -1; + if (xkb->min_key_code<8) xkb->min_key_code= minKC; + if (xkb->max_key_code<8) xkb->max_key_code= maxKC; + if ((minKC>=8)&&(minKCmin_key_code)) + xkb->min_key_code= minKC; + if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) { + _XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC); + return -1; + } + for (i=minKC;i<=(int)maxKC;i++) { + Atom typeName[XkbNumKbdGroups]; + XkbKeyTypePtr type[XkbNumKbdGroups]; + if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmKeySymMapDesc); + bzero((char *)typeName,XkbNumKbdGroups*sizeof(Atom)); + bzero((char *)type,XkbNumKbdGroups*sizeof(XkbKeyTypePtr)); + if (wireMap.flags&XkmKeyHasTypes) { + register int g; + for (g=0;g0)) { + typeName[g]= XkbInternAtom(xkb->dpy,buf,1); + nRead+= tmp; + } + type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL); + if (type[g]==NULL) { + _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0); + return -1; + } + if (typeName[g]==type[g]->name) + xkb->server->explicit[i]|= (1<ctrls->per_key_repeat[i/8]|= (1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + else if (wireMap.flags&XkmNonRepeatingKey) { + xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + xkb->map->modmap[i]= wireMap.modifier_map; + if (wireMap.num_groups>0) { + KeySym *sym; + int nSyms; + + if (wireMap.num_groups>xkb->ctrls->num_groups) + xkb->ctrls->num_groups= wireMap.num_groups; + nSyms= wireMap.num_groups*wireMap.width; + sym= XkbResizeKeySyms(xkb,i,nSyms); + if (!sym) + return -1; + for (s=0;sserver->explicit[i]|= XkbExplicitInterpretMask; + } + } + for (g=0;gserver->explicit[i]&(1<map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]); + } + xkb->map->key_sym_map[i].group_info= wireMap.num_groups; + xkb->map->key_sym_map[i].width= wireMap.width; + if (wireMap.flags&XkmKeyHasBehavior) { + xkmBehaviorDesc b; + tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file); + nRead+= tmp*SIZEOF(xkmBehaviorDesc); + xkb->server->behaviors[i].type= b.type; + xkb->server->behaviors[i].data= b.data; + xkb->server->explicit[i]|= XkbExplicitBehaviorMask; + } + } + if (totalVModMaps>0) { + xkmVModMapDesc v; + for (i=0;i0) + xkb->server->vmodmap[v.key]= v.vmods; + } + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmGeomDoodad( + FILE * file, + Display * dpy, + XkbGeometryPtr geom, + XkbSectionPtr section) +#else +ReadXkmGeomDoodad(file,dpy,geom,section) + FILE * file; + Display * dpy; + XkbGeometryPtr geom; + XkbSectionPtr section; +#endif +{ +XkbDoodadPtr doodad; +xkmDoodadDesc doodadWire; +char buf[100]; +unsigned tmp; +int nRead=0; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file); + nRead+= SIZEOF(xkmDoodadDesc)*tmp; + doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(dpy,buf,False)); + if (!doodad) + return nRead; + doodad->any.type= doodadWire.any.type; + doodad->any.priority= doodadWire.any.priority; + doodad->any.top= doodadWire.any.top; + doodad->any.left= doodadWire.any.left; + switch (doodadWire.any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodad->shape.angle= doodadWire.shape.angle; + doodad->shape.color_ndx= doodadWire.shape.color_ndx; + doodad->shape.shape_ndx= doodadWire.shape.shape_ndx; + break; + case XkbTextDoodad: + doodad->text.angle= doodadWire.text.angle; + doodad->text.width= doodadWire.text.width; + doodad->text.height= doodadWire.text.height; + doodad->text.color_ndx= doodadWire.text.color_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.text= _XkbDupString(buf); + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.font= _XkbDupString(buf); + break; + case XkbIndicatorDoodad: + doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx; + doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx; + doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodad->logo.angle= doodadWire.logo.angle; + doodad->logo.color_ndx= doodadWire.logo.color_ndx; + doodad->logo.shape_ndx= doodadWire.logo.shape_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->logo.logo_name= _XkbDupString(buf); + break; + default: + /* report error? */ + return nRead; + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmGeomOverlay( FILE * file, + Display * dpy, + XkbGeometryPtr geom, + XkbSectionPtr section) +#else +ReadXkmGeomOverlay(file,dpy,geom,section) + FILE * file; + Display * dpy; + XkbGeometryPtr geom; + XkbSectionPtr section; +#endif +{ +char buf[100]; +unsigned tmp; +int nRead=0; +XkbOverlayPtr ol; +XkbOverlayRowPtr row; +xkmOverlayDesc olWire; +xkmOverlayRowDesc rowWire; +register int r; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayDesc); + ol= XkbAddGeomOverlay(section,XkbInternAtom(dpy,buf,False), + olWire.num_rows); + if (!ol) + return nRead; + for (r=0;rkeys[k].over.name,keyWire.over,XkbKeyNameLength); + memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength); + } + row->num_keys= rowWire.num_keys; + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmGeomSection( FILE * file, + Display * dpy, + XkbGeometryPtr geom) +#else +ReadXkmGeomSection(file,dpy,geom) + FILE * file; + Display * dpy; + XkbGeometryPtr geom; +#endif +{ +register int i; +XkbSectionPtr section; +xkmSectionDesc sectionWire; +unsigned tmp; +int nRead= 0; +char buf[100]; +Atom nameAtom; + + nRead+= XkmGetCountedString(file,buf,100); + nameAtom= XkbInternAtom(dpy,buf,False); + tmp= fread(§ionWire,SIZEOF(xkmSectionDesc),1,file); + nRead+= SIZEOF(xkmSectionDesc)*tmp; + section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows, + sectionWire.num_doodads, + sectionWire.num_overlays); + if (!section) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); + return nRead; + } + section->top= sectionWire.top; + section->left= sectionWire.left; + section->width= sectionWire.width; + section->height= sectionWire.height; + section->angle= sectionWire.angle; + section->priority= sectionWire.priority; + if (sectionWire.num_rows>0) { + register int k; + XkbRowPtr row; + xkmRowDesc rowWire; + XkbKeyPtr key; + xkmKeyDesc keyWire; + + for (i=0;itop= rowWire.top; + row->left= rowWire.left; + row->vertical= rowWire.vertical; + for (k=0;kname.name,keyWire.name,XkbKeyNameLength); + key->gap= keyWire.gap; + key->shape_ndx= keyWire.shape_ndx; + key->color_ndx= keyWire.color_ndx; + } + } + } + if (sectionWire.num_doodads>0) { + for (i=0;i0) { + for (i=0;ixkb,&sizes)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + geom= result->xkb->geom; + geom->name= XkbInternAtom(result->xkb->dpy,buf,False); + geom->width_mm= wireGeom.width_mm; + geom->height_mm= wireGeom.height_mm; + nRead+= XkmGetCountedString(file,buf,100); + geom->label_font= _XkbDupString(buf); + if (wireGeom.num_properties>0) { + char val[1024]; + for (i=0;i0) { + for (i=0;ibase_color= &geom->colors[wireGeom.base_color_ndx]; + geom->label_color= &geom->colors[wireGeom.label_color_ndx]; + if (wireGeom.num_shapes>0) { + XkbShapePtr shape; + xkmShapeDesc shapeWire; + Atom nameAtom; + for (i=0;ixkb->dpy,buf,False); + tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file); + nRead+= tmp*SIZEOF(xkmShapeDesc); + shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines); + if (!shape) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + for (n=0;nnum_points= olWire.num_points; + ol->corner_radius= olWire.corner_radius; + for (p=0;ppoints[p].x= ptWire.x; + ol->points[p].y= ptWire.y; + if (ptWire.xbounds.x1) shape->bounds.x1= ptWire.x; + if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x; + if (ptWire.ybounds.y1) shape->bounds.y1= ptWire.y; + if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y; + } + } + if (shapeWire.primary_ndx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire.primary_ndx]; + if (shapeWire.approx_ndx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire.approx_ndx]; + } + } + if (wireGeom.num_sections>0) { + for (i=0;ixkb->dpy,geom); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if (wireGeom.num_doodads>0) { + for (i=0;ixkb->dpy,geom,NULL); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) { + int sz= XkbKeyNameLength*2; + int num= wireGeom.num_key_aliases; + if (fread(geom->key_aliases,sz,num,file)!=num) { + _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0); + return -1; + } + nRead+= (num*sz); + geom->num_key_aliases= num; + } + return nRead; +} + +Bool +#if NeedFunctionPrototypes +XkmProbe(FILE *file) +#else +XkmProbe(file) + FILE * file; +#endif +{ +unsigned hdr,tmp; +int nRead=0; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff); + } + return 0; + } + return 1; +} + +Bool +#if NeedFunctionPrototypes +XkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc) +#else +XkmReadTOC(file,file_info,max_toc,toc) + FILE * file; + xkmFileInfo * file_info; + int max_toc; + xkmSectionInfo * toc; +#endif +{ +unsigned hdr,tmp; +int nRead=0; +unsigned i,size_toc; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff); + } + else { + _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp); + } + return 0; + } + fread(file_info,SIZEOF(xkmFileInfo),1,file); + size_toc= file_info->num_toc; + if (size_toc>max_toc) { +#ifdef DEBUG + fprintf(stderr,"Warning! Too many TOC entries; last %d ignored\n", + size_toc-max_toc); +#endif + size_toc= max_toc; + } + for (i=0;inum_toc;i++) { + if (toc[i].type==type) + return &toc[i]; + } + return NULL; +} + +Bool +#if NeedFunctionPrototypes +XkmReadFileSection( FILE * file, + xkmSectionInfo * toc, + XkbFileInfo * result, + unsigned * loaded_rtrn) +#else +XkmReadFileSection(file,toc,result,loaded_rtrn) + FILE * file; + xkmSectionInfo * toc; + XkbFileInfo * result; + unsigned * loaded_rtrn; +#endif +{ +xkmSectionInfo tmpTOC; +int nRead; + + if ((!result)||(!result->xkb)) { + _XkbLibError(_XkbErrBadMatch,"XkmReadFileSection",0); + return 0; + } + fseek(file,toc->offset,SEEK_SET); + fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); + nRead= SIZEOF(xkmSectionInfo); + if ((tmpTOC.type!=toc->type)||(tmpTOC.format!=toc->format)|| + (tmpTOC.size!=toc->size)||(tmpTOC.offset!=toc->offset)) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFileSection",0); + return 0; + } + switch (tmpTOC.type) { + case XkmVirtualModsIndex: + nRead+= ReadXkmVirtualMods(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmVirtualModsMask; + break; + case XkmTypesIndex: + nRead+= ReadXkmKeyTypes(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmTypesMask; + break; + case XkmCompatMapIndex: + nRead+= ReadXkmCompatMap(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmCompatMapMask; + break; + case XkmKeyNamesIndex: + nRead+= ReadXkmKeycodes(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmKeyNamesMask; + break; + case XkmSymbolsIndex: + nRead+= ReadXkmSymbols(file,result); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmSymbolsMask; + break; + case XkmIndicatorsIndex: + nRead+= ReadXkmIndicators(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmIndicatorsMask; + break; + case XkmGeometryIndex: + nRead+= ReadXkmGeometry(file,result); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmGeometryMask; + break; + default: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(tmpTOC.type,XkbMessage),0); + nRead= 0; + break; + } + if (nRead!=tmpTOC.size) { + _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage), + nRead-tmpTOC.size); + return 0; + } + return (nRead>=0); +} + +char * +#if NeedFunctionPrototypes +XkmReadFileSectionName(FILE *file,xkmSectionInfo *toc) +#else +XkmReadFileSectionName(file,toc) + FILE * file; + xkmSectionInfo * toc; +#endif +{ +xkmSectionInfo tmpTOC; +char name[100]; + + if ((!file)||(!toc)) + return 0; + switch (toc->type) { + case XkmVirtualModsIndex: + case XkmIndicatorsIndex: + break; + case XkmTypesIndex: + case XkmCompatMapIndex: + case XkmKeyNamesIndex: + case XkmSymbolsIndex: + case XkmGeometryIndex: + fseek(file,toc->offset,SEEK_SET); + fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); + if ((tmpTOC.type!=toc->type)||(tmpTOC.format!=toc->format)|| + (tmpTOC.size!=toc->size)||(tmpTOC.offset!=toc->offset)) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFileSectionName",0); + return 0; + } + if (XkmGetCountedString(file,name,100)>0) + return _XkbDupString(name); + break; + default: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(tmpTOC.type,XkbMessage),0); + break; + } + return NULL; +} + +/***====================================================================***/ + +#define MAX_TOC 16 +unsigned +#if NeedFunctionPrototypes +XkmReadFile(FILE *file,unsigned need,unsigned want,XkbFileInfo *result) +#else +XkmReadFile(file,need,want,result) + FILE * file; + unsigned need; + unsigned want; + XkbFileInfo * result; +#endif +{ +register unsigned i; +xkmSectionInfo toc[MAX_TOC],tmpTOC; +xkmFileInfo fileInfo; +unsigned tmp,nRead=0; +unsigned which= need|want; + + if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc)) + return which; + if ((fileInfo.present&need)!=need) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFile", + need&(~fileInfo.present)); + return which; + } + result->type= fileInfo.type; + if (result->xkb==NULL) + result->xkb= XkbAllocKeyboard(); + for (i=0;i0) { + nRead+= tmp; + which&= ~(1<defined|= (1<