13e747e6dSmrg/*****************************************************************************/
23e747e6dSmrg/*
33e747e6dSmrg
43e747e6dSmrgCopyright 1989, 1998  The Open Group
53e747e6dSmrgCopyright 2005 Hitachi, Ltd.
63e747e6dSmrg
73e747e6dSmrgPermission to use, copy, modify, distribute, and sell this software and its
83e747e6dSmrgdocumentation for any purpose is hereby granted without fee, provided that
93e747e6dSmrgthe above copyright notice appear in all copies and that both that
103e747e6dSmrgcopyright notice and this permission notice appear in supporting
113e747e6dSmrgdocumentation.
123e747e6dSmrg
133e747e6dSmrgThe above copyright notice and this permission notice shall be included in
143e747e6dSmrgall copies or substantial portions of the Software.
153e747e6dSmrg
163e747e6dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
173e747e6dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
183e747e6dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
193e747e6dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
203e747e6dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
213e747e6dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
223e747e6dSmrg
233e747e6dSmrgExcept as contained in this notice, the name of The Open Group shall not be
243e747e6dSmrgused in advertising or otherwise to promote the sale, use or other dealings
253e747e6dSmrgin this Software without prior written authorization from The Open Group.
263e747e6dSmrg
273e747e6dSmrg*/
283e747e6dSmrg/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
293e747e6dSmrg/**                          Salt Lake City, Utah                           **/
303e747e6dSmrg/**                        Cambridge, Massachusetts                         **/
313e747e6dSmrg/**                                                                         **/
323e747e6dSmrg/**                           All Rights Reserved                           **/
333e747e6dSmrg/**                                                                         **/
343e747e6dSmrg/**    Permission to use, copy, modify, and distribute this software and    **/
353e747e6dSmrg/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
363e747e6dSmrg/**    granted, provided that the above copyright notice appear  in  all    **/
373e747e6dSmrg/**    copies and that both  that  copyright  notice  and  this  permis-    **/
383e747e6dSmrg/**    sion  notice appear in supporting  documentation,  and  that  the    **/
393e747e6dSmrg/**    name of Evans & Sutherland not be used in advertising    **/
403e747e6dSmrg/**    in publicity pertaining to distribution of the  software  without    **/
413e747e6dSmrg/**    specific, written prior permission.                                  **/
423e747e6dSmrg/**                                                                         **/
433e747e6dSmrg/**    EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD    **/
443e747e6dSmrg/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
453e747e6dSmrg/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND    **/
463e747e6dSmrg/**    BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
473e747e6dSmrg/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
483e747e6dSmrg/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
493e747e6dSmrg/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
503e747e6dSmrg/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
513e747e6dSmrg/*****************************************************************************/
523e747e6dSmrg
533e747e6dSmrg/***********************************************************************
543e747e6dSmrg *
553e747e6dSmrg * twm - "Tom's Window Manager"
563e747e6dSmrg *
573e747e6dSmrg * 27-Oct-1987 Thomas E. LaStrange    File created
583e747e6dSmrg * 10-Oct-1990 David M. Sternlicht    Storing saved colors on root
593e747e6dSmrg * 19-Feb-2005 Julien Lafon           Handle print screens for unified Xserver
603e747e6dSmrg ***********************************************************************/
613e747e6dSmrg
623e747e6dSmrg#include <stdio.h>
633e747e6dSmrg#include <signal.h>
643e747e6dSmrg#include <fcntl.h>
65f66df612Smrg#include <stdarg.h>
66f66df612Smrg
673e747e6dSmrg#include "twm.h"
683e747e6dSmrg#include "iconmgr.h"
693e747e6dSmrg#include "add_window.h"
703e747e6dSmrg#include "gc.h"
713e747e6dSmrg#include "parse.h"
723e747e6dSmrg#include "menus.h"
733e747e6dSmrg#include "events.h"
743e747e6dSmrg#include "util.h"
753e747e6dSmrg#include "screen.h"
763e747e6dSmrg#include "parse.h"
773e747e6dSmrg#include "session.h"
78f66df612Smrg
793e747e6dSmrg#include <X11/Xproto.h>
803e747e6dSmrg#include <X11/Xatom.h>
813e747e6dSmrg#include <X11/SM/SMlib.h>
823e747e6dSmrg#include <X11/Xmu/Error.h>
833e747e6dSmrg#include <X11/extensions/sync.h>
843e747e6dSmrg#include <X11/Xlocale.h>
85f66df612Smrg
86f66df612Smrg#ifdef HAVE_XRANDR
87f66df612Smrg#include <X11/extensions/Xrandr.h>
88f66df612Smrg#endif
893e747e6dSmrg
90f66df612Smrgstatic void InitVariables(void);
91c2535118Smrg
926d8e82c3Smrgstatic XtSignalId si;
933e747e6dSmrg
94f66df612SmrgDisplay *dpy = NULL;            /* which display are we talking to */
95f66df612SmrgWindow ResizeWindow;            /* the window we are resizing */
963e747e6dSmrg
97f66df612Smrgint NumScreens;                 /* number of screens in ScreenList */
98f66df612Smrgint HasShape;                   /* server supports shape extension? */
99f66df612Smrg
100f66df612Smrg#ifdef HAVE_XRANDR
101f66df612Smrgint HasXrandr;                  /* server supports Xrandr extension? */
102f66df612Smrgint XrandrEventBase, XrandrErrorBase;
103f66df612Smrg#endif
104f66df612Smrg
1053e747e6dSmrgint ShapeEventBase, ShapeErrorBase;
106f66df612Smrgint HasSync;                    /* server supports SYNC extension? */
1073e747e6dSmrgint SyncEventBase, SyncErrorBase;
108f66df612SmrgScreenInfo **ScreenList;        /* structures for each screen */
109f66df612SmrgScreenInfo *Scr = NULL;         /* the cur and prev screens */
110f66df612Smrgint PreviousScreen;             /* last screen that we were on */
111f66df612Smrgint message_level = 1;          /* controls error messages */
112f66df612Smrgstatic int RedirectError;       /* TRUE ==> another window manager running */
113f66df612Smrgstatic int TwmErrorHandler(Display *dpy, XErrorEvent *event);   /* for setting RedirectError */
114f66df612Smrgstatic int CatchRedirectError(Display *dpy, XErrorEvent *event);        /* for everything else */
115c2535118Smrgstatic void sigHandler(int);
116f66df612Smrgchar Info[INFO_LINES][INFO_SIZE];       /* info strings to print */
1173e747e6dSmrgint InfoLines;
1183e747e6dSmrg
119f66df612SmrgCursor UpperLeftCursor;         /* upper Left corner cursor */
1203e747e6dSmrgCursor RightButt;
1213e747e6dSmrgCursor MiddleButt;
1223e747e6dSmrgCursor LeftButt;
1233e747e6dSmrg
124f66df612SmrgXContext TwmContext;            /* context for twm windows */
125f66df612SmrgXContext MenuContext;           /* context for all menu windows */
126f66df612SmrgXContext IconManagerContext;    /* context for all window list windows */
127f66df612SmrgXContext ScreenContext;         /* context to get screen data */
128f66df612SmrgXContext ColormapContext;       /* context for colormap operations */
1293e747e6dSmrg
130f66df612SmrgXClassHint NoClass;             /* for applications with no class */
1313e747e6dSmrg
1323e747e6dSmrgXGCValues Gcv;
1333e747e6dSmrg
134f66df612Smrgconst char *Home;               /* the HOME environment variable */
135f66df612Smrgint HomeLen;                    /* length of Home */
136f66df612Smrgint ParseError;                 /* error parsing the .twmrc file */
1373e747e6dSmrg
138f66df612Smrgint HandlingEvents = FALSE;     /* are we handling events yet? */
1393e747e6dSmrg
1403e747e6dSmrgchar *ProgramName;
1413e747e6dSmrgint Argc;
1423e747e6dSmrgchar **Argv;
1433e747e6dSmrg
144f66df612SmrgBool RestartPreviousState = False;      /* try to restart in previous state */
1453e747e6dSmrg
146c2535118Smrgstatic unsigned long black, white;
1473e747e6dSmrg
1483e747e6dSmrgAtom TwmAtoms[11];
1493e747e6dSmrg
150f66df612SmrgBool use_fontset;               /* use XFontSet-related functions or not */
1513e747e6dSmrg
1523e747e6dSmrg/* don't change the order of these strings */
1536d8e82c3Smrgstatic const char *atom_names[11] = {
1543e747e6dSmrg    "_MIT_PRIORITY_COLORS",
1553e747e6dSmrg    "WM_CHANGE_STATE",
1563e747e6dSmrg    "WM_STATE",
1573e747e6dSmrg    "WM_COLORMAP_WINDOWS",
1583e747e6dSmrg    "WM_PROTOCOLS",
1593e747e6dSmrg    "WM_TAKE_FOCUS",
1603e747e6dSmrg    "WM_SAVE_YOURSELF",
1613e747e6dSmrg    "WM_DELETE_WINDOW",
1623e747e6dSmrg    "SM_CLIENT_ID",
1633e747e6dSmrg    "WM_CLIENT_LEADER",
1643e747e6dSmrg    "WM_WINDOW_ROLE"
1653e747e6dSmrg};
1663e747e6dSmrg
1676d8e82c3Smrgstatic _X_NORETURN void
168f66df612Smrgusage(void)
169f66df612Smrg{
170f66df612Smrg    fprintf(stderr, "usage:  %s [-display dpy] [-f file] [-s] [-q] [-v] [-V]"
171f66df612Smrg            " [-clientId id] [-restore file]\n", ProgramName);
172f66df612Smrg    exit(EXIT_FAILURE);
173f66df612Smrg}
174f66df612Smrg
175f66df612Smrgstatic Bool
176f66df612Smrgbrief_opt(const char *param, const char *option)
177f66df612Smrg{
178f66df612Smrg    size_t have = strlen(++param);
179f66df612Smrg    size_t want = strlen(option);
180f66df612Smrg    Bool result = False;
181f66df612Smrg
182f66df612Smrg    if (have <= want) {
183f66df612Smrg        if (!strncmp(param, option, have))
184f66df612Smrg            result = True;
185f66df612Smrg    }
186f66df612Smrg    return result;
187f66df612Smrg}
1883e747e6dSmrg
1893e747e6dSmrg/***********************************************************************
1903e747e6dSmrg *
1913e747e6dSmrg *  Procedure:
192f66df612Smrg *      main - start of twm
1933e747e6dSmrg *
1943e747e6dSmrg ***********************************************************************
1953e747e6dSmrg */
1963e747e6dSmrg
1973e747e6dSmrgint
1983e747e6dSmrgmain(int argc, char *argv[])
1993e747e6dSmrg{
2003e747e6dSmrg    Window root, parent, *children;
2013e747e6dSmrg    unsigned int nchildren;
2023e747e6dSmrg    int i, j;
2033e747e6dSmrg    char *display_name = NULL;
204f66df612Smrg    unsigned long valuemask;    /* mask for create windows */
205f66df612Smrg    XSetWindowAttributes attributes;    /* attributes for create windows */
2063e747e6dSmrg    int numManaged, firstscrn, lastscrn, scrnum;
2073e747e6dSmrg    int zero = 0;
2083e747e6dSmrg    char *restore_filename = NULL;
2093e747e6dSmrg    char *client_id = NULL;
2103e747e6dSmrg    char *loc;
2116d8e82c3Smrg    int MultiScreen = TRUE;         /* try for more than one screen? */
2126d8e82c3Smrg    char *InitFile = NULL;
2136d8e82c3Smrg    XtAppContext appContext;        /* Xt application context */
2143e747e6dSmrg
2153e747e6dSmrg    ProgramName = argv[0];
2163e747e6dSmrg    Argc = argc;
2173e747e6dSmrg    Argv = argv;
2183e747e6dSmrg
2193e747e6dSmrg    for (i = 1; i < argc; i++) {
220f66df612Smrg        if (argv[i][0] == '-') {
221f66df612Smrg            switch (argv[i][1]) {
222f66df612Smrg            case 'V':
223f66df612Smrg                printf("%s %s\n", APP_NAME, APP_VERSION);
224f66df612Smrg                exit(EXIT_SUCCESS);
225f66df612Smrg            case 'd':          /* -display dpy */
226f66df612Smrg                if (!brief_opt(argv[i], "display"))
227f66df612Smrg                    usage();
228f66df612Smrg                if (++i >= argc)
229f66df612Smrg                    usage();
230f66df612Smrg                display_name = argv[i];
231f66df612Smrg                continue;
232f66df612Smrg            case 's':          /* -single */
233f66df612Smrg                if (!brief_opt(argv[i], "single"))
234f66df612Smrg                    usage();
235f66df612Smrg                MultiScreen = FALSE;
236f66df612Smrg                continue;
237f66df612Smrg            case 'f':          /* -file twmrcfilename */
238f66df612Smrg                if (!brief_opt(argv[i], "file"))
239f66df612Smrg                    usage();
240f66df612Smrg                if (++i >= argc)
241f66df612Smrg                    usage();
242f66df612Smrg                InitFile = argv[i];
243f66df612Smrg                continue;
244f66df612Smrg            case 'v':          /* -verbose */
245f66df612Smrg                if (!brief_opt(argv[i], "verbose"))
246f66df612Smrg                    usage();
247f66df612Smrg                message_level++;
248f66df612Smrg                continue;
249f66df612Smrg            case 'c':          /* -clientId */
250f66df612Smrg                if (!brief_opt(argv[i], "clientId"))
251f66df612Smrg                    usage();
252f66df612Smrg                if (++i >= argc)
253f66df612Smrg                    usage();
254f66df612Smrg                client_id = argv[i];
255f66df612Smrg                continue;
256f66df612Smrg            case 'r':          /* -restore */
257f66df612Smrg                if (!brief_opt(argv[i], "restore"))
258f66df612Smrg                    usage();
259f66df612Smrg                if (++i >= argc)
260f66df612Smrg                    usage();
261f66df612Smrg                restore_filename = argv[i];
262f66df612Smrg                continue;
263f66df612Smrg            case 'q':          /* -quiet */
264f66df612Smrg                if (!brief_opt(argv[i], "quiet"))
265f66df612Smrg                    usage();
266f66df612Smrg                --message_level;
267f66df612Smrg                continue;
268f66df612Smrg            }
269f66df612Smrg        }
270f66df612Smrg        usage();
2713e747e6dSmrg    }
2723e747e6dSmrg
2733e747e6dSmrg    loc = setlocale(LC_ALL, "");
2743e747e6dSmrg    if (!loc || !strcmp(loc, "C") || !strcmp(loc, "POSIX") ||
275f66df612Smrg        !XSupportsLocale()) {
276f66df612Smrg        use_fontset = False;
277f66df612Smrg    }
278f66df612Smrg    else {
279f66df612Smrg        use_fontset = True;
2803e747e6dSmrg    }
2813e747e6dSmrg
2823e747e6dSmrg#define newhandler(sig) \
2833e747e6dSmrg    if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, sigHandler)
2843e747e6dSmrg
285f66df612Smrg    newhandler(SIGINT);
286f66df612Smrg    newhandler(SIGHUP);
287f66df612Smrg    newhandler(SIGQUIT);
288f66df612Smrg    newhandler(SIGTERM);
2893e747e6dSmrg
2903e747e6dSmrg#undef newhandler
2913e747e6dSmrg
2923e747e6dSmrg    Home = getenv("HOME");
2933e747e6dSmrg    if (Home != NULL) {
294f66df612Smrg        char *temp_p;
2953e747e6dSmrg
296f66df612Smrg        /*
297f66df612Smrg         * Make a copy of Home because the string returned by getenv() can be
298f66df612Smrg         * overwritten by some POSIX.1 and ANSI-C implementations of getenv()
299f66df612Smrg         * when further calls to getenv() are made
300f66df612Smrg         */
3013e747e6dSmrg
302f66df612Smrg        temp_p = strdup(Home);
303f66df612Smrg        Home = temp_p;
3043e747e6dSmrg    }
3053e747e6dSmrg
3063e747e6dSmrg    if (Home == NULL)
307f66df612Smrg        Home = "./";
3083e747e6dSmrg
309f66df612Smrg    HomeLen = (int) strlen(Home);
3103e747e6dSmrg
3113e747e6dSmrg    NoClass.res_name = NoName;
3123e747e6dSmrg    NoClass.res_class = NoName;
3133e747e6dSmrg
314f66df612Smrg    XtToolkitInitialize();
315f66df612Smrg    appContext = XtCreateApplicationContext();
3163e747e6dSmrg
3173e747e6dSmrg    si = XtAppAddSignal(appContext, Done, NULL);
318ffd25bcaSmrg
3196d8e82c3Smrg    if (!(dpy = XtOpenDisplay(appContext, display_name, APP_NAME, APP_CLASS,
320f66df612Smrg                              NULL, 0, &zero, NULL))) {
321f66df612Smrg        twmError("unable to open display \"%s\"", XDisplayName(display_name));
3223e747e6dSmrg    }
3233e747e6dSmrg
3243e747e6dSmrg    if (fcntl(ConnectionNumber(dpy), F_SETFD, 1) == -1) {
325f66df612Smrg        twmError("unable to mark display connection as close-on-exec");
3263e747e6dSmrg    }
3273e747e6dSmrg
3283e747e6dSmrg    if (restore_filename)
329f66df612Smrg        ReadWinConfigFile(restore_filename);
3303e747e6dSmrg
331f66df612Smrg    HasShape = XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase);
332f66df612Smrg    HasSync = XSyncQueryExtension(dpy, &SyncEventBase, &SyncErrorBase);
333f66df612Smrg#ifdef HAVE_XRANDR
334f66df612Smrg    HasXrandr = XRRQueryExtension(dpy, &XrandrEventBase, &XrandrErrorBase);
335f66df612Smrg#endif
3363e747e6dSmrg    TwmContext = XUniqueContext();
3373e747e6dSmrg    MenuContext = XUniqueContext();
3383e747e6dSmrg    IconManagerContext = XUniqueContext();
3393e747e6dSmrg    ScreenContext = XUniqueContext();
3403e747e6dSmrg    ColormapContext = XUniqueContext();
3413e747e6dSmrg
3426d8e82c3Smrg    (void) XInternAtoms(dpy, (char **) atom_names,
3436d8e82c3Smrg                        sizeof TwmAtoms / sizeof TwmAtoms[0],
344f66df612Smrg                        False, TwmAtoms);
3453e747e6dSmrg
3463e747e6dSmrg    /* Set up the per-screen global information. */
3473e747e6dSmrg
3483e747e6dSmrg    NumScreens = ScreenCount(dpy);
3493e747e6dSmrg
350f66df612Smrg    if (MultiScreen) {
351f66df612Smrg        firstscrn = 0;
352f66df612Smrg        lastscrn = NumScreens - 1;
3533e747e6dSmrg    }
354f66df612Smrg    else {
355f66df612Smrg        firstscrn = lastscrn = DefaultScreen(dpy);
3563e747e6dSmrg    }
3573e747e6dSmrg
3583e747e6dSmrg    InfoLines = 0;
3593e747e6dSmrg
3603e747e6dSmrg    /* for simplicity, always allocate NumScreens ScreenInfo struct pointers */
3616d8e82c3Smrg    ScreenList = (ScreenInfo **)
3626d8e82c3Smrg        calloc((size_t) NumScreens, sizeof(ScreenInfo *));
363f66df612Smrg    if (ScreenList == NULL) {
364f66df612Smrg        twmError("Unable to allocate memory for screen list, exiting");
3653e747e6dSmrg    }
3663e747e6dSmrg    numManaged = 0;
3673e747e6dSmrg    PreviousScreen = DefaultScreen(dpy);
368f66df612Smrg    for (scrnum = firstscrn; scrnum <= lastscrn; scrnum++) {
3696d8e82c3Smrg        Bool FirstScreen = scrnum == firstscrn;
3703e747e6dSmrg
3713e747e6dSmrg        /* Make sure property priority colors is empty */
372f66df612Smrg        XChangeProperty(dpy, RootWindow(dpy, scrnum), _XA_MIT_PRIORITY_COLORS,
373f66df612Smrg                        XA_CARDINAL, 32, PropModeReplace, NULL, 0);
374f66df612Smrg        RedirectError = FALSE;
375f66df612Smrg        XSetErrorHandler(CatchRedirectError);
376f66df612Smrg        XSelectInput(dpy, RootWindow(dpy, scrnum),
377f66df612Smrg                     ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
378f66df612Smrg                     SubstructureRedirectMask | KeyPressMask |
379f66df612Smrg                     ButtonPressMask | ButtonReleaseMask);
380f66df612Smrg        XSync(dpy, 0);
381f66df612Smrg        XSetErrorHandler(TwmErrorHandler);
382f66df612Smrg
383f66df612Smrg        if (RedirectError) {
384f66df612Smrg            if (MultiScreen && NumScreens > 0) {
385f66df612Smrg                twmWarning("another window manager is already running."
386f66df612Smrg                           " on screen %d?\n", scrnum);
387f66df612Smrg            }
388f66df612Smrg            else {
389f66df612Smrg                twmWarning("another window manager is already running.");
390f66df612Smrg            }
391f66df612Smrg            continue;
392f66df612Smrg        }
393f66df612Smrg
394f66df612Smrg        numManaged++;
395f66df612Smrg
396f66df612Smrg        /* Note:  ScreenInfo struct is calloc'ed to initialize to zero. */
3976d8e82c3Smrg        Scr = ScreenList[scrnum] = (ScreenInfo *) calloc(1, sizeof(ScreenInfo));
398f66df612Smrg        if (Scr == NULL) {
399f66df612Smrg            twmWarning
400f66df612Smrg                ("unable to allocate memory for ScreenInfo structure for screen %d.",
401f66df612Smrg                 scrnum);
402f66df612Smrg            continue;
403f66df612Smrg        }
404f66df612Smrg
405f66df612Smrg        /* initialize list pointers, remember to put an initialization
406f66df612Smrg         * in InitVariables also
407f66df612Smrg         */
408f66df612Smrg        Scr->BorderColorL = NULL;
409f66df612Smrg        Scr->IconBorderColorL = NULL;
410f66df612Smrg        Scr->BorderTileForegroundL = NULL;
411f66df612Smrg        Scr->BorderTileBackgroundL = NULL;
412f66df612Smrg        Scr->TitleForegroundL = NULL;
413f66df612Smrg        Scr->TitleBackgroundL = NULL;
414f66df612Smrg        Scr->IconForegroundL = NULL;
415f66df612Smrg        Scr->IconBackgroundL = NULL;
416f66df612Smrg        Scr->NoTitle = NULL;
417f66df612Smrg        Scr->MakeTitle = NULL;
418f66df612Smrg        Scr->AutoRaise = NULL;
419f66df612Smrg        Scr->IconNames = NULL;
420f66df612Smrg        Scr->NoHighlight = NULL;
421f66df612Smrg        Scr->NoStackModeL = NULL;
422f66df612Smrg        Scr->NoTitleHighlight = NULL;
423f66df612Smrg        Scr->DontIconify = NULL;
424f66df612Smrg        Scr->IconMgrNoShow = NULL;
425f66df612Smrg        Scr->IconMgrShow = NULL;
426f66df612Smrg        Scr->IconifyByUn = NULL;
427f66df612Smrg        Scr->IconManagerFL = NULL;
428f66df612Smrg        Scr->IconManagerBL = NULL;
429f66df612Smrg        Scr->IconMgrs = NULL;
430f66df612Smrg        Scr->StartIconified = NULL;
431f66df612Smrg        Scr->SqueezeTitleL = NULL;
432f66df612Smrg        Scr->DontSqueezeTitleL = NULL;
433f66df612Smrg        Scr->WindowRingL = NULL;
434f66df612Smrg        Scr->WarpCursorL = NULL;
435f66df612Smrg        /* remember to put an initialization in InitVariables also
436f66df612Smrg         */
437f66df612Smrg
438f66df612Smrg        Scr->screen = scrnum;
439f66df612Smrg        Scr->d_depth = DefaultDepth(dpy, scrnum);
440f66df612Smrg        Scr->d_visual = DefaultVisual(dpy, scrnum);
441f66df612Smrg        Scr->Root = RootWindow(dpy, scrnum);
442f66df612Smrg        XSaveContext(dpy, Scr->Root, ScreenContext, (XPointer) Scr);
443f66df612Smrg
444f66df612Smrg        Scr->TwmRoot.cmaps.number_cwins = 1;
4456d8e82c3Smrg        Scr->TwmRoot.cmaps.cwins = (ColormapWindow **)
4466d8e82c3Smrg            malloc(sizeof(ColormapWindow *));
447f66df612Smrg        Scr->TwmRoot.cmaps.cwins[0] =
448f66df612Smrg            CreateColormapWindow(Scr->Root, True, False);
449f66df612Smrg        Scr->TwmRoot.cmaps.cwins[0]->visibility = VisibilityPartiallyObscured;
450f66df612Smrg
451f66df612Smrg        Scr->cmapInfo.cmaps = NULL;
452f66df612Smrg        Scr->cmapInfo.maxCmaps =
453f66df612Smrg            MaxCmapsOfScreen(ScreenOfDisplay(dpy, Scr->screen));
454f66df612Smrg        Scr->cmapInfo.root_pushes = 0;
455f66df612Smrg        InstallWindowColormaps(0, &Scr->TwmRoot);
456f66df612Smrg
457f66df612Smrg        Scr->StdCmapInfo.head = Scr->StdCmapInfo.tail =
458f66df612Smrg            Scr->StdCmapInfo.mru = NULL;
459f66df612Smrg        Scr->StdCmapInfo.mruindex = 0;
460f66df612Smrg        LocateStandardColormaps();
461f66df612Smrg
462f66df612Smrg        Scr->TBInfo.nleft = Scr->TBInfo.nright = 0;
463f66df612Smrg        Scr->TBInfo.head = NULL;
464f66df612Smrg        Scr->TBInfo.border = 1;
465f66df612Smrg        Scr->TBInfo.width = 0;
466f66df612Smrg        Scr->TBInfo.leftx = 0;
467f66df612Smrg        Scr->TBInfo.titlex = 0;
468f66df612Smrg
469f66df612Smrg        Scr->MyDisplayWidth = DisplayWidth(dpy, scrnum);
470f66df612Smrg        Scr->MyDisplayHeight = DisplayHeight(dpy, scrnum);
471f66df612Smrg        Scr->MaxWindowWidth = 32767 - Scr->MyDisplayWidth;
472f66df612Smrg        Scr->MaxWindowHeight = 32767 - Scr->MyDisplayHeight;
473f66df612Smrg
474f66df612Smrg        Scr->XORvalue = (((unsigned long) 1) << Scr->d_depth) - 1;
475f66df612Smrg
476f66df612Smrg        if (DisplayCells(dpy, scrnum) < 3)
477f66df612Smrg            Scr->Monochrome = MONOCHROME;
4786d8e82c3Smrg#if defined(__cplusplus) || defined(c_plusplus)
4796d8e82c3Smrg        else if (DefaultVisual(dpy, scrnum)->c_class == GrayScale)
4806d8e82c3Smrg#else
481f66df612Smrg        else if (DefaultVisual(dpy, scrnum)->class == GrayScale)
4826d8e82c3Smrg#endif
483f66df612Smrg            Scr->Monochrome = GRAYSCALE;
484f66df612Smrg        else
485f66df612Smrg            Scr->Monochrome = COLOR;
486f66df612Smrg
487f66df612Smrg        /* setup default colors */
488f66df612Smrg        Scr->FirstTime = TRUE;
489f66df612Smrg        GetColor(Scr->Monochrome, &black, "black");
490f66df612Smrg        Scr->Black = black;
491f66df612Smrg        GetColor(Scr->Monochrome, &white, "white");
492f66df612Smrg        Scr->White = white;
493f66df612Smrg
494f66df612Smrg        if (FirstScreen) {
495f66df612Smrg            SetFocus((TwmWindow *) NULL, CurrentTime);
496f66df612Smrg
497f66df612Smrg            /* define cursors */
498f66df612Smrg
499f66df612Smrg            NewFontCursor(&UpperLeftCursor, "top_left_corner");
500f66df612Smrg            NewFontCursor(&RightButt, "rightbutton");
501f66df612Smrg            NewFontCursor(&LeftButt, "leftbutton");
502f66df612Smrg            NewFontCursor(&MiddleButt, "middlebutton");
503f66df612Smrg        }
504f66df612Smrg
505f66df612Smrg        Scr->iconmgr.x = 0;
506f66df612Smrg        Scr->iconmgr.y = 0;
507f66df612Smrg        Scr->iconmgr.width = 150;
508f66df612Smrg        Scr->iconmgr.height = 5;
509f66df612Smrg        Scr->iconmgr.next = NULL;
510f66df612Smrg        Scr->iconmgr.prev = NULL;
511f66df612Smrg        Scr->iconmgr.lasti = &(Scr->iconmgr);
512f66df612Smrg        Scr->iconmgr.first = NULL;
513f66df612Smrg        Scr->iconmgr.last = NULL;
514f66df612Smrg        Scr->iconmgr.active = NULL;
515f66df612Smrg        Scr->iconmgr.scr = Scr;
516f66df612Smrg        Scr->iconmgr.columns = 1;
517f66df612Smrg        Scr->iconmgr.count = 0;
518f66df612Smrg        Scr->iconmgr.name = "TWM";
519f66df612Smrg        Scr->iconmgr.icon_name = "Icons";
520f66df612Smrg
521f66df612Smrg        Scr->IconDirectory = NULL;
522f66df612Smrg
523f66df612Smrg        Scr->siconifyPm = None;
524f66df612Smrg        Scr->pullPm = None;
525f66df612Smrg        Scr->hilitePm = None;
526f66df612Smrg        Scr->tbpm.xlogo = None;
527f66df612Smrg        Scr->tbpm.resize = None;
528f66df612Smrg        Scr->tbpm.question = None;
529f66df612Smrg        Scr->tbpm.menu = None;
5306d8e82c3Smrg        Scr->tbpm.remove = None;
531f66df612Smrg
532f66df612Smrg        InitVariables();
533f66df612Smrg        InitMenus();
5346d8e82c3Smrg        if (FirstScreen)
5356d8e82c3Smrg            InitMenusFirst();
536f66df612Smrg
537f66df612Smrg        /* Parse it once for each screen. */
538f66df612Smrg        ParseTwmrc(InitFile);
539f66df612Smrg        assign_var_savecolor(); /* storing pixels for twmrc "entities" */
540f66df612Smrg        if (Scr->SqueezeTitle == -1)
541f66df612Smrg            Scr->SqueezeTitle = FALSE;
542f66df612Smrg        if (!Scr->HaveFonts)
543f66df612Smrg            CreateFonts();
544f66df612Smrg        CreateGCs();
545f66df612Smrg        MakeMenus();
546f66df612Smrg
547f66df612Smrg        Scr->TitleBarFont.y += Scr->FramePadding;
548f66df612Smrg        Scr->TitleHeight = Scr->TitleBarFont.height + Scr->FramePadding * 2;
549f66df612Smrg        /* make title height be odd so buttons look nice and centered */
550f66df612Smrg        if (!(Scr->TitleHeight & 1))
551f66df612Smrg            Scr->TitleHeight++;
552f66df612Smrg
553f66df612Smrg        InitTitlebarButtons();  /* menus are now loaded! */
554f66df612Smrg
555f66df612Smrg        XGrabServer(dpy);
556f66df612Smrg        XSync(dpy, 0);
557f66df612Smrg
558f66df612Smrg        XQueryTree(dpy, Scr->Root, &root, &parent, &children, &nchildren);
559f66df612Smrg        CreateIconManagers();
560f66df612Smrg        if (!Scr->NoIconManagers)
561f66df612Smrg            Scr->iconmgr.twm_win->icon = TRUE;
562f66df612Smrg
563f66df612Smrg        /*
564f66df612Smrg         * weed out icon windows
565f66df612Smrg         */
566f66df612Smrg        for (i = 0; (unsigned) i < nchildren; i++) {
567f66df612Smrg            if (children[i]) {
568f66df612Smrg                XWMHints *wmhintsp = XGetWMHints(dpy, children[i]);
569f66df612Smrg
570f66df612Smrg                if (wmhintsp) {
571f66df612Smrg                    if (wmhintsp->flags & IconWindowHint) {
572f66df612Smrg                        for (j = 0; (unsigned) j < nchildren; j++) {
573f66df612Smrg                            if (children[j] == wmhintsp->icon_window) {
574f66df612Smrg                                children[j] = None;
575f66df612Smrg                                break;
576f66df612Smrg                            }
577f66df612Smrg                        }
578f66df612Smrg                    }
579f66df612Smrg                    XFree(wmhintsp);
580f66df612Smrg                }
581f66df612Smrg            }
582f66df612Smrg        }
583f66df612Smrg
584f66df612Smrg        /*
585f66df612Smrg         * map all of the non-override windows
586f66df612Smrg         */
587f66df612Smrg        for (i = 0; (unsigned) i < nchildren; i++) {
588f66df612Smrg            if (children[i] && MappedNotOverride(children[i])) {
589f66df612Smrg                XUnmapWindow(dpy, children[i]);
590f66df612Smrg                SimulateMapRequest(children[i]);
591f66df612Smrg            }
592f66df612Smrg        }
593f66df612Smrg
594f66df612Smrg        if (Scr->ShowIconManager && !Scr->NoIconManagers) {
595f66df612Smrg            Scr->iconmgr.twm_win->icon = FALSE;
596f66df612Smrg            if (Scr->iconmgr.count) {
597f66df612Smrg                SetMapStateProp(Scr->iconmgr.twm_win, NormalState);
598f66df612Smrg                XMapWindow(dpy, Scr->iconmgr.w);
599f66df612Smrg                XMapWindow(dpy, Scr->iconmgr.twm_win->frame);
600f66df612Smrg            }
601f66df612Smrg        }
602f66df612Smrg
603f66df612Smrg        attributes.border_pixel = Scr->DefaultC.fore;
604f66df612Smrg        attributes.background_pixel = Scr->DefaultC.back;
605f66df612Smrg        attributes.event_mask = (ExposureMask | ButtonPressMask |
606f66df612Smrg                                 KeyPressMask | ButtonReleaseMask);
607f66df612Smrg        attributes.backing_store = NotUseful;
608f66df612Smrg        attributes.cursor = XCreateFontCursor(dpy, XC_hand2);
609f66df612Smrg        valuemask = (CWBorderPixel | CWBackPixel | CWEventMask |
610f66df612Smrg                     CWBackingStore | CWCursor);
611f66df612Smrg        Scr->InfoWindow = XCreateWindow(dpy, Scr->Root, 0, 0,
612f66df612Smrg                                        (unsigned int) 5, (unsigned int) 5,
613f66df612Smrg                                        (unsigned int) BW, 0,
614f66df612Smrg                                        (unsigned int) CopyFromParent,
615f66df612Smrg                                        (Visual *) CopyFromParent,
616f66df612Smrg                                        valuemask, &attributes);
617f66df612Smrg
618f66df612Smrg        Scr->SizeStringWidth = MyFont_TextWidth(&Scr->SizeFont,
619f66df612Smrg                                                " 8888 x 8888 ", 13);
620f66df612Smrg        valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity);
621f66df612Smrg        attributes.bit_gravity = NorthWestGravity;
622f66df612Smrg        Scr->SizeWindow = XCreateWindow(dpy, Scr->Root, 0, 0,
623f66df612Smrg                                        (unsigned int) Scr->SizeStringWidth,
624f66df612Smrg                                        (unsigned int) (Scr->SizeFont.height +
625f66df612Smrg                                                        SIZE_VINDENT * 2),
626f66df612Smrg                                        (unsigned int) BW, 0,
627f66df612Smrg                                        (unsigned int) CopyFromParent,
628f66df612Smrg                                        (Visual *) CopyFromParent,
629f66df612Smrg                                        valuemask, &attributes);
630f66df612Smrg
631f66df612Smrg        XUngrabServer(dpy);
632f66df612Smrg
633f66df612Smrg        Scr->FirstTime = FALSE;
634f66df612Smrg    }                           /* for */
6353e747e6dSmrg
6363e747e6dSmrg    if (numManaged == 0) {
637f66df612Smrg        if (MultiScreen && NumScreens > 0) {
6386d8e82c3Smrg            twmError("unable to find any unmanaged video screens.\n");
639f66df612Smrg        }
640f66df612Smrg        exit(EXIT_FAILURE);
6413e747e6dSmrg    }
6423e747e6dSmrg
6436d8e82c3Smrg    (void) ConnectToSessionManager(client_id, appContext);
6443e747e6dSmrg
6453e747e6dSmrg    RestartPreviousState = False;
6463e747e6dSmrg    HandlingEvents = TRUE;
6473e747e6dSmrg    InitEvents();
6486d8e82c3Smrg    HandleEvents(appContext);
649f66df612Smrg    exit(EXIT_SUCCESS);
6503e747e6dSmrg}
6513e747e6dSmrg
6523e747e6dSmrg/**
6533e747e6dSmrg * initialize twm variables
6543e747e6dSmrg */
655c2535118Smrgstatic void
656c2535118SmrgInitVariables(void)
6573e747e6dSmrg{
6583e747e6dSmrg    FreeList(&Scr->BorderColorL);
6593e747e6dSmrg    FreeList(&Scr->IconBorderColorL);
6603e747e6dSmrg    FreeList(&Scr->BorderTileForegroundL);
6613e747e6dSmrg    FreeList(&Scr->BorderTileBackgroundL);
6623e747e6dSmrg    FreeList(&Scr->TitleForegroundL);
6633e747e6dSmrg    FreeList(&Scr->TitleBackgroundL);
6643e747e6dSmrg    FreeList(&Scr->IconForegroundL);
6653e747e6dSmrg    FreeList(&Scr->IconBackgroundL);
6663e747e6dSmrg    FreeList(&Scr->IconManagerFL);
6673e747e6dSmrg    FreeList(&Scr->IconManagerBL);
6683e747e6dSmrg    FreeList(&Scr->IconMgrs);
6693e747e6dSmrg    FreeList(&Scr->NoTitle);
6703e747e6dSmrg    FreeList(&Scr->MakeTitle);
6713e747e6dSmrg    FreeList(&Scr->AutoRaise);
6723e747e6dSmrg    FreeList(&Scr->IconNames);
6733e747e6dSmrg    FreeList(&Scr->NoHighlight);
6743e747e6dSmrg    FreeList(&Scr->NoStackModeL);
6753e747e6dSmrg    FreeList(&Scr->NoTitleHighlight);
6763e747e6dSmrg    FreeList(&Scr->DontIconify);
6773e747e6dSmrg    FreeList(&Scr->IconMgrNoShow);
6783e747e6dSmrg    FreeList(&Scr->IconMgrShow);
6793e747e6dSmrg    FreeList(&Scr->IconifyByUn);
6803e747e6dSmrg    FreeList(&Scr->StartIconified);
6813e747e6dSmrg    FreeList(&Scr->IconManagerHighlightL);
6823e747e6dSmrg    FreeList(&Scr->SqueezeTitleL);
6833e747e6dSmrg    FreeList(&Scr->DontSqueezeTitleL);
6843e747e6dSmrg    FreeList(&Scr->WindowRingL);
6853e747e6dSmrg    FreeList(&Scr->WarpCursorL);
6863e747e6dSmrg
6873e747e6dSmrg    NewFontCursor(&Scr->FrameCursor, "top_left_arrow");
6883e747e6dSmrg    NewFontCursor(&Scr->TitleCursor, "top_left_arrow");
6893e747e6dSmrg    NewFontCursor(&Scr->IconCursor, "top_left_arrow");
6903e747e6dSmrg    NewFontCursor(&Scr->IconMgrCursor, "top_left_arrow");
6913e747e6dSmrg    NewFontCursor(&Scr->MoveCursor, "fleur");
6923e747e6dSmrg    NewFontCursor(&Scr->ResizeCursor, "fleur");
6933e747e6dSmrg    NewFontCursor(&Scr->MenuCursor, "sb_left_arrow");
6943e747e6dSmrg    NewFontCursor(&Scr->ButtonCursor, "hand2");
6953e747e6dSmrg    NewFontCursor(&Scr->WaitCursor, "watch");
6963e747e6dSmrg    NewFontCursor(&Scr->SelectCursor, "dot");
6973e747e6dSmrg    NewFontCursor(&Scr->DestroyCursor, "pirate");
6983e747e6dSmrg
6993e747e6dSmrg    Scr->Ring = NULL;
7003e747e6dSmrg    Scr->RingLeader = NULL;
7013e747e6dSmrg
7023e747e6dSmrg    Scr->DefaultC.fore = black;
7033e747e6dSmrg    Scr->DefaultC.back = white;
7043e747e6dSmrg    Scr->BorderColor = black;
7053e747e6dSmrg    Scr->BorderTileC.fore = black;
7063e747e6dSmrg    Scr->BorderTileC.back = white;
7073e747e6dSmrg    Scr->TitleC.fore = black;
7083e747e6dSmrg    Scr->TitleC.back = white;
7093e747e6dSmrg    Scr->MenuC.fore = black;
7103e747e6dSmrg    Scr->MenuC.back = white;
7113e747e6dSmrg    Scr->MenuTitleC.fore = black;
7123e747e6dSmrg    Scr->MenuTitleC.back = white;
7133e747e6dSmrg    Scr->MenuShadowColor = black;
7143e747e6dSmrg    Scr->MenuBorderColor = black;
7153e747e6dSmrg    Scr->IconC.fore = black;
7163e747e6dSmrg    Scr->IconC.back = white;
7173e747e6dSmrg    Scr->IconBorderColor = black;
7183e747e6dSmrg    Scr->PointerForeground.pixel = black;
7193e747e6dSmrg    XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
720f66df612Smrg                &Scr->PointerForeground);
7213e747e6dSmrg    Scr->PointerBackground.pixel = white;
7223e747e6dSmrg    XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
723f66df612Smrg                &Scr->PointerBackground);
7243e747e6dSmrg    Scr->IconManagerC.fore = black;
7253e747e6dSmrg    Scr->IconManagerC.back = white;
7263e747e6dSmrg    Scr->IconManagerHighlight = black;
7273e747e6dSmrg
728f66df612Smrg    Scr->FramePadding = 2;      /* values that look "nice" on */
729f66df612Smrg    Scr->TitlePadding = 8;      /* 75 and 100dpi displays */
7303e747e6dSmrg    Scr->ButtonIndent = 1;
7313e747e6dSmrg    Scr->SizeStringOffset = 0;
7323e747e6dSmrg    Scr->BorderWidth = BW;
7333e747e6dSmrg    Scr->IconBorderWidth = BW;
7343e747e6dSmrg    Scr->MenuBorderWidth = BW;
7353e747e6dSmrg    Scr->UnknownWidth = 0;
7363e747e6dSmrg    Scr->UnknownHeight = 0;
7373e747e6dSmrg    Scr->NumAutoRaises = 0;
7383e747e6dSmrg    Scr->NoDefaults = FALSE;
7393e747e6dSmrg    Scr->UsePPosition = PPOS_OFF;
7403e747e6dSmrg    Scr->FocusRoot = TRUE;
7413e747e6dSmrg    Scr->Focus = NULL;
7423e747e6dSmrg    Scr->WarpCursor = FALSE;
7433e747e6dSmrg    Scr->ForceIcon = FALSE;
7443e747e6dSmrg    Scr->NoGrabServer = FALSE;
7453e747e6dSmrg    Scr->NoRaiseMove = FALSE;
7463e747e6dSmrg    Scr->NoRaiseResize = FALSE;
7473e747e6dSmrg    Scr->NoRaiseDeicon = FALSE;
7483e747e6dSmrg    Scr->NoRaiseWarp = FALSE;
7493e747e6dSmrg    Scr->DontMoveOff = FALSE;
7503e747e6dSmrg    Scr->DoZoom = FALSE;
7513e747e6dSmrg    Scr->TitleFocus = TRUE;
7523e747e6dSmrg    Scr->NoTitlebar = FALSE;
7533e747e6dSmrg    Scr->DecorateTransients = FALSE;
7543e747e6dSmrg    Scr->IconifyByUnmapping = FALSE;
7553e747e6dSmrg    Scr->ShowIconManager = FALSE;
756f66df612Smrg    Scr->IconManagerDontShow = FALSE;
7573e747e6dSmrg    Scr->BackingStore = TRUE;
7583e747e6dSmrg    Scr->SaveUnder = TRUE;
7593e747e6dSmrg    Scr->RandomPlacement = FALSE;
7603e747e6dSmrg    Scr->OpaqueMove = FALSE;
7613e747e6dSmrg    Scr->Highlight = TRUE;
7623e747e6dSmrg    Scr->StackMode = TRUE;
7633e747e6dSmrg    Scr->TitleHighlight = TRUE;
764f66df612Smrg    Scr->MoveDelta = 1;         /* so that f.deltastop will work */
7653e747e6dSmrg    Scr->ZoomCount = 8;
7663e747e6dSmrg    Scr->SortIconMgr = FALSE;
7673e747e6dSmrg    Scr->Shadow = TRUE;
7683e747e6dSmrg    Scr->InterpolateMenuColors = FALSE;
7693e747e6dSmrg    Scr->NoIconManagers = FALSE;
7703e747e6dSmrg    Scr->ClientBorderWidth = FALSE;
7713e747e6dSmrg    Scr->SqueezeTitle = -1;
7723e747e6dSmrg    Scr->FirstRegion = NULL;
7733e747e6dSmrg    Scr->LastRegion = NULL;
7743e747e6dSmrg    Scr->FirstTime = TRUE;
775f66df612Smrg    Scr->HaveFonts = FALSE;     /* i.e. not loaded yet */
7763e747e6dSmrg    Scr->CaseSensitive = TRUE;
7773e747e6dSmrg    Scr->WarpUnmapped = FALSE;
7783e747e6dSmrg
7793e747e6dSmrg    /* setup default fonts; overridden by defaults from system.twmrc */
7803e747e6dSmrg#define DEFAULT_NICE_FONT "variable"
7813e747e6dSmrg#define DEFAULT_FAST_FONT "fixed"
7823e747e6dSmrg
7833e747e6dSmrg    Scr->TitleBarFont.font = NULL;
7843e747e6dSmrg    Scr->TitleBarFont.fontset = NULL;
7853e747e6dSmrg    Scr->TitleBarFont.name = DEFAULT_NICE_FONT;
7863e747e6dSmrg    Scr->MenuFont.font = NULL;
7873e747e6dSmrg    Scr->MenuFont.fontset = NULL;
7883e747e6dSmrg    Scr->MenuFont.name = DEFAULT_NICE_FONT;
7893e747e6dSmrg    Scr->IconFont.font = NULL;
7903e747e6dSmrg    Scr->IconFont.fontset = NULL;
7913e747e6dSmrg    Scr->IconFont.name = DEFAULT_NICE_FONT;
7923e747e6dSmrg    Scr->SizeFont.font = NULL;
7933e747e6dSmrg    Scr->SizeFont.fontset = NULL;
7943e747e6dSmrg    Scr->SizeFont.name = DEFAULT_FAST_FONT;
7953e747e6dSmrg    Scr->IconManagerFont.font = NULL;
7963e747e6dSmrg    Scr->IconManagerFont.fontset = NULL;
7973e747e6dSmrg    Scr->IconManagerFont.name = DEFAULT_NICE_FONT;
7983e747e6dSmrg    Scr->DefaultFont.font = NULL;
7993e747e6dSmrg    Scr->DefaultFont.fontset = NULL;
8003e747e6dSmrg    Scr->DefaultFont.name = DEFAULT_FAST_FONT;
8013e747e6dSmrg
8023e747e6dSmrg}
8033e747e6dSmrg
8043e747e6dSmrgvoid
805f66df612SmrgCreateFonts(void)
8063e747e6dSmrg{
8073e747e6dSmrg    GetFont(&Scr->TitleBarFont);
8083e747e6dSmrg    GetFont(&Scr->MenuFont);
8093e747e6dSmrg    GetFont(&Scr->IconFont);
8103e747e6dSmrg    GetFont(&Scr->SizeFont);
8113e747e6dSmrg    GetFont(&Scr->IconManagerFont);
8123e747e6dSmrg    GetFont(&Scr->DefaultFont);
8133e747e6dSmrg    Scr->HaveFonts = TRUE;
8143e747e6dSmrg}
8153e747e6dSmrg
8166d8e82c3Smrgstatic void
8176d8e82c3SmrgDestroyFonts(void)
8186d8e82c3Smrg{
8196d8e82c3Smrg    int i;
8206d8e82c3Smrg    for (i = 0; i < NumScreens; ++i) {
8216d8e82c3Smrg        ScreenInfo *scr = ScreenList[i];
8226d8e82c3Smrg
8236d8e82c3Smrg        if (!scr) {
8246d8e82c3Smrg            continue;
8256d8e82c3Smrg        }
8266d8e82c3Smrg
8276d8e82c3Smrg        DestroyFont(&scr->TitleBarFont);
8286d8e82c3Smrg        DestroyFont(&scr->MenuFont);
8296d8e82c3Smrg        DestroyFont(&scr->IconFont);
8306d8e82c3Smrg        DestroyFont(&scr->SizeFont);
8316d8e82c3Smrg        DestroyFont(&scr->IconManagerFont);
8326d8e82c3Smrg        DestroyFont(&scr->DefaultFont);
8336d8e82c3Smrg    }
8346d8e82c3Smrg}
8356d8e82c3Smrg
8363e747e6dSmrgvoid
837f66df612SmrgRestoreWithdrawnLocation(TwmWindow *tmp)
8383e747e6dSmrg{
8393e747e6dSmrg    int gravx, gravy;
840f66df612Smrg    unsigned int bw;
8413e747e6dSmrg    XWindowChanges xwc;
8426d8e82c3Smrg    unsigned udummy = 0;
8436d8e82c3Smrg    Window wdummy = None;
8443e747e6dSmrg
8456d8e82c3Smrg    if (XGetGeometry(dpy, tmp->w, &wdummy, &xwc.x, &xwc.y,
8466d8e82c3Smrg                     &udummy, &udummy, &bw, &udummy)) {
847f66df612Smrg        unsigned mask;
8483e747e6dSmrg
849f66df612Smrg        GetGravityOffsets(tmp, &gravx, &gravy);
850f66df612Smrg        if (gravy < 0)
851f66df612Smrg            xwc.y -= tmp->title_height;
8523e747e6dSmrg
853f66df612Smrg        if (bw != (unsigned) tmp->old_bw) {
854f66df612Smrg            int xoff, yoff;
8553e747e6dSmrg
856f66df612Smrg            if (!Scr->ClientBorderWidth) {
857f66df612Smrg                xoff = gravx;
858f66df612Smrg                yoff = gravy;
859f66df612Smrg            }
860f66df612Smrg            else {
861f66df612Smrg                xoff = 0;
862f66df612Smrg                yoff = 0;
863f66df612Smrg            }
8643e747e6dSmrg
865f66df612Smrg            xwc.x -= (xoff + 1) * tmp->old_bw;
866f66df612Smrg            xwc.y -= (yoff + 1) * tmp->old_bw;
867f66df612Smrg        }
868f66df612Smrg        if (!Scr->ClientBorderWidth) {
869f66df612Smrg            xwc.x += gravx * tmp->frame_bw;
870f66df612Smrg            xwc.y += gravy * tmp->frame_bw;
871f66df612Smrg        }
8723e747e6dSmrg
873f66df612Smrg        mask = (CWX | CWY);
874f66df612Smrg        if (bw != (unsigned) tmp->old_bw) {
875f66df612Smrg            xwc.border_width = tmp->old_bw;
876f66df612Smrg            mask |= CWBorderWidth;
877f66df612Smrg        }
8783e747e6dSmrg
879f66df612Smrg        XConfigureWindow(dpy, tmp->w, mask, &xwc);
8803e747e6dSmrg
881f66df612Smrg        if (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint)) {
882f66df612Smrg            XUnmapWindow(dpy, tmp->wmhints->icon_window);
883f66df612Smrg        }
8843e747e6dSmrg
8853e747e6dSmrg    }
8863e747e6dSmrg}
8873e747e6dSmrg
888ffd25bcaSmrgvoid
889f66df612SmrgReborder(Time time)
8903e747e6dSmrg{
891f66df612Smrg    TwmWindow *tmp;             /* temp twm window structure */
8923e747e6dSmrg    int scrnum;
8933e747e6dSmrg
8943e747e6dSmrg    /* put a border back around all windows */
8953e747e6dSmrg
896f66df612Smrg    XGrabServer(dpy);
897f66df612Smrg    for (scrnum = 0; scrnum < NumScreens; scrnum++) {
898f66df612Smrg        if ((Scr = ScreenList[scrnum]) == NULL)
899f66df612Smrg            continue;
900f66df612Smrg
901f66df612Smrg        InstallWindowColormaps(0, &Scr->TwmRoot);       /* force reinstall */
902f66df612Smrg        for (tmp = Scr->TwmRoot.next; tmp != NULL; tmp = tmp->next) {
903f66df612Smrg            RestoreWithdrawnLocation(tmp);
904f66df612Smrg            XMapWindow(dpy, tmp->w);
905f66df612Smrg        }
9063e747e6dSmrg    }
9073e747e6dSmrg
908f66df612Smrg    XUngrabServer(dpy);
909f66df612Smrg    SetFocus((TwmWindow *) NULL, time);
9103e747e6dSmrg}
9113e747e6dSmrg
912c2535118Smrgstatic void
913f66df612SmrgsigHandler(int sig _X_UNUSED)
9143e747e6dSmrg{
9153e747e6dSmrg    XtNoticeSignal(si);
9163e747e6dSmrg}
9173e747e6dSmrg
9183e747e6dSmrg/**
9193e747e6dSmrg * cleanup and exit twm
9203e747e6dSmrg */
9213e747e6dSmrgvoid
922f66df612SmrgDone(XtPointer client_data _X_UNUSED, XtSignalId *si2 _X_UNUSED)
9233e747e6dSmrg{
924f66df612Smrg    if (dpy) {
925f66df612Smrg        Reborder(CurrentTime);
9266d8e82c3Smrg        DestroyFonts();
927f66df612Smrg        XCloseDisplay(dpy);
9283e747e6dSmrg    }
9296d8e82c3Smrg
9306d8e82c3Smrg    DestroySession();
931f66df612Smrg    exit(EXIT_SUCCESS);
9323e747e6dSmrg}
9333e747e6dSmrg
9343e747e6dSmrg/*
9353e747e6dSmrg * Error Handlers.  If a client dies, we'll get a BadWindow error (except for
9363e747e6dSmrg * GetGeometry which returns BadDrawable) for most operations that we do before
9373e747e6dSmrg * manipulating the client's window.
9383e747e6dSmrg */
9393e747e6dSmrg
9403e747e6dSmrgBool ErrorOccurred = False;
9413e747e6dSmrgXErrorEvent LastErrorEvent;
9423e747e6dSmrg
943ffd25bcaSmrgstatic int
944f66df612SmrgTwmErrorHandler(Display *dpy2, XErrorEvent *event)
9453e747e6dSmrg{
9463e747e6dSmrg    LastErrorEvent = *event;
9473e747e6dSmrg    ErrorOccurred = True;
9483e747e6dSmrg
949f66df612Smrg    if ((message_level > 1) &&  /* don't be too obnoxious */
950f66df612Smrg        event->error_code != BadWindow &&       /* watch for dead puppies */
951f66df612Smrg        (event->request_code != X_GetGeometry &&        /* of all styles */
952f66df612Smrg         event->error_code != BadDrawable))
953f66df612Smrg        XmuPrintDefaultErrorMessage(dpy2, event, stderr);
9543e747e6dSmrg    return 0;
9553e747e6dSmrg}
9563e747e6dSmrg
957ffd25bcaSmrgstatic int
958f66df612SmrgCatchRedirectError(Display *dpy2 _X_UNUSED, XErrorEvent *event)
9593e747e6dSmrg{
9603e747e6dSmrg    RedirectError = TRUE;
9613e747e6dSmrg    LastErrorEvent = *event;
9623e747e6dSmrg    ErrorOccurred = True;
9633e747e6dSmrg    return 0;
9643e747e6dSmrg}
965f66df612Smrg
966f66df612Smrgvoid
967f66df612SmrgtwmError(const char *format, ...)
968f66df612Smrg{
969f66df612Smrg    va_list ap;
970f66df612Smrg
971f66df612Smrg    va_start(ap, format);
972f66df612Smrg    fprintf(stderr, "%s: error: ", ProgramName);
973f66df612Smrg    vfprintf(stderr, format, ap);
974f66df612Smrg    fputc('\n', stderr);
975f66df612Smrg    va_end(ap);
976f66df612Smrg    exit(EXIT_FAILURE);
977f66df612Smrg}
978f66df612Smrg
979f66df612Smrgvoid
980f66df612SmrgtwmWarning(const char *format, ...)
981f66df612Smrg{
982f66df612Smrg    if (message_level > 0) {
983f66df612Smrg        va_list ap;
984f66df612Smrg
985f66df612Smrg        va_start(ap, format);
986f66df612Smrg        fprintf(stderr, "%s: warning: ", ProgramName);
987f66df612Smrg        vfprintf(stderr, format, ap);
988f66df612Smrg        fputc('\n', stderr);
989f66df612Smrg        va_end(ap);
990f66df612Smrg    }
991f66df612Smrg}
992f66df612Smrg
993f66df612Smrgvoid
994f66df612SmrgtwmVerbose(const char *format, ...)
995f66df612Smrg{
996f66df612Smrg    if (message_level > 1) {
997f66df612Smrg        va_list ap;
998f66df612Smrg
999f66df612Smrg        va_start(ap, format);
1000f66df612Smrg        fprintf(stderr, "%s: warning: ", ProgramName);
1001f66df612Smrg        vfprintf(stderr, format, ap);
1002f66df612Smrg        fputc('\n', stderr);
1003f66df612Smrg        va_end(ap);
1004f66df612Smrg    }
1005f66df612Smrg}
1006f66df612Smrg
1007f66df612Smrgvoid
1008f66df612SmrgtwmMessage(const char *format, ...)
1009f66df612Smrg{
1010f66df612Smrg    va_list ap;
1011f66df612Smrg
1012f66df612Smrg    va_start(ap, format);
1013f66df612Smrg    printf("%s: ", ProgramName);
1014f66df612Smrg    vprintf(format, ap);
1015f66df612Smrg    putc('\n', stdout);
1016f66df612Smrg    va_end(ap);
1017f66df612Smrg
1018f66df612Smrg    fflush(stdout);
1019f66df612Smrg}
1020