Back to index

im-sdk  12.3.91
xaux_ext_hdlrmng.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2003 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 
00043 #pragma ident "$Id$"
00044 
00045 #include      <stdio.h>
00046 #include      <stdlib.h>
00047 #include      <strings.h>
00048 #include      <X11/Xlib.h>
00049 #include      "xaux_ext_common.h"
00050 
00051 typedef struct xaux_ext_hdlrmng_ent_struct {
00052        struct xaux_ext_hdlrmng_ent_struct *prev;
00053        struct xaux_ext_hdlrmng_ent_struct *next;
00054        xaux_ext_cb_evhandler_t     handler;
00055        void                 *sodata;
00056 } xaux_ext_hdlrmng_ent_t;
00057 
00058 #define       MAXMASK              32
00059 
00060 typedef struct xaux_ext_hdlrmng_db_struct {
00061        xaux_ext_hdlrmng_ent_t      maskable[MAXMASK];
00062        xaux_ext_hdlrmng_ent_t      nonmaskable;
00063        long                 comb_mask;
00064        Bool                 comb_nonmaskable;
00065 } xaux_ext_hdlrmng_db_t;
00066 
00067 /*
00068  * mask2index
00069  *     e.g. PropertyChangeMask is defined as (1L<<22)
00070  *     mask2index(PropertChangeMask) returns 22.
00071  *     When bit-or of multiple masks is given, result is undefined.
00072  */
00073 static int
00074 mask2index(long mask)
00075 {
00076        int    i;
00077 
00078        for (i = 0; i < MAXMASK; i++) {
00079               if ((mask & 1L) != 0) {
00080                      return (i);
00081               } else {
00082                      mask >>= 1;
00083               }
00084        }
00085        return (-1);
00086 }
00087 
00088 /*
00089  * index2mask
00090  *     e.g. PropertyChangeMask is defined as (1L<<22)
00091  *     index2mask(22) returns PropertyChangeMask
00092  */
00093 static long
00094 index2mask(int idx)
00095 {
00096        return (1L << idx);
00097 }
00098 
00099 /*
00100  * type2mask - event type to mask
00101  */
00102 static long
00103 type2mask(
00104        int    type,
00105        Bool   *nonmaskable_return)
00106 {
00107        long   mask;
00108 
00109        switch (type) {
00110        case DestroyNotify:
00111               mask = StructureNotifyMask;
00112               *nonmaskable_return = False;
00113               break;
00114        case PropertyNotify:
00115               mask = PropertyChangeMask;
00116               *nonmaskable_return = False;
00117               break;
00118        case SelectionClear:
00119        case SelectionNotify:
00120        case SelectionRequest:
00121        case ClientMessage:
00122               mask = NoEventMask;
00123               *nonmaskable_return = True;
00124               break;
00125        default:
00126               /* event type not interested by xaux_ext */
00127               mask = NoEventMask;
00128               *nonmaskable_return = False;
00129               break;
00130        }
00131 
00132        return (mask);
00133 }
00134 
00135 static Bool
00136 add_to_list(
00137        xaux_ext_hdlrmng_ent_t      *list,
00138        xaux_ext_cb_evhandler_t     handler,
00139        void                 *sodata)
00140 {
00141        xaux_ext_hdlrmng_ent_t      *le = list, *le_prev = NULL;
00142 
00143        while (le != NULL) {
00144               if ((le->handler == handler) && (le->sodata == sodata)) {
00145                      /* already registered */
00146                      return (True);
00147               } 
00148               le_prev = le;
00149               le = le->next;
00150        }
00151 
00152        if ((le = le_prev->next = (xaux_ext_hdlrmng_ent_t *)malloc(
00153                      sizeof (xaux_ext_hdlrmng_ent_t))) == NULL) {
00154               return (False);
00155        }
00156 
00157        le->prev = le_prev;
00158        le->next = NULL;
00159        le->handler = handler;
00160        le->sodata = sodata;
00161 
00162        return (True);
00163 }
00164 
00165 static Bool
00166 rm_from_list(
00167        xaux_ext_hdlrmng_ent_t      *list,
00168        xaux_ext_cb_evhandler_t     handler,
00169        void                 *sodata)
00170 {
00171        xaux_ext_hdlrmng_ent_t      *le = list, *le_prev;
00172        Bool                 rv = False;
00173 
00174        while (le != NULL) {
00175               if ((le->handler == handler) && (le->sodata == sodata)) {
00176                      /* found */
00177                      le->prev->next = le->next;
00178                      if (le->next != NULL) {
00179                             le->next->prev = le->prev;
00180                      }
00181                      free(le);
00182                      return (True);
00183               } 
00184               le = le->next;
00185        }
00186 
00187        /* not found */
00188        return (False);
00189 }
00190 
00191 static void
00192 free_list(
00193        xaux_ext_hdlrmng_ent_t      *list)
00194 {
00195        xaux_ext_hdlrmng_ent_t      *le = list, *le_next;
00196 
00197        while (le) {
00198               le_next = le->next;
00199               free(le);
00200               le = le->next;
00201        }
00202        return;
00203 }
00204 
00205 static xaux_ext_hdlrmng_handle_t
00206 xaux_ext_hdlrmng_open(void)
00207 {
00208        xaux_ext_hdlrmng_db_t       *db;
00209        int    i;
00210 
00211        if ((db = (xaux_ext_hdlrmng_db_t *)malloc(
00212                      sizeof (xaux_ext_hdlrmng_db_t))) == NULL) {
00213               return (NULL);
00214        }
00215 
00216        bzero(db, sizeof (xaux_ext_hdlrmng_db_t));
00217 
00218        for (i = 0; i < MAXMASK; i++) {
00219               db->maskable[i].prev = NULL;
00220               db->maskable[i].next = NULL;
00221               db->maskable[i].handler = NULL;
00222               db->maskable[i].sodata = NULL;
00223        }
00224 
00225        db->nonmaskable.prev = NULL;
00226        db->nonmaskable.next = NULL;
00227        db->nonmaskable.handler = NULL;
00228        db->nonmaskable.sodata = NULL;
00229 
00230        db->comb_mask = 0L;
00231        db->comb_nonmaskable = False;
00232 
00233        return ((xaux_ext_hdlrmng_handle_t)db);
00234 }
00235 
00236 static Bool
00237 xaux_ext_hdlrmng_add(
00238        xaux_ext_hdlrmng_handle_t   handle,
00239        xaux_ext_cb_evhandler_t     handler,
00240        void                 *sodata,
00241        long                 mask,
00242        Bool                 nonmaskable,
00243        long                 *mask_add_return,
00244        Bool                 *nonmaskable_add_return,
00245        long                 *mask_new_return,
00246        Bool                 *nonmaskable_new_return)
00247 {
00248        xaux_ext_hdlrmng_db_t       *db = (xaux_ext_hdlrmng_db_t *)handle;
00249        int                  m;
00250        Bool                 rv = False;
00251        long                 mask_new;
00252        Bool                 nonmaskable_new;
00253 
00254 #if defined(DEBUG_XAUX)
00255        fprintf(stderr, "(--) hdlrmng_add: handle=%p handler=%p sodata=%p "
00256               "mask=0x%x nonmaskable=%d %p %p %p %p\n",
00257               handle, handler, sodata, mask, nonmaskable,
00258               mask_add_return, nonmaskable_add_return,
00259               mask_new_return, nonmaskable_new_return);
00260 #endif /* defined(DEBUG_XAUX) */
00261 
00262        if (handler == NULL) {
00263               return (False);
00264        }
00265 
00266        *mask_add_return = NoEventMask;
00267        *nonmaskable_add_return = False;
00268        mask_new = db->comb_mask;
00269        nonmaskable_new = db->comb_nonmaskable;
00270 
00271        for (m = 0; m < MAXMASK; m++) {
00272               if ((mask & (1L << m)) == 0L) {
00273                      continue;
00274               }
00275               if (add_to_list(&(db->maskable[m]), handler, sodata) == True) {
00276                      *mask_add_return |= (1L << m);
00277                      mask_new |= (1L << m);
00278               }
00279        }
00280 
00281        if (nonmaskable == True) {
00282               if (add_to_list(&(db->nonmaskable), handler, sodata) == True) {
00283                      *nonmaskable_add_return = True;
00284                      nonmaskable_new = True;
00285               }
00286        }
00287 
00288        if ((*mask_add_return != NoEventMask) ||
00289               (*nonmaskable_add_return == True)) {
00290               /* mask and/or nonmaskable has been changed */
00291               rv = True;
00292        }
00293 
00294        db->comb_mask = mask_new;
00295        db->comb_nonmaskable = nonmaskable_new;
00296 
00297        if (mask_new_return != NULL) {
00298               *mask_new_return = mask_new;
00299        }
00300        if (nonmaskable_new_return != NULL) {
00301               *nonmaskable_new_return = nonmaskable_new;
00302        }
00303 
00304        return (rv);
00305 }
00306 
00307 static Bool
00308 xaux_ext_hdlrmng_remove(
00309        xaux_ext_hdlrmng_handle_t   handle,
00310        xaux_ext_cb_evhandler_t     handler,
00311        void                 *sodata,
00312        long                 mask,
00313        Bool                 nonmaskable,
00314        long                 *mask_rm_return,
00315        Bool                 *nonmaskable_rm_return,
00316        long                 *mask_new_return,
00317        Bool                 *nonmaskable_new_return)
00318 {
00319        xaux_ext_hdlrmng_db_t       *db = (xaux_ext_hdlrmng_db_t *)handle;
00320        int                  m;
00321        Bool                 rv = False;
00322        long                 mask_new;
00323        Bool                 nonmaskable_new;
00324 
00325        if (handler == NULL) {
00326               return (False);
00327        }
00328 
00329        *mask_rm_return = NoEventMask;
00330        *nonmaskable_rm_return = False;
00331        mask_new = db->comb_mask;
00332        nonmaskable_new = db->comb_nonmaskable;
00333 
00334        for (m = 0; m < MAXMASK; m++) {
00335               if ((mask & (1L << m)) == 0L) {
00336                      continue;
00337               }
00338               if (rm_from_list(&(db->maskable[m]), handler, sodata) == True) {
00339                      if (db->maskable[m].next == NULL) {
00340                             *mask_rm_return |= (1L << m);
00341                             mask_new &= ~(1L << m);
00342                      }
00343               }
00344        }
00345 
00346        if (nonmaskable == True) {
00347               if (rm_from_list(&(db->nonmaskable), handler, sodata) == True) {
00348                      if (db->nonmaskable.next == NULL) {
00349                             *nonmaskable_rm_return = True;
00350                             nonmaskable_new = False;
00351                      }
00352               }
00353        }
00354 
00355        if ((*mask_rm_return != NoEventMask) ||
00356               (*nonmaskable_rm_return == True)) {
00357               /* mask and/or nonmaskable has been changed */
00358               rv = True;
00359        }
00360 
00361        db->comb_mask = *mask_new_return;
00362        db->comb_nonmaskable = *nonmaskable_new_return;
00363 
00364        if (mask_new_return != NULL) {
00365               *mask_new_return = mask_new;
00366        }
00367        if (nonmaskable_new_return != NULL) {
00368               *nonmaskable_new_return = nonmaskable_new;
00369        }
00370 
00371        return (rv);
00372 }
00373 
00374 static Bool
00375 xaux_ext_hdlrmng_filter(
00376        xaux_ext_hdlrmng_handle_t   handle,
00377        xaux_ext_handle_t    ext_handle,
00378        XEvent               *ev)
00379 {
00380        xaux_ext_hdlrmng_db_t       *db = (xaux_ext_hdlrmng_db_t *)handle;
00381        xaux_ext_hdlrmng_ent_t      *le, *list;
00382        Bool   nonmaskable = False;
00383        long   mask;
00384 
00385 #if defined(DEBUG_XAUX_DETAIL)
00386        fprintf(stderr, "(--) filter called ev->type = %d\n", ev->type);
00387 #endif /* defined(DEBUG_XAUX_DETAIL) */
00388 
00389        mask = type2mask(ev->type, &nonmaskable);
00390 
00391        if (mask != NoEventMask) {
00392               le = db->maskable[mask2index(mask)].next;
00393               while (le != NULL) {
00394                      if ((*le->handler)(ext_handle,
00395                                    (Window)None, ev, le->sodata) == True) {
00396                             return (True);
00397                      }
00398                      le = le->next;
00399               }
00400        }
00401 
00402        if (nonmaskable == True) {
00403               le = db->nonmaskable.next;
00404               while (le != NULL) {
00405                      if ((*le->handler)(ext_handle,
00406                                    (Window)None, ev, le->sodata) == True) {
00407                             return (True);
00408                      }
00409                      le = le->next;
00410               }
00411        }
00412 
00413        return (False);
00414 }
00415 
00416 static void
00417 xaux_ext_hdlrmng_close(xaux_ext_hdlrmng_handle_t handle)
00418 {
00419        xaux_ext_hdlrmng_db_t       *db = (xaux_ext_hdlrmng_db_t *)handle;
00420        int    i;
00421 
00422        if (db == NULL) {
00423               return;
00424        }
00425 
00426        for (i = 0; i < MAXMASK; i++) {
00427               free_list(db->maskable[i].next);
00428        }
00429        free_list(db->nonmaskable.next);
00430        free(db);
00431        return;
00432 }
00433 
00434 
00435 xaux_ext_hdlrmng_methods_t xaux_ext_hdlrmng_methods = {
00436        xaux_ext_hdlrmng_open,
00437        xaux_ext_hdlrmng_add,
00438        xaux_ext_hdlrmng_remove,
00439        xaux_ext_hdlrmng_filter,
00440        xaux_ext_hdlrmng_close
00441 };