v12i069: olvwm - Open Look Virtual Window Manager, Part13/16

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


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

#! /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 13 (of 16)."
# Contents:  services.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:09 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'services.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'services.c'\"
else
echo shar: Extracting \"'services.c'\" \(29838 characters\)
sed "s/^X//" >'services.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[] = "@(#)services.c	1.3 olvwm version 4/17/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) services.c 25.17 90/05/31 Crucible";
X *
X */
X
X#include <stdio.h>
X#include <strings.h>
X#include <errno.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <ctype.h>
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X
X#include "events.h"
X#include "olwm.h"
X#include "win.h"
X#include "menu.h"
X#include "notice.h"
X#include "globals.h"
X#include "group.h"
X#include "mem.h"
X#include "resources.h"
X
char	*getenv();
X
X/*
X * Externals
X */
extern Atom AtomProtocols;
extern Atom AtomSaveYourself;
extern Atom AtomShowProperties;
extern Window	NoFocusWin;
extern char	**Envp;
extern Menu FrameFullMenuSticky, FrameFullMenuUnsticky;
extern Menu FrameNormMenuSticky, FrameNormMenuUnsticky;
extern Menu IconFullMenuSticky, IconFullMenuUnsticky;
X
extern Bool UpdInputFocusStyle();
X
extern Window	VDM;
X
X/*
X * Execute a command by handing it to /bin/sh.
X */
static void
execCommand(cmd)
X    char *cmd;
X{
X    char *args[4];
X    int pid;
X
X    args[0] = "/bin/sh";
X    args[1] = "-c";
X    args[2] = cmd;
X    args[3] = NULL;
X
X    pid = fork();
X    if (pid == -1) {
X	perror("olvwm: fork");
X    } else if (pid == 0) {
X	/* child */
X	setpgrp(0, getpid());
X	execve(args[0], args, Envp);
X	perror("olvwm: exec");
X	exit(1);
X    }
X}
X
X
X/***************************************************************************
X* Exit from WM
X****************************************************************************/
X
X/*ARGSUSED*/	/* winInfo, menu, and idx args will be used 
X		 * when more sophisticated ExitFunc is written */
int 
XExitFunc(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu *menu;
int idx;
X{
X	int		screen;
X	NoticeBox	noticeBox;
static	char		*buttons[] = { "Exit", "Cancel" };
static	char		*strings[] = 
X				{ "Please confirm exit from window system" };
X
X	/* multiple screens not yet supported */
X	screen = DefaultScreen( dpy );
X
X	/* set up noticeBox information */
X	noticeBox.numButtons = 2;
X	noticeBox.defaultButton = 1;
X	noticeBox.buttonText = buttons;
X	noticeBox.numStrings = 1;
X	noticeBox.stringText = strings;
X	noticeBox.boxX = -1;
X	noticeBox.boxY = -1;
X
X	/* If Exit button is selected, will return 0 */
X	if ( UseNoticeBox( dpy, screen, &noticeBox ) == 0 )
X		Exit(dpy);
X
X}
X
X/***************************************************************************
X* Command execution
X****************************************************************************/
X
X/*
X * AppMenuFunc -- called when a command is listed as the item selected on
X *      the olwm menu
X */
X/*ARGSUSED*/    /* dpy, winInfo args will be used later */
int
AppMenuFunc(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu    *menu;
int     idx;
X{
X	execCommand((char *)menu->buttons[idx].action.submenu);
X}
X
X/*
X * PshFunc -- called when the "POSTSCRIPT" keyword is present for the
X *      item selected in the olwm menu
X *
X */
X/*ARGSUSED*/    /* dpy, winInfo args will be used later */
int
PshFunc(dpy, winInfo, menu, idx)
Display 	*dpy;
WinGeneric	*winInfo;
Menu    	*menu;
int     	idx;
X{
X	char    *commArgv[2];
X	int	pshPipe[2];
X	int     pid;
X	char	*dir;
X	char	pshPath[100];
X
X	if ( (dir = getenv( "OPENWINHOME" )) == NULL )
X		commArgv[0] = "/usr/bin/psh";
X	else
X	{
X		strcpy( pshPath, dir ); 
X		strcat( pshPath, "/bin/psh" );
X		commArgv[0] = pshPath;
X	}
X
X	commArgv[1] = NULL;
X
X	if ( pipe( pshPipe ) == -1 )
X	{
X		perror( "olvwm: pipe" );
X		return( -1 );
X	}
X
X	pid = fork();
X	if ( pid == -1 )
X	{
X		perror("olvwm: fork");
X		return( -1 );
X	}
X	else if ( pid == 0 )
X	{
X		/* child reads from pipe and writes to stdout/err */
X		close( 0 );		/* close stdin */
X		dup( pshPipe[0] );	/* make stdin the read end */
X		close( pshPipe[0] ); 	/* don't need orig pipe fds */
X		close( pshPipe[1] );
X		close( 1 );		/* close stdout */
X		dup( 2 );		/* make olwm stderr = psh stdout */
X		setpgrp(0, getpid());
X		execve( commArgv[0], commArgv, Envp );
X		fprintf( stderr, "olvwm: psh error: %d\n", errno );
X	}
X	else
X	{
X		/* parent writes user menu postscript code down pipe */
X		close( pshPipe[0] );	/* don't need to read pipe */
X		write( pshPipe[1], 
X		       (char *)(menu->buttons[idx].action.submenu), 
X		       strlen((char *)(menu->buttons[idx].action.submenu)) );
X		close( pshPipe[1] );
X	}
X	return 0;
X}
X
X/***************************************************************************
X* Window controls
X****************************************************************************/
X
X/*
X * WindowCtlFunc - Window Controls
X */
X/*ARGSUSED*/    /* dpy, winInfo, menu, idx args used when implemented */
int
WindowCtlFunc(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu    *menu;
int     idx;
X{
X        fprintf(stderr,"Window controls not implemented\n");
X}
X
X/***************************************************************************
X* Flip Drag
X****************************************************************************/
X
X/*ARGSUSED*/
int
XFlipDragFunc(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu    *menu;
int     idx;
X{
X    GRV.DragWindow = !GRV.DragWindow;
X    return 0;
X}
X
X
X/***************************************************************************
X* Flip Focus
X****************************************************************************/
X
int
XFlipFocusFunc(dpy, winInfo, menu, idx)
X    Display *dpy;
X    WinGeneric *winInfo;
X    Menu    *menu;
X    int     idx;
X{
X    GRV.FocusFollowsMouse = !GRV.FocusFollowsMouse;
X    (void) UpdInputFocusStyle(dpy, RM_INPUTFOCUS, True);
X    return 0;
X}
X
X/***************************************************************************
X* No-Operation
X****************************************************************************/
X
X/*
X * NopFunc - a no-operation function, used as a placeholder for
X *      the NOP service
X */
X/*ARGSUSED*/    /* dpy, winInfo, menu, idx args included for consistency */
int
NopFunc(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu    *menu;
int     idx;
X{
X}
X
X/***************************************************************************
X* Clipboard
X****************************************************************************/
X
X/*ARGSUSED*/	/* dpy, winInfo, menu, and idx args will be used 
X		 * when Clipboard is implemented */
int 
ClipboardFunc(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu *menu;
int idx;
X{
X	NoticeBox	noticeBox;
static	char		*buttons[] = { "Ok" };
static	char		*strings[] = 
X			    { "Sorry, the clipboard is not yet implemented." };
X
X	/* set up noticeBox information */
X	noticeBox.numButtons = 1;
X	noticeBox.defaultButton = 0;
X	noticeBox.buttonText = buttons;
X	noticeBox.numStrings = 1;
X	noticeBox.stringText = strings;
X	noticeBox.boxX = -1;
X	noticeBox.boxY = -1;
X
X	(void) UseNoticeBox(dpy, DefaultScreen(dpy), &noticeBox);
X}
X
X/***************************************************************************
X* Print Screen
X****************************************************************************/
X
X/*ARGSUSED*/	/* dpy, winInfo, menu, and idx args will be used 
X		 * when Print Screen is implemented */
int 
PrintScreenFunc(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu *menu;
int idx;
X{
X	NoticeBox	noticeBox;
static	char		*buttons[] = { "Ok" };
static	char		*strings[] = 
X			    { "Sorry, Print Screen is not yet implemented." };
X
X	/* set up noticeBox information */
X	noticeBox.numButtons = 1;
X	noticeBox.defaultButton = 0;
X	noticeBox.buttonText = buttons;
X	noticeBox.numStrings = 1;
X	noticeBox.stringText = strings;
X	noticeBox.boxX = -1;
X	noticeBox.boxY = -1;
X
X	(void) UseNoticeBox(dpy, DefaultScreen(dpy), &noticeBox);
X}
X
X
X/***************************************************************************
X* Refresh screen
X****************************************************************************/
X
X/*
X * RecursiveRefresh
X * 
X * Recursively refresh an entire window tree, by walking the hierarchy and 
X * sending Expose events to each window (via XClearWindow).  Note that 
X * XClearArea will generate a BadMatch error if called on InputOnly windows; 
X * this error is suppressed in Error.c.
X */
void
RecursiveRefresh(dpy, win)
X    Display *dpy;
X    Window win;
X{
X    int i, nchildren;
X    Status s;
X    Window root, parent;
X    Window *childlist;
X
X    XClearArea(dpy, win, 0, 0, 0, 0, True);
X    s = XQueryTree(dpy, win, &root, &parent, &childlist, &nchildren);
X    if (s == 0)
X	return;
X    for (i=0; i<nchildren; ++i) {
X	RecursiveRefresh(dpy, childlist[i]);
X    }
X    if (nchildren > 0)
X	XFree(childlist);
X}
X
X
X/*
X * RefreshFunc -- called when the "Refresh Screen" item has been selected on
X *	the olwm menu
X */
X/*ARGSUSED*/	/* winInfo, menu, and idx args will be used later */
int 
RefreshFunc(dpy, winInfo, menu, idx)
Display	*dpy;
WinGeneric	*winInfo;
Menu	*menu;
int	idx;
X{
X    if (GRV.RefreshRecursively) {
X	RecursiveRefresh(dpy, DefaultRootWindow(dpy));
X    } else {
X	Window	w;
X	XSetWindowAttributes xswa;
X
X	/* We create a window over the whole screen, map it,
X	 * then destroy it.
X	 */
X	xswa.override_redirect = True;
X	w = XCreateWindow(dpy, 
X			  RootWindow(dpy, DefaultScreen(dpy)),
X			  0, 0,
X			  DisplayWidth(dpy,DefaultScreen(dpy)),
X			  DisplayHeight(dpy,DefaultScreen(dpy)),
X			  0,
X			  DefaultDepth(dpy,DefaultScreen(dpy)), 
X			  InputOutput, 
X			  DefaultVisual(dpy,DefaultScreen(dpy)),
X			  CWOverrideRedirect, 
X			  &xswa);
X
X	XMapRaised(dpy, w);
X	XDestroyWindow(dpy, w);
X    }
X}
X
X/***************************************************************************
X* Properties
X****************************************************************************/
X
X#define WORKSPACEPROPS "props"
X
X/*
X * PropertiesFunc -- called when the "Properties ..." item has been selected 
X * on the root menu.  REMIND: this and AppMenuFunc should be merged.
X */
X/*ARGSUSED*/	/* dpy, winInfo, menu, and idx args will be used later */
int
PropertiesFunc(dpy,winInfo,menu,idx)
Display	*dpy;
WinGeneric	*winInfo;
Menu	*menu;
int	idx;
X{
X	execCommand(WORKSPACEPROPS);
X}
X
X/***************************************************************************
X* Save Workspace
X****************************************************************************/
X
static Window SaveWaiters[500];    /* REMIND: should dynamically allocate */
static int SaveCount = 0;
static FILE *SaveFile;
X
static char *backfilename = NULL;
static char *basefilename = NULL;
static char *tempfilename = NULL;
X
X#define INITFILENAME ".openwin-init"
X
X/*
X * Construct the names: "$HOME/.openwin-init" and "$HOME/.openwin-init.BAK",
X * and "$HOME/.openwin-init.TEMP" and set up pointers to them.
X */
static void
sw_makenames()
X{
X    char *home;
X    char buffer[1024];
X
X    if (basefilename != NULL)
X	return;
X
X    home = getenv("HOME");
X    if (home == NULL)
X	home = "";  /* REMIND - what to do here? */
X
X    strcpy(buffer, home);
X    strcat(buffer, "/");
X    strcat(buffer, INITFILENAME);
X
X    basefilename = MemNewString(buffer);
X
X    strcat(buffer, ".BAK");
X    backfilename = MemNewString(buffer);
X
X    strcpy(buffer, basefilename);
X    strcat(buffer, ".TEMP");
X    tempfilename = MemNewString(buffer);
X}
X
X
static void
sw_timeout(dpy)
Display *dpy;
X{
X    NoticeBox		    noticeBox;
static    char		    *buttons[] = { "Cancel" };
static    char		    *strings[] = {
X    "Save Workspace could not be completed, because",
X    "some applications did not respond." 
X    };
X
X#ifdef DEBUG
X    fprintf(stderr,"Save Workspace timeout!\n");
X#endif /* DEBUG */
X    /* set up noticeBox information */
X    noticeBox.numButtons = 1;
X    noticeBox.defaultButton = 0;
X    noticeBox.buttonText = buttons;
X    noticeBox.numStrings = 2;
X    noticeBox.stringText = strings;
X    noticeBox.boxX = -1;
X    noticeBox.boxY = -1;
X
X    (void) UseNoticeBox(dpy, DefaultScreen(dpy), &noticeBox );
X    sw_interposer(dpy, NULL, NULL, NULL);
X}
X
void *
sw_send2(cli,SaveFile)
Client *cli;
XFILE	*SaveFile;
X{
char	**argv = NULL;
int	i, argc;
X
X
X    if (!(cli->protocols & SAVE_YOURSELF ))
X    {
X	if (XGetCommand(cli->dpy, ClientPane(cli), &argv, &argc)) {
X	   for (i = 0; i < argc; i++) {
X	       print_quoted_word(SaveFile, argv[i]);
X	       putc(' ', SaveFile);
X	       putc('&', SaveFile);
X	       putc('\n', SaveFile);
X	   }
X	   XFreeStringList(argv);
X	}
X    }
X    return NULL;
X}
X
X/*
X * sw_interposer - the interposition function for getting PropertyNotify
X * events on WM_COMMAND on the windows that were sent WM_SAVE_YOURSELF.
X */
static int
sw_interposer( dpy, event, wi, closure )
X    Display *dpy;
X    XEvent *event;
X    WinGeneric *wi;
X    void *closure;
X{
X    int i;
X    Window temp;
X    unsigned long nitems, remainder;
X    char *data;
X    NoticeBox	noticeBox;
static    char	*buttons[] = { "Ok" };
static    char	*strings[] = { "Save Workspace complete." };
X
X    if ( event == NULL ) {
X	XUngrabKeyboard( dpy, CurrentTime );
X	XUngrabPointer( dpy, CurrentTime );
X	UninstallInterposer();
X	TimeoutCancel();
X	fclose(SaveFile);
X	(void) unlink(tempfilename);
X	return DISPOSE_DISPATCH;
X    }
X
X    if ( event->type == PropertyNotify &&
X	 event->xproperty.atom == XA_WM_COMMAND &&
X	 event->xproperty.state == PropertyNewValue )
X    {
X	for ( i=0; i<SaveCount; ++i ) {
X	    if ( SaveWaiters[i] == event->xproperty.window )
X		break;
X	}
X	if ( i == SaveCount )
X	    return DISPOSE_DISPATCH;
X
X	--SaveCount;
X	temp = SaveWaiters[i];
X	SaveWaiters[i] = SaveWaiters[SaveCount];
X	SaveWaiters[SaveCount] = temp;
X
X	data = GetWindowProperty(dpy, event->xproperty.window, XA_WM_COMMAND,
X		0L, 1000000L, XA_STRING, 8, &nitems, &remainder);
X	if (data == NULL)
X	    return DISPOSE_DISPATCH;
X
X	/* ignore zero-length properties */
X	if ( nitems > 0 ) {
X	    for ( i=0; i<nitems; ++i )
X		if ( data[i] == '\0' )
X		    data[i] = ' ';
X	    fputs( data, SaveFile );
X	    fputs( " &\n", SaveFile );
X	}
X	XFree(data);
X
X	if ( SaveCount == 0 ) {
X	    XUngrabKeyboard( dpy, CurrentTime );
X	    XUngrabPointer( dpy, CurrentTime );
X	    UninstallInterposer();
X	    TimeoutCancel();
X	    /*
X	     * Now get the non-Xview clients
X	     */
X    	    ListApply(ActiveClientList, sw_send2, SaveFile);
X
X	    fclose(SaveFile);
X
X	    /* set up noticeBox information */
X	    noticeBox.numButtons = 1;
X	    noticeBox.defaultButton = 0;
X	    noticeBox.buttonText = buttons;
X	    noticeBox.numStrings = 1;
X	    noticeBox.stringText = strings;
X	    noticeBox.boxX = -1;
X	    noticeBox.boxY = -1;
X
X	    if (1 == UseNoticeBox(dpy, DefaultScreen(dpy), &noticeBox)) {
X		/* they hit Cancel */
X		/* actually, there's no longer a Cancel button ... */
X		(void) unlink(tempfilename);
X	    } else {
X		/* they hit OK */
X		(void) unlink(backfilename);
X		(void) rename(basefilename, backfilename);
X		(void) rename(tempfilename, basefilename);
X	    }
X    	    VirtualRestoreDesktop(dpy);
X	    /*
X	     * Because the VDM moves now, we need to do a refresh, becuase
X	     * we interposed on all the refresh events.  Need to change
X	     * this when RefreshFunc no longer ignores it's arguments.
X	     */
X	    RefreshFunc(dpy, NULL, NULL, NULL); 
X
X	}
X
X	return DISPOSE_USED;
X    } else {
X	return DISPOSE_DISPATCH;
X    }
X}
X
void *
sw_send(cli,dpy)
Client *cli;
Display	*dpy;
X{
X    if ( cli->protocols & SAVE_YOURSELF ) 
X    {
X	ClientSendProtocol(cli,AtomSaveYourself,LastEventTime);
X	SaveWaiters[SaveCount++] = ClientPane(cli);
X    }
X    return NULL;
X}
X
X/*
X * SaveWorkspaceFunc - called when "Save Workspace" is selected
X * from the root menu.
X */
int
SaveWorkspaceFunc(dpy,winInfo,menu,idx)
X    Display	*dpy;
X    WinGeneric	*winInfo;
X    Menu	*menu;
X    int		idx;
X{
X    struct stat		    statbuf;
X    NoticeBox		    noticeBox;
static    char		    *buttons[] = { "Cancel" };
static    char		    *strings[] = {
X    "Save Workspace cannot be performed, because no",
X    "running applications understand the Save Workspace."
X};
static	  char		    *strings2[] = {
X    "Save Workspace cannot be performed, because",
X    "your home directory is unwritable."
X};
X    
X    sw_makenames();
X
X    SaveFile = fopen(tempfilename, "w");
X    if ( SaveFile == NULL ) {
X	noticeBox.numButtons = 1;
X	noticeBox.defaultButton = 0;
X	noticeBox.buttonText = buttons;
X	noticeBox.numStrings = 2;
X	noticeBox.stringText = strings2;
X	noticeBox.boxX = -1;
X	noticeBox.boxY = -1;
X
X	(void) UseNoticeBox(dpy, DefaultScreen(dpy), &noticeBox );
X	return 0;
X    }
X
X    VirtualSaveDesktop(dpy, 0, 0);
X
X    /* tell all clients to save themselves */
X    SaveCount = 0;
X    ListApply(ActiveClientList, sw_send, dpy);
X
X    /*if ( SaveCount > 0 ) {*/
X	(void) fstat(fileno(SaveFile), &statbuf);
X	(void) fchmod(fileno(SaveFile),
X		      statbuf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH );
X
X	fputs( "#! /bin/sh\n", SaveFile );
X	fprintf( SaveFile, "# %s - OpenWindows initialization script.\n",
X		 INITFILENAME );
X	fputs("# WARNING: This file is automatically generated.\n", SaveFile );
X	fputs("#          Any changes you make here will be lost!\n",
X	      SaveFile );
X
X	XGrabKeyboard( dpy, NoFocusWin, False, GrabModeAsync, GrabModeAsync,
X		       CurrentTime );
X	XGrabPointer( dpy, NoFocusWin, False, ButtonPressMask,
X		      GrabModeAsync, GrabModeAsync, None,
X		      GRV.BusyPointer, CurrentTime );
X
X	InstallInterposer( sw_interposer, (void *)0 );
X	TimeoutRequest(GRV.SaveWorkspaceTimeout,sw_timeout,dpy);
X#ifdef NOTDEF
X    } else {
X	/* set up noticeBox information */
X	noticeBox.numButtons = 1;
X	noticeBox.defaultButton = 0;
X	noticeBox.buttonText = buttons;
X	noticeBox.numStrings = 2;
X	noticeBox.stringText = strings;
X	noticeBox.boxX = -1;
X	noticeBox.boxY = -1;
X
X	(void) UseNoticeBox(dpy, DefaultScreen(dpy), &noticeBox );
X	(void) unlink(tempfilename);
X    }
X#endif
X
X    return 0;
X}
X
MakeSticky(cli, state)
X    Client	*cli;
X    int		state;
X
X{
X    cli->sticky = state;
X    if (cli->sticky) {
X	cli->iconwin->fcore.menu = &IconFullMenuSticky;
X	if (cli->wmDecors->menu_type == MENU_FULL)
X	    if (cli->framewin->fcore.menu == &FrameFullMenuUnsticky)
X	        cli->framewin->fcore.menu = &FrameFullMenuSticky;
X	    else cli->framewin->fcore.menu = &FrameNormMenuSticky;
X    }
X    else {
X	cli->iconwin->fcore.menu = &IconFullMenuUnsticky;
X	if (cli->wmDecors->menu_type == MENU_FULL)
X	    if (cli->framewin->fcore.menu == &FrameFullMenuSticky)
X	        cli->framewin->fcore.menu = &FrameFullMenuUnsticky;
X	    else cli->framewin->fcore.menu = &FrameNormMenuUnsticky;
X    }
X
X    return NULL;
X}
X
X/***************************************************************************
X* Icon menu services
X****************************************************************************/
X
X/*
X * DoIconFullAction -- routine called for each window when a menu action is
X *      selected from the full frame menu.
X */
X/*ARGSUSED*/    /* menu arg will be used later */
void
DoIconFullAction(dpy, winInfo, menu, idx)
Display *dpy;
WinGeneric *winInfo;
Menu    *menu;
int     idx;
X{
X	Client *cli = winInfo->core.client;
X        WinPaneFrame *frameInfo = cli->framewin;
X	WinPane *paneInfo = (WinPane *)frameInfo->fcore.panewin;
X        XEvent clientEvent;
X        Window w;
X
X#define FFA_OPEN                0
X#define FFA_FULLSIZE            1
X#define FFA_PROPERTIES          2
X#define FFA_BACK                3
X#define FFA_REFRESH             4
X#define FFA_QUIT                6
X#define FFA_STICKY		5
X
X
X        switch(idx)
X
X        {
X        case FFA_OPEN:
X                StateIconNorm(cli);
X                break;
X
X        case FFA_FULLSIZE:
X                StateIconNorm(cli);
X                FrameFullSize(frameInfo);
X                break;
X
X        case FFA_PROPERTIES:
X                /* send a ClientMessage of type WM_SHOW_PROPERTIES */
X                clientEvent.xclient.type = ClientMessage;
X                clientEvent.xclient.message_type = AtomShowProperties;
X                clientEvent.xclient.format = 32;
X                clientEvent.xclient.display = dpy;
X                clientEvent.xclient.window = paneInfo->core.self;
X
X                /* send the event */
X                XSendEvent(dpy, clientEvent.xclient.window,
X                           False, NoEventMask, &clientEvent);
X                break;
X
X        case FFA_BACK:
X                /* lower the window */
X		LowerWindow(winInfo->core.self, cli->virtualWindow,
X				cli->sticky, dpy);
X                break;
X
X        case FFA_REFRESH:
X                /* refresh the window.  We do this by creating a window on top
X                 * of the window to refresh and then immediately destroy it
X                 */
X                w = XCreateSimpleWindow(dpy, paneInfo->core.self, 0, 0,
X                                   paneInfo->core.width, paneInfo->core.height, 0,
X                                   (Pixmap) 0, (Pixmap) 0);
X                XMapRaised(dpy, w);
X                XDestroyWindow(dpy, w);
X                XFlush(dpy);
X                break;
X
X        case FFA_QUIT:
X		if (PANEWINOFCLIENT(cli) == VDM)
X		    ExitFunc(dpy, winInfo, NULL, NULL);
X		else ClientKill(cli,True);
X                break;
X	
X	case FFA_STICKY:
X		MakeSticky(cli, ~cli->sticky);
X		if (cli->groupmask == GROUP_LEADER)
X			GroupApply(cli->groupid, MakeSticky,
X				cli->sticky, GROUP_DEPENDENT);
X		break;
X        }
X}
X
X/* IconFullAction -- handle actions from the Icon menus */
int
IconFullAction(dpy, winInfo, menu, idx, pinnedMenu)
Display *dpy;
WinGeneric *winInfo;
Menu    *menu;
int     idx;
Bool    pinnedMenu;
X{
X	Client *cli = NULL;
X
X        if (pinnedMenu || IsSelected(winInfo->core.client))
X                while(cli = EnumSelections(cli))
X		{
X			if (cli->wmState == NormalState)
X				FrameFullAction(dpy, cli->framewin, menu, idx);
X			else
X	                        DoIconFullAction(dpy, cli->iconwin, menu, idx);
X		}
X        else
X        {
X                DoIconFullAction(dpy, winInfo, menu, idx);
X        }
X}
X
X#ifdef NOTDEF
X
X/*
X * ListFullAction is obsolete.  It was used when menu items operated on the
X * selection.  It may someday be useful for Window Controls.
X */
X
X/*
X * ListFullAction --  routine called when a menu action is selected
X *      from the full frame menu. We step through all the selected windows
X *      and perform the required action.
X */
ListFullAction(dpy, winInfo, menu, idx, pinnedMenu)
Display *dpy;
WinInfo *winInfo;
Menu    *menu;
int     idx;
Bool    pinnedMenu;
X{
X        WinInfo *tempInfo = (WinInfo *)0;
X
X        if (pinnedMenu || IsSelected(winInfo))
X                while(tempInfo = EnumSelections(tempInfo))
X                        FrameFullAction(dpy, tempInfo, menu, idx, pinnedMenu);
X        else
X        {
X                FrameFullAction(dpy, winInfo, menu, idx, pinnedMenu);
X        }
X}
X#endif /* NOTDEF */
X
X
X/*
X * FrameFullAction -- routine called for each window when a menu action is
X *      selected from the full frame menu.
X */
XFrameFullAction(dpy, winInfo, menu, idx, pinnedMenu)
Display *dpy;
WinPaneFrame *winInfo;
Menu    *menu;
int     idx;
Bool    pinnedMenu;
X{
X#define FFA_CLOSE               0
X#define FFA_FULLSIZE            1
X#define FFA_PROPERTIES          2
X#define FFA_BACK                3
X#define FFA_REFRESH             4
X#define FFA_QUIT                6
X#define FFA_STICKY		5
X
X	Client *cli = winInfo->core.client;
X
X        switch(idx)
X
X        {
X        case FFA_CLOSE:
X		StateNormIcon(cli);
X                break;
X
X        case FFA_FULLSIZE:
X		(winInfo->normfullsizefunc)(winInfo);
X                break;
X
X        case FFA_PROPERTIES:
X		ClientShowProps(cli);
X                break;
X
X        case FFA_BACK:
X		LowerWindow(winInfo->core.self, cli->virtualWindow,
X				cli->sticky, dpy);
X                break;
X
X        case FFA_REFRESH:
X		ClientRefresh(cli);
X                break;
X
X        case FFA_QUIT:
X		if (PANEWINOFCLIENT(cli) == VDM)
X		    ExitFunc(dpy, winInfo, NULL, NULL);
X		else ClientKill(cli, True);
X                break;
X	
X	case FFA_STICKY:
X		MakeSticky(cli, ~cli->sticky);
X		if (cli->groupmask == GROUP_LEADER)
X			GroupApply(cli->groupid, MakeSticky,
X				cli->sticky, GROUP_DEPENDENT);
X		break;
X        }
X}
X
X
X#ifdef NOTDEF
X/*
X * ListLimAction is obsolete.  It was used when menu items operated on the
X * selection.  It may someday be useful for Window Controls.
X */
X
X/*
X * ListLimAction --  routine called when a menu action is selected
X *      from the limited frame menu. We step through all the selected windows
X *      and perform the required action.
X */
ListLimAction(dpy, winInfo, menu, idx, pinnedMenu)
Display *dpy;
WinInfo *winInfo;
Menu    *menu;
int     idx;
Bool    pinnedMenu;
X{
X        WinInfo *tempInfo = (WinInfo *)0;
X
X        if (pinnedMenu || IsSelected(winInfo))
X                while(tempInfo = EnumSelections(tempInfo))
X                        FrameLimAction(dpy, tempInfo, menu, idx, pinnedMenu);
X        else
X        {
X                ClearSelections(dpy);
X		/* REMIND the timestamp should maybe be more meaningful? */
X                AddSelection(winInfo->core.client, TimeFresh(winInfo));
X                FrameLimAction(dpy, winInfo, menu, idx, pinnedMenu);
X        }
X}
X#endif /* NOTDEF */
X
X
X/*
X * FrameLimAction -- routine called when a menu action is selected
X *      from the limited frame menu.
X */
X/*ARGSUSED*/    /* menu arg will be used later */
XFrameLimAction(dpy, winInfo, menu, idx, pinnedMenu)
Display *dpy;
WinPaneFrame *winInfo;
Menu    *menu;
int     idx;
Bool    pinnedMenu;
X{
X#define FLM_DISMISS             0
X#define FLM_BACK                1
X#define FLM_REFRESH             2
X#define FLM_OWNER               3
X	Client *cli = winInfo->core.client;
X	Client *cliLead;
X
X        switch(idx)
X        {
X        case FLM_DISMISS:
X                /*
X                 * REMIND
X                 * This is probably redundant with DismissAction
X                 */
X                /* send a ClientMessage of type WM_DELETE_WINDOW */
X                if (cli->groupmask == GROUP_DEPENDENT) /* make sure is pop-up */
X                {
X			ClientKill(cli,False);
X                }
X                break;
X
X        case FLM_BACK:
X                /* lower the window */
X		LowerWindow(winInfo->core.self, cli->virtualWindow,
X				cli->sticky, dpy);
X                break;
X
X        case FLM_REFRESH:
X                /* refresh the window.  We do this by creating a window on top
X                 * of the window to refresh and then immediately destroy it
X                 */
X		ClientRefresh(cli);
X                break;
X
X        case FLM_OWNER:
X                /* find the owner of this pop-up */
X		cliLead = GroupLeader(cli->groupid);
X		if ((cliLead != NULL) && ((winInfo = cliLead->framewin) != NULL))
X		{
X		    RaiseWindow(winInfo->core.self, cli->virtualWindow,
X				cli->sticky, dpy);
X                    XFlush(dpy);
X                    FrameFlashTitleBar(winInfo);
X		}
X                break;
X        }
X}
X
X
X#ifdef NOTDEF
X/*
X * ListDismissAction is obsolete.  It was used when menu items operated on the
X * selection.  It may someday be useful for Window Controls.
X */
X
X/*
X * ListDismissAction --  routine called when a menu action is selected
X *      from the dismiss menu. We step through all the selected windows
X *      and perform the required action.
X */
X/*ARGSUSED*/    /* pinnedMenu arg will be used later */
ListDismissAction(dpy, winInfo, menu, idx, pinnedMenu)
Display *dpy;
WinInfo *winInfo;
Menu    *menu;
int     idx;
Bool    pinnedMenu;
X{
X        WinInfo *tempInfo = (WinInfo *)0;
X
X        if (IsSelected(winInfo))
X                while(tempInfo = EnumSelections(tempInfo))
X                        DismissAction(dpy, tempInfo, menu, idx, pinnedMenu);
X        else
X        {
X                ClearSelections(dpy);
X		/* REMIND the timestamp should be more meaningful ? */
X                AddSelection(winInfo->cli, TimeFresh(winInfo));
X                DismissAction(dpy, winInfo, menu, idx, pinnedMenu);
X        }
X}
X#endif /* NOTDEF */
X
X/*
X * DismissAction -- called when Dismiss submenu is entered and an item
X *      selected.
X */
X/*ARGSUSED*/    /* menu arg will be used later */
DismissAction(dpy, winInfo, menu, idx, pinnedMenu)
Display *dpy;
WinPaneFrame *winInfo;
Menu    *menu;
int     idx;
Bool    pinnedMenu;
X{
X	Client *cli = winInfo->core.client;
X
X#define DA_THIS         0
X#define DA_POPUPS       1
X
X        switch(idx)
X        {
X        case DA_THIS:
X                if (cli->groupmask == GROUP_DEPENDENT) /* ensure this is a popup */
X                {
X			ClientKill(cli,False);
X                }
X                break;
X
X        case DA_POPUPS:
X                /*
X                 * Find all pop-ups associated with this window, or with
X                 * this window's leader, and send them a WM_DELETE_WINDOW
X                 * message.
X                 */
X		GroupApply(cli->groupid, ClientKill, (void *)False, GROUP_DEPENDENT);
X                break;
X        }
X}
X
print_quoted_word (fp, s)
X    char *s;
X    FILE *fp;
X{
X    register char *cp;
X    Bool need_quote = False, in_quote = False;
X    char quote_char = '\'', other_quote = '"';
X
X    /*
X     * walk down seeing whether or not we need to quote
X     */  
X    for (cp = s; *cp; cp++) {
X
X        if (! ((isascii(*cp) && isalnum(*cp)) ||
X               (*cp == '-' || *cp == '_' || *cp == '.' || *cp == '+' ||
X                *cp == '/' || *cp == '=' || *cp == ':' || *cp == ','))) {
X            need_quote = True;
X            break;
X        }
X    }    
X
X    /*
X     * write out the string: if we hit a quote, then close any previous quote,
X     * emit the other quote, swap quotes and continue on.
X     */  
X    in_quote = need_quote;
X    if (need_quote) putc (quote_char, fp);
X    for (cp = s; *cp; cp++) {
X        if (*cp == quote_char) {
X            if (in_quote) putc (quote_char, fp);
X            putc (other_quote, fp);
X            {
X                char tmp = other_quote;
X                other_quote = quote_char; quote_char = tmp;
X            }
X
X            in_quote = True;
X        }
X        putc (*cp, fp);
X    }
X    if (in_quote) putc (quote_char, fp);
X}
END_OF_FILE
if test 29838 -ne `wc -c <'services.c'`; then
    echo shar: \"'services.c'\" unpacked with wrong size!
fi
# end of 'services.c'
fi
echo shar: End of archive 13 \(of 16\).
cp /dev/null ark13isdone
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