1 /* Copyright Massachusetts Institute of Technology 1985 */
6 Copyright (C) 1993, 1996, 2001-2018 Free Software Foundation, Inc.
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>. */
23 * XMenu: MIT Project Athena, X Window system menu package
25 * XMenuInternal.c - XMenu internal (not user visible) routines.
27 * Author: Tony Della Fera, DEC
35 * Internal Window creation queue sizes.
37 #define S_QUE_SIZE 300
42 * XMWinQue - Internal window creation queue datatype.
44 typedef struct _xmwinquedef
{
46 XMSelect
*sq
[S_QUE_SIZE
];
49 XMPane
*pq
[P_QUE_SIZE
];
54 * _XMWinQue - Internal static window creation queue.
56 static Bool _XMWinQueIsInit
= False
;
57 static XMWinQue _XMWinQue
;
60 * _XMErrorCode - Global XMenu error code.
62 int _XMErrorCode
= XME_NO_ERROR
;
64 * _XMErrorList - Global XMenu error code description strings.
67 _XMErrorList
[XME_CODE_COUNT
] = {
68 "No error", /* XME_NO_ERROR */
69 "Menu not initialized", /* XME_NOT_INIT */
70 "Argument out of bounds", /* XME_ARG_BOUNDS */
71 "Pane not found", /* XME_P_NOT_FOUND */
72 "Selection not found", /* XME_S_NOT_FOUND */
73 "Invalid menu style parameter", /* XME_STYLE_PARAM */
74 "Unable to grab mouse", /* XME_GRAB_MOUSE */
75 "Unable to interpret locator", /* XME_INTERP_LOC */
76 "Unable to calloc memory", /* XME_CALLOC */
77 "Unable to create XAssocTable", /* XME_CREATE_ASSOC */
78 "Unable to store bitmap", /* XME_STORE_BITMAP */
79 "Unable to make tile pixmaps", /* XME_MAKE_TILES */
80 "Unable to make pixmap", /* XME_MAKE_PIXMAP */
81 "Unable to create cursor", /* XME_CREATE_CURSOR */
82 "Unable to open font", /* XME_OPEN_FONT */
83 "Unable to create windows", /* XME_CREATE_WINDOW */
84 "Unable to create transparencies", /* XME_CREATE_TRANSP */
88 * _XMEventHandler - Internal event handler variable.
90 int (*_XMEventHandler
)(XEvent
*) = NULL
;
95 * _XMWinQueInit - Internal routine to initialize the window
102 * If the queue is not initialized initialize it.
104 if (!_XMWinQueIsInit
) {
106 * Blank the queue structure.
110 for (i
= 0; i
< S_QUE_SIZE
; i
++)
113 for (i
= 0; i
< P_QUE_SIZE
; i
++)
116 _XMWinQue
.sq_size
= _XMWinQue
.pq_size
= 0;
119 * Initialize the next free location pointers.
121 _XMWinQue
.sq_ptr
= _XMWinQue
.sq
;
122 _XMWinQue
.pq_ptr
= _XMWinQue
.pq
;
129 * _XMWinQueAddPane - Internal routine to add a pane to the pane
133 _XMWinQueAddPane(register Display
*display
, register XMenu
*menu
, register XMPane
*p_ptr
)
135 /* Menu being manipulated. */
136 /* XMPane being queued. */
139 * If the queue is currently full then flush it.
141 if (_XMWinQue
.pq_size
== P_QUE_SIZE
) {
142 if (_XMWinQueFlush(display
, menu
, 0, 0) == _FAILURE
) return(_FAILURE
);
146 * Insert the new XMPane pointer and increment the queue pointer
147 * and the queue size.
149 *_XMWinQue
.pq_ptr
= p_ptr
;
154 * All went well, return successfully.
156 _XMErrorCode
= XME_NO_ERROR
;
163 * _XMWinQueAddSelection - Internal routine to add a selection to
164 * the selection window queue.
167 _XMWinQueAddSelection(register Display
*display
, register XMenu
*menu
, register XMSelect
*s_ptr
)
169 /* Menu being manipulated. */
170 /* XMSelection being queued. */
173 * If this entry will overflow the queue then flush it.
175 if (_XMWinQue
.sq_size
== S_QUE_SIZE
) {
176 if (_XMWinQueFlush(display
, menu
, 0, 0) == _FAILURE
) return(_FAILURE
);
180 * Insert the new XMSelect pointer and increment the queue pointer
181 * and the queue size.
183 *_XMWinQue
.sq_ptr
= s_ptr
;
188 * All went well, return successfully.
190 _XMErrorCode
= XME_NO_ERROR
;
197 * _XMWinQueFlush - Internal routine to flush the pane and
198 * selection window queues.
201 _XMWinQueFlush(register Display
*display
, register XMenu
*menu
, register XMPane
*pane
, XMSelect
*sel
)
203 /* Menu being manipulated. */
206 register int pq_index
; /* Pane queue index. */
207 register int sq_index
; /* Selection queue index. */
208 register XMPane
*p_ptr
; /* XMPane pointer. */
209 register XMSelect
*s_ptr
; /* XMSelect pointer. */
210 unsigned long valuemask
; /* Which attributes to set. */
211 XSetWindowAttributes attributes_buf
; /* Attributes to be set. */
212 XSetWindowAttributes
*attributes
= &attributes_buf
;
215 * If the pane window queue is not empty...
218 if (_XMWinQue
.pq_size
> 0) {
220 * set up attributes for pane window to be created.
222 valuemask
= (CWBackPixmap
| CWBorderPixel
| CWOverrideRedirect
);
223 attributes
->border_pixel
= menu
->p_bdr_color
;
224 attributes
->background_pixmap
= menu
->inact_pixmap
;
225 attributes
->override_redirect
= True
;
228 * Create all the pending panes in order, so that the
229 * current pane will be on top, with the others
230 * stacked appropriately under it.
232 for (pq_index
= _XMWinQue
.pq_size
- 1;
236 p_ptr
= _XMWinQue
.pq
[pq_index
]; /* Retrieve next pane. */
237 if (p_ptr
== pane
) break;
238 p_ptr
->window
= XCreateWindow(display
,
250 XMakeAssoc(display
, menu
->assoc_tab
, p_ptr
->window
, p_ptr
);
251 XSelectInput(display
, p_ptr
->window
, menu
->p_events
);
254 pq_index
< _XMWinQue
.pq_size
;
257 p_ptr
= _XMWinQue
.pq
[pq_index
]; /* Retrieve next pane. */
258 p_ptr
->window
= XCreateWindow(display
,
270 XMakeAssoc(display
, menu
->assoc_tab
, p_ptr
->window
, p_ptr
);
271 XSelectInput(display
, p_ptr
->window
, menu
->p_events
);
272 if (p_ptr
== pane
) break;
276 * Reset the pane queue pointer and size.
278 _XMWinQue
.pq_size
= 0;
279 _XMWinQue
.pq_ptr
= _XMWinQue
.pq
;
283 * If the selection window queue is not empty...
286 if (_XMWinQue
.sq_size
> 0) {
288 for (sq_index
= 0; sq_index
< _XMWinQue
.sq_size
; sq_index
++) {
290 * Retrieve the XMSelect pointer.
292 s_ptr
= _XMWinQue
.sq
[sq_index
];
293 s_ptr
->window
= XCreateWindow(display
,
294 s_ptr
->parent_p
->window
,
307 * Insert the new window id and its
308 * associated XMSelect structure into the
311 XMakeAssoc(display
, menu
->assoc_tab
, s_ptr
->window
, s_ptr
);
312 XSelectInput(display
, s_ptr
->window
, menu
->s_events
);
316 * Reset the selection queue pointer and size.
318 _XMWinQue
.sq_size
= 0;
319 _XMWinQue
.sq_ptr
= _XMWinQue
.sq
;
323 * Flush X's internal queues.
328 * All went well, return successfully.
330 _XMErrorCode
= XME_NO_ERROR
;
337 * _XMGetPanePtr - Given a menu pointer and a pane index number, return
338 * a pane pointer that points to the indexed pane.
341 _XMGetPanePtr(register XMenu
*menu
, register int p_num
)
342 /* Menu to find the pane in. */
343 /* Index number of pane to find. */
345 register XMPane
*p_ptr
; /* Pane pointer to be returned. */
346 register int i
; /* Loop counter. */
349 * Is the pane number out of range?
351 if ((p_num
< 0) || (p_num
> (menu
->p_count
- 1))) {
352 _XMErrorCode
= XME_P_NOT_FOUND
;
357 * Find the right pane.
359 p_ptr
= menu
->p_list
->next
;
360 for (i
= 0; i
< p_num
; i
++) p_ptr
= p_ptr
->next
;
363 * Return successfully.
365 _XMErrorCode
= XME_NO_ERROR
;
372 * _XMGetSelectionPtr - Given pane pointer and a selection index number,
373 * return a selection pointer that points to the
377 _XMGetSelectionPtr(register XMPane
*p_ptr
, register int s_num
)
378 /* Pane to find the selection in. */
379 /* Index number of the selection to find. */
381 register XMSelect
*s_ptr
; /* Selection pointer to be returned. */
382 register int i
; /* Loop counter. */
385 * Is the selection number out of range?
387 if ((s_num
< 0) || (s_num
> (p_ptr
->s_count
- 1))) {
388 _XMErrorCode
= XME_S_NOT_FOUND
;
393 * Find the right selection.
395 s_ptr
= p_ptr
->s_list
->next
;
396 for (i
= 0; i
< s_num
; i
++) s_ptr
= s_ptr
->next
;
399 * Return successfully.
401 _XMErrorCode
= XME_NO_ERROR
;
408 * _XMRecomputeGlobals - Internal subroutine to recompute menu wide
412 _XMRecomputeGlobals(register Display
*display
, register XMenu
*menu
)
413 /*X11 display variable. */
414 /* Menu object to compute from. */
416 register XMPane
*p_ptr
; /* Pane pointer. */
417 register XMSelect
*s_ptr
; /* Selection pointer. */
419 register int max_p_label
= 0; /* Maximum pane label width. */
420 register int max_s_label
= 0; /* Maximum selection label width. */
421 register int s_count
= 0; /* Maximum selection count. */
423 int p_s_pad
; /* Pane <-> selection padding. */
424 int p_s_diff
; /* Pane <-> selection separation. */
426 int p_height
; /* Pane window height. */
427 int p_width
; /* Pane window width. */
428 int s_width
; /* Selection window width. */
430 int screen
; /* DefaultScreen holder. */
436 p_ptr
= menu
->p_list
->next
;
437 p_ptr
!= menu
->p_list
;
442 * Recompute maximum pane label width.
444 max_p_label
= max(max_p_label
, p_ptr
->label_width
);
447 * Recompute maximum selection count.
449 s_count
= max(s_count
, p_ptr
->s_count
);
452 * For each selection in the current pane...
455 s_ptr
= p_ptr
->s_list
->next
;
456 s_ptr
!= p_ptr
->s_list
;
461 * Recompute maximum selection label width.
463 max_s_label
= max(max_s_label
, s_ptr
->label_width
);
468 * Recompute pane height.
470 p_height
= (menu
->flag_height
<< 1) + (menu
->s_y_off
* s_count
);
473 * Recompute horizontal padding between the pane window and the
476 p_s_pad
= menu
->p_x_off
<< 1;
479 * Recompute pane and selection window widths.
480 * This is done by first computing the window sizes from the maximum
481 * label widths. If the spacing between the selection window and the
482 * containing pane window is less than the pane selection padding value
483 * (twice the pane X offset) then change the size of the pane to be
484 * the size of the selection window plus the padding. If, however the
485 * spacing between the selection window and the containing pane window
486 * is more than the pane selection padding value increase the size of
487 * the selection to its maximum possible value (the pane width minus
488 * the pane selection padding value).
490 p_width
= max_p_label
+ p_s_pad
;
491 s_width
= max_s_label
+ (menu
->s_fnt_pad
<< 1) + (menu
->s_bdr_width
<< 1);
492 p_s_diff
= p_width
- s_width
;
493 if (p_s_diff
< p_s_pad
) {
494 p_width
= s_width
+ p_s_pad
;
496 else if (p_s_diff
> p_s_pad
) {
497 s_width
= p_width
- p_s_pad
;
501 * Reset menu wide global values.
503 menu
->s_count
= s_count
;
504 menu
->p_height
= p_height
;
505 menu
->p_width
= p_width
;
506 menu
->s_width
= s_width
;
509 * Ensure that the origin of the menu is placed so that
510 * None of the panes or selections are off the screen.
512 screen
= DefaultScreen(display
);
513 if (menu
->x_pos
+ menu
->width
> DisplayWidth(display
, screen
))
514 menu
->x_pos
= DisplayWidth(display
, screen
) - menu
->width
;
515 else if (menu
->x_pos
< 0) menu
->x_pos
= 0;
516 if(menu
->y_pos
+ menu
->height
> DisplayHeight(display
, screen
))
517 menu
->y_pos
= DisplayHeight(display
, screen
) - menu
->height
;
518 else if (menu
->y_pos
< 0) menu
->y_pos
= 0;
523 * _XMRecomputePane - Internal subroutine to recompute pane
524 * window dependencies.
527 _XMRecomputePane(register Display
*display
, register XMenu
*menu
, register XMPane
*p_ptr
, register int p_num
)
528 /* Standard X display variable. */
529 /* Menu object being recomputed. */
531 /* Pane sequence number. */
533 register int window_x
; /* Recomputed window X coordinate. */
534 register int window_y
; /* Recomputed window Y coordinate. */
536 unsigned long change_mask
; /* Value mask to reconfigure window. */
537 XWindowChanges
*changes
; /* Values to use in configure window. */
539 register Bool config_p
= False
; /* Reconfigure pane window? */
542 * Update the pane serial number.
544 p_ptr
->serial
= p_num
;
547 * Recompute window X and Y coordinates.
549 switch (menu
->menu_style
) {
551 window_x
= menu
->p_x_off
* ((menu
->p_count
- 1) - p_num
);
552 window_y
= menu
->p_y_off
* ((menu
->p_count
- 1) - p_num
);
555 window_x
= menu
->p_x_off
* p_num
;
556 window_y
= menu
->p_y_off
* ((menu
->p_count
- 1) - p_num
);
560 window_y
= menu
->p_y_off
* ((menu
->p_count
- 1) - p_num
);
563 /* Error! Invalid style parameter. */
564 _XMErrorCode
= XME_STYLE_PARAM
;
567 window_x
+= menu
->x_pos
;
568 window_y
+= menu
->y_pos
;
571 * If the newly compute pane coordinates differ from the
572 * current coordinates, reset the current coordinates and
573 * reconfigure the pane.
576 (window_x
!= p_ptr
->window_x
) ||
577 (window_y
!= p_ptr
->window_y
)
580 * Reset the coordinates and schedule
581 * the pane for reconfiguration.
583 p_ptr
->window_x
= window_x
;
584 p_ptr
->window_y
= window_y
;
589 * If the local pane width and height differs from the
590 * menu pane width and height, reset the local values.
593 (p_ptr
->window_w
!= menu
->p_width
) ||
594 (p_ptr
->window_h
!= menu
->p_height
)
597 * Reset window width and height and schedule
598 * the pane for reconfiguration.
600 p_ptr
->window_w
= menu
->p_width
;
601 p_ptr
->window_h
= menu
->p_height
;
606 * If we need to reconfigure the pane window do it now.
608 if (config_p
== True
) {
610 * If the pane window has already been created then
611 * reconfigure the existing window, otherwise queue
612 * it for creation with the new configuration.
615 change_mask
= (CWX
| CWY
| CWWidth
| CWHeight
);
616 changes
= (XWindowChanges
*)malloc(sizeof(XWindowChanges
));
617 changes
->x
= p_ptr
->window_x
;
618 changes
->y
= p_ptr
->window_y
;
619 changes
->width
= p_ptr
->window_w
;
620 changes
->height
= p_ptr
->window_h
;
632 if (_XMWinQueAddPane(display
, menu
, p_ptr
) == _FAILURE
) {
639 * Recompute label X position.
641 switch (menu
->p_style
) {
643 p_ptr
->label_x
= menu
->p_x_off
+ menu
->p_fnt_pad
;
646 p_ptr
->label_x
= menu
->p_width
-
647 (p_ptr
->label_width
+ menu
->p_x_off
+ menu
->p_fnt_pad
);
650 p_ptr
->label_x
= (menu
->p_width
- p_ptr
->label_width
) >> 1;
653 /* Error! Invalid style parameter. */
654 _XMErrorCode
= XME_STYLE_PARAM
;
658 * Recompute label Y positions.
660 p_ptr
->label_uy
= menu
->p_fnt_pad
+ menu
->p_fnt_info
->max_bounds
.ascent
;
661 p_ptr
->label_ly
= (menu
->p_height
- menu
->p_fnt_pad
- menu
->p_fnt_info
->max_bounds
.descent
);
664 * All went well, return successfully.
666 _XMErrorCode
= XME_NO_ERROR
;
673 * _XMRecomputeSelection - Internal subroutine to recompute
674 * selection window dependencies.
677 _XMRecomputeSelection(register Display
*display
, register XMenu
*menu
, register XMSelect
*s_ptr
, register int s_num
)
679 /* Menu object being recomputed. */
680 /* Selection pointer. */
681 /* Selection sequence number. */
683 register Bool config_s
= False
; /* Reconfigure selection window? */
684 XWindowChanges
*changes
; /* Values to change in configure. */
685 unsigned long change_mask
; /* Value mask for XConfigureWindow. */
688 * If the selection serial numbers are out of order, begin
689 * resequencing selections. Recompute selection window coordinates
692 * When selections are created they are given a serial number of
693 * -1, this causes this routine to give a new selection
694 * its initial coordinates and serial number.
696 if (s_ptr
->serial
!= s_num
) {
698 * Fix the sequence number.
700 s_ptr
->serial
= s_num
;
702 * Recompute window X and Y coordinates.
704 s_ptr
->window_x
= menu
->s_x_off
;
705 s_ptr
->window_y
= menu
->flag_height
+ (menu
->s_y_off
* s_num
);
707 * We must reconfigure the window.
713 * If the local selection width and height differs from the
714 * menu selection width and height, reset the local values.
717 (s_ptr
->window_w
!= menu
->s_width
) ||
718 (s_ptr
->window_h
!= menu
->s_height
)
721 * We must reconfigure the window.
725 * Reset window width and height.
727 s_ptr
->window_w
= menu
->s_width
;
728 s_ptr
->window_h
= menu
->s_height
;
732 * If we need to reconfigure the selection window do it now.
734 if (config_s
== True
) {
736 * If the selection window has already been created then
737 * reconfigure the existing window, otherwise queue it
738 * for creation with the new configuration.
741 changes
= (XWindowChanges
*)malloc(sizeof(XWindowChanges
));
742 change_mask
= (CWX
| CWY
| CWWidth
| CWHeight
);
743 changes
= (XWindowChanges
*)malloc(sizeof(XWindowChanges
));
744 changes
->x
= s_ptr
->window_x
;
745 changes
->y
= s_ptr
->window_y
;
746 changes
->width
= s_ptr
->window_w
;
747 changes
->height
= s_ptr
->window_h
;
759 if (_XMWinQueAddSelection(display
, menu
, s_ptr
) == _FAILURE
) {
766 * Recompute label X position.
768 switch (menu
->s_style
) {
770 s_ptr
->label_x
= menu
->s_bdr_width
+ menu
->s_fnt_pad
+ s_ptr
->window_x
;
773 s_ptr
->label_x
= s_ptr
->window_x
+ menu
->s_width
-
774 (s_ptr
->label_width
+ menu
->s_bdr_width
+ menu
->s_fnt_pad
);
777 s_ptr
->label_x
= s_ptr
->window_x
+ ((menu
->s_width
- s_ptr
->label_width
) >> 1);
780 /* Error! Invalid style parameter. */
781 _XMErrorCode
= XME_STYLE_PARAM
;
785 * Recompute label Y position.
787 s_ptr
->label_y
= s_ptr
->window_y
+ menu
->s_fnt_info
->max_bounds
.ascent
+ menu
->s_fnt_pad
+ menu
->s_bdr_width
;
790 * All went well, return successfully.
792 _XMErrorCode
= XME_NO_ERROR
;
799 * _XMTransToOrigin - Internal subroutine to translate the point at
800 * the center of the current pane and selection to the
803 * WARNING! ****** Be certain that all menu dependencies have been
804 * recomputed before calling this routine or
805 * unpredictable results will follow.
808 _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
)
809 /* Not used. Included for consistency. */
810 /* Menu being computed against. */
811 /* Current pane pointer. */
812 /* Current selection pointer. */
813 /* X coordinate of point to translate. */
814 /* Y coordinate of point to translate. */
815 /* Return value X coord. of the menu origin. */
816 /* Return value Y coord. of the menu origin. */
818 register int l_orig_x
; /* Local X coordinate of the menu origin. */
819 register int l_orig_y
; /* Local Y coordinate of the menu origin. */
822 * Translate the menu origin such that the cursor hot point will be in the
823 * center of the desired current selection and pane.
824 * If the current selection pointer is NULL then assume that the hot point
825 * will be in the center of the current pane flag.
830 * Translate from the center of the pane flag to the upper left
831 * of the current pane window.
833 l_orig_x
= x_pos
- (menu
->p_width
>> 1) - menu
->p_bdr_width
;
834 l_orig_y
= y_pos
- (menu
->flag_height
>> 1) - menu
->p_bdr_width
;
838 * First translate from the center of the current selection
839 * to the upper left of the current selection window.
841 l_orig_x
= x_pos
- (menu
->s_width
>> 1);
842 l_orig_y
= y_pos
- (menu
->s_height
>> 1);
845 * Then translate to the upper left of the current pane window.
847 l_orig_x
-= (s_ptr
->window_x
+ menu
->p_bdr_width
);
848 l_orig_y
-= (s_ptr
->window_y
+ menu
->p_bdr_width
);
852 * Finally translate to the upper left of the menu.
854 l_orig_x
-= (p_ptr
->window_x
- menu
->x_pos
);
855 l_orig_y
-= (p_ptr
->window_y
- menu
->y_pos
);
858 * Set the return values.
865 * _XMRefreshPane - Internal subroutine to completely refresh
866 * the contents of a pane.
869 _XMRefreshPane(register Display
*display
, register XMenu
*menu
, register XMPane
*pane
)
871 register XMSelect
*s_list
= pane
->s_list
;
872 register XMSelect
*s_ptr
;
875 * First clear the pane.
877 XClearWindow(display
, pane
->window
);
878 if (!pane
->activated
) {
879 XFillRectangle(display
,
881 menu
->inverse_select_GC
,
882 pane
->label_x
- menu
->p_fnt_pad
,
883 pane
->label_uy
- menu
->p_fnt_info
->max_bounds
.ascent
- menu
->p_fnt_pad
,
884 pane
->label_width
+ (menu
->p_fnt_pad
<< 1),
887 XFillRectangle(display
,
889 menu
->inverse_select_GC
,
890 pane
->label_x
- menu
->p_fnt_pad
,
891 pane
->label_ly
- menu
->p_fnt_info
->max_bounds
.ascent
- menu
->p_fnt_pad
,
892 pane
->label_width
+ (menu
->p_fnt_pad
<< 1),
899 pane
->label_x
, pane
->label_uy
,
900 pane
->label
, pane
->label_length
);
904 pane
->label_x
, pane
->label_ly
,
905 pane
->label
, pane
->label_length
);
911 pane
->label_x
, pane
->label_uy
,
912 pane
->label
, pane
->label_length
);
916 pane
->label_x
, pane
->label_ly
,
917 pane
->label
, pane
->label_length
);
920 * Finally refresh each selection if the pane is activated.
922 if (pane
->activated
) {
923 for (s_ptr
= s_list
->next
; s_ptr
!= s_list
; s_ptr
= s_ptr
->next
)
924 _XMRefreshSelection(display
, menu
, s_ptr
);
933 * _XMRefreshSelection - Internal subroutine that refreshes
934 * a single selection window.
937 _XMRefreshSelection(register Display
*display
, register XMenu
*menu
, register XMSelect
*sel
)
939 register int width
= sel
->window_w
;
940 register int height
= sel
->window_h
;
941 register int bdr_width
= menu
->s_bdr_width
;
943 if (sel
->type
== SEPARATOR
) {
945 sel
->parent_p
->window
,
946 menu
->normal_select_GC
,
948 sel
->window_y
+ height
/ 2,
949 sel
->window_x
+ width
,
950 sel
->window_y
+ height
/ 2);
952 else if (sel
->activated
) {
953 if (menu
->menu_mode
== INVERT
) {
954 XFillRectangle(display
,
955 sel
->parent_p
->window
,
956 menu
->normal_select_GC
,
957 sel
->window_x
, sel
->window_y
,
960 sel
->parent_p
->window
,
961 menu
->inverse_select_GC
,
964 sel
->label
, sel
->label_length
);
969 * Since most drawing routines with arbitrary width lines
970 * are slow compared to raster-ops let's use a raster-op to
974 XDrawRectangle(display
,
975 sel
->parent_p
->window
,
976 menu
->normal_select_GC
,
977 sel
->window_x
+ (bdr_width
>> 1),
978 sel
->window_y
+ (bdr_width
>> 1 ),
982 sel
->parent_p
->window
,
983 menu
->normal_select_GC
,
986 sel
->label
, sel
->label_length
);
991 sel
->parent_p
->window
,
992 sel
->window_x
, sel
->window_y
,
997 sel
->parent_p
->window
,
998 menu
->normal_select_GC
,
1001 sel
->label
, sel
->label_length
);
1004 XDrawString(display
,
1005 sel
->parent_p
->window
,
1009 sel
->label
, sel
->label_length
);