Mercurial > hg > xemacs-beta
annotate lwlib/xlwmenu.c @ 5104:868a5349acee
add documentation to frame.c, rearrange some functions to consolidate in related areas
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* frame.c:
* frame.c (frame_live_p):
* frame.c (Fframep):
* frame.c (Fdisable_frame):
* frame.c (Fenable_frame):
* frame.c (Fraise_frame):
* frame.c (Fframe_name):
* frame.c (Fset_frame_height):
* frame.c (internal_set_frame_size):
* frame.c (adjust_frame_size):
Add documentation on the different types of units used to measure
frame size.
Add section headers to the various sections.
Rearrange the location of some functions in the file to keep
related functions together. This especially goes for frame-sizing
functions (internal_set_frame_size() and adjust_frame_size()),
which have been moved so that they form a group with
change_frame_size() and change_frame_size_1().
No functionality should change.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Mar 2010 22:50:27 -0600 |
parents | a6c778975d7d |
children | ade4c7e2c6cb |
rev | line source |
---|---|
428 | 1 /* Implements a lightweight menubar widget. |
2 Copyright (C) 1992, 1993, 1994 Lucid, Inc. | |
3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp. | |
4 | |
5 This file is part of the Lucid Widget Library. | |
6 | |
7 The Lucid Widget Library is free software; you can redistribute it and/or | |
8 modify it under the terms of the GNU General Public License as published by | |
9 the Free Software Foundation; either version 2, or (at your option) | |
10 any later version. | |
11 | |
12 The Lucid Widget Library is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Created by devin@lucid.com */ | |
23 | |
24 #include <config.h> | |
25 #include <stdlib.h> | |
26 #include <string.h> | |
27 #include <ctype.h> | |
28 #include <stdio.h> | |
29 #include <sys/types.h> | |
30 #include <limits.h> | |
31 #ifdef HAVE_UNISTD_H | |
32 #include <unistd.h> | |
33 #endif | |
34 | |
35 #include <X11/IntrinsicP.h> | |
36 #include <X11/ShellP.h> | |
37 #include <X11/StringDefs.h> | |
38 #include <X11/cursorfont.h> | |
39 #include <X11/bitmaps/gray> | |
40 | |
41 #ifdef NEED_MOTIF | |
42 #include <Xm/Xm.h> | |
43 #if XmVersion < 1002 /* 1.1 or ancient */ | |
44 #undef XmFONTLIST_DEFAULT_TAG | |
45 #define XmFONTLIST_DEFAULT_TAG XmSTRING_DEFAULT_CHARSET | |
46 #endif /* XmVersion < 1.2 */ | |
47 #endif | |
3094 | 48 |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
49 /* #### we may want to turn off HAVE_XFT here if !HAVE_XFT_MENUBARS |
3094 | 50 In fact, maybe that's the right interface overall? */ |
51 #include "lwlib-fonts.h" | |
52 #include "lwlib-colors.h" | |
428 | 53 #include "xlwmenuP.h" |
54 | |
55 #ifdef USE_DEBUG_MALLOC | |
56 #include <dmalloc.h> | |
57 #endif | |
58 | |
442 | 59 /* simple, naive integer maximum */ |
428 | 60 #ifndef max |
61 #define max(a,b) ((a)>(b)?(a):(b)) | |
62 #endif | |
63 | |
64 static char | |
65 xlwMenuTranslations [] = | |
66 "<BtnDown>: start()\n\ | |
67 <BtnMotion>: drag()\n\ | |
68 <BtnUp>: select()\n\ | |
69 "; | |
70 | |
71 extern Widget lw_menubar_widget; | |
72 | |
73 static XtResource | |
74 xlwMenuResources[] = | |
75 { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
76 /* The offset macro is a standard trick. The remaining macros are an |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
77 experiment to compress redundancies in resource descriptions, and shut |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
78 up GCC 4.3 (the String casts, which keep G++ from complaining about |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
79 implicit conversions from const char *). */ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
80 #define offset(field) XtOffset(XlwMenuWidget, menu.field) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
81 #define fontres(name,_class,repr,type,member,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
82 Xt_RESOURCE (name, _class, repr, type, offset(member), XtRString, value) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
83 #define mflres(name,cls,member,repr,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
84 Xt_RESOURCE (name, cls, XmRFontList, XmFontList, offset(member), repr, value) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
85 #define dimres(name,cls,repr,member,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
86 Xt_RESOURCE (name, cls, repr, Dimension, offset(member), XtRImmediate, value) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
87 #define boolres(nm,cls,member,val) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
88 Xt_RESOURCE (nm, cls, XtRBoolean, Boolean, offset(member), XtRImmediate, val) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
89 #define cbres(name,member,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
90 Xt_RESOURCE (name, XtCCallback, XtRCallback, XtPointer, offset(member), \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
91 XtRCallback, value) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
92 #define pixres(name,_class,member,repr,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
93 Xt_RESOURCE (name, _class, XtRPixel, Pixel, offset(member), repr, value) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
94 #define fgpixres(name,_class,member) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
95 pixres (name, _class, member, XtRString, "XtDefaultForeground") |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
96 #define nullpixres(name,_class,member) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
97 pixres (name, _class, member, XtRImmediate, -1) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
98 #define pmres(name,cls,member) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
99 Xt_RESOURCE (name, cls, XtRPixmap, Pixmap, offset(member), XtRImmediate, None) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
100 |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
101 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 102 /* There are three font list resources, so that we can accept either of |
103 the resources *fontList: or *font:, and so that we can tell the | |
104 difference between them being specified, and being defaulted to a | |
105 font from the XtRString specified here. */ | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
106 mflres (XmNfontList, XmCFontList, font_list, XtRImmediate, 0), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
107 mflres (XtNfont, XtCFont, font_list_2, XtRImmediate, 0), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
108 mflres (XmNfontList, XmCFontList, fallback_font_list, |
428 | 109 /* We must use an iso8859-1 font here, or people without $LANG set lose. |
110 It's fair to assume that those who do have $LANG set also have the | |
111 *fontList resource set, or at least know how to deal with this. */ | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
112 XtRString, (XtPointer) "-*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-1"), |
428 | 113 #else |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
114 fontres (XtNfont, XtCFont, XtRFontStruct, XFontStruct *, font, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
115 "XtDefaultFont"), |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
116 #ifdef HAVE_XFT_MENUBARS |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
117 fontres (XtNfcFontName, XtCFcFontName, XtRString, String, fcFontName, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
118 "sans-serif-12:bold"), |
3397 | 119 /* #### This needs to be fixed to give a proper type and converter for |
120 XftFonts. See also xlwtabs.c. */ | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
121 fontres (XtNxftFont, XtCXftFont, XtRString, XtPointer, xftFontName, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
122 "Helvetica-12:bold"), |
3094 | 123 #endif |
428 | 124 # ifdef USE_XFONTSET |
442 | 125 /* #### Consider using the same method as for Motif; see the comment in |
126 XlwMenuInitialize(). */ | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
127 fontres (XtNfontSet, XtCFontSet, XtRFontSet, XFontSet, font_set, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
128 "XtDefaultFontSet"), |
428 | 129 # endif |
130 #endif | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
131 fgpixres (XtNforeground, XtCForeground, foreground), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
132 fgpixres (XtNbuttonForeground, XtCButtonForeground, button_foreground), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
133 fgpixres (XtNhighlightForeground, XtCHighlightForeground, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
134 highlight_foreground), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
135 fgpixres (XtNtitleForeground, XtCTitleForeground, title_foreground), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
136 dimres (XtNmargin, XtCMargin, XtRDimension, margin, 2), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
137 dimres (XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
138 horizontal_margin, 2), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
139 dimres (XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
140 vertical_margin, 1), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
141 dimres (XmNspacing, XmCSpacing, XmRHorizontalDimension, column_spacing, 4), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
142 dimres (XmNindicatorSize, XmCIndicatorSize, XtRDimension, indicator_size, 0), |
428 | 143 #if 0 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
144 dimres (XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
145 shadow_thickness, 2), |
428 | 146 #else |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
147 dimres (XmNshadowThickness, XmCShadowThickness, XtRDimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
148 shadow_thickness, 2), |
428 | 149 #endif |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
150 nullpixres (XmNselectColor, XmCSelectColor, select_color), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
151 nullpixres (XmNtopShadowColor, XmCTopShadowColor, top_shadow_color), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
152 nullpixres (XmNbottomShadowColor, XmCBottomShadowColor, bottom_shadow_color), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
153 pmres (XmNtopShadowPixmap, XmCTopShadowPixmap, top_shadow_pixmap), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
154 pmres (XmNbottomShadowPixmap, XmCBottomShadowPixmap, bottom_shadow_pixmap), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
155 |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
156 cbres (XtNopen, open, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
157 cbres (XtNselect, select, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
158 Xt_RESOURCE (XtNmenu, XtCMenu, XtRPointer, XtPointer, offset(contents), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
159 XtRImmediate, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
160 Xt_RESOURCE (XtNcursor, XtCCursor, XtRCursor, Cursor, offset(cursor_shape), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
161 XtRString, "right_ptr"), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
162 Xt_RESOURCE (XtNhorizontal, XtCHorizontal, XtRInt, int, offset(horizontal), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
163 XtRImmediate, True), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
164 boolres (XtNuseBackingStore, XtCUseBackingStore, use_backing_store, False), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
165 boolres (XtNbounceDown, XtCBounceDown, bounce_down, True), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
166 boolres (XtNresourceLabels, XtCResourceLabels, lookup_labels, False), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
167 |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
168 #undef offset |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
169 #undef mflres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
170 #undef fontres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
171 #undef dimres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
172 #undef boolres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
173 #undef cbres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
174 #undef pixres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
175 #undef fgpixres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
176 #undef nullpixres |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
177 #undef pmres |
4522
fc7067b7f407
Backout last patch; forgot to specify file.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4521
diff
changeset
|
178 }; |
428 | 179 |
1201 | 180 static Boolean XlwMenuSetValues (Widget current, Widget request, Widget new_, |
428 | 181 ArgList args, Cardinal *num_args); |
182 static void XlwMenuRealize (Widget w, Mask *valueMask, | |
183 XSetWindowAttributes *attributes); | |
184 static void XlwMenuRedisplay (Widget w, XEvent *ev, Region region); | |
185 static void XlwMenuResize (Widget w); | |
1201 | 186 static void XlwMenuInitialize (Widget request, Widget new_, ArgList args, |
428 | 187 Cardinal *num_args); |
188 static void XlwMenuDestroy (Widget w); | |
189 static void XlwMenuClassInitialize (void); | |
190 static void Start (Widget w, XEvent *ev, String *params, Cardinal *num_params); | |
191 static void Drag (Widget w, XEvent *ev, String *params, Cardinal *num_params); | |
192 static void Select(Widget w, XEvent *ev, String *params, Cardinal *num_params); | |
193 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
194 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 195 static XFontStruct *default_font_of_font_list (XmFontList); |
196 #endif | |
197 | |
198 static XtActionsRec | |
199 xlwMenuActionsList [] = | |
200 { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
201 { (String) "start", Start}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
202 { (String) "drag", Drag}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
203 { (String) "select", Select}, |
428 | 204 }; |
205 | |
206 #define SuperClass ((CoreWidgetClass)&coreClassRec) | |
207 | |
208 XlwMenuClassRec xlwMenuClassRec = | |
209 { | |
210 { /* CoreClass fields initialization */ | |
211 (WidgetClass) SuperClass, /* superclass */ | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
212 (String) "XlwMenu", /* class_name */ |
428 | 213 sizeof(XlwMenuRec), /* size */ |
214 XlwMenuClassInitialize, /* class_initialize */ | |
215 NULL, /* class_part_initialize */ | |
216 FALSE, /* class_inited */ | |
217 XlwMenuInitialize, /* initialize */ | |
218 NULL, /* initialize_hook */ | |
219 XlwMenuRealize, /* realize */ | |
220 xlwMenuActionsList, /* actions */ | |
221 XtNumber(xlwMenuActionsList), /* num_actions */ | |
222 xlwMenuResources, /* resources */ | |
223 XtNumber(xlwMenuResources), /* resource_count */ | |
224 NULLQUARK, /* xrm_class */ | |
225 TRUE, /* compress_motion */ | |
1294 | 226 XtExposeCompressMaximal, /* compress_exposure */ |
428 | 227 TRUE, /* compress_enterleave */ |
228 FALSE, /* visible_interest */ | |
229 XlwMenuDestroy, /* destroy */ | |
230 XlwMenuResize, /* resize */ | |
231 XlwMenuRedisplay, /* expose */ | |
232 XlwMenuSetValues, /* set_values */ | |
233 NULL, /* set_values_hook */ | |
234 XtInheritSetValuesAlmost, /* set_values_almost */ | |
235 NULL, /* get_values_hook */ | |
236 NULL, /* #### - should this be set for grabs? accept_focus */ | |
237 XtVersion, /* version */ | |
238 NULL, /* callback_private */ | |
239 xlwMenuTranslations, /* tm_table */ | |
240 XtInheritQueryGeometry, /* query_geometry */ | |
241 XtInheritDisplayAccelerator, /* display_accelerator */ | |
242 NULL /* extension */ | |
243 }, /* XlwMenuClass fields initialization */ | |
244 { | |
245 0 /* dummy */ | |
246 }, | |
247 }; | |
248 | |
249 WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec; | |
250 | |
251 extern int lw_menu_accelerate; | |
252 | |
253 /* Utilities */ | |
254 #if 0 /* Apparently not used anywhere */ | |
255 | |
256 static char * | |
257 safe_strdup (char *s) | |
258 { | |
259 char *result; | |
260 if (! s) return 0; | |
261 result = (char *) malloc (strlen (s) + 1); | |
262 if (! result) | |
263 return 0; | |
264 strcpy (result, s); | |
265 return result; | |
266 } | |
267 | |
268 #endif /* 0 */ | |
269 | |
270 static void | |
271 push_new_stack (XlwMenuWidget mw, widget_value *val) | |
272 { | |
273 if (!mw->menu.new_stack) | |
274 { | |
275 mw->menu.new_stack_length = 10; | |
276 mw->menu.new_stack = | |
277 (widget_value**)XtCalloc (mw->menu.new_stack_length, | |
278 sizeof (widget_value*)); | |
279 } | |
280 else if (mw->menu.new_depth == mw->menu.new_stack_length) | |
281 { | |
282 mw->menu.new_stack_length *= 2; | |
283 mw->menu.new_stack = | |
284 (widget_value**)XtRealloc ((char *)mw->menu.new_stack, | |
285 mw->menu.new_stack_length * | |
286 sizeof (widget_value*)); | |
287 } | |
288 mw->menu.new_stack [mw->menu.new_depth++] = val; | |
289 } | |
290 | |
291 static void | |
292 pop_new_stack_if_no_contents (XlwMenuWidget mw) | |
293 { | |
294 if (mw->menu.new_depth && | |
295 !mw->menu.new_stack [mw->menu.new_depth - 1]->contents) | |
296 mw->menu.new_depth -= 1; | |
297 } | |
298 | |
299 static void | |
300 make_old_stack_space (XlwMenuWidget mw, int n) | |
301 { | |
302 if (!mw->menu.old_stack) | |
303 { | |
304 mw->menu.old_stack_length = max (10, n); | |
305 mw->menu.old_stack = | |
306 (widget_value**)XtCalloc (mw->menu.old_stack_length, | |
307 sizeof (widget_value*)); | |
308 } | |
309 else if (mw->menu.old_stack_length < n) | |
310 { | |
311 while (mw->menu.old_stack_length < n) | |
312 mw->menu.old_stack_length *= 2; | |
313 | |
314 mw->menu.old_stack = | |
315 (widget_value**)XtRealloc ((char *)mw->menu.old_stack, | |
316 mw->menu.old_stack_length * | |
317 sizeof (widget_value*)); | |
318 } | |
319 } | |
320 | |
321 static Boolean | |
322 close_to_reference_time (Widget w, Time reference_time, XEvent *ev) | |
323 { | |
324 return | |
325 reference_time && | |
647 | 326 ((int) (ev->xbutton.time - reference_time) < |
327 XtGetMultiClickTime (XtDisplay (w))); | |
428 | 328 } |
329 | |
330 /* Size code */ | |
331 static int | |
332 string_width (XlwMenuWidget mw, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
333 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 334 XmString s |
335 #else | |
336 char *s | |
337 #endif | |
338 ) | |
339 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
340 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 341 Dimension width, height; |
342 XmStringExtent (mw->menu.font_list, s, &width, &height); | |
343 return width; | |
344 #else | |
345 # ifdef USE_XFONTSET | |
346 XRectangle ri, rl; | |
347 XmbTextExtents (mw->menu.font_set, s, strlen (s), &ri, &rl); | |
348 return rl.width; | |
349 # else | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
350 #ifdef HAVE_XFT_MENUBARS |
3094 | 351 XGlyphInfo glyphinfo; |
3374 | 352 XftTextExtents8 (XtDisplay (mw), mw->menu.renderFont, (FcChar8 *) s, |
353 strlen (s), &glyphinfo); | |
3094 | 354 return glyphinfo.xOff; |
355 #else | |
428 | 356 XCharStruct xcs; |
357 int drop; | |
358 XTextExtents (mw->menu.font, s, strlen (s), &drop, &drop, &drop, &xcs); | |
359 return xcs.width; | |
3094 | 360 #endif |
428 | 361 # endif /* USE_XFONTSET */ |
362 #endif | |
363 } | |
364 | |
365 static char massaged_resource_char[256]; | |
366 | |
367 static void | |
368 initialize_massaged_resource_char (void) | |
369 { | |
370 int j; | |
371 for (j = 0; j < (int) sizeof (massaged_resource_char); j++) | |
372 { | |
373 if ((j >= 'a' && j <= 'z') || | |
374 (j >= 'A' && j <= 'Z') || | |
375 (j >= '0' && j <= '9') || | |
376 (j == '_') || | |
377 (j >= 0xa0)) | |
378 massaged_resource_char[j] = (char) j; | |
379 } | |
380 massaged_resource_char ['_'] = '_'; | |
381 massaged_resource_char ['+'] = 'P'; /* Convert C++ to cPP */ | |
382 massaged_resource_char ['.'] = '_'; /* Convert Buffers... to buffers___ */ | |
383 } | |
384 | |
385 static int | |
386 string_width_u (XlwMenuWidget mw, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
387 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 388 XmString string |
389 #else | |
390 char *string | |
391 #endif | |
392 ) | |
393 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
394 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 395 Dimension width, height; |
396 XmString newstring; | |
397 #else | |
398 # ifdef USE_XFONTSET | |
399 XRectangle ri, rl; | |
400 # else /* ! USE_XFONTSET */ | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
401 #ifdef HAVE_XFT_MENUBARS |
3094 | 402 XGlyphInfo glyphinfo; |
403 #else | |
428 | 404 XCharStruct xcs; |
405 int drop; | |
3094 | 406 #endif |
428 | 407 # endif |
408 #endif | |
409 char* newchars; | |
410 int charslength; | |
411 char *chars; | |
412 int i, j; | |
413 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
414 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 415 chars = ""; |
416 if (!XmStringGetLtoR (string, XmFONTLIST_DEFAULT_TAG, &chars)) | |
417 chars = ""; | |
418 #else | |
419 chars = string; | |
420 #endif | |
421 charslength = strlen (chars); | |
422 newchars = (char *) alloca (charslength + 1); | |
423 | |
424 for (i = j = 0; chars[i] && (j < charslength); i++) | |
425 if (chars[i]=='%'&&chars[i+1]=='_') | |
426 i++; | |
427 else | |
428 newchars[j++] = chars[i]; | |
429 newchars[j] = '\0'; | |
430 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
431 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 432 newstring = XmStringLtoRCreate (newchars, XmFONTLIST_DEFAULT_TAG); |
433 XmStringExtent (mw->menu.font_list, newstring, &width, &height); | |
434 XmStringFree (newstring); | |
435 XtFree (chars); | |
436 return width; | |
437 #else | |
438 # ifdef USE_XFONTSET | |
439 XmbTextExtents (mw->menu.font_set, newchars, j, &ri, &rl); | |
440 return rl.width; | |
441 # else /* ! USE_XFONTSET */ | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
442 #ifdef HAVE_XFT_MENUBARS |
3374 | 443 XftTextExtents8 (XtDisplay (mw), mw->menu.renderFont, (FcChar8 *) newchars, |
444 j, &glyphinfo); | |
3094 | 445 return glyphinfo.xOff; |
446 #else | |
428 | 447 XTextExtents (mw->menu.font, newchars, j, &drop, &drop, &drop, &xcs); |
448 return xcs.width; | |
3094 | 449 #endif |
428 | 450 # endif /* USE_XFONTSET */ |
451 #endif | |
452 } | |
453 | |
454 static void | |
442 | 455 massage_resource_name (const char *in, char *out) |
428 | 456 { |
457 /* Turn a random string into something suitable for using as a resource. | |
458 For example: | |
459 | |
460 "Kill Buffer" -> "killBuffer" | |
461 "Find File..." -> "findFile___" | |
462 "Search and Replace..." -> "searchAndReplace___" | |
463 "C++ Mode Commands" -> "cppModeCommands" | |
464 | |
465 Valid characters in a resource NAME component are: a-zA-Z0-9_ | |
466 */ | |
467 | |
468 #ifdef PRINT_XLWMENU_RESOURCE_CONVERSIONS | |
469 /* Compile with -DPRINT_XLWMENU_RESOURCE_CONVERSIONS to generate a | |
470 translation file for menu localizations. */ | |
471 char *save_in = in, *save_out = out; | |
472 #endif | |
473 | |
474 Boolean firstp = True; | |
475 while (*in) | |
476 { | |
442 | 477 if (*in == '%' && *(in + 1) == '_') |
478 in += 2; | |
479 else | |
428 | 480 { |
442 | 481 char ch; |
482 | |
483 if (*in == '%' && *(in + 1) == '%') | |
484 in++; | |
485 ch = massaged_resource_char[(unsigned char) *in++]; | |
486 if (ch) | |
487 { | |
488 int int_ch = (int) (unsigned char) ch; | |
489 *out++ = firstp ? tolower (int_ch) : toupper (int_ch); | |
490 firstp = False; | |
491 while ((ch = massaged_resource_char[(unsigned char) *in++]) | |
492 != '\0') | |
493 *out++ = ch; | |
494 if (!*(in-1)) /* Overshot the NULL byte? */ | |
495 break; | |
496 } | |
428 | 497 } |
498 } | |
499 *out = 0; | |
500 | |
501 #ifdef PRINT_XLWMENU_RESOURCE_CONVERSIONS | |
502 printf ("! Emacs*XlwMenu.%s.labelString:\t%s\n", save_out, save_in); | |
503 printf ( "Emacs*XlwMenu.%s.labelString:\n", save_out); | |
504 #endif | |
505 } | |
506 | |
507 static XtResource | |
508 nameResource[] = | |
509 { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
510 { (String) "labelString", (String) "LabelString", XtRString, sizeof(String), |
428 | 511 0, XtRImmediate, 0 } |
512 }; | |
513 | |
442 | 514 /* This function searches STRING for parameter inserts of the form: |
515 %[padding]1 | |
516 padding is either space (' ') or dash ('-') meaning | |
517 padding to the left or right of the inserted parameter. | |
518 In essence, all %1 strings are replaced by VALUE in the return value. | |
519 The caller is expected to free the return value using XtFree(). | |
520 %% means insert one % (like printf). | |
521 %1 means insert VALUE. | |
522 %-1 means insert VALUE followed by one space. The latter is | |
523 not inserted if VALUE is a zero length string. | |
524 */ | |
428 | 525 static char* |
442 | 526 parameterize_string (const char *string, const char *value) |
428 | 527 { |
442 | 528 const char *percent; |
428 | 529 char *result; |
530 unsigned int done = 0; | |
531 unsigned int ntimes; | |
532 | |
533 if (!string) | |
534 { | |
535 result = XtMalloc(1); | |
536 result[0] = '\0'; | |
442 | 537 return result; |
428 | 538 } |
539 | |
540 if (!value) | |
541 value = ""; | |
542 | |
442 | 543 for (ntimes = 1, percent = string; |
544 (percent = strchr (percent, '%')); | |
428 | 545 ntimes++) |
442 | 546 percent++; |
428 | 547 |
548 result = XtMalloc ((ntimes * strlen(value)) + strlen(string) + 4); | |
549 result[0] = '\0'; | |
550 | |
442 | 551 while ((percent = strchr (string, '%'))) |
428 | 552 { |
553 unsigned int left_pad; | |
554 unsigned int right_pad; | |
442 | 555 const char *p; |
428 | 556 |
557 if (percent[1] == '%') | |
558 { /* it's a real % */ | |
559 strncat (result, string, 1 + percent - string); /* incl % */ | |
560 string = &percent[2]; /* after the second '%' */ | |
561 continue; /* with the while() loop */ | |
562 } | |
563 | |
564 left_pad = 0; | |
565 right_pad = 0; | |
566 | |
567 for (p = &percent[1]; /* test *p inside the loop */ ; p++) | |
568 { | |
569 if (*p == ' ') | |
570 { /* left pad */ | |
571 left_pad++; | |
572 } | |
573 else if (*p == '-') | |
574 { /* right pad */ | |
575 right_pad++; | |
576 } | |
577 else if (*p == '1') | |
578 { /* param and terminator */ | |
579 strncat (result, string, percent - string); | |
580 if (value[0] != '\0') | |
581 { | |
582 unsigned int i; | |
583 for (i = 0; i < left_pad; i++) | |
584 strcat (result, " "); | |
585 strcat (result, value); | |
586 for (i = 0; i < right_pad; i++) | |
587 strcat (result, " "); | |
588 } | |
589 string = &p[1]; /* after the '1' */ | |
590 done++; /* no need to do old way */ | |
591 break; /* out of for() loop */ | |
592 } | |
593 else | |
594 { /* bogus, copy the format as is */ | |
595 /* out of for() loop */ | |
596 strncat (result, string, 1 + p - string); | |
597 string = (*p ? &p[1] : p); | |
598 break; | |
599 } | |
600 } | |
601 } | |
602 | |
603 /* Copy the tail of the string */ | |
604 strcat (result, string); | |
605 | |
606 /* If we have not processed a % string, and we have a value, tail it. */ | |
607 if (!done && value[0] != '\0') | |
608 { | |
609 strcat (result, " "); | |
610 strcat (result, value); | |
611 } | |
612 | |
613 return result; | |
614 } | |
615 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
616 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 617 |
618 static XmString | |
619 resource_widget_value (XlwMenuWidget mw, widget_value *val) | |
620 { | |
621 if (!val->toolkit_data) | |
622 { | |
623 char *resourced_name = NULL; | |
624 char *converted_name, *str; | |
625 XmString complete_name; | |
626 char massaged_name [1024]; | |
627 | |
628 if (mw->menu.lookup_labels) | |
629 { | |
630 /* Convert value style name into resource style name. | |
631 eg: "Free Willy" becomes "freeWilly" */ | |
632 massage_resource_name (val->name, massaged_name); | |
633 | |
634 /* If we have a value (parameter) see if we can find a "Named" | |
635 resource. */ | |
636 if (val->value) | |
637 { | |
638 char named_name[1024]; | |
639 sprintf (named_name, "%sNamed", massaged_name); | |
640 XtGetSubresources ((Widget) mw, | |
641 (XtPointer) &resourced_name, | |
642 named_name, named_name, | |
643 nameResource, 1, NULL, 0); | |
644 } | |
645 | |
646 /* If nothing yet, try to load from the massaged name. */ | |
647 if (!resourced_name) | |
648 { | |
649 XtGetSubresources ((Widget) mw, | |
650 (XtPointer) &resourced_name, | |
651 massaged_name, massaged_name, | |
652 nameResource, 1, NULL, 0); | |
653 } | |
654 } /* if (mw->menu.lookup_labels) */ | |
655 | |
656 /* Still nothing yet, use the name as the value. */ | |
657 if (!resourced_name) | |
658 resourced_name = val->name; | |
659 | |
660 /* Parameterize the string. */ | |
661 converted_name = parameterize_string (resourced_name, val->value); | |
662 | |
663 /* nuke newline characters to prevent menubar screwups */ | |
664 for ( str = converted_name ; *str ; str++ ) | |
665 { | |
666 if (str[0] == '\n') str[0] = ' '; | |
667 } | |
668 | |
669 /* Improve OSF's bottom line. */ | |
670 #if (XmVersion >= 1002) | |
671 complete_name = XmStringCreateLocalized (converted_name); | |
672 #else | |
673 complete_name = XmStringCreateLtoR (converted_name, | |
674 XmSTRING_DEFAULT_CHARSET); | |
675 #endif | |
676 XtFree (converted_name); | |
677 | |
678 val->toolkit_data = complete_name; | |
679 val->free_toolkit_data = True; | |
680 } | |
681 return (XmString) val->toolkit_data; | |
682 } | |
683 | |
684 /* Unused */ | |
685 #if 0 | |
442 | 686 /* These two routines should be a separate file..djw */ |
428 | 687 static char * |
688 xlw_create_localized_string (Widget w, | |
689 char *name, | |
690 char **args, | |
691 unsigned int nargs) | |
692 { | |
693 char *string = NULL; | |
694 char *arg = NULL; | |
695 | |
696 if (nargs > 0) | |
697 arg = args[0]; | |
698 | |
699 XtGetSubresources (w, | |
700 (XtPointer)&string, | |
701 name, | |
702 name, | |
703 nameResource, 1, | |
704 NULL, 0); | |
705 | |
706 if (!string) | |
707 string = name; | |
708 | |
709 return parameterize_string (string, arg); | |
710 } | |
711 | |
712 static XmString | |
713 xlw_create_localized_xmstring (Widget w, | |
714 char *name, | |
715 char **args, | |
716 unsigned int nargs) | |
717 { | |
718 char * string = xlw_create_localized_string (w, name, args, nargs); | |
719 XmString xm_string = XmStringCreateLtoR (string, XmSTRING_DEFAULT_CHARSET); | |
720 XtFree (string); | |
721 return xm_string; | |
722 } | |
723 #endif /* 0 */ | |
724 | |
725 #else /* !Motif */ | |
726 | |
727 static char* | |
728 resource_widget_value (XlwMenuWidget mw, widget_value *val) | |
729 { | |
730 if (!val->toolkit_data) | |
731 { | |
732 char *resourced_name = NULL; | |
733 char *complete_name; | |
734 char massaged_name [1024]; | |
735 | |
736 if (mw->menu.lookup_labels) | |
737 { | |
738 massage_resource_name (val->name, massaged_name); | |
739 | |
740 XtGetSubresources ((Widget) mw, | |
741 (XtPointer) &resourced_name, | |
742 massaged_name, massaged_name, | |
743 nameResource, 1, NULL, 0); | |
744 } | |
745 if (!resourced_name) | |
746 resourced_name = val->name; | |
747 | |
748 complete_name = parameterize_string (resourced_name, val->value); | |
749 | |
750 val->toolkit_data = complete_name; | |
751 /* nuke newline characters to prevent menubar screwups */ | |
752 for ( ; *complete_name ; complete_name++ ) | |
753 { | |
754 if (complete_name[0] == '\n') | |
755 complete_name[0] = ' '; | |
756 } | |
757 val->free_toolkit_data = True; | |
758 } | |
759 return (char *) val->toolkit_data; | |
760 } | |
761 | |
762 #endif /* !Motif */ | |
763 | |
3094 | 764 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ |
765 ? ((unsigned long) (x)) : ((unsigned long) (y))) | |
766 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
767 #ifdef HAVE_XFT_MENUBARS |
3094 | 768 static int |
769 x_xft_text_width (Display *dpy, XftFont *xft_font, char *run, int len) | |
770 { | |
771 static XGlyphInfo glyphinfo; | |
772 | |
773 XftTextExtents8 (dpy, | |
774 xft_font, | |
3374 | 775 (FcChar8 *) run, len, &glyphinfo); |
3094 | 776 return glyphinfo.xOff; |
777 } | |
778 #endif | |
779 | |
428 | 780 /* Code for drawing strings. */ |
781 static void | |
782 string_draw (XlwMenuWidget mw, | |
783 Window window, | |
784 int x, int y, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
785 #ifdef HAVE_XFT_MENUBARS |
3094 | 786 XftColor *color, |
787 XftColor *colorBg, | |
788 #else | |
428 | 789 GC gc, |
3094 | 790 #endif |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
791 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 792 XmString string |
793 #else | |
794 char *string | |
795 #endif | |
796 ) | |
797 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
798 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 799 XmStringDraw (XtDisplay (mw), window, |
800 mw->menu.font_list, | |
801 string, gc, | |
802 x, y, | |
803 1000, /* ???? width */ | |
804 XmALIGNMENT_BEGINNING, | |
805 0, /* ???? layout_direction */ | |
806 0); | |
807 #else | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
808 # ifdef HAVE_XFT_MENUBARS |
3094 | 809 Display *display = XtDisplay (mw); |
810 Visual *visual = DefaultVisualOfScreen (XtScreen (mw)); | |
811 Colormap cmap = mw->core.colormap; | |
812 XftDraw *xftDraw = XftDrawCreate (display, window, visual, cmap); | |
813 XftFont *renderFont = mw->menu.renderFont; | |
814 /* draw background rect */ | |
815 XftDrawRect (xftDraw, colorBg, | |
816 x, y, | |
817 x_xft_text_width (display, renderFont, string, strlen (string)), | |
818 renderFont->ascent + renderFont->descent); /* XXX */ | |
819 /* draw text */ | |
3374 | 820 XftDrawString8 (xftDraw, color, renderFont, x, y + mw->menu.font_ascent, |
821 (FcChar8 *) string, strlen (string)); | |
3094 | 822 XftDrawDestroy (xftDraw); |
823 # else | |
824 # ifdef USE_XFONTSET | |
428 | 825 XmbDrawString (XtDisplay (mw), window, mw->menu.font_set, gc, |
826 x, y + mw->menu.font_ascent, string, strlen (string)); | |
3094 | 827 # else |
428 | 828 XDrawString (XtDisplay (mw), window, gc, |
829 x, y + mw->menu.font_ascent, string, strlen (string)); | |
3094 | 830 # endif /* USE_XFONTSET */ |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
831 # endif /* HAVE_XFT_MENUBARS */ |
3094 | 832 #endif /* NEED_MOTIF */ |
428 | 833 } |
834 | |
835 static int | |
836 string_draw_range ( | |
837 XlwMenuWidget mw, | |
838 Window window, | |
839 int x, int y, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
840 #ifdef HAVE_XFT_MENUBARS |
3094 | 841 XftColor *color, |
842 XftColor *colorBg, | |
843 #else | |
428 | 844 GC gc, |
3094 | 845 #endif |
428 | 846 char *string, |
847 int start, | |
848 int end | |
849 ) | |
850 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
851 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 852 Dimension width, height; |
853 XmString newstring; | |
854 int c; | |
855 | |
856 if (end <= start) | |
857 return 0; | |
858 c = string[end]; | |
859 string[end] = '\0'; | |
860 newstring = XmStringLtoRCreate (&string[start], XmFONTLIST_DEFAULT_TAG); | |
861 XmStringDraw ( | |
862 XtDisplay (mw), window, | |
863 mw->menu.font_list, | |
864 newstring, gc, | |
865 x, y, | |
866 1000, /* ???? width */ | |
867 XmALIGNMENT_BEGINNING, | |
868 0, /* ???? layout_direction */ | |
869 0 | |
870 ); | |
871 XmStringExtent (mw->menu.font_list, newstring, &width, &height); | |
872 XmStringFree (newstring); | |
873 string[end] = c; | |
874 return width; | |
875 #else | |
876 # ifdef USE_XFONTSET | |
877 XRectangle ri, rl; | |
878 | |
879 if (end <= start) | |
880 return 0; | |
881 XmbDrawString ( | |
882 XtDisplay (mw), window, mw->menu.font_set, gc, | |
883 x, y + mw->menu.font_ascent, &string[start], end - start); | |
884 XmbTextExtents ( | |
885 mw->menu.font_set, &string[start], end - start, &ri, &rl); | |
886 return rl.width; | |
887 # else | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
888 #ifdef HAVE_XFT_MENUBARS |
3094 | 889 if (end <= start) |
890 return 0; | |
891 else | |
892 { | |
893 XGlyphInfo glyphinfo; | |
894 Display *display = XtDisplay (mw); | |
895 Visual *visual = DefaultVisualOfScreen (XtScreen (mw)); | |
896 Colormap cmap = mw->core.colormap; | |
897 XftFont *renderFont = mw->menu.renderFont; | |
898 /* #### should use parent frame's .xftDraw? */ | |
899 XftDraw *xftDraw = XftDrawCreate (display, window, visual, cmap); | |
900 /* draw background rect */ | |
901 XftDrawRect (xftDraw, colorBg, | |
902 x, y, | |
903 x_xft_text_width (display, | |
904 renderFont, &string[start], end - start), | |
905 renderFont->ascent + renderFont->descent); /* XXX */ | |
906 /* draw text */ | |
907 XftDrawString8 (xftDraw, color, renderFont, | |
908 x, y + mw->menu.font_ascent, | |
3374 | 909 (FcChar8 *) &string[start], end - start); |
3094 | 910 |
3374 | 911 XftTextExtents8 (display, renderFont, (FcChar8 *) &string[start], |
912 end - start, &glyphinfo); | |
3094 | 913 |
914 /* #### should use parent frame's .xftDraw */ | |
915 XftDrawDestroy (xftDraw); | |
916 return glyphinfo.xOff; | |
917 } | |
918 #else | |
428 | 919 XCharStruct xcs; |
920 int drop; | |
921 | |
922 if (end <= start) | |
923 return 0; | |
3094 | 924 XDrawString ( /* XXX */ |
428 | 925 XtDisplay (mw), window, gc, |
926 x, y + mw->menu.font_ascent, &string[start], end - start); | |
927 XTextExtents ( | |
928 mw->menu.font, &string[start], end - start, | |
929 &drop, &drop, &drop, &xcs); | |
930 return xcs.width; | |
3094 | 931 #endif |
428 | 932 # endif |
933 #endif | |
934 } | |
935 | |
936 static void | |
937 string_draw_u (XlwMenuWidget mw, | |
938 Window window, | |
939 int x, int y, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
940 #ifdef HAVE_XFT_MENUBARS |
3094 | 941 XftColor *color, XftColor *colorBg, GC gc, |
942 #else | |
428 | 943 GC gc, |
3094 | 944 #endif |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
945 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 946 XmString string |
947 #else | |
948 char *string | |
949 #endif | |
950 ) | |
951 { | |
952 int i, s = 0; | |
953 char *chars; | |
954 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
955 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 956 chars = ""; |
957 if (!XmStringGetLtoR (string, XmFONTLIST_DEFAULT_TAG, &chars)) | |
958 chars = ""; | |
959 #else | |
960 chars = string; | |
961 #endif | |
962 for (i=0; chars[i]; ++i) { | |
963 if (chars[i] == '%' && chars[i+1] == '_') { | |
964 int w; | |
965 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
966 #ifdef HAVE_XFT_MENUBARS |
3094 | 967 x += string_draw_range (mw, window, x, y, color, colorBg, chars, s, i); |
968 w = string_draw_range (mw, window, x, y, color, colorBg, chars, i+2, i+3); | |
969 #else | |
428 | 970 x += string_draw_range (mw, window, x, y, gc, chars, s, i); |
971 w = string_draw_range (mw, window, x, y, gc, chars, i+2, i+3); | |
3094 | 972 #endif |
428 | 973 |
974 /* underline next character */ | |
975 XDrawLine (XtDisplay (mw), window, gc, x - 1, | |
976 y + mw->menu.font_ascent + 1, | |
977 x + w - 1, y + mw->menu.font_ascent + 1 ); | |
978 x += w; | |
979 s = i + 3; | |
980 i += 2; | |
981 } | |
982 } | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
983 #ifdef HAVE_XFT_MENUBARS |
3094 | 984 x += string_draw_range (mw, window, x, y, color, colorBg, chars, s, i); |
985 #else | |
428 | 986 x += string_draw_range (mw, window, x, y, gc, chars, s, i); |
3094 | 987 #endif |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
988 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 989 XtFree (chars); |
990 #endif | |
991 } | |
992 | |
3094 | 993 static void /* XXX */ |
994 binding_draw (XlwMenuWidget mw, Window w, int x, int y, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
995 #ifdef HAVE_XFT_MENUBARS |
3094 | 996 XftColor *color, |
997 XftColor *colorBg, | |
998 #else | |
999 GC gc, | |
1000 #endif | |
1001 char *value) | |
428 | 1002 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1003 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 1004 XmString xm_value = XmStringCreateLtoR(value, XmSTRING_DEFAULT_CHARSET); |
1005 string_draw (mw, w, x, y, gc, xm_value); | |
1006 XmStringFree (xm_value); | |
1007 #else | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1008 #ifdef HAVE_XFT_MENUBARS |
3094 | 1009 string_draw (mw, w, x, y, color, colorBg, value); |
1010 #else | |
428 | 1011 string_draw (mw, w, x, y, gc, value); |
1012 #endif | |
3094 | 1013 #endif |
428 | 1014 } |
1015 | |
1016 /* Low level code for drawing 3-D edges. */ | |
1017 static void | |
1018 shadow_rectangle_draw (Display *dpy, | |
1019 Window window, | |
1020 GC top_gc, | |
1021 GC bottom_gc, | |
1022 int x, int y, | |
1023 unsigned int width, | |
1024 unsigned int height, | |
1025 unsigned int thickness) | |
1026 { | |
1027 XPoint points [4]; | |
1028 | |
1029 if (!thickness) | |
1030 return; | |
1031 | |
1032 points [0].x = x; | |
1033 points [0].y = y; | |
1034 points [1].x = x + width; | |
1035 points [1].y = y; | |
1036 points [2].x = x + width - thickness; | |
1037 points [2].y = y + thickness; | |
1038 points [3].x = x; | |
1039 points [3].y = y + thickness; | |
1040 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin); | |
1041 points [0].x = x; | |
1042 points [0].y = y + thickness; | |
1043 points [1].x = x; | |
1044 points [1].y = y + height; | |
1045 points [2].x = x + thickness; | |
1046 points [2].y = y + height - thickness; | |
1047 points [3].x = x + thickness; | |
1048 points [3].y = y + thickness; | |
1049 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin); | |
1050 points [0].x = x + width; | |
1051 points [0].y = y; | |
1052 points [1].x = x + width - thickness; | |
1053 points [1].y = y + thickness; | |
1054 points [2].x = x + width - thickness; | |
1055 points [2].y = y + height - thickness; | |
1056 points [3].x = x + width; | |
1057 points [3].y = y + height - thickness; | |
1058 XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin); | |
1059 points [0].x = x; | |
1060 points [0].y = y + height; | |
1061 points [1].x = x + width; | |
1062 points [1].y = y + height; | |
1063 points [2].x = x + width; | |
1064 points [2].y = y + height - thickness; | |
1065 points [3].x = x + thickness; | |
1066 points [3].y = y + height - thickness; | |
1067 XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin); | |
1068 } | |
1069 | |
1070 typedef enum e_shadow_type | |
1071 { | |
1072 /* these are Motif compliant */ | |
1073 SHADOW_BACKGROUND, | |
1074 SHADOW_OUT, | |
1075 SHADOW_IN, | |
1076 SHADOW_ETCHED_OUT, | |
1077 SHADOW_ETCHED_IN, | |
1078 SHADOW_ETCHED_OUT_DASH, | |
1079 SHADOW_ETCHED_IN_DASH, | |
1080 SHADOW_SINGLE_LINE, | |
1081 SHADOW_DOUBLE_LINE, | |
1082 SHADOW_SINGLE_DASHED_LINE, | |
1083 SHADOW_DOUBLE_DASHED_LINE, | |
1084 SHADOW_NO_LINE, | |
1085 /* these are all non-Motif */ | |
1086 SHADOW_DOUBLE_ETCHED_OUT, | |
1087 SHADOW_DOUBLE_ETCHED_IN, | |
1088 SHADOW_DOUBLE_ETCHED_OUT_DASH, | |
1089 SHADOW_DOUBLE_ETCHED_IN_DASH | |
1090 } shadow_type; | |
1091 | |
1092 static void | |
1093 shadow_draw (XlwMenuWidget mw, | |
1094 Window window, | |
1095 int x, int y, | |
1096 unsigned int width, | |
1097 unsigned int height, | |
1098 shadow_type type) | |
1099 { | |
1100 Display *dpy = XtDisplay (mw); | |
1101 GC top_gc; | |
1102 GC bottom_gc; | |
1103 int thickness = mw->menu.shadow_thickness; | |
1104 #if 0 | |
1105 XPoint points [4]; | |
1106 #endif /* 0 */ | |
1107 Boolean etched = False; | |
1108 | |
1109 switch (type) | |
1110 { | |
1111 case SHADOW_BACKGROUND: | |
1112 top_gc = bottom_gc = mw->menu.background_gc; | |
1113 break; | |
1114 case SHADOW_ETCHED_IN: | |
1115 top_gc = mw->menu.shadow_bottom_gc; | |
1116 bottom_gc = mw->menu.shadow_top_gc; | |
1117 etched = True; | |
1118 break; | |
1119 case SHADOW_ETCHED_OUT: | |
1120 top_gc = mw->menu.shadow_top_gc; | |
1121 bottom_gc = mw->menu.shadow_bottom_gc; | |
1122 etched = True; | |
1123 break; | |
1124 case SHADOW_IN: | |
1125 top_gc = mw->menu.shadow_bottom_gc; | |
1126 bottom_gc = mw->menu.shadow_top_gc; | |
1127 break; | |
1128 case SHADOW_OUT: | |
1129 default: | |
1130 top_gc = mw->menu.shadow_top_gc; | |
1131 bottom_gc = mw->menu.shadow_bottom_gc; | |
1132 break; | |
1133 } | |
1134 | |
1135 if (etched) | |
1136 { | |
1137 unsigned int half = thickness/2; | |
1138 shadow_rectangle_draw (dpy, | |
1139 window, | |
1140 top_gc, | |
1141 top_gc, | |
1142 x, y, | |
1143 width - half, height - half, | |
1144 thickness - half); | |
1145 shadow_rectangle_draw (dpy, | |
1146 window, | |
1147 bottom_gc, | |
1148 bottom_gc, | |
1149 x + half, y + half, | |
1150 width - half , height - half, | |
1151 half); | |
1152 } | |
1153 else | |
1154 { | |
1155 shadow_rectangle_draw (dpy, | |
1156 window, | |
1157 top_gc, | |
1158 bottom_gc, | |
1159 x, y, | |
1160 width, height, | |
1161 thickness); | |
1162 } | |
1163 } | |
1164 | |
1165 static void | |
1166 arrow_decoration_draw (XlwMenuWidget mw, | |
1167 Window window, | |
1168 int x, int y, | |
1169 unsigned int width, | |
1170 Boolean raised) | |
1171 { | |
1172 Display *dpy = XtDisplay (mw); | |
1173 GC top_gc; | |
1174 GC bottom_gc; | |
1175 GC select_gc; | |
1176 int thickness = mw->menu.shadow_thickness; | |
1177 XPoint points [4]; | |
1178 int half_width; | |
1179 int length = (int)((double)width * 0.87); | |
1180 int thick_med = (int)((double)thickness * 1.73); | |
1181 | |
1182 if (width & 0x1) | |
1183 half_width = width/2 + 1; | |
1184 else | |
1185 half_width = width/2; | |
1186 | |
1187 select_gc = mw->menu.background_gc; | |
1188 | |
1189 if (raised) | |
1190 { | |
1191 top_gc = mw->menu.shadow_bottom_gc; | |
1192 bottom_gc = mw->menu.shadow_top_gc; | |
1193 } | |
1194 else | |
1195 { | |
1196 top_gc = mw->menu.shadow_top_gc; | |
1197 bottom_gc = mw->menu.shadow_bottom_gc; | |
1198 } | |
1199 | |
1200 /* Fill internal area. We do this first so that the borders have a | |
1201 nice sharp edge. */ | |
1202 points [0].x = x + thickness; | |
1203 points [0].y = y + thickness; | |
1204 points [1].x = x + length - thickness; | |
1205 points [1].y = y + half_width; | |
1206 points [2].x = x + length - thickness; | |
1207 points [2].y = y + half_width + thickness; | |
1208 points [3].x = x + thickness; | |
1209 points [3].y = y + width - thickness; | |
1210 | |
1211 XFillPolygon (dpy, | |
1212 window, | |
1213 select_gc, | |
1214 points, | |
1215 4, | |
1216 Convex, | |
1217 CoordModeOrigin); | |
1218 | |
1219 /* left border */ | |
1220 points [0].x = x; | |
1221 points [0].y = y; | |
1222 points [1].x = x + thickness; | |
1223 points [1].y = y + thick_med; | |
1224 points [2].x = x + thickness; | |
1225 points [2].y = y + width - thick_med; | |
1226 points [3].x = x; | |
1227 points [3].y = y + width; | |
1228 | |
1229 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin); | |
1230 | |
1231 /* top border */ | |
1232 points [0].x = x; | |
1233 points [0].y = y + width; | |
1234 points [1].x = x + length; | |
1235 points [1].y = y + half_width; | |
1236 points [2].x = x + length - (thickness + thickness); | |
1237 points [2].y = y + half_width; | |
1238 points [3].x = x + thickness; | |
1239 points [3].y = y + width - thick_med; | |
1240 | |
1241 XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin); | |
1242 | |
1243 /* bottom shadow */ | |
1244 points [0].x = x; | |
1245 points [0].y = y; | |
1246 points [1].x = x + length; | |
1247 points [1].y = y + half_width; | |
1248 points [2].x = x + length - (thickness + thickness); | |
1249 points [2].y = y + half_width; | |
1250 points [3].x = x + thickness; | |
1251 points [3].y = y + thick_med; | |
1252 | |
1253 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin); | |
1254 } | |
1255 | |
1256 static void | |
1257 toggle_decoration_draw (XlwMenuWidget mw, | |
1258 Window window, | |
1259 int x, int y, | |
1260 unsigned int width, | |
1261 Boolean set) | |
1262 { | |
1263 Display *dpy = XtDisplay (mw); | |
1264 int thickness = mw->menu.shadow_thickness; | |
1265 shadow_type type; | |
1266 GC select_gc = mw->menu.select_gc; | |
1267 | |
1268 if (set) | |
1269 type = SHADOW_IN; | |
1270 else | |
1271 type = SHADOW_OUT; | |
1272 | |
1273 /* Fill internal area. */ | |
1274 if (set) | |
1275 XFillRectangle (dpy, | |
1276 window, | |
1277 select_gc, | |
1278 x + thickness, | |
1279 y + thickness, | |
1280 width - (2*thickness), | |
1281 width - (2*thickness)); | |
1282 | |
1283 shadow_draw (mw, window, x, y, width, width, type); | |
1284 } | |
1285 | |
1286 static void | |
1287 radio_decoration_draw (XlwMenuWidget mw, | |
1288 Window window, | |
1289 int x, int y, | |
1290 unsigned int width, | |
1291 Boolean enabled) | |
1292 { | |
1293 Display *dpy = XtDisplay (mw); | |
1294 GC top_gc; | |
1295 GC bottom_gc; | |
1296 GC select_gc = mw->menu.select_gc; | |
1297 int thickness = mw->menu.shadow_thickness; | |
1298 XPoint points[6]; | |
1299 int half_width; | |
1300 #if 0 | |
1301 int npoints; | |
1302 #endif /* 0 */ | |
1303 | |
1304 if (width & 0x1) | |
1305 width++; | |
1306 | |
1307 half_width = width/2; | |
1308 | |
1309 if (enabled) | |
1310 { | |
1311 top_gc = mw->menu.shadow_bottom_gc; | |
1312 bottom_gc = mw->menu.shadow_top_gc; | |
1313 } | |
1314 else | |
1315 { | |
1316 top_gc = mw->menu.shadow_top_gc; | |
1317 bottom_gc = mw->menu.shadow_bottom_gc; | |
1318 } | |
1319 | |
1320 #if 1 | |
1321 /* Draw the bottom first, just in case the regions overlap. | |
1322 The top should cast the longer shadow. */ | |
1323 points [0].x = x; /* left corner */ | |
1324 points [0].y = y + half_width; | |
1325 points [1].x = x + half_width; /* bottom corner */ | |
1326 points [1].y = y + width; | |
1327 points [2].x = x + half_width; /* bottom inside corner */ | |
1328 points [2].y = y + width - thickness; | |
1329 points [3].x = x + thickness; /* left inside corner */ | |
1330 points [3].y = y + half_width; | |
1331 | |
1332 XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin); | |
1333 | |
1334 points [0].x = x + half_width; /* bottom corner */ | |
1335 points [0].y = y + width; | |
1336 points [1].x = x + width; /* right corner */ | |
1337 points [1].y = y + half_width; | |
1338 points [2].x = x + width - thickness; /* right inside corner */ | |
1339 points [2].y = y + half_width; | |
1340 points [3].x = x + half_width; /* bottom inside corner */ | |
1341 points [3].y = y + width - thickness; | |
1342 | |
1343 XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin); | |
1344 | |
1345 points [0].x = x; /* left corner */ | |
1346 points [0].y = y + half_width; | |
1347 points [1].x = x + half_width; /* top corner */ | |
1348 points [1].y = y; | |
1349 points [2].x = x + half_width; /* top inside corner */ | |
1350 points [2].y = y + thickness; | |
1351 points [3].x = x + thickness; /* left inside corner */ | |
1352 points [3].y = y + half_width; | |
1353 | |
1354 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin); | |
1355 | |
1356 points [0].x = x + half_width; /* top corner */ | |
1357 points [0].y = y; | |
1358 points [1].x = x + width; /* right corner */ | |
1359 points [1].y = y + half_width; | |
1360 points [2].x = x + width - thickness; /* right inside corner */ | |
1361 points [2].y = y + half_width; | |
1362 points [3].x = x + half_width; /* top inside corner */ | |
1363 points [3].y = y + thickness; | |
1364 | |
1365 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin); | |
1366 #else | |
1367 /* Draw the bottom first, just in case the regions overlap. | |
1368 The top should cast the longer shadow. */ | |
1369 npoints = 0; | |
1370 points [npoints].x = x; /* left corner */ | |
1371 points [npoints++].y = y + half_width; | |
1372 points [npoints].x = x + half_width; /* bottom corner */ | |
1373 points [npoints++].y = y + width; | |
1374 points [npoints].x = x + width; /* right corner */ | |
1375 points [npoints++].y = y + half_width; | |
1376 points [npoints].x = x + width - thickness; /* right inside corner */ | |
1377 points [npoints++].y = y + half_width; | |
1378 points [npoints].x = x + half_width; /* bottom inside corner */ | |
1379 points [npoints++].y = y + width - thickness; | |
1380 points [npoints].x = x + thickness; /* left inside corner */ | |
1381 points [npoints++].y = y + half_width; | |
1382 | |
1383 XFillPolygon (dpy, window, bottom_gc, | |
1384 points, npoints, Nonconvex, CoordModeOrigin); | |
1385 | |
1386 npoints = 0; | |
1387 | |
1388 points [npoints].x = x; /* left corner */ | |
1389 points [npoints++].y = y + half_width; | |
1390 points [npoints].x = x + half_width; /* top corner */ | |
1391 points [npoints++].y = y; | |
1392 points [npoints].x = x + width; /* right corner */ | |
1393 points [npoints++].y = y + half_width; | |
1394 points [npoints].x = x + width - thickness; /* right inside corner */ | |
1395 points [npoints++].y = y + half_width; | |
1396 points [npoints].x = x + half_width; /* top inside corner */ | |
1397 points [npoints++].y = y + thickness; | |
1398 points [npoints].x = x + thickness; /* left inside corner */ | |
1399 points [npoints++].y = y + half_width; | |
1400 | |
1401 XFillPolygon (dpy, window, top_gc, points, npoints, Nonconvex, | |
1402 CoordModeOrigin); | |
1403 #endif | |
1404 | |
1405 | |
1406 /* Fill internal area. */ | |
1407 if (enabled) | |
1408 { | |
1409 points [0].x = x + thickness; | |
1410 points [0].y = y + half_width; | |
1411 points [1].x = x + half_width; | |
1412 points [1].y = y + thickness; | |
1413 points [2].x = x + width - thickness; | |
1414 points [2].y = y + half_width; | |
1415 points [3].x = x + half_width; | |
1416 points [3].y = y + width - thickness; | |
1417 XFillPolygon (dpy, | |
1418 window, | |
1419 select_gc, | |
1420 points, | |
1421 4, | |
1422 Convex, | |
1423 CoordModeOrigin); | |
1424 } | |
1425 } | |
1426 | |
1427 static void | |
1428 separator_decoration_draw (XlwMenuWidget mw, | |
1429 Window window, | |
1430 int x, int y, | |
1431 unsigned int width, | |
2286 | 1432 Boolean UNUSED (vertical), |
428 | 1433 shadow_type type) |
1434 { | |
1435 Display *dpy = XtDisplay (mw); | |
1436 GC top_gc; | |
1437 GC bottom_gc; | |
1438 unsigned int offset = 0; | |
1439 unsigned int num_separators = 1; | |
1440 unsigned int top_line_thickness = 0; | |
1441 unsigned int bottom_line_thickness = 0; | |
1442 Boolean dashed = False; | |
1443 | |
1444 switch (type) | |
1445 { | |
1446 case SHADOW_NO_LINE: /* nothing to do */ | |
1447 return; | |
1448 case SHADOW_DOUBLE_LINE: | |
1449 num_separators = 2; | |
1450 case SHADOW_SINGLE_LINE: | |
1451 top_gc = bottom_gc = mw->menu.foreground_gc; | |
1452 top_line_thickness = 1; | |
1453 break; | |
1454 case SHADOW_DOUBLE_DASHED_LINE: | |
1455 num_separators = 2; | |
1456 case SHADOW_SINGLE_DASHED_LINE: | |
1457 top_gc = bottom_gc = mw->menu.foreground_gc; | |
1458 top_line_thickness = 1; | |
1459 dashed = True; | |
1460 break; | |
1461 case SHADOW_DOUBLE_ETCHED_OUT_DASH: | |
1462 num_separators = 2; | |
1463 case SHADOW_ETCHED_OUT_DASH: | |
1464 top_gc = mw->menu.shadow_top_gc; | |
1465 bottom_gc = mw->menu.shadow_bottom_gc; | |
1466 top_line_thickness = mw->menu.shadow_thickness/2; | |
1467 bottom_line_thickness = mw->menu.shadow_thickness - top_line_thickness; | |
1468 dashed = True; | |
1469 break; | |
1470 case SHADOW_DOUBLE_ETCHED_IN_DASH: | |
1471 num_separators = 2; | |
1472 case SHADOW_ETCHED_IN_DASH: | |
1473 top_gc = mw->menu.shadow_bottom_gc; | |
1474 bottom_gc = mw->menu.shadow_top_gc; | |
1475 top_line_thickness = mw->menu.shadow_thickness/2; | |
1476 bottom_line_thickness = mw->menu.shadow_thickness - top_line_thickness; | |
1477 dashed = True; | |
1478 break; | |
1479 case SHADOW_DOUBLE_ETCHED_OUT: | |
1480 num_separators = 2; | |
1481 case SHADOW_ETCHED_OUT: | |
1482 top_gc = mw->menu.shadow_top_gc; | |
1483 bottom_gc = mw->menu.shadow_bottom_gc; | |
1484 top_line_thickness = mw->menu.shadow_thickness/2; | |
1485 bottom_line_thickness = mw->menu.shadow_thickness - top_line_thickness; | |
1486 break; | |
1487 case SHADOW_DOUBLE_ETCHED_IN: | |
1488 num_separators = 2; | |
1489 case SHADOW_ETCHED_IN: | |
1490 default: | |
1491 top_gc = mw->menu.shadow_bottom_gc; | |
1492 bottom_gc = mw->menu.shadow_top_gc; | |
1493 top_line_thickness = mw->menu.shadow_thickness/2; | |
1494 bottom_line_thickness = mw->menu.shadow_thickness - top_line_thickness; | |
1495 break; | |
1496 } | |
1497 | |
1498 if (dashed) | |
1499 { | |
1500 XGCValues values; | |
1501 values.line_style = LineOnOffDash; | |
1502 if (top_line_thickness > 0) | |
1503 XChangeGC (dpy, top_gc, GCLineStyle, &values); | |
1504 if (bottom_line_thickness > 0 && bottom_gc != top_gc) | |
1505 XChangeGC (dpy, bottom_gc, GCLineStyle, &values); | |
1506 } | |
1507 | |
1508 while (num_separators--) | |
1509 { | |
1510 unsigned int i; | |
1511 for (i = 0; i < top_line_thickness; i++) | |
1512 XDrawLine (dpy, window, top_gc, x, y + i, x + width, y + i); | |
1513 | |
1514 for (i = 0; i < bottom_line_thickness; i++) | |
1515 XDrawLine (dpy, window, bottom_gc, | |
1516 x, y + top_line_thickness + offset + i, | |
1517 x + width, y + top_line_thickness + offset + i); | |
1518 y += (top_line_thickness + offset + bottom_line_thickness + 1); | |
1519 } | |
1520 | |
1521 if (dashed) | |
1522 { | |
1523 XGCValues values; | |
1524 values.line_style = LineSolid; | |
1525 if (top_line_thickness > 0) | |
1526 XChangeGC (dpy, top_gc, GCLineStyle, &values); | |
1527 if (bottom_line_thickness > 0 && bottom_gc != top_gc) | |
1528 XChangeGC (dpy, bottom_gc, GCLineStyle, &values); | |
1529 } | |
1530 } | |
1531 | |
1532 #define SLOPPY_TYPES 0 /* 0=off, 1=error check, 2=easy to please */ | |
1533 #if SLOPPY_TYPES | |
1534 #if SLOPPY_TYPES < 2 | |
1535 | |
1536 static char *wv_types[] = | |
1537 { | |
1538 "UNSPECIFIED", | |
1539 "BUTTON", | |
1540 "TOGGLE", | |
1541 "RADIO", | |
1542 "TEXT", | |
1543 "SEPARATOR", | |
1544 "CASCADE", | |
1545 "PUSHRIGHT", | |
1546 "INCREMENTAL" | |
1547 }; | |
1548 | |
1549 static void | |
1550 print_widget_value (widget_value *wv, int just_one, int depth) | |
1551 { | |
1552 char d [200]; | |
1553 int i; | |
1554 for (i = 0; i < depth; i++) | |
1555 d[i] = ' '; | |
1556 d[depth]=0; | |
1557 if (!wv) | |
1558 { | |
1559 printf ("%s(null widget value pointer)\n", d); | |
1560 return; | |
1561 } | |
1562 printf ("%stype: %s\n", d, wv_types [wv->type]); | |
1563 #if 0 | |
1564 printf ("%sname: %s\n", d, (wv->name ? wv->name : "(null)")); | |
1565 #else | |
1566 if (wv->name) printf ("%sname: %s\n", d, wv->name); | |
1567 #endif | |
1568 if (wv->value) printf ("%svalue: %s\n", d, wv->value); | |
1569 if (wv->key) printf ("%skey: %s\n", d, wv->key); | |
1570 printf ("%senabled: %d\n", d, wv->enabled); | |
1571 if (wv->contents) | |
1572 { | |
1573 printf ("\n%scontents: \n", d); | |
1574 print_widget_value (wv->contents, 0, depth + 5); | |
1575 } | |
1576 if (!just_one && wv->next) | |
1577 { | |
1578 printf ("\n"); | |
1579 print_widget_value (wv->next, 0, depth); | |
1580 } | |
1581 } | |
1582 #endif /* SLOPPY_TYPES < 2 */ | |
1583 | |
1584 static Boolean | |
1585 all_dashes_p (char *s) | |
1586 { | |
1587 char *p; | |
1588 if (!s || s[0] == '\0') | |
1589 return False; | |
1590 for (p = s; *p == '-'; p++); | |
1591 | |
1592 if (*p == '!' || *p == '\0') | |
1593 return True; | |
1594 return False; | |
1595 } | |
1596 #endif /* SLOPPY_TYPES */ | |
1597 | |
1598 static widget_value_type | |
1599 menu_item_type (widget_value *val) | |
1600 { | |
1601 if (val->type != UNSPECIFIED_TYPE) | |
1602 return val->type; | |
1603 #if SLOPPY_TYPES | |
1604 else if (all_dashes_p (val->name)) | |
1605 return SEPARATOR_TYPE; | |
1606 else if (val->name && val->name[0] == '\0') /* push right */ | |
1607 return PUSHRIGHT_TYPE; | |
1608 else if (val->contents) /* cascade */ | |
1609 return CASCADE_TYPE; | |
1610 else if (val->call_data) /* push button */ | |
1611 return BUTTON_TYPE; | |
1612 else | |
1613 return TEXT_TYPE; | |
1614 #else | |
442 | 1615 else |
428 | 1616 abort(); |
1617 return UNSPECIFIED_TYPE; /* Not reached */ | |
1618 #endif | |
1619 } | |
1620 | |
1621 static void | |
1622 label_button_size (XlwMenuWidget mw, | |
1623 widget_value *val, | |
2286 | 1624 Boolean UNUSED (in_menubar), |
428 | 1625 unsigned int *toggle_width, |
1626 unsigned int *label_width, | |
1627 unsigned int *bindings_width, | |
1628 unsigned int *height) | |
1629 { | |
1630 *height = (mw->menu.font_ascent + mw->menu.font_descent + | |
1631 2 * mw->menu.vertical_margin + | |
1632 2 * mw->menu.shadow_thickness); | |
1633 /* no left column decoration */ | |
430 | 1634 *toggle_width = mw->menu.horizontal_margin + mw->menu.shadow_thickness; |
428 | 1635 |
1636 *label_width = string_width_u (mw, resource_widget_value (mw, val)); | |
1637 *bindings_width = mw->menu.horizontal_margin + mw->menu.shadow_thickness; | |
1638 } | |
1639 | |
1640 static void | |
1641 label_button_draw (XlwMenuWidget mw, | |
1642 widget_value *val, | |
1643 Boolean in_menubar, | |
1644 Boolean highlighted, | |
1645 Window window, | |
1646 int x, int y, | |
2286 | 1647 unsigned int UNUSED (width), |
1648 unsigned int UNUSED (height), | |
428 | 1649 unsigned int label_offset, |
2286 | 1650 unsigned int UNUSED (binding_tab)) |
428 | 1651 { |
1652 int y_offset = mw->menu.shadow_thickness + mw->menu.vertical_margin; | |
1653 GC gc; | |
1654 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1655 #ifdef HAVE_XFT_MENUBARS |
3094 | 1656 XftColor color, colorBg; |
1657 Display *display = XtDisplay (mw); | |
1658 Colormap cmap = mw->core.colormap; | |
1659 Visual *visual; | |
1660 int ignored, pixel, pixelBg; | |
1661 | |
1662 visual_info_from_widget ((Widget) mw, &visual, &ignored); | |
1663 #endif | |
1664 | |
428 | 1665 if (!label_offset) |
1666 label_offset = mw->menu.shadow_thickness + mw->menu.horizontal_margin; | |
1667 | |
3094 | 1668 if (highlighted && (in_menubar || val->contents)) |
1669 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1670 #ifdef HAVE_XFT_MENUBARS |
3094 | 1671 pixel = mw->menu.highlight_foreground; |
1672 pixelBg = mw->core.background_pixel; | |
1673 #endif | |
1674 gc = mw->menu.highlight_gc; | |
1675 } | |
428 | 1676 else if (in_menubar || val->contents) |
3094 | 1677 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1678 #ifdef HAVE_XFT_MENUBARS |
3094 | 1679 pixel = mw->menu.foreground; |
1680 pixelBg = mw->core.background_pixel; | |
1681 #endif | |
1682 gc = mw->menu.foreground_gc; | |
1683 } | |
428 | 1684 else |
3094 | 1685 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1686 #ifdef HAVE_XFT_MENUBARS |
3094 | 1687 pixel = mw->menu.title_foreground; |
1688 pixelBg = mw->core.background_pixel; | |
1689 #endif | |
1690 gc = mw->menu.title_gc; | |
1691 } | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1692 #ifdef HAVE_XFT_MENUBARS |
3094 | 1693 color = xft_convert_color (display, cmap, visual, pixel, 0); |
1694 colorBg = xft_convert_color (display, cmap, visual, pixelBg, 0); | |
1695 #endif | |
428 | 1696 |
1697 /* Draw the label string. */ | |
3094 | 1698 string_draw_u (mw, /* XXX */ |
1699 window, | |
1700 x + label_offset, y + y_offset, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1701 #ifdef HAVE_XFT_MENUBARS |
3094 | 1702 &color, &colorBg, gc, |
1703 #else | |
428 | 1704 gc, |
3094 | 1705 #endif |
428 | 1706 resource_widget_value (mw, val)); |
1707 } | |
1708 | |
1709 static void | |
1710 push_button_size (XlwMenuWidget mw, | |
1711 widget_value *val, | |
1712 Boolean in_menubar, | |
1713 unsigned int *toggle_width, | |
1714 unsigned int *label_width, | |
1715 unsigned int *bindings_width, | |
1716 unsigned int *height) | |
1717 { | |
1718 /* inherit */ | |
1719 label_button_size (mw, val, in_menubar, | |
1720 toggle_width, label_width, bindings_width, | |
1721 height); | |
1722 | |
1723 /* key bindings to display? */ | |
1724 if (!in_menubar && val->key) | |
1725 { | |
1726 int w; | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1727 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 1728 XmString key = XmStringCreateLtoR (val->key, XmSTRING_DEFAULT_CHARSET); |
1729 w = string_width (mw, key); | |
1730 XmStringFree (key); | |
1731 #else | |
1732 char *key = val->key; | |
1733 w = string_width (mw, key); | |
1734 #endif | |
1735 *bindings_width += w + mw->menu.column_spacing; | |
1736 } | |
1737 } | |
1738 | |
1739 static void | |
1740 push_button_draw (XlwMenuWidget mw, | |
1741 widget_value *val, | |
1742 Boolean in_menubar, | |
1743 Boolean highlighted, | |
1744 Window window, | |
1745 int x, int y, | |
1746 unsigned int width, | |
1747 unsigned int height, | |
1748 unsigned int label_offset, | |
1749 unsigned int binding_offset) | |
1750 { | |
1751 int y_offset = mw->menu.shadow_thickness + mw->menu.vertical_margin; | |
1752 GC gc; | |
1753 shadow_type type; | |
1754 Boolean menu_pb = in_menubar && (menu_item_type (val) == BUTTON_TYPE); | |
1755 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1756 #ifdef HAVE_XFT_MENUBARS |
3094 | 1757 XftColor color, colorBg; |
1758 Display *display = XtDisplay (mw); | |
1759 Colormap cmap = mw->core.colormap; | |
1760 Visual *visual; | |
1761 int ignored, pixel, pixelBg, dim = 0; | |
1762 | |
1763 visual_info_from_widget ((Widget) mw, &visual, &ignored); | |
1764 #endif | |
1765 | |
428 | 1766 /* Draw the label string. */ |
1767 if (!label_offset) | |
1768 label_offset = mw->menu.shadow_thickness + mw->menu.horizontal_margin; | |
1769 | |
1770 if (highlighted) | |
1771 { | |
1772 if (val->enabled) | |
3094 | 1773 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1774 #ifdef HAVE_XFT_MENUBARS |
3094 | 1775 pixel = mw->menu.highlight_foreground; |
1776 pixelBg = mw->core.background_pixel; | |
1777 #endif | |
1778 gc = mw->menu.highlight_gc; | |
1779 } | |
428 | 1780 else |
3094 | 1781 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1782 #ifdef HAVE_XFT_MENUBARS |
3094 | 1783 dim = 1; |
1784 pixel = mw->menu.foreground; | |
1785 pixelBg = mw->core.background_pixel; | |
1786 #endif | |
1787 gc = mw->menu.inactive_gc; | |
1788 } | |
428 | 1789 } |
1790 else if (menu_pb) | |
1791 { | |
1792 if (val->enabled) | |
3094 | 1793 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1794 #ifdef HAVE_XFT_MENUBARS |
3094 | 1795 pixel = mw->menu.button_foreground; |
1796 pixelBg = mw->core.background_pixel; | |
1797 #endif | |
1798 gc = mw->menu.button_gc; | |
1799 } | |
428 | 1800 else |
3094 | 1801 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1802 #ifdef HAVE_XFT_MENUBARS |
3094 | 1803 dim = 1; |
1804 pixel = mw->menu.button_foreground; | |
1805 pixelBg = mw->core.background_pixel; | |
1806 #endif | |
1807 gc = mw->menu.inactive_button_gc; | |
1808 } | |
428 | 1809 } |
1810 else | |
1811 { | |
1812 if (val->enabled) | |
3094 | 1813 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1814 #ifdef HAVE_XFT_MENUBARS |
3094 | 1815 pixel = mw->menu.foreground; |
1816 pixelBg = mw->core.background_pixel; | |
1817 #endif | |
1818 gc = mw->menu.foreground_gc; | |
1819 } | |
428 | 1820 else |
3094 | 1821 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1822 #ifdef HAVE_XFT_MENUBARS |
3094 | 1823 dim = 1; |
1824 pixel = mw->menu.foreground; | |
1825 pixelBg = mw->core.background_pixel; | |
1826 #endif | |
1827 gc = mw->menu.inactive_gc; | |
1828 } | |
428 | 1829 } |
1830 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1831 #ifdef HAVE_XFT_MENUBARS |
3094 | 1832 color = xft_convert_color (display, cmap, visual, pixel, dim); |
1833 colorBg = xft_convert_color (display, cmap, visual, pixelBg, 0); | |
1834 #endif | |
1835 | |
428 | 1836 string_draw_u (mw, |
3094 | 1837 window, |
1838 x + label_offset, y + y_offset, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1839 #ifdef HAVE_XFT_MENUBARS |
3094 | 1840 &color, &colorBg, gc, |
1841 #else | |
1842 gc, | |
1843 #endif | |
428 | 1844 resource_widget_value (mw, val)); |
1845 | |
1846 /* Draw the keybindings */ | |
1847 if (val->key) | |
1848 { | |
1849 if (!binding_offset) | |
1850 { | |
1851 unsigned int s_width = | |
1852 string_width (mw, resource_widget_value (mw, val)); | |
1853 binding_offset = label_offset + s_width + mw->menu.shadow_thickness; | |
1854 } | |
1855 binding_draw (mw, window, | |
1856 x + binding_offset + mw->menu.column_spacing, | |
3094 | 1857 y + y_offset, |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
1858 #ifdef HAVE_XFT_MENUBARS |
3094 | 1859 &color, &colorBg, |
1860 #else | |
1861 gc, | |
1862 #endif | |
1863 val->key); | |
428 | 1864 } |
1865 | |
1866 /* Draw the shadow */ | |
1867 if (menu_pb) | |
1868 { | |
1869 if (highlighted) | |
1870 type = SHADOW_OUT; | |
1871 else | |
1872 type = (val->selected ? SHADOW_ETCHED_OUT : SHADOW_ETCHED_IN); | |
1873 } | |
1874 else | |
1875 { | |
1876 if (highlighted) | |
1877 type = SHADOW_OUT; | |
1878 else | |
1879 type = SHADOW_BACKGROUND; | |
1880 } | |
1881 | |
1882 shadow_draw (mw, window, x, y, width, height, type); | |
1883 } | |
1884 | |
1885 static unsigned int | |
1886 arrow_decoration_height (XlwMenuWidget mw) | |
1887 { | |
1888 int result = (mw->menu.font_ascent + mw->menu.font_descent) / 2; | |
1889 | |
1890 result += 2 * mw->menu.shadow_thickness; | |
1891 | |
1892 if (result > (mw->menu.font_ascent + mw->menu.font_descent)) | |
1893 result = mw->menu.font_ascent + mw->menu.font_descent; | |
1894 | |
1895 return result; | |
1896 } | |
1897 | |
1898 static void | |
1899 cascade_button_size (XlwMenuWidget mw, | |
1900 widget_value *val, | |
1901 Boolean in_menubar, | |
1902 unsigned int *toggle_width, | |
1903 unsigned int *label_width, | |
1904 unsigned int *arrow_width, | |
1905 unsigned int *height) | |
1906 { | |
1907 /* inherit */ | |
1908 label_button_size (mw, val, in_menubar, | |
1909 toggle_width, label_width, arrow_width, | |
1910 height); | |
1911 /* we have a pull aside arrow */ | |
1912 if (!in_menubar) | |
1913 { | |
1914 *arrow_width += arrow_decoration_height (mw) + mw->menu.column_spacing; | |
1915 } | |
1916 } | |
1917 | |
1918 static void | |
1919 cascade_button_draw (XlwMenuWidget mw, | |
1920 widget_value *val, | |
1921 Boolean in_menubar, | |
1922 Boolean highlighted, | |
1923 Window window, | |
1924 int x, int y, | |
1925 unsigned int width, | |
1926 unsigned int height, | |
1927 unsigned int label_offset, | |
1928 unsigned int binding_offset) | |
1929 { | |
1930 shadow_type type; | |
1931 | |
1932 /* Draw the label string. */ | |
1933 label_button_draw (mw, val, in_menubar, highlighted, | |
1934 window, x, y, width, height, label_offset, | |
1935 binding_offset); | |
1936 | |
1937 /* Draw the pull aside arrow */ | |
1938 if (!in_menubar && val->contents) | |
1939 { | |
1940 int y_offset; | |
1941 unsigned int arrow_height = arrow_decoration_height (mw); | |
1942 | |
1943 y_offset = mw->menu.shadow_thickness + mw->menu.vertical_margin + | |
1944 (mw->menu.font_ascent+mw->menu.font_descent - arrow_height)/2; | |
1945 | |
1946 if (!binding_offset) | |
1947 { | |
1948 unsigned int s_width = | |
1949 string_width (mw, resource_widget_value (mw, val)); | |
1950 | |
1951 if (!label_offset) | |
1952 label_offset = mw->menu.shadow_thickness + | |
1953 mw->menu.horizontal_margin; | |
1954 | |
1955 binding_offset = label_offset + s_width + mw->menu.shadow_thickness; | |
1956 } | |
1957 | |
1958 arrow_decoration_draw (mw, | |
1959 window, | |
1960 x + binding_offset + mw->menu.column_spacing, | |
1961 y + y_offset, | |
1962 arrow_height, | |
1963 highlighted); | |
1964 } | |
1965 | |
1966 /* Draw the shadow */ | |
1967 if (highlighted) | |
1968 type = SHADOW_OUT; | |
1969 else | |
1970 type = SHADOW_BACKGROUND; | |
1971 | |
1972 shadow_draw (mw, window, x, y, width, height, type); | |
1973 } | |
1974 | |
1975 static unsigned int | |
1976 toggle_decoration_height (XlwMenuWidget mw) | |
1977 { | |
1978 int rv; | |
1979 if (mw->menu.indicator_size > 0) | |
1980 rv = mw->menu.indicator_size; | |
1981 else | |
1982 rv = mw->menu.font_ascent; | |
1983 | |
1984 if (rv > (mw->menu.font_ascent + mw->menu.font_descent)) | |
1985 rv = mw->menu.font_ascent + mw->menu.font_descent; | |
1986 | |
1987 /* radio button can't be smaller than its border or a filling | |
1988 error will occur. */ | |
1989 if (rv < 2 * mw->menu.shadow_thickness) | |
1990 rv = 2 * mw->menu.shadow_thickness; | |
1991 | |
1992 return rv; | |
1993 } | |
1994 | |
1995 static void | |
1996 toggle_button_size (XlwMenuWidget mw, | |
1997 widget_value *val, | |
1998 Boolean in_menubar, | |
1999 unsigned int *toggle_width, | |
2000 unsigned int *label_width, | |
2001 unsigned int *bindings_width, | |
2002 unsigned int *height) | |
2003 { | |
2004 /* inherit */ | |
2005 push_button_size (mw, val, in_menubar, | |
2006 toggle_width, label_width, bindings_width, | |
2007 height); | |
2008 /* we have a toggle */ | |
2009 *toggle_width += toggle_decoration_height (mw) + mw->menu.column_spacing; | |
2010 } | |
2011 | |
2012 static void | |
2013 toggle_button_draw (XlwMenuWidget mw, | |
2014 widget_value *val, | |
2015 Boolean in_menubar, | |
2016 Boolean highlighted, | |
2017 Window window, | |
2018 int x, int y, | |
2019 unsigned int width, | |
2020 unsigned int height, | |
2021 unsigned int label_tab, | |
2022 unsigned int binding_tab) | |
2023 { | |
2024 int x_offset; | |
2025 int y_offset; | |
2026 unsigned int t_height = toggle_decoration_height (mw); | |
2027 | |
2028 /* Draw a toggle. */ | |
2029 x_offset = mw->menu.shadow_thickness + mw->menu.horizontal_margin; | |
2030 y_offset = mw->menu.shadow_thickness + mw->menu.vertical_margin; | |
2031 y_offset += (mw->menu.font_ascent + mw->menu.font_descent - t_height)/2; | |
2032 | |
2033 toggle_decoration_draw (mw, window, x + x_offset, y + y_offset, | |
2034 t_height, val->selected); | |
2035 | |
2036 /* Draw the pushbutton parts. */ | |
2037 push_button_draw (mw, val, in_menubar, highlighted, window, x, y, width, | |
2038 height, label_tab, binding_tab); | |
2039 } | |
2040 | |
2041 static unsigned int | |
2042 radio_decoration_height (XlwMenuWidget mw) | |
2043 { | |
2044 return toggle_decoration_height (mw); | |
2045 } | |
2046 | |
2047 static void | |
2048 radio_button_draw (XlwMenuWidget mw, | |
2049 widget_value *val, | |
2050 Boolean in_menubar, | |
2051 Boolean highlighted, | |
2052 Window window, | |
2053 int x, int y, | |
2054 unsigned int width, | |
2055 unsigned int height, | |
2056 unsigned int label_tab, | |
2057 unsigned int binding_tab) | |
2058 { | |
2059 int x_offset; | |
2060 int y_offset; | |
2061 unsigned int r_height = radio_decoration_height (mw); | |
2062 | |
2063 /* Draw a toggle. */ | |
2064 x_offset = mw->menu.shadow_thickness + mw->menu.horizontal_margin; | |
2065 y_offset = mw->menu.shadow_thickness + mw->menu.vertical_margin; | |
2066 y_offset += (mw->menu.font_ascent + mw->menu.font_descent - r_height)/2; | |
2067 | |
2068 radio_decoration_draw (mw, window, x + x_offset, y + y_offset, r_height, | |
2069 val->selected); | |
2070 | |
2071 /* Draw the pushbutton parts. */ | |
2072 push_button_draw (mw, val, in_menubar, highlighted, window, x, y, width, | |
2073 height, label_tab, binding_tab); | |
2074 } | |
2075 | |
2076 static struct _shadow_names | |
2077 { | |
442 | 2078 const char * name; |
428 | 2079 shadow_type type; |
2080 } shadow_names[] = | |
2081 { | |
2082 /* Motif */ | |
2083 { "singleLine", SHADOW_SINGLE_LINE }, | |
2084 { "doubleLine", SHADOW_DOUBLE_LINE }, | |
2085 { "singleDashedLine", SHADOW_SINGLE_DASHED_LINE }, | |
2086 { "doubleDashedLine", SHADOW_DOUBLE_DASHED_LINE }, | |
2087 { "noLine", SHADOW_NO_LINE }, | |
2088 { "shadowEtchedIn", SHADOW_ETCHED_IN }, | |
2089 { "shadowEtchedOut", SHADOW_ETCHED_OUT }, | |
2090 { "shadowEtchedInDash", SHADOW_ETCHED_IN_DASH }, | |
2091 { "shadowEtchedOutDash", SHADOW_ETCHED_OUT_DASH }, | |
2092 /* non-Motif */ | |
2093 { "shadowDoubleEtchedIn", SHADOW_DOUBLE_ETCHED_IN }, | |
2094 { "shadowDoubleEtchedOut", SHADOW_DOUBLE_ETCHED_OUT }, | |
2095 { "shadowDoubleEtchedInDash", SHADOW_DOUBLE_ETCHED_IN_DASH }, | |
2096 { "shadowDoubleEtchedOutDash", SHADOW_DOUBLE_ETCHED_OUT_DASH } | |
2097 }; | |
2098 | |
2099 static shadow_type | |
2100 separator_type (char *name) | |
2101 { | |
2102 if (name) | |
2103 { | |
2104 int i; | |
2105 for (i = 0; i < (int) (XtNumber (shadow_names)); i++ ) | |
2106 { | |
2107 if (strcmp (name, shadow_names[i].name) == 0) | |
2108 return shadow_names[i].type; | |
2109 } | |
2110 } | |
2111 return SHADOW_BACKGROUND; | |
2112 } | |
2113 | |
2114 static unsigned int | |
2115 separator_decoration_height (XlwMenuWidget mw, widget_value *val) | |
2116 { | |
2117 | |
2118 switch (separator_type (val->value)) | |
2119 { | |
2120 case SHADOW_NO_LINE: | |
2121 case SHADOW_SINGLE_LINE: | |
2122 case SHADOW_SINGLE_DASHED_LINE: | |
2123 return 1; | |
2124 case SHADOW_DOUBLE_LINE: | |
2125 case SHADOW_DOUBLE_DASHED_LINE: | |
2126 return 3; | |
2127 case SHADOW_DOUBLE_ETCHED_OUT: | |
2128 case SHADOW_DOUBLE_ETCHED_IN: | |
2129 case SHADOW_DOUBLE_ETCHED_OUT_DASH: | |
2130 case SHADOW_DOUBLE_ETCHED_IN_DASH: | |
2131 return (1 + 2 * mw->menu.shadow_thickness); | |
2132 case SHADOW_ETCHED_OUT: | |
2133 case SHADOW_ETCHED_IN: | |
2134 default: | |
2135 return mw->menu.shadow_thickness; | |
2136 } | |
2137 } | |
2138 | |
2139 static void | |
2140 separator_size (XlwMenuWidget mw, | |
2141 widget_value *val, | |
2286 | 2142 Boolean UNUSED (in_menubar), |
428 | 2143 unsigned int *toggle_width, |
2144 unsigned int *label_width, | |
2145 unsigned int *rest_width, | |
2146 unsigned int *height) | |
2147 { | |
2148 *height = separator_decoration_height (mw, val); | |
2149 *label_width = 1; | |
2150 *toggle_width = *rest_width = 0; | |
2151 } | |
2152 | |
2153 static void | |
2154 separator_draw (XlwMenuWidget mw, | |
2155 widget_value *val, | |
2156 Boolean in_menubar, | |
2286 | 2157 Boolean UNUSED (highlighted), |
428 | 2158 Window window, |
2159 int x, int y, | |
2160 unsigned int width, | |
2161 unsigned int height, | |
2286 | 2162 unsigned int UNUSED (label_tab), |
2163 unsigned int UNUSED (binding_tab)) | |
428 | 2164 { |
2165 unsigned int sep_width; | |
2166 | |
2167 if (in_menubar) | |
2168 sep_width = height; | |
2169 else | |
2170 sep_width = width; | |
2171 | |
2172 separator_decoration_draw (mw, | |
2173 window, | |
2174 x, | |
2175 y, | |
2176 sep_width, | |
2177 in_menubar, | |
2178 separator_type(val->value)); | |
2179 } | |
2180 | |
2181 static void | |
2286 | 2182 pushright_size (XlwMenuWidget UNUSED (mw), |
2183 widget_value *UNUSED (val), | |
2184 Boolean UNUSED (in_menubar), | |
428 | 2185 unsigned int *toggle_width, |
2186 unsigned int *label_width, | |
2187 unsigned int *rest_width, | |
2188 unsigned int *height) | |
2189 { | |
2190 *height = *label_width = *toggle_width = *rest_width = 0; | |
2191 } | |
2192 | |
2193 static void | |
2194 size_menu_item (XlwMenuWidget mw, | |
2195 widget_value *val, | |
2196 int horizontal, | |
2197 unsigned int *toggle_width, | |
2198 unsigned int *label_width, | |
2199 unsigned int *rest_width, | |
2200 unsigned int *height) | |
2201 { | |
2202 void (*function_ptr) (XlwMenuWidget _mw, | |
2203 widget_value *_val, | |
2204 Boolean _in_menubar, | |
2205 unsigned int *_toggle_width, | |
2206 unsigned int *_label_width, | |
2207 unsigned int *_rest_width, | |
2208 unsigned int *_height); | |
2209 | |
2210 switch (menu_item_type (val)) | |
2211 { | |
2212 case TOGGLE_TYPE: | |
2213 case RADIO_TYPE: | |
2214 function_ptr = toggle_button_size; | |
2215 break; | |
2216 case SEPARATOR_TYPE: | |
2217 function_ptr = separator_size; | |
2218 break; | |
2219 case INCREMENTAL_TYPE: | |
2220 case CASCADE_TYPE: | |
2221 function_ptr = cascade_button_size; | |
2222 break; | |
2223 case BUTTON_TYPE: | |
2224 function_ptr = push_button_size; | |
2225 break; | |
2226 case PUSHRIGHT_TYPE: | |
2227 function_ptr = pushright_size; | |
2228 break; | |
2229 case TEXT_TYPE: | |
2230 default: | |
2231 function_ptr = label_button_size; | |
2232 break; | |
2233 } | |
2234 | |
2235 (*function_ptr) (mw, | |
2236 val, | |
2237 horizontal, | |
2238 toggle_width, | |
2239 label_width, | |
2240 rest_width, | |
2241 height); | |
2242 } | |
2243 | |
2244 static void | |
2245 display_menu_item (XlwMenuWidget mw, | |
2246 widget_value *val, | |
2247 window_state *ws, | |
2248 XPoint *where, | |
2249 Boolean highlighted, | |
2250 Boolean horizontal, | |
2251 Boolean just_compute) | |
2252 { | |
2253 | |
2254 int x = where->x /* + mw->menu.shadow_thickness */ ; | |
2255 int y = where->y /* + mw->menu.shadow_thickness */ ; | |
2256 unsigned int toggle_width; | |
2257 unsigned int label_width; | |
2258 unsigned int binding_width; | |
2259 unsigned int width; | |
2260 unsigned int height; | |
2261 unsigned int label_tab; | |
2262 unsigned int binding_tab; | |
2263 void (*function_ptr) (XlwMenuWidget _mw, | |
2264 widget_value *_val, | |
2265 Boolean _in_menubar, | |
2266 Boolean _highlighted, | |
2267 Window _window, | |
2268 int _x, int _y, | |
2269 unsigned int _width, | |
2270 unsigned int _height, | |
2271 unsigned int _label_tab, | |
2272 unsigned int _binding_tab); | |
2273 | |
2274 size_menu_item (mw, val, horizontal, | |
2275 &toggle_width, &label_width, &binding_width, &height); | |
2276 | |
2277 if (horizontal) | |
2278 { | |
2279 width = toggle_width + label_width + binding_width; | |
2280 height = ws->height - 2 * mw->menu.shadow_thickness; | |
2281 } | |
2282 else | |
2283 { | |
2284 width = ws->width - 2 * mw->menu.shadow_thickness; | |
2285 toggle_width = ws->toggle_width; | |
2286 label_width = ws->label_width; | |
2287 } | |
2288 | |
2289 where->x += width; | |
2290 where->y += height; | |
2291 | |
2292 if (just_compute) | |
2293 return; | |
2294 | |
2295 label_tab = toggle_width; | |
2296 binding_tab = toggle_width + label_width; | |
2297 | |
2298 switch (menu_item_type (val)) | |
2299 { | |
2300 case TOGGLE_TYPE: | |
2301 function_ptr = toggle_button_draw; | |
2302 break; | |
2303 case RADIO_TYPE: | |
2304 function_ptr = radio_button_draw; | |
2305 break; | |
2306 case SEPARATOR_TYPE: | |
2307 function_ptr = separator_draw; | |
2308 break; | |
2309 case INCREMENTAL_TYPE: | |
2310 case CASCADE_TYPE: | |
2311 function_ptr = cascade_button_draw; | |
2312 break; | |
2313 case BUTTON_TYPE: | |
2314 function_ptr = push_button_draw; | |
2315 break; | |
2316 case TEXT_TYPE: | |
2317 function_ptr = label_button_draw; | |
2318 break; | |
2319 default: /* do no drawing */ | |
2320 return; | |
2321 } | |
2322 | |
2323 (*function_ptr) (mw, | |
2324 val, | |
2325 horizontal, | |
2326 highlighted, | |
2327 ws->window, | |
2328 x, y, | |
2329 width, height, | |
2330 label_tab, | |
2331 binding_tab); | |
2332 } | |
2333 | |
2334 static void | |
2335 size_menu (XlwMenuWidget mw, int level) | |
2336 { | |
2337 unsigned int toggle_width; | |
2338 unsigned int label_width; | |
2339 unsigned int rest_width; | |
2340 unsigned int height; | |
2341 unsigned int max_toggle_width = 0; | |
2342 unsigned int max_label_width = 0; | |
2343 unsigned int max_rest_width = 0; | |
2344 unsigned int max_height = 0; | |
2345 int horizontal_p = mw->menu.horizontal && (level == 0); | |
2346 widget_value* val; | |
2347 window_state* ws; | |
2348 | |
2349 if (level >= mw->menu.old_depth) | |
2350 abort (); | |
2351 | |
2352 ws = &mw->menu.windows [level]; | |
2353 | |
2354 for (val = mw->menu.old_stack [level]->contents; val; val = val->next) | |
2355 { | |
2356 size_menu_item (mw, | |
2357 val, | |
2358 horizontal_p, | |
2359 &toggle_width, | |
2360 &label_width, | |
2361 &rest_width, | |
2362 &height); | |
2363 if (horizontal_p) | |
2364 { | |
2365 max_label_width += toggle_width + label_width + rest_width; | |
2366 if (height > max_height) | |
2367 max_height = height; | |
2368 } | |
2369 else | |
2370 { | |
2371 if (max_toggle_width < toggle_width) | |
2372 max_toggle_width = toggle_width; | |
2373 if (max_label_width < label_width) | |
2374 max_label_width = label_width; | |
2375 if (max_rest_width < rest_width) | |
2376 max_rest_width = rest_width; | |
2377 max_height += height; | |
2378 } | |
2379 } | |
2380 | |
2381 ws->height = max_height; | |
2382 ws->width = max_label_width + max_rest_width + max_toggle_width; | |
2383 ws->toggle_width = max_toggle_width; | |
2384 ws->label_width = max_label_width; | |
2385 | |
2386 ws->width += 2 * mw->menu.shadow_thickness; | |
2387 ws->height += 2 * mw->menu.shadow_thickness; | |
2388 } | |
2389 | |
2390 static void | |
2391 display_menu (XlwMenuWidget mw, int level, Boolean just_compute_p, | |
2392 XPoint *highlighted_pos, XPoint *hit, widget_value **hit_return, | |
1201 | 2393 widget_value *this_, widget_value *that) |
428 | 2394 { |
2395 widget_value *val; | |
2396 widget_value *following_item; | |
2397 window_state *ws; | |
2398 XPoint where; | |
2399 int horizontal_p = mw->menu.horizontal && (level == 0); | |
2400 int highlighted_p; | |
2401 int just_compute_this_one_p; | |
2402 | |
2403 if (level >= mw->menu.old_depth) | |
2404 abort (); | |
2405 | |
2406 if (level < mw->menu.old_depth - 1) | |
2407 following_item = mw->menu.old_stack [level + 1]; | |
2408 else | |
2409 { | |
2410 if (lw_menu_accelerate | |
2411 && level == mw->menu.old_depth - 1 | |
2412 && mw->menu.old_stack [level]->type == CASCADE_TYPE) | |
2413 just_compute_p = True; | |
2414 following_item = NULL; | |
2415 } | |
2416 | |
2417 #if SLOPPY_TYPES == 1 | |
2418 puts("==================================================================="); | |
2419 print_widget_value (following_item, 1, 0); | |
2420 #endif | |
2421 | |
2422 if (hit) | |
2423 *hit_return = NULL; | |
2424 | |
2425 where.x = mw->menu.shadow_thickness; | |
2426 where.y = mw->menu.shadow_thickness; | |
2427 | |
2428 ws = &mw->menu.windows [level]; | |
2429 for (val = mw->menu.old_stack [level]->contents; val; val = val->next) | |
2430 { | |
2431 XPoint start; | |
2432 | |
2433 highlighted_p = (val == following_item); | |
2434 /* If this is the partition (the dummy item which says that menus | |
2435 after this should be flushright) then figure out how big the | |
2436 following items are. This means we walk down the tail of the | |
2437 list twice, but that's no big deal - it's short. | |
2438 */ | |
2439 if (horizontal_p && (menu_item_type (val) == PUSHRIGHT_TYPE)) | |
2440 { | |
2441 widget_value *rest; | |
2442 XPoint flushright_size; | |
2443 int new_x; | |
2444 flushright_size.x = 0; | |
2445 flushright_size.y = 0; | |
2446 for (rest = val; rest; rest = rest->next) | |
2447 display_menu_item (mw, rest, ws, &flushright_size, | |
2448 highlighted_p, horizontal_p, True); | |
2449 new_x = ws->width - (flushright_size.x + mw->menu.shadow_thickness); | |
2450 if (new_x > where.x) | |
2451 where.x = new_x; | |
2452 /* We know what we need; don't draw this item. */ | |
2453 continue; | |
2454 } | |
2455 | |
2456 if (highlighted_p && highlighted_pos) | |
2457 { | |
2458 if (horizontal_p) | |
2459 highlighted_pos->x = where.x; | |
2460 else | |
2461 highlighted_pos->y = where.y; | |
2462 } | |
2463 | |
2464 just_compute_this_one_p = | |
1201 | 2465 just_compute_p || ((this_ || that) && val != this_ && val != that); |
428 | 2466 |
2467 start.x = where.x; | |
2468 start.y = where.y; | |
2469 display_menu_item (mw, val, ws, &where, highlighted_p, horizontal_p, | |
2470 just_compute_this_one_p); | |
2471 | |
2472 if (highlighted_p && highlighted_pos) | |
2473 { | |
2474 if (horizontal_p) | |
2475 highlighted_pos->y = ws->height; | |
2476 else | |
2477 highlighted_pos->x = ws->width; | |
2478 } | |
2479 | |
2480 if (hit && !*hit_return) | |
2481 { | |
2482 if (horizontal_p && hit->x > start.x && hit->x <= where.x) | |
2483 *hit_return = val; | |
2484 else if (!horizontal_p && hit->y > start.y && hit->y <= where.y) | |
2485 *hit_return = val; | |
2486 } | |
2487 | |
2488 if (horizontal_p) | |
2489 where.y = mw->menu.shadow_thickness; | |
2490 else | |
2491 where.x = mw->menu.shadow_thickness; | |
2492 } | |
2493 | |
2494 /* Draw slab edges around menu */ | |
2495 if (!just_compute_p) | |
2496 shadow_draw(mw, ws->window, 0, 0, ws->width, ws->height, SHADOW_OUT); | |
2497 } | |
2498 | |
2499 /* Motion code */ | |
2500 static void | |
2501 set_new_state (XlwMenuWidget mw, widget_value *val, int level) | |
2502 { | |
2503 int i; | |
2504 | |
2505 mw->menu.new_depth = 0; | |
2506 for (i = 0; i < level; i++) | |
2507 push_new_stack (mw, mw->menu.old_stack [i]); | |
2508 if (val) | |
2509 push_new_stack (mw, val); | |
2510 } | |
2511 | |
2512 static void | |
2513 make_windows_if_needed (XlwMenuWidget mw, int n) | |
2514 { | |
2515 int i; | |
2516 int start_at; | |
2517 XSetWindowAttributes xswa; | |
2518 Widget p; | |
446 | 2519 unsigned long mask; |
428 | 2520 int depth; |
2521 Visual *visual; | |
2522 window_state *windows; | |
2523 Window root; | |
2524 | |
2525 if (mw->menu.windows_length >= n) | |
2526 return; | |
2527 | |
2528 root = RootWindowOfScreen (XtScreen(mw)); | |
3094 | 2529 /* use visual_info_from_widget() from lwlib-colors.c */ |
428 | 2530 /* grab the visual and depth from the nearest shell ancestor */ |
2531 visual = CopyFromParent; | |
2532 depth = CopyFromParent; | |
2533 p = XtParent(mw); | |
2534 while (visual == CopyFromParent && p) | |
2535 { | |
2536 if (XtIsShell(p)) | |
2537 { | |
2538 visual = ((ShellWidget)p)->shell.visual; | |
2539 depth = p->core.depth; | |
2540 } | |
2541 p = XtParent(p); | |
2542 } | |
2543 | |
2544 xswa.save_under = True; | |
2545 xswa.override_redirect = True; | |
2546 xswa.background_pixel = mw->core.background_pixel; | |
2547 xswa.border_pixel = mw->core.border_pixel; | |
2548 xswa.event_mask = (ExposureMask | ButtonMotionMask | |
2549 | ButtonReleaseMask | ButtonPressMask); | |
2550 xswa.cursor = mw->menu.cursor_shape; | |
2551 xswa.colormap = mw->core.colormap; | |
2552 mask = CWSaveUnder | CWOverrideRedirect | CWBackPixel | CWBorderPixel | |
2553 | CWEventMask | CWCursor | CWColormap; | |
2554 | |
2555 if (mw->menu.use_backing_store) | |
2556 { | |
2557 xswa.backing_store = Always; | |
2558 mask |= CWBackingStore; | |
2559 } | |
2560 | |
2561 if (!mw->menu.windows) | |
2562 { | |
2563 mw->menu.windows = | |
2564 (window_state *) XtMalloc (n * sizeof (window_state)); | |
2565 start_at = 0; | |
2566 } | |
2567 else | |
2568 { | |
2569 mw->menu.windows = | |
2570 (window_state *) XtRealloc ((char *) mw->menu.windows, | |
2571 n * sizeof (window_state)); | |
2572 start_at = mw->menu.windows_length; | |
2573 } | |
2574 mw->menu.windows_length = n; | |
2575 | |
2576 windows = mw->menu.windows; | |
2577 | |
2578 for (i = start_at; i < n; i++) | |
2579 { | |
2580 windows [i].x = 0; | |
2581 windows [i].y = 0; | |
2582 windows [i].width = 1; | |
2583 windows [i].height = 1; | |
2584 windows [i].window = | |
2585 XCreateWindow (XtDisplay (mw), | |
2586 root, | |
2587 0, 0, 1, 1, | |
2588 0, depth, CopyFromParent, visual, mask, &xswa); | |
2589 } | |
2590 } | |
2591 | |
2592 /* Make the window fit in the screen */ | |
2593 static void | |
2594 fit_to_screen (XlwMenuWidget mw, window_state *ws, window_state *previous_ws, | |
2595 Boolean horizontal_p) | |
2596 { | |
2597 int screen_width = WidthOfScreen (XtScreen (mw)); | |
2598 int screen_height = HeightOfScreen (XtScreen (mw)); | |
2599 | |
2600 if (ws->x < 0) | |
2601 ws->x = 0; | |
2602 else if ((int) (ws->x + ws->width) > screen_width) | |
2603 { | |
2604 if (!horizontal_p) | |
2605 ws->x = previous_ws->x - ws->width; | |
2606 else | |
2607 { | |
2608 ws->x = screen_width - ws->width; | |
2609 | |
2610 /* This check is to make sure we cut off the right side | |
2611 instead of the left side if the menu is wider than the | |
2612 screen. */ | |
2613 if (ws->x < 0) | |
2614 ws->x = 0; | |
2615 } | |
2616 } | |
2617 if (ws->y < 0) | |
2618 ws->y = 0; | |
2619 else if ((int) (ws->y + ws->height) > screen_height) | |
2620 { | |
2621 if (horizontal_p) | |
2622 { | |
2623 /* A pulldown must either be entirely above or below the menubar. | |
2624 If we're here, the pulldown doesn't fit below the menubar, so | |
2625 let's determine if it will fit above the menubar. | |
2626 Only put it above if there is more room above than below. | |
2627 Note shadow_thickness offset to allow for slab surround. | |
2628 */ | |
2629 if (ws->y > (screen_height / 2)) | |
2630 ws->y = previous_ws->y - ws->height + mw->menu.shadow_thickness; | |
2631 } | |
2632 else | |
2633 { | |
2634 ws->y = screen_height - ws->height; | |
2635 /* if it's taller than the screen, display the topmost part | |
2636 that will fit, beginning at the top of the screen. */ | |
2637 if (ws->y < 0) | |
2638 ws->y = 0; | |
2639 } | |
2640 } | |
2641 } | |
2642 | |
2643 /* Updates old_stack from new_stack and redisplays. */ | |
2644 static void | |
2645 remap_menubar (XlwMenuWidget mw) | |
2646 { | |
2647 int i; | |
2648 int last_same; | |
2649 XPoint selection_position; | |
2650 int old_depth = mw->menu.old_depth; | |
2651 int new_depth = mw->menu.new_depth; | |
2652 widget_value **old_stack; | |
2653 widget_value **new_stack; | |
2654 window_state *windows; | |
2655 widget_value *old_selection; | |
2656 widget_value *new_selection; | |
2657 | |
2658 /* Check that enough windows and old_stack are ready. */ | |
2659 make_windows_if_needed (mw, new_depth); | |
2660 make_old_stack_space (mw, new_depth); | |
2661 windows = mw->menu.windows; | |
2662 old_stack = mw->menu.old_stack; | |
2663 new_stack = mw->menu.new_stack; | |
2664 | |
2665 /* compute the last identical different entry */ | |
2666 for (i = 1; i < old_depth && i < new_depth; i++) | |
2667 if (old_stack [i] != new_stack [i]) | |
2668 break; | |
2669 last_same = i - 1; | |
2670 | |
2671 if (lw_menu_accelerate | |
2672 && last_same | |
2673 && last_same == old_depth - 1 | |
2674 && old_stack [last_same]->contents) | |
2675 last_same--; | |
2676 | |
2677 /* Memorize the previously selected item to be able to refresh it */ | |
2678 old_selection = last_same + 1 < old_depth ? old_stack [last_same + 1] : NULL; | |
2679 new_selection = last_same + 1 < new_depth ? new_stack [last_same + 1] : NULL; | |
2680 | |
2681 /* updates old_state from new_state. It has to be done now because | |
2682 display_menu (called below) uses the old_stack to know what to display. */ | |
2683 for (i = last_same + 1; i < new_depth; i++) | |
2684 old_stack [i] = new_stack [i]; | |
2685 | |
2686 mw->menu.old_depth = new_depth; | |
2687 | |
442 | 2688 /* refresh the last selection */ |
428 | 2689 selection_position.x = 0; |
2690 selection_position.y = 0; | |
2691 display_menu (mw, last_same, new_selection == old_selection, | |
2692 &selection_position, NULL, NULL, old_selection, new_selection); | |
2693 | |
2694 /* Now popup the new menus */ | |
2695 for (i = last_same + 1; i < new_depth && new_stack [i]->contents; i++) | |
2696 { | |
2697 window_state *previous_ws = &windows [i - 1]; | |
2698 window_state *ws = &windows [i]; | |
2699 | |
2700 if (lw_menu_accelerate && i == new_depth - 1) | |
2701 break; | |
2702 | |
2703 ws->x = previous_ws->x + selection_position.x; | |
2704 ws->y = previous_ws->y + selection_position.y; | |
2705 | |
2706 /* take into account the slab around the new menu */ | |
2707 ws->y -= mw->menu.shadow_thickness; | |
2708 | |
2709 { | |
2710 widget_value *val = mw->menu.old_stack [i]; | |
2711 if (val->contents->type == INCREMENTAL_TYPE) | |
2712 { | |
2713 /* okay, we're now doing a lisp callback to incrementally generate | |
2714 more of the menu. */ | |
2715 XtCallCallbackList ((Widget)mw, | |
2716 mw->menu.open, | |
2717 (XtPointer)val->contents); | |
2718 } | |
2719 } | |
2720 | |
2721 size_menu (mw, i); | |
2722 | |
2723 fit_to_screen (mw, ws, previous_ws, mw->menu.horizontal && i == 1); | |
2724 | |
2725 XClearWindow (XtDisplay (mw), ws->window); | |
2726 XMoveResizeWindow (XtDisplay (mw), ws->window, ws->x, ws->y, | |
2727 ws->width, ws->height); | |
2728 XMapRaised (XtDisplay (mw), ws->window); | |
2729 display_menu (mw, i, False, &selection_position, NULL, NULL, NULL, NULL); | |
2730 } | |
2731 | |
2732 /* unmap the menus that popped down */ | |
2733 | |
2734 last_same = new_depth; | |
2735 if (lw_menu_accelerate | |
2736 && last_same > 1 | |
2737 && new_stack [last_same - 1]->contents) | |
2738 last_same--; | |
2739 | |
2740 for (i = last_same - 1; i < old_depth; i++) | |
2741 if (i >= last_same || !new_stack [i]->contents) | |
2742 XUnmapWindow (XtDisplay (mw), windows [i].window); | |
2743 } | |
2744 | |
2745 static Boolean | |
2746 motion_event_is_in_menu (XlwMenuWidget mw, XMotionEvent *ev, int level, | |
2747 XPoint *relative_pos) | |
2748 { | |
2749 window_state *ws = &mw->menu.windows [level]; | |
2750 int x = level == 0 ? ws->x : ws->x + mw->menu.shadow_thickness; | |
2751 int y = level == 0 ? ws->y : ws->y + mw->menu.shadow_thickness; | |
2752 relative_pos->x = ev->x_root - x; | |
2753 relative_pos->y = ev->y_root - y; | |
2754 return (x < ev->x_root && ev->x_root < (int) (x + ws->width) && | |
2755 y < ev->y_root && ev->y_root < (int) (y + ws->height)); | |
2756 } | |
2757 | |
2758 static Boolean | |
2759 map_event_to_widget_value (XlwMenuWidget mw, XMotionEvent *ev, | |
2760 widget_value **val_ptr, int *level, | |
2761 Boolean *inside_menu) | |
2762 { | |
2763 int i; | |
2764 XPoint relative_pos; | |
2765 window_state* ws; | |
2766 | |
2767 *val_ptr = NULL; | |
2768 *inside_menu = False; | |
2769 | |
2770 /* Find the window */ | |
2771 #if 1 | |
2772 for (i = mw->menu.old_depth - 1; i >= 0; i--) | |
2773 #else | |
2774 for (i = 0; i <= mw->menu.old_depth - 1; i++) | |
2775 #endif | |
2776 { | |
2777 ws = &mw->menu.windows [i]; | |
2778 if (ws && motion_event_is_in_menu (mw, ev, i, &relative_pos)) | |
2779 { | |
2780 *inside_menu = True; /* special logic for menubar below... */ | |
2781 if ((ev->type == ButtonPress) || | |
2782 (ev->state != 0)) | |
2783 { | |
2784 display_menu (mw, i, True, NULL, &relative_pos, | |
2785 val_ptr, NULL, NULL); | |
2786 if (*val_ptr) | |
2787 { | |
2788 *level = i + 1; | |
2789 *inside_menu = True; | |
2790 return True; | |
2791 } | |
2792 else if (mw->menu.horizontal || i == 0) | |
2793 { | |
2794 /* if we're clicking on empty part of the menubar, then | |
2795 unpost the stay-up menu */ | |
2796 *inside_menu = False; | |
2797 } | |
2798 } | |
2799 } | |
2800 } | |
2801 return False; | |
2802 } | |
2803 | |
2804 /* Procedures */ | |
2805 static void | |
2806 make_drawing_gcs (XlwMenuWidget mw) | |
2807 { | |
2808 XGCValues xgcv; | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
2809 #ifdef HAVE_XFT_MENUBARS |
3094 | 2810 unsigned long flags = (GCForeground | GCBackground); |
2811 #else | |
428 | 2812 unsigned long flags = (GCFont | GCForeground | GCBackground); |
3094 | 2813 #endif |
2814 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
2815 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 2816 xgcv.font = default_font_of_font_list (mw->menu.font_list)->fid; |
2817 #else | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
2818 #ifndef HAVE_XFT_MENUBARS |
428 | 2819 xgcv.font = mw->menu.font->fid; |
2820 #endif | |
3094 | 2821 #endif |
428 | 2822 |
2823 xgcv.foreground = mw->core.background_pixel; | |
2824 xgcv.background = mw->menu.foreground; | |
2825 mw->menu.background_gc = XtGetGC ((Widget) mw, flags, &xgcv); | |
2826 | |
2827 xgcv.foreground = mw->menu.foreground; | |
2828 xgcv.background = mw->core.background_pixel; | |
2829 mw->menu.foreground_gc = XtGetGC ((Widget) mw, flags, &xgcv); | |
2830 | |
2831 if (mw->menu.select_color != (Pixel)-1) | |
2832 { | |
2833 xgcv.foreground = mw->menu.select_color; | |
2834 } | |
2835 else | |
2836 { | |
2837 Display *dpy = XtDisplay(mw); | |
2838 if (CellsOfScreen(DefaultScreenOfDisplay(dpy)) <= 2) | |
2839 { /* mono */ | |
2840 xgcv.foreground = mw->menu.foreground; | |
2841 } | |
2842 else | |
2843 { /* color */ | |
2844 XColor xcolor; | |
3094 | 2845 Visual *visual; |
2846 int ignore; | |
3157 | 2847 Colormap cmap; |
3094 | 2848 visual_info_from_widget ((Widget) mw, &visual, &ignore); |
3157 | 2849 cmap = mw->core.colormap; |
428 | 2850 xcolor.pixel = mw->core.background_pixel; |
2851 XQueryColor (dpy, cmap, &xcolor); | |
2852 xcolor.red = (xcolor.red * 17) / 20; | |
2853 xcolor.green = (xcolor.green * 17) / 20; | |
2854 xcolor.blue = (xcolor.blue * 17) / 20; | |
3094 | 2855 if (x_allocate_nearest_color (dpy, cmap, visual, &xcolor)) |
428 | 2856 xgcv.foreground = xcolor.pixel; |
2857 } | |
2858 } | |
2859 xgcv.background = mw->core.background_pixel; | |
3094 | 2860 mw->menu.select_gc = XtGetGC ((Widget) mw, flags, &xgcv); |
428 | 2861 |
2862 xgcv.foreground = mw->menu.foreground; | |
2863 xgcv.background = mw->core.background_pixel; | |
2864 xgcv.fill_style = FillStippled; | |
2865 xgcv.stipple = mw->menu.gray_pixmap; | |
2866 mw->menu.inactive_gc = XtGetGC ((Widget)mw, | |
2867 (flags | GCFillStyle | GCStipple), | |
2868 &xgcv); | |
2869 | |
2870 xgcv.foreground = mw->menu.highlight_foreground; | |
2871 xgcv.background = mw->core.background_pixel; | |
2872 mw->menu.highlight_gc = XtGetGC ((Widget)mw, flags, &xgcv); | |
2873 | |
2874 xgcv.foreground = mw->menu.title_foreground; | |
2875 xgcv.background = mw->core.background_pixel; | |
2876 mw->menu.title_gc = XtGetGC ((Widget)mw, flags, &xgcv); | |
2877 | |
2878 xgcv.foreground = mw->menu.button_foreground; | |
2879 xgcv.background = mw->core.background_pixel; | |
2880 mw->menu.button_gc = XtGetGC ((Widget)mw, flags, &xgcv); | |
2881 | |
2882 xgcv.fill_style = FillStippled; | |
2883 xgcv.stipple = mw->menu.gray_pixmap; | |
2884 mw->menu.inactive_button_gc = XtGetGC ((Widget)mw, | |
2885 (flags | GCFillStyle | GCStipple), | |
2886 &xgcv); | |
2887 } | |
2888 | |
2889 static void | |
2890 release_drawing_gcs (XlwMenuWidget mw) | |
2891 { | |
3094 | 2892 |
428 | 2893 XtReleaseGC ((Widget) mw, mw->menu.foreground_gc); |
2894 XtReleaseGC ((Widget) mw, mw->menu.button_gc); | |
2895 XtReleaseGC ((Widget) mw, mw->menu.highlight_gc); | |
2896 XtReleaseGC ((Widget) mw, mw->menu.title_gc); | |
2897 XtReleaseGC ((Widget) mw, mw->menu.inactive_gc); | |
2898 XtReleaseGC ((Widget) mw, mw->menu.inactive_button_gc); | |
2899 XtReleaseGC ((Widget) mw, mw->menu.background_gc); | |
2900 XtReleaseGC ((Widget) mw, mw->menu.select_gc); | |
2901 /* let's get some segvs if we try to use these... */ | |
2902 mw->menu.foreground_gc = (GC) -1; | |
2903 mw->menu.button_gc = (GC) -1; | |
2904 mw->menu.highlight_gc = (GC) -1; | |
2905 mw->menu.title_gc = (GC) -1; | |
2906 mw->menu.inactive_gc = (GC) -1; | |
2907 mw->menu.inactive_button_gc = (GC) -1; | |
2908 mw->menu.background_gc = (GC) -1; | |
2909 mw->menu.select_gc = (GC) -1; | |
2910 } | |
2911 | |
2912 static void | |
2913 make_shadow_gcs (XlwMenuWidget mw) | |
2914 { | |
2915 XGCValues xgcv; | |
2916 unsigned long pm = 0; | |
2917 Display *dpy = XtDisplay ((Widget) mw); | |
2918 Colormap cmap = mw->core.colormap; | |
3094 | 2919 Visual *visual; |
2920 int ignored; | |
428 | 2921 XColor topc, botc; |
2922 int top_frobbed = 0, bottom_frobbed = 0; | |
2923 | |
3094 | 2924 visual_info_from_widget ((Widget) mw, &visual, &ignored); |
2925 /* #### Apparently this is called before any shell has a visual? | |
2926 or maybe the widget doesn't have a parent yet? */ | |
2927 if (visual == CopyFromParent) | |
2928 { | |
2929 Screen *screen = DefaultScreenOfDisplay (dpy); | |
2930 visual = DefaultVisualOfScreen (screen); | |
2931 } | |
2932 | |
428 | 2933 if (mw->menu.top_shadow_color == (Pixel) (-1)) |
2934 mw->menu.top_shadow_color = mw->core.background_pixel; | |
2935 if (mw->menu.bottom_shadow_color == (Pixel) (-1)) | |
2936 mw->menu.bottom_shadow_color = mw->menu.foreground; | |
2937 | |
2938 if (mw->menu.top_shadow_color == mw->core.background_pixel || | |
2939 mw->menu.top_shadow_color == mw->menu.foreground) | |
2940 { | |
2941 topc.pixel = mw->core.background_pixel; | |
2942 XQueryColor (dpy, cmap, &topc); | |
2943 /* don't overflow/wrap! */ | |
2944 topc.red = MINL (65535, topc.red * 1.2); | |
2945 topc.green = MINL (65535, topc.green * 1.2); | |
2946 topc.blue = MINL (65535, topc.blue * 1.2); | |
3094 | 2947 if (x_allocate_nearest_color (dpy, cmap, visual, &topc)) |
428 | 2948 { |
2949 if (topc.pixel == mw->core.background_pixel) | |
2950 { | |
2951 XFreeColors( dpy, cmap, &topc.pixel, 1, 0); | |
2952 topc.red = MINL (65535, topc.red + 0x8000); | |
2953 topc.green = MINL (65535, topc.green + 0x8000); | |
2954 topc.blue = MINL (65535, topc.blue + 0x8000); | |
3094 | 2955 if (x_allocate_nearest_color (dpy, cmap, visual, &topc)) |
428 | 2956 { |
2957 mw->menu.top_shadow_color = topc.pixel; | |
2958 } | |
2959 } | |
2960 else | |
2961 { | |
2962 mw->menu.top_shadow_color = topc.pixel; | |
2963 } | |
2964 | |
2965 top_frobbed = 1; | |
2966 } | |
2967 } | |
2968 if (mw->menu.bottom_shadow_color == mw->menu.foreground || | |
2969 mw->menu.bottom_shadow_color == mw->core.background_pixel) | |
2970 { | |
2971 botc.pixel = mw->core.background_pixel; | |
2972 XQueryColor (dpy, cmap, &botc); | |
2973 botc.red = (botc.red * 3) / 5; | |
2974 botc.green = (botc.green * 3) / 5; | |
2975 botc.blue = (botc.blue * 3) / 5; | |
3094 | 2976 if (x_allocate_nearest_color (dpy, cmap, visual, &botc)) |
428 | 2977 { |
2978 if (botc.pixel == mw->core.background_pixel) | |
2979 { | |
2980 XFreeColors (dpy, cmap, &botc.pixel, 1, 0); | |
2981 botc.red = MINL (65535, botc.red + 0x4000); | |
2982 botc.green = MINL (65535, botc.green + 0x4000); | |
2983 botc.blue = MINL (65535, botc.blue + 0x4000); | |
3094 | 2984 if (x_allocate_nearest_color (dpy, cmap, visual, &botc)) |
428 | 2985 { |
2986 mw->menu.bottom_shadow_color = botc.pixel; | |
2987 } | |
2988 } | |
2989 else | |
2990 { | |
2991 mw->menu.bottom_shadow_color = botc.pixel; | |
2992 } | |
2993 | |
2994 bottom_frobbed = 1; | |
2995 } | |
2996 } | |
2997 | |
2998 if (top_frobbed && bottom_frobbed) | |
2999 { | |
3000 int top_avg = ((topc.red / 3) + (topc.green / 3) + (topc.blue / 3)); | |
3001 int bot_avg = ((botc.red / 3) + (botc.green / 3) + (botc.blue / 3)); | |
3002 if (bot_avg > top_avg) | |
3003 { | |
3004 Pixel tmp = mw->menu.top_shadow_color; | |
3005 mw->menu.top_shadow_color = mw->menu.bottom_shadow_color; | |
3006 mw->menu.bottom_shadow_color = tmp; | |
3007 } | |
3008 else if (topc.pixel == botc.pixel) | |
3009 { | |
3010 if (botc.pixel == mw->menu.foreground) | |
3011 mw->menu.top_shadow_color = mw->core.background_pixel; | |
3012 else | |
3013 mw->menu.bottom_shadow_color = mw->menu.foreground; | |
3014 } | |
3015 } | |
3016 | |
3017 if (!mw->menu.top_shadow_pixmap && | |
3018 mw->menu.top_shadow_color == mw->core.background_pixel) | |
3019 { | |
3020 mw->menu.top_shadow_pixmap = mw->menu.gray_pixmap; | |
3021 mw->menu.top_shadow_color = mw->menu.foreground; | |
3022 } | |
3023 if (!mw->menu.bottom_shadow_pixmap && | |
3024 mw->menu.bottom_shadow_color == mw->core.background_pixel) | |
3025 { | |
3026 mw->menu.bottom_shadow_pixmap = mw->menu.gray_pixmap; | |
3027 mw->menu.bottom_shadow_color = mw->menu.foreground; | |
3028 } | |
3029 | |
3030 xgcv.fill_style = FillOpaqueStippled; | |
3031 xgcv.foreground = mw->menu.top_shadow_color; | |
3032 xgcv.background = mw->core.background_pixel; | |
3033 /* xgcv.stipple = mw->menu.top_shadow_pixmap; gtb */ | |
3034 if (mw->menu.top_shadow_pixmap && | |
3035 mw->menu.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP) | |
3036 xgcv.stipple = mw->menu.top_shadow_pixmap; | |
3037 else | |
3038 xgcv.stipple = 0; | |
3039 pm = (xgcv.stipple ? GCStipple|GCFillStyle : 0); | |
3040 mw->menu.shadow_top_gc = | |
3041 XtGetGC((Widget)mw, GCForeground|GCBackground|pm, &xgcv); | |
3042 | |
3043 xgcv.foreground = mw->menu.bottom_shadow_color; | |
3044 /* xgcv.stipple = mw->menu.bottom_shadow_pixmap; gtb */ | |
3045 if (mw->menu.bottom_shadow_pixmap && | |
3046 mw->menu.bottom_shadow_pixmap != XmUNSPECIFIED_PIXMAP) | |
3047 xgcv.stipple = mw->menu.bottom_shadow_pixmap; | |
3048 else | |
3049 xgcv.stipple = 0; | |
3050 pm = (xgcv.stipple ? GCStipple|GCFillStyle : 0); | |
3051 mw->menu.shadow_bottom_gc = | |
3052 XtGetGC ((Widget)mw, GCForeground|GCBackground|pm, &xgcv); | |
3053 } | |
3054 | |
3055 | |
3056 static void | |
3057 release_shadow_gcs (XlwMenuWidget mw) | |
3058 { | |
3059 XtReleaseGC ((Widget) mw, mw->menu.shadow_top_gc); | |
3060 XtReleaseGC ((Widget) mw, mw->menu.shadow_bottom_gc); | |
3061 } | |
3062 | |
3063 | |
3064 static void | |
3065 extract_font_extents (XlwMenuWidget mw) | |
3066 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3067 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 3068 /* Find the maximal ascent/descent of the fonts in the font list |
3069 so that all menu items can be the same height... */ | |
3070 mw->menu.font_ascent = 0; | |
3071 mw->menu.font_descent = 0; | |
3072 | |
3073 { | |
3074 XmFontContext context; | |
3075 #if (XmVersion >= 1002) | |
3076 XmFontListEntry fontentry; | |
3077 #else | |
3078 XmStringCharSet charset; | |
3079 #endif | |
3080 XFontStruct *font; | |
3081 | |
3082 if (! XmFontListInitFontContext (&context, mw->menu.font_list)) | |
3083 abort (); | |
3084 #if (XmVersion >= 1002) | |
3085 /* There is a BUG in the 1.2 version of XmFontListGetNextFont() (or more | |
3086 specifically, in _XmGetFirstFont()) that can cause a null pointer to be | |
3087 passed to XFontsOfFontSet. Use XmFontListNextEntry(), which is the | |
3088 newer equivalent, instead. Also, it supports font sets, and the | |
3089 older function doesn't. */ | |
3090 while ((fontentry = XmFontListNextEntry (context))) | |
3091 { | |
3092 XmFontType rettype; | |
3093 | |
3094 XtPointer one_of_them = XmFontListEntryGetFont (fontentry, &rettype); | |
3095 if (rettype == XmFONT_IS_FONTSET) | |
3096 { | |
3097 XFontSet fontset = (XFontSet) one_of_them; | |
3098 XFontStruct **fontstruct_list; | |
3099 char **fontname_list; | |
3100 int fontcount = XFontsOfFontSet (fontset, &fontstruct_list, | |
3101 &fontname_list); | |
3102 while (--fontcount >= 0) | |
3103 { | |
3104 font = fontstruct_list[fontcount]; | |
3105 if (font->ascent > (int) mw->menu.font_ascent) | |
3106 mw->menu.font_ascent = font->ascent; | |
3107 if (font->descent > (int) mw->menu.font_descent) | |
3108 mw->menu.font_descent = font->descent; | |
3109 } | |
3110 } | |
3111 else /* XmFONT_IS_FONT */ | |
3112 { | |
3113 font = (XFontStruct *) one_of_them; | |
3114 if (font->ascent > (int) mw->menu.font_ascent) | |
3115 mw->menu.font_ascent = font->ascent; | |
3116 if (font->descent > (int) mw->menu.font_descent) | |
3117 mw->menu.font_descent = font->descent; | |
3118 } | |
3119 } | |
3120 #else /* motif 1.1 */ | |
3121 while (XmFontListGetNextFont (context, &charset, &font)) | |
3122 { | |
3123 if (font->ascent > (int) mw->menu.font_ascent) | |
3124 mw->menu.font_ascent = font->ascent; | |
3125 if (font->descent > (int) mw->menu.font_descent) | |
3126 mw->menu.font_descent = font->descent; | |
3127 XtFree (charset); | |
3128 } | |
3129 #endif /* Motif version */ | |
3130 XmFontListFreeFontContext (context); | |
3131 } | |
3132 #else /* Not Motif */ | |
3133 # ifdef USE_XFONTSET | |
3134 XFontStruct **fontstruct_list; | |
3135 char **fontname_list; | |
3136 XFontStruct *font; | |
3137 int fontcount = XFontsOfFontSet(mw->menu.font_set, &fontstruct_list, | |
3138 &fontname_list); | |
3139 mw->menu.font_ascent = 0; | |
3140 mw->menu.font_descent = 0; | |
3141 # if 0 /* nasty, personal debug, Kazz */ | |
3142 fprintf(stderr, "fontSet count is %d\n", fontcount); | |
3143 # endif | |
3144 while (--fontcount >= 0) { | |
3145 font = fontstruct_list[fontcount]; | |
3146 if (font->ascent > (int) mw->menu.font_ascent) | |
3147 mw->menu.font_ascent = font->ascent; | |
3148 if (font->descent > (int) mw->menu.font_descent) | |
3149 mw->menu.font_descent = font->descent; | |
3150 } | |
3151 # else /* ! USE_XFONTSET */ | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3152 #ifdef HAVE_XFT_MENUBARS |
3094 | 3153 mw->menu.font_ascent = mw->menu.renderFont->ascent; |
3154 mw->menu.font_descent = mw->menu.renderFont->descent; | |
3155 #else | |
428 | 3156 mw->menu.font_ascent = mw->menu.font->ascent; |
3157 mw->menu.font_descent = mw->menu.font->descent; | |
3094 | 3158 #endif |
428 | 3159 # endif |
3160 #endif /* NEED_MOTIF */ | |
3161 } | |
3162 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3163 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 3164 static XFontStruct * |
3165 default_font_of_font_list (XmFontList font_list) | |
3166 { | |
3167 XFontStruct *font = 0; | |
3168 # if 0 | |
3169 /* Xm/Label.c does this: */ | |
3170 _XmFontListGetDefaultFont (font_list, &font); | |
3171 # else /* !0 */ | |
3172 { | |
3173 XmFontContext context; | |
3174 #if (XmVersion >= 1002) | |
3175 XmFontListEntry fontentry; | |
3176 XmFontType rettype; | |
3177 XtPointer one_of_them; | |
3178 #else | |
3179 XmStringCharSet charset; | |
3180 #endif | |
3181 | |
3182 if (! XmFontListInitFontContext (&context, font_list)) | |
3183 abort (); | |
3184 #if (XmVersion >= 1002) | |
3185 /* There is a BUG in the 1.2 version of XmFontListGetNextFont() (or more | |
3186 specifically, in _XmGetFirstFont()) that can cause a null pointer to be | |
3187 passed to XFontsOfFontSet. Use XmFontListNextEntry(), which is the | |
3188 newer equivalent, instead. */ | |
3189 fontentry = XmFontListNextEntry (context); | |
3190 one_of_them = XmFontListEntryGetFont (fontentry, &rettype); | |
3191 if (rettype == XmFONT_IS_FONTSET) | |
3192 { | |
3193 XFontSet fontset = (XFontSet) one_of_them; | |
3194 XFontStruct **fontstruct_list; | |
3195 char **fontname_list; | |
3196 (void) XFontsOfFontSet (fontset, &fontstruct_list, &fontname_list); | |
3197 font = fontstruct_list[0]; | |
3198 } | |
3199 else /* XmFONT_IS_FONT */ | |
3200 { | |
3201 font = (XFontStruct *) one_of_them; | |
3202 } | |
3203 #else | |
3204 if (! XmFontListGetNextFont (context, &charset, &font)) | |
3205 abort (); | |
3206 XtFree (charset); | |
3207 #endif | |
3208 XmFontListFreeFontContext (context); | |
3209 } | |
3210 # endif /* !0 */ | |
3211 | |
3212 if (! font) abort (); | |
3213 return font; | |
3214 } | |
3215 #endif /* NEED_MOTIF */ | |
3216 | |
3217 static void | |
2286 | 3218 XlwMenuInitialize (Widget UNUSED (request), Widget new_, ArgList UNUSED (args), |
3219 Cardinal *UNUSED (num_args)) | |
428 | 3220 { |
3221 /* Get the GCs and the widget size */ | |
1201 | 3222 XlwMenuWidget mw = (XlwMenuWidget)new_; |
428 | 3223 Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw))); |
3224 Display *display = XtDisplay (mw); | |
3225 | |
3226 /* mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */ | |
3227 mw->menu.cursor = mw->menu.cursor_shape; | |
3228 | |
3229 mw->menu.gray_pixmap = | |
3230 XCreatePixmapFromBitmapData (display, window, (char *) gray_bits, | |
3231 gray_width, gray_height, 1, 0, 1); | |
3232 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3233 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
442 | 3234 /* #### Even if it's a kludge!!!, we should consider doing the same for |
3235 X Font Sets. */ | |
428 | 3236 /* The menu.font_list slot came from the *fontList resource (Motif standard.) |
3237 The menu.font_list_2 slot came from the *font resource, for backward | |
3238 compatibility with older versions of this code, and consistency with the | |
442 | 3239 rest of emacs. If both font and fontList are specified, we use fontList. |
428 | 3240 If only one is specified, we use that. If neither are specified, we |
3241 use the "fallback" value. What a kludge!!! | |
3242 | |
3243 Note that this has the bug that a more general wildcard like "*fontList:" | |
3244 will override a more specific resource like "Emacs*menubar.font:". But | |
3245 I can't think of a way around that. | |
3246 */ | |
3247 if (mw->menu.font_list) /* if *fontList is specified, use that */ | |
3248 ; | |
3249 else if (mw->menu.font_list_2) /* else if *font is specified, use that */ | |
3250 mw->menu.font_list = mw->menu.font_list_2; | |
3251 else /* otherwise use default */ | |
3252 mw->menu.font_list = mw->menu.fallback_font_list; | |
3253 #endif | |
3254 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3255 #ifdef HAVE_XFT_MENUBARS |
3685 | 3256 /* #### kludge for name change */ |
3257 if (!mw->menu.fcFontName) | |
3258 mw->menu.fcFontName = mw->menu.xftFontName; | |
3094 | 3259 /* to do this right, we should add a new Xt Resource type + |
3260 conversion function | |
3261 */ | |
3262 mw->menu.renderFont = | |
3397 | 3263 xft_open_font_by_name (XtDisplay (mw), mw->menu.fcFontName); |
3094 | 3264 #endif |
3265 | |
428 | 3266 make_drawing_gcs (mw); |
3267 make_shadow_gcs (mw); | |
3268 extract_font_extents (mw); | |
3269 | |
3270 mw->menu.popped_up = False; | |
3271 mw->menu.pointer_grabbed = False; | |
3272 mw->menu.next_release_must_exit = False; | |
3273 | |
3274 mw->menu.old_depth = 1; | |
3275 mw->menu.old_stack = XtNew (widget_value*); | |
3276 mw->menu.old_stack_length = 1; | |
3277 mw->menu.old_stack [0] = mw->menu.contents; | |
3278 | |
3279 mw->menu.new_depth = 0; | |
3280 mw->menu.new_stack = 0; | |
3281 mw->menu.new_stack_length = 0; | |
3282 push_new_stack (mw, mw->menu.contents); | |
3283 | |
3284 mw->menu.windows = XtNew (window_state); | |
3285 mw->menu.windows_length = 1; | |
3286 mw->menu.windows [0].x = 0; | |
3287 mw->menu.windows [0].y = 0; | |
3288 mw->menu.windows [0].width = 0; | |
3289 mw->menu.windows [0].height = 0; | |
3290 size_menu (mw, 0); | |
3291 | |
3292 mw->core.width = mw->menu.windows [0].width; | |
3293 mw->core.height = mw->menu.windows [0].height; | |
3294 } | |
3295 | |
3296 static void | |
3297 XlwMenuClassInitialize (void) | |
3298 { | |
3299 initialize_massaged_resource_char(); | |
3300 } | |
3301 | |
3302 static void | |
3303 XlwMenuRealize (Widget w, Mask *valueMask, XSetWindowAttributes *attributes) | |
3304 { | |
3305 XlwMenuWidget mw = (XlwMenuWidget)w; | |
3306 XSetWindowAttributes xswa; | |
446 | 3307 unsigned long mask; |
428 | 3308 |
3309 (*xlwMenuWidgetClass->core_class.superclass->core_class.realize) | |
3310 (w, valueMask, attributes); | |
3311 | |
3312 xswa.save_under = True; | |
3313 xswa.cursor = mw->menu.cursor_shape; | |
3314 mask = CWSaveUnder | CWCursor; | |
3315 if (mw->menu.use_backing_store) | |
3316 { | |
3317 xswa.backing_store = Always; | |
3318 mask |= CWBackingStore; | |
3319 } | |
3320 XChangeWindowAttributes (XtDisplay (w), XtWindow (w), mask, &xswa); | |
3321 | |
3322 mw->menu.windows [0].window = XtWindow (w); | |
3323 mw->menu.windows [0].x = w->core.x; | |
3324 mw->menu.windows [0].y = w->core.y; | |
3325 mw->menu.windows [0].width = w->core.width; | |
3326 mw->menu.windows [0].height = w->core.height; | |
3327 } | |
3328 | |
3329 /* Only the toplevel menubar/popup is a widget so it's the only one that | |
3330 receives expose events through Xt. So we repaint all the other panes | |
3331 when receiving an Expose event. */ | |
3332 static void | |
2286 | 3333 XlwMenuRedisplay (Widget w, XEvent *UNUSED (ev), Region UNUSED (region)) |
428 | 3334 { |
3335 XlwMenuWidget mw = (XlwMenuWidget)w; | |
3336 int i; | |
3337 | |
3338 if (mw->core.being_destroyed) return; | |
3339 | |
3340 for (i = 0; i < mw->menu.old_depth; i++) | |
3341 display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL); | |
3342 set_new_state (mw, NULL, mw->menu.old_depth); /* #### - ??? */ | |
3343 remap_menubar (mw); /* #### - do these two lines do anything? */ | |
3344 } | |
3345 | |
3346 static void | |
3347 XlwMenuDestroy (Widget w) | |
3348 { | |
3349 int i; | |
3350 XlwMenuWidget mw = (XlwMenuWidget) w; | |
3351 | |
3352 if (mw->menu.pointer_grabbed) | |
3353 { | |
3354 XtUngrabPointer (w, CurrentTime); | |
3355 mw->menu.pointer_grabbed = False; | |
3356 } | |
3357 | |
3358 release_drawing_gcs (mw); | |
3359 release_shadow_gcs (mw); | |
3360 | |
3361 /* this doesn't come from the resource db but is created explicitly | |
3362 so we must free it ourselves. */ | |
3363 XFreePixmap (XtDisplay (mw), mw->menu.gray_pixmap); | |
3364 mw->menu.gray_pixmap = (Pixmap) -1; | |
3365 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3366 #ifdef HAVE_XFT_MENUBARS |
4173 | 3367 XftFontClose (XtDisplay (mw), mw->menu.renderFont); |
3368 #endif | |
3369 | |
428 | 3370 /* Don't free mw->menu.contents because that comes from our creator. |
3371 The `*_stack' elements are just pointers into `contents' so leave | |
3372 that alone too. But free the stacks themselves. */ | |
3373 if (mw->menu.old_stack) XtFree ((char *) mw->menu.old_stack); | |
3374 if (mw->menu.new_stack) XtFree ((char *) mw->menu.new_stack); | |
3375 | |
3376 /* Remember, you can't free anything that came from the resource | |
3377 database. This includes: | |
3378 mw->menu.cursor | |
3379 mw->menu.top_shadow_pixmap | |
3380 mw->menu.bottom_shadow_pixmap | |
3381 mw->menu.font | |
3382 mw->menu.font_set | |
3383 Also the color cells of top_shadow_color, bottom_shadow_color, | |
3384 foreground, and button_foreground will never be freed until this | |
3385 client exits. Nice, eh? | |
3386 */ | |
3387 | |
3388 /* start from 1 because the one in slot 0 is w->core.window */ | |
3389 for (i = 1; i < mw->menu.windows_length; i++) | |
3390 XDestroyWindow (XtDisplay (mw), mw->menu.windows [i].window); | |
3391 if (mw->menu.windows) | |
3392 XtFree ((char *) mw->menu.windows); | |
3393 } | |
3394 | |
3395 static Boolean | |
2286 | 3396 XlwMenuSetValues (Widget current, Widget UNUSED (request), Widget new_, |
3397 ArgList UNUSED (args), Cardinal *UNUSED (num_args)) | |
428 | 3398 { |
3399 XlwMenuWidget oldmw = (XlwMenuWidget)current; | |
1201 | 3400 XlwMenuWidget newmw = (XlwMenuWidget)new_; |
428 | 3401 Boolean redisplay = False; |
3402 int i; | |
3403 | |
3404 if (newmw->menu.contents | |
3405 && newmw->menu.contents->contents | |
3406 && newmw->menu.contents->contents->change >= VISIBLE_CHANGE) | |
3407 redisplay = True; | |
3408 | |
3409 if (newmw->core.background_pixel != oldmw->core.background_pixel | |
3410 || newmw->menu.foreground != oldmw->menu.foreground | |
3411 /* For the XEditResource protocol, which may want to change the font. */ | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3412 #if defined(NEED_MOTIF) && !defined(HAVE_XFT_MENUBARS) |
428 | 3413 || newmw->menu.font_list != oldmw->menu.font_list |
3414 || newmw->menu.font_list_2 != oldmw->menu.font_list_2 | |
3415 || newmw->menu.fallback_font_list != oldmw->menu.fallback_font_list | |
3416 #else | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4528
diff
changeset
|
3417 #ifdef HAVE_XFT_MENUBARS |
3094 | 3418 || newmw->menu.renderFont != oldmw->menu.renderFont |
3419 #else | |
428 | 3420 || newmw->menu.font != oldmw->menu.font |
3421 #endif | |
3094 | 3422 #endif |
428 | 3423 ) |
3424 { | |
3425 release_drawing_gcs (newmw); | |
3426 make_drawing_gcs (newmw); | |
3427 redisplay = True; | |
3428 | |
3429 for (i = 0; i < oldmw->menu.windows_length; i++) | |
3430 { | |
3431 XSetWindowBackground (XtDisplay (oldmw), | |
3432 oldmw->menu.windows [i].window, | |
3433 newmw->core.background_pixel); | |
3434 /* clear windows and generate expose events */ | |
3435 XClearArea (XtDisplay (oldmw), oldmw->menu.windows[i].window, | |
3436 0, 0, 0, 0, True); | |
3437 } | |
3438 } | |
3439 | |
3440 return redisplay; | |
3441 } | |
3442 | |
3443 static void | |
3444 XlwMenuResize (Widget w) | |
3445 { | |
3446 XlwMenuWidget mw = (XlwMenuWidget)w; | |
3447 | |
3448 mw->menu.windows [0].width = mw->core.width; | |
3449 mw->menu.windows [0].height = mw->core.height; | |
3450 } | |
3451 | |
3452 /* Action procedures */ | |
3453 static void | |
3454 handle_single_motion_event (XlwMenuWidget mw, XMotionEvent *ev, | |
3455 Boolean select_p) | |
3456 { | |
3457 widget_value *val; | |
3458 Boolean stay_up; | |
3459 int level; | |
3460 | |
3461 if (!map_event_to_widget_value (mw, ev, &val, &level, &stay_up)) | |
3462 { | |
3463 /* we wind up here when: (a) the event is in the menubar, (b) the | |
3464 event isn't in the menubar or any of the panes, (c) the event is on | |
3465 a disabled menu item */ | |
3466 pop_new_stack_if_no_contents (mw); | |
3467 if (select_p && !stay_up) { | |
3468 /* pop down all menus and exit */ | |
3469 mw->menu.next_release_must_exit = True; | |
3470 set_new_state(mw, (val = NULL), 1); | |
3471 } | |
3472 } | |
3473 else | |
3474 { | |
3475 /* we wind up here when: (a) the event pops up a pull_right menu, | |
3476 (b) a menu item that is not disabled is highlighted */ | |
3477 if (select_p && mw->menu.bounce_down | |
3478 && close_to_reference_time((Widget)mw, | |
3479 mw->menu.menu_bounce_time, | |
3480 (XEvent *)ev)) | |
3481 { | |
3482 /* motion can cause more than one event. Don't bounce right back | |
3483 up if we've just bounced down. */ | |
3484 val = NULL; | |
3485 } | |
3486 else if (select_p && mw->menu.bounce_down && | |
3487 mw->menu.last_selected_val && | |
3488 (mw->menu.last_selected_val == val)) | |
3489 { | |
3490 val = NULL; /* assigned to mw->last_selected_val below */ | |
3491 mw->menu.menu_bounce_time = ev->time; | |
3492 /* popdown last menu if we're selecting the same menu item as we did | |
3493 last time and the XlwMenu.bounceDown resource is set, if the | |
3494 item is on the menubar itself, then exit. */ | |
3495 if (level == (mw->menu.popped_up ? 0 : 1)) | |
3496 mw->menu.next_release_must_exit = True; | |
3497 } | |
3498 else | |
3499 mw->menu.menu_bounce_time = 0; | |
3500 set_new_state (mw, val, level); | |
3501 } | |
3502 mw->menu.last_selected_val = val; | |
3503 remap_menubar (mw); | |
3504 | |
3505 /* Sync with the display. Makes it feel better on X terms. */ | |
3506 XFlush (XtDisplay (mw)); | |
3507 } | |
3508 | |
3509 static void | |
3510 handle_motion_event (XlwMenuWidget mw, XMotionEvent *ev, | |
3511 Boolean select_p) | |
3512 { | |
3513 int x = ev->x_root; | |
3514 int y = ev->y_root; | |
3515 unsigned int state = ev->state; | |
3516 XMotionEvent *event= ev, dummy; | |
3517 | |
3518 /* allow motion events to be generated again */ | |
3519 dummy.window = ev->window; | |
3520 if (ev->is_hint | |
3521 && XQueryPointer (XtDisplay (mw), dummy.window, | |
3522 &dummy.root, &dummy.subwindow, | |
3523 &dummy.x_root, &dummy.y_root, | |
3524 &dummy.x, &dummy.y, | |
3525 &dummy.state) | |
3526 && dummy.state == state | |
3527 && (dummy.x_root != x || dummy.y_root != y)) | |
3528 { | |
3529 /* don't handle the event twice or that breaks bounce_down. --Stig */ | |
3530 dummy.type = ev->type; | |
3531 event = &dummy; | |
3532 } | |
3533 | |
3534 lw_menu_accelerate = False; | |
3535 handle_single_motion_event (mw, event, select_p); | |
3536 } | |
3537 | |
3538 Time x_focus_timestamp_really_sucks_fix_me_better; | |
3539 | |
3540 static void | |
2286 | 3541 Start (Widget w, XEvent *ev, String *UNUSED (params), |
3542 Cardinal *UNUSED (num_params)) | |
428 | 3543 { |
3544 XlwMenuWidget mw = (XlwMenuWidget)w; | |
3545 | |
3546 lw_menubar_widget = w; | |
3547 | |
3548 lw_menu_active = True; | |
3549 | |
3550 if (!mw->menu.pointer_grabbed) | |
3551 { | |
3552 mw->menu.menu_post_time = ev->xbutton.time; | |
3553 mw->menu.menu_bounce_time = 0; | |
3554 mw->menu.next_release_must_exit = True; | |
3555 mw->menu.last_selected_val = NULL; | |
3556 x_focus_timestamp_really_sucks_fix_me_better = | |
3557 ((XButtonPressedEvent*)ev)->time; | |
3558 XtCallCallbackList ((Widget)mw, mw->menu.open, NULL); | |
3559 | |
3560 /* notes the absolute position of the menubar window */ | |
3561 mw->menu.windows [0].x = ev->xmotion.x_root - ev->xmotion.x; | |
3562 mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y; | |
3563 | |
3564 XtGrabPointer ((Widget)mw, False, | |
3565 (ButtonMotionMask | ButtonReleaseMask | ButtonPressMask), | |
3566 GrabModeAsync, GrabModeAsync, | |
3567 None, mw->menu.cursor_shape, | |
3568 ((XButtonPressedEvent*)ev)->time); | |
3569 mw->menu.pointer_grabbed = True; | |
3570 } | |
3571 | |
3572 /* handles the down like a move, slots are mostly compatible */ | |
3573 handle_motion_event (mw, &ev->xmotion, True); | |
3574 } | |
3575 | |
3576 static void | |
2286 | 3577 Drag (Widget w, XEvent *ev, String *UNUSED (params), |
3578 Cardinal *UNUSED (num_params)) | |
428 | 3579 { |
3580 XlwMenuWidget mw = (XlwMenuWidget)w; | |
3581 handle_motion_event (mw, &ev->xmotion, False); | |
3582 } | |
3583 | |
3584 static void | |
2286 | 3585 Select (Widget w, XEvent *ev, String *UNUSED (params), |
3586 Cardinal *UNUSED (num_params)) | |
428 | 3587 { |
3588 XlwMenuWidget mw = (XlwMenuWidget)w; | |
3589 widget_value *selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; | |
3590 | |
3591 lw_menu_accelerate = False; | |
3592 | |
3593 /* If user releases the button quickly, without selecting anything, | |
3594 after the initial down-click that brought the menu up, | |
3595 do nothing. */ | |
3596 if ((selected_item == 0 || selected_item->call_data == 0) | |
3597 && (!mw->menu.next_release_must_exit | |
3598 || close_to_reference_time(w, mw->menu.menu_post_time, ev))) | |
3599 { | |
3600 mw->menu.next_release_must_exit = False; | |
3601 return; | |
3602 } | |
3603 | |
3604 /* pop down everything */ | |
3605 mw->menu.new_depth = 1; | |
3606 remap_menubar (mw); | |
3607 | |
3608 /* Destroy() only gets called for popup menus. Menubar widgets aren't | |
3609 destroyed when their menu panes get nuked. */ | |
3610 if (mw->menu.pointer_grabbed) | |
3611 { | |
3612 XtUngrabPointer ((Widget)w, ev->xmotion.time); | |
3613 mw->menu.pointer_grabbed = False; | |
3614 } | |
3615 | |
3616 if (mw->menu.popped_up) | |
3617 { | |
3618 mw->menu.popped_up = False; | |
3619 XtPopdown (XtParent (mw)); | |
3620 } | |
3621 | |
3622 lw_menu_active = False; | |
3623 | |
3624 x_focus_timestamp_really_sucks_fix_me_better = | |
3625 ((XButtonPressedEvent*)ev)->time; | |
3626 | |
3627 /* callback */ | |
3628 XtCallCallbackList ((Widget) mw, mw->menu.select, (XtPointer) selected_item); | |
3629 } | |
3630 | |
3631 /* Action procedures for keyboard accelerators */ | |
3632 | |
3633 /* set the menu */ | |
3634 void | |
3635 xlw_set_menu (Widget w, widget_value *val) | |
3636 { | |
3637 lw_menubar_widget = w; | |
3638 set_new_state ((XlwMenuWidget)w, val, 1); | |
3639 } | |
3640 | |
3641 /* prepare the menu structure via the call-backs */ | |
3642 void | |
3643 xlw_map_menu (Time t) | |
3644 { | |
3645 XlwMenuWidget mw = (XlwMenuWidget)lw_menubar_widget; | |
3646 | |
3647 lw_menu_accelerate = True; | |
3648 | |
3649 if (!mw->menu.pointer_grabbed) | |
3650 { | |
3651 XWindowAttributes ret; | |
3462 | 3652 Window parent,root = 0UL; |
3653 Window *waste = NULL; | |
428 | 3654 unsigned int num_waste; |
3655 | |
3656 lw_menu_active = True; | |
3657 | |
3658 mw->menu.menu_post_time = t; | |
3659 mw->menu.menu_bounce_time = 0; | |
3660 | |
3661 mw->menu.next_release_must_exit = True; | |
3662 mw->menu.last_selected_val = NULL; | |
3663 | |
3664 XtCallCallbackList ((Widget)mw, mw->menu.open, NULL); | |
3665 | |
3666 /* do this for keyboards too! */ | |
3667 /* notes the absolute position of the menubar window */ | |
3668 /* | |
3669 mw->menu.windows [0].x = ev->xmotion.x_root - ev->xmotion.x; | |
3670 mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y; | |
3671 */ | |
3672 | |
3673 /* get the geometry of the menubar */ | |
3674 | |
3675 /* there has to be a better way than this. */ | |
3676 | |
3677 mw->menu.windows [0].x = 0; | |
3678 mw->menu.windows [0].y = 0; | |
3679 | |
3680 parent = XtWindow (lw_menubar_widget); | |
3681 do | |
3682 { | |
3683 XGetWindowAttributes (XtDisplay (lw_menubar_widget), parent, &ret); | |
3684 mw->menu.windows [0].x += ret.x; | |
3685 mw->menu.windows [0].y += ret.y; | |
3686 | |
3687 if (parent) | |
3688 XQueryTree (XtDisplay (lw_menubar_widget), parent, &root, &parent, &waste, | |
3689 &num_waste); | |
3690 if (waste) | |
3691 { | |
3692 XFree (waste); | |
3693 } | |
3694 } | |
3695 while (parent != root); | |
3696 | |
3697 XtGrabPointer ((Widget)mw, False, | |
3698 (ButtonMotionMask | ButtonReleaseMask | ButtonPressMask), | |
3699 GrabModeAsync, GrabModeAsync, | |
3700 None, mw->menu.cursor_shape, t); | |
3701 mw->menu.pointer_grabbed = True; | |
3702 } | |
3703 } | |
3704 | |
3705 /* display the stupid menu already */ | |
3706 void | |
2286 | 3707 xlw_display_menu (Time UNUSED (t)) |
428 | 3708 { |
3709 XlwMenuWidget mw = (XlwMenuWidget)lw_menubar_widget; | |
3710 | |
3711 lw_menu_accelerate = True; | |
3712 | |
3713 remap_menubar (mw); | |
3714 | |
3715 /* Sync with the display. Makes it feel better on X terms. */ | |
3716 XFlush (XtDisplay (mw)); | |
3717 } | |
3718 | |
3719 /* push a sub menu */ | |
3720 void | |
3721 xlw_push_menu (widget_value *val) | |
3722 { | |
3723 push_new_stack ((XlwMenuWidget)lw_menubar_widget, val); | |
3724 } | |
3725 | |
3726 /* pop a sub menu */ | |
3727 int | |
3728 xlw_pop_menu (void) | |
3729 { | |
3730 if (((XlwMenuWidget)lw_menubar_widget)->menu.new_depth > 0) | |
3731 ((XlwMenuWidget)lw_menubar_widget)->menu.new_depth --; | |
3732 else | |
3733 return 0; | |
3734 return 1; | |
3735 } | |
3736 | |
3737 void | |
3738 xlw_kill_menus (widget_value *val) | |
3739 { | |
3740 XlwMenuWidget mw = (XlwMenuWidget)lw_menubar_widget; | |
3741 | |
3742 lw_menu_accelerate = False; | |
3743 | |
3744 mw->menu.new_depth = 1; | |
3745 remap_menubar (mw); | |
3746 | |
3747 if (mw->menu.pointer_grabbed) | |
3748 { | |
3749 XtUngrabPointer (lw_menubar_widget, CurrentTime); | |
3750 mw->menu.pointer_grabbed = False; | |
3751 } | |
3752 | |
3753 lw_menu_active = False; | |
3754 XtCallCallbackList (lw_menubar_widget, mw->menu.select, (XtPointer)val); | |
3755 } | |
3756 | |
3757 /* set the menu item */ | |
3758 void | |
3759 xlw_set_item (widget_value *val) | |
3760 { | |
3761 if (((XlwMenuWidget)lw_menubar_widget)->menu.new_depth > 0) | |
3762 ((XlwMenuWidget) lw_menubar_widget)->menu.new_depth --; | |
3763 push_new_stack ((XlwMenuWidget) lw_menubar_widget, val); | |
3764 } | |
3765 | |
3766 /* get either the current entry or a list of all entries in the current submenu */ | |
3767 widget_value * | |
3768 xlw_get_entries (int allp) | |
3769 { | |
3770 XlwMenuWidget mw = (XlwMenuWidget)lw_menubar_widget; | |
3771 if (allp) | |
3772 { | |
3773 if (mw->menu.new_depth >= 2) | |
3774 return mw->menu.new_stack [mw->menu.new_depth - 2]->contents; | |
3775 else | |
3776 return mw->menu.new_stack[0]; | |
3777 } | |
3778 else | |
3779 if (mw->menu.new_depth >= 1) | |
3780 return mw->menu.new_stack [mw->menu.new_depth - 1]; | |
3781 | |
3782 return NULL; | |
3783 } | |
3784 | |
3785 int | |
3786 xlw_menu_level (void) | |
3787 { | |
3788 return ((XlwMenuWidget)lw_menubar_widget)->menu.new_depth; | |
3789 } | |
3790 | |
3791 | |
3792 /* Special code to pop-up a menu */ | |
3793 void | |
3794 xlw_pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event) | |
3795 { | |
3796 int x = event->x_root; | |
3797 int y = event->y_root; | |
3798 int w; | |
3799 int h; | |
3800 int borderwidth = mw->menu.shadow_thickness; | |
3801 Screen* screen = XtScreen (mw); | |
3802 | |
3803 mw->menu.menu_post_time = event->time; | |
3804 mw->menu.menu_bounce_time = 0; | |
3805 mw->menu.next_release_must_exit = True; | |
3806 mw->menu.last_selected_val = NULL; | |
3807 | |
3808 XtCallCallbackList ((Widget) mw, mw->menu.open, NULL); | |
3809 | |
3810 size_menu (mw, 0); | |
3811 | |
3812 w = mw->menu.windows [0].width; | |
3813 h = mw->menu.windows [0].height; | |
3814 | |
3815 x -= borderwidth; | |
3816 y -= borderwidth; | |
3817 | |
3818 if (x < borderwidth) | |
3819 x = borderwidth; | |
3820 | |
3821 if (x > WidthOfScreen (screen) - w - 2 * borderwidth) | |
3822 x = WidthOfScreen (screen) - w - 2 * borderwidth; | |
3823 | |
3824 if (y < borderwidth) | |
3825 y = borderwidth; | |
3826 | |
3827 if (y > HeightOfScreen (screen) - h - 2 * borderwidth) | |
3828 y = HeightOfScreen (screen) - h - 2 * borderwidth; | |
3829 | |
3830 mw->menu.popped_up = True; | |
3831 XtConfigureWidget (XtParent (mw), x, y, w, h, | |
3832 XtParent (mw)->core.border_width); | |
3833 XtPopup (XtParent (mw), XtGrabExclusive); | |
3834 display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL); | |
3835 if (!mw->menu.pointer_grabbed) | |
3836 { | |
3837 XtGrabPointer ((Widget)mw, False, | |
3838 (ButtonMotionMask | ButtonReleaseMask | ButtonPressMask), | |
3839 GrabModeAsync, GrabModeAsync, | |
3840 None, mw->menu.cursor_shape, event->time); | |
3841 mw->menu.pointer_grabbed = True; | |
3842 } | |
3843 | |
3844 mw->menu.windows [0].x = x + borderwidth; | |
3845 mw->menu.windows [0].y = y + borderwidth; | |
3846 | |
3847 handle_motion_event (mw, (XMotionEvent *) event, True); | |
3848 } | |
3849 | |
3850 /* #### unused */ | |
3851 #if 0 | |
3852 /* | |
3853 * This is a horrible function which should not be needed. | |
3854 * use it to put the resize method back the way the XlwMenu | |
3855 * class initializer put it. Motif screws with this when | |
3856 * the XlwMenu class gets instantiated. | |
3857 */ | |
3858 void | |
3859 xlw_unmunge_class_resize (Widget w) | |
3860 { | |
3861 if (w->core.widget_class->core_class.resize != XlwMenuResize) | |
3862 w->core.widget_class->core_class.resize = XlwMenuResize; | |
3863 } | |
3864 #endif /* 0 */ | |
3865 |