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