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