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