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