Mercurial > hg > xemacs-beta
annotate lwlib/xlwtabs.c @ 5569:d19b6e3bdf91
#'cl-defsubst-expand; avoid mutually-recursive symbol macros.
lisp/ChangeLog addition:
2011-09-10 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (cl-defsubst-expand):
Change set 2a6a8da4dd7c of
http://mid.gmane.org/19966.17522.332164.615228@parhasard.net
wasn't sufficiently comprehensive, symbol macros can be mutually
rather than simply recursive, and they can equally hang. Thanks
for the bug report, Michael Sperber, and for the test case,
Stephen Turnbull.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 10 Sep 2011 13:17:29 +0100 |
parents | 308d34e9f07d |
children | 574f0cded429 |
rev | line source |
---|---|
428 | 1 /* Tabs Widget for XEmacs. |
2 Copyright (C) 1999 Edward A. Falk | |
442 | 3 |
428 | 4 This file is part of XEmacs. |
442 | 5 |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
6 XEmacs is free software: you can redistribute it and/or modify it |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
7 under the terms of the GNU General Public License as published by the |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
8 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
9 option) any later version. |
442 | 10 |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
14 for more details. |
442 | 15 |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
16 You should have received a copy of the GNU General Public License |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
17 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
442 | 18 |
428 | 19 /* |
20 * Tabs.c - Index Tabs composite widget | |
21 * | |
22 * Author: Edward A. Falk | |
23 * falk@falconer.vip.best.com | |
24 * | |
25 * Date: July 29, 1997 | |
26 * | |
27 * | |
28 * Overall layout of this widget is as follows: | |
29 * | |
30 * ________ ,---------. _________ | |
31 * | label || Label || Label | \ tabs | |
32 * |________|| ||_________| / | |
33 * |+----------------------------+| \ | |
34 * || || | | |
35 * || child widget window || > frame | |
36 * |+----------------------------+| | | |
37 * +------------------------------+ / | |
38 * | |
39 * The height of the tabs includes the shadow width, top and bottom | |
40 * margins, and the height of the text. | |
41 * | |
42 * The height of the frame includes the top and bottom shadow width and the | |
43 * size of the child widget window. | |
44 * | |
45 * The tabs overlap the frame and each other vertically by the shadow | |
46 * width, so that when the topmost tab is drawn, it obliterates part of | |
47 * the frame. | |
48 */ | |
49 | |
3094 | 50 /* Synched up with: Tabs.c 1.27. |
51 | |
52 This file contains essential XEmacs-related fixes to the original | |
53 version of the Tabs widget. Be VERY careful about syncing if you ever | |
54 update to a more recent version. In general this is probably now a | |
55 bad idea. | |
56 | |
57 #### We need to check that various windows (the whole widget, or a single | |
58 tab) are of "reasonable" size, ie, we need to try for more sanity in the | |
59 geometry management routines. | |
60 */ | |
61 | |
434 | 62 /* |
63 * TODO: min child height = tab height | |
428 | 64 */ |
65 | |
66 #include <config.h> | |
67 #include <stdio.h> | |
68 | |
69 #include <X11/Xlib.h> | |
70 #include <X11/IntrinsicP.h> | |
71 #include <X11/StringDefs.h> | |
4769
5460287a3327
Remove support for pre-X11R5 systems, including systems without Xmu. See
Jerry James <james@xemacs.org>
parents:
4528
diff
changeset
|
72 #include <X11/Xmu/Drawing.h> |
5460287a3327
Remove support for pre-X11R5 systems, including systems without Xmu. See
Jerry James <james@xemacs.org>
parents:
4528
diff
changeset
|
73 #include <X11/Xmu/Misc.h> |
448 | 74 |
3094 | 75 /* #### This may be risky, lwlib-internal.h redefines abort() */ |
76 #include "lwlib-fonts.h" | |
77 #include "lwlib-colors.h" | |
448 | 78 #include "lwlib-internal.h" |
428 | 79 #include "xlwtabsP.h" |
80 #include "xlwgcs.h" | |
81 | |
3094 | 82 #define XFT_USE_HEIGHT_NOT_ASCENT_DESCENT 0 |
83 | |
84 /* #### These should probably be resources. */ | |
428 | 85 #define MIN_WID 10 |
86 #define MIN_HGT 10 | |
87 #define INDENT 3 /* tabs indented from edge by this much */ | |
88 #define SPACING 0 /* distance between tabs */ | |
89 #define SHADWID 1 /* default shadow width */ | |
90 #define TABDELTA 2 /* top tab grows this many pixels */ | |
91 #define TABLDELTA 2 /* top tab label offset this many pixels */ | |
92 | |
93 | |
94 /**************************************************************** | |
95 * | |
96 * IndexTabs Resources | |
97 * | |
98 ****************************************************************/ | |
99 | |
100 static char defaultTranslations[] = "\ | |
101 <BtnUp>: select() \n\ | |
102 <FocusIn>: highlight() \n\ | |
103 <FocusOut>: unhighlight() \n\ | |
104 <Key>Page_Up: page(up) \n\ | |
105 <Key>KP_Page_Up: page(up) \n\ | |
106 <Key>Prior: page(up) \n\ | |
107 <Key>KP_Prior: page(up) \n\ | |
108 <Key>Page_Down: page(down) \n\ | |
109 <Key>KP_Page_Down: page(down) \n\ | |
110 <Key>Next: page(down) \n\ | |
111 <Key>KP_Next: page(down) \n\ | |
112 <Key>Home: page(home) \n\ | |
113 <Key>KP_Home: page(home) \n\ | |
114 <Key>End: page(end) \n\ | |
115 <Key>KP_End: page(end) \n\ | |
116 <Key>Up: highlight(up) \n\ | |
117 <Key>KP_Up: highlight(up) \n\ | |
118 <Key>Down: highlight(down) \n\ | |
119 <Key>KP_Down: highlight(down) \n\ | |
120 <Key> : page(select) \n\ | |
121 " ; | |
122 | |
123 static char accelTable[] = " #augment\n\ | |
124 <Key>Page_Up: page(up) \n\ | |
125 <Key>KP_Page_Up: page(up) \n\ | |
126 <Key>Prior: page(up) \n\ | |
127 <Key>KP_Prior: page(up) \n\ | |
128 <Key>Page_Down: page(down) \n\ | |
129 <Key>KP_Page_Down: page(down) \n\ | |
130 <Key>Next: page(down) \n\ | |
131 <Key>KP_Next: page(down) \n\ | |
132 <Key>Home: page(home) \n\ | |
133 <Key>KP_Home: page(home) \n\ | |
134 <Key>End: page(end) \n\ | |
135 <Key>KP_End: page(end) \n\ | |
136 <Key>Up: highlight(up) \n\ | |
137 <Key>KP_Up: highlight(up) \n\ | |
138 <Key>Down: highlight(down) \n\ | |
139 <Key>KP_Down: highlight(down) \n\ | |
140 <Key> : page(select) \n\ | |
141 " ; | |
446 | 142 static XtAccelerators defaultAccelerators ; /* #### Never used */ |
428 | 143 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
144 static XtResource resources[] = { |
4522
fc7067b7f407
Backout last patch; forgot to specify file.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4521
diff
changeset
|
145 #define offset(field) XtOffsetOf(TabsRec, tabs.field) |
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 #define res(name,_class,intrepr,type,member,extrepr,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
147 Xt_RESOURCE (name, _class, intrepr, type, offset(member), extrepr, value) |
428 | 148 |
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 res (XtNselectInsensitive, XtCSelectInsensitive, XtRBoolean, Boolean, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
150 selectInsensitive, 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
|
151 res (XtNfont, XtCFont, XtRFontStruct, XFontStruct *, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
152 font, XtRString, XtDefaultFont), |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
153 #ifdef HAVE_XFT_TABS |
3397 | 154 /* #### Maybe use "-*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-1" here? |
155 or XtDefaultFont? */ | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
156 res (XtNfcFontName, XtCFcFontName, XtRString, String, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
157 fcFontName, XtRString, NULL), |
3397 | 158 /* #### This needs to be fixed to give a proper type and converter for |
159 XftFonts. See also xlwmenu.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
|
160 res (XtNxftFont, XtCXftFont, XtRString, String, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
161 xftFontName, XtRString, "Helvetica-12"), |
3094 | 162 #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
|
163 res (XtNinternalWidth, XtCWidth, XtRDimension, Dimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
164 internalWidth, XtRImmediate, 4), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
165 res (XtNinternalHeight, XtCHeight, XtRDimension, Dimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
166 internalHeight, XtRImmediate, 4), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
167 Xt_RESOURCE (XtNborderWidth, XtCBorderWidth, XtRDimension, Dimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
168 XtOffsetOf(RectObjRec,rectangle.border_width), 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
|
169 res (XtNtopWidget, XtCTopWidget, XtRWidget, Widget, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
170 topWidget, 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
|
171 res (XtNcallback, XtCCallback, XtRCallback, XtPointer, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
172 callbacks, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
173 res (XtNpopdownCallback, XtCCallback, XtRCallback, XtPointer, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
174 popdownCallbacks, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
175 res (XtNbeNiceToColormap, XtCBeNiceToColormap, XtRBoolean, Boolean, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
176 be_nice_to_cmap, 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
|
177 res (XtNtopShadowContrast, XtCTopShadowContrast, XtRInt, int, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
178 top_shadow_contrast, XtRImmediate, 20), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
179 res (XtNbottomShadowContrast, XtCBottomShadowContrast, XtRInt, int, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
180 bot_shadow_contrast, XtRImmediate, 40), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
181 res (XtNinsensitiveContrast, XtCInsensitiveContrast, XtRInt, int, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
182 insensitive_contrast, XtRImmediate, 33), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
183 Xt_RESOURCE (XtNaccelerators, XtCAccelerators, XtRAcceleratorTable, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
184 XtTranslations, XtOffsetOf(TabsRec,core.accelerators), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
185 XtRString, accelTable), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
186 #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
|
187 #undef res |
4522
fc7067b7f407
Backout last patch; forgot to specify file.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4521
diff
changeset
|
188 }; |
428 | 189 |
190 | |
191 /* constraint resources */ | |
192 | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
193 static XtResource tabsConstraintResources[] = { |
4522
fc7067b7f407
Backout last patch; forgot to specify file.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4521
diff
changeset
|
194 #define offset(field) XtOffsetOf(TabsConstraintsRec, tabs.field) |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
195 #define res(name,_class,intrepr,type,member,extrepr,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
196 Xt_RESOURCE (name, _class, intrepr, type, offset(member), extrepr, value) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
197 res (XtNtabLabel, XtCLabel, XtRString, String, label, XtRString, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
198 res (XtNtabLeftBitmap, XtCLeftBitmap, XtRBitmap, Pixmap, left_bitmap, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
199 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
|
200 res (XtNtabForeground, XtCForeground, XtRPixel, Pixel, foreground, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
201 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
|
202 res (XtNresizable, XtCResizable, XtRBoolean, Boolean, resizable, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
203 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
|
204 #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
|
205 #undef res |
4522
fc7067b7f407
Backout last patch; forgot to specify file.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4521
diff
changeset
|
206 } ; |
428 | 207 |
208 | |
209 | |
210 | |
211 #if !NeedFunctionPrototypes | |
212 | |
213 /* FORWARD REFERENCES: */ | |
214 | |
215 /* member functions */ | |
216 | |
217 static void TabsClassInit(); | |
218 static void TabsInit(); | |
219 static void TabsResize(); | |
220 static void TabsExpose(); | |
221 static void TabsDestroy(); | |
222 static void TabsRealize(); | |
223 static Boolean TabsSetValues(); | |
434 | 224 static Boolean TabsAcceptFocus(); |
428 | 225 static XtGeometryResult TabsQueryGeometry(); |
226 static XtGeometryResult TabsGeometryManager(); | |
227 static void TabsChangeManaged(); | |
228 static void TabsConstraintInitialize() ; | |
229 static Boolean TabsConstraintSetValues() ; | |
230 | |
231 /* action procs */ | |
232 | |
233 static void TabsSelect() ; | |
234 static void TabsPage() ; | |
235 static void TabsHighlight() ; | |
236 static void TabsUnhighlight() ; | |
237 | |
238 /* internal privates */ | |
239 | |
240 static void TabsAllocGCs() ; /* get rendering GCs */ | |
241 static void TabsFreeGCs() ; /* return rendering GCs */ | |
242 static void DrawTabs() ; /* draw all tabs */ | |
243 static void DrawTab() ; /* draw one index tab */ | |
244 static void DrawFrame() ; /* draw frame around contents */ | |
245 static void DrawTrim() ; /* draw trim around a tab */ | |
246 static void DrawBorder() ; /* draw border */ | |
247 static void DrawHighlight() ; /* draw highlight */ | |
248 static void UndrawTab() ; /* undraw interior of a tab */ | |
249 static void TabWidth() ; /* recompute tab size */ | |
250 static void GetPreferredSizes() ; /* query all children for their sizes */ | |
251 static void MaxChild() ; /* find max preferred child size */ | |
252 static int PreferredSize() ; /* compute preferred size */ | |
253 static int PreferredSize2() ; /* compute preferred size */ | |
254 static int PreferredSize3() ; /* compute preferred size */ | |
255 static void MakeSizeRequest() ; /* try to change size */ | |
256 static void getBitmapInfo() ; | |
257 static int TabLayout() ; /* lay out tabs */ | |
258 static void TabsShuffleRows() ; /* bring current tab to bottom row */ | |
259 | |
260 static void TabsAllocFgGC() ; | |
261 static void TabsAllocGreyGC() ; | |
262 | |
263 #else | |
264 | |
265 static void TabsClassInit(void) ; | |
3025 | 266 static void TabsInit( Widget req, Widget new_, ArgList, Cardinal *nargs) ; |
428 | 267 static void TabsConstraintInitialize(Widget, Widget, ArgList, Cardinal *) ; |
268 static void TabsRealize(Widget, Mask *, XSetWindowAttributes *) ; | |
269 static void TabsDestroy( Widget w) ; | |
270 static void TabsResize( Widget w) ; | |
271 static void TabsExpose( Widget w, XEvent *event, Region region) ; | |
272 static Boolean TabsSetValues(Widget, Widget, Widget, ArgList, Cardinal *) ; | |
434 | 273 static Boolean TabsAcceptFocus(Widget, Time *); |
428 | 274 static Boolean TabsConstraintSetValues(Widget, Widget, Widget, |
275 ArgList, Cardinal *) ; | |
276 static XtGeometryResult TabsQueryGeometry(Widget, | |
277 XtWidgetGeometry *, XtWidgetGeometry *) ; | |
278 static XtGeometryResult TabsGeometryManager(Widget, | |
279 XtWidgetGeometry *, XtWidgetGeometry *) ; | |
280 static void TabsChangeManaged( Widget w) ; | |
281 | |
282 static void TabsSelect(Widget, XEvent *, String *, Cardinal *) ; | |
283 static void TabsPage(Widget, XEvent *, String *, Cardinal *) ; | |
284 static void TabsHighlight(Widget, XEvent *, String *, Cardinal *) ; | |
285 static void TabsUnhighlight(Widget, XEvent *, String *, Cardinal *) ; | |
286 | |
287 static void DrawTabs( TabsWidget tw, Bool labels) ; | |
288 static void DrawTab( TabsWidget tw, Widget child, Bool labels) ; | |
289 static void DrawFrame( TabsWidget tw) ; | |
290 static void DrawTrim( TabsWidget, int x, int y, | |
291 int wid, int hgt, Bool bottom, Bool undraw) ; | |
292 static void DrawBorder( TabsWidget tw, Widget child, Bool undraw) ; | |
293 static void DrawHighlight( TabsWidget tw, Widget child, Bool undraw) ; | |
294 static void UndrawTab( TabsWidget tw, Widget child) ; | |
295 | |
296 static void TabWidth( Widget w) ; | |
448 | 297 static int TabLayout( TabsWidget, Dimension wid, Dimension hgt, Dimension *r_hgt, |
428 | 298 Bool query_only) ; |
299 static void GetPreferredSizes(TabsWidget) ; | |
434 | 300 static void MaxChild(TabsWidget, Widget except, Dimension, Dimension) ; |
428 | 301 static void TabsShuffleRows( TabsWidget tw) ; |
302 static int PreferredSize( TabsWidget, | |
303 Dimension *reply_width, Dimension *reply_height, | |
304 Dimension *reply_cw, Dimension *reply_ch) ; | |
448 | 305 static int PreferredSize2( TabsWidget, Dimension cw, Dimension ch, |
428 | 306 Dimension *rw, Dimension *rh) ; |
448 | 307 static int PreferredSize3( TabsWidget, Dimension wid, Dimension hgt, |
428 | 308 Dimension *rw, Dimension *rh) ; |
309 static void MakeSizeRequest(TabsWidget) ; | |
310 | |
311 static void TabsAllocGCs(TabsWidget) ; | |
312 static void TabsFreeGCs(TabsWidget) ; | |
313 static void getBitmapInfo( TabsWidget tw, TabsConstraints tab) ; | |
314 static void TabsAllocFgGC( TabsWidget tw) ; | |
315 static void TabsAllocGreyGC( TabsWidget tw) ; | |
316 | |
317 #endif | |
318 | |
319 #define AddRect(i,xx,yy,w,h) \ | |
320 do{rects[(i)].x=(xx); rects[i].y=(yy); \ | |
321 rects[i].width=(w); rects[i].height=(h);}while(0) | |
322 | |
323 static XtActionsRec actionsList[] = | |
324 { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
325 { (String) "select", TabsSelect }, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
326 { (String) "page", TabsPage }, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
327 { (String) "highlight", TabsHighlight }, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
328 { (String) "unhighlight", TabsUnhighlight }, |
428 | 329 } ; |
330 | |
331 | |
332 /**************************************************************** | |
333 * | |
334 * Full class record constant | |
335 * | |
336 ****************************************************************/ | |
337 | |
338 #ifndef NEED_MOTIF | |
339 #define SuperClass (&constraintClassRec) | |
340 #else | |
341 #define SuperClass (&xmManagerClassRec) | |
342 #endif | |
343 | |
344 TabsClassRec tabsClassRec = { | |
345 { | |
346 /* core_class fields */ | |
347 /* superclass */ (WidgetClass) 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
|
348 /* class_name */ (String) "Tabs", |
428 | 349 /* widget_size */ sizeof(TabsRec), |
350 /* class_initialize */ TabsClassInit, | |
351 /* class_part_init */ NULL, /* TODO? */ | |
352 /* class_inited */ FALSE, | |
353 /* initialize */ TabsInit, | |
354 /* initialize_hook */ NULL, | |
355 /* realize */ TabsRealize, | |
356 /* actions */ actionsList, | |
357 /* num_actions */ XtNumber(actionsList), | |
358 /* resources */ resources, | |
359 /* num_resources */ XtNumber(resources), | |
360 /* xrm_class */ NULLQUARK, | |
361 /* compress_motion */ TRUE, | |
434 | 362 #if XtSpecificationRelease < 6 |
363 /* compress_exposure */ XtExposeCompressMaximal, | |
364 #else | |
365 /* compress_exposure */ XtExposeCompressMaximal|XtExposeNoRegion, | |
366 #endif | |
428 | 367 /* compress_enterleave*/ TRUE, |
434 | 368 /* visible_interest */ TRUE, |
428 | 369 /* destroy */ TabsDestroy, |
370 /* resize */ TabsResize, | |
371 /* expose */ TabsExpose, | |
372 /* set_values */ TabsSetValues, | |
373 /* set_values_hook */ NULL, | |
374 /* set_values_almost */ XtInheritSetValuesAlmost, | |
375 /* get_values_hook */ NULL, | |
434 | 376 /* accept_focus */ TabsAcceptFocus, |
428 | 377 /* version */ XtVersion, |
378 /* callback_private */ NULL, | |
379 /* tm_table */ defaultTranslations, | |
380 /* query_geometry */ TabsQueryGeometry, | |
381 /* display_accelerator*/ XtInheritDisplayAccelerator, | |
382 /* extension */ NULL | |
383 }, | |
384 { | |
385 /* composite_class fields */ | |
386 /* geometry_manager */ TabsGeometryManager, | |
387 /* change_managed */ TabsChangeManaged, | |
388 /* insert_child */ XtInheritInsertChild, /* TODO? */ | |
389 /* delete_child */ XtInheritDeleteChild, /* TODO? */ | |
390 /* extension */ NULL | |
391 }, | |
392 { | |
393 /* constraint_class fields */ | |
394 /* subresources */ tabsConstraintResources, | |
395 /* subresource_count */ XtNumber(tabsConstraintResources), | |
396 /* constraint_size */ sizeof(TabsConstraintsRec), | |
397 /* initialize */ TabsConstraintInitialize, | |
398 /* destroy */ NULL, | |
399 /* set_values */ TabsConstraintSetValues, | |
400 /* extension */ NULL, | |
401 }, | |
402 #ifdef NEED_MOTIF | |
403 /* Manager Class fields */ | |
404 { | |
405 /* translations */ NULL, | |
406 /* syn_resources */ NULL, | |
407 /* num_syn_resources */ 0, | |
408 /* syn_constraint_resources */ NULL, | |
409 /* num_syn_constraint_resources */ 0, | |
410 /* parent_process */ XmInheritParentProcess, | |
411 /* extension */ NULL | |
412 }, | |
413 #endif | |
414 { | |
415 /* Tabs class fields */ | |
416 /* extension */ NULL, | |
417 } | |
418 }; | |
419 | |
420 WidgetClass tabsWidgetClass = (WidgetClass)&tabsClassRec; | |
421 | |
446 | 422 #define TabsNumChildren(tw) (((TabsWidget)tw)->composite.num_children) |
423 #define TabVisible(tab) \ | |
424 (XtIsManaged(tab) && \ | |
425 ((TabsConstraints)((tab)->core.constraints))->tabs.visible) | |
428 | 426 |
427 | |
3094 | 428 |
429 static int debug_tabs = 0; /* increase for more verbosity */ | |
430 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
431 #ifdef HAVE_XFT_TABS |
3094 | 432 /* #### duplicated from xlwmenu.c -- CLEAN THIS SHIT UP! |
433 Undeclared so define at top. */ | |
434 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ | |
435 ? ((unsigned long) (x)) : ((unsigned long) (y))) | |
436 | |
437 static int | |
438 x_xft_text_width (Display *dpy, XftFont *xft_font, FcChar8 *run, int len) | |
439 { | |
440 static XGlyphInfo glyphinfo; /* #### static? */ | |
441 | |
442 XftTextExtents8 (dpy, | |
443 xft_font, | |
444 run, len, &glyphinfo); | |
445 return glyphinfo.xOff; | |
446 } | |
447 #endif | |
448 | |
428 | 449 /**************************************************************** |
450 * | |
451 * Member Procedures | |
452 * | |
453 ****************************************************************/ | |
454 | |
455 static void | |
456 TabsClassInit(void) | |
457 { | |
458 defaultAccelerators = XtParseAcceleratorTable(accelTable) ; | |
459 /* TODO: register converter for labels? */ | |
460 } | |
461 | |
462 | |
463 | |
464 /* Init a newly created tabs widget. Compute height of tabs | |
465 * and optionally compute size of widget. */ | |
466 | |
467 /* ARGSUSED */ | |
468 | |
469 static void | |
3025 | 470 TabsInit(Widget request, Widget new_, ArgList UNUSED (args), |
2286 | 471 Cardinal *UNUSED (num_args)) |
428 | 472 { |
3025 | 473 TabsWidget newTw = (TabsWidget)new_; |
428 | 474 |
475 newTw->tabs.numRows = 0 ; | |
446 | 476 newTw->tabs.realRows = 0; |
428 | 477 |
478 GetPreferredSizes(newTw) ; | |
479 | |
480 /* height is easy, it's the same for all tabs: | |
481 * TODO: font height + height of tallest bitmap. | |
482 */ | |
483 newTw->tabs.tab_height = 2 * newTw->tabs.internalHeight + SHADWID ; | |
484 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
485 #ifdef HAVE_XFT_TABS |
3685 | 486 /* #### kludge for name change */ |
487 if (!newTw->tabs.fcFontName) | |
488 newTw->tabs.fcFontName = newTw->tabs.xftFontName; | |
3094 | 489 /* must get font here |
3685 | 490 #### to do this right, we should add a new Xt Resource type + |
491 conversion function */ | |
3094 | 492 newTw->tabs.renderFont = |
493 xft_open_font_by_name (XtDisplay ((Widget) newTw), | |
3397 | 494 newTw->tabs.fcFontName); |
3094 | 495 if (newTw->tabs.renderFont != NULL) |
496 #if XFT_USE_HEIGHT_NOT_ASCENT_DESCENT | |
497 newTw->tabs.tab_height += newTw->tabs.renderFont->height; | |
498 #else | |
499 newTw->tabs.tab_height += newTw->tabs.renderFont->ascent + | |
500 newTw->tabs.renderFont->descent; | |
501 #endif /* XFT_USE_HEIGHT_NOT_ASCENT_DESCENT */ | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
502 #else /* ! HAVE_XFT_TABS */ |
3094 | 503 if (newTw->tabs.font != NULL) |
428 | 504 newTw->tabs.tab_height += newTw->tabs.font->max_bounds.ascent + |
3094 | 505 newTw->tabs.font->max_bounds.descent; |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
506 #endif /* ! HAVE_XFT_TABS */ |
428 | 507 |
508 /* if size not explicitly set, set it to our preferred size now. */ | |
509 | |
510 if( request->core.width == 0 || request->core.height == 0 ) | |
511 { | |
512 Dimension w,h ; | |
513 PreferredSize(newTw, &w, &h, NULL,NULL) ; | |
3025 | 514 if( request->core.width == 0 ) new_->core.width = w ; |
515 if( request->core.height == 0 ) new_->core.height = h ; | |
516 XtClass(new_)->core_class.resize(new_) ; | |
428 | 517 } |
518 | |
519 /* defer GC allocation, etc., until Realize() time. */ | |
520 newTw->tabs.foregroundGC = | |
521 newTw->tabs.backgroundGC = | |
522 newTw->tabs.greyGC = | |
523 newTw->tabs.topGC = | |
524 newTw->tabs.botGC = None ; | |
525 | |
526 newTw->tabs.grey50 = None ; | |
527 | |
528 newTw->tabs.needs_layout = False ; | |
434 | 529 |
428 | 530 newTw->tabs.hilight = NULL ; |
531 | |
532 #ifdef NEED_MOTIF | |
533 newTw->manager.navigation_type = XmTAB_GROUP ; | |
534 newTw->manager.traversal_on = True ; | |
535 #endif | |
536 } | |
537 | |
538 | |
539 /* Init the constraint part of a new tab child. Compute the | |
540 * size of the tab. | |
541 */ | |
542 /* ARGSUSED */ | |
543 static void | |
3025 | 544 TabsConstraintInitialize(Widget UNUSED (request), Widget new_, |
2286 | 545 ArgList UNUSED (args), Cardinal *UNUSED (num_args)) |
428 | 546 { |
3025 | 547 TabsConstraints tab = (TabsConstraints) new_->core.constraints ; |
428 | 548 tab->tabs.greyAlloc = False ; /* defer allocation of pixel */ |
446 | 549 tab->tabs.visible = False ; |
428 | 550 |
3025 | 551 getBitmapInfo((TabsWidget)XtParent(new_), tab) ; |
552 TabWidth(new_) ; | |
428 | 553 } |
554 | |
555 | |
556 | |
557 /* Called when tabs widget first realized. Create the window | |
558 * and allocate the GCs | |
559 */ | |
560 | |
561 static void | |
562 TabsRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) | |
563 { | |
564 TabsWidget tw = (TabsWidget) w; | |
565 | |
566 attributes->bit_gravity = NorthWestGravity; | |
567 *valueMask |= CWBitGravity; | |
568 | |
569 SuperClass->core_class.realize(w, valueMask, attributes); | |
570 | |
571 TabsAllocGCs(tw) ; | |
572 } | |
573 | |
574 | |
575 | |
576 static void | |
577 TabsDestroy(Widget w) | |
578 { | |
4173 | 579 TabsWidget tw = (TabsWidget) w; |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
580 #ifdef HAVE_XFT_TABS |
4173 | 581 XftFontClose (XtDisplay (w), tw->tabs.renderFont); |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
582 #endif /* ! HAVE_XFT_TABS */ |
4173 | 583 TabsFreeGCs (tw) ; |
428 | 584 } |
585 | |
586 | |
587 /* Parent has resized us. This will require that the tabs be | |
588 * laid out again. | |
589 */ | |
590 | |
591 static void | |
592 TabsResize(Widget w) | |
593 { | |
594 TabsWidget tw = (TabsWidget) w; | |
595 int i ; | |
596 int num_children = tw->composite.num_children ; | |
597 Widget *childP ; | |
2286 | 598 /* TabsConstraints tab ; */ /* #### unused */ |
428 | 599 Dimension cw,ch,bw ; |
600 | |
601 /* Our size has now been dictated by the parent. Lay out the | |
602 * tabs, lay out the frame, lay out the children. Remember | |
603 * that the tabs overlap each other and the frame by shadowWidth. | |
604 * Also, the top tab is larger than the others, so if there's only | |
605 * one row, the widget must be made taller to accommodate this. | |
606 * | |
607 * Once the tabs are laid out, if there is more than one | |
608 * row, we may need to shuffle the rows to bring the top tab | |
609 * to the bottom row. | |
610 */ | |
611 | |
434 | 612 tw->tabs.needs_layout = False ; |
613 | |
428 | 614 if( num_children > 0 && tw->composite.children != NULL ) |
615 { | |
616 /* Loop through the tabs and assign rows & x positions */ | |
617 (void) TabLayout(tw, tw->core.width, tw->core.height, NULL, False) ; | |
446 | 618 num_children = TabsNumChildren (tw); |
428 | 619 |
620 /* assign a top widget, bring it to bottom row. */ | |
621 TabsShuffleRows(tw) ; | |
622 | |
623 /* now assign child positions & sizes. Positions are all the | |
624 * same: just inside the frame. Sizes are also all the same. | |
625 */ | |
626 | |
627 tw->tabs.child_width = cw = tw->core.width - 2 * SHADWID ; | |
628 tw->tabs.child_height = ch = | |
448 | 629 tw->core.height < (tw->tabs.tab_total + 2 * SHADWID) ? 0 : |
630 tw->core.height - tw->tabs.tab_total - 2 * SHADWID ; | |
428 | 631 |
632 for(i=0, childP=tw->composite.children; | |
434 | 633 i < num_children; |
428 | 634 ++i, ++childP) |
448 | 635 if( XtIsManaged(*childP) ) |
428 | 636 { |
2286 | 637 /* tab = (TabsConstraints) (*childP)->core.constraints ; */ |
434 | 638 bw = (*childP)->core.border_width ; |
448 | 639 /* Don't do anything if we can't see any of the child. */ |
640 if (ch >= bw*2 && ch > 0 && cw >= bw*2 && cw > 0) | |
641 XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID, | |
642 cw-bw*2,ch-bw*2, bw) ; | |
428 | 643 } |
434 | 644 if( XtIsRealized(w) ) { |
645 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ; | |
646 /* should not be necessary to explicitly repaint after a | |
647 * resize, but XEmacs folks tell me it is. | |
648 */ | |
649 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ; | |
650 } | |
428 | 651 } |
652 } /* Resize */ | |
653 | |
654 | |
655 | |
656 /* Redraw entire Tabs widget */ | |
657 | |
658 /* ARGSUSED */ | |
659 static void | |
2286 | 660 TabsExpose(Widget w, XEvent *UNUSED (event), Region UNUSED (region)) |
428 | 661 { |
662 TabsWidget tw = (TabsWidget) w; | |
663 | |
664 if( tw->tabs.needs_layout ) | |
665 XtClass(w)->core_class.resize(w) ; | |
666 | |
667 DrawTabs(tw, True) ; | |
668 } | |
669 | |
670 | |
671 /* Called when any Tabs widget resources are changed. */ | |
672 | |
673 /* ARGSUSED */ | |
674 static Boolean | |
3025 | 675 TabsSetValues(Widget current, Widget UNUSED (request), Widget new_, |
2286 | 676 ArgList UNUSED (args), Cardinal *UNUSED (num_args)) |
428 | 677 { |
430 | 678 TabsWidget curtw = (TabsWidget) current ; |
3025 | 679 TabsWidget tw = (TabsWidget) new_ ; |
430 | 680 Boolean needRedraw = False ; |
681 Widget *childP ; | |
682 int i ; | |
428 | 683 |
3094 | 684 if( |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
685 #ifdef HAVE_XFT_TABS |
3094 | 686 tw->tabs.renderFont != curtw->tabs.renderFont || |
687 #else | |
688 tw->tabs.font != curtw->tabs.font || | |
689 #endif | |
690 tw->tabs.internalWidth != curtw->tabs.internalWidth || | |
691 tw->tabs.internalHeight != curtw->tabs.internalHeight) | |
430 | 692 { |
3094 | 693 tw->tabs.tab_height = 2 * tw->tabs.internalHeight + SHADWID; |
428 | 694 |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
695 #ifdef HAVE_XFT_TABS |
3094 | 696 if (tw->tabs.renderFont != NULL) |
697 #if XFT_USE_HEIGHT_NOT_ASCENT_DESCENT | |
698 tw->tabs.tab_height += tw->tabs.renderFont->height; | |
699 #else | |
700 tw->tabs.tab_height += tw->tabs.renderFont->ascent + | |
701 tw->tabs.renderFont->descent; | |
702 #endif /* XFT_USE_HEIGHT_NOT_ASCENT_DESCENT */ | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
703 #else /* ! HAVE_XFT_TABS */ |
3094 | 704 if (tw->tabs.font != NULL) |
430 | 705 tw->tabs.tab_height += tw->tabs.font->max_bounds.ascent + |
3094 | 706 tw->tabs.font->max_bounds.descent; |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
707 #endif /* ! HAVE_XFT_TABS */ |
428 | 708 |
430 | 709 /* Tab size has changed. Resize all tabs and request a new size */ |
710 for(i=0, childP=tw->composite.children; | |
647 | 711 i < (int) tw->composite.num_children; |
430 | 712 ++i, ++childP) |
713 if( XtIsManaged(*childP) ) | |
714 TabWidth(*childP) ; | |
715 PreferredSize(tw, &tw->core.width, &tw->core.height, NULL,NULL) ; | |
716 needRedraw = True ; | |
717 tw->tabs.needs_layout = True ; | |
718 } | |
428 | 719 |
430 | 720 /* TODO: if any color changes, need to recompute GCs and redraw */ |
428 | 721 |
430 | 722 if( tw->core.background_pixel != curtw->core.background_pixel || |
432 | 723 tw->core.background_pixmap != curtw->core.background_pixmap || |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
724 #ifdef HAVE_XFT_TABS |
3094 | 725 tw->tabs.renderFont != curtw->tabs.renderFont |
726 #else | |
727 tw->tabs.font != curtw->tabs.font | |
728 #endif | |
729 ) | |
3025 | 730 if( XtIsRealized(new_) ) |
430 | 731 { |
732 TabsFreeGCs(tw) ; | |
733 TabsAllocGCs(tw) ; | |
734 needRedraw = True ; | |
735 } | |
428 | 736 |
430 | 737 if( tw->core.sensitive != curtw->core.sensitive ) |
738 needRedraw = True ; | |
428 | 739 |
430 | 740 /* If top widget changes, need to change stacking order, redraw tabs. |
741 * Window system will handle the redraws. | |
742 */ | |
428 | 743 |
442 | 744 if( tw->tabs.topWidget != curtw->tabs.topWidget ) |
432 | 745 { |
430 | 746 if( XtIsRealized(tw->tabs.topWidget) ) |
747 { | |
748 Widget w = tw->tabs.topWidget ; | |
749 TabsConstraints tab = (TabsConstraints) w->core.constraints ; | |
428 | 750 |
430 | 751 XRaiseWindow(XtDisplay(w), XtWindow(w)) ; |
428 | 752 #ifdef NEED_MOTIF |
430 | 753 XtVaSetValues(curtw->tabs.topWidget, XmNtraversalOn, False, 0) ; |
754 XtVaSetValues(w, XmNtraversalOn, True, 0) ; | |
428 | 755 #endif |
756 | |
647 | 757 if( tab->tabs.row != (int) tw->tabs.numRows-1 ) |
430 | 758 TabsShuffleRows(tw) ; |
428 | 759 |
430 | 760 needRedraw = True ; |
761 } | |
762 else | |
763 tw->tabs.needs_layout = True ; | |
432 | 764 } |
428 | 765 |
430 | 766 return needRedraw ; |
428 | 767 } |
768 | |
769 | |
770 /* Called when any child constraint resources change. */ | |
771 | |
772 /* ARGSUSED */ | |
773 static Boolean | |
3025 | 774 TabsConstraintSetValues(Widget current, Widget UNUSED (request), Widget new_, |
2286 | 775 ArgList UNUSED (args), Cardinal *UNUSED (num_args)) |
428 | 776 { |
3025 | 777 TabsWidget tw = (TabsWidget) XtParent(new_) ; |
428 | 778 TabsConstraints ctab = (TabsConstraints) current->core.constraints ; |
3025 | 779 TabsConstraints tab = (TabsConstraints) new_->core.constraints ; |
428 | 780 |
781 | |
782 /* if label changes, need to re-layout the entire widget */ | |
783 /* if foreground changes, need to redraw tab label */ | |
784 | |
785 /* TODO: only need resize of new bitmap has different dimensions | |
786 * from old bitmap. | |
787 */ | |
788 | |
789 if( tab->tabs.label != ctab->tabs.label || /* Tab size has changed. */ | |
790 tab->tabs.left_bitmap != ctab->tabs.left_bitmap ) | |
791 { | |
3025 | 792 TabWidth(new_) ; |
428 | 793 tw->tabs.needs_layout = True ; |
794 | |
795 if( tab->tabs.left_bitmap != ctab->tabs.left_bitmap ) | |
796 getBitmapInfo(tw, tab) ; | |
797 | |
798 /* If there are no subclass ConstraintSetValues procedures remaining | |
799 * to be invoked, and if the preferred size has changed, ask | |
800 * for a resize. | |
801 */ | |
802 if( XtClass((Widget)tw) == tabsWidgetClass ) | |
803 MakeSizeRequest(tw) ; | |
804 } | |
805 | |
806 | |
807 /* The child widget itself never needs a redisplay, but the parent | |
808 * Tabs widget might. | |
809 */ | |
810 | |
3025 | 811 if( XtIsRealized(new_) ) |
428 | 812 { |
813 if( tw->tabs.needs_layout ) { | |
814 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ; | |
815 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ; | |
816 } | |
817 | |
818 else if( tab->tabs.foreground != ctab->tabs.foreground ) | |
3025 | 819 DrawTab(tw, new_, True) ; |
428 | 820 } |
821 | |
822 return False ; | |
823 } | |
824 | |
825 | |
434 | 826 static Boolean |
2286 | 827 TabsAcceptFocus(Widget w, Time *UNUSED (t)) |
434 | 828 { |
829 if( !w->core.being_destroyed && XtIsRealized(w) && | |
830 XtIsSensitive(w) && XtIsManaged(w) && w->core.visible ) | |
831 { | |
832 Widget p ; | |
833 for(p = XtParent(w); !XtIsShell(p); p = XtParent(p)) ; | |
834 XtSetKeyboardFocus(p,w) ; | |
835 return True ; | |
836 } | |
837 else | |
838 return False ; | |
839 } | |
840 | |
841 | |
428 | 842 |
843 /* | |
3094 | 844 * Return status, with preferred size in PREFERRED. |
845 * | |
846 * According to the X Toolkit Intrinsics manual | |
847 * XtGeometryYes = accept INTENDED without change | |
848 * XtGeometryNo = request to stay _exactly_ the same | |
849 * XtGeometryAlmost = suggest PREFERRED as a compromise | |
850 * and the PREFERRED argument must be filled in completely (ie, any fields | |
851 * whose bits are set in the request_mode mask must correspond to the | |
852 * preferred geometry, which must be consistent with the return value). | |
853 * | |
854 * Assuming horizontal orientation, in XEmacs, we should always accept if | |
855 * the width is more than we need. There's no problem if there are only a | |
856 * couple of tabs packed to the left. OTOH there's probably something wrong | |
857 * if we're offered a height more than 1.5x or 2x the preferred height. | |
858 * (#### Do tab controls do vertical?) | |
428 | 859 */ |
860 | |
3094 | 861 /* compute the height above which we complain */ |
862 #define TAB_HEIGHT_TOLERANCE(x) (2*x) | |
863 | |
428 | 864 static XtGeometryResult |
3094 | 865 TabsQueryGeometry (Widget w, |
866 XtWidgetGeometry *intended, | |
867 XtWidgetGeometry *preferred) /* RETURN */ | |
428 | 868 { |
3094 | 869 TabsWidget tw = (TabsWidget) w; |
870 XtGeometryMask mode = intended->request_mode; | |
871 | |
872 preferred->request_mode = CWWidth | CWHeight; | |
873 PreferredSize (tw, &preferred->width, &preferred->height, NULL, NULL); | |
428 | 874 |
3094 | 875 /* If width is big enough, accept it. */ |
876 if ((mode & CWWidth) && intended->width >= preferred->width) | |
877 preferred->width = intended->width; | |
428 | 878 |
3094 | 879 /* If height is within range, accept it. |
880 #### If too tall, we could offer a compromise at TAB_HEIGHT_TOLERANCE. | |
881 Should we? */ | |
882 if ((mode & CWHeight) && intended->height >= preferred->height | |
883 && intended->height <= TAB_HEIGHT_TOLERANCE (preferred->height)) | |
884 preferred->height = intended->height; | |
428 | 885 |
3094 | 886 /* Compute return value. */ |
887 if (preferred->width == ((mode & CWWidth) ? intended->width | |
888 : w->core.width) | |
889 && preferred->height == ((mode & CWHeight) ? intended->height | |
890 : w->core.height)) | |
428 | 891 return XtGeometryYes; |
3094 | 892 else if (preferred->width == w->core.width |
893 && preferred->height == w->core.height) | |
894 return XtGeometryNo; | |
895 else | |
896 return XtGeometryAlmost; | |
428 | 897 } |
898 | |
899 | |
900 | |
901 /* | |
3094 | 902 * Geometry Manager; called when TAB (a child) wants to be resized. |
903 * | |
904 * According to the X Toolkit Intrinsics manual | |
905 * XtGeometryDone = accept REQUEST and do it (#### check this) | |
906 * XtGeometryYes = accept REQUEST without change | |
907 * XtGeometryNo = refuse REQUEST (ie, stay _exactly_ the same) | |
908 * XtGeometryAlmost = suggest REPLY as a compromise | |
428 | 909 */ |
910 | |
911 static XtGeometryResult | |
3094 | 912 TabsGeometryManager (Widget tab, |
913 XtWidgetGeometry *request, | |
914 XtWidgetGeometry *reply) /* RETURN */ | |
428 | 915 { |
3094 | 916 TabsWidget control = (TabsWidget) XtParent(tab); |
917 Dimension s = SHADWID; | |
918 TabsConstraints constraint = (TabsConstraints) tab->core.constraints; | |
919 XtGeometryResult result, best_offer = XtGeometryYes; | |
920 Dimension rw, rh; | |
921 | |
922 static int debug_count = 0; | |
923 static int debug_mask = 1; | |
924 | |
925 /* Position request cannot be satisfied, so if tabs are not resizable, | |
926 no nontrivial request can be satisfied: return XGeometryNo. */ | |
927 if (!constraint->tabs.resizable) | |
928 return XtGeometryNo; | |
929 | |
930 fprintf (stderr, "Urk! label is resizable!\n"); | |
428 | 931 |
3094 | 932 /* Assume we will refuse these; toggle iff we accept them. |
933 Reply won't specify any fields not in the request. */ | |
934 reply->request_mode = request->request_mode; | |
935 reply->x = tab->core.x; | |
936 reply->y = tab->core.y; | |
428 | 937 |
3094 | 938 /* If a position request would result in a change, best offer is |
939 XtGeometryAlmost. Otherwise toggle reply->request_mode. */ | |
940 if ((request->request_mode & CWX) && request->x != tab->core.x) | |
941 best_offer = XtGeometryAlmost; | |
942 else | |
943 reply->request_mode &= ~CWX; | |
944 if ((request->request_mode & CWY) && request->y != tab->core.y) | |
945 best_offer = XtGeometryAlmost; | |
946 else | |
947 reply->request_mode &= ~CWY; | |
428 | 948 |
3094 | 949 /* Make all three fields in the reply valid */ |
950 reply->width = (request->request_mode & CWWidth) | |
951 ? request->width : tab->core.width; | |
952 reply->height = (request->request_mode & CWHeight) | |
953 ? request->height : tab->core.height; | |
954 reply->border_width = (request->request_mode & CWBorderWidth) | |
955 ? request->border_width : tab->core.border_width; | |
956 | |
957 /* check if we can already offer a compromise */ | |
958 if (best_offer == XtGeometryAlmost && | |
959 reply->width == tab->core.width && | |
960 reply->height == tab->core.height && | |
961 reply->border_width == tab->core.border_width) | |
962 { | |
963 reply->request_mode &= ~(CWWidth | CWHeight | CWBorderWidth); | |
964 return best_offer; | |
965 } | |
428 | 966 |
3094 | 967 #ifndef DONT_DEBUG_REQUESTS |
968 #define DBG_REQUEST_PRINT(name,field,size) \ | |
969 do { \ | |
970 if (reply->field > size) \ | |
971 { \ | |
972 if (++debug_count == debug_mask) \ | |
973 { \ | |
974 debug_mask <<= 1; \ | |
975 fprintf (stderr, "ridiculous %s request #%d: %d > %d\n", \ | |
976 name, debug_count, reply->field, size); \ | |
977 } \ | |
978 reply->field = tab->core.field; \ | |
979 } \ | |
980 } while (0) | |
428 | 981 |
3094 | 982 DBG_REQUEST_PRINT ("width",width,1024); |
983 DBG_REQUEST_PRINT ("height",height,768); | |
984 DBG_REQUEST_PRINT ("border_width",border_width,30); | |
985 #undef DBG_REQUEST_PRINT | |
986 #endif | |
987 | |
988 rw = reply->width + 2 * reply->border_width; | |
989 rh = reply->height + 2 * reply->border_width; | |
434 | 990 |
991 /* find out how big the children want to be now */ | |
3094 | 992 MaxChild (control, tab, rw, rh); |
428 | 993 |
994 | |
995 /* Size changes must see if the new size can be accommodated. | |
3094 | 996 * The Tabs widget keeps all of its children the same height, but |
997 * widths may vary. | |
998 * A request to shrink will be accepted only if the | |
428 | 999 * new size is still big enough for all other children. A |
1000 * request to shrink that is not big enough for all children | |
434 | 1001 * returns an "almost" response with the new proposed size |
1002 * or a "no" response if unable to shrink at all. | |
1003 * | |
3094 | 1004 * A request to grow will be accepted only if the Tabs control can |
428 | 1005 * grow to accommodate. |
1006 * | |
1007 * TODO: | |
1008 * We could get fancy here and re-arrange the tabs if it is | |
1009 * necessary to compromise with the parent, but we'll save that | |
1010 * for another day. | |
1011 */ | |
1012 | |
3094 | 1013 if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) |
428 | 1014 { |
1015 Dimension cw,ch ; /* children's preferred size */ | |
1016 Dimension aw,ah ; /* available size we can give child */ | |
1017 Dimension th ; /* space used by tabs */ | |
1018 Dimension wid,hgt ; /* Tabs widget size */ | |
3094 | 1019 int check_nrows; |
428 | 1020 |
3094 | 1021 cw = control->tabs.max_cw ; |
1022 ch = control->tabs.max_ch ; | |
428 | 1023 |
434 | 1024 /* find out what *my* resulting preferred size would be */ |
3094 | 1025 /* #### this whole API is wrong; what should happen is |
1026 1. app should hint as to #rows and/or aspect ratio | |
1027 2. tab control should attempt to layout in current space | |
1028 3. if not all tabs fit, should request resize to achieve | |
1029 layout hints | |
1030 Probably can and should cache preferred size in widget, with | |
1031 cache cleared when labels or core size changes. */ | |
1032 PreferredSize2(control, cw, ch, &wid, &hgt) ; | |
434 | 1033 |
1034 /* Would my size change? If so, ask to be resized. */ | |
428 | 1035 |
3094 | 1036 if (wid != control->core.width || hgt != control->core.height) |
428 | 1037 { |
3094 | 1038 Dimension oldWid = control->core.width, |
1039 oldHgt = control->core.height; | |
428 | 1040 XtWidgetGeometry myrequest, myreply ; |
1041 | |
1042 myrequest.width = wid ; | |
1043 myrequest.height = hgt ; | |
1044 myrequest.request_mode = CWWidth | CWHeight ; | |
448 | 1045 |
1046 assert (wid > 0 && hgt > 0); | |
428 | 1047 /* If child is only querying, or if we're going to have to |
1048 * offer the child a compromise, then make this a query only. | |
1049 */ | |
1050 | |
3094 | 1051 if ((request->request_mode & XtCWQueryOnly) || rw < cw || rh < ch) |
1052 myrequest.request_mode |= XtCWQueryOnly; | |
428 | 1053 |
3094 | 1054 result = XtMakeGeometryRequest ((Widget) control, |
1055 &myrequest, &myreply); | |
428 | 1056 |
434 | 1057 /* !$@# Athena Box widget changes the core size even if QueryOnly |
428 | 1058 * is set. I'm convinced this is a bug. At any rate, to work |
1059 * around the bug, we need to restore the core size after every | |
1060 * query geometry request. This is only partly effective, | |
1061 * as there may be other boxes further up the tree. | |
1062 */ | |
3094 | 1063 if (myrequest.request_mode & XtCWQueryOnly) { |
1064 control->core.width = oldWid; | |
1065 control->core.height = oldHgt; | |
428 | 1066 } |
1067 | |
1068 /* based on the parent's response, determine what the | |
1069 * resulting Tabs widget size would be. | |
1070 */ | |
1071 | |
3094 | 1072 switch (result) { |
428 | 1073 case XtGeometryYes: |
1074 case XtGeometryDone: | |
3094 | 1075 control->tabs.needs_layout = True; |
1076 break; | |
428 | 1077 |
1078 case XtGeometryNo: | |
3094 | 1079 wid = control->core.width; |
1080 hgt = control->core.height; | |
1081 break; | |
428 | 1082 |
1083 case XtGeometryAlmost: | |
3094 | 1084 wid = myreply.width; |
1085 hgt = myreply.height; | |
1086 control->tabs.needs_layout = True; | |
1087 break; | |
428 | 1088 } |
1089 } | |
1090 | |
1091 /* Within the constraints imposed by the parent, what is | |
1092 * the max size we can give the child? | |
1093 */ | |
3094 | 1094 check_nrows = TabLayout (control, wid, hgt, &th, True); |
1095 aw = wid - 2*s; | |
1096 if (check_nrows == 1) | |
1097 { | |
1098 ah = hgt - th - 2*s; | |
1099 } | |
1100 else | |
1101 { | |
1102 /* this rarely gets triggered, but when it does it seems to | |
1103 get triggered forever after */ | |
1104 int n = control->composite.num_children; | |
1105 ah = control->tabs.tab_height; | |
3397 | 1106 if (debug_tabs > 1) |
3094 | 1107 fprintf (stderr, "Kludging around %d != 1 rows," |
1108 " #children = %d, total height %d, using %d.\n", | |
1109 check_nrows, n, th, ah); | |
1110 } | |
428 | 1111 |
1112 /* OK, make our decision. If requested size is >= max sibling | |
1113 * preferred size, AND requested size <= available size, then | |
1114 * we accept. Otherwise, we offer a compromise. | |
1115 */ | |
1116 | |
3094 | 1117 if (rw == aw && rh == ah) |
428 | 1118 { |
1119 /* Acceptable. If this wasn't a query, change *all* children | |
1120 * to this size. | |
1121 */ | |
3094 | 1122 if (request->request_mode & XtCWQueryOnly) |
1123 { | |
1124 control->tabs.needs_layout = False; | |
1125 return XtGeometryYes ; | |
1126 } | |
428 | 1127 else |
1128 { | |
3094 | 1129 Widget *childP = control->composite.children; |
1130 int i, bw; | |
1131 tab->core.border_width = request->border_width; | |
1132 for (i = TabsNumChildren (control); --i >= 0; ++childP) | |
1133 if (TabVisible (*childP)) | |
428 | 1134 { |
3094 | 1135 bw = (*childP)->core.border_width; |
1136 XtConfigureWidget (*childP, s, control->tabs.tab_total+s, | |
1137 rw-2*bw, rh-2*bw, bw); | |
428 | 1138 } |
1139 #ifdef COMMENT | |
1140 /* TODO: under what conditions will we need to redraw? */ | |
3094 | 1141 XClearWindow (XtDisplay ((Widget) control), |
1142 XtWindow ((Widget) control)); | |
1143 XtClass (control)->core_class.expose ((Widget)control, | |
1144 NULL, NULL); | |
428 | 1145 #endif /* COMMENT */ |
3094 | 1146 return XtGeometryDone; |
428 | 1147 } |
1148 } | |
1149 | |
1150 /* Cannot grant child's request. Describe what we *can* do | |
1151 * and return counter-offer. | |
1152 */ | |
3094 | 1153 control->tabs.needs_layout = False; |
1154 reply->width = aw - 2 * request->border_width ; | |
1155 reply->height = ah - 2 * request->border_width ; | |
1156 reply->request_mode &= | |
1157 ~((reply->border_width == tab->core.border_width | |
1158 ? CWBorderWidth : 0) | |
1159 |(reply->width == tab->core.width ? CWWidth : 0) | |
1160 |(reply->height == tab->core.height ? CWHeight : 0)); | |
428 | 1161 return XtGeometryAlmost ; |
1162 } | |
1163 | |
1164 return XtGeometryYes ; | |
1165 } | |
1166 | |
1167 | |
1168 | |
1169 | |
1170 /* The number of children we manage has changed; recompute | |
1171 * size from scratch. | |
1172 */ | |
1173 | |
1174 static void | |
1175 TabsChangeManaged(Widget w) | |
1176 { | |
1177 TabsWidget tw = (TabsWidget)w ; | |
1178 Widget *childP = tw->composite.children ; | |
1179 int i ; | |
1180 | |
1181 if( tw->tabs.topWidget != NULL && | |
1182 ( !XtIsManaged(tw->tabs.topWidget) || | |
1183 tw->tabs.topWidget->core.being_destroyed ) ) | |
1184 tw->tabs.topWidget = NULL ; | |
1185 | |
440 | 1186 /* Check whether the highlight tab is still valid. */ |
1187 if( tw->tabs.hilight != NULL && | |
1188 ( !XtIsManaged(tw->tabs.hilight) || | |
1189 tw->tabs.hilight->core.being_destroyed ) ) | |
1190 tw->tabs.hilight = NULL ; | |
1191 | |
428 | 1192 GetPreferredSizes(tw) ; |
1193 MakeSizeRequest(tw) ; | |
1194 | |
1195 XtClass(w)->core_class.resize(w) ; | |
1196 if( XtIsRealized(w) ) | |
1197 { | |
1198 Display *dpy = XtDisplay(w) ; | |
1199 XClearWindow(dpy, XtWindow(w)) ; | |
1200 XtClass(w)->core_class.expose(w,NULL,NULL) ; | |
1201 | |
1202 /* make sure the top widget stays on top. This requires | |
1203 * making sure that all new children are realized first. | |
1204 */ | |
1205 if( tw->tabs.topWidget != NULL && XtIsRealized(tw->tabs.topWidget) ) | |
1206 { | |
446 | 1207 for(i=TabsNumChildren (tw); --i >= 0; ++childP) |
428 | 1208 if( !XtIsRealized(*childP) ) |
1209 XtRealizeWidget(*childP) ; | |
1210 | |
1211 XRaiseWindow(dpy, XtWindow(tw->tabs.topWidget)) ; | |
1212 } | |
1213 } | |
1214 | |
1215 #ifdef NEED_MOTIF | |
1216 /* Only top widget may receive input */ | |
1217 | |
1218 for(childP = tw->composite.children, i=tw->composite.num_children; | |
1219 --i >= 0; | |
1220 ++childP) | |
1221 { | |
1222 XtVaSetValues(*childP, XmNtraversalOn, False, 0) ; | |
1223 } | |
1224 | |
1225 if( tw->tabs.topWidget != NULL ) | |
1226 XtVaSetValues(tw->tabs.topWidget, XmNtraversalOn, True, 0) ; | |
1227 #endif | |
1228 } | |
1229 | |
1230 | |
1231 | |
1232 | |
1233 /**************************************************************** | |
1234 * | |
1235 * Action Procedures | |
1236 * | |
1237 ****************************************************************/ | |
1238 | |
1239 | |
1240 /* User clicks on a tab, figure out which one it was. */ | |
1241 | |
1242 /* ARGSUSED */ | |
1243 static void | |
2286 | 1244 TabsSelect(Widget w, XEvent *event, String *UNUSED (params), |
1245 Cardinal *UNUSED (num_params)) | |
428 | 1246 { |
1247 TabsWidget tw = (TabsWidget) w ; | |
1248 Widget *childP ; | |
1249 Position x,y ; | |
1250 Dimension h = tw->tabs.tab_height ; | |
1251 int i ; | |
1252 | |
1253 #ifdef NEED_MOTIF | |
1254 XmProcessTraversal (w, XmTRAVERSE_CURRENT) ; | |
1255 #endif | |
1256 | |
1257 /* TODO: is there an Xmu function or something to do this instead? */ | |
1258 switch( event->type ) { | |
1259 case ButtonPress: | |
1260 case ButtonRelease: | |
1261 x = event->xbutton.x ; y = event->xbutton.y ; break ; | |
1262 case KeyPress: | |
1263 case KeyRelease: | |
1264 x = event->xkey.x ; y = event->xkey.y ; break ; | |
1265 default: | |
1266 return ; | |
1267 } | |
1268 | |
1269 /* TODO: determine which tab was clicked, if any. Set that | |
1270 * widget to be top of stacking order with XawTabsSetTop(). | |
1271 */ | |
1272 for(i=0, childP=tw->composite.children; | |
647 | 1273 i < (int) TabsNumChildren (tw); |
428 | 1274 ++i, ++childP) |
446 | 1275 if( TabVisible(*childP) ) |
428 | 1276 { |
1277 TabsConstraints tab = (TabsConstraints)(*childP)->core.constraints; | |
1278 if( x > tab->tabs.x && x < tab->tabs.x + tab->tabs.width && | |
1279 y > tab->tabs.y && y < tab->tabs.y + h ) | |
1280 { | |
1281 if( *childP != tw->tabs.topWidget && | |
1282 (XtIsSensitive(*childP) || tw->tabs.selectInsensitive) ) | |
1283 XawTabsSetTop(*childP, True) ; | |
1284 break ; | |
1285 } | |
1286 } | |
1287 } | |
1288 | |
1289 | |
1290 /* User hits a key */ | |
1291 | |
1292 static void | |
2286 | 1293 TabsPage(Widget w, XEvent *UNUSED (event), String *params, |
1294 Cardinal *num_params) | |
428 | 1295 { |
1296 TabsWidget tw = (TabsWidget) w ; | |
430 | 1297 Widget newtop = NULL; |
428 | 1298 Widget *childP ; |
1299 int idx ; | |
446 | 1300 int nc = TabsNumChildren (tw) ; |
428 | 1301 |
1302 if( nc <= 0 ) | |
1303 return ; | |
1304 | |
1305 if( *num_params < 1 ) { | |
1306 XtAppWarning(XtWidgetToApplicationContext(w), | |
1307 "Tabs: page() action called with no arguments") ; | |
1308 return ; | |
1309 } | |
1310 | |
1311 if( tw->tabs.topWidget == NULL ) | |
1312 tw->tabs.topWidget = tw->composite.children[0] ; | |
1313 | |
1314 for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP ) | |
1315 if( tw->tabs.topWidget == *childP ) | |
1316 break ; | |
1317 | |
1318 switch( params[0][0] ) { | |
1319 case 'u': /* up */ | |
1320 case 'U': | |
432 | 1321 if( --idx < 0 ) |
1322 idx = nc-1 ; | |
1323 newtop = tw->composite.children[idx] ; | |
428 | 1324 break ; |
1325 | |
1326 case 'd': /* down */ | |
1327 case 'D': | |
1328 if( ++idx >= nc ) | |
1329 idx = 0 ; | |
1330 newtop = tw->composite.children[idx] ; | |
1331 break ; | |
1332 | |
1333 case 'h': | |
1334 case 'H': | |
432 | 1335 default: |
428 | 1336 newtop = tw->composite.children[0] ; |
1337 break ; | |
1338 | |
1339 case 'e': | |
1340 case 'E': | |
1341 newtop = tw->composite.children[nc-1] ; | |
1342 break ; | |
1343 | |
1344 case 's': /* selected */ | |
1345 case 'S': | |
1346 if( (newtop = tw->tabs.hilight) == NULL ) | |
1347 return ; | |
1348 break ; | |
1349 } | |
1350 | |
1351 XawTabsSetTop(newtop, True) ; | |
1352 } | |
1353 | |
1354 | |
1355 /* User hits up/down key */ | |
1356 | |
1357 static void | |
2286 | 1358 TabsHighlight(Widget w, XEvent *UNUSED (event), String *params, |
1359 Cardinal *num_params) | |
428 | 1360 { |
1361 TabsWidget tw = (TabsWidget) w ; | |
430 | 1362 Widget newhl = NULL; |
428 | 1363 Widget *childP ; |
1364 int idx ; | |
446 | 1365 int nc = TabsNumChildren (tw) ; |
428 | 1366 |
1367 if( nc <= 0 ) | |
1368 return ; | |
1369 | |
1370 if( *num_params < 1 ) | |
1371 { | |
1372 if( tw->tabs.hilight != NULL ) | |
1373 DrawHighlight(tw, tw->tabs.hilight, False) ; | |
1374 return ; | |
1375 } | |
1376 | |
1377 if( tw->tabs.hilight == NULL ) | |
1378 newhl = tw->composite.children[0] ; | |
1379 | |
1380 else | |
1381 { | |
432 | 1382 /* find index of currently highlit child */ |
428 | 1383 for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP ) |
1384 if( tw->tabs.hilight == *childP ) | |
1385 break ; | |
1386 | |
1387 switch( params[0][0] ) { | |
1388 case 'u': /* up */ | |
1389 case 'U': | |
432 | 1390 if( --idx < 0 ) |
1391 idx = nc-1 ; | |
1392 newhl = tw->composite.children[idx] ; | |
428 | 1393 break ; |
1394 | |
1395 case 'd': /* down */ | |
1396 case 'D': | |
1397 if( ++idx >= nc ) | |
1398 idx = 0 ; | |
1399 newhl = tw->composite.children[idx] ; | |
1400 break ; | |
1401 | |
1402 case 'h': | |
1403 case 'H': | |
1404 newhl = tw->composite.children[0] ; | |
1405 break ; | |
1406 | |
1407 case 'e': | |
1408 case 'E': | |
1409 newhl = tw->composite.children[nc-1] ; | |
1410 break ; | |
432 | 1411 |
1412 default: | |
1413 newhl = tw->tabs.hilight ; | |
1414 break ; | |
428 | 1415 } |
1416 } | |
1417 | |
1418 XawTabsSetHighlight(w, newhl) ; | |
1419 } | |
1420 | |
1421 | |
1422 | |
1423 static void | |
2286 | 1424 TabsUnhighlight(Widget w, XEvent *UNUSED (event), String *UNUSED (params), |
1425 Cardinal *UNUSED (num_params)) | |
428 | 1426 { |
1427 TabsWidget tw = (TabsWidget) w ; | |
1428 int nc = tw->composite.num_children ; | |
1429 | |
1430 if( nc <= 0 ) | |
1431 return ; | |
1432 | |
1433 if( tw->tabs.hilight != NULL ) | |
1434 DrawHighlight(tw, tw->tabs.hilight, True) ; | |
1435 } | |
1436 | |
1437 | |
1438 | |
1439 | |
1440 | |
1441 /**************************************************************** | |
1442 * | |
1443 * Public Procedures | |
1444 * | |
1445 ****************************************************************/ | |
1446 | |
1447 | |
1448 /* Set the top tab, optionally call all callbacks. */ | |
1449 void | |
1450 XawTabsSetTop(Widget w, Bool callCallbacks) | |
1451 { | |
1452 TabsWidget tw = (TabsWidget)w->core.parent ; | |
1453 TabsConstraints tab ; | |
1454 Widget oldtop = tw->tabs.topWidget ; | |
1455 | |
1456 if( !XtIsSubclass(w->core.parent, tabsWidgetClass) ) | |
1457 { | |
434 | 1458 char line[256] ; |
1459 sprintf(line, "XawTabsSetTop: widget \"%.64s\" is not the child of a tabs widget.", XtName(w)) ; | |
428 | 1460 XtAppWarning(XtWidgetToApplicationContext(w), line) ; |
1461 return ; | |
1462 } | |
1463 | |
1464 if( callCallbacks ) | |
1465 XtCallCallbackList(w, tw->tabs.popdownCallbacks, | |
434 | 1466 (XtPointer)tw->tabs.topWidget) ; |
428 | 1467 |
1468 if( !XtIsRealized(w) ) { | |
1469 tw->tabs.topWidget = w ; | |
1470 tw->tabs.needs_layout = True ; | |
440 | 1471 tw->tabs.hilight = NULL; /* The highlight tab might disappear. */ |
428 | 1472 return ; |
1473 } | |
1474 | |
1475 XRaiseWindow(XtDisplay(w), XtWindow(w)) ; | |
1476 #ifdef NEED_MOTIF | |
1477 XtVaSetValues(oldtop, XmNtraversalOn, False, 0) ; | |
1478 XtVaSetValues(w, XmNtraversalOn, True, 0) ; | |
1479 #endif | |
1480 | |
1481 tab = (TabsConstraints) w->core.constraints ; | |
440 | 1482 |
1483 /* Unhighlight before we start messing with the stacking order. */ | |
1484 if( tw->tabs.hilight != NULL ) | |
1485 { | |
1486 DrawHighlight(tw, tw->tabs.hilight, True) ; | |
1487 tw->tabs.hilight = NULL; | |
1488 } | |
1489 | |
428 | 1490 if( tab->tabs.row == 0 ) |
1491 { | |
1492 /* Easy case; undraw current top, undraw new top, assign new | |
1493 * top, redraw all borders. | |
1494 * We *could* just erase and execute a full redraw, but I like to | |
1495 * reduce screen flicker. | |
1496 */ | |
1497 UndrawTab(tw, oldtop) ; /* undraw old */ | |
1498 DrawBorder(tw, oldtop, True) ; | |
1499 UndrawTab(tw, w) ; /* undraw new */ | |
1500 DrawBorder(tw, w, True) ; | |
1501 tw->tabs.topWidget = w ; | |
1502 DrawTab(tw, oldtop, True) ; /* redraw old */ | |
1503 DrawTab(tw, w, True) ; /* redraw new */ | |
1504 DrawTabs(tw, False) ; | |
1505 } | |
1506 else | |
1507 { | |
1508 tw->tabs.topWidget = w ; | |
1509 TabsShuffleRows(tw) ; | |
1510 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ; | |
1511 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ; | |
1512 } | |
1513 | |
1514 XawTabsSetHighlight((Widget)tw, w) ; | |
1515 | |
1516 if( callCallbacks ) | |
1517 XtCallCallbackList(w, tw->tabs.callbacks, (XtPointer)w) ; | |
1518 } | |
1519 | |
1520 | |
1521 /* Set the top tab, optionally call all callbacks. */ | |
1522 void | |
1523 XawTabsSetHighlight(Widget t, Widget w) | |
1524 { | |
1525 TabsWidget tw = (TabsWidget)t ; | |
1526 | |
1527 if( !XtIsSubclass(t, tabsWidgetClass) ) | |
1528 return ; | |
1529 | |
1530 if( XtIsRealized(t) && w != tw->tabs.hilight ) | |
1531 { | |
1532 if( w != NULL ) | |
1533 DrawHighlight(tw, w, False) ; | |
1534 } | |
1535 | |
1536 tw->tabs.hilight = w ; | |
1537 } | |
1538 | |
1539 | |
1540 | |
1541 | |
1542 /**************************************************************** | |
1543 * | |
1544 * Private Procedures | |
1545 * | |
1546 ****************************************************************/ | |
1547 | |
1548 | |
1549 static void | |
1550 TabsAllocGCs(TabsWidget tw) | |
1551 { | |
1552 TabsAllocFgGC(tw) ; | |
1553 TabsAllocGreyGC(tw) ; | |
1554 tw->tabs.backgroundGC = AllocBackgroundGC((Widget)tw, None) ; | |
1555 tw->tabs.topGC = AllocTopShadowGC((Widget)tw, | |
1556 tw->tabs.top_shadow_contrast, tw->tabs.be_nice_to_cmap) ; | |
1557 tw->tabs.botGC = AllocBotShadowGC((Widget)tw, | |
1558 tw->tabs.bot_shadow_contrast, tw->tabs.be_nice_to_cmap) ; | |
1559 } | |
1560 | |
1561 | |
1562 static void | |
1563 TabsFreeGCs(TabsWidget tw) | |
1564 { | |
1565 Widget w = (Widget) tw; | |
1566 | |
1567 XtReleaseGC(w, tw->tabs.foregroundGC) ; | |
1568 XtReleaseGC(w, tw->tabs.greyGC) ; | |
1569 XtReleaseGC(w, tw->tabs.backgroundGC) ; | |
1570 XtReleaseGC(w, tw->tabs.topGC) ; | |
1571 XtReleaseGC(w, tw->tabs.botGC) ; | |
1572 XmuReleaseStippledPixmap(XtScreen(w), tw->tabs.grey50) ; | |
1573 } | |
1574 | |
1575 | |
1576 | |
1577 | |
1578 | |
1579 /* Redraw entire Tabs widget */ | |
1580 | |
1581 static void | |
1582 DrawTabs(TabsWidget tw, Bool labels) | |
1583 { | |
1584 Widget *childP ; | |
1585 int i,j ; | |
1586 Dimension s = SHADWID ; | |
1587 Dimension th = tw->tabs.tab_height ; | |
1588 Position y ; | |
1589 TabsConstraints tab ; | |
1590 | |
1591 if( !XtIsRealized((Widget)tw)) | |
1592 return ; | |
442 | 1593 |
428 | 1594 /* draw tabs and frames by row except for the top tab, which |
1595 * is drawn last. (This is inefficiently written, but should not | |
1596 * be too slow as long as there are not a lot of rows.) | |
1597 */ | |
1598 | |
1599 y = tw->tabs.numRows == 1 ? TABDELTA : 0 ; | |
647 | 1600 for(i=0; i < (int) tw->tabs.numRows; ++i, y += th) |
428 | 1601 { |
446 | 1602 for( j=TabsNumChildren (tw), childP=tw->composite.children; |
428 | 1603 --j >= 0; ++childP ) |
446 | 1604 if( TabVisible(*childP) ) |
428 | 1605 { |
1606 tab = (TabsConstraints)(*childP)->core.constraints; | |
1607 if( tab->tabs.row == i && *childP != tw->tabs.topWidget ) | |
1608 DrawTab(tw, *childP, labels) ; | |
1609 } | |
647 | 1610 if( i != (int) tw->tabs.numRows -1 ) |
428 | 1611 DrawTrim(tw, 0,y+th, tw->core.width, th+s, False,False) ; |
1612 } | |
1613 | |
1614 DrawFrame(tw) ; | |
1615 | |
1616 /* and now the top tab */ | |
1617 if( tw->tabs.topWidget != NULL ) | |
1618 DrawTab(tw, tw->tabs.topWidget, labels) ; | |
1619 } | |
1620 | |
1621 | |
1622 | |
1623 /* Draw one tab. Corners are rounded very slightly. */ | |
1624 | |
1625 static void | |
1626 DrawTab(TabsWidget tw, Widget child, Bool labels) | |
1627 { | |
1628 GC gc ; | |
1629 int x,y ; | |
1630 | |
3397 | 1631 if (debug_tabs > 2) fprintf (stderr, "DrawTab called.\n"); |
3094 | 1632 |
428 | 1633 if( !XtIsRealized((Widget)tw)) |
1634 return ; | |
1635 | |
1636 DrawBorder(tw, child, False) ; | |
1637 | |
1638 if( labels ) | |
1639 { | |
1640 TabsConstraints tab = (TabsConstraints)child->core.constraints; | |
1641 Display *dpy = XtDisplay((Widget)tw) ; | |
1642 Window win = XtWindow((Widget)tw) ; | |
1643 String lbl = tab->tabs.label != NULL ? | |
1644 tab->tabs.label : XtName(child) ; | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
1645 #ifdef HAVE_XFT_TABS |
3094 | 1646 XftColor color; |
1647 XftColor colorBG; | |
1648 Colormap cmap = tw->core.colormap; | |
1649 Visual *visual; | |
1650 int ignored; | |
428 | 1651 |
3094 | 1652 visual_info_from_widget ((Widget) tw, &visual, &ignored); |
1653 colorBG = xft_convert_color (dpy, cmap, visual, | |
1654 tw->core.background_pixel, 0); | |
1655 #endif | |
1656 | |
1657 if (debug_tabs > 2) | |
1658 fprintf (stderr, "(Re)drawing labels.\n"); | |
1659 | |
1660 if (XtIsSensitive(child)) | |
428 | 1661 { |
3094 | 1662 gc = tw->tabs.foregroundGC; |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
1663 #ifdef HAVE_XFT_TABS |
3094 | 1664 color = xft_convert_color (dpy, cmap, visual, |
1665 tab->tabs.foreground, 0); | |
1666 #else | |
1667 XSetForeground(dpy, gc, tab->tabs.foreground); | |
1668 #endif | |
428 | 1669 } |
1670 else | |
1671 { | |
1672 /* grey pixel allocation deferred until now */ | |
3094 | 1673 if (!tab->tabs.greyAlloc) |
428 | 1674 { |
3094 | 1675 if (tw->tabs.be_nice_to_cmap || tw->core.depth == 1) |
1676 tab->tabs.grey = tab->tabs.foreground; | |
428 | 1677 else |
3094 | 1678 tab->tabs.grey = AllocGreyPixel ((Widget) tw, |
428 | 1679 tab->tabs.foreground, |
1680 tw->core.background_pixel, | |
3094 | 1681 tw->tabs.insensitive_contrast); |
1682 tab->tabs.greyAlloc = True; | |
428 | 1683 } |
3094 | 1684 gc = tw->tabs.greyGC; |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
1685 #ifdef HAVE_XFT_TABS |
3094 | 1686 color = xft_convert_color (dpy, cmap, visual, tab->tabs.grey, 0); |
1687 #else | |
1688 XSetForeground(dpy, gc, tab->tabs.grey); | |
1689 #endif | |
428 | 1690 } |
1691 | |
3094 | 1692 x = tab->tabs.x; |
1693 y = tab->tabs.y; | |
1694 if (child == tw->tabs.topWidget) | |
1695 y -= TABLDELTA; | |
428 | 1696 |
3094 | 1697 if (tab->tabs.left_bitmap != None && tab->tabs.lbm_width > 0) |
428 | 1698 { |
3094 | 1699 if (tab->tabs.lbm_depth == 1) |
428 | 1700 XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc, |
434 | 1701 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height, |
3094 | 1702 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L); |
428 | 1703 else |
1704 XCopyArea(dpy, tab->tabs.left_bitmap, win,gc, | |
434 | 1705 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height, |
3094 | 1706 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y); |
428 | 1707 } |
1708 | |
3094 | 1709 if (lbl != NULL && |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
1710 #ifdef HAVE_XFT_TABS |
3094 | 1711 tw->tabs.renderFont != NULL |
1712 #else | |
1713 tw->tabs.font != NULL | |
1714 #endif | |
1715 ) | |
1716 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
1717 #ifdef HAVE_XFT_TABS |
3094 | 1718 XftDraw *xftDraw = XftDrawCreate (dpy, win, visual, cmap); |
1719 XftFont *renderFont = tw->tabs.renderFont; | |
1720 XGlyphInfo glyphinfo; | |
1721 XftColor colorDBG; | |
1722 XftColorAllocName (dpy, visual, cmap, "wheat", &colorDBG); | |
3374 | 1723 XftTextExtents8 (dpy, renderFont, (FcChar8 *) lbl, |
1724 (int) strlen (lbl), &glyphinfo); | |
3094 | 1725 /* #### unnecessary? for the moment, give visual extent */ |
1726 /* draw background rect */ | |
1727 if (debug_tabs > 2) | |
1728 { | |
1729 fprintf (stderr, "background color: pixel=%08lx, r=%04x," | |
1730 " g=%04x, b=%04x, alpha=%04x.\n", | |
1731 colorDBG.pixel, colorDBG.color.red, | |
1732 colorDBG.color.green, colorDBG.color.blue, | |
1733 colorDBG.color.alpha); | |
1734 fprintf (stderr, "label geometry: x=%d, y=%d, xOff=%d," | |
1735 " yOff=%d, width=%d, height=%d\n", | |
1736 glyphinfo.x, glyphinfo.y, glyphinfo.xOff, | |
1737 glyphinfo.yOff, glyphinfo.width, glyphinfo.height); | |
1738 } | |
3397 | 1739 if (debug_tabs > 2) |
1740 XftDrawRect (xftDraw, &colorDBG, | |
1741 /* left, top, width, height */ | |
1742 x+tab->tabs.l_x-glyphinfo.x, | |
1743 y+tab->tabs.l_y-glyphinfo.y, | |
1744 glyphinfo.width, glyphinfo.height); | |
1745 | |
3094 | 1746 /* draw text */ |
3397 | 1747 if (debug_tabs > 1) |
3094 | 1748 { |
1749 fprintf (stderr, "label: %s.\n", lbl); | |
1750 fprintf (stderr, "foreground color: pixel=%08lx, r=%04x," | |
1751 " g=%04x, b=%04x, alpha=%04x.\n", | |
1752 color.pixel, color.color.red, color.color.green, | |
1753 color.color.blue, color.color.alpha); | |
1754 fprintf (stderr, "extent: x=%d, y=%d, xOffset=%d," | |
1755 " yOffset=%d, height=%d, width=%d.\n", | |
1756 glyphinfo.x, glyphinfo.y, glyphinfo.xOff, | |
1757 glyphinfo.yOff, glyphinfo.height, glyphinfo.width); | |
3397 | 1758 } |
1759 if (debug_tabs > 0) | |
1760 { | |
1761 FcValue name; | |
1762 FcValue size; | |
1763 FcPatternGet (renderFont->pattern, FC_FAMILY, 0, &name); | |
1764 FcPatternGet (renderFont->pattern, FC_SIZE, 0, &size); | |
3094 | 1765 fprintf (stderr, "font: name=%s-%.1f," |
1766 " height=%d, ascent=%d, descent=%d.\n", | |
1767 name.u.s, size.u.d, renderFont->height, | |
1768 renderFont->ascent, renderFont->descent); | |
1769 } | |
1770 XftDrawString8 (xftDraw, &color, renderFont, | |
1771 x+tab->tabs.l_x, y+tab->tabs.l_y, | |
3374 | 1772 (FcChar8 *) lbl, (int) strlen (lbl)); |
3094 | 1773 XftDrawDestroy (xftDraw); |
1774 #else | |
1775 XDrawString(dpy,win,gc, | |
1776 x+tab->tabs.l_x, y+tab->tabs.l_y, | |
1777 lbl, (int)strlen(lbl)); | |
1778 #endif | |
1779 } | |
428 | 1780 } |
1781 | |
3094 | 1782 if (child == tw->tabs.hilight) |
1783 DrawHighlight(tw, child, False); | |
428 | 1784 } |
1785 | |
1786 | |
1787 /* draw frame all the way around the child windows. */ | |
1788 | |
1789 static void | |
1790 DrawFrame(TabsWidget tw) | |
1791 { | |
1792 GC topgc = tw->tabs.topGC ; | |
1793 GC botgc = tw->tabs.botGC ; | |
1794 Dimension s = SHADWID ; | |
1795 Dimension ch = tw->tabs.child_height ; | |
448 | 1796 if (ch > 0) |
1797 Draw3dBox((Widget)tw, 0,tw->tabs.tab_total, | |
1798 tw->core.width, ch+2*s, s, topgc, botgc) ; | |
1799 else | |
1800 { | |
1801 Widget w = tw->tabs.topWidget ; | |
1802 if (w != NULL) | |
1803 { | |
1804 TabsConstraints tab = (TabsConstraints) w->core.constraints ; | |
1805 Draw3dBox((Widget)tw, 0,tw->core.height - 2*s, | |
1806 tab->tabs.x, 2*s, s, topgc, botgc); | |
1807 Draw3dBox((Widget)tw, tab->tabs.x + tab->tabs.width, | |
1808 tw->core.height - 2*s, | |
1809 tw->core.width - tab->tabs.x - tab->tabs.width, 2*s, s, | |
1810 topgc, botgc); | |
1811 } | |
1812 else | |
1813 Draw3dBox((Widget)tw, 0,tw->core.height - 2*s, | |
1814 tw->core.width, 2*s, s, topgc, botgc) ; | |
1815 } | |
428 | 1816 } |
1817 | |
1818 | |
1819 /* draw trim around a tab or underneath a row of tabs */ | |
1820 | |
1821 static void | |
1822 DrawTrim(TabsWidget tw, /* widget */ | |
1823 int x, /* upper-left corner */ | |
1824 int y, | |
1825 int wid, /* total size */ | |
1826 int hgt, | |
1827 Bool bottom, /* draw bottom? */ | |
1828 Bool undraw) /* undraw all */ | |
1829 { | |
1830 Display *dpy = XtDisplay((Widget)tw) ; | |
1831 Window win = XtWindow((Widget)tw) ; | |
1832 GC bggc = tw->tabs.backgroundGC ; | |
1833 GC topgc = undraw ? bggc : tw->tabs.topGC ; | |
1834 GC botgc = undraw ? bggc : tw->tabs.botGC ; | |
1835 if( bottom ) | |
1836 XDrawLine(dpy,win,bggc, x,y+hgt-1, x+wid-1,y+hgt-1) ; /* bottom */ | |
1837 XDrawLine(dpy,win,topgc, x,y+2, x,y+hgt-2) ; /* left */ | |
1838 XDrawPoint(dpy,win,topgc, x+1,y+1) ; /* corner */ | |
1839 XDrawLine(dpy,win,topgc, x+2,y, x+wid-3,y) ; /* top */ | |
1840 XDrawLine(dpy,win,botgc, x+wid-2,y+1, x+wid-2,y+hgt-2) ; /* right */ | |
1841 XDrawLine(dpy,win,botgc, x+wid-1,y+2, x+wid-1,y+hgt-2) ; /* right */ | |
1842 } | |
1843 | |
1844 | |
1845 /* Draw one tab border. */ | |
1846 | |
1847 static void | |
1848 DrawBorder(TabsWidget tw, Widget child, Bool undraw) | |
1849 { | |
1850 TabsConstraints tab = (TabsConstraints)child->core.constraints; | |
1851 Position x = tab->tabs.x ; | |
1852 Position y = tab->tabs.y ; | |
1853 Dimension twid = tab->tabs.width ; | |
1854 Dimension thgt = tw->tabs.tab_height ; | |
1855 | |
1856 /* top tab requires a little special attention; it overlaps | |
1857 * neighboring tabs slightly, so the background must be cleared | |
1858 * in the region of the overlap to partially erase those neighbors. | |
1859 * TODO: is this worth doing with regions instead? | |
1860 */ | |
1861 if( child == tw->tabs.topWidget ) | |
1862 { | |
1863 Display *dpy = XtDisplay((Widget)tw) ; | |
1864 Window win = XtWindow((Widget)tw) ; | |
1865 GC bggc = tw->tabs.backgroundGC ; | |
1866 XRectangle rects[3] ; | |
1867 x -= TABDELTA ; | |
1868 y -= TABDELTA ; | |
1869 twid += TABDELTA*2 ; | |
1870 thgt += TABDELTA ; | |
1871 AddRect(0, x,y+1,twid,TABDELTA) ; | |
1872 AddRect(1, x+1,y,TABDELTA,thgt) ; | |
1873 AddRect(2, x+twid-TABDELTA-1,y,TABDELTA,thgt) ; | |
1874 XFillRectangles(dpy,win,bggc, rects, 3) ; | |
1875 } | |
1876 | |
1877 DrawTrim(tw, x,y,twid,thgt+1, child == tw->tabs.topWidget, undraw) ; | |
1878 } | |
1879 | |
1880 | |
1881 /* Draw highlight around tab that has focus */ | |
1882 | |
1883 static void | |
1884 DrawHighlight(TabsWidget tw, Widget child, Bool undraw) | |
1885 { | |
1886 TabsConstraints tab = (TabsConstraints)child->core.constraints; | |
1887 Display *dpy = XtDisplay((Widget)tw) ; | |
1888 Window win = XtWindow((Widget)tw) ; | |
1889 GC gc ; | |
1890 Position x = tab->tabs.x ; | |
1891 Position y = tab->tabs.y ; | |
1892 Dimension wid = tab->tabs.width ; | |
1893 Dimension hgt = tw->tabs.tab_height ; | |
1894 XPoint points[6] ; | |
1895 | |
1896 /* top tab does not have a highlight */ | |
1897 | |
1898 if( child == tw->tabs.topWidget ) | |
1899 return ; | |
1900 | |
1901 if( undraw ) | |
1902 gc = tw->tabs.backgroundGC ; | |
1903 | |
1904 else if( XtIsSensitive(child) ) | |
1905 { | |
1906 gc = tw->tabs.foregroundGC ; | |
1907 XSetForeground(dpy, gc, tab->tabs.foreground) ; | |
1908 } | |
1909 else | |
1910 { | |
1911 gc = tw->tabs.greyGC ; | |
1912 XSetForeground(dpy, gc, tab->tabs.grey) ; | |
1913 } | |
1914 | |
1915 points[0].x = x+1 ; points[0].y = y+hgt-1 ; | |
1916 points[1].x = x+1 ; points[1].y = y+2 ; | |
1917 points[2].x = x+2 ; points[2].y = y+1 ; | |
1918 points[3].x = x+wid-4 ; points[3].y = y+1 ; | |
1919 points[4].x = x+wid-3 ; points[4].y = y+2 ; | |
1920 points[5].x = x+wid-3 ; points[5].y = y+hgt-1 ; | |
1921 | |
1922 XDrawLines(dpy,win,gc, points,6, CoordModeOrigin) ; | |
1923 } | |
1924 | |
1925 | |
1926 /* Undraw one tab interior */ | |
1927 | |
1928 static void | |
1929 UndrawTab(TabsWidget tw, Widget child) | |
1930 { | |
1931 TabsConstraints tab = (TabsConstraints)child->core.constraints; | |
1932 Position x = tab->tabs.x ; | |
1933 Position y = tab->tabs.y ; | |
1934 Dimension twid = tab->tabs.width ; | |
1935 Dimension thgt = tw->tabs.tab_height ; | |
1936 Display *dpy = XtDisplay((Widget)tw) ; | |
1937 Window win = XtWindow((Widget)tw) ; | |
1938 GC bggc = tw->tabs.backgroundGC ; | |
1939 | |
1940 XFillRectangle(dpy,win,bggc, x,y, twid,thgt) ; | |
1941 } | |
1942 | |
1943 | |
1944 | |
1945 | |
1946 | |
1947 /* GEOMETRY UTILITIES */ | |
1948 | |
434 | 1949 /* Overview: |
1950 * | |
1951 * MaxChild(): ask all children (except possibly one) their | |
1952 * preferred sizes, set max_cw, max_ch accordingly. | |
1953 * | |
1954 * GetPreferredSizes(): ask all children their preferred sizes, | |
1955 * set max_cw, max_ch accordingly. | |
1956 * | |
1957 * PreferredSize(): given max_cw, max_ch, return tabs widget | |
1958 * preferred size. Iterate with other widths in order to get | |
1959 * a reasonable aspect ratio. | |
1960 * | |
1961 * PreferredSize2(): Given child dimensions, return Tabs | |
1962 * widget dimensions. | |
1963 * | |
1964 * PreferredSize3(): Same, except given child dimensions plus | |
1965 * shadow. | |
1966 */ | |
428 | 1967 |
434 | 1968 |
1969 /* Compute the width of one child's tab. Positions will be computed | |
428 | 1970 * elsewhere. |
1971 * | |
1972 * height: font height + vertical_space*2 + shadowWid*2 | |
1973 * width: string width + horizontal_space*2 + shadowWid*2 | |
1974 * | |
1975 * All tabs are the same height, so that is computed elsewhere. | |
1976 */ | |
1977 | |
1978 static void | |
1979 TabWidth(Widget w) | |
1980 { | |
1981 TabsConstraints tab = (TabsConstraints) w->core.constraints ; | |
1982 TabsWidget tw = (TabsWidget)XtParent(w) ; | |
1983 String lbl = tab->tabs.label != NULL ? | |
3094 | 1984 tab->tabs.label : XtName(w); |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
1985 #ifdef HAVE_XFT_TABS |
3094 | 1986 XftFont *font = tw->tabs.renderFont; |
1987 #else | |
1988 XFontStruct *font = tw->tabs.font; | |
1989 #endif | |
1990 int iw = tw->tabs.internalWidth; | |
428 | 1991 |
1992 tab->tabs.width = iw + SHADWID*2 ; | |
1993 tab->tabs.l_x = tab->tabs.lbm_x = SHADWID + iw ; | |
1994 | |
1995 if( tab->tabs.left_bitmap != None ) | |
1996 { | |
1997 tab->tabs.width += tab->tabs.lbm_width + iw ; | |
1998 tab->tabs.l_x += tab->tabs.lbm_width + iw ; | |
1999 tab->tabs.lbm_y = (tw->tabs.tab_height - tab->tabs.lbm_height)/2 ; | |
2000 } | |
2001 | |
2002 if( lbl != NULL && font != NULL ) | |
2003 { | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2004 #ifdef HAVE_XFT_TABS |
3094 | 2005 tab->tabs.width += x_xft_text_width (XtDisplay(tw), font, |
3374 | 2006 (FcChar8 *) lbl, |
2007 (int)strlen(lbl)) + iw; | |
3094 | 2008 tab->tabs.l_y = (tw->tabs.tab_height |
2009 + tw->tabs.renderFont->ascent | |
2010 /* #### how can this subtraction be correct? */ | |
2011 - tw->tabs.renderFont->descent)/2; | |
2012 if (debug_tabs > 2) | |
2013 fprintf (stderr, "tab: height=%d, width=%d, baseline=%d.\n", | |
2014 tw->tabs.tab_height, tab->tabs.width, tab->tabs.l_y); | |
2015 if (debug_tabs > 1) | |
2016 fprintf (stderr, "font: height=%d, ascent=%d, descent=%d.\n", | |
2017 tw->tabs.renderFont->height, | |
2018 tw->tabs.renderFont->ascent, | |
2019 tw->tabs.renderFont->descent); | |
2020 #else | |
2021 tab->tabs.width += XTextWidth (font, lbl, (int)strlen(lbl)) + iw; | |
428 | 2022 tab->tabs.l_y = (tw->tabs.tab_height + |
434 | 2023 tw->tabs.font->max_bounds.ascent - |
3094 | 2024 tw->tabs.font->max_bounds.descent)/2; |
2025 #endif | |
428 | 2026 } |
2027 } | |
2028 | |
2029 | |
2030 | |
2031 /* Lay out tabs to fit in given width. Compute x,y position and | |
2032 * row number for each tab. Return number of rows and total height | |
2033 * required by all tabs. If there is only one row, add TABDELTA | |
2034 * height to the total. Rows are assigned bottom to top. | |
2035 * | |
2036 * Tabs are indented from the edges by INDENT. | |
2037 * | |
2038 * TODO: if they require more than two rows and the total height:width | |
2039 * ratio is more than 2:1, then try something else. | |
3094 | 2040 * Gaak! This is actually already done in PreferredSize()! |
2041 * | |
2042 * TODO SOONER: for reasons unclear, some applications (specifically | |
2043 * XEmacs) give a nominal geometry (in the core record) which doesn't | |
2044 * make much sense (eg, may be smaller than some of the tab children). | |
2045 * This results in bizarre values for DISPLAY_ROWS and REPLY_HEIGHT. | |
2046 * Specify a way to say "tell me what you really want" (eg, with WID | |
2047 * and/or HGT == 0 or == Dimension_MAX), and use it where appropriate. | |
2048 * LATE-BREAKING LOSE: This happens in PreferredSize(), not XEmacs! | |
2049 * | |
2050 * TODO EVEN SOONER: some applications lay out the tab control by | |
2051 * repeatedly querying until a fixed width and height has been filled | |
2052 * by the tabs (XEmacs). There should be an API to cache this? | |
428 | 2053 */ |
2054 | |
2055 static int | |
448 | 2056 TabLayout(TabsWidget tw, |
3094 | 2057 Dimension wid, /* if 0, use core.width as guess */ |
2058 Dimension hgt, /* if 0, use core.height as guess */ | |
448 | 2059 Dimension *reply_height, Bool query_only) |
428 | 2060 { |
446 | 2061 int i, row, done = 0, display_rows = 0 ; |
428 | 2062 int num_children = tw->composite.num_children ; |
2063 Widget *childP ; | |
2064 Dimension w ; | |
3094 | 2065 Position x,y ; /* #### gaak, these are dimensions! */ |
428 | 2066 TabsConstraints tab ; |
2067 | |
2068 /* Algorithm: loop through children, assign X positions. If a tab | |
2069 * would extend beyond the right edge, start a new row. After all | |
2070 * rows are assigned, make a second pass and assign Y positions. | |
2071 */ | |
2072 | |
2073 if( num_children > 0 ) | |
2074 { | |
2075 /* Loop through the tabs and see how much space they need. */ | |
2076 | |
2077 row = 0 ; | |
2078 x = INDENT ; | |
2079 y = 0 ; | |
3094 | 2080 /* If wid or hgt is 0, we want to guess our own dimensions. |
2081 Currently the guessing functions are broken.... | |
2082 #### When PreferredSize*() get fixed, fix this too. */ | |
3397 | 2083 if (debug_tabs > 1) |
3094 | 2084 fprintf (stderr, "arg=%d,", wid); |
2085 wid = (wid ? wid : tw->core.width) - INDENT ; | |
2086 hgt = hgt ? hgt : tw->core.height; | |
3397 | 2087 if (debug_tabs > 1) |
3094 | 2088 fprintf (stderr, "wid=%d: x,w,y=", wid); |
428 | 2089 for(i=num_children, childP=tw->composite.children; --i >= 0; ++childP) |
2090 if( XtIsManaged(*childP) ) | |
2091 { | |
2092 tab = (TabsConstraints) (*childP)->core.constraints ; | |
2093 w = tab->tabs.width ; | |
446 | 2094 |
3397 | 2095 if (debug_tabs > 1) |
3094 | 2096 fprintf (stderr, "%d,%d,%d;", x, w, y); |
428 | 2097 if( x + w > wid ) { /* new row */ |
3094 | 2098 /* #### algorithm is not robust to wid < child's width */ |
2099 ++row; | |
2100 x = INDENT ; | |
2101 y += tw->tabs.tab_height ; | |
2102 if (y > hgt && !done) | |
446 | 2103 { |
2104 display_rows = row; | |
2105 done = 1; | |
2106 } | |
428 | 2107 } |
2108 if( !query_only ) { | |
2109 tab->tabs.x = x ; | |
2110 tab->tabs.y = y ; | |
2111 tab->tabs.row = row ; | |
2112 } | |
2113 x += w + SPACING ; | |
446 | 2114 if (!query_only && !done) |
2115 tab->tabs.visible = 1; | |
2116 | |
428 | 2117 } |
3397 | 2118 if (debug_tabs > 1) |
3094 | 2119 fprintf (stderr, "\n"); |
442 | 2120 /* If there was only one row, increase the height by TABDELTA */ |
446 | 2121 if( ++display_rows == 1 ) |
428 | 2122 { |
2123 y = TABDELTA ; | |
2124 if( !query_only ) | |
2125 for(i=num_children, childP=tw->composite.children; | |
2126 --i >= 0 ; ++childP) | |
2127 if( XtIsManaged(*childP) ) | |
2128 { | |
2129 tab = (TabsConstraints) (*childP)->core.constraints ; | |
2130 tab->tabs.y = y ; | |
2131 } | |
2132 } | |
3094 | 2133 row++; |
428 | 2134 y += tw->tabs.tab_height ; |
2135 } | |
2136 else | |
446 | 2137 display_rows = row = y = 0 ; |
428 | 2138 |
2139 if( !query_only ) { | |
2140 tw->tabs.tab_total = y ; | |
446 | 2141 tw->tabs.numRows = display_rows ; |
2142 tw->tabs.realRows = row; | |
428 | 2143 } |
2144 | |
3397 | 2145 if (debug_tabs > 1 && (row > 1 || display_rows > 1)) |
3094 | 2146 fprintf (stderr, "tab: %d display rows, #children = %d," |
2147 " total height %d, total rows %d%s.\n", | |
2148 display_rows, num_children, y, row, | |
2149 query_only ? " (query)" : ""); | |
2150 | |
428 | 2151 if( reply_height != NULL ) |
2152 *reply_height = y ; | |
2153 | |
446 | 2154 return display_rows ; |
428 | 2155 } |
2156 | |
2157 | |
2158 | |
2159 /* Find max preferred child size. Returned sizes include child | |
434 | 2160 * border widths. |
428 | 2161 */ |
2162 | |
2163 static void | |
2164 GetPreferredSizes(TabsWidget tw) | |
2165 { | |
434 | 2166 MaxChild(tw, NULL, 0,0) ; |
428 | 2167 } |
2168 | |
2169 | |
2170 | |
3094 | 2171 /* Find max preferred child size and store in control widget. |
2172 * If except is non-null, don't ask that one. | |
434 | 2173 */ |
428 | 2174 |
2175 static void | |
434 | 2176 MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch) |
428 | 2177 { |
434 | 2178 int i ; |
2179 Widget *childP = tw->composite.children ; | |
2180 XtWidgetGeometry preferred ; | |
428 | 2181 |
2182 for(i=tw->composite.num_children; --i >=0; ++childP) | |
448 | 2183 if( TabVisible (*childP) /*XtIsManaged(*childP)*/ && *childP != except ) |
428 | 2184 { |
434 | 2185 (void) XtQueryGeometry(*childP, NULL, &preferred) ; |
2186 cw = Max(cw, preferred.width + preferred.border_width * 2 ) ; | |
2187 ch = Max(ch, preferred.height + preferred.border_width * 2 ) ; | |
428 | 2188 } |
2189 | |
2190 tw->tabs.max_cw = cw ; | |
2191 tw->tabs.max_ch = ch ; | |
2192 } | |
2193 | |
2194 | |
2195 | |
2196 /* rotate row numbers to bring current widget to bottom row, | |
2197 * compute y positions for all tabs | |
2198 */ | |
2199 | |
2200 static void | |
2201 TabsShuffleRows(TabsWidget tw) | |
2202 { | |
2203 TabsConstraints tab ; | |
2204 int move ; | |
446 | 2205 int real_rows, display_rows ; |
428 | 2206 Widget *childP ; |
2207 Dimension th = tw->tabs.tab_height ; | |
2208 Position bottom ; | |
2209 int i ; | |
2210 | |
2211 /* There must be a top widget. If not, assign one. */ | |
2212 if( tw->tabs.topWidget == NULL && tw->composite.children != NULL ) | |
446 | 2213 for(i=TabsNumChildren (tw), childP=tw->composite.children; |
428 | 2214 --i >= 0; |
2215 ++childP) | |
2216 if( XtIsManaged(*childP) ) { | |
2217 tw->tabs.topWidget = *childP ; | |
2218 break ; | |
2219 } | |
2220 | |
2221 if( tw->tabs.topWidget != NULL ) | |
2222 { | |
446 | 2223 display_rows = tw->tabs.numRows ; |
2224 real_rows = tw->tabs.realRows ; | |
448 | 2225 assert( display_rows <= real_rows ) ; |
428 | 2226 |
446 | 2227 if( real_rows > 1 ) |
428 | 2228 { |
2229 tab = (TabsConstraints) tw->tabs.topWidget->core.constraints ; | |
2230 assert( tab != NULL ) ; | |
2231 | |
446 | 2232 /* How far to move top row. The selected tab must be on |
2233 the bottom row of the *visible* rows. */ | |
2234 move = (real_rows + 1 - display_rows) - tab->tabs.row ; | |
2235 if (move < 0) | |
2236 move = real_rows - move; | |
428 | 2237 bottom = tw->tabs.tab_total - th ; |
2238 | |
446 | 2239 for(i=tw->composite.num_children, childP=tw->composite.children; |
428 | 2240 --i >= 0; |
2241 ++childP) | |
2242 if( XtIsManaged(*childP) ) | |
2243 { | |
2244 tab = (TabsConstraints) (*childP)->core.constraints ; | |
446 | 2245 tab->tabs.row = (tab->tabs.row + move) % real_rows ; |
428 | 2246 tab->tabs.y = bottom - tab->tabs.row * th ; |
446 | 2247 tab->tabs.visible = (tab->tabs.row < display_rows); |
428 | 2248 } |
2249 } | |
2250 } | |
2251 } | |
2252 | |
2253 | |
434 | 2254 /* Find preferred size. Ask children, find size of largest, |
428 | 2255 * add room for tabs & return. This can get a little involved, |
2256 * as we don't want to have too many rows of tabs; we may widen | |
2257 * the widget to reduce # of rows. | |
434 | 2258 * |
2259 * This function requires that max_cw, max_ch already be set. | |
428 | 2260 */ |
2261 static int | |
2262 PreferredSize( | |
2263 TabsWidget tw, | |
2264 Dimension *reply_width, /* total widget size */ | |
2265 Dimension *reply_height, | |
2266 Dimension *reply_cw, /* child widget size */ | |
2267 Dimension *reply_ch) | |
2268 { | |
2269 Dimension cw,ch ; /* child width, height */ | |
2270 Dimension wid,hgt ; | |
2271 Dimension rwid,rhgt ; | |
2272 int nrow ; | |
2273 | |
2274 wid = cw = tw->tabs.max_cw ; | |
2275 hgt = ch = tw->tabs.max_ch ; | |
2276 | |
2277 nrow = PreferredSize2(tw, wid,hgt, &rwid, &rhgt) ; | |
2278 | |
2279 /* Check for absurd results (more than 2 rows, high aspect | |
2280 * ratio). Try wider size if needed. | |
2281 * TODO: make sure this terminates. | |
2282 */ | |
2283 | |
2284 if( nrow > 2 && rhgt > rwid ) | |
2285 { | |
2286 Dimension w0, w1 ; | |
434 | 2287 int maxloop = 20 ; |
428 | 2288 |
2289 /* step 1: start doubling size until it's too big */ | |
2290 do { | |
2291 w0 = wid ; | |
2292 wid = Max(wid*2, wid+20) ; | |
2293 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ; | |
2294 } while( nrow > 2 && rhgt > rwid ) ; | |
2295 w1 = wid ; | |
2296 | |
2297 /* step 2: use Newton's method to find ideal size. Stop within | |
2298 * 8 pixels. | |
2299 */ | |
434 | 2300 while( --maxloop > 0 && w1 > w0 + 8 ) |
428 | 2301 { |
2302 wid = (w0+w1)/2 ; | |
2303 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ; | |
2304 if( nrow > 2 && rhgt > rwid ) | |
2305 w0 = wid ; | |
2306 else | |
2307 w1 = wid ; | |
2308 } | |
2309 wid = w1 ; | |
2310 } | |
2311 | |
2312 *reply_width = rwid ; | |
2313 *reply_height = rhgt ; | |
2314 if( reply_cw != NULL ) *reply_cw = cw ; | |
2315 if( reply_ch != NULL ) *reply_ch = ch ; | |
2316 return nrow ; | |
2317 } | |
2318 | |
2319 | |
2320 /* Find preferred size, given size of children. */ | |
2321 | |
2322 static int | |
2323 PreferredSize2( | |
2324 TabsWidget tw, | |
448 | 2325 Dimension cw, /* child width, height */ |
2326 Dimension ch, | |
428 | 2327 Dimension *reply_width, /* total widget size */ |
2328 Dimension *reply_height) | |
2329 { | |
2330 Dimension s = SHADWID ; | |
448 | 2331 int ret; |
428 | 2332 |
2333 /* make room for shadow frame */ | |
2334 cw += s*2 ; | |
2335 ch += s*2 ; | |
2336 | |
448 | 2337 ret = PreferredSize3(tw, cw, ch, reply_width, reply_height) ; |
2338 | |
2339 assert (*reply_width > 0 && *reply_height > 0); | |
2340 return ret; | |
428 | 2341 } |
2342 | |
2343 | |
2344 /* Find preferred size, given size of children+shadow. */ | |
2345 | |
2346 static int | |
2347 PreferredSize3( | |
2348 TabsWidget tw, | |
448 | 2349 Dimension wid, /* child width, height */ |
2350 Dimension hgt, | |
428 | 2351 Dimension *reply_width, /* total widget size */ |
2352 Dimension *reply_height) | |
2353 { | |
2354 Dimension th ; /* space used by tabs */ | |
2355 int nrows ; | |
2356 | |
2357 if( tw->composite.num_children > 0 ) | |
3094 | 2358 /* used to be wid, hgt not 0, 0 but that's obviously wrong |
2359 since TabLayout wants dimensions of control parent but | |
2360 wid, hgt are dimensions of some child */ | |
2361 nrows = TabLayout(tw, 0, 0, &th, True) ; | |
428 | 2362 else { |
2363 th = 0 ; | |
2364 nrows = 0 ; | |
2365 } | |
2366 | |
2367 *reply_width = Max(wid, MIN_WID) ; | |
2368 *reply_height = Max(th+hgt, MIN_HGT) ; | |
2369 | |
2370 return nrows ; | |
2371 } | |
2372 | |
2373 | |
2374 static void | |
2375 MakeSizeRequest(TabsWidget tw) | |
2376 { | |
2377 Widget w = (Widget)tw ; | |
2378 XtWidgetGeometry request, reply ; | |
2379 XtGeometryResult result ; | |
2380 Dimension cw,ch ; | |
2381 | |
2382 request.request_mode = CWWidth | CWHeight ; | |
2383 PreferredSize(tw, &request.width, &request.height, &cw, &ch) ; | |
2384 | |
2385 if( request.width == tw->core.width && | |
2386 request.height == tw->core.height ) | |
2387 return ; | |
2388 | |
2389 result = XtMakeGeometryRequest(w, &request, &reply) ; | |
2390 | |
2391 if( result == XtGeometryAlmost ) | |
2392 { | |
2393 /* Bugger. Didn't get what we want, but were offered a | |
2394 * compromise. If the width was too small, recompute | |
2395 * based on the too-small width and try again. | |
2396 * If the height was too small, make a wild-ass guess | |
2397 * at a wider width and try again. | |
2398 */ | |
2399 | |
2400 if( reply.width < request.width && reply.height >= request.height ) | |
2401 { | |
2402 Dimension s = SHADWID ; | |
2403 ch += s*2 ; | |
2404 PreferredSize3(tw, reply.width,ch, &request.width, &request.height); | |
2405 result = XtMakeGeometryRequest(w, &request, &reply) ; | |
2406 if( result == XtGeometryAlmost ) | |
2407 (void) XtMakeGeometryRequest(w, &reply, NULL) ; | |
2408 } | |
2409 | |
2410 else | |
2411 (void) XtMakeGeometryRequest(w, &reply, NULL) ; | |
2412 } | |
2413 } | |
2414 | |
2415 | |
2416 static void | |
2417 getBitmapInfo(TabsWidget tw, TabsConstraints tab) | |
2418 { | |
2419 Window root ; | |
2420 int x,y ; | |
2421 unsigned int bw ; | |
2422 | |
2423 if( tab->tabs.left_bitmap == None || | |
2424 !XGetGeometry(XtDisplay(tw), tab->tabs.left_bitmap, &root, &x, &y, | |
434 | 2425 &tab->tabs.lbm_width, &tab->tabs.lbm_height, |
428 | 2426 &bw, &tab->tabs.lbm_depth) ) |
2427 tab->tabs.lbm_width = tab->tabs.lbm_height = 0 ; | |
2428 } | |
2429 | |
2430 | |
2431 | |
2432 | |
2433 /* Code copied & modified from Gcs.c. This version has dynamic | |
2434 * foreground. | |
2435 */ | |
2436 | |
2437 static void | |
2438 TabsAllocFgGC(TabsWidget tw) | |
2439 { | |
2440 Widget w = (Widget) tw; | |
2441 XGCValues values ; | |
2442 | |
3094 | 2443 values.background = tw->core.background_pixel; |
2444 values.font = | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2445 #ifdef HAVE_XFT_TABS |
3094 | 2446 None; |
2447 #else | |
2448 tw->tabs.font->fid; | |
2449 #endif | |
2450 values.line_style = LineOnOffDash; | |
2451 values.line_style = LineSolid; | |
428 | 2452 |
2453 tw->tabs.foregroundGC = | |
2454 XtAllocateGC(w, w->core.depth, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2455 #ifndef HAVE_XFT_TABS |
3094 | 2456 GCFont| |
2457 #endif | |
2458 GCBackground|GCLineStyle, | |
2459 &values, | |
2460 GCForeground, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2461 #ifdef HAVE_XFT_TABS |
3094 | 2462 GCFont| |
2463 #endif | |
2464 GCSubwindowMode|GCGraphicsExposures|GCDashOffset| | |
2465 GCDashList|GCArcMode); | |
428 | 2466 } |
2467 | |
2468 static void | |
2469 TabsAllocGreyGC(TabsWidget tw) | |
2470 { | |
2471 Widget w = (Widget) tw; | |
2472 XGCValues values ; | |
2473 | |
3094 | 2474 values.background = tw->core.background_pixel; |
2475 values.font = | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2476 #ifdef HAVE_XFT_TABS |
3094 | 2477 None; |
2478 #else | |
2479 tw->tabs.font->fid; | |
2480 #endif | |
2481 if (tw->tabs.be_nice_to_cmap || w->core.depth == 1) | |
428 | 2482 { |
3094 | 2483 values.fill_style = FillStippled; |
428 | 2484 tw->tabs.grey50 = |
3094 | 2485 values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1); |
428 | 2486 |
2487 tw->tabs.greyGC = | |
2488 XtAllocateGC(w, w->core.depth, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2489 #ifndef HAVE_XFT_TABS |
3094 | 2490 GCFont| |
2491 #endif | |
2492 GCBackground|GCStipple|GCFillStyle, &values, | |
428 | 2493 GCForeground, |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2494 #ifdef HAVE_XFT_TABS |
3094 | 2495 GCFont| |
2496 #endif | |
428 | 2497 GCSubwindowMode|GCGraphicsExposures|GCDashOffset| |
3094 | 2498 GCDashList|GCArcMode); |
428 | 2499 } |
2500 else | |
2501 { | |
2502 tw->tabs.greyGC = | |
2503 XtAllocateGC(w, w->core.depth, | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2504 #ifdef HAVE_XFT_TABS |
3094 | 2505 0L, |
2506 #else | |
2507 GCFont, | |
2508 #endif | |
2509 &values, | |
428 | 2510 GCForeground, |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4769
diff
changeset
|
2511 #ifdef HAVE_XFT_TABS |
3094 | 2512 GCFont| |
2513 #endif | |
428 | 2514 GCBackground|GCSubwindowMode|GCGraphicsExposures|GCDashOffset| |
3094 | 2515 GCDashList|GCArcMode); |
428 | 2516 } |
2517 } |