root/oldXMenu/Internal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _XMWinQueInit
  2. _XMWinQueAddPane
  3. _XMWinQueAddSelection
  4. _XMWinQueFlush
  5. _XMGetPanePtr
  6. _XMGetSelectionPtr
  7. _XMRecomputeGlobals
  8. _XMRecomputePane
  9. _XMRecomputeSelection
  10. _XMTransToOrigin
  11. _XMRefreshPane
  12. _XMRefreshSelection

     1 /* Copyright    Massachusetts Institute of Technology    1985   */
     2 
     3 /*
     4 
     5 Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
     6 
     7 Permission to use, copy, modify, and distribute this
     8 software and its documentation for any purpose and without
     9 fee is hereby granted, provided that the above copyright
    10 notice appear in all copies and that both that copyright
    11 notice and this permission notice appear in supporting
    12 documentation, and that the name of M.I.T. not be used in
    13 advertising or publicity pertaining to distribution of the
    14 software without specific, written prior permission.
    15 M.I.T. makes no representations about the suitability of
    16 this software for any purpose.  It is provided "as is"
    17 without express or implied warranty.
    18 
    19 */
    20 
    21 
    22 
    23 /*
    24 Copyright (C) 1993, 1996, 2001-2023 Free Software Foundation, Inc.
    25 
    26 This program is free software: you can redistribute it and/or modify
    27 it under the terms of the GNU General Public License as published by
    28 the Free Software Foundation, either version 3 of the License, or (at
    29 your option) any later version.
    30 
    31 This program is distributed in the hope that it will be useful,
    32 but WITHOUT ANY WARRANTY; without even the implied warranty of
    33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    34 GNU General Public License for more details.
    35 
    36 You should have received a copy of the GNU General Public License
    37 along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
    38 
    39 
    40 /*
    41  * XMenu:       MIT Project Athena, X Window system menu package
    42  *
    43  *      XMenuInternal.c - XMenu internal (not user visible) routines.
    44  *
    45  *      Author:         Tony Della Fera, DEC
    46  *                      November, 1985
    47  *
    48  */
    49 
    50 #include "XMenuInt.h"
    51 
    52 /*
    53  * Internal Window creation queue sizes.
    54  */
    55 #define S_QUE_SIZE      300
    56 #define P_QUE_SIZE      20
    57 
    58 
    59 /*
    60  * XMWinQue - Internal window creation queue datatype.
    61  */
    62 typedef struct _xmwinquedef {
    63     int sq_size;
    64     XMSelect *sq[S_QUE_SIZE];
    65     XMSelect **sq_ptr;
    66     int pq_size;
    67     XMPane *pq[P_QUE_SIZE];
    68     XMPane **pq_ptr;
    69 } XMWinQue;
    70 
    71 /*
    72  * _XMWinQue - Internal static window creation queue.
    73  */
    74 static Bool _XMWinQueIsInit = False;
    75 static XMWinQue _XMWinQue;
    76 
    77 /*
    78  * _XMErrorCode - Global XMenu error code.
    79  */
    80 int _XMErrorCode = XME_NO_ERROR;
    81 /*
    82  * _XMErrorList - Global XMenu error code description strings.
    83  */
    84 char const *const
    85 _XMErrorList[XME_CODE_COUNT] = {
    86     "No error",                         /* XME_NO_ERROR */
    87     "Menu not initialized",             /* XME_NOT_INIT */
    88     "Argument out of bounds",           /* XME_ARG_BOUNDS */
    89     "Pane not found",                   /* XME_P_NOT_FOUND */
    90     "Selection not found",              /* XME_S_NOT_FOUND */
    91     "Invalid menu style parameter",     /* XME_STYLE_PARAM */
    92     "Unable to grab mouse",             /* XME_GRAB_MOUSE */
    93     "Unable to interpret locator",      /* XME_INTERP_LOC */
    94     "Unable to calloc memory",          /* XME_CALLOC */
    95     "Unable to create XAssocTable",     /* XME_CREATE_ASSOC */
    96     "Unable to store bitmap",           /* XME_STORE_BITMAP */
    97     "Unable to make tile pixmaps",      /* XME_MAKE_TILES */
    98     "Unable to make pixmap",            /* XME_MAKE_PIXMAP */
    99     "Unable to create cursor",          /* XME_CREATE_CURSOR */
   100     "Unable to open font",              /* XME_OPEN_FONT */
   101     "Unable to create windows",         /* XME_CREATE_WINDOW */
   102     "Unable to create transparencies",  /* XME_CREATE_TRANSP */
   103 };
   104 
   105 /*
   106  * _XMEventHandler - Internal event handler variable.
   107  */
   108 int (*_XMEventHandler)(XEvent*) = NULL;
   109 
   110 
   111 
   112 /*
   113  * _XMWinQueInit - Internal routine to initialize the window
   114  *                 queue.
   115  */
   116 void
   117 _XMWinQueInit(void)
   118 {
   119     /*
   120      * If the queue is not initialized initialize it.
   121      */
   122     if (!_XMWinQueIsInit) {
   123         /*
   124          * Blank the queue structure.
   125          */
   126         register int i;
   127 
   128         for (i = 0; i < S_QUE_SIZE; i++)
   129           _XMWinQue.sq[i] = 0;
   130 
   131         for (i = 0; i < P_QUE_SIZE; i++)
   132           _XMWinQue.pq[i] = 0;
   133 
   134         _XMWinQue.sq_size = _XMWinQue.pq_size = 0;
   135 
   136         /*
   137          * Initialize the next free location pointers.
   138          */
   139         _XMWinQue.sq_ptr = _XMWinQue.sq;
   140         _XMWinQue.pq_ptr = _XMWinQue.pq;
   141     }
   142 }
   143 
   144 
   145 
   146 /*
   147  * _XMWinQueAddPane - Internal routine to add a pane to the pane
   148  *                    window queue.
   149  */
   150 int
   151 _XMWinQueAddPane(register Display *display, register XMenu *menu, register XMPane *p_ptr)
   152 
   153                                 /* Menu being manipulated. */
   154                                 /* XMPane being queued. */
   155 {
   156     /*
   157      * If the queue is currently full then flush it.
   158      */
   159     if (_XMWinQue.pq_size == P_QUE_SIZE) {
   160         if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
   161     }
   162 
   163     /*
   164      * Insert the new XMPane pointer and increment the queue pointer
   165      * and the queue size.
   166      */
   167     *_XMWinQue.pq_ptr = p_ptr;
   168     _XMWinQue.pq_ptr++;
   169     _XMWinQue.pq_size++;
   170 
   171     /*
   172      * All went well, return successfully.
   173      */
   174     _XMErrorCode = XME_NO_ERROR;
   175     return(_SUCCESS);
   176 }
   177 
   178 
   179 
   180 /*
   181  * _XMWinQueAddSelection - Internal routine to add a selection to
   182  *                         the selection window queue.
   183  */
   184 int
   185 _XMWinQueAddSelection(register Display *display, register XMenu *menu, register XMSelect *s_ptr)
   186 
   187                                 /* Menu being manipulated. */
   188                                 /* XMSelection being queued. */
   189 {
   190     /*
   191      * If this entry will overflow the queue then flush it.
   192      */
   193     if (_XMWinQue.sq_size == S_QUE_SIZE) {
   194         if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
   195     }
   196 
   197     /*
   198      * Insert the new XMSelect pointer and increment the queue pointer
   199      * and the queue size.
   200      */
   201     *_XMWinQue.sq_ptr = s_ptr;
   202     _XMWinQue.sq_ptr++;
   203     _XMWinQue.sq_size++;
   204 
   205     /*
   206      * All went well, return successfully.
   207      */
   208     _XMErrorCode = XME_NO_ERROR;
   209     return(_SUCCESS);
   210 }
   211 
   212 
   213 
   214 /*
   215  * _XMWinQueFlush - Internal routine to flush the pane and
   216  *                  selection window queues.
   217  */
   218 int
   219 _XMWinQueFlush(register Display *display, register XMenu *menu, register XMPane *pane, XMSelect *sel)
   220 
   221                                         /* Menu being manipulated. */
   222                                         /* Current pane. */
   223 {
   224     register int pq_index;              /* Pane queue index. */
   225     register int sq_index;              /* Selection queue index. */
   226     register XMPane *p_ptr;             /* XMPane pointer. */
   227     register XMSelect *s_ptr;           /* XMSelect pointer. */
   228     unsigned long valuemask;            /* Which attributes to set. */
   229     XSetWindowAttributes attributes_buf; /* Attributes to be set. */
   230     XSetWindowAttributes *attributes = &attributes_buf;
   231 
   232     /*
   233      * If the pane window queue is not empty...
   234      */
   235 
   236     if (_XMWinQue.pq_size > 0) {
   237         /*
   238          * set up attributes for pane window to be created.
   239          */
   240         valuemask = (CWBackPixmap | CWBorderPixel | CWOverrideRedirect);
   241         attributes->border_pixel = menu->p_bdr_color;
   242         attributes->background_pixmap = menu->inact_pixmap;
   243         attributes->override_redirect = True;
   244 
   245         /*
   246          * Create all the pending panes in order, so that the
   247          * current pane will be on top, with the others
   248          * stacked appropriately under it.
   249          */
   250         for (pq_index = _XMWinQue.pq_size - 1;
   251              pq_index >= 0;
   252              pq_index--)
   253           {
   254               p_ptr = _XMWinQue.pq[pq_index];  /* Retrieve next pane. */
   255               if (p_ptr == pane) break;
   256               p_ptr->window = XCreateWindow(display,
   257                                             menu->parent,
   258                                             p_ptr->window_x,
   259                                             p_ptr->window_y,
   260                                             p_ptr->window_w,
   261                                             p_ptr->window_h,
   262                                             menu->p_bdr_width,
   263                                             CopyFromParent,
   264                                             InputOutput,
   265                                             CopyFromParent,
   266                                             valuemask,
   267                                             attributes);
   268               XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
   269               XSelectInput(display, p_ptr->window, menu->p_events);
   270           }
   271         for (pq_index = 0;
   272              pq_index < _XMWinQue.pq_size;
   273              pq_index++)
   274           {
   275               p_ptr = _XMWinQue.pq[pq_index];   /* Retrieve next pane. */
   276               p_ptr->window = XCreateWindow(display,
   277                                             menu->parent,
   278                                             p_ptr->window_x,
   279                                             p_ptr->window_y,
   280                                             p_ptr->window_w,
   281                                             p_ptr->window_h,
   282                                             menu->p_bdr_width,
   283                                             CopyFromParent,
   284                                             InputOutput,
   285                                             CopyFromParent,
   286                                             valuemask,
   287                                             attributes);
   288               XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
   289               XSelectInput(display, p_ptr->window, menu->p_events);
   290               if (p_ptr == pane) break;
   291         }
   292 
   293         /*
   294          * Reset the pane queue pointer and size.
   295          */
   296         _XMWinQue.pq_size = 0;
   297         _XMWinQue.pq_ptr = _XMWinQue.pq;
   298     }
   299 
   300     /*
   301      * If the selection window queue is not empty...
   302      */
   303 
   304     if (_XMWinQue.sq_size > 0) {
   305 
   306         for (sq_index = 0; sq_index < _XMWinQue.sq_size; sq_index++) {
   307             /*
   308              * Retrieve the XMSelect pointer.
   309              */
   310             s_ptr = _XMWinQue.sq[sq_index];
   311             s_ptr->window = XCreateWindow(display,
   312                                    s_ptr->parent_p->window,
   313                                    s_ptr->window_x,
   314                                    s_ptr->window_y,
   315                                    s_ptr->window_w,
   316                                    s_ptr->window_h,
   317                                    0,                /* border width*/
   318                                    CopyFromParent,
   319                                    InputOnly,
   320                                    CopyFromParent,
   321                                    0,
   322                                    attributes);
   323 
   324             /*
   325              * Insert the new window id and its
   326              * associated XMSelect structure into the
   327              * association table.
   328              */
   329             XMakeAssoc(display, menu->assoc_tab, s_ptr->window, s_ptr);
   330             XSelectInput(display, s_ptr->window, menu->s_events);
   331         }
   332 
   333         /*
   334          * Reset the selection queue pointer and size.
   335          */
   336         _XMWinQue.sq_size = 0;
   337         _XMWinQue.sq_ptr = _XMWinQue.sq;
   338     }
   339 
   340     /*
   341      * Flush X's internal queues.
   342      */
   343     XFlush(display);
   344 
   345     /*
   346      * All went well, return successfully.
   347      */
   348     _XMErrorCode = XME_NO_ERROR;
   349     return(_SUCCESS);
   350 }
   351 
   352 
   353 
   354 /*
   355  * _XMGetPanePtr -      Given a menu pointer and a pane index number, return
   356  *                      a pane pointer that points to the indexed pane.
   357  */
   358 XMPane *
   359 _XMGetPanePtr(register XMenu *menu, register int p_num)
   360                                 /* Menu to find the pane in. */
   361                                 /* Index number of pane to find. */
   362 {
   363     register XMPane *p_ptr;     /* Pane pointer to be returned. */
   364     register int i;             /* Loop counter. */
   365 
   366     /*
   367      * Is the pane number out of range?
   368      */
   369     if ((p_num < 0) || (p_num > (menu->p_count - 1))) {
   370         _XMErrorCode = XME_P_NOT_FOUND;
   371         return(NULL);
   372     }
   373 
   374     /*
   375      * Find the right pane.
   376      */
   377     p_ptr = menu->p_list->next;
   378     for (i = 0; i < p_num; i++) p_ptr = p_ptr->next;
   379 
   380     /*
   381      * Return successfully.
   382      */
   383     _XMErrorCode = XME_NO_ERROR;
   384     return(p_ptr);
   385 }
   386 
   387 
   388 
   389 /*
   390  * _XMGetSelectionPtr - Given pane pointer and a selection index number,
   391  *                      return a selection pointer that points to the
   392  *                      indexed selection.
   393  */
   394 XMSelect *
   395 _XMGetSelectionPtr(register XMPane *p_ptr, register int s_num)
   396                                 /* Pane to find the selection in. */
   397                                 /* Index number of the selection to find. */
   398 {
   399     register XMSelect *s_ptr;   /* Selection pointer to be returned. */
   400     register int i;             /* Loop counter. */
   401 
   402     /*
   403      * Is the selection number out of range?
   404      */
   405     if ((s_num < 0) || (s_num > (p_ptr->s_count - 1))) {
   406         _XMErrorCode = XME_S_NOT_FOUND;
   407         return(NULL);
   408     }
   409 
   410     /*
   411      * Find the right selection.
   412      */
   413     s_ptr = p_ptr->s_list->next;
   414     for (i = 0; i < s_num; i++) s_ptr = s_ptr->next;
   415 
   416     /*
   417      * Return successfully.
   418      */
   419     _XMErrorCode = XME_NO_ERROR;
   420     return(s_ptr);
   421 }
   422 
   423 
   424 
   425 /*
   426  * _XMRecomputeGlobals - Internal subroutine to recompute menu wide
   427  *                       global values.
   428  */
   429 void
   430 _XMRecomputeGlobals(register Display *display, register XMenu *menu)
   431                                /*X11 display variable. */
   432                                 /* Menu object to compute from. */
   433 {
   434     register XMPane *p_ptr;     /* Pane pointer. */
   435     register XMSelect *s_ptr;   /* Selection pointer. */
   436 
   437     register int max_p_label = 0;       /* Maximum pane label width. */
   438     register int max_s_label = 0;       /* Maximum selection label width. */
   439     register int s_count = 0;           /* Maximum selection count. */
   440 
   441     int p_s_pad;                /* Pane <-> selection padding. */
   442     int p_s_diff;               /* Pane <-> selection separation. */
   443 
   444     int p_height;               /* Pane window height. */
   445     int p_width;                /* Pane window width. */
   446     int s_width;                /* Selection window width. */
   447 
   448     int screen;                 /* DefaultScreen holder. */
   449 
   450     /*
   451      * For each pane...
   452      */
   453     for (
   454         p_ptr = menu->p_list->next;
   455         p_ptr != menu->p_list;
   456         p_ptr = p_ptr->next
   457     ){
   458 
   459         /*
   460          * Recompute maximum pane label width.
   461          */
   462         max_p_label = max(max_p_label, p_ptr->label_width);
   463 
   464         /*
   465          * Recompute maximum selection count.
   466          */
   467         s_count = max(s_count, p_ptr->s_count);
   468 
   469         /*
   470          * For each selection in the current pane...
   471          */
   472         for (
   473             s_ptr = p_ptr->s_list->next;
   474             s_ptr != p_ptr->s_list;
   475             s_ptr = s_ptr->next
   476         ){
   477 
   478             /*
   479              * Recompute maximum selection label width.
   480              */
   481             max_s_label = max(max_s_label, s_ptr->label_width);
   482         }
   483     }
   484 
   485     /*
   486      * Recompute pane height.
   487      */
   488     p_height = (menu->flag_height << 1) + (menu->s_y_off * s_count);
   489 
   490     /*
   491      * Recompute horizontal padding between the pane window and the
   492      * selection windows.
   493      */
   494     p_s_pad = menu->p_x_off << 1;
   495 
   496     /*
   497      * Recompute pane and selection window widths.
   498      * This is done by first computing the window sizes from the maximum
   499      * label widths.  If the spacing between the selection window and the
   500      * containing pane window is less than the pane selection padding value
   501      * (twice the pane X offset) then change the size of the pane to be
   502      * the size of the selection window plus the padding.  If, however the
   503      * spacing between the selection window and the containing pane window
   504      * is more than the pane selection padding value increase the size of
   505      * the selection to its maximum possible value (the pane width minus
   506      * the pane selection padding value).
   507      */
   508     p_width = max_p_label + p_s_pad;
   509     s_width = max_s_label + (menu->s_fnt_pad << 1) + (menu->s_bdr_width << 1);
   510     p_s_diff = p_width - s_width;
   511     if (p_s_diff < p_s_pad) {
   512         p_width = s_width + p_s_pad;
   513     }
   514     else if (p_s_diff > p_s_pad) {
   515         s_width = p_width - p_s_pad;
   516     }
   517 
   518     /*
   519      * Reset menu wide global values.
   520      */
   521     menu->s_count = s_count;
   522     menu->p_height = p_height;
   523     menu->p_width = p_width;
   524     menu->s_width = s_width;
   525 
   526     /*
   527      * Ensure that the origin of the menu is placed so that
   528      * None of the panes or selections are off the screen.
   529      */
   530     screen = DefaultScreen(display);
   531     if (menu->x_pos + menu->width > DisplayWidth(display, screen))
   532             menu->x_pos = DisplayWidth(display, screen) - menu->width;
   533     else if (menu->x_pos < 0) menu->x_pos = 0;
   534     if(menu->y_pos + menu->height > DisplayHeight(display, screen))
   535             menu->y_pos = DisplayHeight(display, screen) - menu->height;
   536     else if (menu->y_pos < 0) menu->y_pos = 0;
   537 }
   538 
   539 
   540 /*
   541  * _XMRecomputePane - Internal subroutine to recompute pane
   542  *                    window dependencies.
   543  */
   544 int
   545 _XMRecomputePane(register Display *display, register XMenu *menu, register XMPane *p_ptr, register int p_num)
   546                                 /* Standard X display variable. */
   547                                 /* Menu object being recomputed. */
   548                                 /* Pane pointer. */
   549                                 /* Pane sequence number. */
   550 {
   551     register int window_x;      /* Recomputed window X coordinate. */
   552     register int window_y;      /* Recomputed window Y coordinate. */
   553 
   554     unsigned long change_mask;  /* Value mask to reconfigure window. */
   555 
   556     register Bool config_p = False;     /* Reconfigure pane window? */
   557 
   558     /*
   559      * Update the pane serial number.
   560      */
   561     p_ptr->serial = p_num;
   562 
   563     /*
   564      * Recompute window X and Y coordinates.
   565      */
   566     switch (menu->menu_style) {
   567         case LEFT:
   568             window_x = menu->p_x_off * ((menu->p_count - 1) - p_num);
   569             window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
   570             break;
   571         case RIGHT:
   572             window_x = menu->p_x_off * p_num;
   573             window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
   574             break;
   575         case CENTER:
   576             window_x = 0;
   577             window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
   578             break;
   579         default:
   580             /* Error! Invalid style parameter. */
   581             _XMErrorCode = XME_STYLE_PARAM;
   582             return(_FAILURE);
   583     }
   584     window_x += menu->x_pos;
   585     window_y += menu->y_pos;
   586 
   587     /*
   588      * If the newly compute pane coordinates differ from the
   589      * current coordinates, reset the current coordinates and
   590      * reconfigure the pane.
   591      */
   592     if (
   593         (window_x != p_ptr->window_x) ||
   594         (window_y != p_ptr->window_y)
   595     ){
   596         /*
   597          * Reset the coordinates and schedule
   598          * the pane for reconfiguration.
   599          */
   600         p_ptr->window_x = window_x;
   601         p_ptr->window_y = window_y;
   602         config_p = True;
   603     }
   604 
   605     /*
   606      * If the local pane width and height differs from the
   607      * menu pane width and height, reset the local values.
   608      */
   609     if (
   610         (p_ptr->window_w != menu->p_width) ||
   611         (p_ptr->window_h != menu->p_height)
   612     ){
   613         /*
   614          * Reset window width and height and schedule
   615          * the pane for reconfiguration.
   616          */
   617         p_ptr->window_w = menu->p_width;
   618         p_ptr->window_h = menu->p_height;
   619         config_p = True;
   620     }
   621 
   622     /*
   623      * If we need to reconfigure the pane window do it now.
   624      */
   625     if (config_p == True) {
   626         /*
   627          * If the pane window has already been created then
   628          * reconfigure the existing window, otherwise queue
   629          * it for creation with the new configuration.
   630          */
   631         if (p_ptr->window) {
   632             XWindowChanges changes;
   633             change_mask = (CWX | CWY | CWWidth | CWHeight);
   634             changes.x = p_ptr->window_x;
   635             changes.y = p_ptr->window_y;
   636             changes.width = p_ptr->window_w;
   637             changes.height = p_ptr->window_h;
   638 
   639             XConfigureWindow(
   640                              display,
   641                              p_ptr->window,
   642                              change_mask,
   643                              &changes
   644                              );
   645         }
   646         else {
   647             if (_XMWinQueAddPane(display, menu, p_ptr) == _FAILURE) {
   648                 return(_FAILURE);
   649             }
   650         }
   651     }
   652 
   653     /*
   654      * Recompute label X position.
   655      */
   656     switch (menu->p_style) {
   657         case LEFT:
   658             p_ptr->label_x = menu->p_x_off + menu->p_fnt_pad;
   659             break;
   660         case RIGHT:
   661             p_ptr->label_x = menu->p_width -
   662                 (p_ptr->label_width + menu->p_x_off + menu->p_fnt_pad);
   663             break;
   664         case CENTER:
   665             p_ptr->label_x = (menu->p_width - p_ptr->label_width) >> 1;
   666             break;
   667         default:
   668             /* Error! Invalid style parameter. */
   669             _XMErrorCode = XME_STYLE_PARAM;
   670             return(_FAILURE);
   671     }
   672     /*
   673      * Recompute label Y positions.
   674      */
   675     p_ptr->label_uy = menu->p_fnt_pad + menu->p_fnt_info->max_bounds.ascent;
   676     p_ptr->label_ly = (menu->p_height - menu->p_fnt_pad - menu->p_fnt_info->max_bounds.descent);
   677 
   678     /*
   679      * All went well, return successfully.
   680      */
   681     _XMErrorCode = XME_NO_ERROR;
   682     return(_SUCCESS);
   683 }
   684 
   685 
   686 
   687 /*
   688  * _XMRecomputeSelection - Internal subroutine to recompute
   689  *                         selection window dependencies.
   690  */
   691 int
   692 _XMRecomputeSelection(register Display *display, register XMenu *menu, register XMSelect *s_ptr, register int s_num)
   693 
   694                                 /* Menu object being recomputed. */
   695                                 /* Selection pointer. */
   696                                 /* Selection sequence number. */
   697 {
   698     register Bool config_s = False;     /* Reconfigure selection window? */
   699     unsigned long change_mask;          /* Value mask for XConfigureWindow. */
   700 
   701     /*
   702      * If the selection serial numbers are out of order, begin
   703      * resequencing selections.  Recompute selection window coordinates
   704      * and serial number.
   705      *
   706      * When selections are created they are given a serial number of
   707      * -1, this causes this routine to give a new selection
   708      * its initial coordinates and serial number.
   709      */
   710     if (s_ptr->serial != s_num) {
   711         /*
   712          * Fix the sequence number.
   713          */
   714         s_ptr->serial = s_num;
   715         /*
   716          * Recompute window X and Y coordinates.
   717          */
   718         s_ptr->window_x = menu->s_x_off;
   719         s_ptr->window_y = menu->flag_height + (menu->s_y_off * s_num);
   720         /*
   721          * We must reconfigure the window.
   722          */
   723         config_s = True;
   724     }
   725 
   726     /*
   727      * If the local selection width and height differs from the
   728      * menu selection width and height, reset the local values.
   729      */
   730     if (
   731         (s_ptr->window_w != menu->s_width) ||
   732         (s_ptr->window_h != menu->s_height)
   733     ){
   734         /*
   735          * We must reconfigure the window.
   736          */
   737         config_s = True;
   738         /*
   739          * Reset window width and height.
   740          */
   741         s_ptr->window_w = menu->s_width;
   742         s_ptr->window_h = menu->s_height;
   743     }
   744 
   745     /*
   746      * If we need to reconfigure the selection window do it now.
   747      */
   748     if (config_s == True) {
   749         /*
   750          * If the selection window has already been created then
   751          * reconfigure the existing window, otherwise queue it
   752          * for creation with the new configuration.
   753          */
   754         if (s_ptr->window) {
   755             XWindowChanges changes;
   756             change_mask = (CWX | CWY | CWWidth | CWHeight);
   757             changes.x = s_ptr->window_x;
   758             changes.y = s_ptr->window_y;
   759             changes.width = s_ptr->window_w;
   760             changes.height = s_ptr->window_h;
   761 
   762             XConfigureWindow(
   763                              display,
   764                              s_ptr->window,
   765                              change_mask,
   766                              &changes
   767                              );
   768         }
   769         else {
   770             if (_XMWinQueAddSelection(display, menu, s_ptr) == _FAILURE) {
   771                 return(_FAILURE);
   772             }
   773         }
   774     }
   775 
   776     /*
   777      * Recompute label X position.
   778      */
   779     switch (menu->s_style) {
   780         case LEFT:
   781             s_ptr->label_x = menu->s_bdr_width + menu->s_fnt_pad + s_ptr->window_x;
   782             break;
   783         case RIGHT:
   784             s_ptr->label_x = s_ptr->window_x + menu->s_width -
   785                 (s_ptr->label_width + menu->s_bdr_width + menu->s_fnt_pad);
   786             break;
   787         case CENTER:
   788             s_ptr->label_x = s_ptr->window_x + ((menu->s_width - s_ptr->label_width) >> 1);
   789             break;
   790         default:
   791             /* Error! Invalid style parameter. */
   792             _XMErrorCode = XME_STYLE_PARAM;
   793             return(_FAILURE);
   794     }
   795     /*
   796      * Recompute label Y position.
   797      */
   798     s_ptr->label_y = s_ptr->window_y + menu->s_fnt_info->max_bounds.ascent + menu->s_fnt_pad + menu->s_bdr_width;
   799 
   800     /*
   801      * All went well, return successfully.
   802      */
   803     _XMErrorCode = XME_NO_ERROR;
   804     return(_SUCCESS);
   805 }
   806 
   807 
   808 
   809 /*
   810  * _XMTransToOrigin - Internal subroutine to translate the point at
   811  *                    the center of the current pane and selection to the
   812  *                    the menu origin.
   813  *
   814  *      WARNING! ****** Be certain that all menu dependencies have been
   815  *                      recomputed before calling this routine or
   816  *                      unpredictable results will follow.
   817  */
   818 void
   819 _XMTransToOrigin(Display *display, register XMenu *menu, register XMPane *p_ptr, register XMSelect *s_ptr, int x_pos, int y_pos, int *orig_x, int *orig_y)
   820                                 /* Not used. Included for consistency. */
   821                                 /* Menu being computed against. */
   822                                 /* Current pane pointer. */
   823                                 /* Current selection pointer. */
   824                                 /* X coordinate of point to translate. */
   825                                 /* Y coordinate of point to translate. */
   826                                 /* Return value X coord. of the menu origin. */
   827                                 /* Return value Y coord. of the menu origin. */
   828 {
   829     register int l_orig_x;      /* Local X coordinate of the menu origin. */
   830     register int l_orig_y;      /* Local Y coordinate of the menu origin. */
   831 
   832     /*
   833      * Translate the menu origin such that the cursor hot point will be in the
   834      * center of the desired current selection and pane.
   835      * If the current selection pointer is NULL then assume that the hot point
   836      * will be in the center of the current pane flag.
   837      */
   838 
   839     if (s_ptr == NULL) {
   840         /*
   841          * Translate from the center of the pane flag to the upper left
   842          * of the current pane window.
   843          */
   844         l_orig_x = x_pos - (menu->p_width >> 1) - menu->p_bdr_width;
   845         l_orig_y = y_pos - (menu->flag_height >> 1) - menu->p_bdr_width;
   846     }
   847     else {
   848         /*
   849          * First translate from the center of the current selection
   850          * to the upper left of the current selection window.
   851          */
   852         l_orig_x = x_pos - (menu->s_width >> 1);
   853         l_orig_y = y_pos - (menu->s_height >> 1);
   854 
   855         /*
   856          * Then translate to the upper left of the current pane window.
   857          */
   858         l_orig_x -= (s_ptr->window_x + menu->p_bdr_width);
   859         l_orig_y -= (s_ptr->window_y + menu->p_bdr_width);
   860     }
   861 
   862     /*
   863      * Finally translate to the upper left of the menu.
   864      */
   865     l_orig_x -= (p_ptr->window_x - menu->x_pos);
   866     l_orig_y -= (p_ptr->window_y - menu->y_pos);
   867 
   868     /*
   869      * Set the return values.
   870      */
   871     *orig_x = l_orig_x;
   872     *orig_y = l_orig_y;
   873 }
   874 
   875 /*
   876  * _XMRefreshPane - Internal subroutine to completely refresh
   877  *                  the contents of a pane.
   878  */
   879 void
   880 _XMRefreshPane(register Display *display, register XMenu *menu, register XMPane *pane)
   881 {
   882     register XMSelect *s_list = pane->s_list;
   883     register XMSelect *s_ptr;
   884 
   885     /*
   886      * First clear the pane.
   887      */
   888     XClearWindow(display, pane->window);
   889     if (!pane->activated) {
   890         XFillRectangle(display,
   891                        pane->window,
   892                        menu->inverse_select_GC,
   893                        pane->label_x - menu->p_fnt_pad,
   894                        pane->label_uy - menu->p_fnt_info->max_bounds.ascent - menu->p_fnt_pad,
   895                        pane->label_width + (menu->p_fnt_pad << 1),
   896                        menu->flag_height);
   897 
   898         XFillRectangle(display,
   899                        pane->window,
   900                        menu->inverse_select_GC,
   901                        pane->label_x - menu->p_fnt_pad,
   902                        pane->label_ly - menu->p_fnt_info->max_bounds.ascent - menu->p_fnt_pad,
   903                        pane->label_width + (menu->p_fnt_pad << 1),
   904                        menu->flag_height);
   905     }
   906     if (!pane->active) {
   907         XDrawString(display,
   908                     pane->window,
   909                     menu->inact_GC,
   910                     pane->label_x, pane->label_uy,
   911                     pane->label, pane->label_length);
   912         XDrawString(display,
   913                     pane->window,
   914                     menu->inact_GC,
   915                     pane->label_x, pane->label_ly,
   916                     pane->label, pane->label_length);
   917     }
   918     else {
   919         XDrawString(display,
   920                          pane->window,
   921                          menu->pane_GC,
   922                          pane->label_x, pane->label_uy,
   923                          pane->label, pane->label_length);
   924         XDrawString(display,
   925                          pane->window,
   926                          menu->pane_GC,
   927                          pane->label_x, pane->label_ly,
   928                          pane->label, pane->label_length);
   929 
   930         /*
   931          * Finally refresh each selection if the pane is activated.
   932          */
   933         if (pane->activated) {
   934             for (s_ptr = s_list->next; s_ptr != s_list; s_ptr = s_ptr->next)
   935                 _XMRefreshSelection(display, menu, s_ptr);
   936         }
   937     }
   938 }
   939 
   940 
   941 
   942 
   943 /*
   944  * _XMRefreshSelection - Internal subroutine that refreshes
   945  *                       a single selection window.
   946  */
   947 void
   948 _XMRefreshSelection(register Display *display, register XMenu *menu, register XMSelect *sel)
   949 {
   950     register int width = sel->window_w;
   951     register int height = sel->window_h;
   952     register int bdr_width = menu->s_bdr_width;
   953 
   954     if (sel->type == SEPARATOR) {
   955         XDrawLine(display,
   956                   sel->parent_p->window,
   957                   menu->normal_select_GC,
   958                   sel->window_x,
   959                   sel->window_y + height / 2,
   960                   sel->window_x + width,
   961                   sel->window_y + height / 2);
   962     }
   963     else if (sel->activated) {
   964         if (menu->menu_mode == INVERT) {
   965             XFillRectangle(display,
   966                            sel->parent_p->window,
   967                            menu->normal_select_GC,
   968                            sel->window_x, sel->window_y,
   969                            width, height);
   970             XDrawString(display,
   971                         sel->parent_p->window,
   972                         menu->inverse_select_GC,
   973                         sel->label_x,
   974                         sel->label_y,
   975                         sel->label, sel->label_length);
   976         }
   977         else {
   978             /*
   979              * Using BOX mode.
   980              * Since most drawing routines with arbitrary width lines
   981              * are slow compared to raster-ops let's use a raster-op to
   982              * draw the boxes.
   983              */
   984 
   985             XDrawRectangle(display,
   986                            sel->parent_p->window,
   987                            menu->normal_select_GC,
   988                            sel->window_x + (bdr_width >> 1),
   989                            sel->window_y + (bdr_width >> 1 ),
   990                            width - bdr_width,
   991                            height - bdr_width);
   992             XDrawString(display,
   993                         sel->parent_p->window,
   994                         menu->normal_select_GC,
   995                         sel->label_x,
   996                         sel->label_y,
   997                         sel->label, sel->label_length);
   998         }
   999     }
  1000     else {
  1001         XClearArea(display,
  1002                    sel->parent_p->window,
  1003                    sel->window_x, sel->window_y,
  1004                    width, height,
  1005                    False);
  1006         if (sel->active) {
  1007             XDrawString(display,
  1008                         sel->parent_p->window,
  1009                         menu->normal_select_GC,
  1010                         sel->label_x,
  1011                         sel->label_y,
  1012                         sel->label, sel->label_length);
  1013         }
  1014         else {
  1015             XDrawString(display,
  1016                         sel->parent_p->window,
  1017                         menu->inact_GC,
  1018                         sel->label_x,
  1019                         sel->label_y,
  1020                         sel->label, sel->label_length);
  1021         }
  1022     }
  1023 }

/* [<][>][^][v][top][bottom][index][help] */