1 /***********************************************************
2
3 Copyright (c) 1987 X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29 All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its
32 documentation for any purpose and without fee is hereby granted,
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ******************************************************************/
48
49
50 /* $XConsortium: cursor.c /main/19 1996/08/01 19:20:16 dpw $ */
51 /* $XFree86: xc/programs/Xserver/dix/cursor.c,v 3.1 1996/12/23 06:29:36 dawes Exp $ */
52
53 #include "X.h"
54 #include "Xmd.h"
55 #include "servermd.h"
56 #include "scrnintstr.h"
57 #include "dixstruct.h"
58 #include "cursorstr.h"
59 #include "dixfontstr.h"
60 #include "opaque.h"
61
62 typedef struct _GlyphShare {
63 FontPtr font;
64 unsigned short sourceChar;
65 unsigned short maskChar;
66 CursorBitsPtr bits;
67 struct _GlyphShare *next;
68 } GlyphShare, *GlyphSharePtr;
69
70 static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL;
71
72 static void
73 #if NeedFunctionPrototypes
FreeCursorBits(CursorBitsPtr bits)74 FreeCursorBits(CursorBitsPtr bits)
75 #else
76 FreeCursorBits(bits)
77 CursorBitsPtr bits;
78 #endif
79 {
80 if (--bits->refcnt > 0)
81 return;
82 xfree(bits->source);
83 xfree(bits->mask);
84 if (bits->refcnt == 0)
85 {
86 register GlyphSharePtr *prev, this;
87
88 for (prev = &sharedGlyphs;
89 (this = *prev) && (this->bits != bits);
90 prev = &this->next)
91 ;
92 if (this)
93 {
94 *prev = this->next;
95 CloseFont(this->font, (Font)0);
96 xfree(this);
97 }
98 xfree(bits);
99 }
100 }
101
102 /*
103 * To be called indirectly by DeleteResource; must use exactly two args
104 */
105 /*ARGSUSED*/
106 int
FreeCursor(value,cid)107 FreeCursor(value, cid)
108 pointer value; /* must conform to DeleteType */
109 XID cid;
110 {
111 int nscr;
112 CursorPtr pCurs = (CursorPtr)value;
113
114 ScreenPtr pscr;
115
116 if ( --pCurs->refcnt > 0)
117 return(Success);
118
119 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
120 {
121 pscr = screenInfo.screens[nscr];
122 (void)( *pscr->UnrealizeCursor)( pscr, pCurs);
123 }
124 FreeCursorBits(pCurs->bits);
125 xfree( pCurs);
126 return(Success);
127 }
128
129 /*
130 * does nothing about the resource table, just creates the data structure.
131 * does not copy the src and mask bits
132 */
133 CursorPtr
AllocCursor(psrcbits,pmaskbits,cm,foreRed,foreGreen,foreBlue,backRed,backGreen,backBlue)134 AllocCursor(psrcbits, pmaskbits, cm,
135 foreRed, foreGreen, foreBlue, backRed, backGreen, backBlue)
136 unsigned char * psrcbits; /* server-defined padding */
137 unsigned char * pmaskbits; /* server-defined padding */
138 CursorMetricPtr cm;
139 unsigned foreRed, foreGreen, foreBlue;
140 unsigned backRed, backGreen, backBlue;
141 {
142 CursorBitsPtr bits;
143 CursorPtr pCurs;
144 int nscr;
145 ScreenPtr pscr;
146
147 pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
148 if (!pCurs)
149 {
150 xfree(psrcbits);
151 xfree(pmaskbits);
152 return (CursorPtr)NULL;
153 }
154 bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
155 bits->source = psrcbits;
156 bits->mask = pmaskbits;
157 bits->width = cm->width;
158 bits->height = cm->height;
159 bits->xhot = cm->xhot;
160 bits->yhot = cm->yhot;
161 bits->refcnt = -1;
162
163 pCurs->bits = bits;
164 pCurs->refcnt = 1;
165
166 pCurs->foreRed = foreRed;
167 pCurs->foreGreen = foreGreen;
168 pCurs->foreBlue = foreBlue;
169
170 pCurs->backRed = backRed;
171 pCurs->backGreen = backGreen;
172 pCurs->backBlue = backBlue;
173
174 /*
175 * realize the cursor for every screen
176 */
177 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
178 {
179 pscr = screenInfo.screens[nscr];
180 if (!( *pscr->RealizeCursor)( pscr, pCurs))
181 {
182 while (--nscr >= 0)
183 {
184 pscr = screenInfo.screens[nscr];
185 ( *pscr->UnrealizeCursor)( pscr, pCurs);
186 }
187 FreeCursorBits(bits);
188 xfree(pCurs);
189 return (CursorPtr)NULL;
190 }
191 }
192 return pCurs;
193 }
194
195 int
AllocGlyphCursor(source,sourceChar,mask,maskChar,foreRed,foreGreen,foreBlue,backRed,backGreen,backBlue,ppCurs,client)196 AllocGlyphCursor(source, sourceChar, mask, maskChar,
197 foreRed, foreGreen, foreBlue, backRed, backGreen, backBlue,
198 ppCurs, client)
199 Font source, mask;
200 unsigned int sourceChar, maskChar;
201 unsigned foreRed, foreGreen, foreBlue;
202 unsigned backRed, backGreen, backBlue;
203 CursorPtr *ppCurs;
204 ClientPtr client;
205 {
206 FontPtr sourcefont, maskfont;
207 unsigned char *srcbits;
208 unsigned char *mskbits;
209 CursorMetricRec cm;
210 int res;
211 CursorBitsPtr bits;
212 CursorPtr pCurs;
213 int nscr;
214 ScreenPtr pscr;
215 GlyphSharePtr pShare;
216
217 sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT,
218 SecurityReadAccess);
219 maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT,
220 SecurityReadAccess);
221
222 if (!sourcefont)
223 {
224 client->errorValue = source;
225 return(BadFont);
226 }
227 if (!maskfont && (mask != None))
228 {
229 client->errorValue = mask;
230 return(BadFont);
231 }
232 if (sourcefont != maskfont)
233 pShare = (GlyphSharePtr)NULL;
234 else
235 {
236 for (pShare = sharedGlyphs;
237 pShare &&
238 ((pShare->font != sourcefont) ||
239 (pShare->sourceChar != sourceChar) ||
240 (pShare->maskChar != maskChar));
241 pShare = pShare->next)
242 ;
243 }
244 if (pShare)
245 {
246 pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
247 if (!pCurs)
248 return BadAlloc;
249 bits = pShare->bits;
250 bits->refcnt++;
251 }
252 else
253 {
254 if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm))
255 {
256 client->errorValue = sourceChar;
257 return BadValue;
258 }
259 if (!maskfont)
260 {
261 register long n;
262 register unsigned char *mskptr;
263
264 n = BitmapBytePad(cm.width)*(long)cm.height;
265 mskptr = mskbits = (unsigned char *)xalloc(n);
266 if (!mskptr)
267 return BadAlloc;
268 while (--n >= 0)
269 *mskptr++ = ~0;
270 }
271 else
272 {
273 if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm))
274 {
275 client->errorValue = maskChar;
276 return BadValue;
277 }
278 if ((res = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)) != 0)
279 return res;
280 }
281 if ((res = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)) != 0)
282 {
283 xfree(mskbits);
284 return res;
285 }
286 if (sourcefont != maskfont)
287 {
288 pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
289 if (pCurs)
290 bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
291 else
292 bits = (CursorBitsPtr)NULL;
293 }
294 else
295 {
296 pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
297 if (pCurs)
298 bits = (CursorBitsPtr)xalloc(sizeof(CursorBits));
299 else
300 bits = (CursorBitsPtr)NULL;
301 }
302 if (!bits)
303 {
304 xfree(pCurs);
305 xfree(mskbits);
306 xfree(srcbits);
307 return BadAlloc;
308 }
309 bits->source = srcbits;
310 bits->mask = mskbits;
311 bits->width = cm.width;
312 bits->height = cm.height;
313 bits->xhot = cm.xhot;
314 bits->yhot = cm.yhot;
315 if (sourcefont != maskfont)
316 bits->refcnt = -1;
317 else
318 {
319 bits->refcnt = 1;
320 pShare = (GlyphSharePtr)xalloc(sizeof(GlyphShare));
321 if (!pShare)
322 {
323 FreeCursorBits(bits);
324 return BadAlloc;
325 }
326 pShare->font = sourcefont;
327 sourcefont->refcnt++;
328 pShare->sourceChar = sourceChar;
329 pShare->maskChar = maskChar;
330 pShare->bits = bits;
331 pShare->next = sharedGlyphs;
332 sharedGlyphs = pShare;
333 }
334 }
335 pCurs->bits = bits;
336 pCurs->refcnt = 1;
337
338 pCurs->foreRed = foreRed;
339 pCurs->foreGreen = foreGreen;
340 pCurs->foreBlue = foreBlue;
341
342 pCurs->backRed = backRed;
343 pCurs->backGreen = backGreen;
344 pCurs->backBlue = backBlue;
345
346 /*
347 * realize the cursor for every screen
348 */
349 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
350 {
351 pscr = screenInfo.screens[nscr];
352 if (!( *pscr->RealizeCursor)( pscr, pCurs))
353 {
354 while (--nscr >= 0)
355 {
356 pscr = screenInfo.screens[nscr];
357 ( *pscr->UnrealizeCursor)( pscr, pCurs);
358 }
359 FreeCursorBits(pCurs->bits);
360 xfree(pCurs);
361 return BadAlloc;
362 }
363 }
364 *ppCurs = pCurs;
365 return Success;
366 }
367
368 /***********************************************************
369 * CreateRootCursor
370 *
371 * look up the name of a font
372 * open the font
373 * add the font to the resource table
374 * make a cursor from the glyphs
375 * add the cursor to the resource table
376 *************************************************************/
377
378 CursorPtr
CreateRootCursor(pfilename,glyph)379 CreateRootCursor(pfilename, glyph)
380 char * pfilename;
381 unsigned int glyph;
382 {
383 CursorPtr curs;
384 FontPtr cursorfont;
385 int err;
386 XID fontID;
387
388 fontID = FakeClientID(0);
389 err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync,
390 (unsigned)strlen( pfilename), pfilename);
391 if (err != Success)
392 return NullCursor;
393
394 cursorfont = (FontPtr)LookupIDByType(fontID, RT_FONT);
395 if (!cursorfont)
396 return NullCursor;
397 if (AllocGlyphCursor(fontID, glyph, fontID, glyph + 1,
398 0, 0, 0, ~0, ~0, ~0, &curs, serverClient) != Success)
399 return NullCursor;
400
401 if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs))
402 return NullCursor;
403
404 return curs;
405 }
406