#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#define NEED_REPLIES
#define NEED_EVENTS
#include <X11/Xproto.h>
#include "windowstr.h"
#include "propertyst.h"
#include "dixstruct.h"
#include "dispatch.h"
#include "swaprep.h"
#include "xace.h"
#ifdef notdef
static void
PrintPropertys(WindowPtr pWin)
{
PropertyPtr pProp;
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
static void
deliverPropertyNotifyEvent(WindowPtr pWin, int state, Atom atom)
{
xEvent event;
event.u.u.type = PropertyNotify;
event.u.property.window = pWin->drawable.id;
event.u.property.state = state;
event.u.property.atom = atom;
event.u.property.time = currentTime.milliseconds;
DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
}
int
ProcRotateProperties(ClientPtr client)
{
int i, j, delta, rc;
REQUEST(xRotatePropertiesReq);
WindowPtr pWin;
Atom * atoms;
PropertyPtr * props;
PropertyPtr pProp;
REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
UpdateCurrentTime();
rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
if (rc != Success)
return rc;
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++)
{
char action = XaceHook(XACE_PROPERTY_ACCESS, client, pWin, atoms[i],
DixReadAccess|DixWriteAccess);
if (!ValidAtom(atoms[i]) || (XaceErrorOperation == action)) {
DEALLOCATE_LOCAL(props);
client->errorValue = atoms[i];
return BadAtom;
}
if (XaceIgnoreOperation == action) {
DEALLOCATE_LOCAL(props);
return Success;
}
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 ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 )
{
while (delta < 0)
delta += stuff->nAtoms;
for (i = 0; i < stuff->nAtoms; i++)
{
deliverPropertyNotifyEvent(pWin, PropertyNewValue,
props[i]->propertyName);
props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms];
}
}
DEALLOCATE_LOCAL(props);
return Success;
}
int
ProcChangeProperty(ClientPtr client)
{
WindowPtr pWin;
char format, mode;
unsigned long len;
int sizeInBytes, totalSize, 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);
err = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
if (err != Success)
return err;
if (!ValidAtom(stuff->property))
{
client->errorValue = stuff->property;
return(BadAtom);
}
if (!ValidAtom(stuff->type))
{
client->errorValue = stuff->type;
return(BadAtom);
}
switch (XaceHook(XACE_PROPERTY_ACCESS, client, pWin, stuff->property,
DixWriteAccess))
{
case XaceErrorOperation:
client->errorValue = stuff->property;
return BadAtom;
case XaceIgnoreOperation:
return Success;
}
err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format,
(int)mode, len, (pointer)&stuff[1], TRUE);
if (err != Success)
return err;
else
return client->noClientException;
}
_X_EXPORT int
ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format,
int mode, unsigned long len, pointer value,
Bool sendevent)
{
PropertyPtr pProp;
int sizeInBytes;
int totalSize;
pointer data;
sizeInBytes = format>>3;
totalSize = len * sizeInBytes;
pProp = wUserProps (pWin);
while (pProp)
{
if (pProp->propertyName == property)
break;
pProp = pProp->next;
}
if (!pProp)
{
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
{
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)
{
}
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)
deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
return(Success);
}
int
DeleteProperty(WindowPtr pWin, Atom propName)
{
PropertyPtr pProp, prevProp;
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)
{
if (!(pWin->optional->userProps = pProp->next))
CheckWindowOptionalNeed (pWin);
}
else
{
prevProp->next = pProp->next;
}
deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
xfree(pProp->data);
xfree(pProp);
}
return(Success);
}
void
DeleteAllWindowProperties(WindowPtr pWin)
{
PropertyPtr pProp, pNextProp;
pProp = wUserProps (pWin);
while (pProp)
{
deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
pNextProp = pProp->next;
xfree(pProp->data);
xfree(pProp);
pProp = pNextProp;
}
}
static int
NullPropertyReply(
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);
}
int
ProcGetProperty(ClientPtr client)
{
PropertyPtr pProp, prevProp;
unsigned long n, len, ind, rc;
WindowPtr pWin;
xGetPropertyReply reply;
Mask access_mode = DixReadAccess;
REQUEST(xGetPropertyReq);
REQUEST_SIZE_MATCH(xGetPropertyReq);
if (stuff->delete)
UpdateCurrentTime();
rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
if (rc != Success)
return rc;
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);
if (stuff->delete)
access_mode |= DixDestroyAccess;
switch (XaceHook(XACE_PROPERTY_ACCESS, client, pWin, stuff->property,
access_mode))
{
case XaceErrorOperation:
client->errorValue = stuff->property;
return BadAtom;;
case XaceIgnoreOperation:
return NullPropertyReply(client, pProp->type, pProp->format, &reply);
}
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);
}
n = (pProp->format/8) * pProp->size;
ind = stuff->longOffset << 2;
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))
deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
WriteReplyToClient(client, sizeof(xGenericReply), &reply);
if (len)
{
switch (reply.format) {
case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
}
WriteSwappedDataToClient(client, len,
(char *)pProp->data + ind);
}
if (stuff->delete && (reply.bytesAfter == 0))
{
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);
}
int
ProcListProperties(ClientPtr client)
{
Atom *pAtoms = NULL, *temppAtoms;
xListPropertiesReply xlpr;
int rc, numProps = 0;
WindowPtr pWin;
PropertyPtr pProp;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
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 = (ReplySwapPtr)Swap32Write;
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
DEALLOCATE_LOCAL(pAtoms);
}
return(client->noClientException);
}
int
ProcDeleteProperty(ClientPtr client)
{
WindowPtr pWin;
REQUEST(xDeletePropertyReq);
int result;
REQUEST_SIZE_MATCH(xDeletePropertyReq);
UpdateCurrentTime();
result = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
if (result != Success)
return result;
if (!ValidAtom(stuff->property))
{
client->errorValue = stuff->property;
return (BadAtom);
}
switch (XaceHook(XACE_PROPERTY_ACCESS, client, pWin, stuff->property,
DixDestroyAccess))
{
case XaceErrorOperation:
client->errorValue = stuff->property;
return BadAtom;;
case XaceIgnoreOperation:
return Success;
}
result = DeleteProperty(pWin, stuff->property);
if (client->noClientException != Success)
return(client->noClientException);
else
return(result);
}