Mercurial > hg > xemacs-beta
annotate lwlib/xlwmenu.c @ 5554:a42e686a01bf
Automated merge with file:///Sources/xemacs-21.5-checked-out
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Wed, 24 Aug 2011 11:07:26 +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 |
