diff lwlib/xlwgcs.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents
children abe6d1db359e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwlib/xlwgcs.c	Mon Aug 13 11:13:30 2007 +0200
@@ -0,0 +1,545 @@
+ /* Tabs Widget for XEmacs.
+    Copyright (C) 1999 Edward A. Falk
+  
+ This file is part of XEmacs.
+ 
+ XEmacs is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+ 
+ XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with XEmacs; see the file COPYING.  If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+ 
+/* Synched up with: Gcs.c 1.7 */
+ 
+ /* #### This code is duplicated many times within lwlib and XEmacs. It
+    should be modularised. */
+
+/*
+ * Gcs.c - Utility functions to allocate GCs.
+ *
+ * Author: Edward A. Falk
+ *	   falk@falconer.vip.best.com
+ *
+ * Date: Sept 29, 1998
+ */
+
+/* Functions:
+ *
+ * GC AllocFgGC(w, fg, font)
+ *	Return a GC with foreground set as specified.
+ *	If font is None, then the returned GC is allocated with font specified
+ *	as a "don't care" value.
+ *
+ * GC
+ * AllocBackgroundGC(w, font)
+ *	Return a GC with the foreground set to the widget's background color.
+ *
+ * GC
+ * AllocGreyGC(w, fg, font, contrast, be_nice_to_cmap)
+ *	Widget	w ;
+ *	Pixel	fg ;
+ *	Font	font ;
+ *	int	contrast ;
+ *	int	be_nice_to_cmap ;
+ *
+ *	Return a GC suitable for rendering a widget in its "inactive" color.
+ *	Normally returns a GC with a color somewhere between the widget's
+ *	background color and the specified foreground. If font is None, then
+ *	the returned GC is allocated with font specified as "don't care".
+ *	If be_nice_to_cmap is True, the returned GC is created using a 50%
+ *	dither instead of a new color.
+ *
+ *
+ * GC
+ * AllocShadeGC(w, fg, bg, font, contrast, be_nice_to_cmap)
+ *	Widget	w ;
+ *	Pixel	fg, bg ;
+ *	Font	font ;
+ *	int	contrast ;
+ *	int	be_nice_to_cmap ;
+ *
+ *	Return a GC suitable for rendering in a shade somewhere between
+ *	bg and fg, as determined by contrast (0 = bg, 100 = fg)
+ *	If font is None, then the returned GC is allocated with
+ *	font specified as "don't care".  If be_nice_to_cmap
+ *	is True, the returned GC is created using a 50% dither
+ *	instead of a new color.
+ *
+ *
+ * GC
+ * AllocTopShadowGC(w, contrast, be_nice_to_cmap)
+ *	Return a GC suitable for rendering the "top shadow" decorations of
+ *	a widget.  Returns a GC with foreground computed from widget's
+ *	background color and contrast.  If be_nice_to_cmap is True, the
+ *	returned GC will use a foreground color of white.  If widget depth
+ *	is 1, this function will use a foreground color of black.
+ *
+ * GC
+ * AllocBotShadowGC(w, contrast, be_nice_to_cmap)
+ *	Return a GC suitable for rendering the "bottom shadow" decorations
+ *	of a widget. Returns a GC with foreground computed from widget's
+ *	background color and contrast. If be_nice_to_cmap is True, the
+ *	returned GC will use a foreground color of black.
+ *
+ * GC
+ * AllocArmGC(w, contrast, be_nice_to_cmap)
+ *	Return a GC suitable for rendering the "armed" decorations of a
+ *	widget. This GC would typically be used to fill in the widget's
+ *	background. Returns a GC with foreground computed from widget's
+ *	background color and contrast.  If be_nice_to_cmap is True, the
+ *	returned GC will use a foreground color of black and a 50% dither.
+ *
+ *
+ * void
+ * Draw3dBox(w, x,y,wid,hgt,s, topgc, botgc)
+ *	Utility function.  Draws a raised shadow box with outside dimensions
+ *	as specified by x,y,wid,hgt and shadow width specified by s.
+ *	A lowered shadow box may be generated by swapping topgc and botgc.
+ *
+ */
+
+#include	<config.h>
+#include	<stdio.h>
+
+#include	<X11/Xlib.h>
+#include	<X11/IntrinsicP.h>
+#include	<X11/StringDefs.h>
+#include	"../src/xmu.h"
+#include	"xlwgcs.h"
+
+	/* Color & GC allocation.
+	 *
+	 * Frame widgets use the following graphics contexts:
+	 *
+	 *  Foreground		tab label text drawn this way
+	 *  Insensitive Fg	foreground color greyed out.
+	 *  Background		frame background color
+	 *  Top shadow		upper-left highlight around widget
+	 *  Bottom shadow	lower-right highlight around widget
+	 *  Arm shadow		button pressed and ready to be released
+	 *
+	 *
+	 * GC's are defined as follows, depending on attributes and
+	 * window depth:
+	 *
+	 * Monochrome:
+	 *	Foreground = foreground color attribute or BlackPixel()
+	 *	Grey = Foreground color + 50% dither
+	 *	Background = background color attribute or WhitePixel()
+	 *	top shadow = foreground
+	 *	bottom shadow = foreground
+	 *	arm shadow = (what?)
+	 *
+	 * Color, beNiceToColormap=true:
+	 *	Foreground = foreground color attribute or BlackPixel()
+	 *	Grey = Foreground color + 50% dither
+	 *	Background = background color attribute or WhitePixel()
+	 *	top shadow = white
+	 *	bottom shadow = black
+	 *	arm shadow = (what?)
+	 *
+	 * Color, beNiceToColormap=false:
+	 *	Foreground = foreground color attribute or BlackPixel()
+	 *	Grey = (foreground color + background color)/2
+	 *	Background = background color attribute or WhitePixel()
+	 *	top shadow = background * 1.2
+	 *	bottom shadow = background * .6
+	 *	arm shadow = background * .8
+	 *
+	 * Special cases:
+	 *	If background is white,   ??
+	 *	if background is black,   ??
+	 *
+	 *
+	 * If the widget's background is solid white or solid black,
+	 * this code just picks some numbers.  (The choice is designed
+	 * to be compatibile with ThreeD interface.)
+	 */
+
+
+
+#if	XtSpecificationRelease	< 5
+
+static	GC	XtAllocateGC(Widget, int, u_long, XGCValues *, u_long, u_long) ;
+
+#endif
+
+
+#if	NeedFunctionPrototypes
+static	Pixmap	getDitherPixmap(Widget, int contrast) ;
+#else
+static	Pixmap	getDitherPixmap() ;
+#endif
+
+	/* return a GC with the specified foreground and optional font */
+
+GC
+AllocFgGC(Widget w, Pixel fg, Font font)
+{
+	XGCValues	values ;
+	u_long		vmask, dcmask ;
+
+	values.foreground = fg ;
+	values.font = font ;
+
+	if( font != None ) {
+	  vmask = GCForeground|GCFont ;
+	  dcmask = GCSubwindowMode|GCDashOffset|
+		GCDashList|GCArcMode|GCBackground|GCGraphicsExposures ;
+	} else {
+	  vmask = GCForeground ;
+	  dcmask = GCFont|GCSubwindowMode|GCDashOffset|
+		GCDashList|GCArcMode|GCBackground|GCGraphicsExposures ;
+	}
+
+	return XtAllocateGC(w, w->core.depth, vmask, &values, 0L, dcmask) ;
+}
+
+
+	/* return gc with widget background color as the foreground */
+
+GC
+AllocBackgroundGC(Widget w, Font font)
+{
+	return AllocFgGC(w, w->core.background_pixel, font) ;
+}
+
+
+	/* Allocate an "inactive" GC.  Color is grey (possibly via
+	 * dither pattern).
+	 */
+
+GC
+AllocGreyGC(Widget w, Pixel fg, Font font, int contrast, Bool be_nice_to_cmap)
+{
+	return AllocShadeGC(w, fg, w->core.background_pixel,
+		font, contrast, be_nice_to_cmap) ;
+}
+
+
+	/* Allocate a GC somewhere between two colors.  */
+
+GC
+AllocShadeGC(Widget w, Pixel fg, Pixel bg, Font font,
+	int contrast, Bool be_nice_to_cmap)
+{
+	XGCValues	values ;
+	u_long		vmask, dcmask ;
+
+	values.foreground = fg ;
+	values.background = bg ;
+	values.font = font ;
+
+	if( font != None ) {
+	  vmask = GCForeground|GCFont ;
+	  dcmask = GCSubwindowMode|GCDashOffset|
+		GCDashList|GCArcMode|GCGraphicsExposures ;
+	} else {
+	  vmask = GCForeground;
+	  dcmask = GCFont|GCSubwindowMode|GCDashOffset|
+		GCDashList|GCArcMode|GCGraphicsExposures ;
+	}
+#ifdef HAVE_XMU
+	if( be_nice_to_cmap || w->core.depth == 1)
+	{
+	  if( contrast <= 5 )
+	    values.foreground = bg ;
+	  else if( contrast >= 95 )
+	    values.foreground = fg ;
+	  else {
+	    vmask |= GCBackground|GCStipple|GCFillStyle ;
+	    values.fill_style = FillOpaqueStippled ;
+	    values.stipple = getDitherPixmap(w, contrast) ;
+	  }
+
+	  return XtAllocateGC(w, w->core.depth, vmask, &values, 0L, dcmask) ;
+	}
+	else
+#endif
+	{
+	  dcmask |= GCBackground ;
+	  values.foreground = AllocGreyPixel(w, fg, bg, contrast) ;
+	  return XtAllocateGC(w, w->core.depth, vmask, &values, 0L, dcmask) ;
+	}
+}
+
+	/* return top-shadow gc. */
+
+GC
+AllocTopShadowGC(Widget w, int contrast, Bool be_nice_to_cmap)
+{
+	Screen		*scr = XtScreen (w);
+	XGCValues	values ;
+
+	if( w->core.depth == 1 )
+	  values.foreground = BlackPixelOfScreen(scr) ;
+	else if( be_nice_to_cmap )
+	  values.foreground = WhitePixelOfScreen(scr) ;
+	else
+	  values.foreground = AllocShadowPixel(w, 100+contrast) ;
+
+	return XtAllocateGC(w, w->core.depth,
+	    GCForeground, &values,
+	    0L,
+	    GCBackground|GCFont|GCSubwindowMode|GCGraphicsExposures|
+		GCDashOffset|GCDashList|GCArcMode) ;
+}
+
+	/* return bottom-shadow gc. */
+
+GC
+AllocBotShadowGC(Widget w, int contrast, Bool be_nice_to_cmap)
+{
+	Screen		*scr = XtScreen (w);
+	XGCValues	values ;
+
+	if( w->core.depth == 1 || be_nice_to_cmap )
+	  values.foreground = BlackPixelOfScreen(scr) ;
+	else
+	  values.foreground = AllocShadowPixel(w, 100-contrast) ;
+
+	return XtAllocateGC(w, w->core.depth,
+	    GCForeground, &values,
+	    0L,
+	    GCBackground|GCFont|GCSubwindowMode|GCGraphicsExposures|
+		GCDashOffset|GCDashList|GCArcMode) ;
+}
+
+	/* return arm-shadow gc. */
+
+GC
+AllocArmGC(Widget w, int contrast, Bool be_nice_to_cmap)
+{
+	Screen		*scr = XtScreen (w);
+	XGCValues	values ;
+
+	/* Not clear exactly what we should do here.  Take a look at
+	 * Xaw3d to see what they do.
+	 */
+#ifdef HAVE_XMU
+	if( w->core.depth == 1 || be_nice_to_cmap )
+	{
+	  values.background = w->core.background_pixel ;
+	  if( values.background == BlackPixelOfScreen(scr) )
+	    values.foreground = WhitePixelOfScreen(scr) ;
+	  else
+	    values.foreground = BlackPixelOfScreen(scr) ;
+	  values.fill_style = FillStippled ;
+	  values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1) ;
+
+	  return XtAllocateGC(w, w->core.depth,
+	      GCForeground|GCBackground|GCStipple|GCFillStyle,
+	      &values, 0L,
+	      GCFont|GCSubwindowMode|GCGraphicsExposures|
+		  GCDashOffset|GCDashList|GCArcMode) ;
+	}
+	else 
+#endif
+	  {
+	  values.foreground = AllocShadowPixel(w, 100-contrast) ;
+	  return XtAllocateGC(w, w->core.depth,
+	      GCForeground, &values,
+	      0L,
+	      GCBackground|GCFont|GCSubwindowMode|GCGraphicsExposures|
+		  GCDashOffset|GCDashList|GCArcMode) ;
+	}
+}
+
+
+Pixel
+AllocShadowPixel(Widget w, int scale)
+{
+	XColor	get_c, set_c ;
+	Display	*dpy = XtDisplay(w) ;
+	Screen	*scr = XtScreen(w) ;
+	Colormap cmap ;
+	Pixel	maxColor ;
+
+	cmap = w->core.colormap ;
+
+	get_c.pixel = w->core.background_pixel ;
+	if( get_c.pixel == WhitePixelOfScreen(scr)  ||
+	    get_c.pixel == BlackPixelOfScreen(scr) )
+	{
+	  /* what we *ought* to do is choose gray75 as the base color,
+	   * or perhaps gray83.  Instead, we choose colors that are
+	   * the same as ThreeD would choose.
+	   */
+	  if( scale > 100 )	scale = 200 - scale ;
+	  set_c.red = set_c.green = set_c.blue = 65535*scale/100 ;
+	}
+	else
+	{
+	  XQueryColor(dpy, cmap, &get_c) ;
+	  /* adjust scale so that brightest component does not
+	   * exceed 65535; otherwise hue would change.
+	   */
+	  if( scale > 100 ) {
+	    maxColor = Max(get_c.red, Max(get_c.green, get_c.blue)) ;
+	    if( scale*maxColor > 65535*100 )
+	      scale = 65535*100/maxColor ;
+	  }
+	  set_c.red = scale * get_c.red / 100 ;
+	  set_c.green = scale * get_c.green / 100 ;
+	  set_c.blue = scale * get_c.blue / 100 ;
+	}
+	set_c.flags = DoRed | DoGreen | DoBlue ;
+	if( XAllocColor(dpy, cmap, &set_c) )
+	  return set_c.pixel ;
+	else if( scale > 100 )
+	  return WhitePixelOfScreen(scr) ;
+	else
+	  return BlackPixelOfScreen(scr) ;
+}
+
+
+	/* Allocate a pixel partway between foreground and background */
+
+
+Pixel
+AllocGreyPixel(Widget w, Pixel fg, Pixel bg, int scale)
+{
+  XColor	get_cf, get_cb ;
+  Display	*dpy = XtDisplay(w) ;
+  Colormap cmap ;
+
+  cmap = w->core.colormap ;
+
+  get_cf.pixel = fg ;
+  get_cb.pixel = bg ;
+
+  XQueryColor(dpy, cmap, &get_cf) ;
+  XQueryColor(dpy, cmap, &get_cb) ;
+
+  return AllocGreyPixelC(w, &get_cf, &get_cb, scale) ;
+}
+
+
+
+	/* Allocate a pixel partway between foreground and background */
+
+
+Pixel
+AllocGreyPixelC(Widget w, XColor *fg, XColor *bg, int scale)
+{
+  XColor	set_c ;
+  Display	*dpy = XtDisplay(w) ;
+  int		r,g,b ;
+  Colormap	cmap = w->core.colormap ;
+
+  r = (fg->red * scale +   bg->red * (100-scale)) / 100 ;
+  g = (fg->green * scale + bg->green * (100-scale)) / 100 ;
+  b = (fg->blue * scale +  bg->blue * (100-scale)) / 100 ;
+
+  if( scale > 100 || scale < 0 )	/* look out for overflow */
+  {
+    int minc, maxc ;
+    maxc = Max(r, Max(g,b)) ;
+    minc = Min(r, Min(g,b)) ;
+    if( maxc > 65535 )
+    {
+      maxc /= 16 ;
+      r = r*(65535/16) / maxc ;
+      g = g*(65535/16) / maxc ;
+      b = b*(65535/16) / maxc ;
+    }
+    if( minc < 0 )
+    {
+      r = Max(r,0) ;
+      g = Max(g,0) ;
+      b = Max(b,0) ;
+    }
+  }
+
+  set_c.red = r ; set_c.green = g ; set_c.blue = b ;
+  set_c.flags = DoRed | DoGreen | DoBlue ;
+  (void)XAllocColor(dpy, cmap, &set_c) ;
+  return set_c.pixel ;
+}
+
+
+
+
+
+	/* draw a 3-d box */
+
+void
+Draw3dBox(Widget w, int x, int y, int wid, int hgt, int s, GC topgc, GC botgc)
+{
+	Display		*dpy = XtDisplay(w) ;
+	Window		win = XtWindow(w) ;
+
+	if( s == 0 ) return ;
+
+	if( s == 1 ) {
+	  XDrawLine(dpy,win,botgc, x,y+hgt-1, x+wid-1,y+hgt-1) ;
+	  XDrawLine(dpy,win,botgc, x+wid-1,y, x+wid-1,y+hgt-1) ;
+	  XDrawLine(dpy,win,topgc, x,y, x,y+hgt-1) ;
+	  XDrawLine(dpy,win,topgc, x,y, x+wid-1,y) ;
+	}
+	else
+	{
+	  XPoint pts[6] ;
+
+	  /* bottom-right shadow */
+	  pts[0].x = x ;	pts[0].y = y + hgt ;
+	  pts[1].x = s ;	pts[1].y = -s ;
+	  pts[2].x = wid-2*s ;	pts[2].y = 0 ;
+	  pts[3].x = 0 ;	pts[3].y = -(hgt-2*s) ;
+	  pts[4].x = s ;	pts[4].y = -s ;
+	  pts[5].x = 0 ;	pts[5].y = hgt ;
+	  XFillPolygon(dpy,win,botgc, pts,6, Nonconvex,CoordModePrevious) ;
+
+	  /* top-left shadow */
+	  pts[0].x = x ;	pts[0].y = y ;
+	  pts[1].x = wid ;	pts[1].y = 0 ;
+	  pts[2].x = -s ;	pts[2].y = s ;
+	  pts[3].x = -wid+2*s ;	pts[3].y = 0 ;
+	  pts[4].x = 0 ;	pts[4].y = hgt-2*s ;
+	  pts[5].x = -s ;	pts[5].y = s ;
+	  XFillPolygon(dpy,win,topgc, pts,6, Nonconvex,CoordModePrevious) ;
+	}
+}
+
+#if XtSpecificationRelease < 5
+
+static	GC
+XtAllocateGC(Widget w, int depth, u_long mask, XGCValues *values,
+	u_long dynamic, du_long ontcare)
+{
+	return XtGetGC(w, mask, values) ;
+}
+#endif
+
+
+static	u_char	screen0[2] = {0,0} ;
+static	u_char	screen25[2] = {0,0xaa} ;
+static	u_char	screen75[2] = {0xaa,0xff} ;
+static	u_char	screen100[2] = {0xff,0xff} ;
+
+static	Pixmap
+getDitherPixmap(Widget w, int contrast)
+{
+	Display	*dpy = XtDisplay(w) ;
+	Window	win = XtWindow(w) ;
+
+	if( contrast <= 5 )
+	  return XCreateBitmapFromData(dpy,win, (char *)screen0, 2,2) ;
+	else if( contrast <= 37 )
+	  return XCreateBitmapFromData(dpy,win, (char *)screen25, 2,2) ;
+	else if( contrast <= 62 )
+	  return XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1) ;
+	else if( contrast <= 95 )
+	  return XCreateBitmapFromData(dpy,win, (char *)screen75, 2,2) ;
+	else
+	  return XCreateBitmapFromData(dpy,win, (char *)screen100, 2,2) ;
+}