home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / emacs-18.59-src.tgz / emacs-18.59-src.tar / fsf / emacs18 / oldXMenu / Internal.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  26KB  |  989 lines

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