|
|
1.1 root 1: /***********************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ******************************************************************/
24: /* $Header: property.c,v 1.55 87/09/03 03:04:04 newman Exp $ */
25:
26: #include "X.h"
27: #define NEED_REPLIES
28: #define NEED_EVENTS
29: #include "Xproto.h"
30: #include "windowstr.h"
31: #include "propertyst.h"
32: #include "dixstruct.h"
33:
34: extern void (*ReplySwapVector[]) ();
35: extern void CopySwap16Write(), CopySwap32Write(), Swap32Write(), WriteToClient();
36:
37: /*****************************************************************
38: * Property Stuff
39: *
40: * ChangeProperty, DeleteProperty, GetProperties,
41: * ListProperties
42: *
43: * Properties below to windows. A allocate slots each time
44: * a property is added. No fancy searching done.
45: *
46: *****************************************************************/
47:
48: static void
49: PrintPropertys(pWin)
50: WindowPtr pWin;
51: {
52: PropertyPtr pProp;
53: register int j;
54:
55: pProp = pWin->userProps;
56: while (pProp)
57: {
58: ErrorF( "%x %x\n", pProp->propertyName, pProp->type);
59: ErrorF("property format: %d\n", pProp->format);
60: ErrorF("property data: \n");
61: for (j=0; j<(pProp->format/8)*pProp->size; j++)
62: ErrorF("%c\n", pProp->data[j]);
63: pProp = pProp->next;
64: }
65: }
66:
67:
68: int
69: ProcRotateProperties(client)
70: ClientPtr client;
71: {
72: int i, j, delta;
73: REQUEST(xRotatePropertiesReq);
74: WindowPtr pWin;
75: register Atom * atoms;
76: PropertyPtr * props; /* array of pointer */
77: PropertyPtr pProp;
78: xEvent event;
79:
80: REQUEST_AT_LEAST_SIZE(xRotatePropertiesReq);
81: if (stuff->length != ((sizeof(xRotatePropertiesReq) >> 2) + stuff->nAtoms))
82: return BadLength;
83: pWin = (WindowPtr) LookupWindow(stuff->window, client);
84: if (!pWin)
85: return(BadWindow);
86: atoms = (Atom *) & stuff[1];
87: props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr));
88: for (i = 0; i < stuff->nAtoms; i++)
89: {
90: if (!ValidAtom(atoms[i]))
91: {
92: DEALLOCATE_LOCAL(props);
93: return BadAtom;
94: }
95: for (j = i + 1; j < stuff->nAtoms; j++)
96: if (atoms[j] == atoms[i])
97: {
98: DEALLOCATE_LOCAL(props);
99: return BadMatch;
100: }
101: pProp = pWin->userProps;
102: while (pProp)
103: {
104: if (pProp->propertyName == atoms[i])
105: goto found;
106: pProp = pProp->next;
107: }
108: DEALLOCATE_LOCAL(props);
109: return BadMatch;
110: found:
111: props[i] = pProp;
112: }
113: delta = stuff->nPositions;
114:
115: /* If the rotation is a complete 360 degrees, then moving the properties
116: around and generating PropertyNotify events should be skipped. */
117:
118: if ( (stuff->nAtoms > 0) && (abs(delta) % stuff->nAtoms) != 0 )
119: {
120: while (delta < 0) /* faster if abs value is small */
121: delta += stuff->nAtoms;
122: for (i = 0; i < stuff->nAtoms; i++)
123: {
124: /* Generate a PropertyNotify event for each property whose value
125: is changed in the order in which they appear in the request. */
126:
127: event.u.u.type = PropertyNotify;
128: event.u.property.window = pWin->wid;
129: event.u.property.state = PropertyNewValue;
130: event.u.property.atom = props[i]->propertyName;
131: event.u.property.time = currentTime.milliseconds;
132: DeliverEvents(pWin, &event, 1);
133:
134: props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms];
135: }
136: }
137: DEALLOCATE_LOCAL(props);
138: return Success;
139: }
140:
141: int
142: ProcChangeProperty(client)
143: ClientPtr client;
144: {
145: WindowPtr pWin;
146: char format, mode;
147: int len;
148: PropertyPtr pProp;
149: xEvent event;
150: int sizeInBytes;
151: REQUEST(xChangePropertyReq);
152:
153: REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
154: format = stuff->format;
155: mode = stuff->mode;
156: if (((mode != PropModeReplace) && (mode != PropModeAppend) &&
157: (mode != PropModePrepend))
158: || ((format != 8) && (format != 16) && (format != 32)))
159: return BadValue;
160:
161: pWin = (WindowPtr)LookupWindow(stuff->window, client);
162: if (!pWin)
163: return(BadWindow);
164: if (!(ValidAtom(stuff->property) && ValidAtom(stuff->type)))
165: return(BadAtom);
166:
167: /* first see if property already exists */
168:
169: len = stuff->nUnits;
170: sizeInBytes = format/8;
171: pProp = pWin->userProps;
172: while (pProp)
173: {
174: if (pProp->propertyName ==stuff->property)
175: break;
176: pProp = pProp->next;
177: }
178: if (!pProp) /* just add to list */
179: {
180: pProp = (PropertyPtr)Xalloc(sizeof(PropertyRec));
181: pProp->propertyName = stuff->property;
182: pProp->type = stuff->type;
183: pProp->format = format;
184: pProp->data = (pointer)Xalloc(sizeInBytes * len);
185: bcopy(&stuff[1], pProp->data, len * sizeInBytes);
186: pProp->size = len;
187: pProp->next = pWin->userProps;
188: pWin->userProps = pProp;
189: }
190: else
191: {
192:
193: /* To append or prepend to a property the request format and type
194: must match those of the already defined property. The
195: existing format and type are irrelevant when using the mode
196: "PropModeReplace" since they will be written over. */
197:
198: if ((format != pProp->format) && (mode != PropModeReplace))
199: return(BadMatch);
200: if ((pProp->type != stuff->type) && (mode != PropModeReplace))
201: return(BadMatch);
202: /* XXX should check length too */
203: if (mode == PropModeReplace)
204: {
205: pProp->data = (pointer)Xrealloc((char *) pProp->data,
206: sizeInBytes * len);
207: bcopy(&stuff[1], pProp->data, len * sizeInBytes);
208: pProp->size = len;
209: pProp->type = stuff->type;
210: pProp->format = stuff->format;
211: }
212: else if (mode == PropModeAppend)
213: {
214: pProp->data = (pointer)Xrealloc((char *) pProp->data,
215: sizeInBytes * (len + pProp->size));
216: bcopy(&stuff[1], &pProp->data[pProp->size * sizeInBytes],
217: len * sizeInBytes);
218: pProp->size += len;
219: }
220: else if (mode == PropModePrepend)
221: {
222: pointer tstr = pProp->data;
223: pProp->data = (pointer)Xalloc(sizeInBytes * (len + pProp->size));
224: bcopy(tstr, &pProp->data[len * sizeInBytes],
225: pProp->size * sizeInBytes);
226: bcopy(&stuff[1], pProp->data, len * sizeInBytes);
227: pProp->size += len;
228: Xfree(tstr);
229: }
230: }
231: event.u.u.type = PropertyNotify;
232: event.u.property.window = pWin->wid;
233: event.u.property.state = PropertyNewValue;
234: event.u.property.atom = pProp->propertyName;
235: event.u.property.time = currentTime.milliseconds;
236: DeliverEvents(pWin, &event, 1);
237:
238: return(client->noClientException);
239: }
240:
241: DeleteProperty(pWin, propName)
242: WindowPtr pWin;
243: ATOM propName;
244: {
245: PropertyPtr pProp, prevProp;
246: xEvent event;
247:
248: if (!(pProp = pWin->userProps))
249: return(BadAtom);
250: prevProp = (PropertyPtr)NULL;
251: while (pProp)
252: {
253: if (pProp->propertyName == propName)
254: break;
255: prevProp = pProp;
256: pProp = pProp->next;
257: }
258: if (pProp)
259: {
260: if (prevProp == (PropertyPtr)NULL) /* takes care of head */
261: {
262: pWin->userProps = pProp->next;
263: }
264: else
265: {
266: prevProp->next = pProp->next;
267: }
268: Xfree(pProp->data);
269: Xfree(pProp);
270:
271: event.u.u.type = PropertyNotify;
272: event.u.property.window = pWin->wid;
273: event.u.property.state = PropertyDelete;
274: event.u.property.atom = pProp->propertyName;
275: event.u.property.time = currentTime.milliseconds;
276: DeliverEvents(pWin, &event, 1);
277:
278: return(Success);
279: }
280: else
281: return(BadAtom);
282: }
283:
284: DeleteAllWindowProperties(pWin)
285: WindowPtr pWin;
286: {
287: PropertyPtr pProp, pNextProp;
288: xEvent event;
289:
290: pProp = pWin->userProps;
291: while (pProp)
292: {
293: event.u.u.type = PropertyNotify;
294: event.u.property.window = pWin->wid;
295: event.u.property.state = PropertyDelete;
296: event.u.property.atom = pProp->propertyName;
297: event.u.property.time = currentTime.milliseconds;
298: DeliverEvents(pWin, &event, 1);
299: pNextProp = pProp->next;
300: Xfree(pProp->data);
301: Xfree(pProp);
302: pProp = pNextProp;
303: }
304: }
305:
306: /*****************
307: * GetProperty
308: * If type Any is specified, returns the property from the specified
309: * window regardless of its type. If a type is specified, returns the
310: * property only if its type equals the specified type.
311: * If delete is True and a property is returned, the property is also
312: * deleted from the window and a PropertyNotify event is generated on the
313: * window.
314: *****************/
315:
316: int
317: ProcGetProperty(client)
318: ClientPtr client;
319: {
320: PropertyPtr pProp, prevProp;
321: int n, len, ind;
322: WindowPtr pWin;
323: xGetPropertyReply reply;
324: REQUEST(xGetPropertyReq);
325:
326: REQUEST_SIZE_MATCH(xGetPropertyReq);
327: pWin = (WindowPtr)LookupWindow(stuff->window, client);
328: client->errorValue = stuff->window;
329: if (pWin)
330: {
331: if (ValidAtom(stuff->property) &&
332: ((stuff->type == AnyPropertyType) || ValidAtom(stuff->type)))
333: {
334: pProp = pWin->userProps;
335: prevProp = (PropertyPtr)NULL;
336: while (pProp)
337: {
338: if (pProp->propertyName == stuff->property)
339: break;
340: prevProp = pProp;
341: pProp = pProp->next;
342: }
343: reply.type = X_Reply;
344: reply.sequenceNumber = client->sequence;
345: if (pProp)
346: {
347:
348: /* If the request type and actual type don't match. Return the
349: property information, but not the data. */
350:
351: if ((stuff->type != pProp->type) &&
352: (stuff->type != AnyPropertyType))
353: {
354: reply.bytesAfter = pProp->size;
355: reply.format = pProp->format;
356: reply.length = 0;
357: reply.nItems = 0;
358: reply.propertyType = pProp->type;
359: WriteReplyToClient(client, sizeof(xGenericReply), &reply);
360: return(Success);
361: }
362:
363: /*
364: * Return type, format, value to client
365: */
366: n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */
367: ind = stuff->longOffset << 2;
368:
369: /* If longOffset is invalid such that it causes "len" to
370: be negative, it's a value error. */
371:
372: if ((n - ind) < 0)
373: return BadValue;
374:
375: len = min(n - ind, 4 * stuff->longLength);
376:
377: reply.bytesAfter = n - (ind + len);
378: reply.format = pProp->format;
379: reply.length = len >> 2;
380: reply.nItems = len / (pProp->format / 8 );
381: reply.propertyType = pProp->type;
382: WriteReplyToClient(client, sizeof(xGenericReply), &reply);
383: switch (reply.format) {
384: case 32: client->pSwapReplyFunc = CopySwap32Write; break;
385: case 16: client->pSwapReplyFunc = CopySwap16Write; break;
386: default: client->pSwapReplyFunc = WriteToClient; break;
387: }
388: WriteSwappedDataToClient(client, len, pProp->data + ind);
389:
390: if (stuff->delete && (reply.bytesAfter == 0))
391: { /* delete the Property */
392: xEvent event;
393:
394: if (prevProp == (PropertyPtr)NULL) /* takes care of head */
395: pWin->userProps = pProp->next;
396: else
397: prevProp->next = pProp->next;
398: Xfree(pProp->data);
399: Xfree(pProp);
400: event.u.u.type = PropertyNotify;
401: event.u.property.window = pWin->wid;
402: event.u.property.state = PropertyDelete;
403: event.u.property.atom = pProp->propertyName;
404: event.u.property.time = currentTime.milliseconds;
405: DeliverEvents(pWin, &event, 1);
406: }
407: }
408: else
409: {
410: reply.nItems = 0;
411: reply.length = 0;
412: reply.bytesAfter = 0;
413: reply.propertyType = None;
414: reply.format = 0;
415: WriteReplyToClient(client, sizeof(xGenericReply), &reply);
416: }
417: return(client->noClientException);
418:
419: }
420: else
421: return(BadAtom);
422: }
423: else
424: return (BadWindow);
425: }
426:
427: int
428: ProcListProperties(client)
429: ClientPtr client;
430: {
431: Atom *pAtoms, *temppAtoms;
432: xListPropertiesReply xlpr;
433: int numProps = 0;
434: WindowPtr pWin;
435: PropertyPtr pProp;
436: REQUEST(xResourceReq);
437:
438: REQUEST_SIZE_MATCH(xResourceReq);
439: pWin = (WindowPtr)LookupWindow(stuff->id, client);
440: if (!pWin)
441: return(BadWindow);
442:
443: pProp = pWin->userProps;
444: while (pProp)
445: {
446: pProp = pProp->next;
447: numProps++;
448: }
449: if (numProps)
450: if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom))))
451: return(client->noClientException = BadAlloc);
452:
453: xlpr.type = X_Reply;
454: xlpr.nProperties = numProps;
455: xlpr.length = (numProps * sizeof(Atom)) >> 2;
456: xlpr.sequenceNumber = client->sequence;
457: pProp = pWin->userProps;
458: temppAtoms = pAtoms;
459: while (pProp)
460: {
461: *temppAtoms++ = pProp->propertyName;
462: pProp = pProp->next;
463: }
464: WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
465: if (numProps)
466: {
467: client->pSwapReplyFunc = Swap32Write;
468: WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
469: DEALLOCATE_LOCAL(pAtoms);
470: }
471: return(client->noClientException);
472: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.