v12i064: olvwm - Open Look Virtual Window Manager, Part08/16

Scott Oaks - Sun Consulting NYC sdo at soliado.East.Sun.COM
Mon Apr 29 03:29:51 AEST 1991


Submitted-by: sdo at soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC)
Posting-number: Volume 12, Issue 64
Archive-name: olvwm/part08

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 8 (of 16)."
# Contents:  resources1.c usermenu.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:06 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'resources1.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'resources1.c'\"
else
echo shar: Extracting \"'resources1.c'\" \(19186 characters\)
sed "s/^X//" >'resources1.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1990 Sun Microsystems, Inc. Sun design patents
X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
X *      file for terms of the license.
X *
X *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char     sccsid[] = "@(#)resources1.c	1.2 olvwm version 4/26/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) resources.c 25.34 90/06/05 Crucible";
X *
X */
X
X#include <ctype.h>
X#include <errno.h>
X#include <stdio.h>
X#include <string.h>
X#include <sys/file.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xresource.h>
X#include <X11/keysym.h>
X#include <X11/cursorfont.h>
X
X#include <olgx/olgx.h>
X
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "defaults.h"
X#include "globals.h"
X#include "resources.h"
X#include "olcursor.h"
X
extern  char            *AppName;
extern  Bool            ColorDisplay;
extern  List            *ActiveClientList;
X
extern  Graphics_info   *olgx_gisbutton;
extern  Graphics_info   *olgx_gistext;
extern  Graphics_info   *olgx_gisnormal;
extern  Graphics_info   *olgx_gisreverse;
extern  Graphics_info   *olgx_gisrevpin;
X
extern  GC              DrawNormalGC, DrawReverseGC;
extern  GC              DrawLinesGC, DrawRevLinesGC;
extern  GC              DrawBackgroundGC, DrawSelectedGC;
extern  GC              DrawBusyGC;
extern  GC              IconUnselectedGC, IconBorderGC;
extern  GC              IconNormalGC, IconSelectedGC;
X
extern Pixmap Gray50;
extern int Gray50width;
extern int Gray50height;
X
extern XrmDatabase             OlwmDB;
extern GlobalResourceVariables GRV;
X
extern Bool WorkspaceColorUsed;
extern unsigned long WorkspaceColorPixel;
X
X
X/*
X * 	Global routines
X */
X
X/*
X *	The Resource Update Functions
X */
X
X/*
X * setWorkspaceColor -- set the root window background.
X *	If isUpdate is true, then the background has already been set once
X *	(on startup), so XSetWindowBackground not done if default case.
X *
X * REMIND: this routine doesn't work properly for GrayScale visuals.
X *
X */
static void
setWorkspaceColor( dpy, colorname, isUpdate )
Display	*dpy;
char	*colorname;
Bool	isUpdate;
X{
X	XColor		color;
X	GC		gc;
X	XGCValues	gcv;
X	Pixmap		bitmap = 0;
X	Pixmap		pixmap;
X	unsigned int	width, height;
X	Bool		valid = False;
X	Bool		docolor = False;
X
X	if ( colorname != NULL )
X	{
X		/* Null string disables root setting */
X		if (*colorname == '\0')
X		    return;
X
X		if ( *colorname == '/' )
X		{
X			unsigned int x, y;
X
X			if ( BitmapSuccess == XReadBitmapFile( dpy,
X							DefaultRootWindow(dpy),
X							colorname,
X							&width, &height,
X							&bitmap, &x, &y ) )
X			valid = True;
X		}
X		else if ( (*colorname == '#') && ColorDisplay )
X		{
X			XParseColor( dpy,
X				     DefaultColormap(dpy,DefaultScreen(dpy)),
X				     colorname, &color );
X
X			if ( XAllocColor( dpy,
X					DefaultColormap(dpy,DefaultScreen(dpy)),
X					&color ) )
X				valid = docolor = True;
X		}
X		else if ( ColorDisplay )
X		{
X			/* It is a color name */
X			/*
X			 * NOTE:  this could possibly fail on a full
X			 * dynamic colormap. If it does, tough -- 
X			 * we''ll just set it to whatever junk
X			 * comes back for now. 
X			 * Presumably this won''t happen since
X			 * 'props' was able to display the color.
X			 */
X			if ( XAllocNamedColor(dpy,
X					DefaultColormap(dpy,DefaultScreen(dpy)),
X					colorname, &color, &color) )
X			valid = docolor = True;
X		}
X	}
X
X	/* the new color isn't usable, and we've set the background before */
X	if ( !valid && isUpdate )
X		return;
X
X	if ( !valid && ColorDisplay ) 
X	{
X		XParseColor( dpy, DefaultColormap(dpy,DefaultScreen(dpy)),
X			     DEFAULTCOLOR, &color );
X		if ( XAllocColor( dpy, DefaultColormap(dpy,DefaultScreen(dpy)),
X				  &color ) )
X		valid = docolor = True;
X	}
X
X	if ( !valid )
X	{
X		bitmap = Gray50;
X		width = Gray50width;
X		height = Gray50height;
X	}
X
X	if ( docolor ) 
X	{
X		WorkspaceColorUsed = True;
X		WorkspaceColorPixel = color.pixel;
X		XSetWindowBackground(dpy, DefaultRootWindow(dpy), color.pixel);
X		/*if (VirtualDesktop) {
X		    XSetWindowBackground(dpy, VirtualDesktop, color.pixel);
X		    XClearWindow(dpy, VirtualDesktop);
X		}*/
X	}
X	else
X	{
X		WorkspaceColorUsed = False;
X		gcv.foreground = BlackPixel(dpy,DefaultScreen(dpy));
X		gcv.background = WhitePixel(dpy,DefaultScreen(dpy));
X		gc = XCreateGC( dpy, DefaultRootWindow(dpy),
X				GCForeground|GCBackground, &gcv );
X		pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy),
X				       width, height,
X					(unsigned int)DefaultDepth(dpy,
X							DefaultScreen(dpy)));
X		XCopyPlane( dpy, bitmap, pixmap, gc, 0, 0, width, height,
X			    0, 0, (unsigned long)1 );
X		XSetWindowBackgroundPixmap(dpy, DefaultRootWindow(dpy), pixmap);
X		XFreeGC( dpy, gc );
X		XFreePixmap( dpy, bitmap );
X		XFreePixmap( dpy, pixmap );
X	}
X	XClearWindow( dpy, DefaultRootWindow(dpy) );
X}
X
X
X/*
X * UpdWorkspace - Update workspace color 
X *
X */
X/*ARGSUSED*/	/* rmIndex not needed here */
Bool
UpdWorkspace( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	XGCValues xgcv;
X
X	if (isUpdate && WorkspaceColorUsed) {
X	    /*
X	     * REMIND: this code helps prevent us from freeing the same cell
X	     * twice.  We should be able to do this according to the protocol,
X	     * but some servers have bugs where allocating a cell twice and
X	     * then freeing it once will actually free the cell.
X	     */
X	    if (WorkspaceColorPixel != GRV.Bg0Color &&
X		WorkspaceColorPixel != GRV.Bg1Color &&
X		WorkspaceColorPixel != GRV.Bg2Color &&
X		WorkspaceColorPixel != GRV.Bg3Color)
X	    {
X		XFreeColors(dpy, CMAP, &WorkspaceColorPixel, 1, 0);
X	    }
X	    WorkspaceColorUsed = False;
X	}
X
X	setWorkspaceColor( dpy, GRV.WorkspaceColor, isUpdate );
X
X	if (isUpdate)
X	{
X	    xgcv.foreground = WorkspaceColorPixel;
X	    xgcv.background = WorkspaceColorPixel;
X	    if (WorkspaceColorUsed)
X	    {
X	        XChangeGC(dpy, IconNormalGC, GCBackground, &xgcv);
X	        XChangeGC(dpy, IconSelectedGC, GCBackground, &xgcv);
X                XChangeGC(dpy, IconUnselectedGC, GCForeground, &xgcv);
X	    }
X            WinRedrawAllWindows();
X	}
X	return( True );
X}
X
X/*
X * UpdSync - Update whether synchronization is being done, or not.
X *
X */
X/*ARGSUSED*/	/* rmIndex not needed here */
Bool
UpdSync( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	(void) XSynchronize( dpy, GRV.Synchronize );
X	return( True );
X}
X
X
X/*
X * UpdTitleFont - Update title font being used
X *
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdTitleFont( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	XGCValues	values;
X
X	values.font = GRV.TitleFontInfo->fid;
X	XChangeGC( dpy, DrawNormalGC, GCFont, &values );
X	XChangeGC( dpy, DrawReverseGC, GCFont, &values );
X#ifdef REMIND_STILL_NEEDED?
X	XChangeGC( dpy, DrawLinesGC, GCFont, &values );
X	XChangeGC( dpy, DrawRevLinesGC, GCFont, &values );
X#endif	/* REMIND_STILL_NEEDED? */
X
X	olgx_set_text_font(olgx_gisnormal, GRV.TitleFontInfo,
X			   OLGX_NORMAL);
X	olgx_set_text_font(olgx_gisreverse, GRV.TitleFontInfo,
X			   OLGX_NORMAL);
X	olgx_set_text_font(olgx_gisrevpin, GRV.TitleFontInfo,
X			   OLGX_NORMAL);
X	return( True );
X}
X
X/*
X * UpdTextFont - Update text font being used (e.g., notice box text)
X *
X */
X/*ARGSUSED*/	/* std args dpy, rmIndex not used here */
Bool
UpdTextFont( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	olgx_set_text_font(olgx_gistext, GRV.TextFontInfo,
X			   OLGX_NORMAL);
X	return( True );
X}
X
X/*
X * UpdButtonFont - Update button font being used
X *
X */
X/*ARGSUSED*/	/* std args dpy, rmIndex not used here */
Bool
UpdButtonFont( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	olgx_set_text_font(olgx_gisbutton, GRV.ButtonFontInfo,
X			   OLGX_NORMAL);
X
X	return( True );
X}
X
X
X/*
X * UpdIconFont - Update icon font being used
X *
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdIconFont( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	XGCValues	values;
X
X	values.font = GRV.IconFontInfo->fid;
X	XChangeGC( dpy, IconNormalGC, GCFont, &values );
X	XChangeGC( dpy, IconSelectedGC, GCFont, &values );
X
X	return( True );
X}
X
X
X/*
X * UpdGlyphFont - Update glyph font being used
X *
X *	REMIND - this code should be used by InitGraphics.c
X *	instead of being duplicated.
X */
X/*ARGSUSED*/	/* std args dpy, rmIndex not used here */
Bool
UpdGlyphFont( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	olgx_set_glyph_font(olgx_gisnormal, GRV.GlyphFontInfo,
X			    OLGX_NORMAL);
X	olgx_set_glyph_font(olgx_gisreverse, GRV.GlyphFontInfo,
X			    OLGX_NORMAL);
X	olgx_set_glyph_font(olgx_gisrevpin, GRV.GlyphFontInfo,
X			    OLGX_NORMAL);
X	olgx_set_glyph_font(olgx_gisbutton, GRV.GlyphFontInfo,
X			    OLGX_NORMAL);
X
X	/*
X	 * REMIND Even though it might not make sense, what about olgx_gistext?
X	 */
X
X	/* REMIND HACK - if the following routine is modified to
X	 * use olgx macros, may only need to be from InitGraphics(), 
X	 * or perhaps entire call should be moved here!
X	 */
X	setResizeSizes();
X
X	return( True );
X}
X
X
X/*
X * UpdFg1Color - Update Fg1Color used 
X *
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdFg1Color( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	XGCValues xgcv;
X
X	if (isUpdate)
X	{
X	    olgx_set_single_color(olgx_gisrevpin,OLGX_WHITE,GRV.Fg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisreverse,OLGX_BG1,GRV.Fg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisreverse,OLGX_BG3,GRV.Fg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisnormal,OLGX_BLACK,GRV.Fg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisbutton,OLGX_BLACK,GRV.Fg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gistext,OLGX_BLACK,GRV.Fg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisreverse,OLGX_BLACK,GRV.Fg1Color,OLGX_SPECIAL);
X
X	    xgcv.foreground = GRV.Fg1Color;
X	    xgcv.background = GRV.Fg1Color;
X	    XChangeGC(dpy, DrawNormalGC, GCBackground, &xgcv);
X	    XChangeGC(dpy, DrawReverseGC, GCForeground, &xgcv);
X	    XChangeGC(dpy, DrawBusyGC, GCForeground, &xgcv);
X	    XChangeGC(dpy, IconNormalGC, GCBackground, &xgcv);
X	    XChangeGC(dpy, IconSelectedGC, GCForeground, &xgcv);
X#ifdef COLOR2D
X	    XChangeGC(dpy, IconBorderGC, GCBackground, &xgcv);
X#endif
X            WinRedrawAllWindows();
X	}
X}
X
X
X/*
X * UpdBg1Color - Update Bg1Color used 
X *
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdBg1Color( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	XGCValues xgcv;
X
X	if (isUpdate)
X	{
X	    olgx_set_single_color(olgx_gisnormal,OLGX_BG1,GRV.Bg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisrevpin,OLGX_BG1,GRV.Bg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisbutton,OLGX_BG1,GRV.Bg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gistext,OLGX_BG1,GRV.Bg1Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisreverse,OLGX_BLACK,GRV.Bg1Color,OLGX_SPECIAL);
X
X	    xgcv.foreground = GRV.Bg1Color;
X	    xgcv.background = GRV.Bg1Color;
X	    XChangeGC(dpy, DrawBackgroundGC, GCForeground|GCBackground, &xgcv);
X	    XChangeGC(dpy, DrawNormalGC, GCBackground, &xgcv);
X	    XChangeGC(dpy, DrawReverseGC, GCForeground, &xgcv);
X	    if (!WorkspaceColorUsed)
X	    {
X	        XChangeGC(dpy, IconNormalGC, GCBackground, &xgcv);
X	        XChangeGC(dpy, IconSelectedGC, GCBackground, &xgcv);
X	        XChangeGC(dpy, IconUnselectedGC, GCForeground, &xgcv);
X	    }
X	    XChangeGC(dpy, IconBorderGC, GCBackground, &xgcv);
X	}
X
X	UpdBg2Color(dpy,rmIndex,isUpdate);
X	UpdBg3Color(dpy,rmIndex,isUpdate);
X	UpdBg0Color(dpy,rmIndex,isUpdate);
X	if (isUpdate)
X	{
X            WinRedrawAllWindows();
X        }
X}
X
X
X/*
X * UpdBg2Color - Update Bg2Color used 
X *
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdBg2Color( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	XGCValues xgcv;
X
X	if (isUpdate)
X	{
X	    olgx_set_single_color(olgx_gisreverse,OLGX_WHITE,GRV.Bg2Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisnormal,OLGX_BG2,GRV.Bg2Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisrevpin,OLGX_BG2,GRV.Bg2Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gisbutton,OLGX_BG2,GRV.Bg2Color,OLGX_SPECIAL);
X	    olgx_set_single_color(olgx_gistext,OLGX_BG2,GRV.Bg2Color,OLGX_SPECIAL);
X
X	    xgcv.foreground = GRV.Bg2Color;
X	    xgcv.background = GRV.Bg2Color;
X#ifdef COLOR2D
X	    XChangeGC(dpy, DrawSelectedGC, GCForeground, &xgcv);
X#else
X	    if (GRV.F3dUsed)
X	    {
X	        XChangeGC(dpy, DrawSelectedGC, GCForeground, &xgcv);
X	    }
X#endif
X	}
X}
X
X
X/*
X * UpdBg3Color - Update Bg3Color used 
X *
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdBg3Color( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X    if (isUpdate)
X    {
X	olgx_set_single_color(olgx_gisnormal,OLGX_BG3,GRV.Bg3Color,OLGX_SPECIAL);
X	olgx_set_single_color(olgx_gisrevpin,OLGX_BG3,GRV.Bg3Color,OLGX_SPECIAL);
X	olgx_set_single_color(olgx_gisbutton,OLGX_BG3,GRV.Bg3Color,OLGX_SPECIAL);
X	olgx_set_single_color(olgx_gistext,OLGX_BG3,GRV.Bg3Color,OLGX_SPECIAL);
X    }
X}
X
X
X/*
X * UpdBg0Color - Update Bg0Color used for 3d color shading
X *
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdBg0Color( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X    if (isUpdate)
X    {
X	olgx_set_single_color(olgx_gisrevpin,OLGX_BLACK,GRV.Bg0Color,OLGX_SPECIAL);
X	olgx_set_single_color(olgx_gisreverse,OLGX_BG2,GRV.Bg0Color,OLGX_SPECIAL);
X	olgx_set_single_color(olgx_gistext,OLGX_WHITE,GRV.Bg0Color,OLGX_SPECIAL);
X	olgx_set_single_color(olgx_gisbutton,OLGX_WHITE,GRV.Bg0Color,OLGX_SPECIAL);
X	olgx_set_single_color(olgx_gisnormal,OLGX_WHITE,GRV.Bg0Color,OLGX_SPECIAL);
X    }
X}
X
X/*
X * updBorderColor - handle changes in the border colour 
X */
Bool
updBorderColor( dpy, rmIndex, isUpdate)
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X#ifndef COLOR2D
X    XGCValues xgcv;
X
X    if (isUpdate)
X    {
X	xgcv.foreground = GRV.BorderColor;
X	xgcv.background = GRV.BorderColor;
X	XChangeGC(dpy, IconBorderGC, GCForeground, &xgcv);
X	if (!GRV.F3dUsed)
X	    XChangeGC(dpy, DrawSelectedGC, GCForeground, &xgcv);
X        WinRedrawAllWindows();
X    }
X#endif
X}
X
X
X/*
X * UpdCursorColor - Update CursorColor used 
X *
X *	REMIND - this doesn't work; a new XDefineCursor is probably needed.
X */
X/*ARGSUSED*/	/* std arg rmIndex not used here */
Bool
UpdCursorColor( dpy, rmIndex, isUpdate )
Display	*dpy;
int	rmIndex;
Bool	isUpdate;
X{
X	int			ii;
X	XColor			foreColor, backColor;
X	
X	/* set up new cursor rgb values in color structure */
X	foreColor.pixel = GRV.CursorColor;
X	XQueryColor( dpy, CMAP, &foreColor );
X	/* REMIND - should backColor be background (GRV.Bg1Color)? 
X	 * Is backColor even used when making these cursors??
X	 */
X	backColor.pixel = WhitePixel( dpy, DefaultScreen(dpy) );
X	XQueryColor( dpy, CMAP, &backColor );
X
X	/* loop through and update all six pointers */
X	for ( ii = 0 ; ii < NUM_CURSORS ; ii++ )
X	{
X	    Cursor		*tmpVariable;
X
X	    switch( ii )
X	    {
X	    case BASICPTR:	tmpVariable = &GRV.BasicPointer;
X				break;
X	    case MOVEPTR:	tmpVariable = &GRV.MovePointer;
X				break;
X	    case BUSYPTR:	tmpVariable = &GRV.BusyPointer;
X				break;
X	    case ICONPTR:	tmpVariable = &GRV.IconPointer;
X				break;
X	    case RESIZEPTR:	tmpVariable = &GRV.ResizePointer;
X				break;
X	    case MENUPTR:	tmpVariable = &GRV.MenuPointer;
X				break;
X	    case QUESTIONPTR:	tmpVariable = &GRV.QuestionPointer;
X				break;
X	    case TARGETPTR:	tmpVariable = &GRV.TargetPointer;
X				break;
X	    case PANPTR:	tmpVariable = &GRV.PanPointer;
X				break;
X	    }
X
X#ifdef LATER
X	    XRecolorCursor( dpy, *tmpVariable, &foreColor, &backColor );
X#endif
X	}
X
X}
X
X
X/* 
X * UpdIconLocation -- the icon placement policy has changed; rearrange the 
X * icons accordingly.
X */
Bool
updIconLocation( dpy, rmIndex )
Display	*dpy;
int	rmIndex;
X{
X	SlotSetLocations(dpy);
X}
X
X
X/*
X * unconfigureFocus
X *
X * Tell a client to remove any grabs it may have set up according to the focus 
X * mode.  If this client is the focus, tell it to draw in its unfocused state.
X */
static void *
unconfigureFocus(cli)
X    Client *cli;
X{
X    FrameSetupGrabs(cli, cli->framewin->core.self, False);
X    if (cli->isFocus) {
X	cli->isFocus = False;
X	WinCallDraw(cli->framewin);
X	cli->isFocus = True;
X    }
X    return NULL;
X}
X
X
X/*
X * reconfigureFocus
X *
X * Tell a client to restore any grabs it may need for the new focus mode.  If 
X * this client is the focus, tell it to draw using the proper highlighting for 
X * the new focus mode.
X */
static void *
reconfigureFocus(cli)
X    Client *cli;
X{
X    FrameSetupGrabs(cli, cli->framewin->core.self, True);
X    if (cli->isFocus) {
X	WinCallDraw(cli->framewin);
X    }
X    return NULL;
X}
X
X
X/*
X * UpdInputFocusStyle -- change the focus style on the fly
X *
X * This is a trifle odd.  GRV.FocusFollowsMouse has already been updated with 
X * its new value.  Momentarily reset it back to its old value, and then call 
X * unconfigureFocus on every client.  This will clear grabs and highlighting 
X * and such as if the old focus mode were still in effect.  Reset GRV.
X * GRV.FocusFollowsMouse to the new value, and then call reconfigureFocus on 
X * every client to set up stuff for the new focus mode.
X */
Bool
UpdInputFocusStyle(dpy, rmIndex, isUpdate)
X    Display *dpy;
X    int rmIndex;
X    Bool isUpdate;
X{
X    if (isUpdate) {
X	GRV.FocusFollowsMouse = !GRV.FocusFollowsMouse;
X	ListApply(ActiveClientList, unconfigureFocus, 0);
X	GRV.FocusFollowsMouse = !GRV.FocusFollowsMouse;
X	ListApply(ActiveClientList, reconfigureFocus, 0);
X    }
X}
X
X
X/*
X *	The Resource Manipulation Functions
X */
X
X
X/*
X * UpdateDBValues - check all our dynamically configurable current 
X *	resources against the ones in this new db.  If any of them
X *	differ, then set the new global variable, update the value in 
X *	the global db, and call the appropriate update routine.
X *
X *	NOTICE that this assumes that all global variables have been
X *	set to something by this point (since they will be used by
X *	the setFunc()s).
X *
X *	The setFunc() does the actual comparison between the new db
X *	resource and the value previously set (using the appropriate
X *	global variable), since it "knows" how to convert the string
X *	representation of the resource into the appropriate type.
X */
void
UpdateDBValues( dpy, newDB )
Display		*dpy;
XXrmDatabase	newDB;
X{
X	char			name[MAX_NAME];
X	char			class[MAX_CLASS];
X	XrmRepresentation	newRepType;
X	XrmValue		newValue;
X	int			ii;
X
X	for ( ii = 0 ; ii < RM_ENTRYEND ; ii++ )
X	{
X		/* first, ignore all the non-dynamically settable resources */
X		switch ( ii )
X		{
X		case RM_DISPLAY:
X		case RM_PREFIX:
X		case RM_USE3D:
X		case RM_CURSORFONT:
X				continue;
X		}
X
X		/* check to see if this resource is set in the new db */
X		MakeRMName( name, ii );
X		MakeRMClass( class, ii );
X		if ( !XrmGetResource( newDB, name, class, &newRepType, 
X				      &newValue ) )
X			continue;
X		
X		/* let the setFunc convert the newValue, compare it against
X		 * the old, and then set the global variable to that new
X		 * value
X		 */
X		if ( RMTable[ii].setFunc( dpy, ii, newValue.addr, True ) )
X		{
X			/* if we really updated to using the new value,
X			 * store it in the global db for future reference
X			 */
X			XrmPutStringResource( &OlwmDB, name, newValue.addr );
X			if ( RMTable[ii].updFunc != (BFuncPtr)0 )
X				RMTable[ii].updFunc( dpy, ii, True );
X		}
X	}
X}
X
END_OF_FILE
if test 19186 -ne `wc -c <'resources1.c'`; then
    echo shar: \"'resources1.c'\" unpacked with wrong size!
