2015-10-15 21:39:42 +02:00

4099 lines
113 KiB
C

/*****************************************************************************/
/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
/** Salt Lake City, Utah **/
/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
/** Cambridge, Massachusetts **/
/** **/
/** All Rights Reserved **/
/** **/
/** Permission to use, copy, modify, and distribute this software and **/
/** its documentation for any purpose and without fee is hereby **/
/** granted, provided that the above copyright notice appear in all **/
/** copies and that both that copyright notice and this permis- **/
/** sion notice appear in supporting documentation, and that the **/
/** names of Evans & Sutherland and M.I.T. not be used in advertising **/
/** in publicity pertaining to distribution of the software without **/
/** specific, written prior permission. **/
/** **/
/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
/** OR PERFORMANCE OF THIS SOFTWARE. **/
/*****************************************************************************/
/*
* [ ctwm ]
*
* Copyright 1992 Claude Lecommandeur.
*
* Permission to use, copy, modify and distribute this software [ctwm] and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting documen-
* tation, and that the name of Claude Lecommandeur not be used in adverti-
* sing or publicity pertaining to distribution of the software without
* specific, written prior permission. Claude Lecommandeur make no represen-
* tations about the suitability of this software for any purpose. It is
* provided "as is" without express or implied warranty.
*
* Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL Claude Lecommandeur BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* Author: Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
*/
/***********************************************************************
*
* $XConsortium: util.c,v 1.47 91/07/14 13:40:37 rws Exp $
*
* utility routines for twm
*
* 28-Oct-87 Thomas E. LaStrange File created
*
* Do the necessary modification to be integrated in ctwm.
* Can no longer be used for the standard twm.
*
* 22-April-92 Claude Lecommandeur.
*
* Changed behavior of DontMoveOff/MoveOffResistance to allow
* moving a window off screen less than #MoveOffResistance pixels.
* New code will no longer "snap" windows to #MoveOffResistance
* pixels off screen and instead movements will just be stopped and
* then resume once movement of #MoveOffResistance have been attempted.
*
* 15-December-02 Bjorn Knutsson
*
***********************************************************************/
#define LEVITTE_TEST
#include "twm.h"
#include "util.h"
#include "events.h"
#include "add_window.h"
#include "gram.tab.h"
#include "screen.h"
#include "icons.h"
#include "cursor.h"
#include <stdio.h>
/*
* Need this for the fixed-size uint_*'s used below. stdint.h would be
* the more appropriate include, but there exist systems that don't have
* it, but do have inttypes.h (FreeBSD 4, Solaris 7-9 I've heard of,
* probably more).
*/
#include <inttypes.h>
#ifdef VMS
#include <decw$include/Xos.h>
#include <decw$include/Xatom.h>
#include <decw$include/Xutil.h>
#include <X11Xmu/Drawing.h>
#include <X11Xmu/CharSet.h>
#include <X11Xmu/WinUtil.h>
#ifdef HAVE_XWDFILE_H
#include "XWDFile.h" /* We do some tricks, since the original
has bugs... /Richard Levitte */
#endif /* HAVE_XWDFILE_H */
#include <unixlib.h>
#include <starlet.h>
#include <ssdef.h>
#include <psldef.h>
#include <lib$routines.h>
#ifdef __DECC
#include <unistd.h>
#endif /* __DECC */
#define USE_SIGNALS
#ifndef F_OK
# define F_OK 0
#endif
#ifndef X_OK
# define X_OK 1
#endif
#ifndef W_OK
# define W_OK 2
#endif
#ifndef R_OK
# define R_OK 4
#endif
#else /* !VMS */
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/Xmu/Drawing.h>
#include <X11/Xmu/CharSet.h>
#include <X11/Xmu/WinUtil.h>
#include <X11/XWDFile.h>
#endif /* VMS */
#if defined(USE_SIGNALS) && defined(__sgi)
# define _BSD_SIGNALS
#endif
#include <signal.h>
#ifndef VMS
#include <sys/time.h>
#endif
#if defined (XPM)
#ifdef VMS
#include "xpm.h"
#else
# include <X11/xpm.h>
#endif
#endif
#ifdef JPEG
# include <setjmp.h>
# include <jpeglib.h>
# include <jerror.h>
static Image *LoadJpegImage (char *name);
static Image *GetJpegImage (char *name);
struct jpeg_error {
struct jpeg_error_mgr pub;
sigjmp_buf setjmp_buffer;
};
typedef struct jpeg_error *jerr_ptr;
#endif /* JPEG */
#ifdef IMCONV
# include "im.h"
# include "sdsc.h"
#endif
#define MAXANIMATIONSPEED 20
extern Atom _XA_WM_WORKSPACESLIST;
static Image *LoadBitmapImage (char *name, ColorPair cp);
static Image *GetBitmapImage (char *name, ColorPair cp);
#if !defined(VMS) || defined(HAVE_XWDFILE_H)
static Image *LoadXwdImage (char *filename, ColorPair cp);
static Image *GetXwdImage (char *name, ColorPair cp);
#endif
#ifdef XPM
static Image *LoadXpmImage (char *name, ColorPair cp);
static Image *GetXpmImage (char *name, ColorPair cp);
static void xpmErrorMessage (int status, char *name, char *fullname);
#endif
#ifdef IMCONV
static Image *GetImconvImage (char *filename,
unsigned int *widthp, unsigned int *heightp);
#endif
static Pixmap CreateXLogoPixmap(unsigned int *widthp, unsigned int *heightp);
static Pixmap CreateResizePixmap(unsigned int *widthp, unsigned int *heightp);
static Pixmap CreateQuestionPixmap(unsigned int *widthp, unsigned int *heightp);
static Pixmap CreateMenuPixmap(unsigned int *widthp, unsigned int *heightp);
static Pixmap CreateDotPixmap (unsigned int *widthp, unsigned int *heightp);
static Image *Create3DMenuImage (ColorPair cp);
static Image *Create3DDotImage (ColorPair cp);
static Image *Create3DResizeImage (ColorPair cp);
static Image *Create3DZoomImage (ColorPair cp);
static Image *Create3DBarImage (ColorPair cp);
static Image *Create3DVertBarImage (ColorPair cp);
static Image *Create3DResizeAnimation (Bool in, Bool left, Bool top,
ColorPair cp);
static Image *Create3DCrossImage (ColorPair cp);
static Image *Create3DIconifyImage (ColorPair cp);
static Image *Create3DSunkenResizeImage (ColorPair cp);
static Image *Create3DBoxImage (ColorPair cp);
extern FILE *tracefile;
void FreeImage (Image *image);
void _swapshort (register char *bp, register unsigned n);
void _swaplong (register char *bp, register unsigned n);
static int reportfilenotfound = 1;
static Colormap AlternateCmap = None;
int HotX, HotY;
int AnimationSpeed = 0;
Bool AnimationActive = False;
Bool MaybeAnimate = True;
#ifdef USE_SIGNALS
Bool AnimationPending = False;
#else
struct timeval AnimateTimeout;
#endif /* USE_SIGNALS */
/***********************************************************************
*
* Procedure:
* MoveOutline - move a window outline
*
* Inputs:
* root - the window we are outlining
* x - upper left x coordinate
* y - upper left y coordinate
* width - the width of the rectangle
* height - the height of the rectangle
* bw - the border width of the frame
* th - title height
*
***********************************************************************
*/
/* ARGSUSED */
void MoveOutline(Window root,
int x, int y, int width, int height, int bw, int th)
{
static int lastx = 0;
static int lasty = 0;
static int lastWidth = 0;
static int lastHeight = 0;
static int lastBW = 0;
static int lastTH = 0;
int xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb;
int xthird, ythird;
XSegment outline[18];
register XSegment *r;
if (x == lastx && y == lasty && width == lastWidth && height == lastHeight
&& lastBW == bw && th == lastTH)
return;
r = outline;
#define DRAWIT() \
if (lastWidth || lastHeight) \
{ \
xl = lastx; \
xr = lastx + lastWidth - 1; \
yt = lasty; \
yb = lasty + lastHeight - 1; \
xinnerl = xl + lastBW; \
xinnerr = xr - lastBW; \
yinnert = yt + lastTH + lastBW; \
yinnerb = yb - lastBW; \
xthird = (xinnerr - xinnerl) / 3; \
ythird = (yinnerb - yinnert) / 3; \
\
r->x1 = xl; \
r->y1 = yt; \
r->x2 = xr; \
r->y2 = yt; \
r++; \
\
r->x1 = xl; \
r->y1 = yb; \
r->x2 = xr; \
r->y2 = yb; \
r++; \
\
r->x1 = xl; \
r->y1 = yt; \
r->x2 = xl; \
r->y2 = yb; \
r++; \
\
r->x1 = xr; \
r->y1 = yt; \
r->x2 = xr; \
r->y2 = yb; \
r++; \
\
r->x1 = xinnerl + xthird; \
r->y1 = yinnert; \
r->x2 = r->x1; \
r->y2 = yinnerb; \
r++; \
\
r->x1 = xinnerl + (2 * xthird); \
r->y1 = yinnert; \
r->x2 = r->x1; \
r->y2 = yinnerb; \
r++; \
\
r->x1 = xinnerl; \
r->y1 = yinnert + ythird; \
r->x2 = xinnerr; \
r->y2 = r->y1; \
r++; \
\
r->x1 = xinnerl; \
r->y1 = yinnert + (2 * ythird); \
r->x2 = xinnerr; \
r->y2 = r->y1; \
r++; \
\
if (lastTH != 0) { \
r->x1 = xl; \
r->y1 = yt + lastTH; \
r->x2 = xr; \
r->y2 = r->y1; \
r++; \
} \
}
/* undraw the old one, if any */
DRAWIT ();
lastx = x;
lasty = y;
lastWidth = width;
lastHeight = height;
lastBW = bw;
lastTH = th;
/* draw the new one, if any */
DRAWIT ();
#undef DRAWIT
if (r != outline)
{
XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline);
}
}
/***********************************************************************
*
* Procedure:
* Zoom - zoom in or out of an icon
*
* Inputs:
* wf - window to zoom from
* wt - window to zoom to
*
***********************************************************************
*/
void Zoom(Window wf, Window wt)
{
int fx, fy, tx, ty; /* from, to */
unsigned int fw, fh, tw, th; /* from, to */
long dx, dy, dw, dh;
long z;
int j;
if ((Scr->IconifyStyle != ICONIFY_NORMAL) || !Scr->DoZoom || Scr->ZoomCount < 1) return;
if (wf == None || wt == None) return;
XGetGeometry (dpy, wf, &JunkRoot, &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth);
XGetGeometry (dpy, wt, &JunkRoot, &tx, &ty, &tw, &th, &JunkBW, &JunkDepth);
dx = (long) tx - (long) fx; /* going from -> to */
dy = (long) ty - (long) fy; /* going from -> to */
dw = (long) tw - (long) fw; /* going from -> to */
dh = (long) th - (long) fh; /* going from -> to */
z = (long) (Scr->ZoomCount + 1);
for (j = 0; j < 2; j++) {
long i;
XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh);
for (i = 1; i < z; i++) {
int x = fx + (int) ((dx * i) / z);
int y = fy + (int) ((dy * i) / z);
unsigned width = (unsigned) (((long) fw) + (dw * i) / z);
unsigned height = (unsigned) (((long) fh) + (dh * i) / z);
XDrawRectangle (dpy, Scr->Root, Scr->DrawGC,
x, y, width, height);
}
XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th);
}
}
char *ExpandFilePath (char *path)
{
char *ret, *colon, *p;
int len;
len = 0;
p = path;
while ((colon = strchr (p, ':'))) {
len += colon - p + 1;
if (*p == '~') len += HomeLen - 1;
p = colon + 1;
}
if (*p == '~') len += HomeLen - 1;
len += strlen (p);
ret = (char*) malloc (len + 1);
*ret = 0;
p = path;
while ((colon = strchr (p, ':'))) {
*colon = '\0';
if (*p == '~') {
strcat (ret, Home);
strcat (ret, p + 1);
} else {
strcat (ret, p);
}
*colon = ':';
strcat (ret, ":");
p = colon + 1;
}
if (*p == '~') {
strcat (ret, Home);
strcat (ret, p + 1);
} else {
strcat (ret, p);
}
return ret;
}
/***********************************************************************
*
* Procedure:
* ExpandFilename - expand the tilde character to HOME
* if it is the first character of the filename
*
* Returned Value:
* a pointer to the new name
*
* Inputs:
* name - the filename to expand
*
***********************************************************************
*/
char *ExpandFilename(char *name)
{
char *newname;
if (name[0] != '~') return name;
#ifdef VMS
newname = (char *) malloc (HomeLen + strlen(name) + 1);
if (!newname) {
fprintf (stderr,
"%s: unable to allocate %d bytes to expand filename %s%s\n",
ProgramName, HomeLen + strlen(name) + 1, Home, &name[1]);
} else {
(void) sprintf (newname, "%s%s", Home, &name[1]);
}
#else
newname = (char *) malloc (HomeLen + strlen(name) + 2);
if (!newname) {
fprintf (stderr,
"%s: unable to allocate %lu bytes to expand filename %s/%s\n",
ProgramName, (unsigned long) HomeLen + strlen(name) + 2,
Home, &name[1]);
} else {
(void) sprintf (newname, "%s/%s", Home, &name[1]);
}
#endif
return newname;
}
char *ExpandPixmapPath (char *name)
{
char *ret, *colon;
ret = NULL;
#ifdef VMS
if (name[0] == '~') {
ret = (char *) malloc (HomeLen + strlen (name) + 1);
sprintf (ret, "%s%s", Home, &name[1]);
}
if (name[0] == '/') {
ret = (char *) malloc (strlen (name));
sprintf (ret, "%s", &name[1]);
}
else
if (Scr->PixmapDirectory) {
char *p = Scr->PixmapDirectory;
while (colon = strchr (p, ':')) {
*colon = '\0';
ret = (char *) malloc (strlen (p) + strlen (name) + 1);
sprintf (ret, "%s%s", p, name);
*colon = ':';
if (!access (ret, R_OK)) return (ret);
p = colon + 1;
}
ret = (char *) malloc (strlen (Scr->PixmapDirectory) + strlen (name) + 1);
sprintf (ret, "%s%s", Scr->PixmapDirectory, name);
}
#else
if (name[0] == '~') {
ret = (char *) malloc (HomeLen + strlen (name) + 2);
sprintf (ret, "%s/%s", Home, &name[1]);
}
else
if (name[0] == '/') {
ret = (char *) malloc (strlen (name) + 1);
strcpy (ret, name);
}
else
if (Scr->PixmapDirectory) {
char *p = Scr->PixmapDirectory;
while ((colon = strchr (p, ':'))) {
*colon = '\0';
ret = (char *) malloc (strlen (p) + strlen (name) + 2);
sprintf (ret, "%s/%s", p, name);
*colon = ':';
if (!access (ret, R_OK)) return (ret);
p = colon + 1;
}
ret = (char *) malloc (strlen (p) + strlen (name) + 2);
sprintf (ret, "%s/%s", p, name);
}
#endif
return (ret);
}
/***********************************************************************
*
* Procedure:
* GetUnknownIcon - read in the bitmap file for the unknown icon
*
* Inputs:
* name - the filename to read
*
***********************************************************************
*/
void GetUnknownIcon(char *name)
{
Scr->UnknownImage = GetImage (name, Scr->IconC);
}
/***********************************************************************
*
* Procedure:
* FindBitmap - read in a bitmap file and return size
*
* Returned Value:
* the pixmap associated with the bitmap
* widthp - pointer to width of bitmap
* heightp - pointer to height of bitmap
*
* Inputs:
* name - the filename to read
*
***********************************************************************
*/
Pixmap FindBitmap (char *name, unsigned int *widthp, unsigned int *heightp)
{
char *bigname;
Pixmap pm;
if (!name) return None;
/*
* Names of the form :name refer to hardcoded images that are scaled to
* look nice in title buttons. Eventually, it would be nice to put in a
* menu symbol as well....
*/
if (name[0] == ':') {
int i;
static struct {
char *name;
Pixmap (*proc)(unsigned int *wp, unsigned int *hp);
} pmtab[] = {
{ TBPM_DOT, CreateDotPixmap },
{ TBPM_ICONIFY, CreateDotPixmap },
{ TBPM_RESIZE, CreateResizePixmap },
{ TBPM_XLOGO, CreateXLogoPixmap },
{ TBPM_DELETE, CreateXLogoPixmap },
{ TBPM_MENU, CreateMenuPixmap },
{ TBPM_QUESTION, CreateQuestionPixmap },
};
for (i = 0; i < (sizeof pmtab)/(sizeof pmtab[0]); i++) {
if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0)
return (*pmtab[i].proc) (widthp, heightp);
}
fprintf (stderr, "%s: no such built-in bitmap \"%s\"\n",
ProgramName, name);
return None;
}
/*
* Generate a full pathname if any special prefix characters (such as ~)
* are used. If the bigname is different from name, bigname will need to
* be freed.
*/
bigname = ExpandFilename (name);
if (!bigname) return None;
/*
* look along bitmapFilePath resource same as toolkit clients
*/
pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL,
0, (int *)widthp, (int *)heightp, &HotX, &HotY);
if (pm == None && Scr->IconDirectory && bigname[0] != '/') {
if (bigname != name) free (bigname);
/*
* Attempt to find icon in old IconDirectory (now obsolete)
*/
#ifdef VMS
bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 1);
if (!bigname) {
fprintf (stderr,
"%s: unable to allocate memory for \"%s%s\"\n",
ProgramName, Scr->IconDirectory, name);
return None;
}
(void) sprintf (bigname, "%s%s", Scr->IconDirectory, name);
#else
bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 2);
if (!bigname) {
fprintf (stderr,
"%s: unable to allocate memory for \"%s/%s\"\n",
ProgramName, Scr->IconDirectory, name);
return None;
}
(void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name);
#endif
if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm,
&HotX, &HotY) != BitmapSuccess) {
pm = None;
}
}
if (bigname != name) free (bigname);
if ((pm == None) && reportfilenotfound) {
fprintf (stderr, "%s: unable to find bitmap \"%s\"\n", ProgramName, name);
}
return pm;
}
Pixmap GetBitmap (char *name)
{
return FindBitmap (name, &JunkWidth, &JunkHeight);
}
static Image *LoadBitmapImage (char *name, ColorPair cp)
{
Image *image;
Pixmap bm;
unsigned int width, height;
XGCValues gcvalues;
if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues);
bm = FindBitmap (name, &width, &height);
if (bm == None) return (None);
image = (Image*) malloc (sizeof (struct _Image));
image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth);
gcvalues.background = cp.back;
gcvalues.foreground = cp.fore;
XChangeGC (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues);
XCopyPlane (dpy, bm, image->pixmap, Scr->rootGC, 0, 0, width, height,
0, 0, (unsigned long) 1);
XFreePixmap (dpy, bm);
image->mask = None;
image->width = width;
image->height = height;
image->next = None;
return (image);
}
static Image *GetBitmapImage (char *name, ColorPair cp)
{
Image *image, *r, *s;
char path [128], pref [128];
char *perc;
int i;
if (! strchr (name, '%')) return (LoadBitmapImage (name, cp));
s = image = None;
strcpy (pref, name);
perc = strchr (pref, '%');
*perc = '\0';
reportfilenotfound = 0;
for (i = 1;; i++) {
sprintf (path, "%s%d%s", pref, i, perc + 1);
r = LoadBitmapImage (path, cp);
if (r == None) break;
r->next = None;
if (image == None) s = image = r;
else {
s->next = r;
s = r;
}
}
reportfilenotfound = 1;
if (s != None) s->next = image;
if (image == None) {
fprintf (stderr, "Cannot open any %s bitmap file\n", name);
}
return (image);
}
#ifdef XPM
static int reportxpmerror = 1;
static Image *LoadXpmImage (char *name, ColorPair cp)
{
char *fullname;
Image *image;
int status;
Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
XpmAttributes attributes;
static XpmColorSymbol overrides[] = {
{"Foreground", NULL, 0},
{"Background", NULL, 0},
{"HiShadow", NULL, 0},
{"LoShadow", NULL, 0}
};
fullname = ExpandPixmapPath (name);
if (! fullname) return (None);
image = (Image*) malloc (sizeof (struct _Image));
if (image == None) return (None);
attributes.valuemask = 0;
attributes.valuemask |= XpmSize;
attributes.valuemask |= XpmReturnPixels;
attributes.valuemask |= XpmColormap;
attributes.valuemask |= XpmDepth;
attributes.valuemask |= XpmVisual;
attributes.valuemask |= XpmCloseness;
attributes.valuemask |= XpmColorSymbols;
attributes.numsymbols = 4;
attributes.colorsymbols = overrides;
overrides[0].pixel = cp.fore;
overrides[1].pixel = cp.back;
overrides[2].pixel = cp.shadd;
overrides[3].pixel = cp.shadc;
attributes.colormap = AlternateCmap ? AlternateCmap : stdcmap;
attributes.depth = Scr->d_depth;
attributes.visual = Scr->d_visual;
attributes.closeness = 65535; /* Never fail */
status = XpmReadFileToPixmap(dpy, Scr->Root, fullname,
&(image->pixmap), &(image->mask), &attributes);
if (status != XpmSuccess) {
xpmErrorMessage (status, name, fullname);
free (image);
return (None);
}
free (fullname);
image->width = attributes.width;
image->height = attributes.height;
image->next = None;
return (image);
}
static Image *GetXpmImage (char *name, ColorPair cp)
{
char path [128], pref [128];
Image *image, *r, *s;
char *perc;
int i;
if (! strchr (name, '%')) return (LoadXpmImage (name, cp));
s = image = None;
strcpy (pref, name);
perc = strchr (pref, '%');
*perc = '\0';
reportfilenotfound = 0;
for (i = 1;; i++) {
sprintf (path, "%s%d%s", pref, i, perc + 1);
r = LoadXpmImage (path, cp);
if (r == None) break;
r->next = None;
if (image == None) s = image = r;
else {
s->next = r;
s = r;
}
}
reportfilenotfound = 1;
if (s != None) s->next = image;
if (image == None) {
fprintf (stderr, "Cannot open any %s XPM file\n", name);
}
return (image);
}
static void xpmErrorMessage (int status, char *name, char *fullname)
{
switch (status) {
case XpmSuccess:
break;
case XpmColorError:
if (reportxpmerror)
fprintf (stderr,
"Could not parse or alloc requested color : %s\n",
fullname);
return;
case XpmOpenFailed:
if (reportxpmerror && reportfilenotfound)
fprintf (stderr, "unable to locate XPM file : %s\n", fullname);
return;
case XpmFileInvalid:
fprintf (stderr, "invalid XPM file : %s\n", fullname);
return;
case XpmNoMemory:
if (reportxpmerror)
fprintf (stderr, "Not enough memory for XPM file : %s\n", fullname);
return;
case XpmColorFailed:
if (reportxpmerror)
fprintf (stderr, "Color not found in : %s\n", fullname);
return;
default :
fprintf (stderr, "Unknown error in : %s\n", fullname);
return;
}
}
#endif
void MaskScreen (char *file)
{
unsigned long valuemask;
XSetWindowAttributes attributes;
XEvent event;
Cursor waitcursor;
int x, y;
ColorPair WelcomeCp;
XColor black;
NewFontCursor (&waitcursor, "watch");
valuemask = (CWBackingStore | CWSaveUnder | CWBackPixel |
CWOverrideRedirect | CWEventMask | CWCursor);
attributes.backing_store = NotUseful;
attributes.save_under = False;
attributes.override_redirect = True;
attributes.event_mask = ExposureMask;
attributes.cursor = waitcursor;
attributes.background_pixel = Scr->Black;
Scr->WindowMask = XCreateWindow (dpy, Scr->Root, 0, 0,
(unsigned int) Scr->rootw,
(unsigned int) Scr->rooth,
(unsigned int) 0,
CopyFromParent, (unsigned int) CopyFromParent,
(Visual *) CopyFromParent, valuemask,
&attributes);
XMapWindow (dpy, Scr->WindowMask);
XMaskEvent (dpy, ExposureMask, &event);
if (Scr->Monochrome != COLOR) return;
WelcomeCp.fore = Scr->Black;
WelcomeCp.back = Scr->White;
Scr->WelcomeCmap = XCreateColormap (dpy, Scr->WindowMask, Scr->d_visual, AllocNone);
if (! Scr->WelcomeCmap) return;
XSetWindowColormap (dpy, Scr->WindowMask, Scr->WelcomeCmap);
black.red = 0;
black.green = 0;
black.blue = 0;
XAllocColor (dpy, Scr->WelcomeCmap, &black);
reportfilenotfound = 0;
AlternateCmap = Scr->WelcomeCmap;
if (! file) {
Scr->WelcomeImage = GetImage ("xwd:welcome.xwd", WelcomeCp);
#ifdef XPM
if (Scr->WelcomeImage == None)
Scr->WelcomeImage = GetImage ("xpm:welcome.xpm", WelcomeCp);
#endif
}
else {
Scr->WelcomeImage = GetImage (file, WelcomeCp);
}
AlternateCmap = None;
reportfilenotfound = 1;
if (Scr->WelcomeImage == None) return;
if (captive) {
XSetWindowColormap (dpy, Scr->WindowMask, Scr->WelcomeCmap);
XSetWMColormapWindows (dpy, Scr->Root, &(Scr->WindowMask), 1);
}
else XInstallColormap (dpy, Scr->WelcomeCmap);
Scr->WelcomeGC = XCreateGC (dpy, Scr->WindowMask, 0, NULL);
x = (Scr->rootw - Scr->WelcomeImage->width) / 2;
y = (Scr->rooth - Scr->WelcomeImage->height) / 2;
XSetWindowBackground (dpy, Scr->WindowMask, black.pixel);
XClearWindow (dpy, Scr->WindowMask);
XCopyArea (dpy, Scr->WelcomeImage->pixmap, Scr->WindowMask, Scr->WelcomeGC, 0, 0,
Scr->WelcomeImage->width, Scr->WelcomeImage->height, x, y);
}
void UnmaskScreen (void)
{
#ifdef VMS
float timeout;
#else
struct timeval timeout;
#endif
Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
Colormap cmap;
XColor colors [256], stdcolors [256];
int i, j, usec;
#ifdef VMS
timeout = 0.017;
#else
usec = 10000;
timeout.tv_usec = usec % (unsigned long) 1000000;
timeout.tv_sec = usec / (unsigned long) 1000000;
#endif
if (Scr->WelcomeImage) {
Pixel pixels [256];
cmap = Scr->WelcomeCmap;
for (i = 0; i < 256; i++) {
pixels [i] = i;
colors [i].pixel = i;
}
XQueryColors (dpy, cmap, colors, 256);
XFreeColors (dpy, cmap, pixels, 256, 0L);
XFreeColors (dpy, cmap, pixels, 256, 0L); /* Ah Ah */
for (i = 0; i < 256; i++) {
colors [i].pixel = i;
colors [i].flags = DoRed | DoGreen | DoBlue;
stdcolors [i].red = colors [i].red;
stdcolors [i].green = colors [i].green;
stdcolors [i].blue = colors [i].blue;
}
for (i = 0; i < 128; i++) {
for (j = 0; j < 256; j++) {
colors [j].red = stdcolors [j].red * ((127.0 - i) / 128.0);
colors [j].green = stdcolors [j].green * ((127.0 - i) / 128.0);
colors [j].blue = stdcolors [j].blue * ((127.0 - i) / 128.0);
}
XStoreColors (dpy, cmap, colors, 256);
#ifdef VMS
lib$wait(&timeout);
#else
select (0, (void *) 0, (void *) 0, (void *) 0, &timeout);
#endif
}
XFreeColors (dpy, cmap, pixels, 256, 0L);
XFreeGC (dpy, Scr->WelcomeGC);
FreeImage (Scr->WelcomeImage);
}
if (Scr->Monochrome != COLOR) goto fin;
cmap = XCreateColormap (dpy, Scr->Root, Scr->d_visual, AllocNone);
if (! cmap) goto fin;
for (i = 0; i < 256; i++) {
colors [i].pixel = i;
colors [i].red = 0;
colors [i].green = 0;
colors [i].blue = 0;
colors [i].flags = DoRed | DoGreen | DoBlue;
}
XStoreColors (dpy, cmap, colors, 256);
if (captive) XSetWindowColormap (dpy, Scr->Root, cmap);
else XInstallColormap (dpy, cmap);
XUnmapWindow (dpy, Scr->WindowMask);
XClearWindow (dpy, Scr->Root);
XSync (dpy, 0);
PaintAllDecoration ();
for (i = 0; i < 256; i++) stdcolors [i].pixel = i;
XQueryColors (dpy, stdcmap, stdcolors, 256);
for (i = 0; i < 128; i++) {
for (j = 0; j < 256; j++) {
colors [j].pixel = j;
colors [j].red = stdcolors [j].red * (i / 127.0);
colors [j].green = stdcolors [j].green * (i / 127.0);
colors [j].blue = stdcolors [j].blue * (i / 127.0);
colors [j].flags = DoRed | DoGreen | DoBlue;
}
XStoreColors (dpy, cmap, colors, 256);
#ifdef VMS
lib$wait(&timeout);
#else
select (0, (void *) 0, (void *) 0, (void *) 0, &timeout);
#endif
}
if (captive) XSetWindowColormap (dpy, Scr->Root, stdcmap);
else XInstallColormap (dpy, stdcmap);
XFreeColormap (dpy, cmap);
fin:
if (Scr->WelcomeCmap) XFreeColormap (dpy, Scr->WelcomeCmap);
XDestroyWindow (dpy, Scr->WindowMask);
Scr->WindowMask = (Window) 0;
}
#ifdef VMS
/* use the VMS system services to request the timer to issue an AST */
void AnimateHandler (void);
unsigned int tv[2];
int status;
static unsigned long timefi;
/* unsigned long timefe = 17; */
unsigned long timefe;
#define TIMID 12L
void StartAnimation (void)
{
if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
if (AnimationSpeed <= 0) return;
if (AnimationActive) return;
if (!timefi) lib$get_ef(&timefi);
if (!timefe) lib$get_ef(&timefe);
tv[1] = 0xFFFFFFFF; /* quadword negative for relative */
tv[0] = -(10000000 / AnimationSpeed); /* time. In units of 100ns. */
sys$clref(timefe);
status = sys$setimr (timefi, &tv, AnimateHandler, TIMID );
if (status != SS$_NORMAL) lib$signal(status);
AnimationActive = True;
}
void StopAnimation () {
if (AnimationSpeed <= 0) return;
if (! AnimationActive) return;
AnimationActive = False;
status = sys$cantim(TIMID, PSL$C_USER);
if (status != SS$_NORMAL) lib$signal(status);
}
void SetAnimationSpeed (int speed)
{
AnimationSpeed = speed;
if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
}
void ModifyAnimationSpeed (int incr)
{
if ((AnimationSpeed + incr) < 0) return;
if ((AnimationSpeed + incr) == 0) {
if (AnimationActive) StopAnimation ();
AnimationSpeed = 0;
return;
}
AnimationSpeed += incr;
status = sys$cantim(TIMID, PSL$C_USER);
if (status != SS$_NORMAL) lib$signal(status);
tv[1] = 0xFFFFFFFF;
tv[0] = -(10000000 / AnimationSpeed);
sys$clref(timefe);
status = sys$setimr (timefi, &tv, AnimateHandler, TIMID);
if (status != SS$_NORMAL) lib$signal(status);
AnimationActive = True;
}
void AnimateHandler (void) {
AnimationPending = True;
sys$setef(timefe);
status = sys$setimr (timefi, &tv, AnimateHandler, TIMID);
if (status != SS$_NORMAL) lib$signal(status);
}
#else /* VMS */
#ifdef USE_SIGNALS
SIGNAL_T AnimateHandler ();
#endif
#ifndef USE_SIGNALS
void TryToAnimate (void)
{
struct timeval tp;
struct timezone tzp;
static unsigned long lastsec;
static long lastusec;
unsigned long gap;
gettimeofday (&tp, &tzp);
gap = ((tp.tv_sec - lastsec) * 1000000) + (tp.tv_usec - lastusec);
if (tracefile) {
fprintf (tracefile, "Time = %lu, %ld, %ld, %ld, %lu\n", lastsec,
lastusec, (long)tp.tv_sec, (long)tp.tv_usec, gap);
fflush (tracefile);
}
gap *= AnimationSpeed;
if (gap < 1000000) return;
if (tracefile) {
fprintf (tracefile, "Animate\n");
fflush (tracefile);
}
Animate ();
lastsec = tp.tv_sec;
lastusec = tp.tv_usec;
}
#endif /* USE_SIGNALS */
void StartAnimation (void)
{
#ifdef USE_SIGNALS
struct itimerval tv;
#endif
if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
if (AnimationSpeed <= 0) AnimationSpeed = 0;
if (AnimationActive) return;
#ifdef USE_SIGNALS
if (AnimationSpeed == 0) return;
signal (SIGALRM, AnimateHandler);
if (AnimationSpeed == 1) {
tv.it_interval.tv_sec = 1;
tv.it_interval.tv_usec = 0;
tv.it_value.tv_sec = 1;
tv.it_value.tv_usec = 0;
}
else {
tv.it_interval.tv_sec = 0;
tv.it_interval.tv_usec = 1000000 / AnimationSpeed;
tv.it_value.tv_sec = 0;
tv.it_value.tv_usec = 1000000 / AnimationSpeed;
}
setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL);
#else /* USE_SIGNALS */
switch (AnimationSpeed) {
case 0 :
return;
case 1 :
AnimateTimeout.tv_sec = 1;
AnimateTimeout.tv_usec = 0;
break;
default :
AnimateTimeout.tv_sec = 0;
AnimateTimeout.tv_usec = 1000000 / AnimationSpeed;
}
#endif /* USE_SIGNALS */
AnimationActive = True;
}
void StopAnimation (void)
{
#ifdef USE_SIGNALS
struct itimerval tv;
if (AnimationSpeed <= 0) return;
if (! AnimationActive) return;
signal (SIGALRM, SIG_IGN);
tv.it_value.tv_sec = 0;
tv.it_value.tv_usec = 0;
setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL);
#endif
AnimationActive = False;
}
void SetAnimationSpeed (int speed)
{
AnimationSpeed = speed;
if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
}
void ModifyAnimationSpeed (int incr)
{
#ifdef USE_SIGNALS
struct itimerval tv;
#endif
if ((AnimationSpeed + incr) < 0) return;
if ((AnimationSpeed + incr) == 0) {
if (AnimationActive) StopAnimation ();
AnimationSpeed = 0;
return;
}
AnimationSpeed += incr;
if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED;
#ifdef USE_SIGNALS
signal (SIGALRM, AnimateHandler);
if (AnimationSpeed == 1) {
tv.it_interval.tv_sec = 1;
tv.it_interval.tv_usec = 0;
tv.it_value.tv_sec = 1;
tv.it_value.tv_usec = 0;
}
else {
tv.it_interval.tv_sec = 0;
tv.it_interval.tv_usec = 1000000 / AnimationSpeed;
tv.it_value.tv_sec = 0;
tv.it_value.tv_usec = 1000000 / AnimationSpeed;
}
setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL);
#else /* USE_SIGNALS */
if (AnimationSpeed == 1) {
AnimateTimeout.tv_sec = 1;
AnimateTimeout.tv_usec = 0;
}
else {
AnimateTimeout.tv_sec = 0;
AnimateTimeout.tv_usec = 1000000 / AnimationSpeed;
}
#endif /* USE_SIGNALS */
AnimationActive = True;
}
#ifdef USE_SIGNALS
SIGNAL_T AnimateHandler (int dummy)
{
signal (SIGALRM, AnimateHandler);
AnimationPending = True;
}
#endif
#endif /* VMS */
void Animate (void)
{
TwmWindow *t;
int scrnum;
ScreenInfo *scr;
int i;
TBWindow *tbw;
int nb;
if (AnimationSpeed == 0) return;
#ifdef USE_SIGNALS
AnimationPending = False;
#endif
MaybeAnimate = False;
for (scrnum = 0; scrnum < NumScreens; scrnum++) {
if ((scr = ScreenList [scrnum]) == NULL) continue;
for (t = scr->FirstWindow; t != NULL; t = t->next) {
if (! visible (t)) continue;
if (t->icon_on && t->icon && t->icon->bm_w && t->icon->image &&
t->icon->image->next) {
AnimateIcons (scr, t->icon);
MaybeAnimate = True;
}
else
if (t->mapped && t->titlebuttons) {
nb = scr->TBInfo.nleft + scr->TBInfo.nright;
for (i = 0, tbw = t->titlebuttons; i < nb; i++, tbw++) {
if (tbw->image && tbw->image->next) {
AnimateButton (tbw);
MaybeAnimate = True;
}
}
}
}
if (scr->Focus) {
t = scr->Focus;
if (t->mapped && t->titlehighlight && t->title_height &&
t->HiliteImage && t->HiliteImage->next) {
AnimateHighlight (t);
MaybeAnimate = True;
}
}
}
MaybeAnimate |= AnimateRoot ();
XFlush (dpy);
return;
}
void InsertRGBColormap (Atom a, XStandardColormap *maps, int nmaps,
Bool replace)
{
StdCmap *sc = NULL;
if (replace) { /* locate existing entry */
for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
if (sc->atom == a) break;
}
}
if (!sc) { /* no existing, allocate new */
sc = (StdCmap *) malloc (sizeof (StdCmap));
if (!sc) {
fprintf (stderr, "%s: unable to allocate %lu bytes for StdCmap\n",
ProgramName, (unsigned long) sizeof(StdCmap));
return;
}
}
if (replace) { /* just update contents */
if (sc->maps) XFree ((char *) maps);
if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL;
} else { /* else appending */
sc->next = NULL;
sc->atom = a;
if (Scr->StdCmapInfo.tail) {
Scr->StdCmapInfo.tail->next = sc;
} else {
Scr->StdCmapInfo.head = sc;
}
Scr->StdCmapInfo.tail = sc;
}
sc->nmaps = nmaps;
sc->maps = maps;
return;
}
void RemoveRGBColormap (Atom a)
{
StdCmap *sc, *prev;
prev = NULL;
for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
if (sc->atom == a) break;
prev = sc;
}
if (sc) { /* found one */
if (sc->maps) XFree ((char *) sc->maps);
if (prev) prev->next = sc->next;
if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next;
if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev;
if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL;
}
return;
}
void LocateStandardColormaps(void)
{
Atom *atoms;
int natoms;
int i;
atoms = XListProperties (dpy, Scr->Root, &natoms);
for (i = 0; i < natoms; i++) {
XStandardColormap *maps = NULL;
int nmaps;
if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
/* if got one, then append to current list */
InsertRGBColormap (atoms[i], maps, nmaps, False);
}
}
if (atoms) XFree ((char *) atoms);
return;
}
void GetColor(int kind, Pixel *what, char *name)
{
XColor color;
Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c;
#ifndef TOM
if (!Scr->FirstTime)
return;
#endif
if (Scr->Monochrome != kind)
return;
if (! XParseColor (dpy, cmap, name, &color)) {
fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name);
return;
}
if (! XAllocColor (dpy, cmap, &color))
{
/* if we could not allocate the color, let's see if this is a
* standard colormap
*/
XStandardColormap *stdcmap = NULL;
if (! XParseColor (dpy, cmap, name, &color)) {
fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name);
return;
}
/*
* look through the list of standard colormaps (check cache first)
*/
if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps &&
(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap ==
cmap)) {
stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]);
} else {
StdCmap *sc;
for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
int i;
for (i = 0; i < sc->nmaps; i++) {
if (sc->maps[i].colormap == cmap) {
Scr->StdCmapInfo.mru = sc;
Scr->StdCmapInfo.mruindex = i;
stdcmap = &(sc->maps[i]);
goto gotit;
}
}
}
}
gotit:
if (stdcmap) {
color.pixel = (stdcmap->base_pixel +
((Pixel)(((float)color.red / 65535.0) *
stdcmap->red_max + 0.5) *
stdcmap->red_mult) +
((Pixel)(((float)color.green /65535.0) *
stdcmap->green_max + 0.5) *
stdcmap->green_mult) +
((Pixel)(((float)color.blue / 65535.0) *
stdcmap->blue_max + 0.5) *
stdcmap->blue_mult));
} else {
fprintf (stderr, "%s: unable to allocate color \"%s\"\n",
ProgramName, name);
return;
}
}
*what = color.pixel;
return;
}
void GetShadeColors (ColorPair *cp)
{
XColor xcol;
Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c;
int save;
float clearfactor;
float darkfactor;
char clearcol [32], darkcol [32];
clearfactor = (float) Scr->ClearShadowContrast / 100.0;
darkfactor = (100.0 - (float) Scr->DarkShadowContrast) / 100.0;
xcol.pixel = cp->back;
XQueryColor (dpy, cmap, &xcol);
sprintf (clearcol, "#%04x%04x%04x",
xcol.red + (unsigned short) ((65535 - xcol.red) * clearfactor),
xcol.green + (unsigned short) ((65535 - xcol.green) * clearfactor),
xcol.blue + (unsigned short) ((65535 - xcol.blue) * clearfactor));
sprintf (darkcol, "#%04x%04x%04x",
(unsigned short) (xcol.red * darkfactor),
(unsigned short) (xcol.green * darkfactor),
(unsigned short) (xcol.blue * darkfactor));
save = Scr->FirstTime;
Scr->FirstTime = True;
GetColor (Scr->Monochrome, &cp->shadc, clearcol);
GetColor (Scr->Monochrome, &cp->shadd, darkcol);
Scr->FirstTime = save;
}
void GetFont(MyFont *font)
{
char *deffontname = "fixed,*";
char **missing_charset_list_return;
int missing_charset_count_return;
char *def_string_return;
XFontSetExtents *font_extents;
XFontStruct **xfonts;
char **font_names;
register int i;
int ascent;
int descent;
int fnum;
char *basename2;
if (font->font_set != NULL){
XFreeFontSet(dpy, font->font_set);
}
basename2 = (char *)malloc(strlen(font->basename) + 3);
if (basename2) sprintf(basename2, "%s,*", font->basename);
else basename2 = font->basename;
if( (font->font_set = XCreateFontSet(dpy, basename2,
&missing_charset_list_return,
&missing_charset_count_return,
&def_string_return)) == NULL) {
if (Scr->DefaultFont.basename) {
deffontname = Scr->DefaultFont.basename;
}
if ((font->font_set = XCreateFontSet(dpy, deffontname,
&missing_charset_list_return,
&missing_charset_count_return,
&def_string_return)) == NULL)
{
fprintf (stderr, "%s: unable to open fonts \"%s\" or \"%s\"\n",
ProgramName, font->basename, deffontname);
exit(1);
}
}
if (basename2 != font->basename) free(basename2);
font_extents = XExtentsOfFontSet(font->font_set);
fnum = XFontsOfFontSet(font->font_set, &xfonts, &font_names);
for( i = 0, ascent = 0, descent = 0; i<fnum; i++){
ascent = MaxSize(ascent, (*xfonts)->ascent);
descent = MaxSize(descent, (*xfonts)->descent);
xfonts++;
}
font->height = font_extents->max_logical_extent.height;
font->y = ascent;
font->ascent = ascent;
font->descent = descent;
}
void SetFocusVisualAttributes (TwmWindow *tmp_win, Bool focus)
{
if (! tmp_win) return;
if (focus == tmp_win->hasfocusvisible) return;
if (tmp_win->highlight) {
if (Scr->use3Dborders) {
PaintBorders (tmp_win, focus);
}
else {
if (focus) {
XSetWindowBorder (dpy, tmp_win->frame, tmp_win->borderC.back);
if (tmp_win->title_w)
XSetWindowBorder (dpy, tmp_win->title_w, tmp_win->borderC.back);
} else {
XSetWindowBorderPixmap (dpy, tmp_win->frame, tmp_win->gray);
if (tmp_win->title_w)
XSetWindowBorderPixmap (dpy, tmp_win->title_w, tmp_win->gray);
}
}
}
if (focus) {
Bool hil = False;
if (tmp_win->lolite_wl) XUnmapWindow (dpy, tmp_win->lolite_wl);
if (tmp_win->lolite_wr) XUnmapWindow (dpy, tmp_win->lolite_wr);
if (tmp_win->hilite_wl) {
XMapWindow (dpy, tmp_win->hilite_wl);
hil = True;
}
if (tmp_win->hilite_wr) {
XMapWindow (dpy, tmp_win->hilite_wr);
hil = True;
}
if (hil && tmp_win->HiliteImage && tmp_win->HiliteImage->next) {
MaybeAnimate = True;
}
if (tmp_win->iconmanagerlist)
ActiveIconManager (tmp_win->iconmanagerlist);
}
else {
if (tmp_win->hilite_wl) XUnmapWindow (dpy, tmp_win->hilite_wl);
if (tmp_win->hilite_wr) XUnmapWindow (dpy, tmp_win->hilite_wr);
if (tmp_win->lolite_wl) XMapWindow (dpy, tmp_win->lolite_wl);
if (tmp_win->lolite_wr) XMapWindow (dpy, tmp_win->lolite_wr);
if (tmp_win->iconmanagerlist)
NotActiveIconManager (tmp_win->iconmanagerlist);
}
if (Scr->use3Dtitles && Scr->SunkFocusWindowTitle && tmp_win->title_height) {
ButtonState bs;
bs = focus ? on : off;
Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0,
tmp_win->title_width - Scr->TBInfo.titlex -
Scr->TBInfo.rightoff - Scr->TitlePadding,
Scr->TitleHeight, Scr->TitleShadowDepth,
tmp_win->title, bs, False, False);
}
tmp_win->hasfocusvisible = focus;
}
static void move_to_head (TwmWindow *t)
{
if (t == NULL) return;
if (Scr->FirstWindow == t) return;
if (t->prev) t->prev->next = t->next;
if (t->next) t->next->prev = t->prev;
t->next = Scr->FirstWindow;
if (Scr->FirstWindow != NULL)
Scr->FirstWindow->prev = t;
t->prev = NULL;
Scr->FirstWindow = t;
}
/*
* SetFocus - separate routine to set focus to make things more understandable
* and easier to debug
*/
void SetFocus (TwmWindow *tmp_win, Time tim)
{
Window w = (tmp_win ? tmp_win->w : PointerRoot);
int f_iconmgr = 0;
if (Scr->Focus && (Scr->Focus->iconmgr)) f_iconmgr = 1;
if (Scr->SloppyFocus && (w == PointerRoot) && (!f_iconmgr)) return;
XSetInputFocus (dpy, w, RevertToPointerRoot, tim);
if (Scr->Focus == tmp_win) return;
if (Scr->Focus) {
if (Scr->Focus->AutoSqueeze && !Scr->Focus->squeezed) {
AutoSqueeze (Scr->Focus);
}
SetFocusVisualAttributes (Scr->Focus, False);
}
if (tmp_win) {
if (tmp_win->AutoSqueeze && tmp_win->squeezed) {
AutoSqueeze (tmp_win);
}
SetFocusVisualAttributes (tmp_win, True);
}
Scr->Focus = tmp_win;
move_to_head (tmp_win);
}
#
#ifdef NOPUTENV
/*
* define our own putenv() if the system doesn't have one.
* putenv(s): place s (a string of the form "NAME=value") in
* the environment; replacing any existing NAME. s is placed in
* environment, so if you change s, the environment changes (like
* putenv on a sun). Binding removed if you putenv something else
* called NAME.
*/
int
putenv(s)
char *s;
{
char *v;
int varlen, idx;
extern char **environ;
char **newenv;
static int virgin = 1; /* true while "environ" is a virgin */
v = strchr(s, '=');
if(v == 0)
return 0; /* punt if it's not of the right form */
varlen = (v + 1) - s;
for (idx = 0; environ[idx] != 0; idx++) {
if (strncmp(environ[idx], s, varlen) == 0) {
if(v[1] != 0) { /* true if there's a value */
environ[idx] = s;
return 0;
} else {
do {
environ[idx] = environ[idx+1];
} while(environ[++idx] != 0);
return 0;
}
}
}
/* add to environment (unless no value; then just return) */
if(v[1] == 0)
return 0;
if(virgin) {
register i;
newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*)));
if(newenv == 0)
return -1;
for(i = idx-1; i >= 0; --i)
newenv[i] = environ[i];
virgin = 0; /* you're not a virgin anymore, sweety */
} else {
newenv = (char **) realloc((char *) environ,
(unsigned) ((idx + 2) * sizeof(char*)));
if (newenv == 0)
return -1;
}
environ = newenv;
environ[idx] = s;
environ[idx+1] = 0;
return 0;
}
#endif /* NOPUTENV */
static Pixmap CreateXLogoPixmap (unsigned int *widthp, unsigned int *heightp)
{
int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (h < 0) h = 0;
*widthp = *heightp = (unsigned int) h;
if (Scr->tbpm.xlogo == None) {
GC gc, gcBack;
Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1);
gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
XSetForeground (dpy, gc, 0);
XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h);
XSetForeground (dpy, gc, 1);
gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
XSetForeground (dpy, gcBack, 0);
/*
* draw the logo large so that it gets as dense as possible; then white
* out the edges so that they look crisp
*/
XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2);
XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1);
/*
* done drawing
*/
XFreeGC (dpy, gc);
XFreeGC (dpy, gcBack);
}
return Scr->tbpm.xlogo;
}
static Pixmap CreateResizePixmap (unsigned int *widthp, unsigned int *heightp)
{
int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (h < 1) h = 1;
*widthp = *heightp = (unsigned int) h;
if (Scr->tbpm.resize == None) {
XPoint points[3];
GC gc;
int w;
int lw;
/*
* create the pixmap
*/
Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1);
gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL);
XSetForeground (dpy, gc, 0);
XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h);
XSetForeground (dpy, gc, 1);
lw = h / 16;
if (lw == 1)
lw = 0;
XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter);
/*
* draw the resize button,
*/
w = (h * 2) / 3;
points[0].x = w;
points[0].y = 0;
points[1].x = w;
points[1].y = w;
points[2].x = 0;
points[2].y = w;
XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
w = w / 2;
points[0].x = w;
points[0].y = 0;
points[1].x = w;
points[1].y = w;
points[2].x = 0;
points[2].y = w;
XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
/*
* done drawing
*/
XFreeGC(dpy, gc);
}
return Scr->tbpm.resize;
}
static Pixmap CreateDotPixmap (unsigned int *widthp, unsigned int *heightp)
{
int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
h = h * 3 / 4;
if (h < 1) h = 1;
if (!(h & 1))
h--;
*widthp = *heightp = (unsigned int) h;
if (Scr->tbpm.delete == None) {
GC gc;
Pixmap pix;
pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1);
gc = XCreateGC (dpy, pix, 0L, NULL);
XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound);
XSetForeground (dpy, gc, 0L);
XFillRectangle (dpy, pix, gc, 0, 0, h, h);
XSetForeground (dpy, gc, 1L);
XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2);
XFreeGC (dpy, gc);
}
return Scr->tbpm.delete;
}
static Image *Create3DCrossImage (ColorPair cp)
{
Image *image;
int h;
int point;
int midpoint;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
point = 4;
midpoint = h/2;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
#ifdef LEVITTE_TEST
FB (cp.shadc, cp.shadd);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point-1, point-1, point+1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point, point, point+1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point+1, midpoint-2, midpoint);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint+2, h-point-3, h-point-1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point+1, h-point-3, h-point-2);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, h-point-2, midpoint-2, midpoint);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint-2, h-point-2, point-1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-2, h-point-2, point);
#endif
FB (cp.shadd, cp.shadc);
#ifdef LEVITTE_TEST
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point+1, h-point-1, h-point-2);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point, midpoint, midpoint-2);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, h-point-2);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, h-point-2, h-point-2, h-point);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, h-point-2, h-point-2, h-point-1);
#else
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point-1, h-point-1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point, h-point-1, h-point);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point-1, h-point, h-point-1);
#endif
#ifdef LEVITTE_TEST
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, point, h-point-1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point, h-point-1, point);
#else
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, h-point-1, point);
#endif
#ifdef LEVITTE_TEST
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point-1, h-point-1, point+1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point, midpoint, midpoint+2);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, point+1);
#else
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, h-point-1, h-point-1, point-1);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point, h-point, point);
#endif
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DIconifyImage (ColorPair cp)
{
Image *image;
int h;
int point;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
point = ((h/2-2) * 2+1) / 3;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
FB (cp.shadd, cp.shadc);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h/2, h-point);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point, point);
FB (cp.shadc, cp.shadd);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, point, h/2+1, h-point);
XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point+1, h/2+1, h-point-1);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DSunkenResizeImage (ColorPair cp)
{
int h;
Image *image;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
Draw3DBorder (image->pixmap, 3, 3, h-6, h-6, 1, cp, on, True, False);
Draw3DBorder (image->pixmap, 3, ((h-6)/3)+3, ((h-6)*2/3)+1,
((h-6)*2/3)+1, 1, cp, on, True, False);
Draw3DBorder (image->pixmap, 3, ((h-6)*2/3)+3, ((h-6)/3)+1,
((h-6)/3)+1, 1, cp, on, True, False);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DBoxImage (ColorPair cp)
{
int h;
Image *image;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (! (h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
Draw3DBorder (image->pixmap, (h / 2) - 4, (h / 2) - 4, 9, 9, 1, cp,
off, True, False);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DDotImage (ColorPair cp)
{
Image *image;
int h;
static int idepth = 2;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
Draw3DBorder (image->pixmap, (h / 2) - idepth,
(h / 2) - idepth,
2 * idepth + 1,
2 * idepth + 1,
idepth, cp, off, True, False);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DBarImage (ColorPair cp)
{
Image *image;
int h;
static int idepth = 2;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
Draw3DBorder (image->pixmap,
Scr->TitleButtonShadowDepth + 2,
(h / 2) - idepth,
h - 2 * (Scr->TitleButtonShadowDepth + 2),
2 * idepth + 1,
idepth, cp, off, True, False);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DVertBarImage (ColorPair cp)
{
Image *image;
int h;
static int idepth = 2;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
Draw3DBorder (image->pixmap,
(h / 2) - idepth,
Scr->TitleButtonShadowDepth + 2,
2 * idepth + 1,
h - 2 * (Scr->TitleButtonShadowDepth + 2),
idepth, cp, off, True, False);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DMenuImage (ColorPair cp)
{
Image *image;
int h, i;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
for (i = 4; i < h - 7; i += 5) {
Draw3DBorder (image->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False);
}
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DResizeImage (ColorPair cp)
{
Image *image;
int h;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
Draw3DBorder (image->pixmap, 0, h / 4, ((3 * h) / 4) + 1, ((3 * h) / 4) + 1, 2,
cp, off, True, False);
Draw3DBorder (image->pixmap, 0, h / 2, (h / 2) + 1, (h / 2) + 1, 2, cp, off, True, False);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
static Image *Create3DZoomImage (ColorPair cp)
{
Image *image;
int h;
static int idepth = 2;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = (Image*) malloc (sizeof (struct _Image));
if (! image) return (None);
image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (image->pixmap == None) return (None);
Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
Draw3DBorder (image->pixmap, Scr->TitleButtonShadowDepth + 2,
Scr->TitleButtonShadowDepth + 2,
h - 2 * (Scr->TitleButtonShadowDepth + 2),
h - 2 * (Scr->TitleButtonShadowDepth + 2),
idepth, cp, off, True, False);
image->mask = None;
image->width = h;
image->height = h;
image->next = None;
return (image);
}
struct Colori {
Pixel color;
Pixmap pix;
struct Colori *next;
};
Pixmap Create3DMenuIcon (unsigned int height,
unsigned int *widthp, unsigned int *heightp,
ColorPair cp)
{
unsigned int h, w;
int i;
struct Colori *col;
static struct Colori *colori = NULL;
h = height;
w = h * 7 / 8;
if (h < 1) h = 1;
if (w < 1) w = 1;
*widthp = w;
*heightp = h;
for (col = colori; col; col = col->next) {
if (col->color == cp.back) break;
}
if (col != NULL) {
return (col->pix);
}
col = (struct Colori*) malloc (sizeof (struct Colori));
col->color = cp.back;
col->pix = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
col->next = colori;
colori = col;
Draw3DBorder (col->pix, 0, 0, w, h, 1, cp, off, True, False);
for (i = 3; i + 5 < h; i += 5) {
Draw3DBorder (col->pix, 4, i, w - 8, 3, 1, Scr->MenuC, off, True, False);
}
return (colori->pix);
}
#include "siconify.bm"
Pixmap Create3DIconManagerIcon (ColorPair cp)
{
unsigned int w, h;
struct Colori *col;
static struct Colori *colori = NULL;
w = (unsigned int) siconify_width;
h = (unsigned int) siconify_height;
for (col = colori; col; col = col->next) {
if (col->color == cp.back) break;
}
if (col != NULL) {
return (col->pix);
}
col = (struct Colori*) malloc (sizeof (struct Colori));
col->color = cp.back;
col->pix = XCreatePixmap (dpy, Scr->Root, w, h, Scr->d_depth);
Draw3DBorder (col->pix, 0, 0, w, h, 4, cp, off, True, False);
col->next = colori;
colori = col;
return (colori->pix);
}
static Image *Create3DResizeAnimation (Bool in, Bool left, Bool top,
ColorPair cp)
{
int h, i, j;
Image *image, *im, *im1;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = im1 = None;
for (i = (in ? 0 : (h/4)-1); (i < h/4) && (i >= 0); i += (in ? 1 : -1)) {
im = (Image*) malloc (sizeof (struct _Image));
if (! im) return (None);
im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (im->pixmap == None) {
free (im);
return (None);
}
Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
for (j = i; j <= h; j += (h/4)){
Draw3DBorder (im->pixmap, (left ? 0 : j), (top ? 0 : j),
h - j, h - j, 2, cp, off, True, False);
}
im->mask = None;
im->width = h;
im->height = h;
im->next = None;
if (image == None) {
image = im1 = im;
}
else {
im1->next = im;
im1 = im;
}
}
if (im1 != None) im1->next = image;
return (image);
}
static Image *Create3DResizeInTopAnimation (ColorPair cp)
{
return Create3DResizeAnimation (TRUE, FALSE, TRUE, cp);
}
static Image *Create3DResizeOutTopAnimation (ColorPair cp)
{
return Create3DResizeAnimation (False, FALSE, TRUE, cp);
}
static Image *Create3DResizeInBotAnimation (ColorPair cp)
{
return Create3DResizeAnimation (TRUE, TRUE, FALSE, cp);
}
static Image *Create3DResizeOutBotAnimation (ColorPair cp)
{
return Create3DResizeAnimation (False, TRUE, FALSE, cp);
}
static Image *Create3DMenuAnimation (Bool up, ColorPair cp)
{
int h, i, j;
Image *image, *im, *im1;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
image = im1 = None;
for (j = (up ? 4 : 0); j != (up ? -1 : 5); j+= (up ? -1 : 1)) {
im = (Image*) malloc (sizeof (struct _Image));
if (! im) return (None);
im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
if (im->pixmap == None) {
free (im);
return (None);
}
Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
for (i = j; i < h - 3; i += 5) {
Draw3DBorder (im->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False);
}
im->mask = None;
im->width = h;
im->height = h;
im->next = None;
if (image == None) {
image = im1 = im;
}
else {
im1->next = im;
im1 = im;
}
}
if (im1 != None) im1->next = image;
return (image);
}
static Image *Create3DMenuUpAnimation (ColorPair cp)
{
return Create3DMenuAnimation (TRUE, cp);
}
static Image *Create3DMenuDownAnimation (ColorPair cp)
{
return Create3DMenuAnimation (False, cp);
}
static Image *Create3DZoomAnimation (Bool in, Bool out, int n, ColorPair cp)
{
int h, i, j, k;
Image *image, *im, *im1;
h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
if (!(h & 1)) h--;
if (n == 0) n = (h/2) - 2;
image = im1 = None;
for (j = (out ? -1 : 1) ; j < (in ? 2 : 0); j += 2){
for(k = (j > 0 ? 0 : n-1) ; (k >= 0) && (k < n); k += j){
im = (Image*) malloc (sizeof (struct _Image));
im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth);
Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False);
for (i = 2 + k; i < (h / 2); i += n) {
Draw3DBorder (im->pixmap, i, i, h - (2 * i), h - (2 * i), 2, cp, off, True, False);
}
im->mask = None;
im->width = h;
im->height = h;
im->next = None;
if (image == None) {
image = im1 = im;
}
else {
im1->next = im;
im1 = im;
}
}
}
if (im1 != None) im1->next = image;
return (image);
}
static Image *Create3DMazeInAnimation (ColorPair cp)
{
return Create3DZoomAnimation(TRUE, FALSE, 6, cp);
}
static Image *Create3DMazeOutAnimation (ColorPair cp)
{
return Create3DZoomAnimation(FALSE, TRUE, 6, cp);
}
static Image *Create3DZoomInAnimation (ColorPair cp)
{
return Create3DZoomAnimation(TRUE, FALSE, 0, cp);
}
static Image *Create3DZoomOutAnimation (ColorPair cp)
{
return Create3DZoomAnimation(FALSE, TRUE, 0, cp);
}
static Image *Create3DZoomInOutAnimation (ColorPair cp)
{
return Create3DZoomAnimation(TRUE, TRUE, 0, cp);
}
#define questionmark_width 8
#define questionmark_height 8
static char questionmark_bits[] = {
0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18};
static Pixmap CreateQuestionPixmap (unsigned int *widthp,
unsigned int *heightp)
{
*widthp = questionmark_width;
*heightp = questionmark_height;
if (Scr->tbpm.question == None) {
Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root,
questionmark_bits,
questionmark_width,
questionmark_height);
}
/*
* this must succeed or else we are in deep trouble elsewhere
*/
return Scr->tbpm.question;
}
static Pixmap CreateMenuPixmap (unsigned int *widthp, unsigned int *heightp)
{
return (CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2,widthp,heightp));
}
Pixmap CreateMenuIcon (int height, unsigned int *widthp, unsigned int *heightp)
{
int h, w;
int ih, iw;
int ix, iy;
int mh, mw;
int tw, th;
int lw, lh;
int lx, ly;
int lines, dly;
int offset;
int bw;
h = height;
w = h * 7 / 8;
if (h < 1)
h = 1;
if (w < 1)
w = 1;
*widthp = w;
*heightp = h;
if (Scr->tbpm.menu == None) {
Pixmap pix;
GC gc;
pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1);
gc = XCreateGC (dpy, pix, 0L, NULL);
XSetForeground (dpy, gc, 0L);
XFillRectangle (dpy, pix, gc, 0, 0, w, h);
XSetForeground (dpy, gc, 1L);
ix = 1;
iy = 1;
ih = h - iy * 2;
iw = w - ix * 2;
offset = ih / 8;
mh = ih - offset;
mw = iw - offset;
bw = mh / 16;
if (bw == 0 && mw > 2)
bw = 1;
tw = mw - bw * 2;
th = mh - bw * 2;
XFillRectangle (dpy, pix, gc, ix, iy, mw, mh);
XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh);
XSetForeground (dpy, gc, 0L);
XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th);
XSetForeground (dpy, gc, 1L);
lw = tw / 2;
if ((tw & 1) ^ (lw & 1))
lw++;
lx = ix + bw + (tw - lw) / 2;
lh = th / 2 - bw;
if ((lh & 1) ^ ((th - bw) & 1))
lh++;
ly = iy + bw + (th - bw - lh) / 2;
lines = 3;
if ((lh & 1) && lh < 6)
{
lines--;
}
dly = lh / (lines - 1);
while (lines--)
{
XFillRectangle (dpy, pix, gc, lx, ly, lw, bw);
ly += dly;
}
XFreeGC (dpy, gc);
}
return Scr->tbpm.menu;
}
#define FBGC(gc, fix_fore, fix_back)\
Gcv.foreground = fix_fore;\
Gcv.background = fix_back;\
XChangeGC(dpy, gc, GCForeground|GCBackground,&Gcv)
void Draw3DBorder (Window w, int x, int y, int width, int height, int bw,
ColorPair cp, int state, int fill, int forcebw)
{
int i;
XGCValues gcv;
unsigned long gcm;
if ((width < 1) || (height < 1)) return;
if (Scr->Monochrome != COLOR) {
if (fill) {
gcm = GCFillStyle;
gcv.fill_style = FillOpaqueStippled;
XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height);
}
gcm = 0;
gcm |= GCLineStyle;
gcv.line_style = (state == on) ? LineSolid : LineDoubleDash;
gcm |= GCFillStyle;
gcv.fill_style = FillSolid;
XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
for (i = 0; i < bw; i++) {
XDrawLine (dpy, w, Scr->BorderGC, x, y + i,
x + width - i - 1, y + i);
XDrawLine (dpy, w, Scr->BorderGC, x + i, y,
x + i, y + height - i - 1);
}
gcm = 0;
gcm |= GCLineStyle;
gcv.line_style = (state == on) ? LineDoubleDash : LineSolid;
gcm |= GCFillStyle;
gcv.fill_style = FillSolid;
XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
for (i = 0; i < bw; i++) {
XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i,
x + width - i - 1, y + height - 1);
XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1,
x + width - 1, y + height - i - 1);
}
return;
}
if (fill) {
FBGC (Scr->BorderGC, cp.back, cp.fore);
XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height);
}
if (Scr->BeNiceToColormap) {
int dashoffset = 0;
gcm = 0;
gcm |= GCLineStyle;
gcv.line_style = (forcebw) ? LineSolid : LineDoubleDash;
gcm |= GCBackground;
gcv.background = cp.back;
XChangeGC (dpy, Scr->BorderGC, gcm, &gcv);
if (state == on)
XSetForeground (dpy, Scr->BorderGC, Scr->Black);
else
XSetForeground (dpy, Scr->BorderGC, Scr->White);
for (i = 0; i < bw; i++) {
XDrawLine (dpy, w, Scr->BorderGC, x + i, y + dashoffset,
x + i, y + height - i - 1);
XDrawLine (dpy, w, Scr->BorderGC, x + dashoffset, y + i,
x + width - i - 1, y + i);
dashoffset = 1 - dashoffset;
}
XSetForeground (dpy, Scr->BorderGC, ((state == on) ? Scr->White : Scr->Black));
for (i = 0; i < bw; i++) {
XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1,
x + width - 1, y + height - i - 1);
XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i,
x + width - i - 1, y + height - 1);
}
return;
}
if (state == on) { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); }
else { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); }
for (i = 0; i < bw; i++) {
XDrawLine (dpy, w, Scr->BorderGC, x, y + i,
x + width - i - 1, y + i);
XDrawLine (dpy, w, Scr->BorderGC, x + i, y,
x + i, y + height - i - 1);
}
if (state == on) { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); }
else { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); }
for (i = 0; i < bw; i++) {
XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i,
x + width - i - 1, y + height - 1);
XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1,
x + width - 1, y + height - i - 1);
}
return;
}
void Draw3DCorner (Window w,
int x, int y, int width, int height, int thick, int bw,
ColorPair cp, int type)
{
XRectangle rects [2];
switch (type) {
case 0 :
Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
Draw3DBorder (w, x + thick - bw, y + thick - bw,
width - thick + 2 * bw, height - thick + 2 * bw,
bw, cp, on, True, False);
break;
case 1 :
Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
Draw3DBorder (w, x, y + thick - bw,
width - thick + bw, height - thick,
bw, cp, on, True, False);
break;
case 2 :
rects [0].x = x + width - thick;
rects [0].y = y;
rects [0].width = thick;
rects [0].height = height;
rects [1].x = x;
rects [1].y = y + width - thick;
rects [1].width = width - thick;
rects [1].height = thick;
XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted);
Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
Draw3DBorder (w, x, y,
width - thick + bw, height - thick + bw,
bw, cp, on, True, False);
XSetClipMask (dpy, Scr->BorderGC, None);
break;
case 3 :
rects [0].x = x;
rects [0].y = y;
rects [0].width = thick;
rects [0].height = height;
rects [1].x = x + thick;
rects [1].y = y + height - thick;
rects [1].width = width - thick;
rects [1].height = thick;
XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted);
Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
Draw3DBorder (w, x + thick - bw, y,
width - thick, height - thick + bw,
bw, cp, on, True, False);
XSetClipMask (dpy, Scr->BorderGC, None);
break;
}
return;
}
void PaintAllDecoration (void)
{
TwmWindow *tmp_win;
virtualScreen *vs;
for (tmp_win = Scr->FirstWindow; tmp_win != NULL; tmp_win = tmp_win->next) {
if (! visible (tmp_win)) continue;
if (tmp_win->mapped == TRUE) {
if (tmp_win->frame_bw3D) {
if (tmp_win->highlight && tmp_win == Scr->Focus)
PaintBorders (tmp_win, True);
else
PaintBorders (tmp_win, False);
}
if (tmp_win->title_w) PaintTitle (tmp_win);
if (tmp_win->titlebuttons) PaintTitleButtons (tmp_win);
}
else
if ((tmp_win->icon_on == TRUE) &&
!tmp_win->icon_not_ours &&
!Scr->NoIconTitlebar &&
tmp_win->icon &&
tmp_win->icon->w &&
! LookInList (Scr->NoIconTitle, tmp_win->full_name, &tmp_win->class)) {
PaintIcon (tmp_win);
}
}
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
PaintWorkSpaceManager (vs);
}
}
void PaintBorders (TwmWindow *tmp_win, Bool focus)
{
ColorPair cp;
cp = (focus && tmp_win->highlight) ? tmp_win->borderC : tmp_win->border_tile;
if (tmp_win->title_height == 0) {
Draw3DBorder (tmp_win->frame,
0,
0,
tmp_win->frame_width,
tmp_win->frame_height,
Scr->BorderShadowDepth, cp, off, True, False);
Draw3DBorder (tmp_win->frame,
tmp_win->frame_bw3D - Scr->BorderShadowDepth,
tmp_win->frame_bw3D - Scr->BorderShadowDepth,
tmp_win->frame_width - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth,
tmp_win->frame_height - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth,
Scr->BorderShadowDepth, cp, on, True, False);
return;
}
Draw3DCorner (tmp_win->frame,
tmp_win->title_x - tmp_win->frame_bw3D,
0,
Scr->TitleHeight + tmp_win->frame_bw3D,
Scr->TitleHeight + tmp_win->frame_bw3D,
tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 0);
Draw3DCorner (tmp_win->frame,
tmp_win->title_x + tmp_win->title_width - Scr->TitleHeight,
0,
Scr->TitleHeight + tmp_win->frame_bw3D,
Scr->TitleHeight + tmp_win->frame_bw3D,
tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 1);
Draw3DCorner (tmp_win->frame,
tmp_win->frame_width - (Scr->TitleHeight + tmp_win->frame_bw3D),
tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D),
Scr->TitleHeight + tmp_win->frame_bw3D,
Scr->TitleHeight + tmp_win->frame_bw3D,
tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 2);
Draw3DCorner (tmp_win->frame,
0,
tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D),
Scr->TitleHeight + tmp_win->frame_bw3D,
Scr->TitleHeight + tmp_win->frame_bw3D,
tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 3);
Draw3DBorder (tmp_win->frame,
tmp_win->title_x + Scr->TitleHeight,
0,
tmp_win->title_width - 2 * Scr->TitleHeight,
tmp_win->frame_bw3D,
Scr->BorderShadowDepth, cp, off, True, False);
Draw3DBorder (tmp_win->frame,
tmp_win->frame_bw3D + Scr->TitleHeight,
tmp_win->frame_height - tmp_win->frame_bw3D,
tmp_win->frame_width - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D),
tmp_win->frame_bw3D,
Scr->BorderShadowDepth, cp, off, True, False);
Draw3DBorder (tmp_win->frame,
0,
Scr->TitleHeight + tmp_win->frame_bw3D,
tmp_win->frame_bw3D,
tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D),
Scr->BorderShadowDepth, cp, off, True, False);
Draw3DBorder (tmp_win->frame,
tmp_win->frame_width - tmp_win->frame_bw3D,
Scr->TitleHeight + tmp_win->frame_bw3D,
tmp_win->frame_bw3D,
tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D),
Scr->BorderShadowDepth, cp, off, True, False);
if (tmp_win->squeeze_info && !tmp_win->squeezed) {
Draw3DBorder (tmp_win->frame,
0,
Scr->TitleHeight,
tmp_win->title_x,
tmp_win->frame_bw3D,
Scr->BorderShadowDepth, cp, off, True, False);
Draw3DBorder (tmp_win->frame,
tmp_win->title_x + tmp_win->title_width,
Scr->TitleHeight,
tmp_win->frame_width - tmp_win->title_x - tmp_win->title_width,
tmp_win->frame_bw3D,
Scr->BorderShadowDepth, cp, off, True, False);
}
}
void PaintTitle (TwmWindow *tmp_win)
{
int width, mwidth, len;
XRectangle inc_rect;
XRectangle logical_rect;
if (Scr->use3Dtitles) {
if (Scr->SunkFocusWindowTitle && (Scr->Focus == tmp_win) &&
(tmp_win->title_height != 0))
Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0,
tmp_win->title_width - Scr->TBInfo.titlex -
Scr->TBInfo.rightoff - Scr->TitlePadding,
Scr->TitleHeight, Scr->TitleShadowDepth,
tmp_win->title, on, True, False);
else
Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0,
tmp_win->title_width - Scr->TBInfo.titlex -
Scr->TBInfo.rightoff - Scr->TitlePadding,
Scr->TitleHeight, Scr->TitleShadowDepth,
tmp_win->title, off, True, False);
}
FB(tmp_win->title.fore, tmp_win->title.back);
if (Scr->use3Dtitles) {
len = strlen(tmp_win->name);
XmbTextExtents(Scr->TitleBarFont.font_set,
tmp_win->name, strlen (tmp_win->name),
&inc_rect, &logical_rect);
width = logical_rect.width;
mwidth = tmp_win->title_width - Scr->TBInfo.titlex -
Scr->TBInfo.rightoff - Scr->TitlePadding -
Scr->TitleShadowDepth - 4;
while ((len > 0) && (width > mwidth)) {
len--;
XmbTextExtents(Scr->TitleBarFont.font_set,
tmp_win->name, len,
&inc_rect, &logical_rect);
width = logical_rect.width;
}
if (Scr->Monochrome != COLOR) {
XmbDrawImageString(dpy, tmp_win->title_w, Scr->TitleBarFont.font_set,
Scr->NormalGC,
tmp_win->name_x,
Scr->TitleBarFont.y + Scr->TitleShadowDepth,
tmp_win->name, len);
}
else {
XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set,
Scr->NormalGC, tmp_win->name_x,
Scr->TitleBarFont.y + Scr->TitleShadowDepth,
tmp_win->name, len);
}
}
else
XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set,
Scr->NormalGC,
tmp_win->name_x, Scr->TitleBarFont.y,
tmp_win->name, strlen(tmp_win->name));
}
void PaintIcon (TwmWindow *tmp_win)
{
int width, twidth, mwidth, len, x;
Icon *icon;
XRectangle inc_rect;
XRectangle logical_rect;
if (!tmp_win || !tmp_win->icon) return;
icon = tmp_win->icon;
if (!icon->has_title) return;
x = 0;
width = icon->w_width;
if (Scr->ShrinkIconTitles && icon->title_shrunk) {
x = GetIconOffset (icon);
width = icon->width;
}
len = strlen (tmp_win->icon_name);
XmbTextExtents(Scr->IconFont.font_set,
tmp_win->icon_name, len,
&inc_rect, &logical_rect);
twidth = logical_rect.width;
mwidth = width - 2 * Scr->IconManagerShadowDepth - 6;
if (Scr->use3Diconmanagers) {
Draw3DBorder (icon->w, x, icon->height, width,
Scr->IconFont.height + 2 * Scr->IconManagerShadowDepth + 6,
Scr->IconManagerShadowDepth, icon->iconc, off, False, False);
}
while ((len > 0) && (twidth > mwidth)) {
len--;
XmbTextExtents(Scr->IconFont.font_set,
tmp_win->icon_name, len,
&inc_rect, &logical_rect);
twidth = logical_rect.width;
}
FB (icon->iconc.fore, icon->iconc.back);
XmbDrawString(dpy, icon->w, Scr->IconFont.font_set, Scr->NormalGC,
x + ((mwidth - twidth)/2) + Scr->IconManagerShadowDepth + 3,
icon->y, tmp_win->icon_name, len);
}
void PaintTitleButton (TwmWindow *tmp_win, TBWindow *tbw)
{
TitleButton *tb = tbw->info;
XCopyArea (dpy, tbw->image->pixmap, tbw->window, Scr->NormalGC,
tb->srcx, tb->srcy, tb->width, tb->height,
tb->dstx, tb->dsty);
return;
}
void PaintTitleButtons (TwmWindow *tmp_win)
{
int i;
TBWindow *tbw = tmp_win->titlebuttons;
int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
if (tbw == NULL)
return;
for (i = 0; i < nb; i++, tbw++) {
PaintTitleButton (tmp_win, tbw);
}
}
void adoptWindow (void)
{
unsigned long data [2];
Window localroot, w;
unsigned char *prop;
unsigned long bytesafter;
unsigned long len;
Atom actual_type;
int actual_format;
XEvent event;
Window root, parent, child, *children;
unsigned int nchildren, key_buttons;
int root_x, root_y, win_x, win_y;
int ret;
localroot = w = RootWindow (dpy, Scr->screen);
XGrabPointer (dpy, localroot, False,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
None, Scr->SelectCursor, CurrentTime);
XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event);
child = event.xbutton.subwindow;
while (1) {
if (child == (Window) 0) break;
w = XmuClientWindow (dpy, child);
ret = XGetWindowProperty (dpy, w, _XA_WM_WORKSPACESLIST, 0L, 512,
False, XA_STRING, &actual_type, &actual_format, &len,
&bytesafter, &prop);
XFree ((char *)prop); /* Don't ever do anything with it */
if (ret != Success)
break;
if (len == 0) /* it is not a local root window */
break; /* it is not a local root window */
localroot = w;
XQueryPointer (dpy, localroot, &root, &child, &root_x, &root_y,
&win_x, &win_y, &key_buttons);
}
XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event);
XUngrabPointer (dpy, CurrentTime);
if (localroot == Scr->Root) return;
if (w == localroot) { /* try to not adopt an ancestor */
XQueryTree (dpy, Scr->Root, &root, &parent, &children, &nchildren);
while (parent != (Window) 0) {
XFree ((char *) children);
if (w == parent) return;
XQueryTree (dpy, parent, &root, &parent, &children, &nchildren);
}
XFree ((char *) children);
if (w == root) return;
}
if (localroot == RootWindow (dpy, Scr->screen)) {
XWithdrawWindow (dpy, w, Scr->screen);
}
else {
XUnmapWindow (dpy, w);
}
XReparentWindow (dpy, w, Scr->Root, 0, 0);
data [0] = (unsigned long) NormalState;
data [1] = (unsigned long) None;
XChangeProperty (dpy, w, _XA_WM_STATE, _XA_WM_STATE, 32,
PropModeReplace, (unsigned char *) data, 2);
XFlush (dpy);
SimulateMapRequest (w);
return;
}
void DebugTrace (char *file)
{
if (!file) return;
if (tracefile) {
fprintf (stderr, "stop logging events\n");
if (tracefile != stderr) fclose (tracefile);
tracefile = NULL;
}
else {
if (strcmp (file, "stderr"))
tracefile = fopen (file, "w");
else
tracefile = stderr;
fprintf (stderr, "logging events to : %s\n", file);
}
}
extern Cursor TopRightCursor, TopLeftCursor, BottomRightCursor, BottomLeftCursor,
LeftCursor, RightCursor, TopCursor, BottomCursor;
void SetBorderCursor (TwmWindow *tmp_win, int x, int y)
{
Cursor cursor;
XSetWindowAttributes attr;
int h, fw, fh, wd;
if (!tmp_win)
return;
/* Use the max of these, but since one is always 0 we can add them. */
wd = tmp_win->frame_bw + tmp_win->frame_bw3D;
h = Scr->TitleHeight + wd;
fw = tmp_win->frame_width;
fh = tmp_win->frame_height;
#if defined DEBUG && DEBUG
fprintf(stderr, "wd=%d h=%d, fw=%d fh=%d x=%d y=%d\n",
wd, h, fw, fh, x, y);
#endif
/*
* If not using 3D borders:
*
* The left border has negative x coordinates,
* The top border (above the title) has negative y coordinates.
* The title is TitleHeight high, the next wd pixels are border.
* The bottom border has coordinates >= the frame height.
* The right border has coordinates >= the frame width.
*
* If using 3D borders: all coordinates are >= 0, and all coordinates
* are higher by the border width.
*
* Since we only get events when we're actually in the border, we simply
* allow for both cases at the same time.
*/
if ((x < -wd) || (y < -wd)) {
cursor = Scr->FrameCursor;
} else if (x < h) {
if (y < h)
cursor = TopLeftCursor;
else if (y >= fh - h)
cursor = BottomLeftCursor;
else
cursor = LeftCursor;
} else if (x >= fw - h) {
if (y < h)
cursor = TopRightCursor;
else if (y >= fh - h)
cursor = BottomRightCursor;
else
cursor = RightCursor;
} else if (y < h) { /* also include title bar in top border area */
cursor = TopCursor;
} else if (y >= fh - h) {
cursor = BottomCursor;
} else {
cursor = Scr->FrameCursor;
}
attr.cursor = cursor;
XChangeWindowAttributes (dpy, tmp_win->frame, CWCursor, &attr);
tmp_win->curcurs = cursor;
}
Image *GetImage (char *name, ColorPair cp)
{
name_list **list;
char fullname [256];
Image *image;
if (name == NULL) return (None);
image = None;
list = &Scr->ImageCache;
#ifdef XPM
if ((name [0] == '@') || (strncmp (name, "xpm:", 4) == 0)) {
sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
int startn = (name [0] == '@') ? 1 : 4;
if ((image = GetXpmImage (name + startn, cp)) != None) {
AddToList (list, fullname, (char*) image);
}
}
}
else
#endif
#ifdef JPEG
if (strncmp (name, "jpeg:", 5) == 0) {
if ((image = (Image*) LookInNameList (*list, name)) == None) {
if ((image = GetJpegImage (&name [5])) != None) {
AddToList (list, name, (char*) image);
}
}
}
else
#endif
#ifdef IMCONV
if (strncmp (name, "im:", 3) == 0) {
if ((image = (Image*) LookInNameList (*list, name)) == None) {
if ((image = GetImconvImage (&name [3])) != None) {
AddToList (list, name, (char*) image);
}
}
}
else
#endif
#if !defined(VMS) || defined(HAVE_XWDFILE_H)
if ((strncmp (name, "xwd:", 4) == 0) || (name [0] == '|')) {
int startn = (name [0] == '|') ? 0 : 4;
if ((image = (Image*) LookInNameList (*list, name)) == None) {
if ((image = GetXwdImage (&name [startn], cp)) != None) {
AddToList (list, name, (char*) image);
}
}
}
else
#endif
if (strncmp (name, ":xpm:", 5) == 0) {
int i;
static struct {
char *name;
Image* (*proc)(ColorPair colorpair);
} pmtab[] = {
{ TBPM_3DDOT, Create3DDotImage },
{ TBPM_3DRESIZE, Create3DResizeImage },
{ TBPM_3DMENU, Create3DMenuImage },
{ TBPM_3DZOOM, Create3DZoomImage },
{ TBPM_3DBAR, Create3DBarImage },
{ TBPM_3DVBAR, Create3DVertBarImage },
{ TBPM_3DCROSS, Create3DCrossImage },
{ TBPM_3DICONIFY, Create3DIconifyImage },
{ TBPM_3DSUNKEN_RESIZE, Create3DSunkenResizeImage },
{ TBPM_3DBOX, Create3DBoxImage }
};
sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) {
image = (*pmtab[i].proc) (cp);
if (image == None) {
fprintf (stderr,
"%s: unable to build pixmap \"%s\"\n", ProgramName, name);
return (None);
}
break;
}
}
if (image == None) {
fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name);
return (None);
}
AddToList (list, fullname, (char*) image);
}
}
else
if (strncmp (name, "%xpm:", 5) == 0) {
int i;
static struct {
char *name;
Image* (*proc)(ColorPair colorpair);
} pmtab[] = {
{ "%xpm:menu-up", Create3DMenuUpAnimation },
{ "%xpm:menu-down", Create3DMenuDownAnimation },
{ "%xpm:resize", Create3DZoomOutAnimation }, /* compatibility */
{ "%xpm:resize-out-top", Create3DResizeInTopAnimation },
{ "%xpm:resize-in-top", Create3DResizeOutTopAnimation },
{ "%xpm:resize-out-bot", Create3DResizeInBotAnimation },
{ "%xpm:resize-in-bot", Create3DResizeOutBotAnimation },
{ "%xpm:maze-out", Create3DMazeOutAnimation },
{ "%xpm:maze-in", Create3DMazeInAnimation },
{ "%xpm:zoom-out", Create3DZoomOutAnimation },
{ "%xpm:zoom-in", Create3DZoomInAnimation },
{ "%xpm:zoom-inout", Create3DZoomInOutAnimation }
};
sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) {
image = (*pmtab[i].proc) (cp);
if (image == None) {
fprintf (stderr,
"%s: unable to build pixmap \"%s\"\n", ProgramName, name);
return (None);
}
break;
}
}
if (image == None) {
fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name);
return (None);
}
AddToList (list, fullname, (char*) image);
}
}
else
if (name [0] == ':') {
int i;
unsigned int width, height;
Pixmap pm = 0;
XGCValues gcvalues;
static struct {
char *name;
Pixmap (*proc)(unsigned int *widthp, unsigned int *heightp);
} pmtab[] = {
{ TBPM_DOT, CreateDotPixmap },
{ TBPM_ICONIFY, CreateDotPixmap },
{ TBPM_RESIZE, CreateResizePixmap },
{ TBPM_XLOGO, CreateXLogoPixmap },
{ TBPM_DELETE, CreateXLogoPixmap },
{ TBPM_MENU, CreateMenuPixmap },
{ TBPM_QUESTION, CreateQuestionPixmap },
};
sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) {
pm = (*pmtab[i].proc) (&width, &height);
if (pm == None) {
fprintf (stderr,
"%s: unable to build pixmap \"%s\"\n", ProgramName, name);
return (None);
}
break;
}
}
if (pm == None) {
fprintf (stderr, "%s: no such built-in bitmap \"%s\"\n", ProgramName, name);
return (None);
}
image = (Image*) malloc (sizeof (struct _Image));
image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth);
if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues);
gcvalues.background = cp.back;
gcvalues.foreground = cp.fore;
XChangeGC (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues);
XCopyPlane (dpy, pm, image->pixmap, Scr->rootGC, 0, 0, width, height, 0, 0,
(unsigned long) 1);
image->mask = None;
image->width = width;
image->height = height;
image->next = None;
AddToList (list, fullname, (char*) image);
}
}
else {
sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
if ((image = GetBitmapImage (name, cp)) != None) {
AddToList (list, fullname, (char*) image);
}
}
}
return (image);
}
void FreeImage (Image *image)
{
Image *im, *im2;
im = image;
while (im != None) {
if (im->pixmap) XFreePixmap (dpy, im->pixmap);
if (im->mask) XFreePixmap (dpy, im->mask);
im2 = im->next;
free (im);
im = im2;
}
}
#if !defined(VMS) || defined(HAVE_XWDFILE_H)
static void compress (XImage *image, XColor *colors, int *ncolors);
static Image *LoadXwdImage (char *filename, ColorPair cp)
{
FILE *file;
char *fullname;
XColor colors [256];
XWDColor xwdcolors [256];
unsigned buffer_size;
XImage *image;
unsigned char *imagedata;
Pixmap pixret;
Visual *visual;
char win_name [256];
int win_name_size;
int ispipe;
int i, len;
int w, h, depth, ncolors;
int scrn;
Colormap cmap;
Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
GC gc;
XGCValues gcvalues;
XWDFileHeader header;
Image *ret;
Bool anim;
unsigned long swaptest = 1;
ispipe = 0;
anim = False;
#ifndef VMS
if (filename [0] == '|') {
file = (FILE*) popen (filename + 1, "r");
if (file == NULL) return (None);
ispipe = 1;
anim = AnimationActive;
if (anim) StopAnimation ();
goto file_opened;
}
#endif
fullname = ExpandPixmapPath (filename);
if (! fullname) return (None);
file = fopen (fullname, "r");
free (fullname);
if (file == NULL) {
if (reportfilenotfound) fprintf (stderr, "unable to locate %s\n", filename);
return (None);
}
file_opened:
len = fread ((char *) &header, sizeof (header), 1, file);
if (len != 1) {
fprintf (stderr, "ctwm: cannot read %s\n", filename);
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (None);
}
if (*(char *) &swaptest) _swaplong ((char *) &header, sizeof (header));
if (header.file_version != XWD_FILE_VERSION) {
fprintf(stderr,"ctwm: XWD file format version mismatch : %s\n", filename);
return (None);
}
win_name_size = header.header_size - sizeof (header);
len = fread (win_name, win_name_size, 1, file);
if (len != 1) {
fprintf (stderr, "file %s has not the correct format\n", filename);
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (None);
}
if (header.pixmap_format == XYPixmap) {
fprintf (stderr,"ctwm: XYPixmap XWD file not supported : %s\n", filename);
return (None);
}
w = header.pixmap_width;
h = header.pixmap_height;
depth = header.pixmap_depth;
ncolors = header.ncolors;
len = fread ((char *) xwdcolors, sizeof (XWDColor), ncolors, file);
if (len != ncolors) {
fprintf (stderr, "file %s has not the correct format\n", filename);
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (None);
}
if (*(char *) &swaptest) {
for (i = 0; i < ncolors; i++) {
_swaplong ((char *) &xwdcolors [i].pixel, 4);
_swapshort ((char *) &xwdcolors [i].red, 3 * 2);
}
}
for (i = 0; i < ncolors; i++) {
colors [i].pixel = xwdcolors [i].pixel;
colors [i].red = xwdcolors [i].red;
colors [i].green = xwdcolors [i].green;
colors [i].blue = xwdcolors [i].blue;
colors [i].flags = xwdcolors [i].flags;
colors [i].pad = xwdcolors [i].pad;
}
scrn = Scr->screen;
cmap = AlternateCmap ? AlternateCmap : stdcmap;
visual = Scr->d_visual;
gc = DefaultGC (dpy, scrn);
buffer_size = header.bytes_per_line * h;
imagedata = (unsigned char*) malloc (buffer_size);
if (! imagedata) {
fprintf (stderr, "cannot allocate memory for image %s\n", filename);
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (None);
}
len = fread (imagedata, (int) buffer_size, 1, file);
if (len != 1) {
free (imagedata);
fprintf (stderr, "file %s has not the correct format\n", filename);
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (None);
}
#ifndef VMS
if (ispipe)
pclose (file);
else
#endif
fclose (file);
image = XCreateImage (dpy, visual, depth, header.pixmap_format,
0, (char*) imagedata, w, h,
header.bitmap_pad, header.bytes_per_line);
if (image == None) {
free (imagedata);
fprintf (stderr, "cannot create image for %s\n", filename);
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (None);
}
if (header.pixmap_format == ZPixmap) {
compress (image, colors, &ncolors);
}
if (header.pixmap_format != XYBitmap) {
for (i = 0; i < ncolors; i++) {
XAllocColor (dpy, cmap, &(colors [i]));
}
for (i = 0; i < buffer_size; i++) {
imagedata [i] = (unsigned char) colors [imagedata [i]].pixel;
}
}
if (w > Scr->rootw) w = Scr->rootw;
if (h > Scr->rooth) h = Scr->rooth;
ret = (Image*) malloc (sizeof (struct _Image));
if (! ret) {
fprintf (stderr, "unable to allocate memory for image : %s\n", filename);
free (image);
free (imagedata);
for (i = 0; i < ncolors; i++) {
XFreeColors (dpy, cmap, &(colors [i].pixel), 1, 0L);
}
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (None);
}
if (header.pixmap_format == XYBitmap) {
gcvalues.foreground = cp.fore;
gcvalues.background = cp.back;
XChangeGC (dpy, gc, GCForeground | GCBackground, &gcvalues);
}
if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) {
int x, y;
pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw,
Scr->rooth, Scr->d_depth);
x = (Scr->rootw - w) / 2;
y = (Scr->rooth - h) / 2;
XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth);
XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h);
ret->width = Scr->rootw;
ret->height = Scr->rooth;
}
else {
pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth);
XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h);
ret->width = w;
ret->height = h;
}
XDestroyImage (image);
ret->pixmap = pixret;
ret->mask = None;
ret->next = None;
#ifdef USE_SIGNALS
if (ispipe && anim) StartAnimation ();
#endif
return (ret);
}
static Image *GetXwdImage (char *name, ColorPair cp)
{
Image *image, *r, *s;
char path [128];
char pref [128], *perc;
int i;
if (! strchr (name, '%')) return (LoadXwdImage (name, cp));
s = image = None;
strcpy (pref, name);
perc = strchr (pref, '%');
*perc = '\0';
reportfilenotfound = 0;
for (i = 1;; i++) {
sprintf (path, "%s%d%s", pref, i, perc + 1);
r = LoadXwdImage (path, cp);
if (r == None) break;
r->next = None;
if (image == None) s = image = r;
else {
s->next = r;
s = r;
}
}
reportfilenotfound = 1;
if (s != None) s->next = image;
if (image == None) {
fprintf (stderr, "Cannot open any %s xwd file\n", name);
}
return (image);
}
static void compress (XImage *image, XColor *colors, int *ncolors)
{
unsigned char ind [256];
unsigned int used [256];
int i, j, size, nused;
unsigned char color;
XColor newcolors [256];
unsigned char *imagedata;
for (i = 0; i < 256; i++) {
used [i] = 0;
ind [i] = 0;
}
nused = 0;
size = image->bytes_per_line * image->height;
imagedata = (unsigned char *) image->data;
for (i = 0; i < size; i++) {
if ((i % image->bytes_per_line) > image->width) continue;
color = imagedata [i];
if (used [color] == 0) {
for (j = 0; j < nused; j++) {
if ((colors [color].red == newcolors [j].red) &&
(colors [color].green == newcolors [j].green) &&
(colors [color].blue == newcolors [j].blue)) break;
}
ind [color] = j;
used [color] = 1;
if (j == nused) {
newcolors [j].red = colors [color].red;
newcolors [j].green = colors [color].green;
newcolors [j].blue = colors [color].blue;
nused++;
}
}
}
for (i = 0; i < size; i++) {
imagedata [i] = ind [imagedata [i]];
}
for (i = 0; i < nused; i++) {
colors [i] = newcolors [i];
}
*ncolors = nused;
}
#endif
#ifdef IMCONV
static void free_images ();
static Image *GetImconvImage (char *filename,
unsigned int *widthp, unsigned int *heightp)
{
TagTable *toolInTable;
ImVfb *sourceVfb;
ImVfbPtr vptr;
ImClt *clt;
int i, j, ij, k, retval;
XColor colors [256];
unsigned buffer_size;
XImage *image;
unsigned char *imagedata;
Pixmap pixret;
Visual *visual;
int w, h, depth, ncolors;
int scrn;
Colormap cmap;
Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
GC gc;
unsigned char red, green, blue;
int icol;
char *fullname;
TagEntry *dataEntry;
FILE *fp;
char the_format[1024];
char *tmp_format;
Image *ret;
if (*filename == NULL) return (None);
fullname = ExpandPixmapPath (filename);
if (! fullname) return (None);
fp = fopen (fullname, "r");
if (!fp) {
if (reportfilenotfound) fprintf (stderr, "Cannot open the image %s\n", filename);
free (fullname);
return (None);
}
if ((toolInTable = TagTableAlloc ()) == TAGTABLENULL ) {
fprintf (stderr, "TagTableAlloc failed\n");
free_images (toolInTable);
free (fullname);
return (None);
}
if ((tmp_format = ImFileQFFormat (fp, fullname)) == NULL) {
fprintf (stderr, "Cannot determine image type of %s\n", filename);
free_images (toolInTable);
free (fullname);
return (None);
}
strcpy (the_format, tmp_format);
retval = ImFileFRead (fp, the_format, NULL, toolInTable);
if(retval < 0) {
fprintf(stderr, "Cannot read image file %s: ", fullname);
switch(ImErrNo) {
case IMESYS:
fprintf (stderr, "System call error\n");
break;
case IMEMALLOC:
fprintf (stderr, "Cannot allocate memory\n");
break;
case IMEFORMAT:
fprintf (stderr, "Data in file is corrupt\n");
break;
case IMENOREAD:
fprintf (stderr, "Sorry, this format is write-only\n");
break;
case IMEMAGIC:
fprintf (stderr, "Bad magic number in image file\n");
break;
case IMEDEPTH:
fprintf (stderr, "Unknown image depth\n");
break;
default:
fprintf(stderr, "Unknown error\n");
break;
}
free_images (toolInTable);
free (fullname);
return (None);
}
if (TagTableQNEntry (toolInTable, "image vfb") == 0) {
fprintf (stderr, "Image file %s contains no images\n", fullname);
free_images (toolInTable);
free (fullname);
return (None);
}
dataEntry = TagTableQDirect (toolInTable, "image vfb", 0);
TagEntryQValue (dataEntry, &sourceVfb);
fclose (fp);
w = ImVfbQWidth (sourceVfb);
h = ImVfbQHeight (sourceVfb);
depth = 8 * ImVfbQNBytes (sourceVfb);
if (depth != 8) {
fprintf (stderr, "I don't know yet how to deal with images not of 8 planes depth\n");
free_images (toolInTable);
return (None);
}
*width = w;
*height = h;
scrn = Scr->screen;
cmap = AlternateCmap ? AlternateCmap : stdcmap;
visual = Scr->d_visual;
gc = DefaultGC (dpy, scrn);
buffer_size = w * h;
imagedata = (unsigned char*) malloc (buffer_size);
if (imagedata == (unsigned char*) 0) {
fprintf (stderr, "Can't alloc enough space for background images\n");
free_images (toolInTable);
return (None);
}
clt = ImVfbQClt (sourceVfb);
vptr = ImVfbQFirst (sourceVfb);
ncolors = 0;
for (i = 0; i < h - 1; i++) {
for (j = 0; j < w; j++) {
ij = (i * w) + j;
red = ImCltQRed (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr)));
green = ImCltQGreen (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr)));
blue = ImCltQBlue (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr)));
for (k = 0; k < ncolors; k++) {
if ((colors [k].red == red) &&
(colors [k].green == green) &&
(colors [k].blue == blue)) {
icol = k;
break;
}
}
if (k == ncolors) {
icol = ncolors;
ncolors++;
}
imagedata [ij] = icol;
colors [icol].red = red;
colors [icol].green = green;
colors [icol].blue = blue;
ImVfbSInc (sourceVfb, vptr);
}
}
for (i = 0; i < ncolors; i++) {
colors [i].red *= 256;
colors [i].green *= 256;
colors [i].blue *= 256;
}
for (i = 0; i < ncolors; i++) {
if (! XAllocColor (dpy, cmap, &(colors [i]))) {
fprintf (stderr, "can't alloc color for image %s\n", filename);
}
}
for (i = 0; i < buffer_size; i++) {
imagedata [i] = (unsigned char) colors [imagedata [i]].pixel;
}
image = XCreateImage (dpy, visual, depth, ZPixmap, 0, (char*) imagedata, w, h, 8, 0);
if (w > Scr->rootw) w = Scr->rootw;
if (h > Scr->rooth) h = Scr->rooth;
if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) {
int x, y;
pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, depth);
x = (Scr->rootw - w) / 2;
y = (Scr->rooth - h) / 2;
XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth);
XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h);
ret->width = Scr->rootw;
ret->height = Scr->rooth;
}
else {
pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth);
XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h);
ret->width = w;
ret->height = h;
}
XFree (image);
ret = (Image*) malloc (sizeof (struct _Image));
ret->pixmap = pixret;
ret->mask = None;
ret->next = None;
return (ret);
}
static void free_images (table)
TagTable *table;
{
int i, n;
ImVfb *v;
ImClt *c;
TagEntry *dataEntry;
n = TagTableQNEntry (table, "image vfb");
for (i = 0 ; i < n ; i++) {
dataEntry = TagTableQDirect (table, "image vfb", i);
TagEntryQValue (dataEntry, &v);
ImVfbFree (v);
}
n = TagTableQNEntry (table, "image clt");
for (i = 0 ; i < n ; i++) {
dataEntry = TagTableQDirect (table, "image clt", i );
TagEntryQValue (dataEntry, &c);
ImCltFree (c);
}
TagTableFree (table);
}
#endif
void _swapshort (register char *bp, register unsigned n)
{
register char c;
register char *ep = bp + n;
while (bp < ep) {
c = *bp;
*bp = *(bp + 1);
bp++;
*bp++ = c;
}
}
void _swaplong (register char *bp, register unsigned n)
{
register char c;
register char *ep = bp + n;
register char *sp;
while (bp < ep) {
sp = bp + 3;
c = *sp;
*sp = *bp;
*bp++ = c;
sp = bp + 1;
c = *sp;
*sp = *bp;
*bp++ = c;
bp += 2;
}
}
/***********************************************************************
*
* Procedure:
* GetWMPropertyString - Get Window Manager text property and
* convert it to a string.
*
* Returned Value:
* (char *) - pointer to the malloc'd string or NULL
*
* Inputs:
* w - the id of the window whose property is to be retrieved
* prop - property atom (typically WM_NAME or WM_ICON_NAME)
*
***********************************************************************
*/
unsigned char *GetWMPropertyString(Window w, Atom prop)
{
XTextProperty text_prop;
char **text_list;
int text_list_count;
Atom XA_COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False);
unsigned char *stringptr;
int status, len = -1;
(void)XGetTextProperty(dpy, w, &text_prop, prop);
if (text_prop.value != NULL) {
if (text_prop.encoding == XA_STRING
|| text_prop.encoding == XA_COMPOUND_TEXT) {
/* property is encoded as compound text - convert to locale string */
status = XmbTextPropertyToTextList(dpy, &text_prop,
&text_list, &text_list_count);
if (text_list_count == 0) {
stringptr = NULL;
} else
if (text_list == (char **)0) {
stringptr = NULL;
} else
if (text_list [0] == (char *)0) {
stringptr = NULL;
} else
if (status < 0 || text_list_count < 0) {
switch (status) {
case XConverterNotFound:
fprintf (stderr, "%s: Converter not found; unable to convert property %s of window ID %lx.\n",
ProgramName, XGetAtomName(dpy, prop), w);
break;
case XNoMemory:
fprintf (stderr, "%s: Insufficient memory; unable to convert property %s of window ID %lx.\n",
ProgramName, XGetAtomName(dpy, prop), w);
break;
case XLocaleNotSupported:
fprintf (stderr, "%s: Locale not supported; unable to convert property %s of window ID %lx.\n",
ProgramName, XGetAtomName(dpy, prop), w);
break;
}
stringptr = NULL;
/*
don't call XFreeStringList - text_list appears to have
invalid address if status is bad
XFreeStringList(text_list);
*/
} else {
len = strlen(text_list[0]);
stringptr = memcpy(malloc(len+1), text_list[0], len+1);
XFreeStringList(text_list);
}
} else {
/* property is encoded in a format we don't understand */
fprintf (stderr, "%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n",
ProgramName, XGetAtomName(dpy, prop), w);
stringptr = NULL;
}
XFree (text_prop.value);
} else {
stringptr = NULL;
}
return stringptr;
}
void FreeWMPropertyString(char *prop)
{
if (prop && (char *)prop != NoName) {
free(prop);
}
}
static void ConstrainLeftTop (int *value, int border)
{
if (*value < border) {
if (Scr->MoveOffResistance < 0 ||
*value > border - Scr->MoveOffResistance)
{
*value = border;
} else if (Scr->MoveOffResistance > 0 &&
*value <= border - Scr->MoveOffResistance)
{
*value = *value + Scr->MoveOffResistance;
}
}
}
static void ConstrainRightBottom (int *value, int size1, int border, int size2)
{
if (*value + size1 > size2 - border) {
if (Scr->MoveOffResistance < 0 ||
*value + size1 < size2 - border + Scr->MoveOffResistance)
{
*value = size2 - size1 - border;
} else if (Scr->MoveOffResistance > 0 &&
*value + size1 >= size2 - border + Scr->MoveOffResistance) {
*value = *value - Scr->MoveOffResistance;
}
}
}
void ConstrainByBorders1 (int *left, int width, int *top, int height)
{
ConstrainRightBottom (left, width, Scr->BorderRight, Scr->rootw);
ConstrainLeftTop (left, Scr->BorderLeft);
ConstrainRightBottom (top, height, Scr->BorderBottom, Scr->rooth);
ConstrainLeftTop (top, Scr->BorderTop);
}
void ConstrainByBorders (TwmWindow *twmwin,
int *left, int width, int *top, int height)
{
if (twmwin->winbox) {
XWindowAttributes attr;
XGetWindowAttributes (dpy, twmwin->winbox->window, &attr);
ConstrainRightBottom (left, width, 0, attr.width);
ConstrainLeftTop (left, 0);
ConstrainRightBottom (top, height, 0, attr.height);
ConstrainLeftTop (top, 0);
} else {
ConstrainByBorders1 (left, width, top, height);
}
}
#ifdef JPEG
uint16_t *buffer_16bpp;
uint32_t *buffer_32bpp;
static void convert_for_16 (int w, int x, int y, int r, int g, int b) {
buffer_16bpp [y * w + x] = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3);
}
static void convert_for_32 (int w, int x, int y, int r, int g, int b) {
buffer_32bpp [y * w + x] = ((r << 16) + (g << 8) + b) & 0xFFFFFFFF;
}
static void jpeg_error_exit (j_common_ptr cinfo) {
jerr_ptr errmgr = (jerr_ptr) cinfo->err;
cinfo->err->output_message (cinfo);
siglongjmp (errmgr->setjmp_buffer, 1);
return;
}
static Image *GetJpegImage (char *name)
{
Image *image, *r, *s;
char path [128];
char pref [128], *perc;
int i;
if (! strchr (name, '%')) return (LoadJpegImage (name));
s = image = None;
strcpy (pref, name);
perc = strchr (pref, '%');
*perc = '\0';
reportfilenotfound = 0;
for (i = 1;; i++) {
sprintf (path, "%s%d%s", pref, i, perc + 1);
r = LoadJpegImage (path);
if (r == None) break;
r->next = None;
if (image == None) s = image = r;
else {
s->next = r;
s = r;
}
}
reportfilenotfound = 1;
if (s != None) s->next = image;
if (image == None) {
fprintf (stderr, "Cannot open any %s jpeg file\n", name);
}
return (image);
}
static Image *LoadJpegImage (char *name)
{
char *fullname;
XImage *ximage;
FILE *infile;
Image *image;
Pixmap pixret;
void (*store_data) (int w, int x, int y, int r, int g, int b);
struct jpeg_decompress_struct cinfo;
struct jpeg_error jerr;
JSAMPARRAY buffer;
int width, height;
int row_stride;
int g, i, a;
int bpix;
GC gc;
fullname = ExpandPixmapPath (name);
if (! fullname) return (None);
image = (Image*) malloc (sizeof (struct _Image));
if (image == None) return (None);
if ((infile = fopen (fullname, "rb")) == NULL) {
if (!reportfilenotfound) fprintf (stderr, "unable to locate %s\n", fullname);
fflush (stdout);
return None;
}
cinfo.err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = jpeg_error_exit;
if (sigsetjmp(jerr.setjmp_buffer, 1)) {
jpeg_destroy_decompress (&cinfo);
fclose (infile);
return None;
}
jpeg_create_decompress (&cinfo);
jpeg_stdio_src (&cinfo, infile);
jpeg_read_header (&cinfo, FALSE);
cinfo.do_fancy_upsampling = FALSE;
cinfo.do_block_smoothing = FALSE;
jpeg_start_decompress (&cinfo);
width = cinfo.output_width;
height = cinfo.output_height;
if (Scr->d_depth == 16) {
store_data = &convert_for_16;
buffer_16bpp = (unsigned short int *) malloc ((width) * (height) * 2);
ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0,
(char *) buffer_16bpp, width, height, 16, width * 2);
} else {
if (Scr->d_depth == 24) {
store_data = &convert_for_32;
buffer_32bpp = malloc (width * height * 4);
ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0,
(char *) buffer_32bpp, width, height, 32, width * 4);
} else
if (Scr->d_depth == 32) {
store_data = &convert_for_32;
buffer_32bpp = malloc (width * height * 4);
ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0,
(char *) buffer_32bpp, width, height, 32, width * 4);
} else {
fprintf (stderr, "Image %s unsupported depth : %d\n", name, Scr->d_depth);
return None;
}
}
if (ximage == None) {
fprintf (stderr, "cannot create image for %s\n", name);
}
g = 0;
row_stride = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
bpix = cinfo.output_components;
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines (&cinfo, buffer, 1);
a = 0;
for (i = 0; i < bpix * cinfo.output_width; i += bpix) {
(*store_data) (width, a, g, buffer[0][i], buffer[0][i + 1], buffer[0][i + 2]);
a++;
}
g++;
}
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
fclose (infile);
gc = DefaultGC (dpy, Scr->screen);
if ((width > (Scr->rootw / 2)) || (height > (Scr->rooth / 2))) {
int x, y;
pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, Scr->d_depth);
x = (Scr->rootw - width) / 2;
y = (Scr->rooth - height) / 2;
XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth);
XPutImage (dpy, pixret, gc, ximage, 0, 0, x, y, width, height);
image->width = Scr->rootw;
image->height = Scr->rooth;
} else {
pixret = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth);
XPutImage (dpy, pixret, gc, ximage, 0, 0, 0, 0, width, height);
image->width = width;
image->height = height;
}
XDestroyImage (ximage);
image->pixmap = pixret;
image->mask = None;
image->next = None;
return image;
}
#endif /* JPEG */