sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) (04/29/91)
Submitted-by: sdo@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@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@uunet.uu.net argv@ora.com argv@zipcode.com