home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Stars of Shareware: Programmierung
/
SOURCE.mdf
/
programm
/
msdos
/
c
/
xv221src
/
xvevent.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-29
|
41KB
|
1,465 lines
/*
* xvevent.c - EventLoop and support routines for XV
*
* Author: John Bradley, University of Pennsylvania
* (bradley@cis.upenn.edu)
*
* Contains:
* int EventLoop()
* void DrawWindow(x,y,w,h)
* void WResize(w,h)
* void WRotate()
* void WCrop(w,h)
* void WUnCrop()
* void GetWindowPos(&xwa)
* void SetWindowPos(&xwa)
* static void TrackCrop(mx,my)
* static void CropKey(dx,dy,grow)
* static int Rect(x,y,x1,y1)
* void InvCropRect()
* static void TrackPicValues(mx,my)
* static int CheckForConfig()
* void SetEpicMode()
* int xvErrorHandler(disp, err)
*/
/*
* Copyright 1989, 1990, 1991, 1992 by John Bradley and
* The University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any expressed or implied warranty.
*
* The author may be contacted via:
* US Mail: John Bradley
* GRASP Lab, Room 301C
* 3401 Walnut St.
* Philadelphia, PA 19104
*
* Phone: (215) 898-8813
* EMail: bradley@cis.upenn.edu
*/
#define NEEDSTIME /* for -wait handling in eventloop */
#include "xv.h"
static int rotatesLeft = 0;
static int origcropx, origcropy, origcropvalid=0;
static int canstartwait;
/* local function pre-definitions */
#ifdef __STDC__
static void WMaximize(void);
static void TrackCrop(int, int);
static void CropKey(int, int, int);
static int Rect(int, int, int, int);
static void TrackPicValues(int, int);
static int CheckForConfig(void);
static void onInterrupt(void);
#else
static void WMaximize(), TrackCrop(), CropKey(), TrackPicValues();
static int Rect(), CheckForConfig();
static void onInterrupt();
#endif
/****************/
int EventLoop()
/****************/
{
XEvent event;
int retval,done,waiting;
time_t orgtime, curtime;
#ifndef NOSIGNAL
signal(SIGQUIT, onInterrupt);
#endif
/* note: there's no special event handling if we're using the root window.
if we're using the root window, we will recieve NO events for mainW */
/* note: 'canstartwait' is magically turned 'true' in HandleEvent when I
think I've finally gotten 'mainW' drawn. It does not necessarily
mean that any waiting is/will be done. Also note that if we're
using a root mode, canstartwait is instantly turned on, as we aren't
going to be getting Expose/Configure events on the root window */
done = retval = waiting = canstartwait = 0;
if (useroot) canstartwait = 1;
while (!done) {
if (waitsec > -1 && canstartwait && !waiting && XPending(theDisp)==0) {
/* we wanna wait, we can wait, we haven't started waiting yet, and
all pending events (ie, drawing the image the first time)
have been dealt with: START WAITING */
time((time_t *) &orgtime);
waiting = 1;
}
if (waitsec == -1 || XPending(theDisp)>0) {
XNextEvent(theDisp, &event);
retval = HandleEvent(&event,&done);
}
else { /* no events. check wait status */
if (waitsec>-1 && waiting) {
time((time_t *) &curtime);
if (curtime - orgtime < waitsec) sleep(1);
else {
if (waitloop) return NEXTLOOP;
else return NEXTQUIT;
}
}
}
} /* while (!done) */
if (!useroot && origcropvalid) WUnCrop();
origcropvalid = 0;
return(retval);
}
/****************/
int HandleEvent(event, donep)
XEvent *event;
int *donep;
{
static int wasInfoUp=0, wasCtrlUp=0, wasDirUp=0, wasGamUp=0, wasPsUp=0;
static int wasJpegUp=0, wasTiffUp=0;
int done=0, retval=0;
switch (event->type) {
case ColormapNotify: {
XColormapEvent *cev = (XColormapEvent *) event;
if (cev->window == mainW || cev->window == rootW ||
(cev->window == gamW && cmapInGam)) {
if (LocalCmap) {
if (cev->colormap == LocalCmap)
cmapinstalled = (cev->state == ColormapInstalled);
else if (cev->window == rootW &&
cev->colormap != LocalCmap &&
cev->state == ColormapInstalled)
cmapinstalled = 0;
else if (cev->window == mainW &&
cev->colormap != LocalCmap &&
cev->state == ColormapInstalled) {
cmapinstalled = 1; /* KLUDGE */
}
if (DEBUG) fprintf(stderr,"Cmapinstalled = %d\n", cmapinstalled);
}
if (DEBUG) {
fprintf(stderr, "Colormap event: window = %s",
(cev->window == mainW) ? "mainW" :
((cev->window == rootW) ? "rootW" : "gamW/other"));
fprintf(stderr, " colormap = %s, state = %s\n",
(cev->colormap == None) ? "None" :
(cev->colormap == LocalCmap) ? "LocalCmap" : "???",
(cev->state == ColormapInstalled) ?
"installed" : "deinstalled");
}
}
}
break;
case ClientMessage: {
Atom proto, delwin;
XClientMessageEvent *client_event = (XClientMessageEvent *) event;
if (PUCheckEvent (event)) break; /* event has been processed */
proto = XInternAtom(theDisp, "WM_PROTOCOLS", FALSE);
delwin = XInternAtom(theDisp, "WM_DELETE_WINDOW", FALSE);
if (client_event->message_type == proto &&
client_event->data.l[0] == delwin) {
/* it's a WM_DELETE_WINDOW event */
if (client_event->window == infoW) InfoBox(0);
else if (client_event->window == gamW) GamBox(0);
else if (client_event->window == ctrlW) CtrlBox(0);
else if (client_event->window == dirW) DirBox(0);
else if (client_event->window == psW) PSDialog(0);
#ifdef HAVE_JPEG
else if (client_event->window == jpegW) JPEGDialog(0);
#endif
#ifdef HAVE_TIFF
else if (client_event->window == tiffW) TIFFDialog(0);
#endif
else if (client_event->window == mainW) exit(0);
}
}
break;
case Expose: {
XExposeEvent *exp_event = (XExposeEvent *) event;
int x,y,w,h;
Window win;
#ifdef VMS
static int borders_sized = 0;
if (!borders_sized && !useroot && exp_event->window == mainW) {
/*
* Initial expose of main window, find the size of the ancestor
* window just prior to the root window and adjust saved size
* of display so that maximize functions will allow for window
* decorations.
*/
int status, count, mwid, mhgt, x, y, w, h, b, d, mbrd;
Window root, parent, *children, crw = exp_event->window;
borders_sized = 1;
status = XGetGeometry(theDisp, crw,
&root, &x, &y, &mwid, &mhgt, &mbrd, &d);
for ( parent = crw, w=mwid, h=mhgt;
status && (parent != root) && (parent != vrootW); ) {
crw = parent;
status = XQueryTree ( theDisp, crw, &root, &parent,
&children, &count );
if ( children != NULL ) XFree ( children );
}
status = XGetGeometry(theDisp, crw, &root, &x, &y, &w, &h, &b, &d);
if ( status ) {
dispWIDE = dispWIDE + mwid - w + (2*b);
dispHIGH = dispHIGH + mhgt - h + b;
/*printf("New display dims: %d %d\n", dispWIDE, dispHIGH ); */
}
}
#endif
win = exp_event->window;
x = exp_event->x; y = exp_event->y;
w = exp_event->width; h = exp_event->height;
if (PUCheckEvent (event)) break; /* event has been processed */
if (PSCheckEvent (event)) break; /* event has been processed */
#ifdef HAVE_JPEG
if (JPEGCheckEvent(event)) break; /* event has been processed */
#endif
#ifdef HAVE_TIFF
if (TIFFCheckEvent(event)) break; /* event has been processed */
#endif
if (GamCheckEvent (event)) break; /* event has been processed */
/* if the window doesn't do intelligent redraw, drop all-1 exposes */
if (exp_event->count>0 && exp_event->window != mainW
&& exp_event->window != ctrlW
&& exp_event->window != dirW
&& exp_event->window != infoW) break;
if (win == mainW) {
if (DEBUG) fprintf(stderr,"EXPOSE: ");
if (!CheckForConfig()) {
if (DEBUG) fprintf(stderr,"No configs. Expose %d,%d %dx%d\n",x,y,w,h);
if (DEBUG) XClearArea(theDisp, mainW, x,y,w,h, False);
DrawWindow(x,y,w,h);
if (but[BCROP].active) {
XRectangle xr;
xr.x = x; xr.y = y; xr.width = w; xr.height = h;
XSetClipRectangles(theDisp,theGC,0,0,&xr,1,Unsorted);
InvCropRect();
XSetClipMask(theDisp,theGC,None);
}
if (exp_event->count == 0) {
canstartwait = 1; /* finished drawing */
XSync(theDisp, False);
}
}
else
if (DEBUG)
fprintf(stderr,"Ignoring expose event. Config pending\n");
}
else if (win == infoW) RedrawInfo(x,y,w,h);
else if (win == ctrlW) RedrawCtrl(x,y,w,h);
else if (win == nList.win) LSRedraw(&nList);
else if (win == nList.scrl.win) SCRedraw(&nList.scrl);
else if (win == dirW) RedrawDirW(x,y,w,h);
else if (win == dList.win) LSRedraw(&dList);
else if (win == dList.scrl.win) SCRedraw(&dList.scrl);
else if (win == dnamW) RedrawDNamW();
}
break;
case ButtonPress: {
XButtonEvent *but_event = (XButtonEvent *) event;
int i,x,y;
Window win;
win = but_event->window;
x = but_event->x; y = but_event->y;
if (win == mainW && !useroot && showzoomcursor) {
DoZoom(x, y, but_event->button);
break;
}
if (PUCheckEvent (event)) break;
if (PSCheckEvent (event)) break;
#ifdef HAVE_JPEG
if (JPEGCheckEvent(event)) break;
#endif
#ifdef HAVE_TIFF
if (TIFFCheckEvent(event)) break;
#endif
if (GamCheckEvent (event)) break;
switch (but_event->button) {
case Button1:
if (win == mainW) TrackPicValues(x,y);
else if (win == ctrlW) {
int w,h;
if (MBClick(&dispMB, x,y)) {
if (MBTrack(&dispMB)) HandleDispMode();
break;
}
if (MBClick(&conv24MB, x,y)) {
if (MBTrack(&conv24MB)) { conv24 = conv24MB.selected; }
break;
}
i=ClickCtrl(x,y);
switch (i) {
case BNEXT: retval= NEXTPIC; done=1; break;
case BPREV: retval= PREVPIC; done=1; break;
case BLOAD: DirBox(BLOAD); break;
case BSAVE: DirBox(BSAVE); break;
case BQUIT: retval= QUIT; done=1; break;
case BCROP: DoCrop(); break;
case BUNCROP: UnCrop(); break;
case BNORM: WResize(cWIDE/normFact, cHIGH/normFact); break;
case BMAX: WMaximize(); break;
case BUP10: w = (eWIDE*11)/10; h = (eHIGH*11)/10;
if (w==eWIDE) w++;
if (h==eHIGH) h++;
WResize(w,h);
break;
case BDN10: WResize((eWIDE*9)/10, (eHIGH*9)/10); break;
case BUP2: WResize(eWIDE*2, eHIGH*2); break;
case BDN2: WResize(eWIDE/2, eHIGH/2); break;
case B4BY3: w = eWIDE; h = (w * 3) / 4;
if (h>maxHIGH) { h = eHIGH; w = (h*4)/3; }
WResize(w,h);
break;
case BASPECT: FixAspect(1,&w,&h); WResize(w,h); break;
case BMAXPECT: { int w1,h1;
w1 = eWIDE; h1 = eHIGH;
eWIDE = dispWIDE; eHIGH = dispHIGH;
FixAspect(0,&w,&h);
eWIDE = w1; eHIGH = h1; /* play it safe */
WResize(w,h);
} break;
case BROTL: Rotate(1); break;
case BROTR: Rotate(0); break;
case BACROP: AutoCrop(); break;
case BFLIPH: Flip(0); break;
case BFLIPV: Flip(1); break;
case BSMOOTH: Smooth(); break;
case BDITH: ColorDither(NULL, eWIDE, eHIGH); break;
case BRAW: xvDestroyImage(theImage);
theImage = NULL;
Resize(eWIDE,eHIGH);
break;
case BINFO: InfoBox(!infoUp); break;
case BGAMMA: GamBox(!gamUp); break;
case BDELETE: if (DeleteCmd()) { done = 1; retval = DELETE; }
break;
case BGRAB: if (Grab()) { done = 1; retval = GRABBED; }
break;
default: break;
}
if (i==BFLIPH || i==BFLIPV || i==BSMOOTH || i==BDITH || i==BRAW) {
if (useroot) MakeRootPic();
else DrawWindow(0,0,eWIDE,eHIGH);
if (but[BCROP].active) InvCropRect();
SetCursors(-1);
}
}
else if (win == nList.win) {
i=LSClick(&nList,but_event);
if (i>=0) { done = 1; retval = i; }
}
else if (win == nList.scrl.win) SCTrack(&nList.scrl, x, y);
else if (win == dirW) {
i=ClickDirW(x,y);
switch (i) {
case S_BOK: if (dirUp == BLOAD) {
retval = LOADPIC;
done=1;
}
else if (dirUp == BSAVE) {
DoSave();
}
break;
case S_BCANC: DirBox(0); break;
case S_BRESCAN:
WaitCursor(); LoadCurrentDirectory(); SetCursors(-1);
break;
}
}
else if (win == dList.win) {
i=LSClick(&dList,but_event);
SelectDir(i);
}
else if (win == dList.scrl.win) SCTrack(&dList.scrl, x,y);
else if (win == infoW) InfoBox(0); /* close info */
break;
case Button2: if (win == mainW) TrackCrop(x,y);
break;
case Button3: /* if using root, MUST NOT get rid of ctrlbox. */
if (!useroot) CtrlBox(!ctrlUp);
break;
default: break;
}
}
break;
case KeyRelease: {
XKeyEvent *key_event = (XKeyEvent *) event;
char buf[128]; KeySym ks;
int stlen, dealt, shift;
stlen = XLookupString(key_event,buf,128,&ks,(XComposeStatus *) NULL);
dealt = 0;
if (key_event->window == mainW &&
(ks == XK_Control_L || ks == XK_Control_R)) {
if (showzoomcursor) {
showzoomcursor = 0;
SetCursors(-1);
}
}
}
break;
case KeyPress: {
XKeyEvent *key_event = (XKeyEvent *) event;
char buf[128]; KeySym ks;
int stlen, dealt, shift;
stlen = XLookupString(key_event,buf,128,&ks,(XComposeStatus *) NULL);
dealt = 0;
if (PUCheckEvent (event)) break;
if (PSCheckEvent (event)) break;
if (key_event->window == mainW &&
(ks == XK_Control_L || ks == XK_Control_R)) {
if (!showzoomcursor) {
showzoomcursor = 1;
SetCursors(-1);
}
}
#ifdef HAVE_JPEG
if (JPEGCheckEvent(event)) break;
#endif
#ifdef HAVE_TIFF
if (TIFFCheckEvent(event)) break;
#endif
if (GamCheckEvent (event)) break;
/* check for crop rect keys */
if (key_event->window == mainW /* && !dirUp */) {
dealt = 1; shift = key_event->state & ShiftMask;
if (ks==XK_Left || ks==XK_KP_4 || ks==XK_F30) CropKey(-1, 0,shift);
else if (ks==XK_Right || ks==XK_KP_6 || ks==XK_F32) CropKey( 1, 0,shift);
else if (ks==XK_Up || ks==XK_KP_8 || ks==XK_F28) CropKey( 0,-1,shift);
else if (ks==XK_Down || ks==XK_KP_2 || ks==XK_F34) CropKey( 0, 1,shift);
else dealt = 0;
if (dealt) break;
}
/* check for List keys */
if (key_event->window == ctrlW || key_event->window == dirW /*||dirUp*/) {
LIST *theList;
if (key_event->window == dirW /*|| dirUp*/) theList = &dList;
else theList = &nList;
dealt = 1;
if (ks==XK_Prior) LSKey(theList,LS_PAGEUP);
else if (ks==XK_Next) LSKey(theList,LS_PAGEDOWN);
else if (ks==XK_Up) LSKey(theList,LS_LINEUP);
else if (ks==XK_Down) LSKey(theList,LS_LINEDOWN);
else if (ks==XK_Home) LSKey(theList,LS_HOME);
else if (ks==XK_End) LSKey(theList,LS_END);
else dealt = 0;
if (theList == &dList && dealt) { /* changed dir selection */
SelectDir(-1); /* nothing was double-clicked */
}
if (dealt) break;
}
/* check dir filename arrows */
if (key_event->window == dirW && ks==XK_Left) { DirKey('\002'); break; }
if (key_event->window == dirW && ks==XK_Right) { DirKey('\006'); break; }
if (!stlen) break;
/* if dirUp, send all keystrokes to it OR NOT */
if (key_event->window == dirW /* || dirUp */) {
if (DirKey(buf[0])) XBell(theDisp,0);
}
else {
/* commands valid in any window */
switch (buf[0]) {
case '\t':
case ' ': FakeButtonPress(&but[BNEXT]); break;
case '\r':
case '\n': if (nList.selected >= 0 && nList.selected < nList.nstr) {
done = 1; retval = nList.selected;
}
break;
case '\010':
case '\177': FakeButtonPress(&but[BPREV]); break;
case '\004': FakeButtonPress(&but[BDELETE]); break; /* ^D */
case '\014': FakeButtonPress(&but[BLOAD]); break; /* ^L */
case '\023': FakeButtonPress(&but[BSAVE]); break; /* ^S */
case '\007': FakeButtonPress(&but[BGRAB]); break; /* ^G */
case 'q': FakeButtonPress(&but[BQUIT]); break;
case '?': if (!useroot) CtrlBox(!ctrlUp); break;
case 's': FakeButtonPress(&but[BSMOOTH]); break;
case 'd': FakeButtonPress(&but[BDITH]); break;
case 'r': FakeButtonPress(&but[BRAW]); break;
case 'a': FakeButtonPress(&but[BASPECT]); break;
case 'A': FakeButtonPress(&but[BACROP]); break;
case 'T': FakeButtonPress(&but[BROTL]); break;
case 't': FakeButtonPress(&but[BROTR]); break;
case 'h': FakeButtonPress(&but[BFLIPH]); break;
case 'v': FakeButtonPress(&but[BFLIPV]); break;
case '4': FakeButtonPress(&but[B4BY3]); break;
case 'c': FakeButtonPress(&but[BCROP]); break;
case 'u': FakeButtonPress(&but[BUNCROP]); break;
case 'n': FakeButtonPress(&but[BNORM]); break;
case 'm': FakeButtonPress(&but[BMAX]); break;
case 'M': FakeButtonPress(&but[BMAXPECT]); break;
case ',': FakeButtonPress(&but[BDN10]); break;
case '.': FakeButtonPress(&but[BUP10]); break;
case '<': FakeButtonPress(&but[BDN2]); break;
case '>': FakeButtonPress(&but[BUP2]); break;
case 'i': FakeButtonPress(&but[BINFO]); break;
case 'e': FakeButtonPress(&but[BGAMMA]); break;
case 'R': FakeButtonPress(&gbut[G_BRESET]); break;
case 'p': FakeButtonPress(&gbut[G_BAPPLY]); break;
case 'H': FakeButtonPress(&gbut[G_BHISTEQ]); break;
case 'N': FakeButtonPress(&gbut[G_BMAXCONT]); break;
default: break;
}
}
}
break;
case ConfigureNotify: {
XConfigureEvent *conf_event = (XConfigureEvent *) event;
if (conf_event->window == ctrlW ||
conf_event->window == gamW ||
conf_event->window == infoW ||
conf_event->window == mainW ||
conf_event->window == dirW) {
XSizeHints hints;
if (DEBUG) fprintf(stderr,"got configure event. %d,%d %dx%d\n",
conf_event->x, conf_event->y, conf_event->width,
conf_event->height);
/* if there's a virtual window manager running (e.g. tvtwm),
we're going to get 'conf_event' values in terms of the
'real' root window (the one that is the size of the screen).
We'll want to translate them into values that are in terms of
the 'virtual' root window (the 'big' one) */
if (vrootW != rootW) { /* virtual window manager running */
int x1,y1;
Window child;
XTranslateCoordinates(theDisp, rootW, vrootW,
conf_event->x, conf_event->y,
&x1, &y1, &child);
if (DEBUG) fprintf(stderr," conf translate: -> %d,%d\n", x1,y1);
conf_event->x = x1; conf_event->y = y1;
}
#ifndef VMS
/* read hints for this window and adjust any position hints */
if (XGetNormalHints(theDisp, conf_event->window, &hints)) {
if (DEBUG) fprintf(stderr," got hints (0x%x %d,%d)\n",
hints.flags, hints.x, hints.y);
hints.x = conf_event->x;
hints.y = conf_event->y;
XSetNormalHints(theDisp, conf_event->window, &hints);
if (DEBUG) fprintf(stderr," set hints (0x%x %d,%d)\n",
hints.flags, hints.x, hints.y);
}
#endif
}
if (conf_event->window == mainW) {
if (!rotatesLeft) {
if (DEBUG) fprintf(stderr,"CONFIG: (%d,%d %dx%d) ",
conf_event->x, conf_event->y,
conf_event->width, conf_event->height);
if (CheckForConfig()) {
if (DEBUG) fprintf(stderr,"more configs pending. ignored\n");
}
else {
XEvent xev;
if (DEBUG) fprintf(stderr,"No configs pend.");
if (conf_event->width == eWIDE && conf_event->height == eHIGH) {
if (DEBUG) fprintf(stderr,"No redraw\n");
}
else {
if (DEBUG) fprintf(stderr,"Do full redraw\n");
Resize(conf_event->width, conf_event->height);
/* eat any pending expose events and do a full redraw */
while (XCheckTypedWindowEvent(theDisp, mainW, Expose, &xev)) {
XExposeEvent *exp = (XExposeEvent *) &xev;
if (DEBUG)
fprintf(stderr," ate expose (%s) (count=%d) %d,%d %dx%d\n",
exp->send_event ? "program" : "user", exp->count,
exp->x, exp->y, exp->width, exp->height);
}
DrawWindow(0,0,conf_event->width, conf_event->height);
canstartwait=1;
XSync(theDisp, False);
SetCursors(-1);
}
}
}
if (rotatesLeft>0) rotatesLeft--;
if (!rotatesLeft) SetCursors(-1);
}
}
break;
case CirculateNotify:
case DestroyNotify:
case GravityNotify: break;
case MapNotify: {
XMapEvent *map_event = (XMapEvent *) event;
if (map_event->window == mainW ||
(map_event->window == ctrlW && dispMB.selected != 0)) {
if (DEBUG) fprintf(stderr,"map event received on mainW/ctrlW\n");
if (autoclose) {
if (wasInfoUp) { InfoBox(wasInfoUp); wasInfoUp=0; }
if (wasCtrlUp) { CtrlBox(wasCtrlUp); wasCtrlUp=0; }
if (wasDirUp) { DirBox(wasDirUp); wasDirUp=0; }
if (wasGamUp) { GamBox(wasGamUp); wasGamUp=0; }
if (wasPsUp) { PSDialog(wasPsUp); wasPsUp=0; }
#ifdef HAVE_JPEG
if (wasJpegUp) { JPEGDialog(wasJpegUp); wasJpegUp=0; }
#endif
#ifdef HAVE_TIFF
if (wasTiffUp) { TIFFDialog(wasTiffUp); wasTiffUp=0; }
#endif
}
}
}
break;
case UnmapNotify: {
XUnmapEvent *unmap_event = (XUnmapEvent *) event;
if (unmap_event->window == mainW ||
(unmap_event->window == ctrlW && dispMB.selected != 0)) {
if (DEBUG) fprintf(stderr,"unmap event received on mainW/ctrlW\n");
if (DEBUG) fprintf(stderr,"dispMB.selected = %d\n", dispMB.selected);
/* don't do it if we've just switched to a root mode */
if ((unmap_event->window == mainW && dispMB.selected == 0) ||
(unmap_event->window == ctrlW && dispMB.selected != 0)) {
if (autoclose) {
if (unmap_event->window == mainW) {
if (ctrlUp) { wasCtrlUp = ctrlUp; CtrlBox(0); }
}
if (infoUp) { wasInfoUp = infoUp; InfoBox(0); }
if (dirUp) { wasDirUp = dirUp; DirBox(0); }
if (gamUp) { wasGamUp = gamUp; GamBox(0); }
if (psUp) { wasPsUp = psUp; PSDialog(0); }
#ifdef HAVE_JPEG
if (jpegUp) { wasJpegUp = jpegUp; JPEGDialog(0); }
#endif
#ifdef HAVE_TIFF
if (tiffUp) { wasTiffUp = tiffUp; TIFFDialog(0); }
#endif
}
}
}
}
break;
case ReparentNotify: {
XReparentEvent *reparent_event = (XReparentEvent *) event;
if (DEBUG) {
fprintf(stderr,"Reparent: mainW=%x ->win=%x ->ev=%x ->parent=%x ",
mainW, reparent_event->window, reparent_event->event,
reparent_event->parent);
fprintf(stderr,"%d,%d\n", reparent_event->x, reparent_event->y);
}
if (reparent_event->window == mainW) {
ch_offx = reparent_event->x; /* offset required for ChangeAttr call */
ch_offy = reparent_event->y;
p_offx = p_offy = 0; /* topleft correction for WMs titlebar */
if (ch_offx == 0 && ch_offy == 0) {
/* looks like the user is running MWM or OLWM */
XWindowAttributes xwa;
/* first query the attributes of mainW. x,y should be the offset
from the parent's topleft corner to the windows topleft.
OLWM puts the info here */
XSync(theDisp, False);
XGetWindowAttributes(theDisp, mainW, &xwa);
if (DEBUG)
fprintf(stderr,"XGetAttr: mainW %d,%d %dx%d\n", xwa.x, xwa.y,
xwa.width, xwa.height);
if (xwa.x == 0 && xwa.y == 0) {
/* MWM, at least mine, puts 0's in those fields. To get the
info, we'll have to query the parent window */
XSync(theDisp, False);
XGetWindowAttributes(theDisp, reparent_event->parent, &xwa);
if (DEBUG)
fprintf(stderr,"XGetAttr: parent %d,%d %dx%d\n", xwa.x, xwa.y,
xwa.width, xwa.height);
}
else {
/* KLUDGE: if we're running olwm, xwa.{x,y} won't be 0,0.
in olwm, the window drifts down and right each time
SetWindowPos() is called. God knows why. Anyway, I'm
inserting a kludge here to increase 'ch_offx' and 'ch_offy'
by bwidth so that this drifting won't happen. No doubt this'll
screw up behavior on some *other* window manager, but it should
work with TWM, OLWM, and MWM (the big three) */
ch_offx += bwidth;
ch_offy += bwidth;
}
p_offx = xwa.x;
p_offy = xwa.y;
}
}
}
break;
case EnterNotify:
case LeaveNotify: {
XCrossingEvent *cross_event = (XCrossingEvent *) event;
if (cross_event->window == mainW || 0
/* (cross_event->window == gamW && cmapInGam) */ ) {
if (cross_event->type == EnterNotify && cross_event->window == mainW) {
if (cross_event->state & ControlMask) { /* ctrl pressed */
if (!showzoomcursor) {
showzoomcursor = 1;
SetCursors(-1);
}
}
else {
if (showzoomcursor) {
showzoomcursor = 0;
SetCursors(-1);
}
}
}
if (cross_event->type == EnterNotify && LocalCmap && !ninstall)
XInstallColormap(theDisp,LocalCmap);
if (cross_event->type == LeaveNotify && LocalCmap && !ninstall)
XUninstallColormap(theDisp,LocalCmap);
}
}
break;
default: break; /* ignore unexpected events */
} /* switch */
*donep = done;
return(retval);
}
/***********************************/
void DrawWindow(x,y,w,h)
int x,y,w,h;
{
if (x+w < eWIDE) w++; /* add one for broken servers (?) */
if (y+h < eHIGH) h++;
if (theImage)
XPutImage(theDisp,mainW,theGC,theImage,x,y,x,y,w,h);
else
if (DEBUG) fprintf(stderr,"Tried to DrawWindow when theImage was NIL\n");
}
/***********************************/
void WResize(w,h)
int w,h;
{
XWindowAttributes xwa;
RANGE(w,1,maxWIDE); RANGE(h,1,maxHIGH);
if (useroot) {
Resize(w,h);
MakeRootPic();
SetCursors(-1);
return;
}
/* determine if new size goes off edge of screen. if so move window so it
doesn't go off screen */
GetWindowPos(&xwa);
if (xwa.x + w > vrWIDE) xwa.x = vrWIDE - w;
if (xwa.y + h > vrHIGH) xwa.y = vrHIGH - h;
if (DEBUG) fprintf(stderr,"%s: resizing window to %d,%d at %d,%d\n",
cmd,w,h,xwa.x,xwa.y);
/* resize the window */
xwa.width = w; xwa.height = h;
SetWindowPos(&xwa);
}
/***********************************/
static void WMaximize()
{
if (useroot) WResize(dispWIDE, dispHIGH);
else {
XWindowAttributes xwa;
bzero((char *) &xwa, sizeof(XWindowAttributes));
xwa.x = xwa.y = 0;
xwa.width = dispWIDE;
xwa.height = dispHIGH;
SetWindowPos(&xwa);
}
}
/***********************************/
void WRotate()
{
/* rotate the window and redraw the contents */
if (but[BCROP].active) BTSetActive(&but[BCROP],0);
if (useroot) {
MakeRootPic();
SetCursors(-1);
return;
}
if (eWIDE == eHIGH) { /* no configure events will be gen'd */
Resize(eWIDE, eHIGH); /* to regen Ximage */
DrawWindow(0, 0, eWIDE, eHIGH);
SetCursors(-1);
}
else {
rotatesLeft++;
XClearWindow(theDisp, mainW); /* get rid of old bits */
GenExpose(mainW, 0, 0, eWIDE, eHIGH);
WResize(eWIDE, eHIGH);
}
}
/***********************************/
void WCrop(w,h)
int w,h;
{
XWindowAttributes xwa;
if (useroot) {
MakeRootPic();
SetCursors(-1);
}
else {
/* we want to move window to old x,y + crx1,cry1 */
GetWindowPos(&xwa);
if (!origcropvalid) { /* first crop. remember win pos */
origcropvalid = 1;
origcropx = xwa.x;
origcropy = xwa.y;
}
xwa.x += crx1; xwa.y += cry1;
xwa.width = w; xwa.height = h;
GenExpose(mainW, 0, 0, eWIDE, eHIGH);
SetWindowPos(&xwa);
}
}
/***********************************/
void WUnCrop()
{
int w,h;
XWindowAttributes xwa;
/* a proper epic has been generated. eWIDE,eHIGH are the new window size */
if (useroot) {
MakeRootPic();
SetCursors(-1);
}
else { /* !useroot */
GetWindowPos(&xwa);
w = eWIDE; h = eHIGH;
/* restore to position when originally cropped */
if (origcropvalid) { /* *should* always be true... */
origcropvalid = 0;
xwa.x = origcropx;
xwa.y = origcropy;
}
if (xwa.x + w > vrWIDE) xwa.x = vrWIDE - w; /* keep on screen */
if (xwa.y + h > vrHIGH) xwa.y = vrHIGH - h;
if (xwa.x<0) xwa.x = 0;
if (xwa.y<0) xwa.y = 0;
xwa.width = w; xwa.height = h;
if (!useroot) {
SetWindowPos(&xwa);
GenExpose(mainW, 0, 0, eWIDE, eHIGH);
}
}
}
/***********************************/
void GetWindowPos(xwa)
XWindowAttributes *xwa;
{
Window child;
/* returns the x,y,w,h coords of mainW. x,y are relative to rootW
the border is not included (x,y map to top-left pixel in window) */
/* Get the window width/height */
XGetWindowAttributes(theDisp,mainW,xwa);
/* Get the window origin */
XTranslateCoordinates(theDisp,mainW,rootW,0,0,&xwa->x,&xwa->y,&child);
}
/***********************************/
void SetWindowPos(xwa)
XWindowAttributes *xwa;
{
/* sets window x,y,w,h values */
XWindowChanges xwc;
/* Adjust from window origin, to border origin */
xwc.x = xwa->x - xwa->border_width - ch_offx;
xwc.y = xwa->y - xwa->border_width - ch_offy;
if (!xwa->border_width) xwa->border_width = bwidth;
xwc.border_width = xwa->border_width;
/* if we're less than max size in one axis, allow window manager doohickeys
on the screen */
if (xwa->width < dispWIDE && xwc.x < p_offx) xwc.x = p_offx;
if (xwa->height < dispHIGH && xwc.y < p_offy) xwc.y = p_offy;
xwc.width = xwa->width;
xwc.height = xwa->height;
if (DEBUG) {
fprintf(stderr,"SWP: xwa=%d,%d %dx%d xwc=%d,%d %dx%d off=%d,%d bw=%d\n",
xwa->x, xwa->y, xwa->width, xwa->height,
xwc.x, xwc.y, xwc.width, xwc.height, p_offx, p_offy,
xwa->border_width);
}
#ifdef DXWM /* dxwm seems to *only* pay attention to the hints */
{
XSizeHints hints;
if (DEBUG) fprintf(stderr,"SWP: doing the DXWM thing\n");
/* read hints for this window and adjust any position hints */
if (XGetNormalHints(theDisp, mainW, &hints)) {
hints.flags |= USPosition | USSize;
hints.x = xwc.x; hints.y = xwc.y;
hints.width = xwc.width; hints.height = xwc.height;
XSetNormalHints(theDisp, mainW, &hints);
}
xwc.x -= 5; xwc.y -= 25; /* EVIL KLUDGE */
}
#endif
/* all non-DXWM window managers (?) */
/* Move/Resize the window. */
XConfigureWindow(theDisp, mainW,
CWX | CWY | CWWidth | CWHeight /*| CWBorderWidth*/, &xwc);
}
/***********************************/
static void TrackCrop(mx,my)
int mx,my;
{
Window rW,cW;
int rx,ry,ox,oy,x,y,active;
unsigned int mask;
if (but[BCROP].active) { /* turn off old cropping rectangle */
XSetFunction(theDisp,theGC,GXinvert);
Rect(crx1,cry1,crx2,cry2);
XSetFunction(theDisp,theGC,GXcopy);
}
active = 0;
SetCropString(active);
crx1 = ox = mx; cry1 = oy = my; /* nail down one corner */
while (1) {
if (XQueryPointer(theDisp,mainW,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
if (!(mask & Button2Mask)) break; /* button released */
if (x!=ox || y!=oy) { /* moved. erase and redraw */
crx2 = x; cry2 = y;
XSetFunction(theDisp,theGC,GXinvert);
Rect(crx1,cry1,ox,oy);
active = Rect(crx1,cry1,crx2,cry2);
XSetFunction(theDisp,theGC,GXcopy);
XFlush(theDisp);
ox=crx2; oy=cry2;
if (infoUp) SetCropString(active);
}
}
}
RANGE(crx1,0,eWIDE); RANGE(cry1,0,eHIGH);
RANGE(crx2,0,eWIDE); RANGE(cry2,0,eHIGH);
BTSetActive(&but[BCROP],active);
SetCropString(active);
}
/***********************************/
static void CropKey(dx,dy,grow)
int dx,dy,grow;
{
int x1,x2,y1,y2,active;
if (!but[BCROP].active) return;
/* x1,y1 = top-left, x2,y2 = bot-right */
if (crx1<crx2) { x1=crx1; x2=crx2; } else { x1=crx2; x2=crx1; }
if (cry1<cry2) { y1=cry1; y2=cry2; } else { y1=cry2; y2=cry1; }
if (!grow) { /* move the rectangle */
x1 += dx; x2 += dx; y1 += dy; y2 += dy;
if (x1<0 || x2>=eWIDE) { x1 -= dx; x2 -= dx; }
if (y1<0 || y2>=eHIGH) { y1 -= dy; y2 -= dy; }
}
else { /* grow the rectangle, pref. keeping top-left anchored */
x2 += dx; y2 += dy;
if (x2>=eWIDE) {
x1 -= dx; x2 -= dx;
if (x1<0) x1=0;
}
if (y2>=eHIGH) {
y1 -= dy; y2 -= dy;
if (y1<0) y1=0;
}
}
XSetFunction(theDisp,theGC,GXinvert);
Rect(crx1,cry1,crx2,cry2);
crx1 = x1; cry1 = y1; crx2 = x2; cry2 = y2;
active = Rect(crx1,cry1,crx2,cry2);
XSetFunction(theDisp,theGC,GXcopy);
BTSetActive(&but[BCROP], active);
SetCropString(active);
}
/***********************************/
static int Rect(x,y,x1,y1)
int x,y,x1,y1;
{
int w,h;
/* returns 0 if it didn't draw anything (rect is too small), 1 if it did */
w = abs(x-x1); h = abs(y-y1);
if (x>x1) x = x1;
if (y>y1) y = y1;
/* keep rectangle inside window */
if (x<0) { w+=x; x=0; }
if (y<0) { h+=y; y=0; }
if (x+w>=eWIDE) w=eWIDE-x-1;
if (y+h>=eHIGH) h=eHIGH-y-1;
if (w<4 || h<4) return 0; /* too small */
XSetPlaneMask(theDisp, theGC, AllPlanes);
XDrawRectangle(theDisp, mainW, theGC, x, y, w, h);
XSetPlaneMask(theDisp, theGC, 1L);
XDrawRectangle(theDisp, mainW, theGC, x+1, y+1, w-2, h-2);
XSetPlaneMask(theDisp, theGC, AllPlanes);
return 1;
}
/***********************************/
void InvCropRect()
{
XSetFunction(theDisp,theGC,GXinvert);
Rect(crx1,cry1,crx2,cry2);
XSetFunction(theDisp,theGC,GXcopy);
}
/***********************************/
static void TrackPicValues(mx,my)
int mx,my;
{
Window rW,cW;
int rx,ry,ox,oy,x,y;
unsigned int mask;
int ty, w, ecol;
char foo[64];
unsigned long wh, bl;
char *str = "8888,8888 = 123,123,123 (123,123,123 HSV)";
wh = infobg; bl = infofg;
/* do a colormap search for black and white if LocalCmap
and use those colors instead of infobg and infofg */
if (LocalCmap) {
XColor ctab[256];
int i;
long cval;
for (i=0; i<nfcols; i++) ctab[i].pixel = freecols[i];
XQueryColors(theDisp,LocalCmap,ctab,nfcols);
/* find 'blackest' pixel */
cval = 0x10000 * 3;
for (i=0; i<nfcols; i++)
if (ctab[i].red + ctab[i].green + ctab[i].blue < cval) {
cval = ctab[i].red + ctab[i].green + ctab[i].blue;
bl = ctab[i].pixel;
}
/* find 'whitest' pixel */
cval = -1;
for (i=0; i<nfcols; i++)
if ((long)ctab[i].red + (long)ctab[i].green + (long)ctab[i].blue >cval) {
cval = ctab[i].red + ctab[i].green + ctab[i].blue;
wh = ctab[i].pixel;
}
}
XSetFont(theDisp, theGC, monofont);
w = XTextWidth(monofinfo, str, strlen(str));
if (my > eHIGH/2) ty = 0;
else ty = eHIGH-(monofinfo->ascent + mfinfo->descent)-4;
ox = oy = -1; /* kludge to force redraw first time through */
XSetForeground(theDisp, theGC, bl);
XFillRectangle(theDisp, mainW, theGC, 0, ty, w + 8,
(monofinfo->ascent+monofinfo->descent) + 4);
XSetForeground(theDisp, theGC, wh);
XSetBackground(theDisp, theGC, bl);
foo[0] = '\0';
x = mx; y = my;
RANGE(x,0,eWIDE-1); RANGE(y,0,eHIGH-1);
rx = cXOFF + (x * cWIDE) / eWIDE;
ry = cYOFF + (y * cHIGH) / eHIGH;
ecol = pic[ry * pWIDE + rx];
while (1) {
int px, py, pix;
if (XQueryPointer(theDisp,mainW,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
if (!(mask & Button1Mask)) break; /* button released */
RANGE(x,0,eWIDE-1);
RANGE(y,0,eHIGH-1);
px = cXOFF + (x * cWIDE) / eWIDE;
py = cYOFF + (y * cHIGH) / eHIGH;
if (px!=ox || py!=oy) { /* moved. erase and redraw */
double h1, s1, v1;
ecol = pix = pic[py * pWIDE + px];
rgb2hsv(rcmap[pix],gcmap[pix],bcmap[pix],&h1,&s1,&v1);
if (h1<0.0) h1 = 0.0; /* map 'NOHUE' to 0.0 */
sprintf(foo,"%4d,%4d = %3d,%3d,%3d (%3d %3d %3d HSV)",
px, py, rcmap[pix],gcmap[pix],bcmap[pix],
(int) h1, (int) (s1 * 100), (int) (v1 * 100));
XDrawImageString(theDisp,mainW,theGC, 4, ty + 2 + monofinfo->ascent,
foo, strlen(foo));
ox = px; oy = py;
}
}
}
if (foo[0]) {
strcat(foo, "\n");
XStoreBytes(theDisp, foo, strlen(foo));
}
XSetFont(theDisp, theGC, mfont);
DrawWindow(0,ty,eWIDE,(monofinfo->ascent+monofinfo->descent)+4);
if (ecol != editColor) ChangeEC(ecol);
}
/***********************************/
static Bool IsConfig(dpy, ev, arg)
Display *dpy;
XEvent *ev;
char *arg;
{
XConfigureEvent *cev;
if (ev->type == ConfigureNotify) {
cev = (XConfigureEvent *) ev;
if (cev->window == mainW && (cev->width != eWIDE || cev->height != eHIGH))
*arg = 1;
}
return False;
}
/***********************************/
static int CheckForConfig()
{
XEvent ev;
char foo;
/* returns true if there's a config event in which mainW changes size
in the event queue */
XSync(theDisp, False);
foo = 0;
XCheckIfEvent(theDisp, &ev, IsConfig, &foo);
return foo;
}
/************************************************************************/
void SetEpicMode()
{
if (epicmode == EM_RAW) {
BTSetActive(&but[BRAW], 0);
BTSetActive(&but[BDITH], (ncols>0) ); /* only enable dith if ncols>0 */
BTSetActive(&but[BSMOOTH],1);
}
else if (epicmode == EM_DITH) {
BTSetActive(&but[BRAW], 1);
BTSetActive(&but[BDITH], 0);
BTSetActive(&but[BSMOOTH],1);
}
else if (epicmode == EM_SMOOTH) {
BTSetActive(&but[BRAW], 1);
BTSetActive(&but[BDITH], 0);
BTSetActive(&but[BSMOOTH],1); /* color editing may require a re-smooth */
}
}
/************************************************************************/
int xvErrorHandler(disp, err)
Display *disp;
XErrorEvent *err;
{
char buf[128];
XUngrabPointer(theDisp, CurrentTime); /* in case error occurred in Grab */
xerrcode = err->error_code;
/* BadAlloc errors (on a XCreatePixmap() call)
and BadAccess errors on XFreeColors are 'ignoreable' errors */
if (xerrcode == BadAlloc ||
(xerrcode == BadAccess && err->request_code==88)) return 0;
else {
/* all other errors are 'fatal' */
XGetErrorText(disp, xerrcode, buf, 128);
fprintf(stderr,"X Error: %s\n",buf);
fprintf(stderr," Major Opcode: %d\n",err->request_code);
exit(-1);
}
return 0;
}
static void onInterrupt()
{
/* make the interrupt signal look like a '\n' keypress in ctrlW */
XKeyEvent ev;
ev.type = KeyPress;
ev.send_event = True;
ev.display = theDisp;
ev.window = ctrlW;
ev.root = rootW;
ev.subwindow = (Window) NULL;
ev.time = CurrentTime;
ev.x = ev.y = ev.x_root = ev.y_root = 0;
ev.state = 0;
ev.keycode = XKeysymToKeycode(theDisp, XK_Return);
ev.same_screen = True;
XSendEvent(theDisp, ctrlW, False, NoEventMask, (XEvent *) &ev);
XFlush(theDisp);
}