700 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			700 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 2006 Keith Packard
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
 * documentation for any purpose is hereby granted without fee, provided that
 | 
						|
 * the 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 copyright holders not be used in advertising or
 | 
						|
 * publicity pertaining to distribution of the software without specific,
 | 
						|
 * written prior permission.  The 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 COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL THE 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.
 | 
						|
 */
 | 
						|
 | 
						|
#include "randrstr.h"
 | 
						|
#include "propertyst.h"
 | 
						|
#include "swaprep.h"
 | 
						|
 | 
						|
static void
 | 
						|
RRDeliverEvent (ScreenPtr pScreen, xEvent *event, CARD32 mask)
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
RRDeleteAllOutputProperties (RROutputPtr output)
 | 
						|
{
 | 
						|
    RRPropertyPtr prop, next;
 | 
						|
    xRROutputPropertyNotifyEvent    event;
 | 
						|
 | 
						|
    for (prop = output->properties; prop; prop = next)
 | 
						|
    {
 | 
						|
	next = prop->next;
 | 
						|
	event.type = RREventBase + RRNotify;
 | 
						|
	event.subCode = RRNotify_OutputProperty;
 | 
						|
	event.output = output->id;
 | 
						|
	event.state = PropertyDelete;
 | 
						|
	event.atom = prop->propertyName;
 | 
						|
	event.timestamp = currentTime.milliseconds;
 | 
						|
	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
 | 
						|
	if (prop->current.data)
 | 
						|
	    xfree(prop->current.data);
 | 
						|
	if (prop->pending.data)
 | 
						|
	    xfree(prop->pending.data);
 | 
						|
	xfree(prop);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
RRInitOutputPropertyValue (RRPropertyValuePtr property_value)
 | 
						|
{
 | 
						|
    property_value->type = None;
 | 
						|
    property_value->format = 0;
 | 
						|
    property_value->size = 0;
 | 
						|
    property_value->data = NULL;
 | 
						|
}
 | 
						|
 | 
						|
static RRPropertyPtr
 | 
						|
RRCreateOutputProperty (Atom property)
 | 
						|
{
 | 
						|
    RRPropertyPtr   prop;
 | 
						|
 | 
						|
    prop = (RRPropertyPtr)xalloc(sizeof(RRPropertyRec));
 | 
						|
    if (!prop)
 | 
						|
	return NULL;
 | 
						|
    prop->next = NULL;
 | 
						|
    prop->propertyName = property;
 | 
						|
    prop->is_pending = FALSE;
 | 
						|
    prop->range = FALSE;
 | 
						|
    prop->immutable = FALSE;
 | 
						|
    prop->num_valid = 0;
 | 
						|
    prop->valid_values = NULL;
 | 
						|
    RRInitOutputPropertyValue (&prop->current);
 | 
						|
    RRInitOutputPropertyValue (&prop->pending);
 | 
						|
    return prop;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
RRDestroyOutputProperty (RRPropertyPtr prop)
 | 
						|
{
 | 
						|
    if (prop->valid_values)
 | 
						|
	xfree (prop->valid_values);
 | 
						|
    if (prop->current.data)
 | 
						|
	xfree(prop->current.data);
 | 
						|
    if (prop->pending.data)
 | 
						|
	xfree(prop->pending.data);
 | 
						|
    xfree(prop);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
RRDeleteOutputProperty (RROutputPtr output, Atom property)
 | 
						|
{
 | 
						|
    RRPropertyPtr	prop, *prev;
 | 
						|
    xRROutputPropertyNotifyEvent    event;
 | 
						|
 | 
						|
    for (prev = &output->properties; (prop = *prev); prev = &(prop->next))
 | 
						|
	if (prop->propertyName == property)
 | 
						|
	    break;
 | 
						|
    if (prop)
 | 
						|
    {
 | 
						|
	*prev = prop->next;
 | 
						|
	event.type = RREventBase + RRNotify;
 | 
						|
	event.subCode = RRNotify_OutputProperty;
 | 
						|
	event.output = output->id;
 | 
						|
	event.state = PropertyDelete;
 | 
						|
	event.atom = prop->propertyName;
 | 
						|
	event.timestamp = currentTime.milliseconds;
 | 
						|
	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
 | 
						|
	RRDestroyOutputProperty (prop);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 | 
						|
			int format, int mode, unsigned long len,
 | 
						|
			pointer value, Bool sendevent, Bool pending)
 | 
						|
{
 | 
						|
    RRPropertyPtr		    prop;
 | 
						|
    xRROutputPropertyNotifyEvent    event;
 | 
						|
    rrScrPrivPtr		    pScrPriv = rrGetScrPriv(output->pScreen);
 | 
						|
    int				    size_in_bytes;
 | 
						|
    int				    total_size;
 | 
						|
    unsigned long		    total_len;
 | 
						|
    RRPropertyValuePtr		    prop_value;
 | 
						|
    RRPropertyValueRec		    new_value;
 | 
						|
    Bool			    add = FALSE;
 | 
						|
 | 
						|
    size_in_bytes = format >> 3;
 | 
						|
 | 
						|
    /* first see if property already exists */
 | 
						|
    prop = RRQueryOutputProperty (output, property);
 | 
						|
    if (!prop)   /* just add to list */
 | 
						|
    {
 | 
						|
	prop = RRCreateOutputProperty (property);
 | 
						|
	if (!prop)
 | 
						|
	    return(BadAlloc);
 | 
						|
	add = TRUE;
 | 
						|
	mode = PropModeReplace;
 | 
						|
    }
 | 
						|
    if (pending && prop->is_pending)
 | 
						|
	prop_value = &prop->pending;
 | 
						|
    else
 | 
						|
	prop_value = &prop->current;
 | 
						|
 | 
						|
    /* 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 != prop_value->format) && (mode != PropModeReplace))
 | 
						|
	return(BadMatch);
 | 
						|
    if ((prop_value->type != type) && (mode != PropModeReplace))
 | 
						|
	return(BadMatch);
 | 
						|
    new_value = *prop_value;
 | 
						|
    if (mode == PropModeReplace)
 | 
						|
	total_len = len;
 | 
						|
    else
 | 
						|
	total_len = prop_value->size + len;
 | 
						|
 | 
						|
    if (mode == PropModeReplace || len > 0)
 | 
						|
    {
 | 
						|
	pointer	    new_data = NULL, old_data = NULL;
 | 
						|
 | 
						|
	total_size = total_len * size_in_bytes;
 | 
						|
	new_value.data = (pointer)xalloc (total_size);
 | 
						|
	if (!new_value.data && total_size)
 | 
						|
	{
 | 
						|
	    if (add)
 | 
						|
		RRDestroyOutputProperty (prop);
 | 
						|
	    return BadAlloc;
 | 
						|
	}
 | 
						|
	new_value.size = len;
 | 
						|
	new_value.type = type;
 | 
						|
	new_value.format = format;
 | 
						|
 | 
						|
	switch (mode) {
 | 
						|
	case PropModeReplace:
 | 
						|
	    new_data = new_value.data;
 | 
						|
	    old_data = NULL;
 | 
						|
	    break;
 | 
						|
	case PropModeAppend:
 | 
						|
	    new_data = (pointer) (((char *) new_value.data) + 
 | 
						|
				  (prop_value->size * size_in_bytes));
 | 
						|
	    old_data = new_value.data;
 | 
						|
	    break;
 | 
						|
	case PropModePrepend:
 | 
						|
	    new_data = new_value.data;
 | 
						|
	    old_data = (pointer) (((char *) new_value.data) + 
 | 
						|
				  (prop_value->size * size_in_bytes));
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	if (new_data)
 | 
						|
	    memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
 | 
						|
	if (old_data)
 | 
						|
	    memcpy ((char *) old_data, (char *) prop_value->data, 
 | 
						|
		    prop_value->size * size_in_bytes);
 | 
						|
 | 
						|
	if (pending && pScrPriv->rrOutputSetProperty &&
 | 
						|
	    !pScrPriv->rrOutputSetProperty(output->pScreen, output,
 | 
						|
					   prop->propertyName, &new_value))
 | 
						|
	{
 | 
						|
	    if (new_value.data)
 | 
						|
		xfree (new_value.data);
 | 
						|
	    return (BadValue);
 | 
						|
	}
 | 
						|
	if (prop_value->data)
 | 
						|
	    xfree (prop_value->data);
 | 
						|
	*prop_value = new_value;
 | 
						|
    }
 | 
						|
 | 
						|
    else if (len == 0)
 | 
						|
    {
 | 
						|
	/* do nothing */
 | 
						|
    }
 | 
						|
 | 
						|
    if (add)
 | 
						|
    {
 | 
						|
	prop->next = output->properties;
 | 
						|
	output->properties = prop;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pending && prop->is_pending)
 | 
						|
	output->pendingProperties = TRUE;
 | 
						|
 | 
						|
    if (sendevent)
 | 
						|
    {
 | 
						|
	event.type = RREventBase + RRNotify;
 | 
						|
	event.subCode = RRNotify_OutputProperty;
 | 
						|
	event.output = output->id;
 | 
						|
	event.state = PropertyNewValue;
 | 
						|
	event.atom = prop->propertyName;
 | 
						|
	event.timestamp = currentTime.milliseconds;
 | 
						|
	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
 | 
						|
    }
 | 
						|
    return(Success);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
RRPostPendingProperties (RROutputPtr output)
 | 
						|
{
 | 
						|
    RRPropertyValuePtr	pending_value;
 | 
						|
    RRPropertyValuePtr	current_value;
 | 
						|
    RRPropertyPtr	property;
 | 
						|
    Bool		ret = TRUE;
 | 
						|
 | 
						|
    if (!output->pendingProperties)
 | 
						|
	return TRUE;
 | 
						|
    
 | 
						|
    output->pendingProperties = FALSE;
 | 
						|
    for (property = output->properties; property; property = property->next)
 | 
						|
    {
 | 
						|
	/* Skip non-pending properties */
 | 
						|
	if (!property->is_pending)
 | 
						|
	    continue;
 | 
						|
	
 | 
						|
	pending_value = &property->pending;
 | 
						|
	current_value = &property->current;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * If the pending and current values are equal, don't mark it
 | 
						|
	 * as changed (which would deliver an event)
 | 
						|
	 */
 | 
						|
	if (pending_value->type == current_value->type &&
 | 
						|
	    pending_value->format == current_value->format &&
 | 
						|
	    pending_value->size == current_value->size &&
 | 
						|
	    !memcmp (pending_value->data, current_value->data,
 | 
						|
		     pending_value->size))
 | 
						|
	    continue;
 | 
						|
 | 
						|
	if (RRChangeOutputProperty (output, property->propertyName,
 | 
						|
				    pending_value->type, pending_value->format,
 | 
						|
				    PropModeReplace, pending_value->size,
 | 
						|
				    pending_value->data, TRUE,
 | 
						|
				    FALSE) != Success)
 | 
						|
	    ret = FALSE;
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
RRPropertyPtr
 | 
						|
RRQueryOutputProperty (RROutputPtr output, Atom property)
 | 
						|
{
 | 
						|
    RRPropertyPtr   prop;
 | 
						|
    
 | 
						|
    for (prop = output->properties; prop; prop = prop->next)
 | 
						|
	if (prop->propertyName == property)
 | 
						|
	    return prop;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
		       
 | 
						|
RRPropertyValuePtr
 | 
						|
RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending)
 | 
						|
{
 | 
						|
    RRPropertyPtr   prop = RRQueryOutputProperty (output, property);
 | 
						|
    rrScrPrivPtr    pScrPriv = rrGetScrPriv(output->pScreen);
 | 
						|
 | 
						|
    if (!prop)
 | 
						|
	return NULL;
 | 
						|
    if (pending && prop->is_pending)
 | 
						|
	return &prop->pending;
 | 
						|
    else {
 | 
						|
#if RANDR_13_INTERFACE
 | 
						|
	/* If we can, try to update the property value first */
 | 
						|
	if (pScrPriv->rrOutputGetProperty)
 | 
						|
	    pScrPriv->rrOutputGetProperty(output->pScreen, output,
 | 
						|
					  prop->propertyName);
 | 
						|
#endif
 | 
						|
	return &prop->current;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
RRConfigureOutputProperty (RROutputPtr output, Atom property,
 | 
						|
			   Bool pending, Bool range, Bool immutable,
 | 
						|
			   int num_values, INT32 *values)
 | 
						|
{
 | 
						|
    RRPropertyPtr   prop = RRQueryOutputProperty (output, property);
 | 
						|
    Bool	    add = FALSE;
 | 
						|
    INT32	    *new_values;
 | 
						|
 | 
						|
    if (!prop)
 | 
						|
    {
 | 
						|
        prop = RRCreateOutputProperty (property);
 | 
						|
	if (!prop)
 | 
						|
	    return(BadAlloc);
 | 
						|
	add = TRUE;
 | 
						|
    } else if (prop->immutable && !immutable)
 | 
						|
	return(BadAccess);
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * ranges must have even number of values
 | 
						|
     */
 | 
						|
    if (range && (num_values & 1))
 | 
						|
	return BadMatch;
 | 
						|
 | 
						|
    new_values = xalloc (num_values * sizeof (INT32));
 | 
						|
    if (!new_values && num_values)
 | 
						|
	return BadAlloc;
 | 
						|
    if (num_values)
 | 
						|
	memcpy (new_values, values, num_values * sizeof (INT32));
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Property moving from pending to non-pending
 | 
						|
     * loses any pending values
 | 
						|
     */
 | 
						|
    if (prop->is_pending && !pending)
 | 
						|
    {
 | 
						|
	if (prop->pending.data)
 | 
						|
	    xfree (prop->pending.data);
 | 
						|
	RRInitOutputPropertyValue (&prop->pending);
 | 
						|
    }
 | 
						|
 | 
						|
    prop->is_pending = pending;
 | 
						|
    prop->range = range;
 | 
						|
    prop->immutable = immutable;
 | 
						|
    prop->num_valid = num_values;
 | 
						|
    if (prop->valid_values)
 | 
						|
	xfree (prop->valid_values);
 | 
						|
    prop->valid_values = new_values;
 | 
						|
 | 
						|
    if (add) {
 | 
						|
	prop->next = output->properties;
 | 
						|
	output->properties = prop;
 | 
						|
    }
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRListOutputProperties (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRListOutputPropertiesReq);
 | 
						|
    Atom			    *pAtoms = NULL, *temppAtoms;
 | 
						|
    xRRListOutputPropertiesReply    rep;
 | 
						|
    int				    numProps = 0;
 | 
						|
    RROutputPtr			    output;
 | 
						|
    RRPropertyPtr			    prop;
 | 
						|
    
 | 
						|
    REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
 | 
						|
 | 
						|
    output = LookupOutput (client, stuff->output, DixReadAccess);
 | 
						|
    
 | 
						|
    if (!output)
 | 
						|
        return RRErrorBase + BadRROutput;
 | 
						|
 | 
						|
    for (prop = output->properties; prop; prop = prop->next)
 | 
						|
	numProps++;
 | 
						|
    if (numProps)
 | 
						|
        if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
 | 
						|
            return(BadAlloc);
 | 
						|
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.length = (numProps * sizeof(Atom)) >> 2;
 | 
						|
    rep.sequenceNumber = client->sequence;
 | 
						|
    rep.nAtoms = numProps;
 | 
						|
    if (client->swapped) 
 | 
						|
    {
 | 
						|
	int n;
 | 
						|
	swaps (&rep.sequenceNumber, n);
 | 
						|
	swapl (&rep.length, n);
 | 
						|
    }
 | 
						|
    temppAtoms = pAtoms;
 | 
						|
    for (prop = output->properties; prop; prop = prop->next)
 | 
						|
	*temppAtoms++ = prop->propertyName;
 | 
						|
 | 
						|
    WriteReplyToClient(client, sizeof(xRRListOutputPropertiesReply), &rep);
 | 
						|
    if (numProps)
 | 
						|
    {
 | 
						|
        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
 | 
						|
        WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
 | 
						|
        xfree(pAtoms);
 | 
						|
    }
 | 
						|
    return(client->noClientException);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRQueryOutputProperty (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRQueryOutputPropertyReq);
 | 
						|
    xRRQueryOutputPropertyReply	    rep;
 | 
						|
    RROutputPtr			    output;
 | 
						|
    RRPropertyPtr		    prop;
 | 
						|
    
 | 
						|
    REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
 | 
						|
 | 
						|
    output = LookupOutput (client, stuff->output, DixReadAccess);
 | 
						|
    
 | 
						|
    if (!output)
 | 
						|
        return RRErrorBase + BadRROutput;
 | 
						|
    
 | 
						|
    prop = RRQueryOutputProperty (output, stuff->property);
 | 
						|
    if (!prop)
 | 
						|
	return BadName;
 | 
						|
    
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.length = prop->num_valid;
 | 
						|
    rep.sequenceNumber = client->sequence;
 | 
						|
    rep.pending = prop->is_pending;
 | 
						|
    rep.range = prop->range;
 | 
						|
    rep.immutable = prop->immutable;
 | 
						|
    if (client->swapped) 
 | 
						|
    {
 | 
						|
	int n;
 | 
						|
	swaps (&rep.sequenceNumber, n);
 | 
						|
	swapl (&rep.length, n);
 | 
						|
    }
 | 
						|
    WriteReplyToClient (client, sizeof (xRRQueryOutputPropertyReply), &rep);
 | 
						|
    if (prop->num_valid)
 | 
						|
    {
 | 
						|
        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
 | 
						|
        WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
 | 
						|
				 prop->valid_values);
 | 
						|
    }
 | 
						|
    return(client->noClientException);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRConfigureOutputProperty (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRConfigureOutputPropertyReq);
 | 
						|
    RROutputPtr				output;
 | 
						|
    int					num_valid;
 | 
						|
    
 | 
						|
    REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq);
 | 
						|
 | 
						|
    output = LookupOutput (client, stuff->output, DixReadAccess);
 | 
						|
    
 | 
						|
    if (!output)
 | 
						|
        return RRErrorBase + BadRROutput;
 | 
						|
    
 | 
						|
    num_valid = stuff->length - (sizeof (xRRConfigureOutputPropertyReq) >> 2);
 | 
						|
    return RRConfigureOutputProperty (output, stuff->property,
 | 
						|
				      stuff->pending, stuff->range,
 | 
						|
				      FALSE, num_valid, 
 | 
						|
				      (INT32 *) (stuff + 1));
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRChangeOutputProperty (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRChangeOutputPropertyReq);
 | 
						|
    RROutputPtr	    output;
 | 
						|
    char	    format, mode;
 | 
						|
    unsigned long   len;
 | 
						|
    int		    sizeInBytes;
 | 
						|
    int		    totalSize;
 | 
						|
    int		    err;
 | 
						|
 | 
						|
    REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq);
 | 
						|
    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(xRRChangeOutputPropertyReq, totalSize);
 | 
						|
 | 
						|
    output = LookupOutput (client, stuff->output, DixWriteAccess);
 | 
						|
    if (!output)
 | 
						|
	return RRErrorBase + BadRROutput;
 | 
						|
    
 | 
						|
    if (!ValidAtom(stuff->property))
 | 
						|
    {
 | 
						|
	client->errorValue = stuff->property;
 | 
						|
	return(BadAtom);
 | 
						|
    }
 | 
						|
    if (!ValidAtom(stuff->type))
 | 
						|
    {
 | 
						|
	client->errorValue = stuff->type;
 | 
						|
	return(BadAtom);
 | 
						|
    }
 | 
						|
 | 
						|
    err = RRChangeOutputProperty(output, stuff->property,
 | 
						|
				 stuff->type, (int)format,
 | 
						|
				 (int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
 | 
						|
    if (err != Success)
 | 
						|
	return err;
 | 
						|
    else
 | 
						|
	return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRDeleteOutputProperty (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRDeleteOutputPropertyReq);
 | 
						|
    RROutputPtr	output;
 | 
						|
              
 | 
						|
    REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
 | 
						|
    UpdateCurrentTime();
 | 
						|
    output = LookupOutput (client, stuff->output, DixWriteAccess);
 | 
						|
    if (!output)
 | 
						|
        return RRErrorBase + BadRROutput;
 | 
						|
    
 | 
						|
    if (!ValidAtom(stuff->property))
 | 
						|
    {
 | 
						|
	client->errorValue = stuff->property;
 | 
						|
	return (BadAtom);
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    RRDeleteOutputProperty(output, stuff->property);
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRGetOutputProperty (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRGetOutputPropertyReq);
 | 
						|
    RRPropertyPtr		prop, *prev;
 | 
						|
    RRPropertyValuePtr		prop_value;
 | 
						|
    unsigned long		n, len, ind;
 | 
						|
    RROutputPtr			output;
 | 
						|
    xRRGetOutputPropertyReply	reply;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
 | 
						|
    if (stuff->delete)
 | 
						|
	UpdateCurrentTime();
 | 
						|
    output = LookupOutput (client, stuff->output, 
 | 
						|
			   stuff->delete ? DixWriteAccess :
 | 
						|
			   DixReadAccess);
 | 
						|
    if (!output)
 | 
						|
	return RRErrorBase + BadRROutput;
 | 
						|
 | 
						|
    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);
 | 
						|
    }
 | 
						|
 | 
						|
    for (prev = &output->properties; (prop = *prev); prev = &prop->next)
 | 
						|
	if (prop->propertyName == stuff->property) 
 | 
						|
	    break;
 | 
						|
 | 
						|
    reply.type = X_Reply;
 | 
						|
    reply.sequenceNumber = client->sequence;
 | 
						|
    if (!prop) 
 | 
						|
    {
 | 
						|
	reply.nItems = 0;
 | 
						|
	reply.length = 0;
 | 
						|
	reply.bytesAfter = 0;
 | 
						|
	reply.propertyType = None;
 | 
						|
	reply.format = 0;
 | 
						|
	WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
 | 
						|
	return(client->noClientException);
 | 
						|
    }
 | 
						|
 | 
						|
    if (prop->immutable && stuff->delete)
 | 
						|
	return BadAccess;
 | 
						|
 | 
						|
    prop_value = RRGetOutputProperty(output, stuff->property, stuff->pending);
 | 
						|
    if (!prop_value)
 | 
						|
	return BadAtom;
 | 
						|
 | 
						|
    /* If the request type and actual type don't match. Return the
 | 
						|
    property information, but not the data. */
 | 
						|
 | 
						|
    if (((stuff->type != prop_value->type) &&
 | 
						|
	 (stuff->type != AnyPropertyType))
 | 
						|
       )
 | 
						|
    {
 | 
						|
	reply.bytesAfter = prop_value->size;
 | 
						|
	reply.format = prop_value->format;
 | 
						|
	reply.length = 0;
 | 
						|
	reply.nItems = 0;
 | 
						|
	reply.propertyType = prop_value->type;
 | 
						|
	WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
 | 
						|
	return(client->noClientException);
 | 
						|
    }
 | 
						|
 | 
						|
/*
 | 
						|
 *  Return type, format, value to client
 | 
						|
 */
 | 
						|
    n = (prop_value->format/8) * prop_value->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 = prop_value->format;
 | 
						|
    reply.length = (len + 3) >> 2;
 | 
						|
    if (prop_value->format)
 | 
						|
	reply.nItems = len / (prop_value->format / 8);
 | 
						|
    else
 | 
						|
	reply.nItems = 0;
 | 
						|
    reply.propertyType = prop_value->type;
 | 
						|
 | 
						|
    if (stuff->delete && (reply.bytesAfter == 0))
 | 
						|
    {
 | 
						|
	xRROutputPropertyNotifyEvent    event;
 | 
						|
 | 
						|
	event.type = RREventBase + RRNotify;
 | 
						|
	event.subCode = RRNotify_OutputProperty;
 | 
						|
	event.output = output->id;
 | 
						|
	event.state = PropertyDelete;
 | 
						|
	event.atom = prop->propertyName;
 | 
						|
	event.timestamp = currentTime.milliseconds;
 | 
						|
	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
 | 
						|
    }
 | 
						|
 | 
						|
    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 *)prop_value->data + ind);
 | 
						|
    }
 | 
						|
 | 
						|
    if (stuff->delete && (reply.bytesAfter == 0))
 | 
						|
    { /* delete the Property */
 | 
						|
	*prev = prop->next;
 | 
						|
	RRDestroyOutputProperty (prop);
 | 
						|
    }
 | 
						|
    return(client->noClientException);
 | 
						|
}
 | 
						|
 |