fi
# end of 'resources1.c'
fi
if test -f 'usermenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'usermenu.c'\"
else
echo shar: Extracting \"'usermenu.c'\" \(20286 characters\)
sed "s/^X//" >'usermenu.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
X *      file for terms of the license.
X *
X *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char     sccsid[] = "@(#)usermenu.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) usermenu.c 25.4 90/05/23 Crucible";
X *
X */
X
X/*
X * This file contains all of the functions for manipulating the user menu
X *
X * Global Functions:
X * InitUserMenu -- load the user menu and initialise
X *
X * Global data:
X * RootMenu -- workspace menu
X */
X
X/*
X * Syntax of the user menu file should be identical to that used by
X *	buildmenu (SunView style rootmenu files).
X *
X *	NOTICE that SunView compatibility has resulted in old-style 
X *	olwm menus no longer being supported.
X *
X *	There are two new reserved keywords: 
X *
X *		DEFAULT tags a default button
X *		TITLE tags a title string for a menu (for titlebar)
X *
X *	One syntax in sunview menus is not supported:
X *		<icon_file> can not be used as a menu item 
X *
X *	Here are the common reserved keywords:
X *		MENU and END are used to delimit a submenu
X *		PIN (appearing after END) indicates the menu is pinnable
X *		EXIT (built-in - olwm service)
X *		REFRESH (built-in - olwm service)
X *		POSTSCRIPT will invoke psh on the named command
X *
X * 	The file is line-oriented, however commands to be executed can
X *	extend to the next line if the newline is escaped (\).
X *
X *	Each line consists of up to three fields:  a label (a string 
X *	corresponding to either the menu label or menu option label),
X *	up to two tags (keywords), and a command to be executed
X *	(or a file from which to read a submenu).  Two tags are allowed
X *	if one of them is "DEFAULT" or "END".  
X *
X *	The tag is used to indicate the start and end of menu definitions,
X *	pinnability, built-in functions, and default options.  
X *	The label indicates the text which appears on the user's menu,
X *	and the command describes what should be done when each item
X *	is selected.
X *
X *	Labels must be enclosed in double quotes if they contain 
X *	whitespace.  Commands may be enclosed in double quotes (but
X *	do not have to be).
X *
X *	Comments can be embedded in a file by starting a line with a
X *	pound sign (#).  Comments may not be preserved as the file is 
X *	used.
X *
X *	There are several functions which aren't invoked as programs;
X *	rather, they are built in to window manager.  These built-in
X *	services are each denoted by a single keyword.  The keywords are
X *	listed in the svctokenlookup[] array initialization.
X *
X *	example (will always have label: "Workspace Menu"):
X *
X *	"Workspace Menu"	TITLE
X *	Programs	MENU
X *		"Helpful Programs"	TITLE
X *		"Command Tool"	cmdtool
X *		"Blue Xterm"	DEFAULT xterm -fg white \
X *				-bg blue
X *	Programs	END	PIN
X *	Utilities	MENU
X *		"Refresh Screen" DEFAULT REFRESH
X *		"Clipboard"	 CLIPBOARD
X *	Utilities	END
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <ctype.h>
X#include <strings.h>
X#include <sys/file.h>
X#include <sys/param.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X
extern char *strtok();		/* not defined in strings.h */
X
X#include "olwm.h"
X#include "mem.h"
X#include "menu.h"
X
X#define	MENUFILE	"openwin-menu"
X#define TOKLEN		300
X
X/* parseMenu return values */
X#define MENU_FATAL     -1
X#define MENU_NOTFOUND	0
X#define MENU_OK		1
X#define MENU_PINNABLE	2
X
typedef enum { UsrToken, MenuToken, EndToken, DefaultToken, PinToken, 
X	TitleToken, ServiceToken, PshToken } TokenType;
X
X/* locally useful macro */
X#define	APPEND_STRING(buf, str)	( strncat( buf, str, \
X					( sizeof(buf) - strlen(buf) - 1 ) ) )
X
X/* Externals */
extern int RefreshFunc();
extern int ClipboardFunc();
extern int PrintScreenFunc();
extern int ExitFunc();
extern int PropertiesFunc();
extern int SaveWorkspaceFunc();
extern int FlipDragFunc();
extern int AppMenuFunc();
extern int PshFunc();
extern int NopFunc();
extern int WindowCtlFunc();
extern int RestartOLWM();
extern int FlipFocusFunc();
X
X/* global data */
Menu *RootMenu;
X
X/* local forward declarations */
static Bool	checkFile();
static int	menuFromFile();
static int	parseMenu();
static void	fillMenuStruct();
static TokenType lookupToken();
static Menu	*buildFromSpec();
static void	initMenu();
static void	initButton();
static void	freeButtonData();
static void	freeMenuData();
X
X/* local data */
typedef struct _buttondata {
X	struct _buttondata *next;
X	char *name;
X	Bool isDefault;
X	Bool isLast;
X	FuncPtr func;
X	char *exec;		/* string to be executed, like "xterm" */
X	void *submenu;
X	} buttondata;
X
X
typedef struct {
X	char *title;
X	char *label;
X	int idefault;		/* index of default button */
X	int nbuttons;
X	Bool pinnable;
X	buttondata *bfirst;
X} menudata;
X
menudata userroot = { "Workspace Menu", NULL, -1, 0, True, NULL };
X
X/* default Root menu should be quite minimal */
Button RootButtons[] = {
X	{ "Xterm", False, Enabled, {AppMenuFunc, (void *)"xterm"} },
X        { "Refresh", False, Enabled, {RefreshFunc, NULL} },
X	{ "Exit WM", False, Enabled, {ExitOLWM, NULL} },
X        { "Exit", False, Enabled, {ExitFunc, NULL} },
X        };
Menu DefaultRootMenu = { "Workspace", RootButtons, 4, -1, True, (FuncPtr)MakeMenu};
X
X
X/*
X * Global routines
X */
X
X/*	
X * InitUserMenu	-- load the user menu from a file using menuFromFile()
X *	and then create the actual RootMenu using buildFromSpec().
X *
X *	The file to be read is either in the directory specified by 
X *	OLWMPATH or HOME, or OPENWINHOME/lib, and should be called 
X *	MENUFILE.  If none of those three files exist,
X *	use the default menu.
X *
X */
void
InitUserMenu(dpy)
Display		*dpy;
X{
X    char *getenv();
X    char temp[MAXPATHLEN];
X    char *path;
X
X    RootMenu = (Menu *) 0;
X
X    /*
X     * SLEAZE
X     * This isn't a loop.  It's a construct that makes "break" mean "jump to 
X     * the statement just outside the brace."
X     */
X    while (1) {
X	/* try reading $OLWMMENU */
X	path = getenv("OLWMMENU");
X	if (path != NULL && menuFromFile(path, &userroot, False) >= MENU_OK)
X	    break;
X
X	/* try reading $HOME/.openwin-menu */
X	path = getenv("HOME");
X	strcpy(temp, path ? path : "");
X	strcat(temp, "/.");
X	strcat(temp, MENUFILE);
X	if (menuFromFile(temp, &userroot, False) >= MENU_OK)
X	    break;
X
X	/* try reading $OPENWINHOME/lib/openwin-menu */
X	path = getenv("OPENWINHOME");
X	strcpy(temp, path ? path : "");
X	strcat(temp, "/lib/");
X	strcat(temp, MENUFILE);
X	if (menuFromFile(temp, &userroot, False) >= MENU_OK)
X	    break;
X
X	/* use default root menu */
X	MenuCreate(dpy, &DefaultRootMenu);
X	RootMenu = &DefaultRootMenu;
X	return;
X    }
X
X    /* we read a menu from a file; now build it */
X    RootMenu = buildFromSpec( dpy, &userroot, userroot.title );
X}
X
X
X/*
X * Local routines
X */
X
X#ifdef NOTDEF
X/*
X * checkFile - check to see that a file (composed of named file and dir)
X *	is readable
X */
static Bool
checkFile( location, file, path )
char *location, *file, *path;
X{
X	char	*getenv();
X	char	*dir;
X
X	if ( (dir = getenv( location )) == NULL )
X		return False;
X	strcpy( path, dir );
X	strcat( path, file );
X	return ( access( path, R_OK ) == 0 );
X}
X#endif
X
X/*
X * menuFromFile - read a menu description from a file
X *
X *	Return values: same as parseMenu, with the addition of
X *		MENU_NOTFOUND = couldn't read submenu file
X */
static int
menuFromFile(file, menu, messages)
char		*file;
menudata	*menu;
Bool		messages;
X{
X	FILE       *stream;
X	int         lineno = 1;	/* Needed for recursion */
X	int         rval;
X
X	stream = fopen(file, "r");
X	if (stream == NULL) {
X	    if (messages)
X		fprintf(stderr, "olvwm: can't open menu file %s\n", file);
X	    return(MENU_NOTFOUND);
X	}
X
X	rval = parseMenu(file, stream, menu, &lineno);
X	fclose(stream);
X	if (rval >= MENU_OK)
X	    fillMenuStruct(menu);
X	else
X	    freeMenuData(menu);
X
X	return(rval);
X}
X
X
X/*
X * parseMenu -- read the user menu from the given stream and
X *	parse the stream into the menu structures defined locally.
X *	These structures (which are local to this module) are later
X *	used to build real menu structures.
X *
X *	Note that fillMenuStruct() needs to be called after parseMenu()
X *	is called (to finish filling out the menudata structure).
X *	If parseMenu() returns < 0, then freeMenuData() needs to be 
X *	called instead, to free up unused memory.
X *
X *	Return values:
X *		MENU_OK		= an unpinnable menu was read successfully
X *		MENU_PINNABLE	= a pinnable menu was read successfully
X *		MENU_FATAL	= a fatal error was encountered
X *
X *	This is based heavily on buildmenu's getmenu() parsing routine.
X *
X */
static int
parseMenu(filename, stream, rootmenu, lineno)
char	 *filename;
XFILE	 *stream;
menudata *rootmenu;
int      *lineno;
X{
X	menudata	*currentMenu, *saveMenu;
X	buttondata	*currentButton;
X	char		line[TOKLEN];
X	char		label[TOKLEN];
X	char		prog[TOKLEN];
X	char		args[TOKLEN];
static	char		localBuf[1024];
X	char		*nqformat = 
X				"%[^ \t\n]%*[ \t]%[^ \t\n]%*[ \t]%[^\n]\n";
X	char		*qformat = 
X				"\"%[^\"]\"%*[ \t]%[^ \t\n]%*[ \t]%[^\n]\n";
X	char		*format;
X	register char	*p;
X	int		continuation;
X	Bool		done;
X
X	currentMenu = rootmenu;
X	initButton( (buttondata **)&(currentMenu->bfirst) );
X	currentButton = currentMenu->bfirst;
X	continuation = 0;
X
X	for ( ; fgets(line, sizeof(line), stream) ; (*lineno)++ )
X	{
X	    if (line[0] == '#') 
X		    continue;
X
X	    for ( p = line ; isspace(*p) ; p++ )
X		    ;
X
X	    if ( *p == '\0' )
X		    continue;
X
X	    /*
X	     * if we're already on a continuation line (the previous 
X	     * line ended in '\') then just copy the input through
X	     * to the output until we get a line that doesn't end in 
X	     * '\' (nuke the vi backslash).
X	     */
X	    if (continuation) 
X	    {
X		    /* fgets includes the newline in the string read */
X		    while ( line[strlen(line) - 2] == '\\' )
X		    {
X			    /* get rid of backslash */
X			    line[strlen(line) - 2] = '\0'; 
X			    APPEND_STRING( localBuf, " " );
X			    APPEND_STRING(localBuf, p);
X			    if ( !fgets(line, sizeof(line), stream) )
X				    break;
X			    (*lineno)++;
X			    for ( p = line ; isspace(*p) ; p++ )
X				    ;
X		    }
X		    /* last line of continuation - replace \n with \0 */
X		    line[strlen(line) - 1] = '\0';
X		    APPEND_STRING( localBuf, " " );
X		    APPEND_STRING(localBuf, p);
X		    /* save it permanently in the buttondata structure */
X		    currentButton->exec = MemNewString( localBuf );
X		    localBuf[0] = '\0';
X		    continuation = 0;
X		    initButton( (buttondata **)&(currentButton->next) );
X		    currentButton = currentButton->next;
X		    continue;
X	    }
X
X	    /* if the line ends in '\' remember that continuation 
X	     * has started.
X	     */
X	    if ( line[strlen(line) - 2] == '\\' )
X	    {
X		    continuation = 1;
X		    line[strlen(line) - 2] = '\0';
X	    }
X	
X	    args[0] = '\0';
X	    format = ( *p == '"' ) ? qformat : nqformat;
X
X	    if ( sscanf( p, format, label, prog, args ) < 2 )
X	    {
X		    fprintf(stderr,
X			"olvwm: syntax error in menu file %s, line %d\n", 
X			    filename, *lineno);
X		    return(MENU_FATAL);
X	    }
X
X	    if ( strcmp(prog, "END") == 0 ) 
X	    {
X		    /* currently allocated button is last for this menu */
X		    currentButton->isLast = True;
X		    if (currentMenu->label != NULL &&
X			strcmp(label, currentMenu->label) != 0) {
X			fprintf(stderr,
X			    "olvwm: menu label mismatch in file %s, line %d\n",
X			    filename, *lineno);
X			return(MENU_FATAL);
X		    }
X		    if ( strcmp(args, "PIN") == 0 )
X			    return(MENU_PINNABLE);
X		    else
X			    return(MENU_OK);
X	    }
X
X	    if ( strcmp(prog, "TITLE") == 0 ) 
X	    {
X		    currentMenu->title = MemNewString( label );
X		    /* we don't need to set up the next button, since
X		     * the TITLE line didn't use up a button
X		     */
X		    continue;
X	    }
X
X	    currentButton->name = MemNewString( label );
X
X	    if ( strcmp(prog, "DEFAULT") == 0) {
X		char *t;
X		char *u;
X
X		currentButton->isDefault = True;
X
X		/*
X		 * Pull the first token from args into prog.
X		 */
X		t = strtok(args, " \t");
X		if ( t == NULL ) {
X		    fprintf(stderr,
X			    "olvwm: error in menu file %s, line %d\n",
X			    filename, *lineno);
X		    fputs("missing item after DEFAULT keyword.\n", stderr);
X		    return(MENU_FATAL);
X		}
X		strcpy(prog, t);
X		t = strtok(NULL, ""); /* get remainder of args */
X		if (t == NULL)
X		    args[0] = '\0';
X		else {
X		    u = args;
X		    /* can't use strcpy because they overlap */
X		    while ( *u++ = *t++ )
X			;
X		}
X	    }
X
X	    if ( strcmp(prog, "MENU") == 0 ) 
X	    {
X		    int         rval;
X
X		    initMenu( (menudata **)&(currentButton->submenu) );
X		    saveMenu = currentMenu;
X		    currentMenu = (menudata *)currentButton->submenu;
X		    currentMenu->label = MemNewString(label);
X
X		    if (args[0] == '\0') 
X		    {
X			    /* we haven't incremented lineno for this
X			     * read loop yet, so we need to do it now.
X			     * when END is read, parseMenu returns without
X			     * incrementing lineno, so the count will be
X			     * ok when this loop increments it before
X			     * reading the next line of the file.
X			     */
X			    (*lineno)++;
X			    if ( (rval = parseMenu(filename, stream, 
X						   currentMenu, lineno)) < 0 )
X			    {
X				freeMenuData( currentMenu );
X				return(MENU_FATAL);
X			    }
X			    else
X				fillMenuStruct( currentMenu );
X		    }
X		    else {
X			rval = menuFromFile(args, currentMenu, True);
X			if (rval <= MENU_NOTFOUND)
X			    return(MENU_FATAL);
X		    }
X		    if ( rval == MENU_PINNABLE ) 
X			    currentMenu->pinnable = True;
X
X		    currentMenu = saveMenu;
X		    /* if submenu not found, reuse button */
X		    if ( rval != MENU_NOTFOUND )
X		    {
X		        initButton( (buttondata **)&(currentButton->next) );
X		        currentButton = currentButton->next;
X		    }
X		    continue;			
X	    }
X
X	    done = False;
X	    while ( !done )
X	    {
X		switch ( lookupToken( prog, &(currentButton->func) ) )
X		{
X		case UsrToken:
X		    /* if UsrToken, that means that "prog" was just
X		     * the first word of the command to be executed,
X		     */
X		    strcpy( localBuf, prog );
X		    APPEND_STRING( localBuf, " " );
X		    APPEND_STRING( localBuf, args );
X 		    /* copy current contents of localBuf back into
X		     * args array so that PshToken code can be used
X		     */
X		    strcpy( args, localBuf );
X		    localBuf[0] = '\0';
X		    /* fall through */
X		case PshToken:
X		    if (continuation) 
X		    	strcpy( localBuf, args );
X		    else
X		    	currentButton->exec = MemNewString( args );
X		    done = True;
X		    break;
X		case PinToken:
X		    fprintf( stderr, 
X			"olvwm: format error in menu file %s, line %d\n", 
X			filename, *lineno );
X		    fputs("menu title and END required before PIN keyword.\n",
X			  stderr);
X		    return(MENU_FATAL);
X		    break;
X		default:
X		    /* some other valid token found and returned */
X		    done = True;
X		    break;
X		}
X	    }
X		    
X	    if ( !continuation )
X	    {
X	        initButton( (buttondata **)&(currentButton->next) );
X	        currentButton = currentButton->next;
X	    }
X	}
X	/* never used the last button created */
X	currentButton->isLast = True;
X
X	return(MENU_OK);
X}
X
X
X/* 
X * fillMenuStruct - Once the menu structures have been filled out using 
X * 	information in the menu description file (via parseMenu()), the 
X * 	nbuttons and idefault elements need to be set.
X */
static void
fillMenuStruct( mptr )
menudata	*mptr;
X{
X	buttondata	*bptr;
X	int		buttonIndex = 0;
X
X	bptr = mptr->bfirst;
X	if ( bptr->isLast == True )
X	{
X		MemFree( bptr );
X		bptr = mptr->bfirst = NULL;
X	}
X	for ( ; bptr != NULL && bptr->isLast == False ; bptr = bptr->next )
X	{
X		if ( bptr->isDefault == True )
X			mptr->idefault = buttonIndex;
X
X		if ( (bptr->next)->isLast == True )
X		{
X			MemFree( bptr->next);
X			bptr->next = NULL;
X		}
X
X		buttonIndex++;
X	}
X	/* buttonIndex is one past end, but started at 0, so = number buttons */
X	mptr->nbuttons = buttonIndex;
X}
X
X
X/* 
X * Allowed menu keywords ("Token") 
X */
X
struct _svctoken {
X	char *token;
X	FuncPtr func;
X	TokenType toktype;
X} svctokenlookup[] = {
X	{ "REFRESH", RefreshFunc, ServiceToken },
X	{ "CLIPBOARD", ClipboardFunc, ServiceToken },
X	{ "PRINT_SCREEN", PrintScreenFunc, ServiceToken },
X	{ "EXIT", ExitFunc, ServiceToken },
X	{ "WMEXIT", ExitOLWM, ServiceToken },
X	{ "PROPERTIES", PropertiesFunc, ServiceToken },
X	{ "NOP", NopFunc, ServiceToken },
X	{ "DEFAULT", NULL, DefaultToken },
X	{ "MENU", NULL, MenuToken },
X	{ "END", NULL, EndToken },
X	{ "PIN", NULL, PinToken },
X	{ "TITLE", NULL, TitleToken },
X	{ "WINDOW_CONTROLS", WindowCtlFunc, ServiceToken },
X	{ "FLIPDRAG", FlipDragFunc, ServiceToken },
X	{ "SAVE_WORKSPACE", SaveWorkspaceFunc, ServiceToken },
X	{ "POSTSCRIPT", PshFunc, PshToken },
X	{ "RESTART", RestartOLWM, ServiceToken },
X	{ "FLIPFOCUS", FlipFocusFunc, ServiceToken },
X};
X
X#define NSERVICES (sizeof(svctokenlookup)/sizeof(struct _svctoken))
X
X/* lookupToken -- look up a token in the list of tokens
X *	given a supposed keyword or service name.  If the name doesn't
X *	match any existing token, return the user-defined token.  
X */
static TokenType
lookupToken(nm,ppf)
char *nm;
XFuncPtr *ppf;
X{
X	int ii;
X
X	for (ii=0; ii<NSERVICES; ii++)
X	{
X		if (!strcmp(nm,svctokenlookup[ii].token))
X		{
X			if (ppf != (FuncPtr *)0) 
X				*ppf = svctokenlookup[ii].func;
X			return svctokenlookup[ii].toktype;
X		}
X	}
X	if (ppf != (FuncPtr *)0)
X		*ppf = AppMenuFunc;
X	return UsrToken;
X}
X
X
X/* buildFromSpec -- build the real menu structures, and create the
X * 	associated menus, from the specifications parsed from
X *	the menu layout.  Free up the specifications as we go
X *	along.
X */
static Menu *
buildFromSpec(dpy,menu,deftitle)
Display *dpy;
menudata *menu;
char *deftitle;
X{
X	Menu *m;
X	Button *b;
X	int ii;
X	buttondata *bdata, *bsave;
X
X	m = MemNew(Menu);
X	if (menu->pinnable)
X	{
X		m->hasPushPin = True;
X		m->pinAction = (FuncPtr)MakeMenu;
X		if (menu->title == NULL)
X			m->title = deftitle;
X		else
X			m->title = menu->title;
X	}
X	else
X	{
X		m->hasPushPin = False;
X		m->pinAction = NULL;
X		/* non-pinnable menus only get titles if they ask for them */
X		/* m->title must be NULL if menu->title is NULL */
X		m->title = menu->title;
X	}
X
X	m->buttonCount = menu->nbuttons;
X	m->buttonDefault = menu->idefault;
X
X	b = (Button *)MemAlloc((unsigned)(menu->nbuttons * sizeof(Button)));
X	m->buttons = b;
X	for ( ii=0, bdata=menu->bfirst ; ii<menu->nbuttons ; ii++ )
X	{
X		b[ii].label = bdata->name;
X		b[ii].stacked = bdata->submenu != NULL;
X		b[ii].state = Enabled;
X		b[ii].action.callback = bdata->func;
X		if ( b[ii].stacked )
X			b[ii].action.submenu = 
X				(void *)buildFromSpec(dpy, 
X					      (menudata *)(bdata->submenu),
X					      bdata->name);
X		else
X			b[ii].action.submenu = (void *)bdata->exec;
X
X		bsave = bdata;
X		bdata = bdata->next;
X		MemFree(bsave);
X
X	}
X
X	MenuCreate(dpy,m);
X	MemFree(menu);
X	return(m);
X}
X
X
X/*
X * initMenu - 
X */
static void
initMenu( newmenu )
menudata	**newmenu;
X{
X	*newmenu = MemNew(menudata);
X	(*newmenu)->title = NULL;
X	(*newmenu)->label = NULL;
X	(*newmenu)->idefault = -1;
X	(*newmenu)->nbuttons = 0;
X	(*newmenu)->pinnable = False;
X	(*newmenu)->bfirst = (buttondata *)0;
X}
X
X/*
X * initButton - 
X */
static void
initButton( newButton )
buttondata	**newButton;
X{
X	*newButton = MemNew(buttondata);
X	(*newButton)->next = NULL;
X	(*newButton)->name = NULL;
X	(*newButton)->isDefault = False;
X	(*newButton)->isLast = False;
X	(*newButton)->func = (FuncPtr)0;
X	(*newButton)->exec = NULL;
X	(*newButton)->submenu = NULL;
X}
X
X/*
X * freeMenuData - free any possibly allocated memory for this menudata 
X *	structure (and its buttons), since it's not going to be used
X */
static void
freeMenuData( unusedMenu )
menudata	*unusedMenu;
X{
X	buttondata	*unusedButton;
X
X	/* isLast probably isn't set, since this menu had an error */
X	if ( ( unusedButton = unusedMenu->bfirst ) != (buttondata *)0 )
X		freeButtonData( unusedButton );
X
X	MemFree( unusedMenu->title );
X	MemFree( unusedMenu->label );
X	MemFree( unusedMenu );
X	unusedMenu = NULL;
X}
X
X/*
X * freeButtonData - free any possibly allocated memory for this buttondata 
X *	structure, since it's not going to be used
X */
static void
freeButtonData( unusedButton )
buttondata	*unusedButton;
X{
X
X	if ( unusedButton->next != NULL )
X		freeButtonData( unusedButton->next );
X
X	MemFree( unusedButton->name );
X	MemFree( unusedButton->exec );
X	if ( unusedButton->submenu != NULL )
X		freeMenuData( unusedButton->submenu );
X	MemFree( unusedButton );
X	unusedButton = NULL;
X}
END_OF_FILE
if test 20286 -ne `wc -c <'usermenu.c'`; then
    echo shar: \"'usermenu.c'\" unpacked with wrong size!
fi
# end of 'usermenu.c'
fi
echo shar: End of archive 8 \(of 16\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 16 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources.x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list