util.c revision 645f5050
1645f5050Syouri/*****************************************************************************/
2645f5050Syouri/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3645f5050Syouri/**                          Salt Lake City, Utah                           **/
4645f5050Syouri/**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5645f5050Syouri/**                        Cambridge, Massachusetts                         **/
6645f5050Syouri/**                                                                         **/
7645f5050Syouri/**                           All Rights Reserved                           **/
8645f5050Syouri/**                                                                         **/
9645f5050Syouri/**    Permission to use, copy, modify, and distribute this software and    **/
10645f5050Syouri/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11645f5050Syouri/**    granted, provided that the above copyright notice appear  in  all    **/
12645f5050Syouri/**    copies and that both  that  copyright  notice  and  this  permis-    **/
13645f5050Syouri/**    sion  notice appear in supporting  documentation,  and  that  the    **/
14645f5050Syouri/**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15645f5050Syouri/**    in publicity pertaining to distribution of the  software  without    **/
16645f5050Syouri/**    specific, written prior permission.                                  **/
17645f5050Syouri/**                                                                         **/
18645f5050Syouri/**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19645f5050Syouri/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20645f5050Syouri/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21645f5050Syouri/**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22645f5050Syouri/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23645f5050Syouri/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24645f5050Syouri/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25645f5050Syouri/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26645f5050Syouri/*****************************************************************************/
27645f5050Syouri/*
28645f5050Syouri *  [ ctwm ]
29645f5050Syouri *
30645f5050Syouri *  Copyright 1992 Claude Lecommandeur.
31645f5050Syouri *
32645f5050Syouri * Permission to use, copy, modify  and distribute this software  [ctwm] and
33645f5050Syouri * its documentation for any purpose is hereby granted without fee, provided
34645f5050Syouri * that the above  copyright notice appear  in all copies and that both that
35645f5050Syouri * copyright notice and this permission notice appear in supporting documen-
36645f5050Syouri * tation, and that the name of  Claude Lecommandeur not be used in adverti-
37645f5050Syouri * sing or  publicity  pertaining to  distribution of  the software  without
38645f5050Syouri * specific, written prior permission. Claude Lecommandeur make no represen-
39645f5050Syouri * tations  about the suitability  of this software  for any purpose.  It is
40645f5050Syouri * provided "as is" without express or implied warranty.
41645f5050Syouri *
42645f5050Syouri * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43645f5050Syouri * INCLUDING ALL  IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS.  IN NO
44645f5050Syouri * EVENT SHALL  Claude Lecommandeur  BE LIABLE FOR ANY SPECIAL,  INDIRECT OR
45645f5050Syouri * CONSEQUENTIAL  DAMAGES OR ANY  DAMAGES WHATSOEVER  RESULTING FROM LOSS OF
46645f5050Syouri * USE, DATA  OR PROFITS,  WHETHER IN AN ACTION  OF CONTRACT,  NEGLIGENCE OR
47645f5050Syouri * OTHER  TORTIOUS ACTION,  ARISING OUT OF OR IN  CONNECTION WITH THE USE OR
48645f5050Syouri * PERFORMANCE OF THIS SOFTWARE.
49645f5050Syouri *
50645f5050Syouri * Author:  Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
51645f5050Syouri */
52645f5050Syouri
53645f5050Syouri
54645f5050Syouri/***********************************************************************
55645f5050Syouri *
56645f5050Syouri * $XConsortium: util.c,v 1.47 91/07/14 13:40:37 rws Exp $
57645f5050Syouri *
58645f5050Syouri * utility routines for twm
59645f5050Syouri *
60645f5050Syouri * 28-Oct-87 Thomas E. LaStrange	File created
61645f5050Syouri *
62645f5050Syouri * Do the necessary modification to be integrated in ctwm.
63645f5050Syouri * Can no longer be used for the standard twm.
64645f5050Syouri *
65645f5050Syouri * 22-April-92 Claude Lecommandeur.
66645f5050Syouri *
67645f5050Syouri * Changed behavior of DontMoveOff/MoveOffResistance to allow
68645f5050Syouri * moving a window off screen less than #MoveOffResistance pixels.
69645f5050Syouri * New code will no longer "snap" windows to #MoveOffResistance
70645f5050Syouri * pixels off screen and instead movements will just be stopped and
71645f5050Syouri * then resume once movement of #MoveOffResistance have been attempted.
72645f5050Syouri *
73645f5050Syouri * 15-December-02 Bjorn Knutsson
74645f5050Syouri *
75645f5050Syouri ***********************************************************************/
76645f5050Syouri
77645f5050Syouri#define LEVITTE_TEST
78645f5050Syouri
79645f5050Syouri#include "twm.h"
80645f5050Syouri#include "util.h"
81645f5050Syouri#include "events.h"
82645f5050Syouri#include "add_window.h"
83645f5050Syouri#include "gram.tab.h"
84645f5050Syouri#include "screen.h"
85645f5050Syouri#include "icons.h"
86645f5050Syouri#include "cursor.h"
87645f5050Syouri#include <stdio.h>
88645f5050Syouri
89645f5050Syouri/*
90645f5050Syouri * Need this for the fixed-size uint_*'s used below.  stdint.h would be
91645f5050Syouri * the more appropriate include, but there exist systems that don't have
92645f5050Syouri * it, but do have inttypes.h (FreeBSD 4, Solaris 7-9 I've heard of,
93645f5050Syouri * probably more).
94645f5050Syouri */
95645f5050Syouri#include <inttypes.h>
96645f5050Syouri
97645f5050Syouri#ifdef VMS
98645f5050Syouri#include <decw$include/Xos.h>
99645f5050Syouri#include <decw$include/Xatom.h>
100645f5050Syouri#include <decw$include/Xutil.h>
101645f5050Syouri#include <X11Xmu/Drawing.h>
102645f5050Syouri#include <X11Xmu/CharSet.h>
103645f5050Syouri#include <X11Xmu/WinUtil.h>
104645f5050Syouri#ifdef HAVE_XWDFILE_H
105645f5050Syouri#include "XWDFile.h"		/* We do some tricks, since the original
106645f5050Syouri				   has bugs...		/Richard Levitte */
107645f5050Syouri#endif /* HAVE_XWDFILE_H */
108645f5050Syouri#include <unixlib.h>
109645f5050Syouri#include <starlet.h>
110645f5050Syouri#include <ssdef.h>
111645f5050Syouri#include <psldef.h>
112645f5050Syouri#include <lib$routines.h>
113645f5050Syouri#ifdef __DECC
114645f5050Syouri#include <unistd.h>
115645f5050Syouri#endif /* __DECC */
116645f5050Syouri#define USE_SIGNALS
117645f5050Syouri#ifndef F_OK
118645f5050Syouri#  define F_OK 0
119645f5050Syouri#endif
120645f5050Syouri#ifndef X_OK
121645f5050Syouri#  define X_OK 1
122645f5050Syouri#endif
123645f5050Syouri#ifndef W_OK
124645f5050Syouri#  define W_OK 2
125645f5050Syouri#endif
126645f5050Syouri#ifndef R_OK
127645f5050Syouri#  define R_OK 4
128645f5050Syouri#endif
129645f5050Syouri#else /* !VMS */
130645f5050Syouri#include <X11/Xos.h>
131645f5050Syouri#include <X11/Xatom.h>
132645f5050Syouri#include <X11/Xmu/Drawing.h>
133645f5050Syouri#include <X11/Xmu/CharSet.h>
134645f5050Syouri#include <X11/Xmu/WinUtil.h>
135645f5050Syouri#include <X11/XWDFile.h>
136645f5050Syouri#endif /* VMS */
137645f5050Syouri
138645f5050Syouri#if defined(USE_SIGNALS) && defined(__sgi)
139645f5050Syouri#  define _BSD_SIGNALS
140645f5050Syouri#endif
141645f5050Syouri
142645f5050Syouri#include <signal.h>
143645f5050Syouri#ifndef VMS
144645f5050Syouri#include <sys/time.h>
145645f5050Syouri#endif
146645f5050Syouri
147645f5050Syouri#if defined (XPM)
148645f5050Syouri#ifdef VMS
149645f5050Syouri#include "xpm.h"
150645f5050Syouri#else
151645f5050Syouri#   include <X11/xpm.h>
152645f5050Syouri#endif
153645f5050Syouri#endif
154645f5050Syouri
155645f5050Syouri#ifdef JPEG
156645f5050Syouri# include <setjmp.h>
157645f5050Syouri# include <jpeglib.h>
158645f5050Syouri# include <jerror.h>
159645f5050Syouri  static Image *LoadJpegImage (char *name);
160645f5050Syouri  static Image *GetJpegImage  (char *name);
161645f5050Syouri
162645f5050Syouri  struct jpeg_error {
163645f5050Syouri    struct jpeg_error_mgr pub;
164645f5050Syouri    sigjmp_buf setjmp_buffer;
165645f5050Syouri  };
166645f5050Syouri
167645f5050Syouri  typedef struct jpeg_error *jerr_ptr;
168645f5050Syouri#endif /* JPEG */
169645f5050Syouri
170645f5050Syouri#ifdef IMCONV
171645f5050Syouri#   include "im.h"
172645f5050Syouri#   include "sdsc.h"
173645f5050Syouri#endif
174645f5050Syouri
175645f5050Syouri#define MAXANIMATIONSPEED 20
176645f5050Syouri
177645f5050Syouriextern Atom _XA_WM_WORKSPACESLIST;
178645f5050Syouri
179645f5050Syouristatic Image *LoadBitmapImage (char  *name, ColorPair cp);
180645f5050Syouristatic Image *GetBitmapImage  (char  *name, ColorPair cp);
181645f5050Syouri#if !defined(VMS) || defined(HAVE_XWDFILE_H)
182645f5050Syouristatic Image *LoadXwdImage    (char  *filename, ColorPair cp);
183645f5050Syouristatic Image *GetXwdImage     (char  *name, ColorPair cp);
184645f5050Syouri#endif
185645f5050Syouri#ifdef XPM
186645f5050Syouristatic Image *LoadXpmImage    (char  *name, ColorPair cp);
187645f5050Syouristatic Image *GetXpmImage     (char  *name, ColorPair cp);
188645f5050Syouristatic void   xpmErrorMessage (int status, char *name, char *fullname);
189645f5050Syouri#endif
190645f5050Syouri#ifdef IMCONV
191645f5050Syouristatic Image *GetImconvImage  (char *filename,
192645f5050Syouri			       unsigned int *widthp, unsigned int *heightp);
193645f5050Syouri#endif
194645f5050Syouristatic Pixmap CreateXLogoPixmap(unsigned int *widthp, unsigned int *heightp);
195645f5050Syouristatic Pixmap CreateResizePixmap(unsigned int *widthp, unsigned int *heightp);
196645f5050Syouristatic Pixmap CreateQuestionPixmap(unsigned int *widthp, unsigned int *heightp);
197645f5050Syouristatic Pixmap CreateMenuPixmap(unsigned int *widthp, unsigned int *heightp);
198645f5050Syouristatic Pixmap CreateDotPixmap (unsigned int *widthp, unsigned int *heightp);
199645f5050Syouristatic Image  *Create3DMenuImage (ColorPair cp);
200645f5050Syouristatic Image  *Create3DDotImage (ColorPair cp);
201645f5050Syouristatic Image  *Create3DResizeImage (ColorPair cp);
202645f5050Syouristatic Image  *Create3DZoomImage (ColorPair cp);
203645f5050Syouristatic Image  *Create3DBarImage (ColorPair cp);
204645f5050Syouristatic Image  *Create3DVertBarImage (ColorPair cp);
205645f5050Syouristatic Image  *Create3DResizeAnimation (Bool in, Bool left, Bool top,
206645f5050Syouri					ColorPair cp);
207645f5050Syouristatic Image  *Create3DCrossImage (ColorPair cp);
208645f5050Syouristatic Image  *Create3DIconifyImage (ColorPair cp);
209645f5050Syouristatic Image  *Create3DSunkenResizeImage (ColorPair cp);
210645f5050Syouristatic Image  *Create3DBoxImage (ColorPair cp);
211645f5050Syouri
212645f5050Syouriextern FILE *tracefile;
213645f5050Syouri
214645f5050Syourivoid FreeImage (Image *image);
215645f5050Syouri
216645f5050Syourivoid _swapshort (register char *bp, register unsigned n);
217645f5050Syourivoid _swaplong (register char *bp, register unsigned n);
218645f5050Syouri
219645f5050Syouristatic int    reportfilenotfound = 1;
220645f5050Syouristatic Colormap AlternateCmap = None;
221645f5050Syouri
222645f5050Syouriint  HotX, HotY;
223645f5050Syouri
224645f5050Syouriint  AnimationSpeed   = 0;
225645f5050SyouriBool AnimationActive  = False;
226645f5050SyouriBool MaybeAnimate     = True;
227645f5050Syouri#ifdef USE_SIGNALS
228645f5050Syouri   Bool AnimationPending = False;
229645f5050Syouri#else
230645f5050Syouri   struct timeval AnimateTimeout;
231645f5050Syouri#endif /* USE_SIGNALS */
232645f5050Syouri
233645f5050Syouri/***********************************************************************
234645f5050Syouri *
235645f5050Syouri *  Procedure:
236645f5050Syouri *	MoveOutline - move a window outline
237645f5050Syouri *
238645f5050Syouri *  Inputs:
239645f5050Syouri *	root	    - the window we are outlining
240645f5050Syouri *	x	    - upper left x coordinate
241645f5050Syouri *	y	    - upper left y coordinate
242645f5050Syouri *	width	    - the width of the rectangle
243645f5050Syouri *	height	    - the height of the rectangle
244645f5050Syouri *      bw          - the border width of the frame
245645f5050Syouri *      th          - title height
246645f5050Syouri *
247645f5050Syouri ***********************************************************************
248645f5050Syouri */
249645f5050Syouri
250645f5050Syouri/* ARGSUSED */
251645f5050Syourivoid MoveOutline(Window root,
252645f5050Syouri		 int x, int y, int width, int height, int bw, int th)
253645f5050Syouri{
254645f5050Syouri    static int	lastx = 0;
255645f5050Syouri    static int	lasty = 0;
256645f5050Syouri    static int	lastWidth = 0;
257645f5050Syouri    static int	lastHeight = 0;
258645f5050Syouri    static int	lastBW = 0;
259645f5050Syouri    static int	lastTH = 0;
260645f5050Syouri    int		xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb;
261645f5050Syouri    int		xthird, ythird;
262645f5050Syouri    XSegment	outline[18];
263645f5050Syouri    register XSegment	*r;
264645f5050Syouri
265645f5050Syouri    if (x == lastx && y == lasty && width == lastWidth && height == lastHeight
266645f5050Syouri	&& lastBW == bw && th == lastTH)
267645f5050Syouri	return;
268645f5050Syouri
269645f5050Syouri    r = outline;
270645f5050Syouri
271645f5050Syouri#define DRAWIT() \
272645f5050Syouri    if (lastWidth || lastHeight)			\
273645f5050Syouri    {							\
274645f5050Syouri	xl = lastx;					\
275645f5050Syouri	xr = lastx + lastWidth - 1;			\
276645f5050Syouri	yt = lasty;					\
277645f5050Syouri	yb = lasty + lastHeight - 1;			\
278645f5050Syouri	xinnerl = xl + lastBW;				\
279645f5050Syouri	xinnerr = xr - lastBW;				\
280645f5050Syouri	yinnert = yt + lastTH + lastBW;			\
281645f5050Syouri	yinnerb = yb - lastBW;				\
282645f5050Syouri	xthird = (xinnerr - xinnerl) / 3;		\
283645f5050Syouri	ythird = (yinnerb - yinnert) / 3;		\
284645f5050Syouri							\
285645f5050Syouri	r->x1 = xl;					\
286645f5050Syouri	r->y1 = yt;					\
287645f5050Syouri	r->x2 = xr;					\
288645f5050Syouri	r->y2 = yt;					\
289645f5050Syouri	r++;						\
290645f5050Syouri							\
291645f5050Syouri	r->x1 = xl;					\
292645f5050Syouri	r->y1 = yb;					\
293645f5050Syouri	r->x2 = xr;					\
294645f5050Syouri	r->y2 = yb;					\
295645f5050Syouri	r++;						\
296645f5050Syouri							\
297645f5050Syouri	r->x1 = xl;					\
298645f5050Syouri	r->y1 = yt;					\
299645f5050Syouri	r->x2 = xl;					\
300645f5050Syouri	r->y2 = yb;					\
301645f5050Syouri	r++;						\
302645f5050Syouri							\
303645f5050Syouri	r->x1 = xr;					\
304645f5050Syouri	r->y1 = yt;					\
305645f5050Syouri	r->x2 = xr;					\
306645f5050Syouri	r->y2 = yb;					\
307645f5050Syouri	r++;						\
308645f5050Syouri							\
309645f5050Syouri	r->x1 = xinnerl + xthird;			\
310645f5050Syouri	r->y1 = yinnert;				\
311645f5050Syouri	r->x2 = r->x1;					\
312645f5050Syouri	r->y2 = yinnerb;				\
313645f5050Syouri	r++;						\
314645f5050Syouri							\
315645f5050Syouri	r->x1 = xinnerl + (2 * xthird);			\
316645f5050Syouri	r->y1 = yinnert;				\
317645f5050Syouri	r->x2 = r->x1;					\
318645f5050Syouri	r->y2 = yinnerb;				\
319645f5050Syouri	r++;						\
320645f5050Syouri							\
321645f5050Syouri	r->x1 = xinnerl;				\
322645f5050Syouri	r->y1 = yinnert + ythird;			\
323645f5050Syouri	r->x2 = xinnerr;				\
324645f5050Syouri	r->y2 = r->y1;					\
325645f5050Syouri	r++;						\
326645f5050Syouri							\
327645f5050Syouri	r->x1 = xinnerl;				\
328645f5050Syouri	r->y1 = yinnert + (2 * ythird);			\
329645f5050Syouri	r->x2 = xinnerr;				\
330645f5050Syouri	r->y2 = r->y1;					\
331645f5050Syouri	r++;						\
332645f5050Syouri							\
333645f5050Syouri	if (lastTH != 0) {				\
334645f5050Syouri	    r->x1 = xl;					\
335645f5050Syouri	    r->y1 = yt + lastTH;			\
336645f5050Syouri	    r->x2 = xr;					\
337645f5050Syouri	    r->y2 = r->y1;				\
338645f5050Syouri	    r++;					\
339645f5050Syouri	}						\
340645f5050Syouri    }
341645f5050Syouri
342645f5050Syouri    /* undraw the old one, if any */
343645f5050Syouri    DRAWIT ();
344645f5050Syouri
345645f5050Syouri    lastx = x;
346645f5050Syouri    lasty = y;
347645f5050Syouri    lastWidth = width;
348645f5050Syouri    lastHeight = height;
349645f5050Syouri    lastBW = bw;
350645f5050Syouri    lastTH = th;
351645f5050Syouri
352645f5050Syouri    /* draw the new one, if any */
353645f5050Syouri    DRAWIT ();
354645f5050Syouri
355645f5050Syouri#undef DRAWIT
356645f5050Syouri
357645f5050Syouri
358645f5050Syouri    if (r != outline)
359645f5050Syouri    {
360645f5050Syouri	XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline);
361645f5050Syouri    }
362645f5050Syouri}
363645f5050Syouri
364645f5050Syouri/***********************************************************************
365645f5050Syouri *
366645f5050Syouri *  Procedure:
367645f5050Syouri *	Zoom - zoom in or out of an icon
368645f5050Syouri *
369645f5050Syouri *  Inputs:
370645f5050Syouri *	wf	- window to zoom from
371645f5050Syouri *	wt	- window to zoom to
372645f5050Syouri *
373645f5050Syouri ***********************************************************************
374645f5050Syouri */
375645f5050Syouri
376645f5050Syourivoid Zoom(Window wf, Window wt)
377645f5050Syouri{
378645f5050Syouri    int fx, fy, tx, ty;			/* from, to */
379645f5050Syouri    unsigned int fw, fh, tw, th;	/* from, to */
380645f5050Syouri    long dx, dy, dw, dh;
381645f5050Syouri    long z;
382645f5050Syouri    int j;
383645f5050Syouri
384645f5050Syouri    if ((Scr->IconifyStyle != ICONIFY_NORMAL) || !Scr->DoZoom || Scr->ZoomCount < 1) return;
385645f5050Syouri
386645f5050Syouri    if (wf == None || wt == None) return;
387645f5050Syouri
388645f5050Syouri    XGetGeometry (dpy, wf, &JunkRoot, &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth);
389645f5050Syouri    XGetGeometry (dpy, wt, &JunkRoot, &tx, &ty, &tw, &th, &JunkBW, &JunkDepth);
390645f5050Syouri
391645f5050Syouri    dx = (long) tx - (long) fx;	/* going from -> to */
392645f5050Syouri    dy = (long) ty - (long) fy;	/* going from -> to */
393645f5050Syouri    dw = (long) tw - (long) fw;	/* going from -> to */
394645f5050Syouri    dh = (long) th - (long) fh;	/* going from -> to */
395645f5050Syouri    z = (long) (Scr->ZoomCount + 1);
396645f5050Syouri
397645f5050Syouri    for (j = 0; j < 2; j++) {
398645f5050Syouri	long i;
399645f5050Syouri
400645f5050Syouri	XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh);
401645f5050Syouri	for (i = 1; i < z; i++) {
402645f5050Syouri	    int x = fx + (int) ((dx * i) / z);
403645f5050Syouri	    int y = fy + (int) ((dy * i) / z);
404645f5050Syouri	    unsigned width = (unsigned) (((long) fw) + (dw * i) / z);
405645f5050Syouri	    unsigned height = (unsigned) (((long) fh) + (dh * i) / z);
406645f5050Syouri
407645f5050Syouri	    XDrawRectangle (dpy, Scr->Root, Scr->DrawGC,
408645f5050Syouri			    x, y, width, height);
409645f5050Syouri	}
410645f5050Syouri	XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th);
411645f5050Syouri    }
412645f5050Syouri}
413645f5050Syouri
414645f5050Syouri
415645f5050Syourichar *ExpandFilePath (char *path)
416645f5050Syouri{
417645f5050Syouri    char *ret, *colon, *p;
418645f5050Syouri    int  len;
419645f5050Syouri
420645f5050Syouri    len = 0;
421645f5050Syouri    p   = path;
422645f5050Syouri    while ((colon = strchr (p, ':'))) {
423645f5050Syouri	len += colon - p + 1;
424645f5050Syouri	if (*p == '~') len += HomeLen - 1;
425645f5050Syouri	p = colon + 1;
426645f5050Syouri    }
427645f5050Syouri    if (*p == '~') len += HomeLen - 1;
428645f5050Syouri    len += strlen (p);
429645f5050Syouri    ret = (char*) malloc (len + 1);
430645f5050Syouri    *ret = 0;
431645f5050Syouri
432645f5050Syouri    p   = path;
433645f5050Syouri    while ((colon = strchr (p, ':'))) {
434645f5050Syouri	*colon = '\0';
435645f5050Syouri	if (*p == '~') {
436645f5050Syouri	    strcat (ret, Home);
437645f5050Syouri	    strcat (ret, p + 1);
438645f5050Syouri	} else {
439645f5050Syouri	    strcat (ret, p);
440645f5050Syouri	}
441645f5050Syouri	*colon = ':';
442645f5050Syouri	strcat (ret, ":");
443645f5050Syouri	p = colon + 1;
444645f5050Syouri    }
445645f5050Syouri    if (*p == '~') {
446645f5050Syouri	strcat (ret, Home);
447645f5050Syouri	strcat (ret, p + 1);
448645f5050Syouri    } else {
449645f5050Syouri	strcat (ret, p);
450645f5050Syouri    }
451645f5050Syouri    return ret;
452645f5050Syouri}
453645f5050Syouri
454645f5050Syouri/***********************************************************************
455645f5050Syouri *
456645f5050Syouri *  Procedure:
457645f5050Syouri *	ExpandFilename - expand the tilde character to HOME
458645f5050Syouri *		if it is the first character of the filename
459645f5050Syouri *
460645f5050Syouri *  Returned Value:
461645f5050Syouri *	a pointer to the new name
462645f5050Syouri *
463645f5050Syouri *  Inputs:
464645f5050Syouri *	name	- the filename to expand
465645f5050Syouri *
466645f5050Syouri ***********************************************************************
467645f5050Syouri */
468645f5050Syouri
469645f5050Syourichar *ExpandFilename(char *name)
470645f5050Syouri{
471645f5050Syouri    char *newname;
472645f5050Syouri
473645f5050Syouri    if (name[0] != '~') return name;
474645f5050Syouri
475645f5050Syouri#ifdef VMS
476645f5050Syouri    newname = (char *) malloc (HomeLen + strlen(name) + 1);
477645f5050Syouri    if (!newname) {
478645f5050Syouri        fprintf (stderr,
479645f5050Syouri 		 "%s:  unable to allocate %d bytes to expand filename %s%s\n",
480645f5050Syouri 		 ProgramName, HomeLen + strlen(name) + 1, Home, &name[1]);
481645f5050Syouri    } else {
482645f5050Syouri        (void) sprintf (newname, "%s%s", Home, &name[1]);
483645f5050Syouri    }
484645f5050Syouri#else
485645f5050Syouri    newname = (char *) malloc (HomeLen + strlen(name) + 2);
486645f5050Syouri    if (!newname) {
487645f5050Syouri	fprintf (stderr,
488645f5050Syouri		 "%s:  unable to allocate %lu bytes to expand filename %s/%s\n",
489645f5050Syouri		 ProgramName, (unsigned long) HomeLen + strlen(name) + 2,
490645f5050Syouri		 Home, &name[1]);
491645f5050Syouri    } else {
492645f5050Syouri	(void) sprintf (newname, "%s/%s", Home, &name[1]);
493645f5050Syouri    }
494645f5050Syouri#endif
495645f5050Syouri
496645f5050Syouri    return newname;
497645f5050Syouri}
498645f5050Syouri
499645f5050Syourichar *ExpandPixmapPath (char *name)
500645f5050Syouri{
501645f5050Syouri    char    *ret, *colon;
502645f5050Syouri
503645f5050Syouri    ret = NULL;
504645f5050Syouri#ifdef VMS
505645f5050Syouri    if (name[0] == '~') {
506645f5050Syouri	ret = (char *) malloc (HomeLen + strlen (name) + 1);
507645f5050Syouri	sprintf (ret, "%s%s", Home, &name[1]);
508645f5050Syouri    }
509645f5050Syouri    if (name[0] == '/') {
510645f5050Syouri	ret = (char *) malloc (strlen (name));
511645f5050Syouri	sprintf (ret, "%s", &name[1]);
512645f5050Syouri    }
513645f5050Syouri    else
514645f5050Syouri    if (Scr->PixmapDirectory) {
515645f5050Syouri	char *p = Scr->PixmapDirectory;
516645f5050Syouri	while (colon = strchr (p, ':')) {
517645f5050Syouri	    *colon = '\0';
518645f5050Syouri	    ret = (char *) malloc (strlen (p) + strlen (name) + 1);
519645f5050Syouri	    sprintf (ret, "%s%s", p, name);
520645f5050Syouri	    *colon = ':';
521645f5050Syouri	    if (!access (ret, R_OK)) return (ret);
522645f5050Syouri	    p = colon + 1;
523645f5050Syouri	}
524645f5050Syouri        ret = (char *) malloc (strlen (Scr->PixmapDirectory) + strlen (name) + 1);
525645f5050Syouri	sprintf (ret, "%s%s", Scr->PixmapDirectory, name);
526645f5050Syouri    }
527645f5050Syouri#else
528645f5050Syouri    if (name[0] == '~') {
529645f5050Syouri	ret = (char *) malloc (HomeLen + strlen (name) + 2);
530645f5050Syouri	sprintf (ret, "%s/%s", Home, &name[1]);
531645f5050Syouri    }
532645f5050Syouri    else
533645f5050Syouri    if (name[0] == '/') {
534645f5050Syouri	ret = (char *) malloc (strlen (name) + 1);
535645f5050Syouri	strcpy (ret, name);
536645f5050Syouri    }
537645f5050Syouri    else
538645f5050Syouri    if (Scr->PixmapDirectory) {
539645f5050Syouri	char *p = Scr->PixmapDirectory;
540645f5050Syouri	while ((colon = strchr (p, ':'))) {
541645f5050Syouri	    *colon = '\0';
542645f5050Syouri	    ret = (char *) malloc (strlen (p) + strlen (name) + 2);
543645f5050Syouri	    sprintf (ret, "%s/%s", p, name);
544645f5050Syouri	    *colon = ':';
545645f5050Syouri	    if (!access (ret, R_OK)) return (ret);
546645f5050Syouri	    p = colon + 1;
547645f5050Syouri	}
548645f5050Syouri	ret = (char *) malloc (strlen (p) + strlen (name) + 2);
549645f5050Syouri	sprintf (ret, "%s/%s", p, name);
550645f5050Syouri    }
551645f5050Syouri#endif
552645f5050Syouri    return (ret);
553645f5050Syouri}
554645f5050Syouri
555645f5050Syouri/***********************************************************************
556645f5050Syouri *
557645f5050Syouri *  Procedure:
558645f5050Syouri *	GetUnknownIcon - read in the bitmap file for the unknown icon
559645f5050Syouri *
560645f5050Syouri *  Inputs:
561645f5050Syouri *	name - the filename to read
562645f5050Syouri *
563645f5050Syouri ***********************************************************************
564645f5050Syouri */
565645f5050Syouri
566645f5050Syourivoid GetUnknownIcon(char *name)
567645f5050Syouri{
568645f5050Syouri    Scr->UnknownImage = GetImage (name, Scr->IconC);
569645f5050Syouri}
570645f5050Syouri
571645f5050Syouri/***********************************************************************
572645f5050Syouri *
573645f5050Syouri *  Procedure:
574645f5050Syouri *	FindBitmap - read in a bitmap file and return size
575645f5050Syouri *
576645f5050Syouri *  Returned Value:
577645f5050Syouri *	the pixmap associated with the bitmap
578645f5050Syouri *      widthp	- pointer to width of bitmap
579645f5050Syouri *      heightp	- pointer to height of bitmap
580645f5050Syouri *
581645f5050Syouri *  Inputs:
582645f5050Syouri *	name	- the filename to read
583645f5050Syouri *
584645f5050Syouri ***********************************************************************
585645f5050Syouri */
586645f5050Syouri
587645f5050SyouriPixmap FindBitmap (char *name, unsigned int *widthp, unsigned int *heightp)
588645f5050Syouri{
589645f5050Syouri    char *bigname;
590645f5050Syouri    Pixmap pm;
591645f5050Syouri
592645f5050Syouri    if (!name) return None;
593645f5050Syouri
594645f5050Syouri    /*
595645f5050Syouri     * Names of the form :name refer to hardcoded images that are scaled to
596645f5050Syouri     * look nice in title buttons.  Eventually, it would be nice to put in a
597645f5050Syouri     * menu symbol as well....
598645f5050Syouri     */
599645f5050Syouri    if (name[0] == ':') {
600645f5050Syouri	int i;
601645f5050Syouri	static struct {
602645f5050Syouri	    char *name;
603645f5050Syouri	    Pixmap (*proc)(unsigned int *wp, unsigned int *hp);
604645f5050Syouri	} pmtab[] = {
605645f5050Syouri	    { TBPM_DOT,		CreateDotPixmap },
606645f5050Syouri	    { TBPM_ICONIFY,	CreateDotPixmap },
607645f5050Syouri	    { TBPM_RESIZE,	CreateResizePixmap },
608645f5050Syouri	    { TBPM_XLOGO,	CreateXLogoPixmap },
609645f5050Syouri	    { TBPM_DELETE,	CreateXLogoPixmap },
610645f5050Syouri	    { TBPM_MENU,	CreateMenuPixmap },
611645f5050Syouri	    { TBPM_QUESTION,	CreateQuestionPixmap },
612645f5050Syouri	};
613645f5050Syouri
614645f5050Syouri	for (i = 0; i < (sizeof pmtab)/(sizeof pmtab[0]); i++) {
615645f5050Syouri	    if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0)
616645f5050Syouri	      return (*pmtab[i].proc) (widthp, heightp);
617645f5050Syouri	}
618645f5050Syouri	fprintf (stderr, "%s:  no such built-in bitmap \"%s\"\n",
619645f5050Syouri		 ProgramName, name);
620645f5050Syouri	return None;
621645f5050Syouri    }
622645f5050Syouri
623645f5050Syouri    /*
624645f5050Syouri     * Generate a full pathname if any special prefix characters (such as ~)
625645f5050Syouri     * are used.  If the bigname is different from name, bigname will need to
626645f5050Syouri     * be freed.
627645f5050Syouri     */
628645f5050Syouri    bigname = ExpandFilename (name);
629645f5050Syouri    if (!bigname) return None;
630645f5050Syouri
631645f5050Syouri    /*
632645f5050Syouri     * look along bitmapFilePath resource same as toolkit clients
633645f5050Syouri     */
634645f5050Syouri    pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL,
635645f5050Syouri			      0, (int *)widthp, (int *)heightp, &HotX, &HotY);
636645f5050Syouri    if (pm == None && Scr->IconDirectory && bigname[0] != '/') {
637645f5050Syouri	if (bigname != name) free (bigname);
638645f5050Syouri	/*
639645f5050Syouri	 * Attempt to find icon in old IconDirectory (now obsolete)
640645f5050Syouri	 */
641645f5050Syouri#ifdef VMS
642645f5050Syouri	bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 1);
643645f5050Syouri	if (!bigname) {
644645f5050Syouri	    fprintf (stderr,
645645f5050Syouri		"%s:  unable to allocate memory for \"%s%s\"\n",
646645f5050Syouri		ProgramName, Scr->IconDirectory, name);
647645f5050Syouri	    return None;
648645f5050Syouri	}
649645f5050Syouri	(void) sprintf (bigname, "%s%s", Scr->IconDirectory, name);
650645f5050Syouri#else
651645f5050Syouri	bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 2);
652645f5050Syouri	if (!bigname) {
653645f5050Syouri	    fprintf (stderr,
654645f5050Syouri		     "%s:  unable to allocate memory for \"%s/%s\"\n",
655645f5050Syouri		     ProgramName, Scr->IconDirectory, name);
656645f5050Syouri	    return None;
657645f5050Syouri	}
658645f5050Syouri	(void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name);
659645f5050Syouri#endif
660645f5050Syouri	if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm,
661645f5050Syouri			     &HotX, &HotY) != BitmapSuccess) {
662645f5050Syouri	    pm = None;
663645f5050Syouri	}
664645f5050Syouri    }
665645f5050Syouri    if (bigname != name) free (bigname);
666645f5050Syouri    if ((pm == None) && reportfilenotfound) {
667645f5050Syouri	fprintf (stderr, "%s:  unable to find bitmap \"%s\"\n", ProgramName, name);
668645f5050Syouri    }
669645f5050Syouri
670645f5050Syouri    return pm;
671645f5050Syouri}
672645f5050Syouri
673645f5050SyouriPixmap GetBitmap (char *name)
674645f5050Syouri{
675645f5050Syouri    return FindBitmap (name, &JunkWidth, &JunkHeight);
676645f5050Syouri}
677645f5050Syouri
678645f5050Syouristatic Image *LoadBitmapImage (char  *name, ColorPair cp)
679645f5050Syouri{
680645f5050Syouri    Image	 *image;
681645f5050Syouri    Pixmap	 bm;
682645f5050Syouri    unsigned int width, height;
683645f5050Syouri    XGCValues	 gcvalues;
684645f5050Syouri
685645f5050Syouri    if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues);
686645f5050Syouri    bm = FindBitmap (name, &width, &height);
687645f5050Syouri    if (bm == None) return (None);
688645f5050Syouri
689645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
690645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth);
691645f5050Syouri    gcvalues.background = cp.back;
692645f5050Syouri    gcvalues.foreground = cp.fore;
693645f5050Syouri    XChangeGC   (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues);
694645f5050Syouri    XCopyPlane  (dpy, bm, image->pixmap, Scr->rootGC, 0, 0, width, height,
695645f5050Syouri		0, 0, (unsigned long) 1);
696645f5050Syouri    XFreePixmap (dpy, bm);
697645f5050Syouri    image->mask   = None;
698645f5050Syouri    image->width  = width;
699645f5050Syouri    image->height = height;
700645f5050Syouri    image->next   = None;
701645f5050Syouri    return (image);
702645f5050Syouri}
703645f5050Syouri
704645f5050Syouristatic Image *GetBitmapImage (char  *name, ColorPair cp)
705645f5050Syouri{
706645f5050Syouri    Image	*image, *r, *s;
707645f5050Syouri    char	path [128], pref [128];
708645f5050Syouri    char	*perc;
709645f5050Syouri    int		i;
710645f5050Syouri
711645f5050Syouri    if (! strchr (name, '%')) return (LoadBitmapImage (name, cp));
712645f5050Syouri    s = image = None;
713645f5050Syouri    strcpy (pref, name);
714645f5050Syouri    perc  = strchr (pref, '%');
715645f5050Syouri    *perc = '\0';
716645f5050Syouri    reportfilenotfound = 0;
717645f5050Syouri    for (i = 1;; i++) {
718645f5050Syouri	sprintf (path, "%s%d%s", pref, i, perc + 1);
719645f5050Syouri	r = LoadBitmapImage (path, cp);
720645f5050Syouri	if (r == None) break;
721645f5050Syouri	r->next = None;
722645f5050Syouri	if (image == None) s = image = r;
723645f5050Syouri	else {
724645f5050Syouri	    s->next = r;
725645f5050Syouri	    s = r;
726645f5050Syouri	}
727645f5050Syouri    }
728645f5050Syouri    reportfilenotfound = 1;
729645f5050Syouri    if (s != None) s->next = image;
730645f5050Syouri    if (image == None) {
731645f5050Syouri	fprintf (stderr, "Cannot open any %s bitmap file\n", name);
732645f5050Syouri    }
733645f5050Syouri    return (image);
734645f5050Syouri}
735645f5050Syouri
736645f5050Syouri#ifdef XPM
737645f5050Syouristatic int reportxpmerror = 1;
738645f5050Syouri
739645f5050Syouristatic Image *LoadXpmImage (char *name, ColorPair cp)
740645f5050Syouri{
741645f5050Syouri    char	*fullname;
742645f5050Syouri    Image	*image;
743645f5050Syouri    int		status;
744645f5050Syouri    Colormap    stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
745645f5050Syouri    XpmAttributes attributes;
746645f5050Syouri    static XpmColorSymbol overrides[] = {
747645f5050Syouri	{"Foreground", NULL, 0},
748645f5050Syouri	{"Background", NULL, 0},
749645f5050Syouri	{"HiShadow", NULL, 0},
750645f5050Syouri	{"LoShadow", NULL, 0}
751645f5050Syouri    };
752645f5050Syouri
753645f5050Syouri    fullname = ExpandPixmapPath (name);
754645f5050Syouri    if (! fullname) return (None);
755645f5050Syouri
756645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
757645f5050Syouri    if (image == None) return (None);
758645f5050Syouri
759645f5050Syouri    attributes.valuemask  = 0;
760645f5050Syouri    attributes.valuemask |= XpmSize;
761645f5050Syouri    attributes.valuemask |= XpmReturnPixels;
762645f5050Syouri    attributes.valuemask |= XpmColormap;
763645f5050Syouri    attributes.valuemask |= XpmDepth;
764645f5050Syouri    attributes.valuemask |= XpmVisual;
765645f5050Syouri    attributes.valuemask |= XpmCloseness;
766645f5050Syouri    attributes.valuemask |= XpmColorSymbols;
767645f5050Syouri
768645f5050Syouri    attributes.numsymbols = 4;
769645f5050Syouri    attributes.colorsymbols = overrides;
770645f5050Syouri    overrides[0].pixel = cp.fore;
771645f5050Syouri    overrides[1].pixel = cp.back;
772645f5050Syouri    overrides[2].pixel = cp.shadd;
773645f5050Syouri    overrides[3].pixel = cp.shadc;
774645f5050Syouri
775645f5050Syouri
776645f5050Syouri    attributes.colormap  = AlternateCmap ? AlternateCmap : stdcmap;
777645f5050Syouri    attributes.depth     = Scr->d_depth;
778645f5050Syouri    attributes.visual    = Scr->d_visual;
779645f5050Syouri    attributes.closeness = 65535; /* Never fail */
780645f5050Syouri    status = XpmReadFileToPixmap(dpy, Scr->Root, fullname,
781645f5050Syouri				 &(image->pixmap), &(image->mask), &attributes);
782645f5050Syouri    if (status != XpmSuccess) {
783645f5050Syouri	xpmErrorMessage (status, name, fullname);
784645f5050Syouri	free (image);
785645f5050Syouri	return (None);
786645f5050Syouri    }
787645f5050Syouri    free (fullname);
788645f5050Syouri    image->width  = attributes.width;
789645f5050Syouri    image->height = attributes.height;
790645f5050Syouri    image->next   = None;
791645f5050Syouri    return (image);
792645f5050Syouri}
793645f5050Syouri
794645f5050Syouristatic Image *GetXpmImage (char *name, ColorPair cp)
795645f5050Syouri{
796645f5050Syouri    char    path [128], pref [128];
797645f5050Syouri    Image   *image, *r, *s;
798645f5050Syouri    char    *perc;
799645f5050Syouri    int     i;
800645f5050Syouri
801645f5050Syouri    if (! strchr (name, '%')) return (LoadXpmImage (name, cp));
802645f5050Syouri    s = image = None;
803645f5050Syouri    strcpy (pref, name);
804645f5050Syouri    perc  = strchr (pref, '%');
805645f5050Syouri    *perc = '\0';
806645f5050Syouri    reportfilenotfound = 0;
807645f5050Syouri    for (i = 1;; i++) {
808645f5050Syouri	sprintf (path, "%s%d%s", pref, i, perc + 1);
809645f5050Syouri	r = LoadXpmImage (path, cp);
810645f5050Syouri	if (r == None) break;
811645f5050Syouri	r->next = None;
812645f5050Syouri	if (image == None) s = image = r;
813645f5050Syouri	else {
814645f5050Syouri	    s->next = r;
815645f5050Syouri	    s = r;
816645f5050Syouri	}
817645f5050Syouri    }
818645f5050Syouri    reportfilenotfound = 1;
819645f5050Syouri    if (s != None) s->next = image;
820645f5050Syouri    if (image == None) {
821645f5050Syouri	fprintf (stderr, "Cannot open any %s XPM file\n", name);
822645f5050Syouri    }
823645f5050Syouri    return (image);
824645f5050Syouri}
825645f5050Syouri
826645f5050Syouristatic void xpmErrorMessage (int status, char *name, char *fullname)
827645f5050Syouri{
828645f5050Syouri    switch (status) {
829645f5050Syouri	case XpmSuccess:
830645f5050Syouri	    break;
831645f5050Syouri
832645f5050Syouri	case XpmColorError:
833645f5050Syouri	    if (reportxpmerror)
834645f5050Syouri		fprintf (stderr,
835645f5050Syouri			"Could not parse or alloc requested color : %s\n",
836645f5050Syouri			fullname);
837645f5050Syouri	    return;
838645f5050Syouri
839645f5050Syouri	case XpmOpenFailed:
840645f5050Syouri	    if (reportxpmerror && reportfilenotfound)
841645f5050Syouri		fprintf (stderr, "unable to locate XPM file : %s\n", fullname);
842645f5050Syouri	    return;
843645f5050Syouri
844645f5050Syouri	case XpmFileInvalid:
845645f5050Syouri	    fprintf (stderr, "invalid XPM file : %s\n", fullname);
846645f5050Syouri	    return;
847645f5050Syouri
848645f5050Syouri	case XpmNoMemory:
849645f5050Syouri	    if (reportxpmerror)
850645f5050Syouri		fprintf (stderr, "Not enough memory for XPM file : %s\n", fullname);
851645f5050Syouri	    return;
852645f5050Syouri
853645f5050Syouri	case XpmColorFailed:
854645f5050Syouri	    if (reportxpmerror)
855645f5050Syouri		fprintf (stderr, "Color not found in : %s\n", fullname);
856645f5050Syouri	    return;
857645f5050Syouri
858645f5050Syouri	default :
859645f5050Syouri	    fprintf (stderr, "Unknown error in : %s\n", fullname);
860645f5050Syouri	    return;
861645f5050Syouri    }
862645f5050Syouri}
863645f5050Syouri
864645f5050Syouri#endif
865645f5050Syouri
866645f5050Syourivoid MaskScreen (char *file)
867645f5050Syouri{
868645f5050Syouri    unsigned long valuemask;
869645f5050Syouri    XSetWindowAttributes attributes;
870645f5050Syouri    XEvent event;
871645f5050Syouri    Cursor waitcursor;
872645f5050Syouri    int x, y;
873645f5050Syouri    ColorPair WelcomeCp;
874645f5050Syouri    XColor black;
875645f5050Syouri
876645f5050Syouri    NewFontCursor (&waitcursor, "watch");
877645f5050Syouri
878645f5050Syouri    valuemask = (CWBackingStore | CWSaveUnder | CWBackPixel |
879645f5050Syouri		 CWOverrideRedirect | CWEventMask | CWCursor);
880645f5050Syouri    attributes.backing_store	 = NotUseful;
881645f5050Syouri    attributes.save_under	 = False;
882645f5050Syouri    attributes.override_redirect = True;
883645f5050Syouri    attributes.event_mask	 = ExposureMask;
884645f5050Syouri    attributes.cursor		 = waitcursor;
885645f5050Syouri    attributes.background_pixel	 = Scr->Black;
886645f5050Syouri    Scr->WindowMask = XCreateWindow (dpy, Scr->Root, 0, 0,
887645f5050Syouri			(unsigned int) Scr->rootw,
888645f5050Syouri			(unsigned int) Scr->rooth,
889645f5050Syouri			(unsigned int) 0,
890645f5050Syouri			CopyFromParent, (unsigned int) CopyFromParent,
891645f5050Syouri			(Visual *) CopyFromParent, valuemask,
892645f5050Syouri			&attributes);
893645f5050Syouri    XMapWindow (dpy, Scr->WindowMask);
894645f5050Syouri    XMaskEvent (dpy, ExposureMask, &event);
895645f5050Syouri
896645f5050Syouri    if (Scr->Monochrome != COLOR) return;
897645f5050Syouri
898645f5050Syouri    WelcomeCp.fore = Scr->Black;
899645f5050Syouri    WelcomeCp.back = Scr->White;
900645f5050Syouri    Scr->WelcomeCmap  = XCreateColormap (dpy, Scr->WindowMask, Scr->d_visual, AllocNone);
901645f5050Syouri    if (! Scr->WelcomeCmap) return;
902645f5050Syouri    XSetWindowColormap (dpy, Scr->WindowMask, Scr->WelcomeCmap);
903645f5050Syouri    black.red   = 0;
904645f5050Syouri    black.green = 0;
905645f5050Syouri    black.blue  = 0;
906645f5050Syouri    XAllocColor (dpy, Scr->WelcomeCmap, &black);
907645f5050Syouri
908645f5050Syouri    reportfilenotfound = 0;
909645f5050Syouri    AlternateCmap = Scr->WelcomeCmap;
910645f5050Syouri    if (! file) {
911645f5050Syouri	Scr->WelcomeImage  = GetImage ("xwd:welcome.xwd", WelcomeCp);
912645f5050Syouri#ifdef XPM
913645f5050Syouri	if (Scr->WelcomeImage == None)
914645f5050Syouri		Scr->WelcomeImage  = GetImage ("xpm:welcome.xpm", WelcomeCp);
915645f5050Syouri#endif
916645f5050Syouri    }
917645f5050Syouri    else {
918645f5050Syouri	Scr->WelcomeImage  = GetImage (file, WelcomeCp);
919645f5050Syouri    }
920645f5050Syouri    AlternateCmap = None;
921645f5050Syouri    reportfilenotfound = 1;
922645f5050Syouri    if (Scr->WelcomeImage == None) return;
923645f5050Syouri
924645f5050Syouri    if (captive) {
925645f5050Syouri	XSetWindowColormap (dpy, Scr->WindowMask, Scr->WelcomeCmap);
926645f5050Syouri	XSetWMColormapWindows (dpy, Scr->Root, &(Scr->WindowMask), 1);
927645f5050Syouri    }
928645f5050Syouri    else XInstallColormap (dpy, Scr->WelcomeCmap);
929645f5050Syouri
930645f5050Syouri    Scr->WelcomeGC = XCreateGC (dpy, Scr->WindowMask, 0, NULL);
931645f5050Syouri    x = (Scr->rootw  -  Scr->WelcomeImage->width) / 2;
932645f5050Syouri    y = (Scr->rooth - Scr->WelcomeImage->height) / 2;
933645f5050Syouri
934645f5050Syouri    XSetWindowBackground (dpy, Scr->WindowMask, black.pixel);
935645f5050Syouri    XClearWindow (dpy, Scr->WindowMask);
936645f5050Syouri    XCopyArea (dpy, Scr->WelcomeImage->pixmap, Scr->WindowMask, Scr->WelcomeGC, 0, 0,
937645f5050Syouri		Scr->WelcomeImage->width, Scr->WelcomeImage->height, x, y);
938645f5050Syouri}
939645f5050Syouri
940645f5050Syourivoid UnmaskScreen (void)
941645f5050Syouri{
942645f5050Syouri#ifdef VMS
943645f5050Syouri    float  timeout;
944645f5050Syouri#else
945645f5050Syouri    struct timeval	timeout;
946645f5050Syouri#endif
947645f5050Syouri    Colormap            stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
948645f5050Syouri    Colormap		cmap;
949645f5050Syouri    XColor		colors [256], stdcolors [256];
950645f5050Syouri    int			i, j, usec;
951645f5050Syouri
952645f5050Syouri#ifdef VMS
953645f5050Syouri    timeout = 0.017;
954645f5050Syouri#else
955645f5050Syouri    usec = 10000;
956645f5050Syouri    timeout.tv_usec = usec % (unsigned long) 1000000;
957645f5050Syouri    timeout.tv_sec  = usec / (unsigned long) 1000000;
958645f5050Syouri#endif
959645f5050Syouri
960645f5050Syouri    if (Scr->WelcomeImage) {
961645f5050Syouri	Pixel pixels [256];
962645f5050Syouri
963645f5050Syouri	cmap = Scr->WelcomeCmap;
964645f5050Syouri	for (i = 0; i < 256; i++) {
965645f5050Syouri	    pixels [i] = i;
966645f5050Syouri	    colors [i].pixel = i;
967645f5050Syouri	}
968645f5050Syouri	XQueryColors (dpy, cmap, colors, 256);
969645f5050Syouri	XFreeColors  (dpy, cmap, pixels, 256, 0L);
970645f5050Syouri	XFreeColors  (dpy, cmap, pixels, 256, 0L); /* Ah Ah */
971645f5050Syouri
972645f5050Syouri	for (i = 0; i < 256; i++) {
973645f5050Syouri	    colors [i].pixel = i;
974645f5050Syouri	    colors [i].flags = DoRed | DoGreen | DoBlue;
975645f5050Syouri	    stdcolors [i].red   = colors [i].red;
976645f5050Syouri	    stdcolors [i].green = colors [i].green;
977645f5050Syouri	    stdcolors [i].blue  = colors [i].blue;
978645f5050Syouri	}
979645f5050Syouri	for (i = 0; i < 128; i++) {
980645f5050Syouri	    for (j = 0; j < 256; j++) {
981645f5050Syouri		colors [j].red   = stdcolors [j].red   * ((127.0 - i) / 128.0);
982645f5050Syouri		colors [j].green = stdcolors [j].green * ((127.0 - i) / 128.0);
983645f5050Syouri		colors [j].blue  = stdcolors [j].blue  * ((127.0 - i) / 128.0);
984645f5050Syouri	    }
985645f5050Syouri	    XStoreColors (dpy, cmap, colors, 256);
986645f5050Syouri#ifdef VMS
987645f5050Syouri	    lib$wait(&timeout);
988645f5050Syouri#else
989645f5050Syouri	    select (0, (void *) 0, (void *) 0, (void *) 0, &timeout);
990645f5050Syouri#endif
991645f5050Syouri	}
992645f5050Syouri	XFreeColors   (dpy, cmap, pixels, 256, 0L);
993645f5050Syouri	XFreeGC       (dpy, Scr->WelcomeGC);
994645f5050Syouri	FreeImage     (Scr->WelcomeImage);
995645f5050Syouri    }
996645f5050Syouri    if (Scr->Monochrome != COLOR) goto fin;
997645f5050Syouri
998645f5050Syouri    cmap = XCreateColormap (dpy, Scr->Root, Scr->d_visual, AllocNone);
999645f5050Syouri    if (! cmap) goto fin;
1000645f5050Syouri    for (i = 0; i < 256; i++) {
1001645f5050Syouri	colors [i].pixel = i;
1002645f5050Syouri	colors [i].red   = 0;
1003645f5050Syouri	colors [i].green = 0;
1004645f5050Syouri	colors [i].blue  = 0;
1005645f5050Syouri	colors [i].flags = DoRed | DoGreen | DoBlue;
1006645f5050Syouri    }
1007645f5050Syouri    XStoreColors (dpy, cmap, colors, 256);
1008645f5050Syouri
1009645f5050Syouri    if (captive) XSetWindowColormap (dpy, Scr->Root, cmap);
1010645f5050Syouri    else XInstallColormap (dpy, cmap);
1011645f5050Syouri
1012645f5050Syouri    XUnmapWindow (dpy, Scr->WindowMask);
1013645f5050Syouri    XClearWindow (dpy, Scr->Root);
1014645f5050Syouri    XSync (dpy, 0);
1015645f5050Syouri    PaintAllDecoration ();
1016645f5050Syouri
1017645f5050Syouri    for (i = 0; i < 256; i++) stdcolors [i].pixel = i;
1018645f5050Syouri    XQueryColors (dpy, stdcmap, stdcolors, 256);
1019645f5050Syouri    for (i = 0; i < 128; i++) {
1020645f5050Syouri	for (j = 0; j < 256; j++) {
1021645f5050Syouri	    colors [j].pixel = j;
1022645f5050Syouri	    colors [j].red   = stdcolors [j].red   * (i / 127.0);
1023645f5050Syouri	    colors [j].green = stdcolors [j].green * (i / 127.0);
1024645f5050Syouri	    colors [j].blue  = stdcolors [j].blue  * (i / 127.0);
1025645f5050Syouri	    colors [j].flags = DoRed | DoGreen | DoBlue;
1026645f5050Syouri	}
1027645f5050Syouri	XStoreColors (dpy, cmap, colors, 256);
1028645f5050Syouri#ifdef VMS
1029645f5050Syouri        lib$wait(&timeout);
1030645f5050Syouri#else
1031645f5050Syouri	select (0, (void *) 0, (void *) 0, (void *) 0, &timeout);
1032645f5050Syouri#endif
1033645f5050Syouri    }
1034645f5050Syouri
1035645f5050Syouri    if (captive) XSetWindowColormap (dpy, Scr->Root, stdcmap);
1036645f5050Syouri    else XInstallColormap (dpy, stdcmap);
1037645f5050Syouri
1038645f5050Syouri    XFreeColormap (dpy, cmap);
1039645f5050Syouri
1040645f5050Syourifin:
1041645f5050Syouri    if (Scr->WelcomeCmap) XFreeColormap (dpy, Scr->WelcomeCmap);
1042645f5050Syouri    XDestroyWindow (dpy, Scr->WindowMask);
1043645f5050Syouri    Scr->WindowMask = (Window) 0;
1044645f5050Syouri}
1045645f5050Syouri
1046645f5050Syouri#ifdef VMS
1047645f5050Syouri
1048645f5050Syouri/* use the VMS system services to request the timer to issue an AST */
1049645f5050Syourivoid AnimateHandler (void);
1050645f5050Syouri
1051645f5050Syouriunsigned int tv[2];
1052645f5050Syouriint status;
1053645f5050Syouristatic unsigned long timefi;
1054645f5050Syouri/* unsigned long timefe = 17; */
1055645f5050Syouriunsigned long timefe;
1056645f5050Syouri
1057645f5050Syouri#define TIMID 12L
1058645f5050Syouri
1059645f5050Syourivoid StartAnimation (void)
1060645f5050Syouri{
1061645f5050Syouri    if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
1062645f5050Syouri    if (AnimationSpeed <= 0) return;
1063645f5050Syouri    if (AnimationActive) return;
1064645f5050Syouri
1065645f5050Syouri    if (!timefi) lib$get_ef(&timefi);
1066645f5050Syouri    if (!timefe) lib$get_ef(&timefe);
1067645f5050Syouri
1068645f5050Syouri    tv[1] = 0xFFFFFFFF;                   /* quadword negative for relative */
1069645f5050Syouri    tv[0] = -(10000000 / AnimationSpeed); /* time. In units of 100ns. */
1070645f5050Syouri    sys$clref(timefe);
1071645f5050Syouri    status = sys$setimr (timefi, &tv, AnimateHandler, TIMID );
1072645f5050Syouri    if (status != SS$_NORMAL) lib$signal(status);
1073645f5050Syouri    AnimationActive = True;
1074645f5050Syouri}
1075645f5050Syouri
1076645f5050Syourivoid StopAnimation () {
1077645f5050Syouri    if (AnimationSpeed <= 0) return;
1078645f5050Syouri    if (! AnimationActive) return;
1079645f5050Syouri    AnimationActive = False;
1080645f5050Syouri
1081645f5050Syouri    status = sys$cantim(TIMID, PSL$C_USER);
1082645f5050Syouri    if (status != SS$_NORMAL) lib$signal(status);
1083645f5050Syouri}
1084645f5050Syouri
1085645f5050Syourivoid SetAnimationSpeed (int speed)
1086645f5050Syouri{
1087645f5050Syouri    AnimationSpeed = speed;
1088645f5050Syouri    if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
1089645f5050Syouri}
1090645f5050Syouri
1091645f5050Syourivoid ModifyAnimationSpeed (int incr)
1092645f5050Syouri{
1093645f5050Syouri    if ((AnimationSpeed + incr) < 0) return;
1094645f5050Syouri    if ((AnimationSpeed + incr) == 0) {
1095645f5050Syouri	if (AnimationActive) StopAnimation ();
1096645f5050Syouri	AnimationSpeed = 0;
1097645f5050Syouri	return;
1098645f5050Syouri    }
1099645f5050Syouri    AnimationSpeed += incr;
1100645f5050Syouri
1101645f5050Syouri    status = sys$cantim(TIMID, PSL$C_USER);
1102645f5050Syouri    if (status != SS$_NORMAL) lib$signal(status);
1103645f5050Syouri
1104645f5050Syouri    tv[1] = 0xFFFFFFFF;
1105645f5050Syouri    tv[0] = -(10000000 / AnimationSpeed);
1106645f5050Syouri
1107645f5050Syouri    sys$clref(timefe);
1108645f5050Syouri    status = sys$setimr (timefi, &tv, AnimateHandler, TIMID);
1109645f5050Syouri    if (status != SS$_NORMAL) lib$signal(status);
1110645f5050Syouri
1111645f5050Syouri    AnimationActive = True;
1112645f5050Syouri}
1113645f5050Syouri
1114645f5050Syourivoid AnimateHandler (void) {
1115645f5050Syouri    AnimationPending = True;
1116645f5050Syouri
1117645f5050Syouri    sys$setef(timefe);
1118645f5050Syouri    status = sys$setimr (timefi, &tv, AnimateHandler, TIMID);
1119645f5050Syouri    if (status != SS$_NORMAL) lib$signal(status);
1120645f5050Syouri}
1121645f5050Syouri#else /* VMS */
1122645f5050Syouri
1123645f5050Syouri#ifdef USE_SIGNALS
1124645f5050SyouriSIGNAL_T AnimateHandler ();
1125645f5050Syouri#endif
1126645f5050Syouri
1127645f5050Syouri#ifndef USE_SIGNALS
1128645f5050Syourivoid TryToAnimate (void)
1129645f5050Syouri{
1130645f5050Syouri    struct timeval  tp;
1131645f5050Syouri    struct timezone tzp;
1132645f5050Syouri    static unsigned long lastsec;
1133645f5050Syouri    static long lastusec;
1134645f5050Syouri    unsigned long gap;
1135645f5050Syouri
1136645f5050Syouri    gettimeofday (&tp, &tzp);
1137645f5050Syouri    gap = ((tp.tv_sec - lastsec) * 1000000) + (tp.tv_usec - lastusec);
1138645f5050Syouri    if (tracefile) {
1139645f5050Syouri	fprintf (tracefile, "Time = %lu, %ld, %ld, %ld, %lu\n", lastsec,
1140645f5050Syouri		lastusec, (long)tp.tv_sec, (long)tp.tv_usec, gap);
1141645f5050Syouri	fflush (tracefile);
1142645f5050Syouri    }
1143645f5050Syouri    gap *= AnimationSpeed;
1144645f5050Syouri    if (gap < 1000000) return;
1145645f5050Syouri    if (tracefile) {
1146645f5050Syouri	fprintf (tracefile, "Animate\n");
1147645f5050Syouri	fflush (tracefile);
1148645f5050Syouri    }
1149645f5050Syouri    Animate ();
1150645f5050Syouri    lastsec  = tp.tv_sec;
1151645f5050Syouri    lastusec = tp.tv_usec;
1152645f5050Syouri}
1153645f5050Syouri#endif /* USE_SIGNALS */
1154645f5050Syouri
1155645f5050Syourivoid StartAnimation (void)
1156645f5050Syouri{
1157645f5050Syouri#ifdef USE_SIGNALS
1158645f5050Syouri    struct itimerval tv;
1159645f5050Syouri#endif
1160645f5050Syouri
1161645f5050Syouri    if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
1162645f5050Syouri    if (AnimationSpeed <= 0) AnimationSpeed = 0;
1163645f5050Syouri    if (AnimationActive) return;
1164645f5050Syouri#ifdef USE_SIGNALS
1165645f5050Syouri    if (AnimationSpeed == 0) return;
1166645f5050Syouri    signal (SIGALRM, AnimateHandler);
1167645f5050Syouri    if (AnimationSpeed == 1) {
1168645f5050Syouri	tv.it_interval.tv_sec  = 1;
1169645f5050Syouri	tv.it_interval.tv_usec = 0;
1170645f5050Syouri	tv.it_value.tv_sec     = 1;
1171645f5050Syouri	tv.it_value.tv_usec    = 0;
1172645f5050Syouri    }
1173645f5050Syouri    else {
1174645f5050Syouri	tv.it_interval.tv_sec  = 0;
1175645f5050Syouri	tv.it_interval.tv_usec = 1000000 / AnimationSpeed;
1176645f5050Syouri	tv.it_value.tv_sec     = 0;
1177645f5050Syouri	tv.it_value.tv_usec    = 1000000 / AnimationSpeed;
1178645f5050Syouri    }
1179645f5050Syouri    setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL);
1180645f5050Syouri#else /* USE_SIGNALS */
1181645f5050Syouri    switch (AnimationSpeed) {
1182645f5050Syouri	case 0 :
1183645f5050Syouri	    return;
1184645f5050Syouri	case 1 :
1185645f5050Syouri	    AnimateTimeout.tv_sec  = 1;
1186645f5050Syouri	    AnimateTimeout.tv_usec = 0;
1187645f5050Syouri	    break;
1188645f5050Syouri	default :
1189645f5050Syouri	    AnimateTimeout.tv_sec  = 0;
1190645f5050Syouri	    AnimateTimeout.tv_usec = 1000000 / AnimationSpeed;
1191645f5050Syouri    }
1192645f5050Syouri#endif /* USE_SIGNALS */
1193645f5050Syouri    AnimationActive = True;
1194645f5050Syouri}
1195645f5050Syouri
1196645f5050Syourivoid StopAnimation (void)
1197645f5050Syouri{
1198645f5050Syouri#ifdef USE_SIGNALS
1199645f5050Syouri    struct itimerval tv;
1200645f5050Syouri
1201645f5050Syouri    if (AnimationSpeed <= 0) return;
1202645f5050Syouri    if (! AnimationActive) return;
1203645f5050Syouri    signal (SIGALRM, SIG_IGN);
1204645f5050Syouri
1205645f5050Syouri    tv.it_value.tv_sec     = 0;
1206645f5050Syouri    tv.it_value.tv_usec    = 0;
1207645f5050Syouri    setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL);
1208645f5050Syouri#endif
1209645f5050Syouri    AnimationActive = False;
1210645f5050Syouri}
1211645f5050Syouri
1212645f5050Syourivoid SetAnimationSpeed (int speed)
1213645f5050Syouri{
1214645f5050Syouri    AnimationSpeed = speed;
1215645f5050Syouri    if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
1216645f5050Syouri}
1217645f5050Syouri
1218645f5050Syourivoid ModifyAnimationSpeed (int incr)
1219645f5050Syouri{
1220645f5050Syouri#ifdef USE_SIGNALS
1221645f5050Syouri    struct itimerval tv;
1222645f5050Syouri#endif
1223645f5050Syouri
1224645f5050Syouri    if ((AnimationSpeed + incr) < 0) return;
1225645f5050Syouri    if ((AnimationSpeed + incr) == 0) {
1226645f5050Syouri	if (AnimationActive) StopAnimation ();
1227645f5050Syouri	AnimationSpeed = 0;
1228645f5050Syouri	return;
1229645f5050Syouri    }
1230645f5050Syouri    AnimationSpeed += incr;
1231645f5050Syouri    if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
1232645f5050Syouri
1233645f5050Syouri#ifdef USE_SIGNALS
1234645f5050Syouri    signal (SIGALRM, AnimateHandler);
1235645f5050Syouri    if (AnimationSpeed == 1) {
1236645f5050Syouri	tv.it_interval.tv_sec  = 1;
1237645f5050Syouri	tv.it_interval.tv_usec = 0;
1238645f5050Syouri	tv.it_value.tv_sec     = 1;
1239645f5050Syouri	tv.it_value.tv_usec    = 0;
1240645f5050Syouri    }
1241645f5050Syouri    else {
1242645f5050Syouri	tv.it_interval.tv_sec  = 0;
1243645f5050Syouri	tv.it_interval.tv_usec = 1000000 / AnimationSpeed;
1244645f5050Syouri	tv.it_value.tv_sec     = 0;
1245645f5050Syouri	tv.it_value.tv_usec    = 1000000 / AnimationSpeed;
1246645f5050Syouri    }
1247645f5050Syouri    setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL);
1248645f5050Syouri#else /* USE_SIGNALS */
1249645f5050Syouri    if (AnimationSpeed == 1) {
1250645f5050Syouri	AnimateTimeout.tv_sec  = 1;
1251645f5050Syouri	AnimateTimeout.tv_usec = 0;
1252645f5050Syouri    }
1253645f5050Syouri    else {
1254645f5050Syouri	AnimateTimeout.tv_sec  = 0;
1255645f5050Syouri	AnimateTimeout.tv_usec = 1000000 / AnimationSpeed;
1256645f5050Syouri    }
1257645f5050Syouri#endif /* USE_SIGNALS */
1258645f5050Syouri    AnimationActive = True;
1259645f5050Syouri}
1260645f5050Syouri
1261645f5050Syouri#ifdef USE_SIGNALS
1262645f5050SyouriSIGNAL_T AnimateHandler (int dummy)
1263645f5050Syouri{
1264645f5050Syouri    signal (SIGALRM, AnimateHandler);
1265645f5050Syouri    AnimationPending = True;
1266645f5050Syouri}
1267645f5050Syouri#endif
1268645f5050Syouri#endif /* VMS */
1269645f5050Syouri
1270645f5050Syourivoid Animate (void)
1271645f5050Syouri{
1272645f5050Syouri    TwmWindow	*t;
1273645f5050Syouri    int		scrnum;
1274645f5050Syouri    ScreenInfo	*scr;
1275645f5050Syouri    int		i;
1276645f5050Syouri    TBWindow	*tbw;
1277645f5050Syouri    int		nb;
1278645f5050Syouri
1279645f5050Syouri    if (AnimationSpeed == 0) return;
1280645f5050Syouri#ifdef USE_SIGNALS
1281645f5050Syouri    AnimationPending = False;
1282645f5050Syouri#endif
1283645f5050Syouri
1284645f5050Syouri    MaybeAnimate = False;
1285645f5050Syouri    for (scrnum = 0; scrnum < NumScreens; scrnum++) {
1286645f5050Syouri	if ((scr = ScreenList [scrnum]) == NULL) continue;
1287645f5050Syouri
1288645f5050Syouri	for (t = scr->FirstWindow; t != NULL; t = t->next) {
1289645f5050Syouri	    if (! visible (t)) continue;
1290645f5050Syouri	    if (t->icon_on && t->icon && t->icon->bm_w && t->icon->image &&
1291645f5050Syouri		t->icon->image->next) {
1292645f5050Syouri		AnimateIcons (scr, t->icon);
1293645f5050Syouri		MaybeAnimate = True;
1294645f5050Syouri	    }
1295645f5050Syouri	    else
1296645f5050Syouri	    if (t->mapped && t->titlebuttons) {
1297645f5050Syouri		nb = scr->TBInfo.nleft + scr->TBInfo.nright;
1298645f5050Syouri		for (i = 0, tbw = t->titlebuttons; i < nb; i++, tbw++) {
1299645f5050Syouri		    if (tbw->image && tbw->image->next) {
1300645f5050Syouri			AnimateButton (tbw);
1301645f5050Syouri			MaybeAnimate = True;
1302645f5050Syouri		    }
1303645f5050Syouri		}
1304645f5050Syouri	    }
1305645f5050Syouri	}
1306645f5050Syouri	if (scr->Focus) {
1307645f5050Syouri	    t = scr->Focus;
1308645f5050Syouri	    if (t->mapped && t->titlehighlight && t->title_height &&
1309645f5050Syouri		t->HiliteImage && t->HiliteImage->next) {
1310645f5050Syouri		AnimateHighlight (t);
1311645f5050Syouri		MaybeAnimate = True;
1312645f5050Syouri	    }
1313645f5050Syouri	}
1314645f5050Syouri    }
1315645f5050Syouri    MaybeAnimate |= AnimateRoot ();
1316645f5050Syouri    XFlush (dpy);
1317645f5050Syouri    return;
1318645f5050Syouri}
1319645f5050Syouri
1320645f5050Syourivoid InsertRGBColormap (Atom a, XStandardColormap *maps, int nmaps,
1321645f5050Syouri			Bool replace)
1322645f5050Syouri{
1323645f5050Syouri    StdCmap *sc = NULL;
1324645f5050Syouri
1325645f5050Syouri    if (replace) {			/* locate existing entry */
1326645f5050Syouri	for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
1327645f5050Syouri	    if (sc->atom == a) break;
1328645f5050Syouri	}
1329645f5050Syouri    }
1330645f5050Syouri
1331645f5050Syouri    if (!sc) {				/* no existing, allocate new */
1332645f5050Syouri	sc = (StdCmap *) malloc (sizeof (StdCmap));
1333645f5050Syouri	if (!sc) {
1334645f5050Syouri	    fprintf (stderr, "%s:  unable to allocate %lu bytes for StdCmap\n",
1335645f5050Syouri		     ProgramName, (unsigned long) sizeof(StdCmap));
1336645f5050Syouri	    return;
1337645f5050Syouri	}
1338645f5050Syouri    }
1339645f5050Syouri
1340645f5050Syouri    if (replace) {			/* just update contents */
1341645f5050Syouri	if (sc->maps) XFree ((char *) maps);
1342645f5050Syouri	if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL;
1343645f5050Syouri    } else {				/* else appending */
1344645f5050Syouri	sc->next = NULL;
1345645f5050Syouri	sc->atom = a;
1346645f5050Syouri	if (Scr->StdCmapInfo.tail) {
1347645f5050Syouri	    Scr->StdCmapInfo.tail->next = sc;
1348645f5050Syouri	} else {
1349645f5050Syouri	    Scr->StdCmapInfo.head = sc;
1350645f5050Syouri	}
1351645f5050Syouri	Scr->StdCmapInfo.tail = sc;
1352645f5050Syouri    }
1353645f5050Syouri    sc->nmaps = nmaps;
1354645f5050Syouri    sc->maps = maps;
1355645f5050Syouri
1356645f5050Syouri    return;
1357645f5050Syouri}
1358645f5050Syouri
1359645f5050Syourivoid RemoveRGBColormap (Atom a)
1360645f5050Syouri{
1361645f5050Syouri    StdCmap *sc, *prev;
1362645f5050Syouri
1363645f5050Syouri    prev = NULL;
1364645f5050Syouri    for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
1365645f5050Syouri	if (sc->atom == a) break;
1366645f5050Syouri	prev = sc;
1367645f5050Syouri    }
1368645f5050Syouri    if (sc) {				/* found one */
1369645f5050Syouri	if (sc->maps) XFree ((char *) sc->maps);
1370645f5050Syouri	if (prev) prev->next = sc->next;
1371645f5050Syouri	if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next;
1372645f5050Syouri	if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev;
1373645f5050Syouri	if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL;
1374645f5050Syouri    }
1375645f5050Syouri    return;
1376645f5050Syouri}
1377645f5050Syouri
1378645f5050Syourivoid LocateStandardColormaps(void)
1379645f5050Syouri{
1380645f5050Syouri    Atom *atoms;
1381645f5050Syouri    int natoms;
1382645f5050Syouri    int i;
1383645f5050Syouri
1384645f5050Syouri    atoms = XListProperties (dpy, Scr->Root, &natoms);
1385645f5050Syouri    for (i = 0; i < natoms; i++) {
1386645f5050Syouri	XStandardColormap *maps = NULL;
1387645f5050Syouri	int nmaps;
1388645f5050Syouri
1389645f5050Syouri	if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
1390645f5050Syouri	    /* if got one, then append to current list */
1391645f5050Syouri	    InsertRGBColormap (atoms[i], maps, nmaps, False);
1392645f5050Syouri	}
1393645f5050Syouri    }
1394645f5050Syouri    if (atoms) XFree ((char *) atoms);
1395645f5050Syouri    return;
1396645f5050Syouri}
1397645f5050Syouri
1398645f5050Syourivoid GetColor(int kind, Pixel *what, char *name)
1399645f5050Syouri{
1400645f5050Syouri    XColor color;
1401645f5050Syouri    Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c;
1402645f5050Syouri
1403645f5050Syouri#ifndef TOM
1404645f5050Syouri    if (!Scr->FirstTime)
1405645f5050Syouri	return;
1406645f5050Syouri#endif
1407645f5050Syouri
1408645f5050Syouri    if (Scr->Monochrome != kind)
1409645f5050Syouri	return;
1410645f5050Syouri
1411645f5050Syouri    if (! XParseColor (dpy, cmap, name, &color)) {
1412645f5050Syouri	fprintf (stderr, "%s:  invalid color name \"%s\"\n", ProgramName, name);
1413645f5050Syouri	return;
1414645f5050Syouri    }
1415645f5050Syouri    if (! XAllocColor (dpy, cmap, &color))
1416645f5050Syouri    {
1417645f5050Syouri	/* if we could not allocate the color, let's see if this is a
1418645f5050Syouri	 * standard colormap
1419645f5050Syouri	 */
1420645f5050Syouri	XStandardColormap *stdcmap = NULL;
1421645f5050Syouri
1422645f5050Syouri	if (! XParseColor (dpy, cmap, name, &color)) {
1423645f5050Syouri	    fprintf (stderr, "%s:  invalid color name \"%s\"\n", ProgramName, name);
1424645f5050Syouri	    return;
1425645f5050Syouri	}
1426645f5050Syouri
1427645f5050Syouri	/*
1428645f5050Syouri	 * look through the list of standard colormaps (check cache first)
1429645f5050Syouri	 */
1430645f5050Syouri	if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps &&
1431645f5050Syouri	    (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap ==
1432645f5050Syouri	     cmap)) {
1433645f5050Syouri	    stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]);
1434645f5050Syouri	} else {
1435645f5050Syouri	    StdCmap *sc;
1436645f5050Syouri
1437645f5050Syouri	    for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
1438645f5050Syouri		int i;
1439645f5050Syouri
1440645f5050Syouri		for (i = 0; i < sc->nmaps; i++) {
1441645f5050Syouri		    if (sc->maps[i].colormap == cmap) {
1442645f5050Syouri			Scr->StdCmapInfo.mru = sc;
1443645f5050Syouri			Scr->StdCmapInfo.mruindex = i;
1444645f5050Syouri			stdcmap = &(sc->maps[i]);
1445645f5050Syouri			goto gotit;
1446645f5050Syouri		    }
1447645f5050Syouri		}
1448645f5050Syouri	    }
1449645f5050Syouri	}
1450645f5050Syouri
1451645f5050Syouri      gotit:
1452645f5050Syouri	if (stdcmap) {
1453645f5050Syouri            color.pixel = (stdcmap->base_pixel +
1454645f5050Syouri			   ((Pixel)(((float)color.red / 65535.0) *
1455645f5050Syouri				    stdcmap->red_max + 0.5) *
1456645f5050Syouri			    stdcmap->red_mult) +
1457645f5050Syouri			   ((Pixel)(((float)color.green /65535.0) *
1458645f5050Syouri				    stdcmap->green_max + 0.5) *
1459645f5050Syouri			    stdcmap->green_mult) +
1460645f5050Syouri			   ((Pixel)(((float)color.blue  / 65535.0) *
1461645f5050Syouri				    stdcmap->blue_max + 0.5) *
1462645f5050Syouri			    stdcmap->blue_mult));
1463645f5050Syouri        } else {
1464645f5050Syouri	    fprintf (stderr, "%s:  unable to allocate color \"%s\"\n",
1465645f5050Syouri		     ProgramName, name);
1466645f5050Syouri	    return;
1467645f5050Syouri	}
1468645f5050Syouri    }
1469645f5050Syouri
1470645f5050Syouri    *what = color.pixel;
1471645f5050Syouri    return;
1472645f5050Syouri}
1473645f5050Syouri
1474645f5050Syourivoid GetShadeColors (ColorPair *cp)
1475645f5050Syouri{
1476645f5050Syouri    XColor	xcol;
1477645f5050Syouri    Colormap	cmap = Scr->RootColormaps.cwins[0]->colormap->c;
1478645f5050Syouri    int		save;
1479645f5050Syouri    float	clearfactor;
1480645f5050Syouri    float	darkfactor;
1481645f5050Syouri    char	clearcol [32], darkcol [32];
1482645f5050Syouri
1483645f5050Syouri    clearfactor = (float) Scr->ClearShadowContrast / 100.0;
1484645f5050Syouri    darkfactor  = (100.0 - (float) Scr->DarkShadowContrast)  / 100.0;
1485645f5050Syouri    xcol.pixel = cp->back;
1486645f5050Syouri    XQueryColor (dpy, cmap, &xcol);
1487645f5050Syouri
1488645f5050Syouri    sprintf (clearcol, "#%04x%04x%04x",
1489645f5050Syouri		xcol.red   + (unsigned short) ((65535 -   xcol.red) * clearfactor),
1490645f5050Syouri		xcol.green + (unsigned short) ((65535 - xcol.green) * clearfactor),
1491645f5050Syouri		xcol.blue  + (unsigned short) ((65535 -  xcol.blue) * clearfactor));
1492645f5050Syouri    sprintf (darkcol,  "#%04x%04x%04x",
1493645f5050Syouri		(unsigned short) (xcol.red   * darkfactor),
1494645f5050Syouri		(unsigned short) (xcol.green * darkfactor),
1495645f5050Syouri		(unsigned short) (xcol.blue  * darkfactor));
1496645f5050Syouri
1497645f5050Syouri    save = Scr->FirstTime;
1498645f5050Syouri    Scr->FirstTime = True;
1499645f5050Syouri    GetColor (Scr->Monochrome, &cp->shadc, clearcol);
1500645f5050Syouri    GetColor (Scr->Monochrome, &cp->shadd,  darkcol);
1501645f5050Syouri    Scr->FirstTime = save;
1502645f5050Syouri}
1503645f5050Syouri
1504645f5050Syourivoid GetFont(MyFont *font)
1505645f5050Syouri{
1506645f5050Syouri    char *deffontname = "fixed,*";
1507645f5050Syouri    char **missing_charset_list_return;
1508645f5050Syouri    int missing_charset_count_return;
1509645f5050Syouri    char *def_string_return;
1510645f5050Syouri    XFontSetExtents *font_extents;
1511645f5050Syouri    XFontStruct **xfonts;
1512645f5050Syouri    char **font_names;
1513645f5050Syouri    register int i;
1514645f5050Syouri    int ascent;
1515645f5050Syouri    int descent;
1516645f5050Syouri    int fnum;
1517645f5050Syouri    char *basename2;
1518645f5050Syouri
1519645f5050Syouri    if (font->font_set != NULL){
1520645f5050Syouri	XFreeFontSet(dpy, font->font_set);
1521645f5050Syouri    }
1522645f5050Syouri
1523645f5050Syouri    basename2 = (char *)malloc(strlen(font->basename) + 3);
1524645f5050Syouri    if (basename2) sprintf(basename2, "%s,*", font->basename);
1525645f5050Syouri    else basename2 = font->basename;
1526645f5050Syouri    if( (font->font_set = XCreateFontSet(dpy, basename2,
1527645f5050Syouri				    &missing_charset_list_return,
1528645f5050Syouri				    &missing_charset_count_return,
1529645f5050Syouri				    &def_string_return)) == NULL) {
1530645f5050Syouri	if (Scr->DefaultFont.basename) {
1531645f5050Syouri	    deffontname = Scr->DefaultFont.basename;
1532645f5050Syouri	}
1533645f5050Syouri	if ((font->font_set = XCreateFontSet(dpy, deffontname,
1534645f5050Syouri					     &missing_charset_list_return,
1535645f5050Syouri					     &missing_charset_count_return,
1536645f5050Syouri					     &def_string_return)) == NULL)
1537645f5050Syouri	{
1538645f5050Syouri	    fprintf (stderr, "%s:  unable to open fonts \"%s\" or \"%s\"\n",
1539645f5050Syouri		     ProgramName, font->basename, deffontname);
1540645f5050Syouri	    exit(1);
1541645f5050Syouri	}
1542645f5050Syouri    }
1543645f5050Syouri    if (basename2 != font->basename) free(basename2);
1544645f5050Syouri    font_extents = XExtentsOfFontSet(font->font_set);
1545645f5050Syouri
1546645f5050Syouri    fnum = XFontsOfFontSet(font->font_set, &xfonts, &font_names);
1547645f5050Syouri    for( i = 0, ascent = 0, descent = 0; i<fnum; i++){
1548645f5050Syouri	ascent = MaxSize(ascent, (*xfonts)->ascent);
1549645f5050Syouri	descent = MaxSize(descent, (*xfonts)->descent);
1550645f5050Syouri	xfonts++;
1551645f5050Syouri    }
1552645f5050Syouri
1553645f5050Syouri    font->height = font_extents->max_logical_extent.height;
1554645f5050Syouri    font->y = ascent;
1555645f5050Syouri    font->ascent = ascent;
1556645f5050Syouri    font->descent = descent;
1557645f5050Syouri}
1558645f5050Syouri
1559645f5050Syouri
1560645f5050Syourivoid SetFocusVisualAttributes (TwmWindow *tmp_win, Bool focus)
1561645f5050Syouri{
1562645f5050Syouri    if (! tmp_win) return;
1563645f5050Syouri
1564645f5050Syouri    if (focus == tmp_win->hasfocusvisible) return;
1565645f5050Syouri    if (tmp_win->highlight) {
1566645f5050Syouri	if (Scr->use3Dborders) {
1567645f5050Syouri	    PaintBorders (tmp_win, focus);
1568645f5050Syouri	}
1569645f5050Syouri	else {
1570645f5050Syouri	    if (focus) {
1571645f5050Syouri		XSetWindowBorder (dpy, tmp_win->frame, tmp_win->borderC.back);
1572645f5050Syouri		if (tmp_win->title_w)
1573645f5050Syouri		    XSetWindowBorder (dpy, tmp_win->title_w, tmp_win->borderC.back);
1574645f5050Syouri	    } else {
1575645f5050Syouri		XSetWindowBorderPixmap (dpy, tmp_win->frame, tmp_win->gray);
1576645f5050Syouri		if (tmp_win->title_w)
1577645f5050Syouri		    XSetWindowBorderPixmap (dpy, tmp_win->title_w, tmp_win->gray);
1578645f5050Syouri	    }
1579645f5050Syouri	}
1580645f5050Syouri    }
1581645f5050Syouri
1582645f5050Syouri    if (focus) {
1583645f5050Syouri	Bool hil = False;
1584645f5050Syouri
1585645f5050Syouri	if (tmp_win->lolite_wl) XUnmapWindow (dpy, tmp_win->lolite_wl);
1586645f5050Syouri	if (tmp_win->lolite_wr) XUnmapWindow (dpy, tmp_win->lolite_wr);
1587645f5050Syouri	if (tmp_win->hilite_wl) {
1588645f5050Syouri	    XMapWindow (dpy, tmp_win->hilite_wl);
1589645f5050Syouri	    hil = True;
1590645f5050Syouri	}
1591645f5050Syouri	if (tmp_win->hilite_wr) {
1592645f5050Syouri	    XMapWindow (dpy, tmp_win->hilite_wr);
1593645f5050Syouri	    hil = True;
1594645f5050Syouri	}
1595645f5050Syouri	if (hil && tmp_win->HiliteImage && tmp_win->HiliteImage->next) {
1596645f5050Syouri	    MaybeAnimate = True;
1597645f5050Syouri	}
1598645f5050Syouri	if (tmp_win->iconmanagerlist)
1599645f5050Syouri	    ActiveIconManager (tmp_win->iconmanagerlist);
1600645f5050Syouri    }
1601645f5050Syouri    else {
1602645f5050Syouri	if (tmp_win->hilite_wl) XUnmapWindow (dpy, tmp_win->hilite_wl);
1603645f5050Syouri	if (tmp_win->hilite_wr) XUnmapWindow (dpy, tmp_win->hilite_wr);
1604645f5050Syouri	if (tmp_win->lolite_wl) XMapWindow (dpy, tmp_win->lolite_wl);
1605645f5050Syouri	if (tmp_win->lolite_wr) XMapWindow (dpy, tmp_win->lolite_wr);
1606645f5050Syouri	if (tmp_win->iconmanagerlist)
1607645f5050Syouri	    NotActiveIconManager (tmp_win->iconmanagerlist);
1608645f5050Syouri    }
1609645f5050Syouri    if (Scr->use3Dtitles && Scr->SunkFocusWindowTitle && tmp_win->title_height) {
1610645f5050Syouri	ButtonState bs;
1611645f5050Syouri
1612645f5050Syouri	bs = focus ? on : off;
1613645f5050Syouri	Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0,
1614645f5050Syouri			tmp_win->title_width - Scr->TBInfo.titlex -
1615645f5050Syouri			Scr->TBInfo.rightoff - Scr->TitlePadding,
1616645f5050Syouri			Scr->TitleHeight, Scr->TitleShadowDepth,
1617645f5050Syouri			tmp_win->title, bs, False, False);
1618645f5050Syouri    }
1619645f5050Syouri    tmp_win->hasfocusvisible = focus;
1620645f5050Syouri}
1621645f5050Syouri
1622645f5050Syouristatic void move_to_head (TwmWindow *t)
1623645f5050Syouri{
1624645f5050Syouri    if (t == NULL) return;
1625645f5050Syouri    if (Scr->FirstWindow == t) return;
1626645f5050Syouri
1627645f5050Syouri    if (t->prev) t->prev->next = t->next;
1628645f5050Syouri    if (t->next) t->next->prev = t->prev;
1629645f5050Syouri
1630645f5050Syouri    t->next = Scr->FirstWindow;
1631645f5050Syouri    if (Scr->FirstWindow != NULL)
1632645f5050Syouri	Scr->FirstWindow->prev = t;
1633645f5050Syouri    t->prev = NULL;
1634645f5050Syouri    Scr->FirstWindow = t;
1635645f5050Syouri}
1636645f5050Syouri
1637645f5050Syouri/*
1638645f5050Syouri * SetFocus - separate routine to set focus to make things more understandable
1639645f5050Syouri * and easier to debug
1640645f5050Syouri */
1641645f5050Syourivoid SetFocus (TwmWindow *tmp_win, Time	tim)
1642645f5050Syouri{
1643645f5050Syouri    Window w = (tmp_win ? tmp_win->w : PointerRoot);
1644645f5050Syouri    int f_iconmgr = 0;
1645645f5050Syouri
1646645f5050Syouri    if (Scr->Focus && (Scr->Focus->iconmgr)) f_iconmgr = 1;
1647645f5050Syouri    if (Scr->SloppyFocus && (w == PointerRoot) && (!f_iconmgr)) return;
1648645f5050Syouri
1649645f5050Syouri    XSetInputFocus (dpy, w, RevertToPointerRoot, tim);
1650645f5050Syouri    if (Scr->Focus == tmp_win) return;
1651645f5050Syouri
1652645f5050Syouri    if (Scr->Focus) {
1653645f5050Syouri	if (Scr->Focus->AutoSqueeze && !Scr->Focus->squeezed) {
1654645f5050Syouri	    AutoSqueeze (Scr->Focus);
1655645f5050Syouri	}
1656645f5050Syouri	SetFocusVisualAttributes (Scr->Focus, False);
1657645f5050Syouri    }
1658645f5050Syouri    if (tmp_win)    {
1659645f5050Syouri	if (tmp_win->AutoSqueeze && tmp_win->squeezed) {
1660645f5050Syouri	    AutoSqueeze (tmp_win);
1661645f5050Syouri	}
1662645f5050Syouri	SetFocusVisualAttributes (tmp_win, True);
1663645f5050Syouri    }
1664645f5050Syouri    Scr->Focus = tmp_win;
1665645f5050Syouri    move_to_head (tmp_win);
1666645f5050Syouri}
1667645f5050Syouri
1668645f5050Syouri#
1669645f5050Syouri#ifdef NOPUTENV
1670645f5050Syouri/*
1671645f5050Syouri * define our own putenv() if the system doesn't have one.
1672645f5050Syouri * putenv(s): place s (a string of the form "NAME=value") in
1673645f5050Syouri * the environment; replacing any existing NAME.  s is placed in
1674645f5050Syouri * environment, so if you change s, the environment changes (like
1675645f5050Syouri * putenv on a sun).  Binding removed if you putenv something else
1676645f5050Syouri * called NAME.
1677645f5050Syouri */
1678645f5050Syouriint
1679645f5050Syouriputenv(s)
1680645f5050Syouri    char *s;
1681645f5050Syouri{
1682645f5050Syouri    char *v;
1683645f5050Syouri    int varlen, idx;
1684645f5050Syouri    extern char **environ;
1685645f5050Syouri    char **newenv;
1686645f5050Syouri    static int virgin = 1; /* true while "environ" is a virgin */
1687645f5050Syouri
1688645f5050Syouri    v = strchr(s, '=');
1689645f5050Syouri    if(v == 0)
1690645f5050Syouri	return 0; /* punt if it's not of the right form */
1691645f5050Syouri    varlen = (v + 1) - s;
1692645f5050Syouri
1693645f5050Syouri    for (idx = 0; environ[idx] != 0; idx++) {
1694645f5050Syouri	if (strncmp(environ[idx], s, varlen) == 0) {
1695645f5050Syouri	    if(v[1] != 0) { /* true if there's a value */
1696645f5050Syouri		environ[idx] = s;
1697645f5050Syouri		return 0;
1698645f5050Syouri	    } else {
1699645f5050Syouri		do {
1700645f5050Syouri		    environ[idx] = environ[idx+1];
1701645f5050Syouri		} while(environ[++idx] != 0);
1702645f5050Syouri		return 0;
1703645f5050Syouri	    }
1704645f5050Syouri	}
1705645f5050Syouri    }
1706645f5050Syouri
1707645f5050Syouri    /* add to environment (unless no value; then just return) */
1708645f5050Syouri    if(v[1] == 0)
1709645f5050Syouri	return 0;
1710645f5050Syouri    if(virgin) {
1711645f5050Syouri	register i;
1712645f5050Syouri
1713645f5050Syouri	newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*)));
1714645f5050Syouri	if(newenv == 0)
1715645f5050Syouri	    return -1;
1716645f5050Syouri	for(i = idx-1; i >= 0; --i)
1717645f5050Syouri	    newenv[i] = environ[i];
1718645f5050Syouri	virgin = 0;     /* you're not a virgin anymore, sweety */
1719645f5050Syouri    } else {
1720645f5050Syouri	newenv = (char **) realloc((char *) environ,
1721645f5050Syouri				   (unsigned) ((idx + 2) * sizeof(char*)));
1722645f5050Syouri	if (newenv == 0)
1723645f5050Syouri	    return -1;
1724645f5050Syouri    }
1725645f5050Syouri
1726645f5050Syouri    environ = newenv;
1727645f5050Syouri    environ[idx] = s;
1728645f5050Syouri    environ[idx+1] = 0;
1729645f5050Syouri
1730645f5050Syouri    return 0;
1731645f5050Syouri}
1732645f5050Syouri#endif /* NOPUTENV */
1733645f5050Syouri
1734645f5050Syouri
1735645f5050Syouristatic Pixmap CreateXLogoPixmap (unsigned int *widthp, unsigned int *heightp)
1736645f5050Syouri{
1737645f5050Syouri    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
1738645f5050Syouri    if (h < 0) h = 0;
1739645f5050Syouri
1740645f5050Syouri    *widthp = *heightp = (unsigned int) h;
1741645f5050Syouri    if (Scr->tbpm.xlogo == None) {
1742645f5050Syouri	GC gc, gcBack;
1743645f5050Syouri
1744645f5050Syouri	Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1);
1745645f5050Syouri	gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
1746645f5050Syouri	XSetForeground (dpy, gc, 0);
1747645f5050Syouri	XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h);
1748645f5050Syouri	XSetForeground (dpy, gc, 1);
1749645f5050Syouri	gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
1750645f5050Syouri	XSetForeground (dpy, gcBack, 0);
1751645f5050Syouri
1752645f5050Syouri	/*
1753645f5050Syouri	 * draw the logo large so that it gets as dense as possible; then white
1754645f5050Syouri	 * out the edges so that they look crisp
1755645f5050Syouri	 */
1756645f5050Syouri	XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2);
1757645f5050Syouri	XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1);
1758645f5050Syouri
1759645f5050Syouri	/*
1760645f5050Syouri	 * done drawing
1761645f5050Syouri	 */
1762645f5050Syouri	XFreeGC (dpy, gc);
1763645f5050Syouri	XFreeGC (dpy, gcBack);
1764645f5050Syouri    }
1765645f5050Syouri    return Scr->tbpm.xlogo;
1766645f5050Syouri}
1767645f5050Syouri
1768645f5050Syouri
1769645f5050Syouristatic Pixmap CreateResizePixmap (unsigned int *widthp, unsigned int *heightp)
1770645f5050Syouri{
1771645f5050Syouri    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
1772645f5050Syouri    if (h < 1) h = 1;
1773645f5050Syouri
1774645f5050Syouri    *widthp = *heightp = (unsigned int) h;
1775645f5050Syouri    if (Scr->tbpm.resize == None) {
1776645f5050Syouri	XPoint	points[3];
1777645f5050Syouri	GC gc;
1778645f5050Syouri	int w;
1779645f5050Syouri	int lw;
1780645f5050Syouri
1781645f5050Syouri	/*
1782645f5050Syouri	 * create the pixmap
1783645f5050Syouri	 */
1784645f5050Syouri	Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1);
1785645f5050Syouri	gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL);
1786645f5050Syouri	XSetForeground (dpy, gc, 0);
1787645f5050Syouri	XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h);
1788645f5050Syouri	XSetForeground (dpy, gc, 1);
1789645f5050Syouri	lw = h / 16;
1790645f5050Syouri	if (lw == 1)
1791645f5050Syouri	    lw = 0;
1792645f5050Syouri	XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter);
1793645f5050Syouri
1794645f5050Syouri	/*
1795645f5050Syouri	 * draw the resize button,
1796645f5050Syouri	 */
1797645f5050Syouri	w = (h * 2) / 3;
1798645f5050Syouri	points[0].x = w;
1799645f5050Syouri	points[0].y = 0;
1800645f5050Syouri	points[1].x = w;
1801645f5050Syouri	points[1].y = w;
1802645f5050Syouri	points[2].x = 0;
1803645f5050Syouri	points[2].y = w;
1804645f5050Syouri	XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
1805645f5050Syouri	w = w / 2;
1806645f5050Syouri	points[0].x = w;
1807645f5050Syouri	points[0].y = 0;
1808645f5050Syouri	points[1].x = w;
1809645f5050Syouri	points[1].y = w;
1810645f5050Syouri	points[2].x = 0;
1811645f5050Syouri	points[2].y = w;
1812645f5050Syouri	XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
1813645f5050Syouri
1814645f5050Syouri	/*
1815645f5050Syouri	 * done drawing
1816645f5050Syouri	 */
1817645f5050Syouri	XFreeGC(dpy, gc);
1818645f5050Syouri    }
1819645f5050Syouri    return Scr->tbpm.resize;
1820645f5050Syouri}
1821645f5050Syouri
1822645f5050Syouristatic Pixmap CreateDotPixmap (unsigned int *widthp, unsigned int *heightp)
1823645f5050Syouri{
1824645f5050Syouri    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
1825645f5050Syouri
1826645f5050Syouri    h = h * 3 / 4;
1827645f5050Syouri    if (h < 1) h = 1;
1828645f5050Syouri    if (!(h & 1))
1829645f5050Syouri	h--;
1830645f5050Syouri    *widthp = *heightp = (unsigned int) h;
1831645f5050Syouri    if (Scr->tbpm.delete == None) {
1832645f5050Syouri	GC  gc;
1833645f5050Syouri	Pixmap pix;
1834645f5050Syouri
1835645f5050Syouri	pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1);
1836645f5050Syouri	gc = XCreateGC (dpy, pix, 0L, NULL);
1837645f5050Syouri	XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound);
1838645f5050Syouri	XSetForeground (dpy, gc, 0L);
1839645f5050Syouri	XFillRectangle (dpy, pix, gc, 0, 0, h, h);
1840645f5050Syouri	XSetForeground (dpy, gc, 1L);
1841645f5050Syouri	XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2);
1842645f5050Syouri	XFreeGC (dpy, gc);
1843645f5050Syouri    }
1844645f5050Syouri    return Scr->tbpm.delete;
1845645f5050Syouri}
1846645f5050Syouri
1847645f5050Syouristatic Image *Create3DCrossImage (ColorPair cp)
1848645f5050Syouri{
1849645f5050Syouri    Image *image;
1850645f5050Syouri    int        h;
1851645f5050Syouri    int    point;
1852645f5050Syouri    int midpoint;
1853645f5050Syouri
1854645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
1855645f5050Syouri    if (!(h & 1)) h--;
1856645f5050Syouri    point = 4;
1857645f5050Syouri    midpoint = h/2;
1858645f5050Syouri
1859645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
1860645f5050Syouri    if (! image) return (None);
1861645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
1862645f5050Syouri    if (image->pixmap == None) return (None);
1863645f5050Syouri
1864645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
1865645f5050Syouri
1866645f5050Syouri#ifdef LEVITTE_TEST
1867645f5050Syouri    FB (cp.shadc, cp.shadd);
1868645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point-1, point-1, point+1);
1869645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point, point, point+1);
1870645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point+1, midpoint-2, midpoint);
1871645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint+2, h-point-3, h-point-1);
1872645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point+1, h-point-3, h-point-2);
1873645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, h-point-2, midpoint-2, midpoint);
1874645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint-2, h-point-2, point-1);
1875645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-2, h-point-2, point);
1876645f5050Syouri#endif
1877645f5050Syouri
1878645f5050Syouri    FB (cp.shadd, cp.shadc);
1879645f5050Syouri#ifdef LEVITTE_TEST
1880645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point+1, h-point-1, h-point-2);
1881645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point, midpoint, midpoint-2);
1882645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, h-point-2);
1883645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, h-point-2, h-point-2, h-point);
1884645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, h-point-2, h-point-2, h-point-1);
1885645f5050Syouri#else
1886645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point-1, h-point-1);
1887645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point, h-point-1, h-point);
1888645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point-1, h-point, h-point-1);
1889645f5050Syouri#endif
1890645f5050Syouri
1891645f5050Syouri#ifdef LEVITTE_TEST
1892645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, point, h-point-1);
1893645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point, h-point-1, point);
1894645f5050Syouri#else
1895645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, h-point-1, point);
1896645f5050Syouri#endif
1897645f5050Syouri#ifdef LEVITTE_TEST
1898645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point-1, h-point-1, point+1);
1899645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point, midpoint, midpoint+2);
1900645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, point+1);
1901645f5050Syouri#else
1902645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, h-point-1, h-point-1, point-1);
1903645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point, h-point, point);
1904645f5050Syouri#endif
1905645f5050Syouri
1906645f5050Syouri    image->mask   = None;
1907645f5050Syouri    image->width  = h;
1908645f5050Syouri    image->height = h;
1909645f5050Syouri    image->next   = None;
1910645f5050Syouri
1911645f5050Syouri    return (image);
1912645f5050Syouri}
1913645f5050Syouri
1914645f5050Syouristatic Image *Create3DIconifyImage (ColorPair cp)
1915645f5050Syouri{
1916645f5050Syouri    Image *image;
1917645f5050Syouri    int     h;
1918645f5050Syouri    int point;
1919645f5050Syouri
1920645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
1921645f5050Syouri    if (!(h & 1)) h--;
1922645f5050Syouri    point = ((h/2-2) * 2+1) / 3;
1923645f5050Syouri
1924645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
1925645f5050Syouri    if (! image) return (None);
1926645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
1927645f5050Syouri    if (image->pixmap == None) return (None);
1928645f5050Syouri
1929645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
1930645f5050Syouri    FB (cp.shadd, cp.shadc);
1931645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h/2, h-point);
1932645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point, point);
1933645f5050Syouri
1934645f5050Syouri    FB (cp.shadc, cp.shadd);
1935645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, point, h/2+1, h-point);
1936645f5050Syouri    XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point+1, h/2+1, h-point-1);
1937645f5050Syouri
1938645f5050Syouri    image->mask   = None;
1939645f5050Syouri    image->width  = h;
1940645f5050Syouri    image->height = h;
1941645f5050Syouri    image->next   = None;
1942645f5050Syouri
1943645f5050Syouri    return (image);
1944645f5050Syouri}
1945645f5050Syouri
1946645f5050Syouristatic Image *Create3DSunkenResizeImage (ColorPair cp)
1947645f5050Syouri{
1948645f5050Syouri    int     h;
1949645f5050Syouri    Image *image;
1950645f5050Syouri
1951645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
1952645f5050Syouri    if (!(h & 1)) h--;
1953645f5050Syouri
1954645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
1955645f5050Syouri    if (! image) return (None);
1956645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
1957645f5050Syouri    if (image->pixmap == None) return (None);
1958645f5050Syouri
1959645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
1960645f5050Syouri    Draw3DBorder (image->pixmap, 3, 3, h-6, h-6, 1, cp, on, True, False);
1961645f5050Syouri    Draw3DBorder (image->pixmap, 3, ((h-6)/3)+3, ((h-6)*2/3)+1,
1962645f5050Syouri     ((h-6)*2/3)+1, 1, cp, on, True, False);
1963645f5050Syouri    Draw3DBorder (image->pixmap, 3, ((h-6)*2/3)+3, ((h-6)/3)+1,
1964645f5050Syouri     ((h-6)/3)+1, 1, cp, on, True, False);
1965645f5050Syouri
1966645f5050Syouri    image->mask   = None;
1967645f5050Syouri    image->width  = h;
1968645f5050Syouri    image->height = h;
1969645f5050Syouri    image->next   = None;
1970645f5050Syouri
1971645f5050Syouri    return (image);
1972645f5050Syouri}
1973645f5050Syouri
1974645f5050Syouristatic Image *Create3DBoxImage (ColorPair cp)
1975645f5050Syouri{
1976645f5050Syouri    int     h;
1977645f5050Syouri    Image   *image;
1978645f5050Syouri
1979645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
1980645f5050Syouri    if (! (h & 1)) h--;
1981645f5050Syouri
1982645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
1983645f5050Syouri    if (! image) return (None);
1984645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
1985645f5050Syouri    if (image->pixmap == None) return (None);
1986645f5050Syouri
1987645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
1988645f5050Syouri    Draw3DBorder (image->pixmap, (h / 2) - 4, (h / 2) - 4, 9, 9, 1, cp,
1989645f5050Syouri     off, True, False);
1990645f5050Syouri
1991645f5050Syouri    image->mask   = None;
1992645f5050Syouri    image->width  = h;
1993645f5050Syouri    image->height = h;
1994645f5050Syouri    image->next   = None;
1995645f5050Syouri
1996645f5050Syouri    return (image);
1997645f5050Syouri}
1998645f5050Syouri
1999645f5050Syouristatic Image *Create3DDotImage (ColorPair cp)
2000645f5050Syouri{
2001645f5050Syouri    Image *image;
2002645f5050Syouri    int	  h;
2003645f5050Syouri    static int idepth = 2;
2004645f5050Syouri
2005645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2006645f5050Syouri    if (!(h & 1)) h--;
2007645f5050Syouri
2008645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
2009645f5050Syouri    if (! image) return (None);
2010645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2011645f5050Syouri    if (image->pixmap == None) return (None);
2012645f5050Syouri
2013645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2014645f5050Syouri    Draw3DBorder (image->pixmap, (h / 2) - idepth,
2015645f5050Syouri				 (h / 2) - idepth,
2016645f5050Syouri				 2 * idepth + 1,
2017645f5050Syouri				 2 * idepth + 1,
2018645f5050Syouri				 idepth, cp, off, True, False);
2019645f5050Syouri    image->mask   = None;
2020645f5050Syouri    image->width  = h;
2021645f5050Syouri    image->height = h;
2022645f5050Syouri    image->next   = None;
2023645f5050Syouri    return (image);
2024645f5050Syouri}
2025645f5050Syouri
2026645f5050Syouristatic Image *Create3DBarImage (ColorPair cp)
2027645f5050Syouri{
2028645f5050Syouri    Image *image;
2029645f5050Syouri    int	  h;
2030645f5050Syouri    static int idepth = 2;
2031645f5050Syouri
2032645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2033645f5050Syouri    if (!(h & 1)) h--;
2034645f5050Syouri
2035645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
2036645f5050Syouri    if (! image) return (None);
2037645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2038645f5050Syouri    if (image->pixmap == None) return (None);
2039645f5050Syouri
2040645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2041645f5050Syouri    Draw3DBorder (image->pixmap,
2042645f5050Syouri			Scr->TitleButtonShadowDepth + 2,
2043645f5050Syouri			(h / 2) - idepth,
2044645f5050Syouri			h - 2 * (Scr->TitleButtonShadowDepth + 2),
2045645f5050Syouri			2 * idepth + 1,
2046645f5050Syouri			idepth, cp, off, True, False);
2047645f5050Syouri    image->mask   = None;
2048645f5050Syouri    image->width  = h;
2049645f5050Syouri    image->height = h;
2050645f5050Syouri    image->next   = None;
2051645f5050Syouri    return (image);
2052645f5050Syouri}
2053645f5050Syouri
2054645f5050Syouristatic Image *Create3DVertBarImage (ColorPair cp)
2055645f5050Syouri{
2056645f5050Syouri    Image *image;
2057645f5050Syouri    int	  h;
2058645f5050Syouri    static int idepth = 2;
2059645f5050Syouri
2060645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2061645f5050Syouri    if (!(h & 1)) h--;
2062645f5050Syouri
2063645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
2064645f5050Syouri    if (! image) return (None);
2065645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2066645f5050Syouri    if (image->pixmap == None) return (None);
2067645f5050Syouri
2068645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2069645f5050Syouri    Draw3DBorder (image->pixmap,
2070645f5050Syouri			(h / 2) - idepth,
2071645f5050Syouri			Scr->TitleButtonShadowDepth + 2,
2072645f5050Syouri			2 * idepth + 1,
2073645f5050Syouri			h - 2 * (Scr->TitleButtonShadowDepth + 2),
2074645f5050Syouri			idepth, cp, off, True, False);
2075645f5050Syouri    image->mask   = None;
2076645f5050Syouri    image->width  = h;
2077645f5050Syouri    image->height = h;
2078645f5050Syouri    image->next   = None;
2079645f5050Syouri    return (image);
2080645f5050Syouri}
2081645f5050Syouri
2082645f5050Syouristatic Image *Create3DMenuImage (ColorPair cp)
2083645f5050Syouri{
2084645f5050Syouri    Image *image;
2085645f5050Syouri    int	  h, i;
2086645f5050Syouri
2087645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2088645f5050Syouri    if (!(h & 1)) h--;
2089645f5050Syouri
2090645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
2091645f5050Syouri    if (! image) return (None);
2092645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2093645f5050Syouri    if (image->pixmap == None) return (None);
2094645f5050Syouri
2095645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2096645f5050Syouri    for (i = 4; i < h - 7; i += 5) {
2097645f5050Syouri	Draw3DBorder (image->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False);
2098645f5050Syouri    }
2099645f5050Syouri    image->mask   = None;
2100645f5050Syouri    image->width  = h;
2101645f5050Syouri    image->height = h;
2102645f5050Syouri    image->next   = None;
2103645f5050Syouri    return (image);
2104645f5050Syouri}
2105645f5050Syouri
2106645f5050Syouristatic Image *Create3DResizeImage (ColorPair cp)
2107645f5050Syouri{
2108645f5050Syouri    Image *image;
2109645f5050Syouri    int	  h;
2110645f5050Syouri
2111645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2112645f5050Syouri    if (!(h & 1)) h--;
2113645f5050Syouri
2114645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
2115645f5050Syouri    if (! image) return (None);
2116645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2117645f5050Syouri    if (image->pixmap == None) return (None);
2118645f5050Syouri
2119645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2120645f5050Syouri    Draw3DBorder (image->pixmap, 0, h / 4, ((3 * h) / 4) + 1, ((3 * h) / 4) + 1, 2,
2121645f5050Syouri		cp, off, True, False);
2122645f5050Syouri    Draw3DBorder (image->pixmap, 0, h / 2, (h / 2) + 1, (h / 2) + 1, 2, cp, off, True, False);
2123645f5050Syouri    image->mask   = None;
2124645f5050Syouri    image->width  = h;
2125645f5050Syouri    image->height = h;
2126645f5050Syouri    image->next   = None;
2127645f5050Syouri    return (image);
2128645f5050Syouri}
2129645f5050Syouri
2130645f5050Syouristatic Image *Create3DZoomImage (ColorPair cp)
2131645f5050Syouri{
2132645f5050Syouri    Image *image;
2133645f5050Syouri    int		h;
2134645f5050Syouri    static int idepth = 2;
2135645f5050Syouri
2136645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2137645f5050Syouri    if (!(h & 1)) h--;
2138645f5050Syouri
2139645f5050Syouri    image = (Image*) malloc (sizeof (struct _Image));
2140645f5050Syouri    if (! image) return (None);
2141645f5050Syouri    image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2142645f5050Syouri    if (image->pixmap == None) return (None);
2143645f5050Syouri
2144645f5050Syouri    Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2145645f5050Syouri    Draw3DBorder (image->pixmap, Scr->TitleButtonShadowDepth + 2,
2146645f5050Syouri				 Scr->TitleButtonShadowDepth + 2,
2147645f5050Syouri				 h - 2 * (Scr->TitleButtonShadowDepth + 2),
2148645f5050Syouri				 h - 2 * (Scr->TitleButtonShadowDepth + 2),
2149645f5050Syouri				 idepth, cp, off, True, False);
2150645f5050Syouri
2151645f5050Syouri    image->mask   = None;
2152645f5050Syouri    image->width  = h;
2153645f5050Syouri    image->height = h;
2154645f5050Syouri    image->next   = None;
2155645f5050Syouri    return (image);
2156645f5050Syouri}
2157645f5050Syouri
2158645f5050Syouristruct Colori {
2159645f5050Syouri    Pixel color;
2160645f5050Syouri    Pixmap pix;
2161645f5050Syouri    struct Colori *next;
2162645f5050Syouri};
2163645f5050Syouri
2164645f5050SyouriPixmap Create3DMenuIcon (unsigned int height,
2165645f5050Syouri			 unsigned int *widthp, unsigned int *heightp,
2166645f5050Syouri			 ColorPair cp)
2167645f5050Syouri{
2168645f5050Syouri    unsigned int h, w;
2169645f5050Syouri    int		i;
2170645f5050Syouri    struct Colori *col;
2171645f5050Syouri    static struct Colori *colori = NULL;
2172645f5050Syouri
2173645f5050Syouri    h = height;
2174645f5050Syouri    w = h * 7 / 8;
2175645f5050Syouri    if (h < 1) h = 1;
2176645f5050Syouri    if (w < 1) w = 1;
2177645f5050Syouri    *widthp  = w;
2178645f5050Syouri    *heightp = h;
2179645f5050Syouri
2180645f5050Syouri    for (col = colori; col; col = col->next) {
2181645f5050Syouri	if (col->color == cp.back) break;
2182645f5050Syouri    }
2183645f5050Syouri    if (col != NULL) {
2184645f5050Syouri	return (col->pix);
2185645f5050Syouri    }
2186645f5050Syouri    col = (struct Colori*) malloc (sizeof (struct Colori));
2187645f5050Syouri    col->color = cp.back;
2188645f5050Syouri    col->pix   = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2189645f5050Syouri    col->next = colori;
2190645f5050Syouri    colori = col;
2191645f5050Syouri
2192645f5050Syouri    Draw3DBorder (col->pix, 0, 0, w, h, 1, cp, off, True, False);
2193645f5050Syouri    for (i = 3; i + 5 < h; i += 5) {
2194645f5050Syouri	Draw3DBorder (col->pix, 4, i, w - 8, 3, 1, Scr->MenuC, off, True, False);
2195645f5050Syouri    }
2196645f5050Syouri    return (colori->pix);
2197645f5050Syouri}
2198645f5050Syouri
2199645f5050Syouri#include "siconify.bm"
2200645f5050Syouri
2201645f5050SyouriPixmap Create3DIconManagerIcon (ColorPair cp)
2202645f5050Syouri{
2203645f5050Syouri    unsigned int w, h;
2204645f5050Syouri    struct Colori *col;
2205645f5050Syouri    static struct Colori *colori = NULL;
2206645f5050Syouri
2207645f5050Syouri    w = (unsigned int) siconify_width;
2208645f5050Syouri    h = (unsigned int) siconify_height;
2209645f5050Syouri
2210645f5050Syouri    for (col = colori; col; col = col->next) {
2211645f5050Syouri	if (col->color == cp.back) break;
2212645f5050Syouri    }
2213645f5050Syouri    if (col != NULL) {
2214645f5050Syouri	return (col->pix);
2215645f5050Syouri    }
2216645f5050Syouri    col = (struct Colori*) malloc (sizeof (struct Colori));
2217645f5050Syouri    col->color = cp.back;
2218645f5050Syouri    col->pix   = XCreatePixmap (dpy, Scr->Root, w, h, Scr->d_depth);
2219645f5050Syouri    Draw3DBorder (col->pix, 0, 0, w, h, 4, cp, off, True, False);
2220645f5050Syouri    col->next = colori;
2221645f5050Syouri    colori = col;
2222645f5050Syouri
2223645f5050Syouri    return (colori->pix);
2224645f5050Syouri}
2225645f5050Syouri
2226645f5050Syouristatic Image *Create3DResizeAnimation (Bool in, Bool left, Bool top,
2227645f5050Syouri				       ColorPair cp)
2228645f5050Syouri{
2229645f5050Syouri    int		h, i, j;
2230645f5050Syouri    Image	*image, *im, *im1;
2231645f5050Syouri
2232645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2233645f5050Syouri    if (!(h & 1)) h--;
2234645f5050Syouri
2235645f5050Syouri    image = im1 = None;
2236645f5050Syouri    for (i = (in ? 0 : (h/4)-1); (i < h/4) && (i >= 0); i += (in ? 1 : -1)) {
2237645f5050Syouri	im = (Image*) malloc (sizeof (struct _Image));
2238645f5050Syouri	if (! im) return (None);
2239645f5050Syouri	im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2240645f5050Syouri	if (im->pixmap == None) {
2241645f5050Syouri	    free (im);
2242645f5050Syouri	    return (None);
2243645f5050Syouri	}
2244645f5050Syouri	Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2245645f5050Syouri	for (j = i; j <= h; j += (h/4)){
2246645f5050Syouri	    Draw3DBorder (im->pixmap, (left ? 0 : j), (top ? 0 : j),
2247645f5050Syouri			  h - j, h - j, 2, cp, off, True, False);
2248645f5050Syouri	}
2249645f5050Syouri	im->mask   = None;
2250645f5050Syouri	im->width  = h;
2251645f5050Syouri	im->height = h;
2252645f5050Syouri	im->next   = None;
2253645f5050Syouri	if (image == None) {
2254645f5050Syouri	    image = im1 = im;
2255645f5050Syouri	}
2256645f5050Syouri	else {
2257645f5050Syouri	    im1->next = im;
2258645f5050Syouri	    im1 = im;
2259645f5050Syouri	}
2260645f5050Syouri    }
2261645f5050Syouri    if (im1 != None) im1->next = image;
2262645f5050Syouri    return (image);
2263645f5050Syouri}
2264645f5050Syouri
2265645f5050Syouristatic Image *Create3DResizeInTopAnimation (ColorPair cp)
2266645f5050Syouri{
2267645f5050Syouri    return Create3DResizeAnimation (TRUE, FALSE, TRUE, cp);
2268645f5050Syouri}
2269645f5050Syouri
2270645f5050Syouristatic Image *Create3DResizeOutTopAnimation (ColorPair cp)
2271645f5050Syouri{
2272645f5050Syouri    return Create3DResizeAnimation (False, FALSE, TRUE, cp);
2273645f5050Syouri}
2274645f5050Syouri
2275645f5050Syouristatic Image *Create3DResizeInBotAnimation (ColorPair cp)
2276645f5050Syouri{
2277645f5050Syouri    return Create3DResizeAnimation (TRUE, TRUE, FALSE, cp);
2278645f5050Syouri}
2279645f5050Syouri
2280645f5050Syouristatic Image *Create3DResizeOutBotAnimation (ColorPair cp)
2281645f5050Syouri{
2282645f5050Syouri    return Create3DResizeAnimation (False, TRUE, FALSE, cp);
2283645f5050Syouri}
2284645f5050Syouri
2285645f5050Syouristatic Image *Create3DMenuAnimation (Bool up, ColorPair cp)
2286645f5050Syouri{
2287645f5050Syouri    int               h, i, j;
2288645f5050Syouri    Image     *image, *im, *im1;
2289645f5050Syouri
2290645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2291645f5050Syouri    if (!(h & 1)) h--;
2292645f5050Syouri
2293645f5050Syouri    image = im1 = None;
2294645f5050Syouri    for (j = (up ? 4 : 0); j != (up ? -1 : 5); j+= (up ? -1 : 1)) {
2295645f5050Syouri	im = (Image*) malloc (sizeof (struct _Image));
2296645f5050Syouri	if (! im) return (None);
2297645f5050Syouri	im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2298645f5050Syouri	if (im->pixmap == None) {
2299645f5050Syouri	    free (im);
2300645f5050Syouri	    return (None);
2301645f5050Syouri	}
2302645f5050Syouri	Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2303645f5050Syouri	for (i = j; i < h - 3; i += 5) {
2304645f5050Syouri	    Draw3DBorder (im->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False);
2305645f5050Syouri	}
2306645f5050Syouri	im->mask   = None;
2307645f5050Syouri	im->width  = h;
2308645f5050Syouri	im->height = h;
2309645f5050Syouri	im->next   = None;
2310645f5050Syouri	if (image == None) {
2311645f5050Syouri	    image = im1 = im;
2312645f5050Syouri	}
2313645f5050Syouri	else {
2314645f5050Syouri	    im1->next = im;
2315645f5050Syouri	    im1 = im;
2316645f5050Syouri	}
2317645f5050Syouri    }
2318645f5050Syouri    if (im1 != None) im1->next = image;
2319645f5050Syouri    return (image);
2320645f5050Syouri}
2321645f5050Syouri
2322645f5050Syouristatic Image *Create3DMenuUpAnimation (ColorPair cp)
2323645f5050Syouri{
2324645f5050Syouri    return Create3DMenuAnimation (TRUE, cp);
2325645f5050Syouri}
2326645f5050Syouri
2327645f5050Syouristatic Image *Create3DMenuDownAnimation (ColorPair cp)
2328645f5050Syouri{
2329645f5050Syouri    return Create3DMenuAnimation (False, cp);
2330645f5050Syouri}
2331645f5050Syouri
2332645f5050Syouristatic Image *Create3DZoomAnimation (Bool in, Bool out, int n, ColorPair cp)
2333645f5050Syouri{
2334645f5050Syouri    int		h, i, j, k;
2335645f5050Syouri    Image	*image, *im, *im1;
2336645f5050Syouri
2337645f5050Syouri    h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2338645f5050Syouri    if (!(h & 1)) h--;
2339645f5050Syouri
2340645f5050Syouri    if (n == 0) n = (h/2) - 2;
2341645f5050Syouri
2342645f5050Syouri    image = im1 = None;
2343645f5050Syouri    for (j = (out ? -1 : 1) ; j < (in ? 2 : 0); j += 2){
2344645f5050Syouri	for(k = (j > 0 ? 0 : n-1) ; (k >= 0) && (k < n); k += j){
2345645f5050Syouri	    im = (Image*) malloc (sizeof (struct _Image));
2346645f5050Syouri	    im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
2347645f5050Syouri	    Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
2348645f5050Syouri	    for (i = 2 + k; i < (h / 2); i += n) {
2349645f5050Syouri		Draw3DBorder (im->pixmap, i, i, h - (2 * i), h - (2 * i), 2, cp, off, True, False);
2350645f5050Syouri	    }
2351645f5050Syouri	    im->mask   = None;
2352645f5050Syouri	    im->width  = h;
2353645f5050Syouri	    im->height = h;
2354645f5050Syouri	    im->next   = None;
2355645f5050Syouri	    if (image == None) {
2356645f5050Syouri		image = im1 = im;
2357645f5050Syouri	    }
2358645f5050Syouri	    else {
2359645f5050Syouri		im1->next = im;
2360645f5050Syouri		im1 = im;
2361645f5050Syouri	    }
2362645f5050Syouri	}
2363645f5050Syouri    }
2364645f5050Syouri    if (im1 != None) im1->next = image;
2365645f5050Syouri    return (image);
2366645f5050Syouri}
2367645f5050Syouri
2368645f5050Syouristatic Image *Create3DMazeInAnimation (ColorPair cp)
2369645f5050Syouri{
2370645f5050Syouri    return Create3DZoomAnimation(TRUE, FALSE, 6, cp);
2371645f5050Syouri}
2372645f5050Syouri
2373645f5050Syouristatic Image *Create3DMazeOutAnimation (ColorPair cp)
2374645f5050Syouri{
2375645f5050Syouri    return Create3DZoomAnimation(FALSE, TRUE, 6, cp);
2376645f5050Syouri}
2377645f5050Syouri
2378645f5050Syouristatic Image *Create3DZoomInAnimation (ColorPair cp)
2379645f5050Syouri{
2380645f5050Syouri    return Create3DZoomAnimation(TRUE, FALSE, 0, cp);
2381645f5050Syouri}
2382645f5050Syouri
2383645f5050Syouristatic Image *Create3DZoomOutAnimation (ColorPair cp)
2384645f5050Syouri{
2385645f5050Syouri    return Create3DZoomAnimation(FALSE, TRUE, 0, cp);
2386645f5050Syouri}
2387645f5050Syouri
2388645f5050Syouristatic Image *Create3DZoomInOutAnimation (ColorPair cp)
2389645f5050Syouri{
2390645f5050Syouri    return Create3DZoomAnimation(TRUE, TRUE, 0, cp);
2391645f5050Syouri}
2392645f5050Syouri
2393645f5050Syouri#define questionmark_width 8
2394645f5050Syouri#define questionmark_height 8
2395645f5050Syouristatic char questionmark_bits[] = {
2396645f5050Syouri   0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18};
2397645f5050Syouri
2398645f5050Syouristatic Pixmap CreateQuestionPixmap (unsigned int *widthp,
2399645f5050Syouri				    unsigned int *heightp)
2400645f5050Syouri{
2401645f5050Syouri    *widthp = questionmark_width;
2402645f5050Syouri    *heightp = questionmark_height;
2403645f5050Syouri    if (Scr->tbpm.question == None) {
2404645f5050Syouri	Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root,
2405645f5050Syouri						    questionmark_bits,
2406645f5050Syouri						    questionmark_width,
2407645f5050Syouri						    questionmark_height);
2408645f5050Syouri    }
2409645f5050Syouri    /*
2410645f5050Syouri     * this must succeed or else we are in deep trouble elsewhere
2411645f5050Syouri     */
2412645f5050Syouri    return Scr->tbpm.question;
2413645f5050Syouri}
2414645f5050Syouri
2415645f5050Syouri
2416645f5050Syouristatic Pixmap CreateMenuPixmap (unsigned int *widthp, unsigned int *heightp)
2417645f5050Syouri{
2418645f5050Syouri    return (CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2,widthp,heightp));
2419645f5050Syouri}
2420645f5050Syouri
2421645f5050SyouriPixmap CreateMenuIcon (int height, unsigned int *widthp, unsigned int *heightp)
2422645f5050Syouri{
2423645f5050Syouri    int h, w;
2424645f5050Syouri    int ih, iw;
2425645f5050Syouri    int	ix, iy;
2426645f5050Syouri    int	mh, mw;
2427645f5050Syouri    int	tw, th;
2428645f5050Syouri    int	lw, lh;
2429645f5050Syouri    int	lx, ly;
2430645f5050Syouri    int	lines, dly;
2431645f5050Syouri    int offset;
2432645f5050Syouri    int	bw;
2433645f5050Syouri
2434645f5050Syouri    h = height;
2435645f5050Syouri    w = h * 7 / 8;
2436645f5050Syouri    if (h < 1)
2437645f5050Syouri	h = 1;
2438645f5050Syouri    if (w < 1)
2439645f5050Syouri	w = 1;
2440645f5050Syouri    *widthp = w;
2441645f5050Syouri    *heightp = h;
2442645f5050Syouri    if (Scr->tbpm.menu == None) {
2443645f5050Syouri	Pixmap  pix;
2444645f5050Syouri	GC	gc;
2445645f5050Syouri
2446645f5050Syouri	pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1);
2447645f5050Syouri	gc = XCreateGC (dpy, pix, 0L, NULL);
2448645f5050Syouri	XSetForeground (dpy, gc, 0L);
2449645f5050Syouri	XFillRectangle (dpy, pix, gc, 0, 0, w, h);
2450645f5050Syouri	XSetForeground (dpy, gc, 1L);
2451645f5050Syouri	ix = 1;
2452645f5050Syouri	iy = 1;
2453645f5050Syouri	ih = h - iy * 2;
2454645f5050Syouri	iw = w - ix * 2;
2455645f5050Syouri	offset = ih / 8;
2456645f5050Syouri	mh = ih - offset;
2457645f5050Syouri	mw = iw - offset;
2458645f5050Syouri	bw = mh / 16;
2459645f5050Syouri	if (bw == 0 && mw > 2)
2460645f5050Syouri	    bw = 1;
2461645f5050Syouri	tw = mw - bw * 2;
2462645f5050Syouri	th = mh - bw * 2;
2463645f5050Syouri	XFillRectangle (dpy, pix, gc, ix, iy, mw, mh);
2464645f5050Syouri	XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh);
2465645f5050Syouri	XSetForeground (dpy, gc, 0L);
2466645f5050Syouri	XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th);
2467645f5050Syouri	XSetForeground (dpy, gc, 1L);
2468645f5050Syouri	lw = tw / 2;
2469645f5050Syouri	if ((tw & 1) ^ (lw & 1))
2470645f5050Syouri	    lw++;
2471645f5050Syouri	lx = ix + bw + (tw - lw) / 2;
2472645f5050Syouri
2473645f5050Syouri	lh = th / 2 - bw;
2474645f5050Syouri	if ((lh & 1) ^ ((th - bw) & 1))
2475645f5050Syouri	    lh++;
2476645f5050Syouri	ly = iy + bw + (th - bw - lh) / 2;
2477645f5050Syouri
2478645f5050Syouri	lines = 3;
2479645f5050Syouri	if ((lh & 1) && lh < 6)
2480645f5050Syouri	{
2481645f5050Syouri	    lines--;
2482645f5050Syouri	}
2483645f5050Syouri	dly = lh / (lines - 1);
2484645f5050Syouri	while (lines--)
2485645f5050Syouri	{
2486645f5050Syouri	    XFillRectangle (dpy, pix, gc, lx, ly, lw, bw);
2487645f5050Syouri	    ly += dly;
2488645f5050Syouri	}
2489645f5050Syouri	XFreeGC (dpy, gc);
2490645f5050Syouri    }
2491645f5050Syouri    return Scr->tbpm.menu;
2492645f5050Syouri}
2493645f5050Syouri
2494645f5050Syouri#define FBGC(gc, fix_fore, fix_back)\
2495645f5050Syouri    Gcv.foreground = fix_fore;\
2496645f5050Syouri    Gcv.background = fix_back;\
2497645f5050Syouri    XChangeGC(dpy, gc, GCForeground|GCBackground,&Gcv)
2498645f5050Syouri
2499645f5050Syourivoid Draw3DBorder (Window w, int x, int y, int width, int height, int bw,
2500645f5050Syouri		   ColorPair cp, int state, int fill, int forcebw)
2501645f5050Syouri{
2502645f5050Syouri    int		  i;
2503645f5050Syouri    XGCValues	  gcv;
2504645f5050Syouri    unsigned long gcm;
2505645f5050Syouri
2506645f5050Syouri    if ((width < 1) || (height < 1)) return;
2507645f5050Syouri    if (Scr->Monochrome != COLOR) {
2508645f5050Syouri	if (fill) {
2509645f5050Syouri	    gcm = GCFillStyle;
2510645f5050Syouri	    gcv.fill_style = FillOpaqueStippled;
2511645f5050Syouri	    XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
2512645f5050Syouri	    XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height);
2513645f5050Syouri	}
2514645f5050Syouri	gcm  = 0;
2515645f5050Syouri	gcm |= GCLineStyle;
2516645f5050Syouri	gcv.line_style = (state == on) ? LineSolid : LineDoubleDash;
2517645f5050Syouri	gcm |= GCFillStyle;
2518645f5050Syouri	gcv.fill_style = FillSolid;
2519645f5050Syouri	XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
2520645f5050Syouri	for (i = 0; i < bw; i++) {
2521645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x,                 y + i,
2522645f5050Syouri					    x + width - i - 1, y + i);
2523645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x + i,                  y,
2524645f5050Syouri					    x + i, y + height - i - 1);
2525645f5050Syouri	}
2526645f5050Syouri
2527645f5050Syouri	gcm  = 0;
2528645f5050Syouri	gcm |= GCLineStyle;
2529645f5050Syouri	gcv.line_style = (state == on) ? LineDoubleDash : LineSolid;
2530645f5050Syouri	gcm |= GCFillStyle;
2531645f5050Syouri	gcv.fill_style = FillSolid;
2532645f5050Syouri	XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
2533645f5050Syouri	for (i = 0; i < bw; i++) {
2534645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1,          y + i,
2535645f5050Syouri					    x + width - i - 1, y + height - 1);
2536645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x + i,         y + height - i - 1,
2537645f5050Syouri					    x + width - 1, y + height - i - 1);
2538645f5050Syouri	}
2539645f5050Syouri	return;
2540645f5050Syouri    }
2541645f5050Syouri
2542645f5050Syouri    if (fill) {
2543645f5050Syouri	FBGC (Scr->BorderGC, cp.back, cp.fore);
2544645f5050Syouri	XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height);
2545645f5050Syouri    }
2546645f5050Syouri    if (Scr->BeNiceToColormap) {
2547645f5050Syouri	int dashoffset = 0;
2548645f5050Syouri
2549645f5050Syouri	gcm  = 0;
2550645f5050Syouri	gcm |= GCLineStyle;
2551645f5050Syouri	gcv.line_style = (forcebw) ? LineSolid : LineDoubleDash;
2552645f5050Syouri	gcm |= GCBackground;
2553645f5050Syouri	gcv.background = cp.back;
2554645f5050Syouri	XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
2555645f5050Syouri
2556645f5050Syouri	if (state == on)
2557645f5050Syouri	    XSetForeground (dpy, Scr->BorderGC, Scr->Black);
2558645f5050Syouri	else
2559645f5050Syouri	    XSetForeground (dpy, Scr->BorderGC, Scr->White);
2560645f5050Syouri	for (i = 0; i < bw; i++) {
2561645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x + i,     y + dashoffset,
2562645f5050Syouri					    x + i, y + height - i - 1);
2563645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x + dashoffset,    y + i,
2564645f5050Syouri					    x + width - i - 1, y + i);
2565645f5050Syouri	    dashoffset = 1 - dashoffset;
2566645f5050Syouri	}
2567645f5050Syouri	XSetForeground (dpy, Scr->BorderGC, ((state == on) ? Scr->White : Scr->Black));
2568645f5050Syouri	for (i = 0; i < bw; i++) {
2569645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x + i,         y + height - i - 1,
2570645f5050Syouri					    x + width - 1, y + height - i - 1);
2571645f5050Syouri	    XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1,          y + i,
2572645f5050Syouri					    x + width - i - 1, y + height - 1);
2573645f5050Syouri	}
2574645f5050Syouri	return;
2575645f5050Syouri    }
2576645f5050Syouri    if (state == on) { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); }
2577645f5050Syouri    else             { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); }
2578645f5050Syouri    for (i = 0; i < bw; i++) {
2579645f5050Syouri	XDrawLine (dpy, w, Scr->BorderGC, x,                 y + i,
2580645f5050Syouri					  x + width - i - 1, y + i);
2581645f5050Syouri	XDrawLine (dpy, w, Scr->BorderGC, x + i,                  y,
2582645f5050Syouri					  x + i, y + height - i - 1);
2583645f5050Syouri    }
2584645f5050Syouri
2585645f5050Syouri    if (state == on) { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); }
2586645f5050Syouri    else             { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); }
2587645f5050Syouri    for (i = 0; i < bw; i++) {
2588645f5050Syouri	XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1,          y + i,
2589645f5050Syouri					  x + width - i - 1, y + height - 1);
2590645f5050Syouri	XDrawLine (dpy, w, Scr->BorderGC, x + i,         y + height - i - 1,
2591645f5050Syouri					  x + width - 1, y + height - i - 1);
2592645f5050Syouri    }
2593645f5050Syouri    return;
2594645f5050Syouri}
2595645f5050Syouri
2596645f5050Syourivoid Draw3DCorner (Window w,
2597645f5050Syouri		   int x, int y, int width, int height, int thick, int bw,
2598645f5050Syouri		   ColorPair cp, int type)
2599645f5050Syouri{
2600645f5050Syouri    XRectangle rects [2];
2601645f5050Syouri
2602645f5050Syouri    switch (type) {
2603645f5050Syouri	case 0 :
2604645f5050Syouri	    Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
2605645f5050Syouri	    Draw3DBorder (w, x + thick - bw, y + thick - bw,
2606645f5050Syouri			width - thick + 2 * bw, height - thick + 2 * bw,
2607645f5050Syouri			bw, cp, on, True, False);
2608645f5050Syouri	    break;
2609645f5050Syouri	case 1 :
2610645f5050Syouri	    Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
2611645f5050Syouri	    Draw3DBorder (w, x, y + thick - bw,
2612645f5050Syouri			width - thick + bw, height - thick,
2613645f5050Syouri			bw, cp, on, True, False);
2614645f5050Syouri	    break;
2615645f5050Syouri	case 2 :
2616645f5050Syouri	    rects [0].x      = x + width - thick;
2617645f5050Syouri	    rects [0].y      = y;
2618645f5050Syouri	    rects [0].width  = thick;
2619645f5050Syouri	    rects [0].height = height;
2620645f5050Syouri	    rects [1].x      = x;
2621645f5050Syouri	    rects [1].y      = y + width - thick;
2622645f5050Syouri	    rects [1].width  = width - thick;
2623645f5050Syouri	    rects [1].height = thick;
2624645f5050Syouri	    XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted);
2625645f5050Syouri	    Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
2626645f5050Syouri	    Draw3DBorder (w, x, y,
2627645f5050Syouri			width - thick + bw, height - thick + bw,
2628645f5050Syouri			bw, cp, on, True, False);
2629645f5050Syouri	    XSetClipMask (dpy, Scr->BorderGC, None);
2630645f5050Syouri	    break;
2631645f5050Syouri	case 3 :
2632645f5050Syouri	    rects [0].x      = x;
2633645f5050Syouri	    rects [0].y      = y;
2634645f5050Syouri	    rects [0].width  = thick;
2635645f5050Syouri	    rects [0].height = height;
2636645f5050Syouri	    rects [1].x      = x + thick;
2637645f5050Syouri	    rects [1].y      = y + height - thick;
2638645f5050Syouri	    rects [1].width  = width - thick;
2639645f5050Syouri	    rects [1].height = thick;
2640645f5050Syouri	    XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted);
2641645f5050Syouri	    Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
2642645f5050Syouri	    Draw3DBorder (w, x + thick - bw, y,
2643645f5050Syouri			width - thick, height - thick + bw,
2644645f5050Syouri			bw, cp, on, True, False);
2645645f5050Syouri	    XSetClipMask (dpy, Scr->BorderGC, None);
2646645f5050Syouri	    break;
2647645f5050Syouri    }
2648645f5050Syouri    return;
2649645f5050Syouri}
2650645f5050Syouri
2651645f5050Syourivoid PaintAllDecoration (void)
2652645f5050Syouri{
2653645f5050Syouri    TwmWindow *tmp_win;
2654645f5050Syouri    virtualScreen *vs;
2655645f5050Syouri
2656645f5050Syouri    for (tmp_win = Scr->FirstWindow; tmp_win != NULL; tmp_win = tmp_win->next) {
2657645f5050Syouri	if (! visible (tmp_win)) continue;
2658645f5050Syouri	if (tmp_win->mapped == TRUE) {
2659645f5050Syouri	    if (tmp_win->frame_bw3D) {
2660645f5050Syouri		if (tmp_win->highlight && tmp_win == Scr->Focus)
2661645f5050Syouri		    PaintBorders (tmp_win, True);
2662645f5050Syouri		else
2663645f5050Syouri		    PaintBorders (tmp_win, False);
2664645f5050Syouri	    }
2665645f5050Syouri	    if (tmp_win->title_w)      PaintTitle        (tmp_win);
2666645f5050Syouri	    if (tmp_win->titlebuttons) PaintTitleButtons (tmp_win);
2667645f5050Syouri	}
2668645f5050Syouri	else
2669645f5050Syouri	if ((tmp_win->icon_on == TRUE)  &&
2670645f5050Syouri		!tmp_win->icon_not_ours &&
2671645f5050Syouri		!Scr->NoIconTitlebar    &&
2672645f5050Syouri		tmp_win->icon           &&
2673645f5050Syouri		tmp_win->icon->w        &&
2674645f5050Syouri		! LookInList (Scr->NoIconTitle, tmp_win->full_name, &tmp_win->class)) {
2675645f5050Syouri	    PaintIcon (tmp_win);
2676645f5050Syouri	}
2677645f5050Syouri    }
2678645f5050Syouri    for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
2679645f5050Syouri      PaintWorkSpaceManager (vs);
2680645f5050Syouri    }
2681645f5050Syouri}
2682645f5050Syouri
2683645f5050Syourivoid PaintBorders (TwmWindow *tmp_win, Bool focus)
2684645f5050Syouri{
2685645f5050Syouri    ColorPair cp;
2686645f5050Syouri
2687645f5050Syouri    cp = (focus && tmp_win->highlight) ? tmp_win->borderC : tmp_win->border_tile;
2688645f5050Syouri    if (tmp_win->title_height == 0) {
2689645f5050Syouri	Draw3DBorder (tmp_win->frame,
2690645f5050Syouri	    0,
2691645f5050Syouri	    0,
2692645f5050Syouri	    tmp_win->frame_width,
2693645f5050Syouri	    tmp_win->frame_height,
2694645f5050Syouri	    Scr->BorderShadowDepth, cp, off, True, False);
2695645f5050Syouri	Draw3DBorder (tmp_win->frame,
2696645f5050Syouri	    tmp_win->frame_bw3D - Scr->BorderShadowDepth,
2697645f5050Syouri	    tmp_win->frame_bw3D - Scr->BorderShadowDepth,
2698645f5050Syouri	    tmp_win->frame_width  - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth,
2699645f5050Syouri	    tmp_win->frame_height - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth,
2700645f5050Syouri	    Scr->BorderShadowDepth, cp, on, True, False);
2701645f5050Syouri	return;
2702645f5050Syouri    }
2703645f5050Syouri    Draw3DCorner (tmp_win->frame,
2704645f5050Syouri		tmp_win->title_x - tmp_win->frame_bw3D,
2705645f5050Syouri		0,
2706645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2707645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2708645f5050Syouri		tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 0);
2709645f5050Syouri    Draw3DCorner (tmp_win->frame,
2710645f5050Syouri		tmp_win->title_x + tmp_win->title_width - Scr->TitleHeight,
2711645f5050Syouri		0,
2712645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2713645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2714645f5050Syouri		tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 1);
2715645f5050Syouri    Draw3DCorner (tmp_win->frame,
2716645f5050Syouri		tmp_win->frame_width  - (Scr->TitleHeight + tmp_win->frame_bw3D),
2717645f5050Syouri		tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D),
2718645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2719645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2720645f5050Syouri		tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 2);
2721645f5050Syouri    Draw3DCorner (tmp_win->frame,
2722645f5050Syouri		0,
2723645f5050Syouri		tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D),
2724645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2725645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2726645f5050Syouri		tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 3);
2727645f5050Syouri
2728645f5050Syouri    Draw3DBorder (tmp_win->frame,
2729645f5050Syouri		tmp_win->title_x + Scr->TitleHeight,
2730645f5050Syouri		0,
2731645f5050Syouri		tmp_win->title_width - 2 * Scr->TitleHeight,
2732645f5050Syouri		tmp_win->frame_bw3D,
2733645f5050Syouri		Scr->BorderShadowDepth, cp, off, True, False);
2734645f5050Syouri    Draw3DBorder (tmp_win->frame,
2735645f5050Syouri		tmp_win->frame_bw3D + Scr->TitleHeight,
2736645f5050Syouri		tmp_win->frame_height - tmp_win->frame_bw3D,
2737645f5050Syouri		tmp_win->frame_width - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D),
2738645f5050Syouri		tmp_win->frame_bw3D,
2739645f5050Syouri		Scr->BorderShadowDepth, cp, off, True, False);
2740645f5050Syouri    Draw3DBorder (tmp_win->frame,
2741645f5050Syouri		0,
2742645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2743645f5050Syouri		tmp_win->frame_bw3D,
2744645f5050Syouri		tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D),
2745645f5050Syouri		Scr->BorderShadowDepth, cp, off, True, False);
2746645f5050Syouri    Draw3DBorder (tmp_win->frame,
2747645f5050Syouri		tmp_win->frame_width  - tmp_win->frame_bw3D,
2748645f5050Syouri		Scr->TitleHeight + tmp_win->frame_bw3D,
2749645f5050Syouri		tmp_win->frame_bw3D,
2750645f5050Syouri		tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D),
2751645f5050Syouri		Scr->BorderShadowDepth, cp, off, True, False);
2752645f5050Syouri
2753645f5050Syouri    if (tmp_win->squeeze_info && !tmp_win->squeezed) {
2754645f5050Syouri	Draw3DBorder (tmp_win->frame,
2755645f5050Syouri		0,
2756645f5050Syouri		Scr->TitleHeight,
2757645f5050Syouri		tmp_win->title_x,
2758645f5050Syouri		tmp_win->frame_bw3D,
2759645f5050Syouri		Scr->BorderShadowDepth, cp, off, True, False);
2760645f5050Syouri	Draw3DBorder (tmp_win->frame,
2761645f5050Syouri		tmp_win->title_x + tmp_win->title_width,
2762645f5050Syouri		Scr->TitleHeight,
2763645f5050Syouri		tmp_win->frame_width - tmp_win->title_x - tmp_win->title_width,
2764645f5050Syouri		tmp_win->frame_bw3D,
2765645f5050Syouri		Scr->BorderShadowDepth, cp, off, True, False);
2766645f5050Syouri    }
2767645f5050Syouri}
2768645f5050Syouri
2769645f5050Syourivoid PaintTitle (TwmWindow *tmp_win)
2770645f5050Syouri{
2771645f5050Syouri    int width, mwidth, len;
2772645f5050Syouri    XRectangle inc_rect;
2773645f5050Syouri    XRectangle logical_rect;
2774645f5050Syouri
2775645f5050Syouri    if (Scr->use3Dtitles) {
2776645f5050Syouri	if (Scr->SunkFocusWindowTitle && (Scr->Focus == tmp_win) &&
2777645f5050Syouri	    (tmp_win->title_height != 0))
2778645f5050Syouri	    Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0,
2779645f5050Syouri		tmp_win->title_width - Scr->TBInfo.titlex -
2780645f5050Syouri		Scr->TBInfo.rightoff - Scr->TitlePadding,
2781645f5050Syouri		Scr->TitleHeight, Scr->TitleShadowDepth,
2782645f5050Syouri		tmp_win->title, on, True, False);
2783645f5050Syouri	else
2784645f5050Syouri	    Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0,
2785645f5050Syouri		tmp_win->title_width - Scr->TBInfo.titlex -
2786645f5050Syouri		Scr->TBInfo.rightoff - Scr->TitlePadding,
2787645f5050Syouri		Scr->TitleHeight, Scr->TitleShadowDepth,
2788645f5050Syouri		tmp_win->title, off, True, False);
2789645f5050Syouri    }
2790645f5050Syouri    FB(tmp_win->title.fore, tmp_win->title.back);
2791645f5050Syouri    if (Scr->use3Dtitles) {
2792645f5050Syouri	len    = strlen(tmp_win->name);
2793645f5050Syouri	XmbTextExtents(Scr->TitleBarFont.font_set,
2794645f5050Syouri		       tmp_win->name, strlen (tmp_win->name),
2795645f5050Syouri		       &inc_rect, &logical_rect);
2796645f5050Syouri	width = logical_rect.width;
2797645f5050Syouri	mwidth = tmp_win->title_width  - Scr->TBInfo.titlex -
2798645f5050Syouri		 Scr->TBInfo.rightoff  - Scr->TitlePadding  -
2799645f5050Syouri		 Scr->TitleShadowDepth - 4;
2800645f5050Syouri	while ((len > 0) && (width > mwidth)) {
2801645f5050Syouri	    len--;
2802645f5050Syouri	    XmbTextExtents(Scr->TitleBarFont.font_set,
2803645f5050Syouri			   tmp_win->name, len,
2804645f5050Syouri			   &inc_rect, &logical_rect);
2805645f5050Syouri	    width = logical_rect.width;
2806645f5050Syouri	}
2807645f5050Syouri	if (Scr->Monochrome != COLOR) {
2808645f5050Syouri	    XmbDrawImageString(dpy, tmp_win->title_w, Scr->TitleBarFont.font_set,
2809645f5050Syouri			     Scr->NormalGC,
2810645f5050Syouri			     tmp_win->name_x,
2811645f5050Syouri			     Scr->TitleBarFont.y + Scr->TitleShadowDepth,
2812645f5050Syouri			     tmp_win->name, len);
2813645f5050Syouri	}
2814645f5050Syouri	else {
2815645f5050Syouri	    XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set,
2816645f5050Syouri			   Scr->NormalGC, tmp_win->name_x,
2817645f5050Syouri			   Scr->TitleBarFont.y + Scr->TitleShadowDepth,
2818645f5050Syouri			   tmp_win->name, len);
2819645f5050Syouri	}
2820645f5050Syouri    }
2821645f5050Syouri    else
2822645f5050Syouri        XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set,
2823645f5050Syouri		       Scr->NormalGC,
2824645f5050Syouri		       tmp_win->name_x, Scr->TitleBarFont.y,
2825645f5050Syouri		       tmp_win->name, strlen(tmp_win->name));
2826645f5050Syouri}
2827645f5050Syouri
2828645f5050Syourivoid PaintIcon (TwmWindow *tmp_win)
2829645f5050Syouri{
2830645f5050Syouri    int		width, twidth, mwidth, len, x;
2831645f5050Syouri    Icon	*icon;
2832645f5050Syouri    XRectangle inc_rect;
2833645f5050Syouri    XRectangle logical_rect;
2834645f5050Syouri
2835645f5050Syouri    if (!tmp_win || !tmp_win->icon) return;
2836645f5050Syouri    icon = tmp_win->icon;
2837645f5050Syouri    if (!icon->has_title) return;
2838645f5050Syouri
2839645f5050Syouri    x     = 0;
2840645f5050Syouri    width = icon->w_width;
2841645f5050Syouri    if (Scr->ShrinkIconTitles && icon->title_shrunk) {
2842645f5050Syouri	x     = GetIconOffset (icon);
2843645f5050Syouri	width = icon->width;
2844645f5050Syouri    }
2845645f5050Syouri    len    = strlen (tmp_win->icon_name);
2846645f5050Syouri    XmbTextExtents(Scr->IconFont.font_set,
2847645f5050Syouri		   tmp_win->icon_name, len,
2848645f5050Syouri		   &inc_rect, &logical_rect);
2849645f5050Syouri    twidth = logical_rect.width;
2850645f5050Syouri    mwidth = width - 2 * Scr->IconManagerShadowDepth - 6;
2851645f5050Syouri    if (Scr->use3Diconmanagers) {
2852645f5050Syouri	Draw3DBorder (icon->w, x, icon->height, width,
2853645f5050Syouri		Scr->IconFont.height + 2 * Scr->IconManagerShadowDepth + 6,
2854645f5050Syouri		Scr->IconManagerShadowDepth, icon->iconc, off, False, False);
2855645f5050Syouri    }
2856645f5050Syouri    while ((len > 0) && (twidth > mwidth)) {
2857645f5050Syouri	len--;
2858645f5050Syouri	XmbTextExtents(Scr->IconFont.font_set,
2859645f5050Syouri		       tmp_win->icon_name, len,
2860645f5050Syouri		       &inc_rect, &logical_rect);
2861645f5050Syouri	twidth = logical_rect.width;
2862645f5050Syouri    }
2863645f5050Syouri    FB (icon->iconc.fore, icon->iconc.back);
2864645f5050Syouri    XmbDrawString(dpy, icon->w, Scr->IconFont.font_set, Scr->NormalGC,
2865645f5050Syouri		  x + ((mwidth - twidth)/2) + Scr->IconManagerShadowDepth + 3,
2866645f5050Syouri		  icon->y, tmp_win->icon_name, len);
2867645f5050Syouri}
2868645f5050Syouri
2869645f5050Syourivoid PaintTitleButton (TwmWindow *tmp_win, TBWindow  *tbw)
2870645f5050Syouri{
2871645f5050Syouri    TitleButton *tb = tbw->info;
2872645f5050Syouri
2873645f5050Syouri    XCopyArea (dpy, tbw->image->pixmap, tbw->window, Scr->NormalGC,
2874645f5050Syouri		tb->srcx, tb->srcy, tb->width, tb->height,
2875645f5050Syouri		tb->dstx, tb->dsty);
2876645f5050Syouri    return;
2877645f5050Syouri}
2878645f5050Syouri
2879645f5050Syourivoid PaintTitleButtons (TwmWindow *tmp_win)
2880645f5050Syouri{
2881645f5050Syouri    int i;
2882645f5050Syouri    TBWindow *tbw;
2883645f5050Syouri    int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
2884645f5050Syouri
2885645f5050Syouri    for (i = 0, tbw = tmp_win->titlebuttons; i < nb; i++, tbw++) {
2886645f5050Syouri	if (tbw) PaintTitleButton (tmp_win, tbw);
2887645f5050Syouri    }
2888645f5050Syouri}
2889645f5050Syouri
2890645f5050Syourivoid adoptWindow (void)
2891645f5050Syouri{
2892645f5050Syouri    unsigned long	data [2];
2893645f5050Syouri    Window		localroot, w;
2894645f5050Syouri    unsigned char	*prop;
2895645f5050Syouri    unsigned long	bytesafter;
2896645f5050Syouri    unsigned long	len;
2897645f5050Syouri    Atom		actual_type;
2898645f5050Syouri    int			actual_format;
2899645f5050Syouri    XEvent		event;
2900645f5050Syouri    Window		root, parent, child, *children;
2901645f5050Syouri    unsigned int	nchildren, key_buttons;
2902645f5050Syouri    int			root_x, root_y, win_x, win_y;
2903645f5050Syouri    int			ret;
2904645f5050Syouri
2905645f5050Syouri    localroot = w = RootWindow (dpy, Scr->screen);
2906645f5050Syouri    XGrabPointer (dpy, localroot, False,
2907645f5050Syouri			ButtonPressMask | ButtonReleaseMask,
2908645f5050Syouri			GrabModeAsync, GrabModeAsync,
2909645f5050Syouri		        None, Scr->SelectCursor, CurrentTime);
2910645f5050Syouri
2911645f5050Syouri    XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event);
2912645f5050Syouri    child = event.xbutton.subwindow;
2913645f5050Syouri    while (1) {
2914645f5050Syouri	if (child == (Window) 0) break;
2915645f5050Syouri
2916645f5050Syouri	w = XmuClientWindow (dpy, child);
2917645f5050Syouri	ret = XGetWindowProperty (dpy, w, _XA_WM_WORKSPACESLIST, 0L, 512,
2918645f5050Syouri			False, XA_STRING, &actual_type, &actual_format, &len,
2919645f5050Syouri			&bytesafter, &prop);
2920645f5050Syouri	XFree ((char *)prop); /* Don't ever do anything with it */
2921645f5050Syouri	if (ret != Success)
2922645f5050Syouri		break;
2923645f5050Syouri	if (len == 0) /* it is not a local root window */
2924645f5050Syouri		break; /* it is not a local root window */
2925645f5050Syouri	localroot = w;
2926645f5050Syouri	XQueryPointer (dpy, localroot, &root, &child, &root_x, &root_y,
2927645f5050Syouri					&win_x, &win_y, &key_buttons);
2928645f5050Syouri    }
2929645f5050Syouri    XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event);
2930645f5050Syouri    XUngrabPointer (dpy, CurrentTime);
2931645f5050Syouri
2932645f5050Syouri    if (localroot == Scr->Root) return;
2933645f5050Syouri    if (w == localroot) {  /* try to not adopt an ancestor */
2934645f5050Syouri	XQueryTree (dpy, Scr->Root, &root, &parent, &children, &nchildren);
2935645f5050Syouri	while (parent != (Window) 0) {
2936645f5050Syouri	    XFree ((char *) children);
2937645f5050Syouri	    if (w == parent) return;
2938645f5050Syouri	    XQueryTree (dpy, parent, &root, &parent, &children, &nchildren);
2939645f5050Syouri	}
2940645f5050Syouri	XFree ((char *) children);
2941645f5050Syouri	if (w == root) return;
2942645f5050Syouri    }
2943645f5050Syouri    if (localroot == RootWindow (dpy, Scr->screen)) {
2944645f5050Syouri	XWithdrawWindow (dpy, w, Scr->screen);
2945645f5050Syouri    }
2946645f5050Syouri    else {
2947645f5050Syouri	XUnmapWindow (dpy, w);
2948645f5050Syouri    }
2949645f5050Syouri    XReparentWindow (dpy, w, Scr->Root, 0, 0);
2950645f5050Syouri
2951645f5050Syouri    data [0] = (unsigned long) NormalState;
2952645f5050Syouri    data [1] = (unsigned long) None;
2953645f5050Syouri
2954645f5050Syouri    XChangeProperty (dpy, w, _XA_WM_STATE, _XA_WM_STATE, 32,
2955645f5050Syouri			PropModeReplace, (unsigned char *) data, 2);
2956645f5050Syouri    XFlush (dpy);
2957645f5050Syouri    SimulateMapRequest (w);
2958645f5050Syouri    return;
2959645f5050Syouri}
2960645f5050Syouri
2961645f5050Syourivoid DebugTrace (char *file)
2962645f5050Syouri{
2963645f5050Syouri    if (!file) return;
2964645f5050Syouri    if (tracefile) {
2965645f5050Syouri	fprintf (stderr, "stop logging events\n");
2966645f5050Syouri	if (tracefile != stderr) fclose (tracefile);
2967645f5050Syouri	tracefile = NULL;
2968645f5050Syouri    }
2969645f5050Syouri    else {
2970645f5050Syouri	if (strcmp (file, "stderr"))
2971645f5050Syouri	    tracefile = fopen (file, "w");
2972645f5050Syouri	else
2973645f5050Syouri	    tracefile = stderr;
2974645f5050Syouri	fprintf (stderr, "logging events to : %s\n", file);
2975645f5050Syouri    }
2976645f5050Syouri}
2977645f5050Syouri
2978645f5050Syouriextern Cursor	TopRightCursor, TopLeftCursor, BottomRightCursor, BottomLeftCursor,
2979645f5050Syouri		LeftCursor, RightCursor, TopCursor, BottomCursor;
2980645f5050Syouri
2981645f5050Syourivoid SetBorderCursor (TwmWindow *tmp_win, int x, int y)
2982645f5050Syouri{
2983645f5050Syouri    Cursor cursor;
2984645f5050Syouri    XSetWindowAttributes attr;
2985645f5050Syouri    int h, fw, fh, wd;
2986645f5050Syouri
2987645f5050Syouri    if (!tmp_win)
2988645f5050Syouri	return;
2989645f5050Syouri
2990645f5050Syouri    /* Use the max of these, but since one is always 0 we can add them. */
2991645f5050Syouri    wd = tmp_win->frame_bw + tmp_win->frame_bw3D;
2992645f5050Syouri    h = Scr->TitleHeight + wd;
2993645f5050Syouri    fw = tmp_win->frame_width;
2994645f5050Syouri    fh = tmp_win->frame_height;
2995645f5050Syouri
2996645f5050Syouri#if defined DEBUG && DEBUG
2997645f5050Syouri    fprintf(stderr, "wd=%d h=%d, fw=%d fh=%d x=%d y=%d\n",
2998645f5050Syouri	    wd, h, fw, fh, x, y);
2999645f5050Syouri#endif
3000645f5050Syouri
3001645f5050Syouri    /*
3002645f5050Syouri     * If not using 3D borders:
3003645f5050Syouri     *
3004645f5050Syouri     * The left border has negative x coordinates,
3005645f5050Syouri     * The top border (above the title) has negative y coordinates.
3006645f5050Syouri     * The title is TitleHeight high, the next wd pixels are border.
3007645f5050Syouri     * The bottom border has coordinates >= the frame height.
3008645f5050Syouri     * The right border has coordinates >= the frame width.
3009645f5050Syouri     *
3010645f5050Syouri     * If using 3D borders: all coordinates are >= 0, and all coordinates
3011645f5050Syouri     * are higher by the border width.
3012645f5050Syouri     *
3013645f5050Syouri     * Since we only get events when we're actually in the border, we simply
3014645f5050Syouri     * allow for both cases at the same time.
3015645f5050Syouri     */
3016645f5050Syouri
3017645f5050Syouri    if ((x < -wd) || (y < -wd)) {
3018645f5050Syouri	cursor = Scr->FrameCursor;
3019645f5050Syouri    } else if (x < h) {
3020645f5050Syouri	if (y < h)
3021645f5050Syouri	    cursor = TopLeftCursor;
3022645f5050Syouri	else if (y >= fh - h)
3023645f5050Syouri	    cursor = BottomLeftCursor;
3024645f5050Syouri	else
3025645f5050Syouri	    cursor = LeftCursor;
3026645f5050Syouri    } else if (x >= fw - h) {
3027645f5050Syouri	if (y < h)
3028645f5050Syouri	    cursor = TopRightCursor;
3029645f5050Syouri	else if (y >= fh - h)
3030645f5050Syouri	    cursor = BottomRightCursor;
3031645f5050Syouri	else
3032645f5050Syouri	    cursor = RightCursor;
3033645f5050Syouri    } else if (y < h) {	/* also include title bar in top border area */
3034645f5050Syouri	cursor = TopCursor;
3035645f5050Syouri    } else if (y >= fh - h) {
3036645f5050Syouri	cursor = BottomCursor;
3037645f5050Syouri    } else {
3038645f5050Syouri	cursor = Scr->FrameCursor;
3039645f5050Syouri    }
3040645f5050Syouri    attr.cursor = cursor;
3041645f5050Syouri    XChangeWindowAttributes (dpy, tmp_win->frame, CWCursor, &attr);
3042645f5050Syouri    tmp_win->curcurs = cursor;
3043645f5050Syouri}
3044645f5050Syouri
3045645f5050SyouriImage *GetImage (char *name, ColorPair cp)
3046645f5050Syouri{
3047645f5050Syouri    name_list **list;
3048645f5050Syouri    char fullname [256];
3049645f5050Syouri    Image *image;
3050645f5050Syouri
3051645f5050Syouri    if (name == NULL) return (None);
3052645f5050Syouri    image = None;
3053645f5050Syouri
3054645f5050Syouri    list = &Scr->ImageCache;
3055645f5050Syouri#ifdef XPM
3056645f5050Syouri    if ((name [0] == '@') || (strncmp (name, "xpm:", 4) == 0)) {
3057645f5050Syouri	sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
3058645f5050Syouri
3059645f5050Syouri	if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
3060645f5050Syouri	    int startn = (name [0] == '@') ? 1 : 4;
3061645f5050Syouri	    if ((image = GetXpmImage (name + startn, cp)) != None) {
3062645f5050Syouri	        AddToList (list, fullname, (char*) image);
3063645f5050Syouri	    }
3064645f5050Syouri	}
3065645f5050Syouri    }
3066645f5050Syouri    else
3067645f5050Syouri#endif
3068645f5050Syouri#ifdef JPEG
3069645f5050Syouri    if (strncmp (name, "jpeg:", 5) == 0) {
3070645f5050Syouri	if ((image = (Image*) LookInNameList (*list, name)) == None) {
3071645f5050Syouri	    if ((image = GetJpegImage (&name [5])) != None) {
3072645f5050Syouri		AddToList (list, name, (char*) image);
3073645f5050Syouri	    }
3074645f5050Syouri	}
3075645f5050Syouri    }
3076645f5050Syouri    else
3077645f5050Syouri#endif
3078645f5050Syouri#ifdef IMCONV
3079645f5050Syouri    if (strncmp (name, "im:", 3) == 0) {
3080645f5050Syouri	if ((image = (Image*) LookInNameList (*list, name)) == None) {
3081645f5050Syouri	    if ((image = GetImconvImage (&name [3])) != None) {
3082645f5050Syouri		AddToList (list, name, (char*) image);
3083645f5050Syouri	    }
3084645f5050Syouri	}
3085645f5050Syouri    }
3086645f5050Syouri    else
3087645f5050Syouri#endif
3088645f5050Syouri#if !defined(VMS) || defined(HAVE_XWDFILE_H)
3089645f5050Syouri    if ((strncmp (name, "xwd:", 4) == 0) || (name [0] == '|')) {
3090645f5050Syouri	int startn = (name [0] == '|') ? 0 : 4;
3091645f5050Syouri	if ((image = (Image*) LookInNameList (*list, name)) == None) {
3092645f5050Syouri	    if ((image = GetXwdImage (&name [startn], cp)) != None) {
3093645f5050Syouri		AddToList (list, name, (char*) image);
3094645f5050Syouri	    }
3095645f5050Syouri	}
3096645f5050Syouri    }
3097645f5050Syouri    else
3098645f5050Syouri#endif
3099645f5050Syouri    if (strncmp (name, ":xpm:", 5) == 0) {
3100645f5050Syouri	int    i;
3101645f5050Syouri	static struct {
3102645f5050Syouri	    char *name;
3103645f5050Syouri	    Image* (*proc)(ColorPair colorpair);
3104645f5050Syouri	} pmtab[] = {
3105645f5050Syouri	    { TBPM_3DDOT,	Create3DDotImage },
3106645f5050Syouri	    { TBPM_3DRESIZE,	Create3DResizeImage },
3107645f5050Syouri	    { TBPM_3DMENU,	Create3DMenuImage },
3108645f5050Syouri	    { TBPM_3DZOOM,	Create3DZoomImage },
3109645f5050Syouri	    { TBPM_3DBAR,	Create3DBarImage },
3110645f5050Syouri	    { TBPM_3DVBAR,	Create3DVertBarImage },
3111645f5050Syouri	    { TBPM_3DCROSS,     Create3DCrossImage },
3112645f5050Syouri	    { TBPM_3DICONIFY,   Create3DIconifyImage },
3113645f5050Syouri	    { TBPM_3DSUNKEN_RESIZE,     Create3DSunkenResizeImage },
3114645f5050Syouri	    { TBPM_3DBOX,       Create3DBoxImage }
3115645f5050Syouri	};
3116645f5050Syouri
3117645f5050Syouri	sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
3118645f5050Syouri	if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
3119645f5050Syouri	    for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
3120645f5050Syouri		if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) {
3121645f5050Syouri		    image = (*pmtab[i].proc) (cp);
3122645f5050Syouri		    if (image == None) {
3123645f5050Syouri			fprintf (stderr,
3124645f5050Syouri			    "%s:  unable to build pixmap \"%s\"\n", ProgramName, name);
3125645f5050Syouri			return (None);
3126645f5050Syouri		    }
3127645f5050Syouri		    break;
3128645f5050Syouri		}
3129645f5050Syouri	    }
3130645f5050Syouri	    if (image == None) {
3131645f5050Syouri		fprintf (stderr, "%s:  no such built-in pixmap \"%s\"\n", ProgramName, name);
3132645f5050Syouri		return (None);
3133645f5050Syouri	    }
3134645f5050Syouri	    AddToList (list, fullname, (char*) image);
3135645f5050Syouri	}
3136645f5050Syouri    }
3137645f5050Syouri    else
3138645f5050Syouri    if (strncmp (name, "%xpm:", 5) == 0) {
3139645f5050Syouri	int    i;
3140645f5050Syouri	static struct {
3141645f5050Syouri	    char *name;
3142645f5050Syouri	    Image* (*proc)(ColorPair colorpair);
3143645f5050Syouri	} pmtab[] = {
3144645f5050Syouri	    { "%xpm:menu-up", Create3DMenuUpAnimation },
3145645f5050Syouri	    { "%xpm:menu-down", Create3DMenuDownAnimation },
3146645f5050Syouri	    { "%xpm:resize", Create3DZoomOutAnimation }, /* compatibility */
3147645f5050Syouri	    { "%xpm:resize-out-top", Create3DResizeInTopAnimation },
3148645f5050Syouri	    { "%xpm:resize-in-top", Create3DResizeOutTopAnimation },
3149645f5050Syouri	    { "%xpm:resize-out-bot", Create3DResizeInBotAnimation },
3150645f5050Syouri	    { "%xpm:resize-in-bot", Create3DResizeOutBotAnimation },
3151645f5050Syouri	    { "%xpm:maze-out", Create3DMazeOutAnimation },
3152645f5050Syouri	    { "%xpm:maze-in", Create3DMazeInAnimation },
3153645f5050Syouri	    { "%xpm:zoom-out", Create3DZoomOutAnimation },
3154645f5050Syouri	    { "%xpm:zoom-in", Create3DZoomInAnimation },
3155645f5050Syouri	    { "%xpm:zoom-inout", Create3DZoomInOutAnimation }
3156645f5050Syouri	};
3157645f5050Syouri
3158645f5050Syouri	sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
3159645f5050Syouri	if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
3160645f5050Syouri	    for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
3161645f5050Syouri		if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) {
3162645f5050Syouri		    image = (*pmtab[i].proc) (cp);
3163645f5050Syouri		    if (image == None) {
3164645f5050Syouri			fprintf (stderr,
3165645f5050Syouri			    "%s:  unable to build pixmap \"%s\"\n", ProgramName, name);
3166645f5050Syouri			return (None);
3167645f5050Syouri		    }
3168645f5050Syouri		    break;
3169645f5050Syouri		}
3170645f5050Syouri	    }
3171645f5050Syouri	    if (image == None) {
3172645f5050Syouri		fprintf (stderr, "%s:  no such built-in pixmap \"%s\"\n", ProgramName, name);
3173645f5050Syouri		return (None);
3174645f5050Syouri	    }
3175645f5050Syouri	    AddToList (list, fullname, (char*) image);
3176645f5050Syouri	}
3177645f5050Syouri    }
3178645f5050Syouri    else
3179645f5050Syouri    if (name [0] == ':') {
3180645f5050Syouri	int		i;
3181645f5050Syouri	unsigned int	width, height;
3182645f5050Syouri	Pixmap		pm = 0;
3183645f5050Syouri	XGCValues	gcvalues;
3184645f5050Syouri	static struct {
3185645f5050Syouri	    char *name;
3186645f5050Syouri	    Pixmap (*proc)(unsigned int *widthp, unsigned int *heightp);
3187645f5050Syouri	} pmtab[] = {
3188645f5050Syouri	    { TBPM_DOT,		CreateDotPixmap },
3189645f5050Syouri	    { TBPM_ICONIFY,	CreateDotPixmap },
3190645f5050Syouri	    { TBPM_RESIZE,	CreateResizePixmap },
3191645f5050Syouri	    { TBPM_XLOGO,	CreateXLogoPixmap },
3192645f5050Syouri	    { TBPM_DELETE,	CreateXLogoPixmap },
3193645f5050Syouri	    { TBPM_MENU,	CreateMenuPixmap },
3194645f5050Syouri	    { TBPM_QUESTION,	CreateQuestionPixmap },
3195645f5050Syouri	};
3196645f5050Syouri
3197645f5050Syouri	sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
3198645f5050Syouri	if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
3199645f5050Syouri	    for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
3200645f5050Syouri		if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) {
3201645f5050Syouri		    pm = (*pmtab[i].proc) (&width, &height);
3202645f5050Syouri		    if (pm == None) {
3203645f5050Syouri			fprintf (stderr,
3204645f5050Syouri			    "%s:  unable to build pixmap \"%s\"\n", ProgramName, name);
3205645f5050Syouri			return (None);
3206645f5050Syouri		    }
3207645f5050Syouri		    break;
3208645f5050Syouri		}
3209645f5050Syouri	    }
3210645f5050Syouri	    if (pm == None) {
3211645f5050Syouri		fprintf (stderr, "%s:  no such built-in bitmap \"%s\"\n", ProgramName, name);
3212645f5050Syouri		return (None);
3213645f5050Syouri	    }
3214645f5050Syouri	    image = (Image*) malloc (sizeof (struct _Image));
3215645f5050Syouri	    image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth);
3216645f5050Syouri	    if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues);
3217645f5050Syouri	    gcvalues.background = cp.back;
3218645f5050Syouri	    gcvalues.foreground = cp.fore;
3219645f5050Syouri	    XChangeGC   (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues);
3220645f5050Syouri	    XCopyPlane  (dpy, pm, image->pixmap, Scr->rootGC, 0, 0, width, height, 0, 0,
3221645f5050Syouri			(unsigned long) 1);
3222645f5050Syouri	    image->mask   = None;
3223645f5050Syouri	    image->width  = width;
3224645f5050Syouri	    image->height = height;
3225645f5050Syouri	    image->next   = None;
3226645f5050Syouri	    AddToList (list, fullname, (char*) image);
3227645f5050Syouri	}
3228645f5050Syouri    }
3229645f5050Syouri    else {
3230645f5050Syouri	sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
3231645f5050Syouri	if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
3232645f5050Syouri	    if ((image = GetBitmapImage (name, cp)) != None) {
3233645f5050Syouri		AddToList (list, fullname, (char*) image);
3234645f5050Syouri	    }
3235645f5050Syouri	}
3236645f5050Syouri    }
3237645f5050Syouri    return (image);
3238645f5050Syouri}
3239645f5050Syouri
3240645f5050Syourivoid FreeImage (Image *image)
3241645f5050Syouri{
3242645f5050Syouri    Image *im, *im2;
3243645f5050Syouri
3244645f5050Syouri    im = image;
3245645f5050Syouri    while (im != None) {
3246645f5050Syouri	if (im->pixmap) XFreePixmap (dpy, im->pixmap);
3247645f5050Syouri	if (im->mask)   XFreePixmap (dpy, im->mask);
3248645f5050Syouri	im2 = im->next;
3249645f5050Syouri	free (im);
3250645f5050Syouri	im = im2;
3251645f5050Syouri    }
3252645f5050Syouri}
3253645f5050Syouri
3254645f5050Syouri#if !defined(VMS) || defined(HAVE_XWDFILE_H)
3255645f5050Syouristatic void compress (XImage *image, XColor *colors, int *ncolors);
3256645f5050Syouri
3257645f5050Syouristatic Image *LoadXwdImage (char *filename, ColorPair cp)
3258645f5050Syouri{
3259645f5050Syouri    FILE	*file;
3260645f5050Syouri    char	*fullname;
3261645f5050Syouri    XColor	colors [256];
3262645f5050Syouri    XWDColor	xwdcolors [256];
3263645f5050Syouri    unsigned	buffer_size;
3264645f5050Syouri    XImage	*image;
3265645f5050Syouri    unsigned char *imagedata;
3266645f5050Syouri    Pixmap	pixret;
3267645f5050Syouri    Visual	*visual;
3268645f5050Syouri    char	win_name [256];
3269645f5050Syouri    int		win_name_size;
3270645f5050Syouri    int		ispipe;
3271645f5050Syouri    int		i, len;
3272645f5050Syouri    int		w, h, depth, ncolors;
3273645f5050Syouri    int		scrn;
3274645f5050Syouri    Colormap	cmap;
3275645f5050Syouri    Colormap	stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
3276645f5050Syouri    GC		gc;
3277645f5050Syouri    XGCValues   gcvalues;
3278645f5050Syouri    XWDFileHeader header;
3279645f5050Syouri    Image	*ret;
3280645f5050Syouri    Bool	anim;
3281645f5050Syouri    unsigned long swaptest = 1;
3282645f5050Syouri
3283645f5050Syouri    ispipe = 0;
3284645f5050Syouri    anim   = False;
3285645f5050Syouri#ifndef VMS
3286645f5050Syouri    if (filename [0] == '|') {
3287645f5050Syouri	file = (FILE*) popen (filename + 1, "r");
3288645f5050Syouri	if (file == NULL) return (None);
3289645f5050Syouri	ispipe = 1;
3290645f5050Syouri	anim = AnimationActive;
3291645f5050Syouri	if (anim) StopAnimation ();
3292645f5050Syouri	goto file_opened;
3293645f5050Syouri    }
3294645f5050Syouri#endif
3295645f5050Syouri    fullname = ExpandPixmapPath (filename);
3296645f5050Syouri    if (! fullname) return (None);
3297645f5050Syouri    file = fopen (fullname, "r");
3298645f5050Syouri    free (fullname);
3299645f5050Syouri    if (file == NULL) {
3300645f5050Syouri	if (reportfilenotfound) fprintf (stderr, "unable to locate %s\n", filename);
3301645f5050Syouri        return (None);
3302645f5050Syouri    }
3303645f5050Syourifile_opened:
3304645f5050Syouri    len = fread ((char *) &header, sizeof (header), 1, file);
3305645f5050Syouri    if (len != 1) {
3306645f5050Syouri	fprintf (stderr, "ctwm: cannot read %s\n", filename);
3307645f5050Syouri#ifdef USE_SIGNALS
3308645f5050Syouri	if (ispipe && anim) StartAnimation ();
3309645f5050Syouri#endif
3310645f5050Syouri	return (None);
3311645f5050Syouri    }
3312645f5050Syouri    if (*(char *) &swaptest) _swaplong ((char *) &header, sizeof (header));
3313645f5050Syouri    if (header.file_version != XWD_FILE_VERSION) {
3314645f5050Syouri	fprintf(stderr,"ctwm: XWD file format version mismatch : %s\n", filename);
3315645f5050Syouri	return (None);
3316645f5050Syouri    }
3317645f5050Syouri    win_name_size = header.header_size - sizeof (header);
3318645f5050Syouri    len = fread (win_name, win_name_size, 1, file);
3319645f5050Syouri    if (len != 1) {
3320645f5050Syouri	fprintf (stderr, "file %s has not the correct format\n", filename);
3321645f5050Syouri#ifdef USE_SIGNALS
3322645f5050Syouri	if (ispipe && anim) StartAnimation ();
3323645f5050Syouri#endif
3324645f5050Syouri	return (None);
3325645f5050Syouri    }
3326645f5050Syouri
3327645f5050Syouri    if (header.pixmap_format == XYPixmap) {
3328645f5050Syouri	fprintf (stderr,"ctwm: XYPixmap XWD file not supported : %s\n", filename);
3329645f5050Syouri	return (None);
3330645f5050Syouri    }
3331645f5050Syouri    w       = header.pixmap_width;
3332645f5050Syouri    h       = header.pixmap_height;
3333645f5050Syouri    depth   = header.pixmap_depth;
3334645f5050Syouri    ncolors = header.ncolors;
3335645f5050Syouri    len = fread ((char *) xwdcolors, sizeof (XWDColor), ncolors, file);
3336645f5050Syouri    if (len != ncolors) {
3337645f5050Syouri	fprintf (stderr, "file %s has not the correct format\n", filename);
3338645f5050Syouri#ifdef USE_SIGNALS
3339645f5050Syouri	if (ispipe && anim) StartAnimation ();
3340645f5050Syouri#endif
3341645f5050Syouri	return (None);
3342645f5050Syouri    }
3343645f5050Syouri    if (*(char *) &swaptest) {
3344645f5050Syouri	for (i = 0; i < ncolors; i++) {
3345645f5050Syouri	    _swaplong  ((char *) &xwdcolors [i].pixel, 4);
3346645f5050Syouri	    _swapshort ((char *) &xwdcolors [i].red, 3 * 2);
3347645f5050Syouri	}
3348645f5050Syouri    }
3349645f5050Syouri    for (i = 0; i < ncolors; i++) {
3350645f5050Syouri	colors [i].pixel = xwdcolors [i].pixel;
3351645f5050Syouri	colors [i].red   = xwdcolors [i].red;
3352645f5050Syouri	colors [i].green = xwdcolors [i].green;
3353645f5050Syouri	colors [i].blue  = xwdcolors [i].blue;
3354645f5050Syouri	colors [i].flags = xwdcolors [i].flags;
3355645f5050Syouri	colors [i].pad   = xwdcolors [i].pad;
3356645f5050Syouri    }
3357645f5050Syouri
3358645f5050Syouri    scrn    = Scr->screen;
3359645f5050Syouri    cmap    = AlternateCmap ? AlternateCmap : stdcmap;
3360645f5050Syouri    visual  = Scr->d_visual;
3361645f5050Syouri    gc      = DefaultGC (dpy, scrn);
3362645f5050Syouri
3363645f5050Syouri    buffer_size = header.bytes_per_line * h;
3364645f5050Syouri    imagedata = (unsigned char*) malloc (buffer_size);
3365645f5050Syouri    if (! imagedata) {
3366645f5050Syouri	fprintf (stderr, "cannot allocate memory for image %s\n", filename);
3367645f5050Syouri#ifdef USE_SIGNALS
3368645f5050Syouri	if (ispipe && anim) StartAnimation ();
3369645f5050Syouri#endif
3370645f5050Syouri	return (None);
3371645f5050Syouri    }
3372645f5050Syouri    len = fread (imagedata, (int) buffer_size, 1, file);
3373645f5050Syouri    if (len != 1) {
3374645f5050Syouri	free (imagedata);
3375645f5050Syouri	fprintf (stderr, "file %s has not the correct format\n", filename);
3376645f5050Syouri#ifdef USE_SIGNALS
3377645f5050Syouri	if (ispipe && anim) StartAnimation ();
3378645f5050Syouri#endif
3379645f5050Syouri	return (None);
3380645f5050Syouri    }
3381645f5050Syouri#ifndef VMS
3382645f5050Syouri    if (ispipe)
3383645f5050Syouri      pclose (file);
3384645f5050Syouri    else
3385645f5050Syouri#endif
3386645f5050Syouri      fclose (file);
3387645f5050Syouri
3388645f5050Syouri    image = XCreateImage (dpy, visual,  depth, header.pixmap_format,
3389645f5050Syouri                          0, (char*) imagedata, w, h,
3390645f5050Syouri                          header.bitmap_pad, header.bytes_per_line);
3391645f5050Syouri    if (image == None) {
3392645f5050Syouri	free (imagedata);
3393645f5050Syouri	fprintf (stderr, "cannot create image for %s\n", filename);
3394645f5050Syouri#ifdef USE_SIGNALS
3395645f5050Syouri	if (ispipe && anim) StartAnimation ();
3396645f5050Syouri#endif
3397645f5050Syouri	return (None);
3398645f5050Syouri    }
3399645f5050Syouri    if (header.pixmap_format == ZPixmap) {
3400645f5050Syouri	compress (image, colors, &ncolors);
3401645f5050Syouri    }
3402645f5050Syouri    if (header.pixmap_format != XYBitmap) {
3403645f5050Syouri	for (i = 0; i < ncolors; i++) {
3404645f5050Syouri            XAllocColor (dpy, cmap, &(colors [i]));
3405645f5050Syouri	}
3406645f5050Syouri	for (i = 0; i < buffer_size; i++) {
3407645f5050Syouri            imagedata [i] = (unsigned char) colors [imagedata [i]].pixel;
3408645f5050Syouri	}
3409645f5050Syouri    }
3410645f5050Syouri    if (w > Scr->rootw)  w = Scr->rootw;
3411645f5050Syouri    if (h > Scr->rooth) h = Scr->rooth;
3412645f5050Syouri
3413645f5050Syouri    ret = (Image*) malloc (sizeof (struct _Image));
3414645f5050Syouri    if (! ret) {
3415645f5050Syouri	fprintf (stderr, "unable to allocate memory for image : %s\n", filename);
3416645f5050Syouri	free (image);
3417645f5050Syouri	free (imagedata);
3418645f5050Syouri	for (i = 0; i < ncolors; i++) {
3419645f5050Syouri            XFreeColors (dpy, cmap, &(colors [i].pixel), 1, 0L);
3420645f5050Syouri	}
3421645f5050Syouri#ifdef USE_SIGNALS
3422645f5050Syouri	if (ispipe && anim) StartAnimation ();
3423645f5050Syouri#endif
3424645f5050Syouri	return (None);
3425645f5050Syouri    }
3426645f5050Syouri    if (header.pixmap_format == XYBitmap) {
3427645f5050Syouri	gcvalues.foreground = cp.fore;
3428645f5050Syouri	gcvalues.background = cp.back;
3429645f5050Syouri	XChangeGC (dpy, gc, GCForeground | GCBackground, &gcvalues);
3430645f5050Syouri    }
3431645f5050Syouri    if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) {
3432645f5050Syouri	int x, y;
3433645f5050Syouri
3434645f5050Syouri	pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw,
3435645f5050Syouri				Scr->rooth, Scr->d_depth);
3436645f5050Syouri	x = (Scr->rootw  - w) / 2;
3437645f5050Syouri	y = (Scr->rooth - h) / 2;
3438645f5050Syouri	XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth);
3439645f5050Syouri	XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h);
3440645f5050Syouri	ret->width  = Scr->rootw;
3441645f5050Syouri	ret->height = Scr->rooth;
3442645f5050Syouri    }
3443645f5050Syouri    else {
3444645f5050Syouri	pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth);
3445645f5050Syouri	XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h);
3446645f5050Syouri	ret->width  = w;
3447645f5050Syouri	ret->height = h;
3448645f5050Syouri    }
3449645f5050Syouri    XDestroyImage (image);
3450645f5050Syouri
3451645f5050Syouri    ret->pixmap = pixret;
3452645f5050Syouri    ret->mask   = None;
3453645f5050Syouri    ret->next   = None;
3454645f5050Syouri#ifdef USE_SIGNALS
3455645f5050Syouri    if (ispipe && anim) StartAnimation ();
3456645f5050Syouri#endif
3457645f5050Syouri    return (ret);
3458645f5050Syouri}
3459645f5050Syouri
3460645f5050Syouristatic Image *GetXwdImage (char *name, ColorPair cp)
3461645f5050Syouri{
3462645f5050Syouri    Image *image, *r, *s;
3463645f5050Syouri    char  path [128];
3464645f5050Syouri    char  pref [128], *perc;
3465645f5050Syouri    int   i;
3466645f5050Syouri
3467645f5050Syouri    if (! strchr (name, '%')) return (LoadXwdImage (name, cp));
3468645f5050Syouri    s = image = None;
3469645f5050Syouri    strcpy (pref, name);
3470645f5050Syouri    perc  = strchr (pref, '%');
3471645f5050Syouri    *perc = '\0';
3472645f5050Syouri    reportfilenotfound = 0;
3473645f5050Syouri    for (i = 1;; i++) {
3474645f5050Syouri	sprintf (path, "%s%d%s", pref, i, perc + 1);
3475645f5050Syouri	r = LoadXwdImage (path, cp);
3476645f5050Syouri	if (r == None) break;
3477645f5050Syouri	r->next   = None;
3478645f5050Syouri	if (image == None) s = image = r;
3479645f5050Syouri	else {
3480645f5050Syouri	    s->next = r;
3481645f5050Syouri	    s = r;
3482645f5050Syouri	}
3483645f5050Syouri    }
3484645f5050Syouri    reportfilenotfound = 1;
3485645f5050Syouri    if (s != None) s->next = image;
3486645f5050Syouri    if (image == None) {
3487645f5050Syouri	fprintf (stderr, "Cannot open any %s xwd file\n", name);
3488645f5050Syouri    }
3489645f5050Syouri    return (image);
3490645f5050Syouri}
3491645f5050Syouri
3492645f5050Syouristatic void compress (XImage *image, XColor *colors, int *ncolors)
3493645f5050Syouri{
3494645f5050Syouri    unsigned char ind  [256];
3495645f5050Syouri    unsigned int  used [256];
3496645f5050Syouri    int           i, j, size, nused;
3497645f5050Syouri    unsigned char color;
3498645f5050Syouri    XColor        newcolors [256];
3499645f5050Syouri    unsigned char *imagedata;
3500645f5050Syouri
3501645f5050Syouri    for (i = 0; i < 256; i++) {
3502645f5050Syouri	used [i] = 0;
3503645f5050Syouri	ind  [i] = 0;
3504645f5050Syouri    }
3505645f5050Syouri    nused = 0;
3506645f5050Syouri    size  = image->bytes_per_line * image->height;
3507645f5050Syouri    imagedata = (unsigned char *) image->data;
3508645f5050Syouri    for (i = 0; i < size; i++) {
3509645f5050Syouri	if ((i % image->bytes_per_line) > image->width) continue;
3510645f5050Syouri        color = imagedata [i];
3511645f5050Syouri        if (used [color] == 0) {
3512645f5050Syouri            for (j = 0; j < nused; j++) {
3513645f5050Syouri                if ((colors [color].red   == newcolors [j].red)   &&
3514645f5050Syouri                    (colors [color].green == newcolors [j].green) &&
3515645f5050Syouri                    (colors [color].blue  == newcolors [j].blue)) break;
3516645f5050Syouri            }
3517645f5050Syouri            ind  [color] = j;
3518645f5050Syouri            used [color] = 1;
3519645f5050Syouri            if (j == nused) {
3520645f5050Syouri                newcolors [j].red   = colors [color].red;
3521645f5050Syouri                newcolors [j].green = colors [color].green;
3522645f5050Syouri                newcolors [j].blue  = colors [color].blue;
3523645f5050Syouri                nused++;
3524645f5050Syouri            }
3525645f5050Syouri        }
3526645f5050Syouri    }
3527645f5050Syouri    for (i = 0; i < size; i++) {
3528645f5050Syouri        imagedata [i] = ind [imagedata [i]];
3529645f5050Syouri    }
3530645f5050Syouri    for (i = 0; i < nused; i++) {
3531645f5050Syouri        colors [i] = newcolors [i];
3532645f5050Syouri    }
3533645f5050Syouri    *ncolors = nused;
3534645f5050Syouri}
3535645f5050Syouri#endif
3536645f5050Syouri
3537645f5050Syouri#ifdef IMCONV
3538645f5050Syouri
3539645f5050Syouristatic void free_images  ();
3540645f5050Syouri
3541645f5050Syouristatic Image *GetImconvImage (char *filename,
3542645f5050Syouri			      unsigned int *widthp, unsigned int *heightp)
3543645f5050Syouri{
3544645f5050Syouri    TagTable		*toolInTable;
3545645f5050Syouri    ImVfb		*sourceVfb;
3546645f5050Syouri    ImVfbPtr		vptr;
3547645f5050Syouri    ImClt		*clt;
3548645f5050Syouri    int			i, j, ij, k, retval;
3549645f5050Syouri
3550645f5050Syouri    XColor		colors [256];
3551645f5050Syouri    unsigned		buffer_size;
3552645f5050Syouri    XImage		*image;
3553645f5050Syouri    unsigned char	*imagedata;
3554645f5050Syouri    Pixmap		pixret;
3555645f5050Syouri    Visual		*visual;
3556645f5050Syouri    int			w, h, depth, ncolors;
3557645f5050Syouri    int			scrn;
3558645f5050Syouri    Colormap		cmap;
3559645f5050Syouri    Colormap		stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
3560645f5050Syouri    GC			gc;
3561645f5050Syouri    unsigned char	red, green, blue;
3562645f5050Syouri    int			icol;
3563645f5050Syouri    char		*fullname;
3564645f5050Syouri
3565645f5050Syouri    TagEntry		*dataEntry;
3566645f5050Syouri    FILE		*fp;
3567645f5050Syouri    char		the_format[1024];
3568645f5050Syouri    char		*tmp_format;
3569645f5050Syouri    Image		*ret;
3570645f5050Syouri
3571645f5050Syouri    if (*filename == NULL) return (None);
3572645f5050Syouri    fullname = ExpandPixmapPath (filename);
3573645f5050Syouri    if (! fullname) return (None);
3574645f5050Syouri
3575645f5050Syouri    fp = fopen (fullname, "r");
3576645f5050Syouri    if (!fp) {
3577645f5050Syouri	if (reportfilenotfound) fprintf (stderr, "Cannot open the image %s\n", filename);
3578645f5050Syouri	free (fullname);
3579645f5050Syouri	return (None);
3580645f5050Syouri    }
3581645f5050Syouri    if ((toolInTable = TagTableAlloc ()) == TAGTABLENULL ) {
3582645f5050Syouri	fprintf (stderr, "TagTableAlloc failed\n");
3583645f5050Syouri	free_images (toolInTable);
3584645f5050Syouri	free (fullname);
3585645f5050Syouri	return (None);
3586645f5050Syouri    }
3587645f5050Syouri    if ((tmp_format = ImFileQFFormat (fp, fullname)) == NULL)  {
3588645f5050Syouri	fprintf (stderr, "Cannot determine image type of %s\n", filename);
3589645f5050Syouri	free_images  (toolInTable);
3590645f5050Syouri	free (fullname);
3591645f5050Syouri	return (None);
3592645f5050Syouri    }
3593645f5050Syouri    strcpy (the_format, tmp_format);
3594645f5050Syouri    retval = ImFileFRead (fp, the_format, NULL, toolInTable);
3595645f5050Syouri    if(retval < 0) {
3596645f5050Syouri	fprintf(stderr, "Cannot read image file %s: ", fullname);
3597645f5050Syouri	switch(ImErrNo) {
3598645f5050Syouri	    case IMESYS:
3599645f5050Syouri		fprintf (stderr, "System call error\n");
3600645f5050Syouri		break;
3601645f5050Syouri	    case IMEMALLOC:
3602645f5050Syouri		fprintf (stderr, "Cannot allocate memory\n");
3603645f5050Syouri		break;
3604645f5050Syouri	    case IMEFORMAT:
3605645f5050Syouri		fprintf (stderr, "Data in file is corrupt\n");
3606645f5050Syouri		break;
3607645f5050Syouri	    case IMENOREAD:
3608645f5050Syouri		fprintf (stderr, "Sorry, this format is write-only\n");
3609645f5050Syouri		break;
3610645f5050Syouri	    case IMEMAGIC:
3611645f5050Syouri		fprintf (stderr, "Bad magic number in image file\n");
3612645f5050Syouri		break;
3613645f5050Syouri	    case IMEDEPTH:
3614645f5050Syouri		fprintf (stderr, "Unknown image depth\n");
3615645f5050Syouri		break;
3616645f5050Syouri	    default:
3617645f5050Syouri		fprintf(stderr, "Unknown error\n");
3618645f5050Syouri		break;
3619645f5050Syouri	}
3620645f5050Syouri	free_images (toolInTable);
3621645f5050Syouri	free (fullname);
3622645f5050Syouri	return (None);
3623645f5050Syouri    }
3624645f5050Syouri
3625645f5050Syouri    if (TagTableQNEntry (toolInTable, "image vfb") == 0)  {
3626645f5050Syouri	fprintf (stderr, "Image file %s contains no images\n", fullname);
3627645f5050Syouri	free_images (toolInTable);
3628645f5050Syouri	free (fullname);
3629645f5050Syouri	return (None);
3630645f5050Syouri    }
3631645f5050Syouri    dataEntry = TagTableQDirect (toolInTable, "image vfb", 0);
3632645f5050Syouri    TagEntryQValue (dataEntry, &sourceVfb);
3633645f5050Syouri    fclose (fp);
3634645f5050Syouri
3635645f5050Syouri    w = ImVfbQWidth  (sourceVfb);
3636645f5050Syouri    h = ImVfbQHeight (sourceVfb);
3637645f5050Syouri    depth = 8 * ImVfbQNBytes (sourceVfb);
3638645f5050Syouri    if (depth != 8) {
3639645f5050Syouri	fprintf (stderr, "I don't know yet how to deal with images not of 8 planes depth\n");
3640645f5050Syouri	free_images (toolInTable);
3641645f5050Syouri	return (None);
3642645f5050Syouri    }
3643645f5050Syouri
3644645f5050Syouri    *width  = w;
3645645f5050Syouri    *height = h;
3646645f5050Syouri
3647645f5050Syouri    scrn   = Scr->screen;
3648645f5050Syouri    cmap   = AlternateCmap ? AlternateCmap : stdcmap;
3649645f5050Syouri    visual = Scr->d_visual;
3650645f5050Syouri    gc     = DefaultGC (dpy, scrn);
3651645f5050Syouri
3652645f5050Syouri    buffer_size = w * h;
3653645f5050Syouri    imagedata = (unsigned char*) malloc (buffer_size);
3654645f5050Syouri    if (imagedata == (unsigned char*) 0) {
3655645f5050Syouri	fprintf (stderr, "Can't alloc enough space for background images\n");
3656645f5050Syouri	free_images (toolInTable);
3657645f5050Syouri	return (None);
3658645f5050Syouri    }
3659645f5050Syouri
3660645f5050Syouri    clt  = ImVfbQClt   (sourceVfb);
3661645f5050Syouri    vptr = ImVfbQFirst (sourceVfb);
3662645f5050Syouri    ncolors = 0;
3663645f5050Syouri    for (i = 0; i < h - 1; i++) {
3664645f5050Syouri	for (j = 0; j < w; j++) {
3665645f5050Syouri	    ij = (i * w) + j;
3666645f5050Syouri	    red   = ImCltQRed   (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr)));
3667645f5050Syouri	    green = ImCltQGreen (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr)));
3668645f5050Syouri	    blue  = ImCltQBlue  (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr)));
3669645f5050Syouri	    for (k = 0; k < ncolors; k++) {
3670645f5050Syouri		if ((colors [k].red   == red) &&
3671645f5050Syouri		    (colors [k].green == green) &&
3672645f5050Syouri		    (colors [k].blue  == blue)) {
3673645f5050Syouri		    icol = k;
3674645f5050Syouri		    break;
3675645f5050Syouri		}
3676645f5050Syouri	    }
3677645f5050Syouri	    if (k == ncolors) {
3678645f5050Syouri		icol = ncolors;
3679645f5050Syouri		ncolors++;
3680645f5050Syouri	    }
3681645f5050Syouri	    imagedata [ij] = icol;
3682645f5050Syouri	    colors [icol].red   = red;
3683645f5050Syouri	    colors [icol].green = green;
3684645f5050Syouri	    colors [icol].blue  = blue;
3685645f5050Syouri	    ImVfbSInc (sourceVfb, vptr);
3686645f5050Syouri	}
3687645f5050Syouri    }
3688645f5050Syouri    for (i = 0; i < ncolors; i++) {
3689645f5050Syouri	colors [i].red   *= 256;
3690645f5050Syouri	colors [i].green *= 256;
3691645f5050Syouri	colors [i].blue  *= 256;
3692645f5050Syouri    }
3693645f5050Syouri    for (i = 0; i < ncolors; i++) {
3694645f5050Syouri        if (! XAllocColor (dpy, cmap, &(colors [i]))) {
3695645f5050Syouri	    fprintf (stderr, "can't alloc color for image %s\n", filename);
3696645f5050Syouri	}
3697645f5050Syouri    }
3698645f5050Syouri    for (i = 0; i < buffer_size; i++) {
3699645f5050Syouri        imagedata [i] = (unsigned char) colors [imagedata [i]].pixel;
3700645f5050Syouri    }
3701645f5050Syouri
3702645f5050Syouri    image  = XCreateImage  (dpy, visual, depth, ZPixmap, 0, (char*) imagedata, w, h, 8, 0);
3703645f5050Syouri    if (w > Scr->rootw)  w = Scr->rootw;
3704645f5050Syouri    if (h > Scr->rooth) h = Scr->rooth;
3705645f5050Syouri
3706645f5050Syouri    if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) {
3707645f5050Syouri	int x, y;
3708645f5050Syouri
3709645f5050Syouri	pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, depth);
3710645f5050Syouri	x = (Scr->rootw  - w) / 2;
3711645f5050Syouri	y = (Scr->rooth - h) / 2;
3712645f5050Syouri	XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth);
3713645f5050Syouri	XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h);
3714645f5050Syouri	ret->width  = Scr->rootw;
3715645f5050Syouri	ret->height = Scr->rooth;
3716645f5050Syouri    }
3717645f5050Syouri    else {
3718645f5050Syouri	pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth);
3719645f5050Syouri	XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h);
3720645f5050Syouri	ret->width  = w;
3721645f5050Syouri	ret->height = h;
3722645f5050Syouri    }
3723645f5050Syouri    XFree (image);
3724645f5050Syouri    ret = (Image*) malloc (sizeof (struct _Image));
3725645f5050Syouri    ret->pixmap = pixret;
3726645f5050Syouri    ret->mask   = None;
3727645f5050Syouri    ret->next   = None;
3728645f5050Syouri    return (ret);
3729645f5050Syouri
3730645f5050Syouri}
3731645f5050Syouri
3732645f5050Syouristatic void free_images (table)
3733645f5050SyouriTagTable *table;
3734645f5050Syouri{
3735645f5050Syouri    int		i, n;
3736645f5050Syouri    ImVfb	*v;
3737645f5050Syouri    ImClt	*c;
3738645f5050Syouri    TagEntry	*dataEntry;
3739645f5050Syouri
3740645f5050Syouri    n = TagTableQNEntry (table, "image vfb");
3741645f5050Syouri    for (i = 0 ; i < n ; i++) {
3742645f5050Syouri	dataEntry = TagTableQDirect (table, "image vfb", i);
3743645f5050Syouri	TagEntryQValue (dataEntry, &v);
3744645f5050Syouri	ImVfbFree (v);
3745645f5050Syouri    }
3746645f5050Syouri    n = TagTableQNEntry (table, "image clt");
3747645f5050Syouri    for (i = 0 ; i < n ; i++) {
3748645f5050Syouri	dataEntry = TagTableQDirect (table, "image clt", i );
3749645f5050Syouri	TagEntryQValue (dataEntry, &c);
3750645f5050Syouri	ImCltFree (c);
3751645f5050Syouri    }
3752645f5050Syouri    TagTableFree (table);
3753645f5050Syouri}
3754645f5050Syouri
3755645f5050Syouri#endif
3756645f5050Syouri
3757645f5050Syourivoid _swapshort (register char *bp, register unsigned n)
3758645f5050Syouri{
3759645f5050Syouri    register char c;
3760645f5050Syouri    register char *ep = bp + n;
3761645f5050Syouri
3762645f5050Syouri    while (bp < ep) {
3763645f5050Syouri	c = *bp;
3764645f5050Syouri	*bp = *(bp + 1);
3765645f5050Syouri	bp++;
3766645f5050Syouri	*bp++ = c;
3767645f5050Syouri    }
3768645f5050Syouri}
3769645f5050Syouri
3770645f5050Syourivoid _swaplong (register char *bp, register unsigned n)
3771645f5050Syouri{
3772645f5050Syouri    register char c;
3773645f5050Syouri    register char *ep = bp + n;
3774645f5050Syouri    register char *sp;
3775645f5050Syouri
3776645f5050Syouri    while (bp < ep) {
3777645f5050Syouri	sp = bp + 3;
3778645f5050Syouri	c = *sp;
3779645f5050Syouri	*sp = *bp;
3780645f5050Syouri	*bp++ = c;
3781645f5050Syouri	sp = bp + 1;
3782645f5050Syouri	c = *sp;
3783645f5050Syouri	*sp = *bp;
3784645f5050Syouri	*bp++ = c;
3785645f5050Syouri	bp += 2;
3786645f5050Syouri    }
3787645f5050Syouri}
3788645f5050Syouri
3789645f5050Syouri/***********************************************************************
3790645f5050Syouri *
3791645f5050Syouri *  Procedure:
3792645f5050Syouri *	GetWMPropertyString - Get Window Manager text property and
3793645f5050Syouri *				convert it to a string.
3794645f5050Syouri *
3795645f5050Syouri *  Returned Value:
3796645f5050Syouri *	(char *) - pointer to the malloc'd string or NULL
3797645f5050Syouri *
3798645f5050Syouri *  Inputs:
3799645f5050Syouri *	w	- the id of the window whose property is to be retrieved
3800645f5050Syouri *	prop	- property atom (typically WM_NAME or WM_ICON_NAME)
3801645f5050Syouri *
3802645f5050Syouri ***********************************************************************
3803645f5050Syouri */
3804645f5050Syouri
3805645f5050Syouriunsigned char *GetWMPropertyString(Window w, Atom prop)
3806645f5050Syouri{
3807645f5050Syouri    XTextProperty	text_prop;
3808645f5050Syouri    char 		**text_list;
3809645f5050Syouri    int 		text_list_count;
3810645f5050Syouri    Atom 		XA_COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False);
3811645f5050Syouri    unsigned char	*stringptr;
3812645f5050Syouri    int			status, len = -1;
3813645f5050Syouri
3814645f5050Syouri    (void)XGetTextProperty(dpy, w, &text_prop, prop);
3815645f5050Syouri    if (text_prop.value != NULL) {
3816645f5050Syouri	if (text_prop.encoding == XA_STRING
3817645f5050Syouri	    || text_prop.encoding == XA_COMPOUND_TEXT) {
3818645f5050Syouri	    /* property is encoded as compound text - convert to locale string */
3819645f5050Syouri	    status = XmbTextPropertyToTextList(dpy, &text_prop,
3820645f5050Syouri					       &text_list, &text_list_count);
3821645f5050Syouri	    if (text_list_count == 0) {
3822645f5050Syouri		stringptr = NULL;
3823645f5050Syouri	    } else
3824645f5050Syouri	    if (text_list == (char **)0) {
3825645f5050Syouri		stringptr = NULL;
3826645f5050Syouri	    } else
3827645f5050Syouri	    if (text_list [0] == (char *)0) {
3828645f5050Syouri		stringptr = NULL;
3829645f5050Syouri	    } else
3830645f5050Syouri	    if (status < 0 || text_list_count < 0) {
3831645f5050Syouri		switch (status) {
3832645f5050Syouri		case XConverterNotFound:
3833645f5050Syouri		    fprintf (stderr, "%s: Converter not found; unable to convert property %s of window ID %lx.\n",
3834645f5050Syouri			     ProgramName, XGetAtomName(dpy, prop), w);
3835645f5050Syouri		    break;
3836645f5050Syouri		case XNoMemory:
3837645f5050Syouri		    fprintf (stderr, "%s: Insufficient memory; unable to convert property %s of window ID %lx.\n",
3838645f5050Syouri			     ProgramName, XGetAtomName(dpy, prop), w);
3839645f5050Syouri		    break;
3840645f5050Syouri		case XLocaleNotSupported:
3841645f5050Syouri		    fprintf (stderr, "%s: Locale not supported; unable to convert property %s of window ID %lx.\n",
3842645f5050Syouri			     ProgramName, XGetAtomName(dpy, prop), w);
3843645f5050Syouri		    break;
3844645f5050Syouri		}
3845645f5050Syouri		stringptr = NULL;
3846645f5050Syouri		/*
3847645f5050Syouri		   don't call XFreeStringList - text_list appears to have
3848645f5050Syouri		   invalid address if status is bad
3849645f5050Syouri		   XFreeStringList(text_list);
3850645f5050Syouri		*/
3851645f5050Syouri	    } else {
3852645f5050Syouri		len = strlen(text_list[0]);
3853645f5050Syouri		stringptr = memcpy(malloc(len+1), text_list[0], len+1);
3854645f5050Syouri		XFreeStringList(text_list);
3855645f5050Syouri	    }
3856645f5050Syouri	} else {
3857645f5050Syouri	    /* property is encoded in a format we don't understand */
3858645f5050Syouri	    fprintf (stderr, "%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n",
3859645f5050Syouri		     ProgramName, XGetAtomName(dpy, prop), w);
3860645f5050Syouri	    stringptr = NULL;
3861645f5050Syouri	}
3862645f5050Syouri	XFree (text_prop.value);
3863645f5050Syouri    } else {
3864645f5050Syouri	stringptr = NULL;
3865645f5050Syouri    }
3866645f5050Syouri
3867645f5050Syouri    return stringptr;
3868645f5050Syouri}
3869645f5050Syouri
3870645f5050Syourivoid FreeWMPropertyString(char *prop)
3871645f5050Syouri{
3872645f5050Syouri    if (prop && (char *)prop != NoName) {
3873645f5050Syouri	free(prop);
3874645f5050Syouri    }
3875645f5050Syouri}
3876645f5050Syouri
3877645f5050Syouristatic void ConstrainLeftTop (int *value, int border)
3878645f5050Syouri{
3879645f5050Syouri  if (*value < border) {
3880645f5050Syouri    if (Scr->MoveOffResistance < 0 ||
3881645f5050Syouri	*value > border - Scr->MoveOffResistance)
3882645f5050Syouri    {
3883645f5050Syouri        *value = border;
3884645f5050Syouri    } else if (Scr->MoveOffResistance > 0 &&
3885645f5050Syouri	       *value <= border - Scr->MoveOffResistance)
3886645f5050Syouri    {
3887645f5050Syouri      *value = *value + Scr->MoveOffResistance;
3888645f5050Syouri    }
3889645f5050Syouri    }
3890645f5050Syouri}
3891645f5050Syouri
3892645f5050Syouristatic void ConstrainRightBottom (int *value, int size1, int border, int size2)
3893645f5050Syouri{
3894645f5050Syouri    if (*value + size1 > size2 - border) {
3895645f5050Syouri      if (Scr->MoveOffResistance < 0 ||
3896645f5050Syouri         *value + size1 < size2 - border + Scr->MoveOffResistance)
3897645f5050Syouri    {
3898645f5050Syouri        *value = size2 - size1 - border;
3899645f5050Syouri	} else if (Scr->MoveOffResistance > 0 &&
3900645f5050Syouri		   *value + size1 >= size2 - border + Scr->MoveOffResistance) {
3901645f5050Syouri	  *value = *value - Scr->MoveOffResistance;
3902645f5050Syouri	}
3903645f5050Syouri    }
3904645f5050Syouri}
3905645f5050Syouri
3906645f5050Syourivoid ConstrainByBorders1 (int *left, int width, int *top, int height)
3907645f5050Syouri{
3908645f5050Syouri    ConstrainRightBottom (left, width, Scr->BorderRight, Scr->rootw);
3909645f5050Syouri    ConstrainLeftTop     (left, Scr->BorderLeft);
3910645f5050Syouri    ConstrainRightBottom (top, height, Scr->BorderBottom, Scr->rooth);
3911645f5050Syouri    ConstrainLeftTop     (top, Scr->BorderTop);
3912645f5050Syouri}
3913645f5050Syouri
3914645f5050Syourivoid ConstrainByBorders (TwmWindow *twmwin,
3915645f5050Syouri			 int *left, int width, int *top, int height)
3916645f5050Syouri{
3917645f5050Syouri    if (twmwin->winbox) {
3918645f5050Syouri	XWindowAttributes attr;
3919645f5050Syouri	XGetWindowAttributes (dpy, twmwin->winbox->window, &attr);
3920645f5050Syouri	ConstrainRightBottom (left, width, 0, attr.width);
3921645f5050Syouri	ConstrainLeftTop     (left, 0);
3922645f5050Syouri	ConstrainRightBottom (top, height, 0, attr.height);
3923645f5050Syouri	ConstrainLeftTop     (top, 0);
3924645f5050Syouri    } else {
3925645f5050Syouri	ConstrainByBorders1 (left, width, top, height);
3926645f5050Syouri    }
3927645f5050Syouri}
3928645f5050Syouri
3929645f5050Syouri#ifdef JPEG
3930645f5050Syouri
3931645f5050Syouriuint16_t *buffer_16bpp;
3932645f5050Syouriuint32_t *buffer_32bpp;
3933645f5050Syouri
3934645f5050Syouristatic void convert_for_16 (int w, int x, int y, int r, int g, int b) {
3935645f5050Syouri  buffer_16bpp [y * w + x] = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3);
3936645f5050Syouri}
3937645f5050Syouri
3938645f5050Syouristatic void convert_for_32 (int w, int x, int y, int r, int g, int b) {
3939645f5050Syouri  buffer_32bpp [y * w + x] = ((r << 16) + (g << 8) + b) & 0xFFFFFFFF;
3940645f5050Syouri}
3941645f5050Syouri
3942645f5050Syouristatic void jpeg_error_exit (j_common_ptr cinfo) {
3943645f5050Syouri  jerr_ptr errmgr = (jerr_ptr) cinfo->err;
3944645f5050Syouri  cinfo->err->output_message (cinfo);
3945645f5050Syouri  siglongjmp (errmgr->setjmp_buffer, 1);
3946645f5050Syouri  return;
3947645f5050Syouri}
3948645f5050Syouri
3949645f5050Syouristatic Image *GetJpegImage (char *name)
3950645f5050Syouri{
3951645f5050Syouri    Image *image, *r, *s;
3952645f5050Syouri    char  path [128];
3953645f5050Syouri    char  pref [128], *perc;
3954645f5050Syouri    int   i;
3955645f5050Syouri
3956645f5050Syouri    if (! strchr (name, '%')) return (LoadJpegImage (name));
3957645f5050Syouri    s = image = None;
3958645f5050Syouri    strcpy (pref, name);
3959645f5050Syouri    perc  = strchr (pref, '%');
3960645f5050Syouri    *perc = '\0';
3961645f5050Syouri    reportfilenotfound = 0;
3962645f5050Syouri    for (i = 1;; i++) {
3963645f5050Syouri	sprintf (path, "%s%d%s", pref, i, perc + 1);
3964645f5050Syouri	r = LoadJpegImage (path);
3965645f5050Syouri	if (r == None) break;
3966645f5050Syouri	r->next   = None;
3967645f5050Syouri	if (image == None) s = image = r;
3968645f5050Syouri	else {
3969645f5050Syouri	    s->next = r;
3970645f5050Syouri	    s = r;
3971645f5050Syouri	}
3972645f5050Syouri    }
3973645f5050Syouri    reportfilenotfound = 1;
3974645f5050Syouri    if (s != None) s->next = image;
3975645f5050Syouri    if (image == None) {
3976645f5050Syouri	fprintf (stderr, "Cannot open any %s jpeg file\n", name);
3977645f5050Syouri    }
3978645f5050Syouri    return (image);
3979645f5050Syouri}
3980645f5050Syouri
3981645f5050Syouristatic Image *LoadJpegImage (char *name)
3982645f5050Syouri{
3983645f5050Syouri  char   *fullname;
3984645f5050Syouri  XImage *ximage;
3985645f5050Syouri  FILE   *infile;
3986645f5050Syouri  Image  *image;
3987645f5050Syouri  Pixmap pixret;
3988645f5050Syouri  void   (*store_data) (int w, int x, int y, int r, int g, int b);
3989645f5050Syouri  struct jpeg_decompress_struct cinfo;
3990645f5050Syouri  struct jpeg_error jerr;
3991645f5050Syouri  JSAMPARRAY buffer;
3992645f5050Syouri  int width, height;
3993645f5050Syouri  int row_stride;
3994645f5050Syouri  int g, i, a;
3995645f5050Syouri  int bpix;
3996645f5050Syouri  GC  gc;
3997645f5050Syouri
3998645f5050Syouri  fullname = ExpandPixmapPath (name);
3999645f5050Syouri  if (! fullname) return (None);
4000645f5050Syouri
4001645f5050Syouri  image = (Image*) malloc (sizeof (struct _Image));
4002645f5050Syouri  if (image == None) return (None);
4003645f5050Syouri
4004645f5050Syouri  if ((infile = fopen (fullname, "rb")) == NULL) {
4005645f5050Syouri    if (!reportfilenotfound) fprintf (stderr, "unable to locate %s\n", fullname);
4006645f5050Syouri    fflush (stdout);
4007645f5050Syouri    return None;
4008645f5050Syouri  }
4009645f5050Syouri  cinfo.err = jpeg_std_error (&jerr.pub);
4010645f5050Syouri  jerr.pub.error_exit = jpeg_error_exit;
4011645f5050Syouri
4012645f5050Syouri  if (sigsetjmp(jerr.setjmp_buffer, 1)) {
4013645f5050Syouri    jpeg_destroy_decompress (&cinfo);
4014645f5050Syouri    fclose (infile);
4015645f5050Syouri    return None;
4016645f5050Syouri  }
4017645f5050Syouri  jpeg_create_decompress (&cinfo);
4018645f5050Syouri  jpeg_stdio_src (&cinfo, infile);
4019645f5050Syouri  jpeg_read_header (&cinfo, FALSE);
4020645f5050Syouri  cinfo.do_fancy_upsampling = FALSE;
4021645f5050Syouri  cinfo.do_block_smoothing = FALSE;
4022645f5050Syouri  jpeg_start_decompress (&cinfo);
4023645f5050Syouri  width  = cinfo.output_width;
4024645f5050Syouri  height = cinfo.output_height;
4025645f5050Syouri
4026645f5050Syouri  if (Scr->d_depth == 16) {
4027645f5050Syouri    store_data = &convert_for_16;
4028645f5050Syouri    buffer_16bpp = (unsigned short int *) malloc ((width) * (height) * 2);
4029645f5050Syouri    ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0,
4030645f5050Syouri			   (char *) buffer_16bpp, width, height, 16, width * 2);
4031645f5050Syouri  } else {
4032645f5050Syouri    if (Scr->d_depth == 24) {
4033645f5050Syouri      store_data = &convert_for_32;
4034645f5050Syouri      buffer_32bpp = malloc (width * height * 4);
4035645f5050Syouri      ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0,
4036645f5050Syouri			     (char *) buffer_32bpp, width, height, 32, width * 4);
4037645f5050Syouri    } else
4038645f5050Syouri    if (Scr->d_depth == 32) {
4039645f5050Syouri      store_data = &convert_for_32;
4040645f5050Syouri      buffer_32bpp = malloc (width * height * 4);
4041645f5050Syouri      ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0,
4042645f5050Syouri			     (char *) buffer_32bpp, width, height, 32, width * 4);
4043645f5050Syouri    } else {
4044645f5050Syouri      fprintf (stderr, "Image %s unsupported depth : %d\n", name, Scr->d_depth);
4045645f5050Syouri      return None;
4046645f5050Syouri    }
4047645f5050Syouri  }
4048645f5050Syouri  if (ximage == None) {
4049645f5050Syouri    fprintf (stderr, "cannot create image for %s\n", name);
4050645f5050Syouri  }
4051645f5050Syouri  g = 0;
4052645f5050Syouri  row_stride = cinfo.output_width * cinfo.output_components;
4053645f5050Syouri  buffer = (*cinfo.mem->alloc_sarray)
4054645f5050Syouri    ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
4055645f5050Syouri
4056645f5050Syouri  bpix = cinfo.output_components;
4057645f5050Syouri  while (cinfo.output_scanline < cinfo.output_height) {
4058645f5050Syouri    jpeg_read_scanlines (&cinfo, buffer, 1);
4059645f5050Syouri    a = 0;
4060645f5050Syouri    for (i = 0; i < bpix * cinfo.output_width; i += bpix) {
4061645f5050Syouri      (*store_data) (width, a, g, buffer[0][i],  buffer[0][i + 1], buffer[0][i + 2]);
4062645f5050Syouri      a++;
4063645f5050Syouri    }
4064645f5050Syouri    g++;
4065645f5050Syouri  }
4066645f5050Syouri  jpeg_finish_decompress (&cinfo);
4067645f5050Syouri  jpeg_destroy_decompress (&cinfo);
4068645f5050Syouri  fclose (infile);
4069645f5050Syouri
4070645f5050Syouri  gc = DefaultGC (dpy, Scr->screen);
4071645f5050Syouri  if ((width > (Scr->rootw / 2)) || (height > (Scr->rooth / 2))) {
4072645f5050Syouri    int x, y;
4073645f5050Syouri
4074645f5050Syouri    pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, Scr->d_depth);
4075645f5050Syouri    x = (Scr->rootw  -  width) / 2;
4076645f5050Syouri    y = (Scr->rooth  - height) / 2;
4077645f5050Syouri    XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth);
4078645f5050Syouri    XPutImage (dpy, pixret, gc, ximage, 0, 0, x, y, width, height);
4079645f5050Syouri    image->width  = Scr->rootw;
4080645f5050Syouri    image->height = Scr->rooth;
4081645f5050Syouri  } else {
4082645f5050Syouri    pixret = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth);
4083645f5050Syouri    XPutImage (dpy, pixret, gc, ximage, 0, 0, 0, 0, width, height);
4084645f5050Syouri    image->width  = width;
4085645f5050Syouri    image->height = height;
4086645f5050Syouri  }
4087645f5050Syouri  XDestroyImage (ximage);
4088645f5050Syouri  image->pixmap = pixret;
4089645f5050Syouri  image->mask   = None;
4090645f5050Syouri  image->next   = None;
4091645f5050Syouri
4092645f5050Syouri  return image;
4093645f5050Syouri}
4094645f5050Syouri
4095645f5050Syouri#endif /* JPEG */
4096