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, ¬iceBox ) == 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), ¬iceBox);
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), ¬iceBox);
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), ¬iceBox );
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), ¬iceBox)) {
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), ¬iceBox );
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), ¬iceBox );
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