comparison lwlib/xlwtabs.c @ 3094:ad2f4ae9895b

[xemacs-hg @ 2005-11-26 11:45:47 by stephent] Xft merge. <87k6ev4p8q.fsf@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Sat, 26 Nov 2005 11:46:25 +0000
parents facf3239ba30
children 174eb4da74fb
comparison
equal deleted inserted replaced
3093:769dc945b085 3094:ad2f4ae9895b
15 15
16 You should have received a copy of the GNU General Public License 16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to 17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */ 19 Boston, MA 02111-1307, USA. */
20
21 /* Synched up with: Tabs.c 1.27.
22
23 #### This file contains essential XEmacs related fixes to the original
24 verison of the Tabs widget. Be VERY careful about syncing if you ever
25 update to a more recent version. In general this is probably now a
26 bad idea. */
27 20
28 /* 21 /*
29 * Tabs.c - Index Tabs composite widget 22 * Tabs.c - Index Tabs composite widget
30 * 23 *
31 * Author: Edward A. Falk 24 * Author: Edward A. Falk
54 * The tabs overlap the frame and each other vertically by the shadow 47 * The tabs overlap the frame and each other vertically by the shadow
55 * width, so that when the topmost tab is drawn, it obliterates part of 48 * width, so that when the topmost tab is drawn, it obliterates part of
56 * the frame. 49 * the frame.
57 */ 50 */
58 51
52 /* Synched up with: Tabs.c 1.27.
53
54 This file contains essential XEmacs-related fixes to the original
55 version of the Tabs widget. Be VERY careful about syncing if you ever
56 update to a more recent version. In general this is probably now a
57 bad idea.
58
59 #### We need to check that various windows (the whole widget, or a single
60 tab) are of "reasonable" size, ie, we need to try for more sanity in the
61 geometry management routines.
62 */
63
59 /* 64 /*
60 * TODO: min child height = tab height 65 * TODO: min child height = tab height
61 */ 66 */
62 67
63 #include <config.h> 68 #include <config.h>
65 70
66 #include <X11/Xlib.h> 71 #include <X11/Xlib.h>
67 #include <X11/IntrinsicP.h> 72 #include <X11/IntrinsicP.h>
68 #include <X11/StringDefs.h> 73 #include <X11/StringDefs.h>
69 74
75 /* #### This may be risky, lwlib-internal.h redefines abort() */
76 #include "lwlib-fonts.h"
77 #include "lwlib-colors.h"
70 #include "lwlib-internal.h" 78 #include "lwlib-internal.h"
71 #include "../src/xmu.h" 79 #include "../src/xmu.h"
72 #include "xlwtabsP.h" 80 #include "xlwtabsP.h"
73 #include "xlwgcs.h" 81 #include "xlwgcs.h"
74 82
83 #define XFT_USE_HEIGHT_NOT_ASCENT_DESCENT 0
84
85 /* #### These should probably be resources. */
75 #define MIN_WID 10 86 #define MIN_WID 10
76 #define MIN_HGT 10 87 #define MIN_HGT 10
77 #define INDENT 3 /* tabs indented from edge by this much */ 88 #define INDENT 3 /* tabs indented from edge by this much */
78 #define SPACING 0 /* distance between tabs */ 89 #define SPACING 0 /* distance between tabs */
79 #define SHADWID 1 /* default shadow width */ 90 #define SHADWID 1 /* default shadow width */
136 147
137 {XtNselectInsensitive, XtCSelectInsensitive, XtRBoolean, sizeof(Boolean), 148 {XtNselectInsensitive, XtCSelectInsensitive, XtRBoolean, sizeof(Boolean),
138 offset(selectInsensitive), XtRImmediate, (XtPointer) True}, 149 offset(selectInsensitive), XtRImmediate, (XtPointer) True},
139 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 150 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
140 offset(font), XtRString, (XtPointer) XtDefaultFont}, 151 offset(font), XtRString, (XtPointer) XtDefaultFont},
152 #ifdef USE_XFT_TABS
153 /* #### Maybe use "-*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-1" here? */
154 {XtNxftFont, XtCXftFont, XtRString, sizeof (String),
155 offset(renderFontSpec), XtRString,
156 (XtPointer) "AirCut-16" /* XtDefaultFont */},
157 #endif
141 {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension), 158 {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
142 offset(internalWidth), XtRImmediate, (XtPointer)4 }, 159 offset(internalWidth), XtRImmediate, (XtPointer)4 },
143 {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension), 160 {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
144 offset(internalHeight), XtRImmediate, (XtPointer)4 }, 161 offset(internalHeight), XtRImmediate, (XtPointer)4 },
145 {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), 162 {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
398 #define TabVisible(tab) \ 415 #define TabVisible(tab) \
399 (XtIsManaged(tab) && \ 416 (XtIsManaged(tab) && \
400 ((TabsConstraints)((tab)->core.constraints))->tabs.visible) 417 ((TabsConstraints)((tab)->core.constraints))->tabs.visible)
401 418
402 419
420
421 static int debug_tabs = 0; /* increase for more verbosity */
422
423 #ifdef USE_XFT_TABS
424 /* #### duplicated from xlwmenu.c -- CLEAN THIS SHIT UP!
425 Undeclared so define at top. */
426 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
427 ? ((unsigned long) (x)) : ((unsigned long) (y)))
428
429 static int
430 x_xft_text_width (Display *dpy, XftFont *xft_font, FcChar8 *run, int len)
431 {
432 static XGlyphInfo glyphinfo; /* #### static? */
433
434 XftTextExtents8 (dpy,
435 xft_font,
436 run, len, &glyphinfo);
437 return glyphinfo.xOff;
438 }
439 #endif
440
403 /**************************************************************** 441 /****************************************************************
404 * 442 *
405 * Member Procedures 443 * Member Procedures
406 * 444 *
407 ****************************************************************/ 445 ****************************************************************/
434 /* height is easy, it's the same for all tabs: 472 /* height is easy, it's the same for all tabs:
435 * TODO: font height + height of tallest bitmap. 473 * TODO: font height + height of tallest bitmap.
436 */ 474 */
437 newTw->tabs.tab_height = 2 * newTw->tabs.internalHeight + SHADWID ; 475 newTw->tabs.tab_height = 2 * newTw->tabs.internalHeight + SHADWID ;
438 476
439 if( newTw->tabs.font != NULL ) 477 #ifdef USE_XFT_TABS
478 /* must get font here
479 to do this right, we should add a new Xt Resource type +
480 conversion function
481 */
482 newTw->tabs.renderFont =
483 xft_open_font_by_name (XtDisplay ((Widget) newTw),
484 newTw->tabs.renderFontSpec);
485 if (newTw->tabs.renderFont != NULL)
486 #if XFT_USE_HEIGHT_NOT_ASCENT_DESCENT
487 newTw->tabs.tab_height += newTw->tabs.renderFont->height;
488 #else
489 newTw->tabs.tab_height += newTw->tabs.renderFont->ascent +
490 newTw->tabs.renderFont->descent;
491 #endif /* XFT_USE_HEIGHT_NOT_ASCENT_DESCENT */
492 #else /* ! USE_XFT_TABS */
493 if (newTw->tabs.font != NULL)
440 newTw->tabs.tab_height += newTw->tabs.font->max_bounds.ascent + 494 newTw->tabs.tab_height += newTw->tabs.font->max_bounds.ascent +
441 newTw->tabs.font->max_bounds.descent ; 495 newTw->tabs.font->max_bounds.descent;
442 496 #endif /* ! USE_XFT_TABS */
443 /* GC allocation is deferred until XtRealize() */
444 497
445 /* if size not explicitly set, set it to our preferred size now. */ 498 /* if size not explicitly set, set it to our preferred size now. */
446 499
447 if( request->core.width == 0 || request->core.height == 0 ) 500 if( request->core.width == 0 || request->core.height == 0 )
448 { 501 {
612 TabsWidget tw = (TabsWidget) new_ ; 665 TabsWidget tw = (TabsWidget) new_ ;
613 Boolean needRedraw = False ; 666 Boolean needRedraw = False ;
614 Widget *childP ; 667 Widget *childP ;
615 int i ; 668 int i ;
616 669
617 670 if(
618 if( tw->tabs.font != curtw->tabs.font || 671 #ifdef USE_XFT_TABS
619 tw->tabs.internalWidth != curtw->tabs.internalWidth || 672 tw->tabs.renderFont != curtw->tabs.renderFont ||
620 tw->tabs.internalHeight != curtw->tabs.internalHeight ) 673 #else
674 tw->tabs.font != curtw->tabs.font ||
675 #endif
676 tw->tabs.internalWidth != curtw->tabs.internalWidth ||
677 tw->tabs.internalHeight != curtw->tabs.internalHeight)
621 { 678 {
622 tw->tabs.tab_height = 2 * tw->tabs.internalHeight + SHADWID ; 679 tw->tabs.tab_height = 2 * tw->tabs.internalHeight + SHADWID;
623 680
624 if( tw->tabs.font != NULL ) 681 #ifdef USE_XFT_TABS
682 if (tw->tabs.renderFont != NULL)
683 #if XFT_USE_HEIGHT_NOT_ASCENT_DESCENT
684 tw->tabs.tab_height += tw->tabs.renderFont->height;
685 #else
686 tw->tabs.tab_height += tw->tabs.renderFont->ascent +
687 tw->tabs.renderFont->descent;
688 #endif /* XFT_USE_HEIGHT_NOT_ASCENT_DESCENT */
689 #else /* ! USE_XFT_TABS */
690 if (tw->tabs.font != NULL)
625 tw->tabs.tab_height += tw->tabs.font->max_bounds.ascent + 691 tw->tabs.tab_height += tw->tabs.font->max_bounds.ascent +
626 tw->tabs.font->max_bounds.descent ; 692 tw->tabs.font->max_bounds.descent;
693 #endif /* ! USE_XFT_TABS */
627 694
628 /* Tab size has changed. Resize all tabs and request a new size */ 695 /* Tab size has changed. Resize all tabs and request a new size */
629 for(i=0, childP=tw->composite.children; 696 for(i=0, childP=tw->composite.children;
630 i < (int) tw->composite.num_children; 697 i < (int) tw->composite.num_children;
631 ++i, ++childP) 698 ++i, ++childP)
638 705
639 /* TODO: if any color changes, need to recompute GCs and redraw */ 706 /* TODO: if any color changes, need to recompute GCs and redraw */
640 707
641 if( tw->core.background_pixel != curtw->core.background_pixel || 708 if( tw->core.background_pixel != curtw->core.background_pixel ||
642 tw->core.background_pixmap != curtw->core.background_pixmap || 709 tw->core.background_pixmap != curtw->core.background_pixmap ||
643 tw->tabs.font != curtw->tabs.font ) 710 #ifdef USE_XFT_TABS
711 tw->tabs.renderFont != curtw->tabs.renderFont
712 #else
713 tw->tabs.font != curtw->tabs.font
714 #endif
715 )
644 if( XtIsRealized(new_) ) 716 if( XtIsRealized(new_) )
645 { 717 {
646 TabsFreeGCs(tw) ; 718 TabsFreeGCs(tw) ;
647 TabsAllocGCs(tw) ; 719 TabsAllocGCs(tw) ;
648 needRedraw = True ; 720 needRedraw = True ;
753 } 825 }
754 826
755 827
756 828
757 /* 829 /*
758 * Return preferred size. Happily accept anything >= our preferred size. 830 * Return status, with preferred size in PREFERRED.
759 * (TODO: is that the right thing to do? Should we always return "almost" 831 *
760 * if offered more than we need?) 832 * According to the X Toolkit Intrinsics manual
833 * XtGeometryYes = accept INTENDED without change
834 * XtGeometryNo = request to stay _exactly_ the same
835 * XtGeometryAlmost = suggest PREFERRED as a compromise
836 * and the PREFERRED argument must be filled in completely (ie, any fields
837 * whose bits are set in the request_mode mask must correspond to the
838 * preferred geometry, which must be consistent with the return value).
839 *
840 * Assuming horizontal orientation, in XEmacs, we should always accept if
841 * the width is more than we need. There's no problem if there are only a
842 * couple of tabs packed to the left. OTOH there's probably something wrong
843 * if we're offered a height more than 1.5x or 2x the preferred height.
844 * (#### Do tab controls do vertical?)
761 */ 845 */
762 846
847 /* compute the height above which we complain */
848 #define TAB_HEIGHT_TOLERANCE(x) (2*x)
849
763 static XtGeometryResult 850 static XtGeometryResult
764 TabsQueryGeometry(Widget w, 851 TabsQueryGeometry (Widget w,
765 XtWidgetGeometry *intended, XtWidgetGeometry *preferred) 852 XtWidgetGeometry *intended,
766 { 853 XtWidgetGeometry *preferred) /* RETURN */
767 register TabsWidget tw = (TabsWidget)w ; 854 {
768 XtGeometryMask mode = intended->request_mode ; 855 TabsWidget tw = (TabsWidget) w;
769 856 XtGeometryMask mode = intended->request_mode;
770 preferred->request_mode = CWWidth | CWHeight ; 857
771 PreferredSize(tw, &preferred->width, &preferred->height, NULL,NULL) ; 858 preferred->request_mode = CWWidth | CWHeight;
772 859 PreferredSize (tw, &preferred->width, &preferred->height, NULL, NULL);
773 if( (!(mode & CWWidth) || intended->width == w->core.width) && 860
774 (!(mode & CWHeight) || intended->height == w->core.height) ) 861 /* If width is big enough, accept it. */
775 return XtGeometryNo ; 862 if ((mode & CWWidth) && intended->width >= preferred->width)
776 863 preferred->width = intended->width;
777 if( (!(mode & CWWidth) || intended->width >= preferred->width) && 864
778 (!(mode & CWHeight) || intended->height >= preferred->height) ) 865 /* If height is within range, accept it.
866 #### If too tall, we could offer a compromise at TAB_HEIGHT_TOLERANCE.
867 Should we? */
868 if ((mode & CWHeight) && intended->height >= preferred->height
869 && intended->height <= TAB_HEIGHT_TOLERANCE (preferred->height))
870 preferred->height = intended->height;
871
872 /* Compute return value. */
873 if (preferred->width == ((mode & CWWidth) ? intended->width
874 : w->core.width)
875 && preferred->height == ((mode & CWHeight) ? intended->height
876 : w->core.height))
779 return XtGeometryYes; 877 return XtGeometryYes;
780 878 else if (preferred->width == w->core.width
781 return XtGeometryAlmost; 879 && preferred->height == w->core.height)
880 return XtGeometryNo;
881 else
882 return XtGeometryAlmost;
782 } 883 }
783 884
784 885
785 886
786 /* 887 /*
787 * Geometry Manager; called when a child wants to be resized. 888 * Geometry Manager; called when TAB (a child) wants to be resized.
889 *
890 * According to the X Toolkit Intrinsics manual
891 * XtGeometryDone = accept REQUEST and do it (#### check this)
892 * XtGeometryYes = accept REQUEST without change
893 * XtGeometryNo = refuse REQUEST (ie, stay _exactly_ the same)
894 * XtGeometryAlmost = suggest REPLY as a compromise
788 */ 895 */
789 896
790 static XtGeometryResult 897 static XtGeometryResult
791 TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply) 898 TabsGeometryManager (Widget tab,
792 { 899 XtWidgetGeometry *request,
793 TabsWidget tw = (TabsWidget) XtParent(w); 900 XtWidgetGeometry *reply) /* RETURN */
794 Dimension s = SHADWID ; 901 {
795 TabsConstraints tab = (TabsConstraints)w->core.constraints; 902 TabsWidget control = (TabsWidget) XtParent(tab);
796 XtGeometryResult result ; 903 Dimension s = SHADWID;
797 Dimension rw, rh ; 904 TabsConstraints constraint = (TabsConstraints) tab->core.constraints;
798 905 XtGeometryResult result, best_offer = XtGeometryYes;
799 /* Position request always denied */ 906 Dimension rw, rh;
800 907
801 if( ((req->request_mode & CWX) && req->x != w->core.x) || 908 static int debug_count = 0;
802 ((req->request_mode & CWY) && req->y != w->core.y) || 909 static int debug_mask = 1;
803 !tab->tabs.resizable ) 910
804 return XtGeometryNo ; 911 /* Position request cannot be satisfied, so if tabs are not resizable,
805 912 no nontrivial request can be satisfied: return XGeometryNo. */
806 /* Make all three fields in the request valid */ 913 if (!constraint->tabs.resizable)
807 if( !(req->request_mode & CWWidth) ) 914 return XtGeometryNo;
808 req->width = w->core.width; 915
809 if( !(req->request_mode & CWHeight) ) 916 fprintf (stderr, "Urk! label is resizable!\n");
810 req->height = w->core.height; 917
811 if( !(req->request_mode & CWBorderWidth) ) 918 /* Assume we will refuse these; toggle iff we accept them.
812 req->border_width = w->core.border_width; 919 Reply won't specify any fields not in the request. */
813 920 reply->request_mode = request->request_mode;
814 if( req->width == w->core.width && 921 reply->x = tab->core.x;
815 req->height == w->core.height && 922 reply->y = tab->core.y;
816 req->border_width == w->core.border_width ) 923
817 return XtGeometryNo ; 924 /* If a position request would result in a change, best offer is
818 925 XtGeometryAlmost. Otherwise toggle reply->request_mode. */
819 rw = req->width + 2 * req->border_width ; 926 if ((request->request_mode & CWX) && request->x != tab->core.x)
820 rh = req->height + 2 * req->border_width ; 927 best_offer = XtGeometryAlmost;
928 else
929 reply->request_mode &= ~CWX;
930 if ((request->request_mode & CWY) && request->y != tab->core.y)
931 best_offer = XtGeometryAlmost;
932 else
933 reply->request_mode &= ~CWY;
934
935 /* Make all three fields in the reply valid */
936 reply->width = (request->request_mode & CWWidth)
937 ? request->width : tab->core.width;
938 reply->height = (request->request_mode & CWHeight)
939 ? request->height : tab->core.height;
940 reply->border_width = (request->request_mode & CWBorderWidth)
941 ? request->border_width : tab->core.border_width;
942
943 /* check if we can already offer a compromise */
944 if (best_offer == XtGeometryAlmost &&
945 reply->width == tab->core.width &&
946 reply->height == tab->core.height &&
947 reply->border_width == tab->core.border_width)
948 {
949 reply->request_mode &= ~(CWWidth | CWHeight | CWBorderWidth);
950 return best_offer;
951 }
952
953 #ifndef DONT_DEBUG_REQUESTS
954 #define DBG_REQUEST_PRINT(name,field,size) \
955 do { \
956 if (reply->field > size) \
957 { \
958 if (++debug_count == debug_mask) \
959 { \
960 debug_mask <<= 1; \
961 fprintf (stderr, "ridiculous %s request #%d: %d > %d\n", \
962 name, debug_count, reply->field, size); \
963 } \
964 reply->field = tab->core.field; \
965 } \
966 } while (0)
967
968 DBG_REQUEST_PRINT ("width",width,1024);
969 DBG_REQUEST_PRINT ("height",height,768);
970 DBG_REQUEST_PRINT ("border_width",border_width,30);
971 #undef DBG_REQUEST_PRINT
972 #endif
973
974 rw = reply->width + 2 * reply->border_width;
975 rh = reply->height + 2 * reply->border_width;
821 976
822 /* find out how big the children want to be now */ 977 /* find out how big the children want to be now */
823 MaxChild(tw, w, rw, rh) ; 978 MaxChild (control, tab, rw, rh);
824 979
825 980
826 /* Size changes must see if the new size can be accommodated. 981 /* Size changes must see if the new size can be accommodated.
827 * The Tabs widget keeps all of its children the same 982 * The Tabs widget keeps all of its children the same height, but
828 * size. A request to shrink will be accepted only if the 983 * widths may vary.
984 * A request to shrink will be accepted only if the
829 * new size is still big enough for all other children. A 985 * new size is still big enough for all other children. A
830 * request to shrink that is not big enough for all children 986 * request to shrink that is not big enough for all children
831 * returns an "almost" response with the new proposed size 987 * returns an "almost" response with the new proposed size
832 * or a "no" response if unable to shrink at all. 988 * or a "no" response if unable to shrink at all.
833 * 989 *
834 * A request to grow will be accepted only if the Tabs parent can 990 * A request to grow will be accepted only if the Tabs control can
835 * grow to accommodate. 991 * grow to accommodate.
836 * 992 *
837 * TODO: 993 * TODO:
838 * We could get fancy here and re-arrange the tabs if it is 994 * We could get fancy here and re-arrange the tabs if it is
839 * necessary to compromise with the parent, but we'll save that 995 * necessary to compromise with the parent, but we'll save that
840 * for another day. 996 * for another day.
841 */ 997 */
842 998
843 if (req->request_mode & (CWWidth | CWHeight | CWBorderWidth)) 999 if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth))
844 { 1000 {
845 Dimension cw,ch ; /* children's preferred size */ 1001 Dimension cw,ch ; /* children's preferred size */
846 Dimension aw,ah ; /* available size we can give child */ 1002 Dimension aw,ah ; /* available size we can give child */
847 Dimension th ; /* space used by tabs */ 1003 Dimension th ; /* space used by tabs */
848 Dimension wid,hgt ; /* Tabs widget size */ 1004 Dimension wid,hgt ; /* Tabs widget size */
849 1005 int check_nrows;
850 cw = tw->tabs.max_cw ; 1006
851 ch = tw->tabs.max_ch ; 1007 cw = control->tabs.max_cw ;
1008 ch = control->tabs.max_ch ;
852 1009
853 /* find out what *my* resulting preferred size would be */ 1010 /* find out what *my* resulting preferred size would be */
854 1011 /* #### this whole API is wrong; what should happen is
855 PreferredSize2(tw, cw, ch, &wid, &hgt) ; 1012 1. app should hint as to #rows and/or aspect ratio
1013 2. tab control should attempt to layout in current space
1014 3. if not all tabs fit, should request resize to achieve
1015 layout hints
1016 Probably can and should cache preferred size in widget, with
1017 cache cleared when labels or core size changes. */
1018 PreferredSize2(control, cw, ch, &wid, &hgt) ;
856 1019
857 /* Would my size change? If so, ask to be resized. */ 1020 /* Would my size change? If so, ask to be resized. */
858 1021
859 if( wid != tw->core.width || hgt != tw->core.height ) 1022 if (wid != control->core.width || hgt != control->core.height)
860 { 1023 {
861 Dimension oldWid = tw->core.width, oldHgt = tw->core.height ; 1024 Dimension oldWid = control->core.width,
1025 oldHgt = control->core.height;
862 XtWidgetGeometry myrequest, myreply ; 1026 XtWidgetGeometry myrequest, myreply ;
863 1027
864 myrequest.width = wid ; 1028 myrequest.width = wid ;
865 myrequest.height = hgt ; 1029 myrequest.height = hgt ;
866 myrequest.request_mode = CWWidth | CWHeight ; 1030 myrequest.request_mode = CWWidth | CWHeight ;
868 assert (wid > 0 && hgt > 0); 1032 assert (wid > 0 && hgt > 0);
869 /* If child is only querying, or if we're going to have to 1033 /* If child is only querying, or if we're going to have to
870 * offer the child a compromise, then make this a query only. 1034 * offer the child a compromise, then make this a query only.
871 */ 1035 */
872 1036
873 if( (req->request_mode & XtCWQueryOnly) || rw < cw || rh < ch ) 1037 if ((request->request_mode & XtCWQueryOnly) || rw < cw || rh < ch)
874 myrequest.request_mode |= XtCWQueryOnly ; 1038 myrequest.request_mode |= XtCWQueryOnly;
875 1039
876 result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ; 1040 result = XtMakeGeometryRequest ((Widget) control,
1041 &myrequest, &myreply);
877 1042
878 /* !$@# Athena Box widget changes the core size even if QueryOnly 1043 /* !$@# Athena Box widget changes the core size even if QueryOnly
879 * is set. I'm convinced this is a bug. At any rate, to work 1044 * is set. I'm convinced this is a bug. At any rate, to work
880 * around the bug, we need to restore the core size after every 1045 * around the bug, we need to restore the core size after every
881 * query geometry request. This is only partly effective, 1046 * query geometry request. This is only partly effective,
882 * as there may be other boxes further up the tree. 1047 * as there may be other boxes further up the tree.
883 */ 1048 */
884 if( myrequest.request_mode & XtCWQueryOnly ) { 1049 if (myrequest.request_mode & XtCWQueryOnly) {
885 tw->core.width = oldWid ; 1050 control->core.width = oldWid;
886 tw->core.height = oldHgt ; 1051 control->core.height = oldHgt;
887 } 1052 }
888 1053
889 /* based on the parent's response, determine what the 1054 /* based on the parent's response, determine what the
890 * resulting Tabs widget size would be. 1055 * resulting Tabs widget size would be.
891 */ 1056 */
892 1057
893 switch( result ) { 1058 switch (result) {
894 case XtGeometryYes: 1059 case XtGeometryYes:
895 case XtGeometryDone: 1060 case XtGeometryDone:
896 tw->tabs.needs_layout = True ; 1061 control->tabs.needs_layout = True;
897 break ; 1062 break;
898 1063
899 case XtGeometryNo: 1064 case XtGeometryNo:
900 wid = tw->core.width ; 1065 wid = control->core.width;
901 hgt = tw->core.height ; 1066 hgt = control->core.height;
902 break ; 1067 break;
903 1068
904 case XtGeometryAlmost: 1069 case XtGeometryAlmost:
905 wid = myreply.width ; 1070 wid = myreply.width;
906 hgt = myreply.height ; 1071 hgt = myreply.height;
907 tw->tabs.needs_layout = True ; 1072 control->tabs.needs_layout = True;
908 break ; 1073 break;
909 } 1074 }
910 } 1075 }
911 1076
912 /* Within the constraints imposed by the parent, what is 1077 /* Within the constraints imposed by the parent, what is
913 * the max size we can give the child? 1078 * the max size we can give the child?
914 */ 1079 */
915 (void) TabLayout(tw, wid, hgt, &th, True) ; 1080 check_nrows = TabLayout (control, wid, hgt, &th, True);
916 aw = wid - 2*s ; 1081 aw = wid - 2*s;
917 ah = hgt - th - 2*s ; 1082 if (check_nrows == 1)
1083 {
1084 ah = hgt - th - 2*s;
1085 }
1086 else
1087 {
1088 /* this rarely gets triggered, but when it does it seems to
1089 get triggered forever after */
1090 int n = control->composite.num_children;
1091 ah = control->tabs.tab_height;
1092 if (debug_tabs > 0)
1093 fprintf (stderr, "Kludging around %d != 1 rows,"
1094 " #children = %d, total height %d, using %d.\n",
1095 check_nrows, n, th, ah);
1096 }
918 1097
919 /* OK, make our decision. If requested size is >= max sibling 1098 /* OK, make our decision. If requested size is >= max sibling
920 * preferred size, AND requested size <= available size, then 1099 * preferred size, AND requested size <= available size, then
921 * we accept. Otherwise, we offer a compromise. 1100 * we accept. Otherwise, we offer a compromise.
922 */ 1101 */
923 1102
924 if( rw == aw && rh == ah ) 1103 if (rw == aw && rh == ah)
925 { 1104 {
926 /* Acceptable. If this wasn't a query, change *all* children 1105 /* Acceptable. If this wasn't a query, change *all* children
927 * to this size. 1106 * to this size.
928 */ 1107 */
929 if( req->request_mode & XtCWQueryOnly ) 1108 if (request->request_mode & XtCWQueryOnly)
930 return XtGeometryYes ; 1109 {
1110 control->tabs.needs_layout = False;
1111 return XtGeometryYes ;
1112 }
931 else 1113 else
932 { 1114 {
933 Widget *childP = tw->composite.children ; 1115 Widget *childP = control->composite.children;
934 int i,bw ; 1116 int i, bw;
935 w->core.border_width = req->border_width ; 1117 tab->core.border_width = request->border_width;
936 for(i=TabsNumChildren (tw); --i >= 0; ++childP) 1118 for (i = TabsNumChildren (control); --i >= 0; ++childP)
937 if( TabVisible(*childP) ) 1119 if (TabVisible (*childP))
938 { 1120 {
939 bw = (*childP)->core.border_width ; 1121 bw = (*childP)->core.border_width;
940 XtConfigureWidget(*childP, s,tw->tabs.tab_total+s, 1122 XtConfigureWidget (*childP, s, control->tabs.tab_total+s,
941 rw-2*bw, rh-2*bw, bw) ; 1123 rw-2*bw, rh-2*bw, bw);
942 } 1124 }
943 #ifdef COMMENT 1125 #ifdef COMMENT
944 /* TODO: under what conditions will we need to redraw? */ 1126 /* TODO: under what conditions will we need to redraw? */
945 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ; 1127 XClearWindow (XtDisplay ((Widget) control),
946 XtClass(tw)->core_class.expose((Widget)tw,NULL,NULL) ; 1128 XtWindow ((Widget) control));
1129 XtClass (control)->core_class.expose ((Widget)control,
1130 NULL, NULL);
947 #endif /* COMMENT */ 1131 #endif /* COMMENT */
948 return XtGeometryDone ; 1132 return XtGeometryDone;
949 } 1133 }
950 } 1134 }
951 1135
952 /* Cannot grant child's request. Describe what we *can* do 1136 /* Cannot grant child's request. Describe what we *can* do
953 * and return counter-offer. 1137 * and return counter-offer.
954 */ 1138 */
955 reply->width = aw - 2 * req->border_width ; 1139 control->tabs.needs_layout = False;
956 reply->height = ah - 2 * req->border_width ; 1140 reply->width = aw - 2 * request->border_width ;
957 reply->border_width = req->border_width ; 1141 reply->height = ah - 2 * request->border_width ;
958 reply->request_mode = CWWidth | CWHeight | CWBorderWidth ; 1142 reply->request_mode &=
1143 ~((reply->border_width == tab->core.border_width
1144 ? CWBorderWidth : 0)
1145 |(reply->width == tab->core.width ? CWWidth : 0)
1146 |(reply->height == tab->core.height ? CWHeight : 0));
959 return XtGeometryAlmost ; 1147 return XtGeometryAlmost ;
960 } 1148 }
961 1149
962 return XtGeometryYes ; 1150 return XtGeometryYes ;
963 } 1151 }
1426 DrawTab(TabsWidget tw, Widget child, Bool labels) 1614 DrawTab(TabsWidget tw, Widget child, Bool labels)
1427 { 1615 {
1428 GC gc ; 1616 GC gc ;
1429 int x,y ; 1617 int x,y ;
1430 1618
1619 if (debug_tabs > 1) fprintf (stderr, "DrawTab called.\n");
1620
1431 if( !XtIsRealized((Widget)tw)) 1621 if( !XtIsRealized((Widget)tw))
1432 return ; 1622 return ;
1433 1623
1434 DrawBorder(tw, child, False) ; 1624 DrawBorder(tw, child, False) ;
1435 1625
1438 TabsConstraints tab = (TabsConstraints)child->core.constraints; 1628 TabsConstraints tab = (TabsConstraints)child->core.constraints;
1439 Display *dpy = XtDisplay((Widget)tw) ; 1629 Display *dpy = XtDisplay((Widget)tw) ;
1440 Window win = XtWindow((Widget)tw) ; 1630 Window win = XtWindow((Widget)tw) ;
1441 String lbl = tab->tabs.label != NULL ? 1631 String lbl = tab->tabs.label != NULL ?
1442 tab->tabs.label : XtName(child) ; 1632 tab->tabs.label : XtName(child) ;
1443 1633 #ifdef USE_XFT_TABS
1444 if( XtIsSensitive(child) ) 1634 XftColor color;
1635 XftColor colorBG;
1636 Colormap cmap = tw->core.colormap;
1637 Visual *visual;
1638 int ignored;
1639
1640 visual_info_from_widget ((Widget) tw, &visual, &ignored);
1641 colorBG = xft_convert_color (dpy, cmap, visual,
1642 tw->core.background_pixel, 0);
1643 #endif
1644
1645 if (debug_tabs > 2)
1646 fprintf (stderr, "(Re)drawing labels.\n");
1647
1648 if (XtIsSensitive(child))
1445 { 1649 {
1446 gc = tw->tabs.foregroundGC ; 1650 gc = tw->tabs.foregroundGC;
1447 XSetForeground(dpy, gc, tab->tabs.foreground) ; 1651 #ifdef USE_XFT_TABS
1652 color = xft_convert_color (dpy, cmap, visual,
1653 tab->tabs.foreground, 0);
1654 #else
1655 XSetForeground(dpy, gc, tab->tabs.foreground);
1656 #endif
1448 } 1657 }
1449 else 1658 else
1450 { 1659 {
1451 /* grey pixel allocation deferred until now */ 1660 /* grey pixel allocation deferred until now */
1452 if( !tab->tabs.greyAlloc ) 1661 if (!tab->tabs.greyAlloc)
1453 { 1662 {
1454 if( tw->tabs.be_nice_to_cmap || tw->core.depth == 1 ) 1663 if (tw->tabs.be_nice_to_cmap || tw->core.depth == 1)
1455 tab->tabs.grey = tab->tabs.foreground ; 1664 tab->tabs.grey = tab->tabs.foreground;
1456 else 1665 else
1457 tab->tabs.grey = AllocGreyPixel((Widget)tw, 1666 tab->tabs.grey = AllocGreyPixel ((Widget) tw,
1458 tab->tabs.foreground, 1667 tab->tabs.foreground,
1459 tw->core.background_pixel, 1668 tw->core.background_pixel,
1460 tw->tabs.insensitive_contrast ) ; 1669 tw->tabs.insensitive_contrast);
1461 tab->tabs.greyAlloc = True ; 1670 tab->tabs.greyAlloc = True;
1462 } 1671 }
1463 gc = tw->tabs.greyGC ; 1672 gc = tw->tabs.greyGC;
1464 XSetForeground(dpy, gc, tab->tabs.grey) ; 1673 #ifdef USE_XFT_TABS
1674 color = xft_convert_color (dpy, cmap, visual, tab->tabs.grey, 0);
1675 #else
1676 XSetForeground(dpy, gc, tab->tabs.grey);
1677 #endif
1465 } 1678 }
1466 1679
1467 x = tab->tabs.x ; 1680 x = tab->tabs.x;
1468 y = tab->tabs.y ; 1681 y = tab->tabs.y;
1469 if( child == tw->tabs.topWidget ) 1682 if (child == tw->tabs.topWidget)
1470 y -= TABLDELTA ; 1683 y -= TABLDELTA;
1471 1684
1472 if( tab->tabs.left_bitmap != None && tab->tabs.lbm_width > 0 ) 1685 if (tab->tabs.left_bitmap != None && tab->tabs.lbm_width > 0)
1473 { 1686 {
1474 if( tab->tabs.lbm_depth == 1 ) 1687 if (tab->tabs.lbm_depth == 1)
1475 XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc, 1688 XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc,
1476 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height, 1689 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
1477 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L) ; 1690 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L);
1478 else 1691 else
1479 XCopyArea(dpy, tab->tabs.left_bitmap, win,gc, 1692 XCopyArea(dpy, tab->tabs.left_bitmap, win,gc,
1480 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height, 1693 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
1481 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y) ; 1694 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y);
1482 } 1695 }
1483 1696
1484 if( lbl != NULL && tw->tabs.font != NULL ) 1697 if (lbl != NULL &&
1485 XDrawString(dpy,win,gc, 1698 #ifdef USE_XFT_TABS
1486 x+tab->tabs.l_x, y+tab->tabs.l_y, 1699 tw->tabs.renderFont != NULL
1487 lbl, (int)strlen(lbl)) ; 1700 #else
1488 } 1701 tw->tabs.font != NULL
1489 1702 #endif
1490 if( child == tw->tabs.hilight ) 1703 )
1491 DrawHighlight(tw, child, False) ; 1704 {
1705 #ifdef USE_XFT_TABS
1706 XftDraw *xftDraw = XftDrawCreate (dpy, win, visual, cmap);
1707 XftFont *renderFont = tw->tabs.renderFont;
1708 XGlyphInfo glyphinfo;
1709 XftColor colorDBG;
1710 XftColorAllocName (dpy, visual, cmap, "wheat", &colorDBG);
1711 XftTextExtents8 (dpy, renderFont, lbl, (int) strlen (lbl),
1712 &glyphinfo);
1713 /* #### unnecessary? for the moment, give visual extent */
1714 /* draw background rect */
1715 #if 1
1716 if (debug_tabs > 2)
1717 {
1718 fprintf (stderr, "background color: pixel=%08lx, r=%04x,"
1719 " g=%04x, b=%04x, alpha=%04x.\n",
1720 colorDBG.pixel, colorDBG.color.red,
1721 colorDBG.color.green, colorDBG.color.blue,
1722 colorDBG.color.alpha);
1723 fprintf (stderr, "label geometry: x=%d, y=%d, xOff=%d,"
1724 " yOff=%d, width=%d, height=%d\n",
1725 glyphinfo.x, glyphinfo.y, glyphinfo.xOff,
1726 glyphinfo.yOff, glyphinfo.width, glyphinfo.height);
1727 }
1728 XftDrawRect (xftDraw, &colorDBG,
1729 /* left, top, width, height */
1730 x+tab->tabs.l_x-glyphinfo.x,
1731 y+tab->tabs.l_y-glyphinfo.y,
1732 glyphinfo.width, glyphinfo.height);
1733 #endif
1734 /* draw text */
1735 if (debug_tabs > 2)
1736 {
1737 FcValue name;
1738 FcValue size;
1739 FcPatternGet (renderFont->pattern, FC_FAMILY, 0, &name);
1740 FcPatternGet (renderFont->pattern, FC_SIZE, 0, &size);
1741 fprintf (stderr, "label: %s.\n", lbl);
1742 fprintf (stderr, "foreground color: pixel=%08lx, r=%04x,"
1743 " g=%04x, b=%04x, alpha=%04x.\n",
1744 color.pixel, color.color.red, color.color.green,
1745 color.color.blue, color.color.alpha);
1746 fprintf (stderr, "extent: x=%d, y=%d, xOffset=%d,"
1747 " yOffset=%d, height=%d, width=%d.\n",
1748 glyphinfo.x, glyphinfo.y, glyphinfo.xOff,
1749 glyphinfo.yOff, glyphinfo.height, glyphinfo.width);
1750 fprintf (stderr, "font: name=%s-%.1f,"
1751 " height=%d, ascent=%d, descent=%d.\n",
1752 name.u.s, size.u.d, renderFont->height,
1753 renderFont->ascent, renderFont->descent);
1754 }
1755 XftDrawString8 (xftDraw, &color, renderFont,
1756 x+tab->tabs.l_x, y+tab->tabs.l_y,
1757 lbl, (int) strlen (lbl));
1758 XftDrawDestroy (xftDraw);
1759 #else
1760 XDrawString(dpy,win,gc,
1761 x+tab->tabs.l_x, y+tab->tabs.l_y,
1762 lbl, (int)strlen(lbl));
1763 #endif
1764 }
1765 }
1766
1767 if (child == tw->tabs.hilight)
1768 DrawHighlight(tw, child, False);
1492 } 1769 }
1493 1770
1494 1771
1495 /* draw frame all the way around the child windows. */ 1772 /* draw frame all the way around the child windows. */
1496 1773
1687 TabWidth(Widget w) 1964 TabWidth(Widget w)
1688 { 1965 {
1689 TabsConstraints tab = (TabsConstraints) w->core.constraints ; 1966 TabsConstraints tab = (TabsConstraints) w->core.constraints ;
1690 TabsWidget tw = (TabsWidget)XtParent(w) ; 1967 TabsWidget tw = (TabsWidget)XtParent(w) ;
1691 String lbl = tab->tabs.label != NULL ? 1968 String lbl = tab->tabs.label != NULL ?
1692 tab->tabs.label : XtName(w) ; 1969 tab->tabs.label : XtName(w);
1693 XFontStruct *font = tw->tabs.font ; 1970 #ifdef USE_XFT_TABS
1694 int iw = tw->tabs.internalWidth ; 1971 XftFont *font = tw->tabs.renderFont;
1972 #else
1973 XFontStruct *font = tw->tabs.font;
1974 #endif
1975 int iw = tw->tabs.internalWidth;
1695 1976
1696 tab->tabs.width = iw + SHADWID*2 ; 1977 tab->tabs.width = iw + SHADWID*2 ;
1697 tab->tabs.l_x = tab->tabs.lbm_x = SHADWID + iw ; 1978 tab->tabs.l_x = tab->tabs.lbm_x = SHADWID + iw ;
1698 1979
1699 if( tab->tabs.left_bitmap != None ) 1980 if( tab->tabs.left_bitmap != None )
1703 tab->tabs.lbm_y = (tw->tabs.tab_height - tab->tabs.lbm_height)/2 ; 1984 tab->tabs.lbm_y = (tw->tabs.tab_height - tab->tabs.lbm_height)/2 ;
1704 } 1985 }
1705 1986
1706 if( lbl != NULL && font != NULL ) 1987 if( lbl != NULL && font != NULL )
1707 { 1988 {
1708 tab->tabs.width += XTextWidth( font, lbl, (int)strlen(lbl) ) + iw ; 1989 #ifdef USE_XFT_TABS
1990 tab->tabs.width += x_xft_text_width (XtDisplay(tw), font,
1991 lbl, (int)strlen(lbl)) + iw;
1992 tab->tabs.l_y = (tw->tabs.tab_height
1993 + tw->tabs.renderFont->ascent
1994 /* #### how can this subtraction be correct? */
1995 - tw->tabs.renderFont->descent)/2;
1996 if (debug_tabs > 2)
1997 fprintf (stderr, "tab: height=%d, width=%d, baseline=%d.\n",
1998 tw->tabs.tab_height, tab->tabs.width, tab->tabs.l_y);
1999 if (debug_tabs > 1)
2000 fprintf (stderr, "font: height=%d, ascent=%d, descent=%d.\n",
2001 tw->tabs.renderFont->height,
2002 tw->tabs.renderFont->ascent,
2003 tw->tabs.renderFont->descent);
2004 #else
2005 tab->tabs.width += XTextWidth (font, lbl, (int)strlen(lbl)) + iw;
1709 tab->tabs.l_y = (tw->tabs.tab_height + 2006 tab->tabs.l_y = (tw->tabs.tab_height +
1710 tw->tabs.font->max_bounds.ascent - 2007 tw->tabs.font->max_bounds.ascent -
1711 tw->tabs.font->max_bounds.descent)/2 ; 2008 tw->tabs.font->max_bounds.descent)/2;
2009 #endif
1712 } 2010 }
1713 } 2011 }
1714 2012
1715 2013
1716 2014
1721 * 2019 *
1722 * Tabs are indented from the edges by INDENT. 2020 * Tabs are indented from the edges by INDENT.
1723 * 2021 *
1724 * TODO: if they require more than two rows and the total height:width 2022 * TODO: if they require more than two rows and the total height:width
1725 * ratio is more than 2:1, then try something else. 2023 * ratio is more than 2:1, then try something else.
2024 * Gaak! This is actually already done in PreferredSize()!
2025 *
2026 * TODO SOONER: for reasons unclear, some applications (specifically
2027 * XEmacs) give a nominal geometry (in the core record) which doesn't
2028 * make much sense (eg, may be smaller than some of the tab children).
2029 * This results in bizarre values for DISPLAY_ROWS and REPLY_HEIGHT.
2030 * Specify a way to say "tell me what you really want" (eg, with WID
2031 * and/or HGT == 0 or == Dimension_MAX), and use it where appropriate.
2032 * LATE-BREAKING LOSE: This happens in PreferredSize(), not XEmacs!
2033 *
2034 * TODO EVEN SOONER: some applications lay out the tab control by
2035 * repeatedly querying until a fixed width and height has been filled
2036 * by the tabs (XEmacs). There should be an API to cache this?
1726 */ 2037 */
1727 2038
1728 static int 2039 static int
1729 TabLayout(TabsWidget tw, 2040 TabLayout(TabsWidget tw,
1730 Dimension wid, 2041 Dimension wid, /* if 0, use core.width as guess */
1731 Dimension hgt, 2042 Dimension hgt, /* if 0, use core.height as guess */
1732 Dimension *reply_height, Bool query_only) 2043 Dimension *reply_height, Bool query_only)
1733 { 2044 {
1734 int i, row, done = 0, display_rows = 0 ; 2045 int i, row, done = 0, display_rows = 0 ;
1735 int num_children = tw->composite.num_children ; 2046 int num_children = tw->composite.num_children ;
1736 Widget *childP ; 2047 Widget *childP ;
1737 Dimension w ; 2048 Dimension w ;
1738 Position x,y ; 2049 Position x,y ; /* #### gaak, these are dimensions! */
1739 TabsConstraints tab ; 2050 TabsConstraints tab ;
1740 2051
1741 /* Algorithm: loop through children, assign X positions. If a tab 2052 /* Algorithm: loop through children, assign X positions. If a tab
1742 * would extend beyond the right edge, start a new row. After all 2053 * would extend beyond the right edge, start a new row. After all
1743 * rows are assigned, make a second pass and assign Y positions. 2054 * rows are assigned, make a second pass and assign Y positions.
1748 /* Loop through the tabs and see how much space they need. */ 2059 /* Loop through the tabs and see how much space they need. */
1749 2060
1750 row = 0 ; 2061 row = 0 ;
1751 x = INDENT ; 2062 x = INDENT ;
1752 y = 0 ; 2063 y = 0 ;
1753 wid -= INDENT ; 2064 /* If wid or hgt is 0, we want to guess our own dimensions.
2065 Currently the guessing functions are broken....
2066 #### When PreferredSize*() get fixed, fix this too. */
2067 if (debug_tabs > 0)
2068 fprintf (stderr, "arg=%d,", wid);
2069 wid = (wid ? wid : tw->core.width) - INDENT ;
2070 hgt = hgt ? hgt : tw->core.height;
2071 if (debug_tabs > 0)
2072 fprintf (stderr, "wid=%d: x,w,y=", wid);
1754 for(i=num_children, childP=tw->composite.children; --i >= 0; ++childP) 2073 for(i=num_children, childP=tw->composite.children; --i >= 0; ++childP)
1755 if( XtIsManaged(*childP) ) 2074 if( XtIsManaged(*childP) )
1756 { 2075 {
1757 tab = (TabsConstraints) (*childP)->core.constraints ; 2076 tab = (TabsConstraints) (*childP)->core.constraints ;
1758 w = tab->tabs.width ; 2077 w = tab->tabs.width ;
1759 2078
2079 if (debug_tabs > 0)
2080 fprintf (stderr, "%d,%d,%d;", x, w, y);
1760 if( x + w > wid ) { /* new row */ 2081 if( x + w > wid ) { /* new row */
1761 if (y + tw->tabs.tab_height > hgt && !done) 2082 /* #### algorithm is not robust to wid < child's width */
2083 ++row;
2084 x = INDENT ;
2085 y += tw->tabs.tab_height ;
2086 if (y > hgt && !done)
1762 { 2087 {
1763 display_rows = row; 2088 display_rows = row;
1764 done = 1; 2089 done = 1;
1765 } 2090 }
1766 ++row;
1767 x = INDENT ;
1768 y += tw->tabs.tab_height ;
1769 } 2091 }
1770 if( !query_only ) { 2092 if( !query_only ) {
1771 tab->tabs.x = x ; 2093 tab->tabs.x = x ;
1772 tab->tabs.y = y ; 2094 tab->tabs.y = y ;
1773 tab->tabs.row = row ; 2095 tab->tabs.row = row ;
1775 x += w + SPACING ; 2097 x += w + SPACING ;
1776 if (!query_only && !done) 2098 if (!query_only && !done)
1777 tab->tabs.visible = 1; 2099 tab->tabs.visible = 1;
1778 2100
1779 } 2101 }
2102 if (debug_tabs > 0)
2103 fprintf (stderr, "\n");
1780 /* If there was only one row, increase the height by TABDELTA */ 2104 /* If there was only one row, increase the height by TABDELTA */
1781 if( ++display_rows == 1 ) 2105 if( ++display_rows == 1 )
1782 { 2106 {
1783 row++;
1784 y = TABDELTA ; 2107 y = TABDELTA ;
1785 if( !query_only ) 2108 if( !query_only )
1786 for(i=num_children, childP=tw->composite.children; 2109 for(i=num_children, childP=tw->composite.children;
1787 --i >= 0 ; ++childP) 2110 --i >= 0 ; ++childP)
1788 if( XtIsManaged(*childP) ) 2111 if( XtIsManaged(*childP) )
1789 { 2112 {
1790 tab = (TabsConstraints) (*childP)->core.constraints ; 2113 tab = (TabsConstraints) (*childP)->core.constraints ;
1791 tab->tabs.y = y ; 2114 tab->tabs.y = y ;
1792 } 2115 }
1793 } 2116 }
2117 row++;
1794 y += tw->tabs.tab_height ; 2118 y += tw->tabs.tab_height ;
1795 } 2119 }
1796 else 2120 else
1797 display_rows = row = y = 0 ; 2121 display_rows = row = y = 0 ;
1798 2122
1800 tw->tabs.tab_total = y ; 2124 tw->tabs.tab_total = y ;
1801 tw->tabs.numRows = display_rows ; 2125 tw->tabs.numRows = display_rows ;
1802 tw->tabs.realRows = row; 2126 tw->tabs.realRows = row;
1803 } 2127 }
1804 2128
2129 if (debug_tabs > 0 && (row > 1 || display_rows > 1))
2130 fprintf (stderr, "tab: %d display rows, #children = %d,"
2131 " total height %d, total rows %d%s.\n",
2132 display_rows, num_children, y, row,
2133 query_only ? " (query)" : "");
2134
1805 if( reply_height != NULL ) 2135 if( reply_height != NULL )
1806 *reply_height = y ; 2136 *reply_height = y ;
1807 2137
1808 return display_rows ; 2138 return display_rows ;
1809 } 2139 }
1820 MaxChild(tw, NULL, 0,0) ; 2150 MaxChild(tw, NULL, 0,0) ;
1821 } 2151 }
1822 2152
1823 2153
1824 2154
1825 /* Find max preferred child size. Returned sizes include child 2155 /* Find max preferred child size and store in control widget.
1826 * border widths. If except is non-null, don't ask that one. 2156 * If except is non-null, don't ask that one.
1827 */ 2157 */
1828 2158
1829 static void 2159 static void
1830 MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch) 2160 MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch)
1831 { 2161 {
2007 { 2337 {
2008 Dimension th ; /* space used by tabs */ 2338 Dimension th ; /* space used by tabs */
2009 int nrows ; 2339 int nrows ;
2010 2340
2011 if( tw->composite.num_children > 0 ) 2341 if( tw->composite.num_children > 0 )
2012 nrows = TabLayout(tw, wid, hgt, &th, True) ; 2342 /* used to be wid, hgt not 0, 0 but that's obviously wrong
2343 since TabLayout wants dimensions of control parent but
2344 wid, hgt are dimensions of some child */
2345 nrows = TabLayout(tw, 0, 0, &th, True) ;
2013 else { 2346 else {
2014 th = 0 ; 2347 th = 0 ;
2015 nrows = 0 ; 2348 nrows = 0 ;
2016 } 2349 }
2017 2350
2089 TabsAllocFgGC(TabsWidget tw) 2422 TabsAllocFgGC(TabsWidget tw)
2090 { 2423 {
2091 Widget w = (Widget) tw; 2424 Widget w = (Widget) tw;
2092 XGCValues values ; 2425 XGCValues values ;
2093 2426
2094 values.background = tw->core.background_pixel ; 2427 values.background = tw->core.background_pixel;
2095 values.font = tw->tabs.font->fid ; 2428 values.font =
2096 values.line_style = LineOnOffDash ; 2429 #ifdef USE_XFT_TABS
2097 values.line_style = LineSolid ; 2430 None;
2431 #else
2432 tw->tabs.font->fid;
2433 #endif
2434 values.line_style = LineOnOffDash;
2435 values.line_style = LineSolid;
2098 2436
2099 tw->tabs.foregroundGC = 2437 tw->tabs.foregroundGC =
2100 XtAllocateGC(w, w->core.depth, 2438 XtAllocateGC(w, w->core.depth,
2101 GCBackground|GCFont|GCLineStyle, &values, 2439 #ifndef USE_XFT_TABS
2102 GCForeground, 2440 GCFont|
2103 GCSubwindowMode|GCGraphicsExposures|GCDashOffset| 2441 #endif
2104 GCDashList|GCArcMode) ; 2442 GCBackground|GCLineStyle,
2443 &values,
2444 GCForeground,
2445 #ifdef USE_XFT_TABS
2446 GCFont|
2447 #endif
2448 GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
2449 GCDashList|GCArcMode);
2105 } 2450 }
2106 2451
2107 static void 2452 static void
2108 TabsAllocGreyGC(TabsWidget tw) 2453 TabsAllocGreyGC(TabsWidget tw)
2109 { 2454 {
2110 Widget w = (Widget) tw; 2455 Widget w = (Widget) tw;
2111 XGCValues values ; 2456 XGCValues values ;
2112 2457
2113 values.background = tw->core.background_pixel ; 2458 values.background = tw->core.background_pixel;
2114 values.font = tw->tabs.font->fid ; 2459 values.font =
2460 #ifdef USE_XFT_TABS
2461 None;
2462 #else
2463 tw->tabs.font->fid;
2464 #endif
2115 #ifdef HAVE_XMU 2465 #ifdef HAVE_XMU
2116 if( tw->tabs.be_nice_to_cmap || w->core.depth == 1) 2466 if (tw->tabs.be_nice_to_cmap || w->core.depth == 1)
2117 { 2467 {
2118 values.fill_style = FillStippled ; 2468 values.fill_style = FillStippled;
2119 tw->tabs.grey50 = 2469 tw->tabs.grey50 =
2120 values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1) ; 2470 values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1);
2121 2471
2122 tw->tabs.greyGC = 2472 tw->tabs.greyGC =
2123 XtAllocateGC(w, w->core.depth, 2473 XtAllocateGC(w, w->core.depth,
2124 GCBackground|GCFont|GCStipple|GCFillStyle, &values, 2474 #ifndef USE_XFT_TABS
2475 GCFont|
2476 #endif
2477 GCBackground|GCStipple|GCFillStyle, &values,
2125 GCForeground, 2478 GCForeground,
2479 #ifdef USE_XFT_TABS
2480 GCFont|
2481 #endif
2126 GCSubwindowMode|GCGraphicsExposures|GCDashOffset| 2482 GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
2127 GCDashList|GCArcMode) ; 2483 GCDashList|GCArcMode);
2128 } 2484 }
2129 else 2485 else
2130 #endif 2486 #endif
2131 { 2487 {
2132 tw->tabs.greyGC = 2488 tw->tabs.greyGC =
2133 XtAllocateGC(w, w->core.depth, 2489 XtAllocateGC(w, w->core.depth,
2134 GCFont, &values, 2490 #ifdef USE_XFT_TABS
2491 0L,
2492 #else
2493 GCFont,
2494 #endif
2495 &values,
2135 GCForeground, 2496 GCForeground,
2497 #ifdef USE_XFT_TABS
2498 GCFont|
2499 #endif
2136 GCBackground|GCSubwindowMode|GCGraphicsExposures|GCDashOffset| 2500 GCBackground|GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
2137 GCDashList|GCArcMode) ; 2501 GCDashList|GCArcMode);
2138 } 2502 }
2139 } 2503 }