Home | History | Annotate | Line # | Download | only in src
      1 /*
      2 
      3 Copyright 1987, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included
     12 in all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall
     23 not be used in advertising or otherwise to promote the sale, use or
     24 other dealings in this Software without prior written authorization
     25 from The Open Group.
     26 
     27 */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include <config.h>
     31 #endif
     32 #include <X11/Xlibint.h>
     33 #include <X11/Xos.h>
     34 #include <stdio.h>
     35 
     36 /* The X11 protocol spec reserves events 64 through 127 for extensions */
     37 #ifndef LastExtensionEvent
     38 #define LastExtensionEvent 127
     39 #endif
     40 
     41 /* The X11 protocol spec reserves requests 128 through 255 for extensions */
     42 #ifndef LastExtensionRequest
     43 #define FirstExtensionRequest 128
     44 #define LastExtensionRequest 255
     45 #endif
     46 
     47 
     48 /*
     49  * This routine is used to link a extension in so it will be called
     50  * at appropriate times.
     51  */
     52 
     53 XExtCodes *XInitExtension (
     54 	Display *dpy,
     55 	_Xconst char *name)
     56 {
     57 	XExtCodes codes;	/* temp. place for extension information. */
     58 	register _XExtension *ext;/* need a place to build it all */
     59 	if (!XQueryExtension(dpy, name,
     60 		&codes.major_opcode, &codes.first_event,
     61 		&codes.first_error)) return (NULL);
     62 
     63 	LockDisplay (dpy);
     64 	if (! (ext = Xcalloc (1, sizeof (_XExtension))) ||
     65 	    ! (ext->name = strdup(name))) {
     66 	    Xfree(ext);
     67 	    UnlockDisplay(dpy);
     68 	    return (XExtCodes *) NULL;
     69 	}
     70 	codes.extension = dpy->ext_number++;
     71 	ext->codes = codes;
     72 
     73 	/* chain it onto the display list */
     74 	ext->next = dpy->ext_procs;
     75 	dpy->ext_procs = ext;
     76 	UnlockDisplay (dpy);
     77 
     78 	return (&ext->codes);		/* tell him which extension */
     79 }
     80 
     81 XExtCodes *XAddExtension (Display *dpy)
     82 {
     83     register _XExtension *ext;
     84 
     85     LockDisplay (dpy);
     86     if (! (ext = Xcalloc (1, sizeof (_XExtension)))) {
     87 	UnlockDisplay(dpy);
     88 	return (XExtCodes *) NULL;
     89     }
     90     ext->codes.extension = dpy->ext_number++;
     91 
     92     /* chain it onto the display list */
     93     ext->next = dpy->ext_procs;
     94     dpy->ext_procs = ext;
     95     UnlockDisplay (dpy);
     96 
     97     return (&ext->codes);		/* tell him which extension */
     98 }
     99 
    100 static _XExtension *XLookupExtension (
    101 	register Display *dpy,	/* display */
    102 	register int extension)	/* extension number */
    103 {
    104 	register _XExtension *ext;
    105 	for (ext = dpy->ext_procs; ext; ext = ext->next)
    106 	    if (ext->codes.extension == extension) return (ext);
    107 	return (NULL);
    108 }
    109 
    110 XExtData **XEHeadOfExtensionList(XEDataObject object)
    111 {
    112     return *(XExtData ***)&object;
    113 }
    114 
    115 int
    116 XAddToExtensionList(
    117     XExtData **structure,
    118     XExtData *ext_data)
    119 {
    120     ext_data->next = *structure;
    121     *structure = ext_data;
    122     return 1;
    123 }
    124 
    125 XExtData *XFindOnExtensionList(
    126     XExtData **structure,
    127     int number)
    128 {
    129     XExtData *ext;
    130 
    131     ext = *structure;
    132     while (ext && (ext->number != number))
    133 	ext = ext->next;
    134     return ext;
    135 }
    136 
    137 /*
    138  * Routines to hang procs on the extension structure.
    139  */
    140 CreateGCType XESetCreateGC(
    141 	Display *dpy,		/* display */
    142 	int extension,		/* extension number */
    143 	CreateGCType proc)	/* routine to call when GC created */
    144 {
    145 	register _XExtension *e;	/* for lookup of extension */
    146 	register CreateGCType oldproc;
    147 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    148 	LockDisplay(dpy);
    149 	oldproc = e->create_GC;
    150 	e->create_GC = proc;
    151 	UnlockDisplay(dpy);
    152 	return (CreateGCType)oldproc;
    153 }
    154 
    155 CopyGCType XESetCopyGC(
    156 	Display *dpy,		/* display */
    157 	int extension,		/* extension number */
    158 	CopyGCType proc)	/* routine to call when GC copied */
    159 {
    160 	register _XExtension *e;	/* for lookup of extension */
    161 	register CopyGCType oldproc;
    162 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    163 	LockDisplay(dpy);
    164 	oldproc = e->copy_GC;
    165 	e->copy_GC = proc;
    166 	UnlockDisplay(dpy);
    167 	return (CopyGCType)oldproc;
    168 }
    169 
    170 FlushGCType XESetFlushGC(
    171 	Display *dpy,		/* display */
    172 	int extension,		/* extension number */
    173 	FlushGCType proc)	/* routine to call when GC copied */
    174 {
    175 	register _XExtension *e;	/* for lookup of extension */
    176 	register FlushGCType oldproc;
    177 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    178 	LockDisplay(dpy);
    179 	oldproc = e->flush_GC;
    180 	e->flush_GC = proc;
    181 	UnlockDisplay(dpy);
    182 	return (FlushGCType)oldproc;
    183 }
    184 
    185 FreeGCType XESetFreeGC(
    186 	Display *dpy,		/* display */
    187 	int extension,		/* extension number */
    188 	FreeGCType proc)	/* routine to call when GC freed */
    189 {
    190 	register _XExtension *e;	/* for lookup of extension */
    191 	register FreeGCType oldproc;
    192 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    193 	LockDisplay(dpy);
    194 	oldproc = e->free_GC;
    195 	e->free_GC = proc;
    196 	UnlockDisplay(dpy);
    197 	return (FreeGCType)oldproc;
    198 }
    199 
    200 CreateFontType XESetCreateFont(
    201 	Display *dpy,		/* display */
    202 	int extension,		/* extension number */
    203 	CreateFontType proc)	/* routine to call when font created */
    204 {
    205 	register _XExtension *e;	/* for lookup of extension */
    206 	register CreateFontType oldproc;
    207 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    208 	LockDisplay(dpy);
    209 	oldproc = e->create_Font;
    210 	e->create_Font = proc;
    211 	UnlockDisplay(dpy);
    212 	return (CreateFontType)oldproc;
    213 }
    214 
    215 FreeFontType XESetFreeFont(
    216 	Display *dpy,		/* display */
    217 	int extension,		/* extension number */
    218 	FreeFontType proc)	/* routine to call when font freed */
    219 {
    220 	register _XExtension *e;	/* for lookup of extension */
    221 	register FreeFontType oldproc;
    222 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    223 	LockDisplay(dpy);
    224 	oldproc = e->free_Font;
    225 	e->free_Font = proc;
    226 	UnlockDisplay(dpy);
    227 	return (FreeFontType)oldproc;
    228 }
    229 
    230 CloseDisplayType XESetCloseDisplay(
    231 	Display *dpy,		/* display */
    232 	int extension,		/* extension number */
    233 	CloseDisplayType proc)	/* routine to call when display closed */
    234 {
    235 	register _XExtension *e;	/* for lookup of extension */
    236 	register CloseDisplayType oldproc;
    237 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    238 	LockDisplay(dpy);
    239 	oldproc = e->close_display;
    240 	e->close_display = proc;
    241 	UnlockDisplay(dpy);
    242 	return (CloseDisplayType)oldproc;
    243 }
    244 
    245 typedef Bool (*WireToEventType) (
    246     Display*	/* display */,
    247     XEvent*	/* re */,
    248     xEvent*	/* event */
    249 );
    250 
    251 WireToEventType XESetWireToEvent(
    252 	Display *dpy,		/* display */
    253 	int event_number,	/* event routine to replace */
    254 	WireToEventType proc)	/* routine to call when converting event */
    255 {
    256 	register WireToEventType oldproc;
    257 	if (event_number < 0 ||
    258 	    event_number > LastExtensionEvent) {
    259 	    fprintf(stderr, "Xlib: ignoring invalid extension event %d\n",
    260 		    event_number);
    261 	    return (WireToEventType)_XUnknownWireEvent;
    262 	}
    263 	if (proc == NULL) proc = (WireToEventType)_XUnknownWireEvent;
    264 	LockDisplay (dpy);
    265 	oldproc = dpy->event_vec[event_number];
    266 	dpy->event_vec[event_number] = proc;
    267 	UnlockDisplay (dpy);
    268 	return (WireToEventType)oldproc;
    269 }
    270 
    271 typedef Bool (*WireToEventCookieType) (
    272     Display*	/* display */,
    273     XGenericEventCookie*	/* re */,
    274     xEvent*	/* event */
    275 );
    276 
    277 WireToEventCookieType XESetWireToEventCookie(
    278     Display *dpy,       /* display */
    279     int extension,      /* extension major opcode */
    280     WireToEventCookieType proc /* routine to call for generic events */
    281     )
    282 {
    283 	WireToEventCookieType oldproc;
    284 	if (extension < FirstExtensionRequest ||
    285 	    extension > LastExtensionRequest) {
    286 	    fprintf(stderr, "Xlib: ignoring invalid extension opcode %d\n",
    287 		    extension);
    288 	    return (WireToEventCookieType)_XUnknownWireEventCookie;
    289 	}
    290 	if (proc == NULL) proc = (WireToEventCookieType)_XUnknownWireEventCookie;
    291 	LockDisplay (dpy);
    292 	oldproc = dpy->generic_event_vec[extension & 0x7F];
    293 	dpy->generic_event_vec[extension & 0x7F] = proc;
    294 	UnlockDisplay (dpy);
    295 	return (WireToEventCookieType)oldproc;
    296 }
    297 
    298 typedef Bool (*CopyEventCookieType) (
    299     Display*	/* display */,
    300     XGenericEventCookie*	/* in */,
    301     XGenericEventCookie*	/* out */
    302 );
    303 
    304 CopyEventCookieType XESetCopyEventCookie(
    305     Display *dpy,       /* display */
    306     int extension,      /* extension major opcode */
    307     CopyEventCookieType proc /* routine to copy generic events */
    308     )
    309 {
    310 	CopyEventCookieType oldproc;
    311 	if (extension < FirstExtensionRequest ||
    312 	    extension > LastExtensionRequest) {
    313 	    fprintf(stderr, "Xlib: ignoring invalid extension opcode %d\n",
    314 		    extension);
    315 	    return (CopyEventCookieType)_XUnknownCopyEventCookie;
    316 	}
    317 	if (proc == NULL) proc = (CopyEventCookieType)_XUnknownCopyEventCookie;
    318 	LockDisplay (dpy);
    319 	oldproc = dpy->generic_event_copy_vec[extension & 0x7F];
    320 	dpy->generic_event_copy_vec[extension & 0x7F] = proc;
    321 	UnlockDisplay (dpy);
    322 	return (CopyEventCookieType)oldproc;
    323 }
    324 
    325 
    326 typedef Status (*EventToWireType) (
    327     Display*	/* display */,
    328     XEvent*	/* re */,
    329     xEvent*	/* event */
    330 );
    331 
    332 EventToWireType XESetEventToWire(
    333 	Display *dpy,		/* display */
    334 	int event_number,	/* event routine to replace */
    335 	EventToWireType proc)	/* routine to call when converting event */
    336 {
    337 	register EventToWireType oldproc;
    338 	if (event_number < 0 ||
    339 	    event_number > LastExtensionEvent) {
    340 	    fprintf(stderr, "Xlib: ignoring invalid extension event %d\n",
    341 		    event_number);
    342 	    return (EventToWireType)_XUnknownNativeEvent;
    343 	}
    344 	if (proc == NULL) proc = (EventToWireType) _XUnknownNativeEvent;
    345 	LockDisplay (dpy);
    346 	oldproc = dpy->wire_vec[event_number];
    347 	dpy->wire_vec[event_number] = proc;
    348 	UnlockDisplay(dpy);
    349 	return (EventToWireType)oldproc;
    350 }
    351 
    352 typedef Bool (*WireToErrorType) (
    353     Display*	/* display */,
    354     XErrorEvent* /* he */,
    355     xError*	/* we */
    356 );
    357 
    358 WireToErrorType XESetWireToError(
    359 	Display *dpy,		/* display */
    360 	int error_number,	/* error routine to replace */
    361 	WireToErrorType proc)	/* routine to call when converting error */
    362 {
    363 	register WireToErrorType oldproc = NULL;
    364 	if (error_number < 0 ||
    365 	    error_number > LastExtensionError) {
    366 	   fprintf(stderr, "Xlib: ignoring invalid extension error %d\n",
    367 		    error_number);
    368 	   return (WireToErrorType)_XDefaultWireError;
    369 	}
    370 	if (proc == NULL) proc = (WireToErrorType)_XDefaultWireError;
    371 	LockDisplay (dpy);
    372 	if (!dpy->error_vec) {
    373 	    int i;
    374 	    dpy->error_vec = Xmalloc(256 * sizeof(oldproc));
    375 	    for (i = 1; i < 256; i++)
    376 		dpy->error_vec[i] = _XDefaultWireError;
    377 	}
    378 	if (dpy->error_vec) {
    379 	    oldproc = dpy->error_vec[error_number];
    380 	    dpy->error_vec[error_number] = proc;
    381 	}
    382 	UnlockDisplay (dpy);
    383 	return (WireToErrorType)oldproc;
    384 }
    385 
    386 ErrorType XESetError(
    387 	Display *dpy,		/* display */
    388 	int extension,		/* extension number */
    389 	ErrorType proc)		/* routine to call when X error happens */
    390 {
    391 	register _XExtension *e;	/* for lookup of extension */
    392 	register ErrorType oldproc;
    393 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    394 	LockDisplay(dpy);
    395 	oldproc = e->error;
    396 	e->error = proc;
    397 	UnlockDisplay(dpy);
    398 	return (ErrorType)oldproc;
    399 }
    400 
    401 ErrorStringType XESetErrorString(
    402 	Display *dpy,		/* display */
    403 	int extension,		/* extension number */
    404 	ErrorStringType proc)	/* routine to call when I/O error happens */
    405 {
    406 	register _XExtension *e;	/* for lookup of extension */
    407 	register ErrorStringType oldproc;
    408 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    409 	LockDisplay(dpy);
    410 	oldproc = e->error_string;
    411 	e->error_string = proc;
    412 	UnlockDisplay(dpy);
    413 	return (ErrorStringType)oldproc;
    414 }
    415 
    416 PrintErrorType XESetPrintErrorValues(
    417 	Display *dpy,		/* display */
    418 	int extension,		/* extension number */
    419 	PrintErrorType proc)	/* routine to call to print */
    420 {
    421 	register _XExtension *e;	/* for lookup of extension */
    422 	register PrintErrorType oldproc;
    423 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    424 	LockDisplay(dpy);
    425 	oldproc = e->error_values;
    426 	e->error_values = proc;
    427 	UnlockDisplay(dpy);
    428 	return (PrintErrorType)oldproc;
    429 }
    430 
    431 BeforeFlushType XESetBeforeFlush(
    432 	Display *dpy,		/* display */
    433 	int extension,		/* extension number */
    434 	BeforeFlushType proc)	/* routine to call on flush */
    435 {
    436 	register _XExtension *e;	/* for lookup of extension */
    437 	register BeforeFlushType oldproc;
    438 	register _XExtension *ext;
    439 	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
    440 	LockDisplay(dpy);
    441 	oldproc = e->before_flush;
    442 	e->before_flush = proc;
    443 	for (ext = dpy->flushes; ext && ext != e; ext = ext->next)
    444 	    ;
    445 	if (!ext) {
    446 	    e->next_flush = dpy->flushes;
    447 	    dpy->flushes = e;
    448 	}
    449 	UnlockDisplay(dpy);
    450 	return (BeforeFlushType)oldproc;
    451 }
    452