#include <stdlib.h>
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Label.h>
#include <X11/Shell.h>
#include <X11/cursorfont.h>
#include <X11/Xmu/Error.h>
#include "RootWin.h"
#include "Scale.h"
#include "CutPaste.h"
#define SRCWIDTH 64
#define SRCHEIGHT 64
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
#define HLINTERVAL 10
typedef enum { drag, resize, done } hlMode;
typedef struct {
Boolean newScale;
hlMode selectMode;
GC gc;
XWindowAttributes win_info;
XImage *image;
Position homeX, homeY, x, y;
Dimension width, height;
Widget scaleShell, scaleInstance, pixShell, pixLabel, cmapWinList [2];
} hlStruct, *hlPtr;
static XtAppContext app;
static Cursor ulAngle, urAngle, lrAngle, llAngle;
static Display *dpy;
static int scr;
static GC selectGC;
static XGCValues selectGCV;
static Widget toplevel, root;
static Atom wm_delete_window;
static int numXmags = 0;
static int srcStat, srcX, srcY;
static unsigned int srcWidth, srcHeight;
static int Error(Display *, XErrorEvent *);
static void CloseAP(Widget, XEvent *, String *, Cardinal *);
static void SetCmapPropsAP(Widget, XEvent *, String *, Cardinal *);
static void UnsetCmapPropsAP(Widget, XEvent *, String *, Cardinal *);
static void NewAP(Widget, XEvent *, String *, Cardinal *);
static void ReplaceAP(Widget, XEvent *, String *, Cardinal *);
static void PopupPixelAP(Widget, XEvent *, String *, Cardinal *);
static void UpdatePixelAP(Widget, XEvent *, String *, Cardinal *);
static void PopdownPixelAP(Widget, XEvent *, String *, Cardinal *);
static void SelectRegionAP(Widget, XEvent *, String *, Cardinal *);
static void CheckPoints(Position *, Position *, Position *, Position *);
static void HighlightTO(XtPointer, XtIntervalId *);
static void CloseCB(Widget, XtPointer, XtPointer);
static void ReplaceCB(Widget, XtPointer, XtPointer);
static void NewCB(Widget, XtPointer, XtPointer);
static void SelectCB(Widget, XtPointer, XtPointer);
static void PasteCB(Widget, XtPointer, XtPointer);
static void SetupGC(void);
static Window FindWindow(int, int);
static void ResizeEH(Widget, XtPointer, XEvent *, Boolean *);
static void DragEH(Widget, XtPointer, XEvent *, Boolean *);
static void StartRootPtrGrab(int, hlPtr);
static void CreateRoot(void);
static void GetImageAndAttributes(Window, int, int, int, int, hlPtr);
static int Get_XColors(XWindowAttributes *, XColor **);
static Pixel GetMaxIntensity(hlPtr);
static Pixel GetMinIntensity(hlPtr);
static void PopupNewScale(hlPtr);
static void RedoOldScale(hlPtr);
static void InitCursors(void);
static void ParseSourceGeom(void);
typedef struct { String geometry, source, mag, title; } OptionsRec;
static OptionsRec options;
#define Offset(field) XtOffsetOf(OptionsRec, field)
static XtResource resources[] = {
{"geometry", "Geometry", XtRString, sizeof(String),
Offset(geometry), XtRString, (XtPointer)NULL},
{"mag", "Mag", XtRString, sizeof(String),
Offset(mag), XtRString, (XtPointer)"5.0"},
{"source", "Source", XtRString, sizeof(String),
Offset(source), XtRString, (XtPointer)"SRCWIDTHxSRCHEIGHT"},
{"title", XtCString, XtRString, sizeof(char *),
Offset(title), XtRString, "xmag"},
};
#undef Offset
static XrmOptionDescRec optionDesc[] = {
{"-bd", "*borderColor", XrmoptionSepArg, (XtPointer)NULL},
{"-bg", "*background", XrmoptionSepArg, (XtPointer)NULL},
{"-bw", "*borderWidth", XrmoptionSepArg, (XtPointer)NULL},
{"-geometry", "*geometry", XrmoptionSepArg, (XtPointer)NULL},
{"-mag", "*mag", XrmoptionSepArg, (XtPointer)NULL},
{"-source", "*source", XrmoptionSepArg, (XtPointer)NULL},
{"-title", "*title", XrmoptionSepArg, (XtPointer)NULL},
};
static XtActionsRec actions_table[] = {
{"close", CloseAP},
{"set-colors", SetCmapPropsAP},
{"unset-colors", UnsetCmapPropsAP},
{"new", NewAP},
{"replace", ReplaceAP},
{"popup-pixel", PopupPixelAP},
{"update-pixel", UpdatePixelAP},
{"popdown-pixel", PopdownPixelAP},
{"select-region", SelectRegionAP}
};
static int
Error(Display *dpy, XErrorEvent *err)
{
(void) XmuPrintDefaultErrorMessage (dpy, err, stderr);
return 0;
}
static void
CloseAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
Arg wargs[2]; int n; hlPtr data;
if (!--numXmags) exit(0);
if (event->type != ClientMessage) {
n = 0;
XtSetArg(wargs[0], XtNuserData, &data); n++;
XtGetValues(w, wargs, n);
w = data->scaleShell;
}
XtPopdown(w);
XtDestroyWidget(w);
}
static void
SetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
Arg wargs[2]; int n; hlPtr data;
n = 0;
XtSetArg(wargs[0], XtNuserData, &data); n++;
XtGetValues(w, wargs, n);
if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
data->cmapWinList[0] = data->scaleInstance;
data->cmapWinList[1] = data->scaleShell;
XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
}
}
static void
UnsetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
Arg wargs[2]; int n; hlPtr data;
n = 0;
XtSetArg(wargs[0], XtNuserData, &data); n++;
XtGetValues(w, wargs, n);
if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
data->cmapWinList[0] = data->scaleShell;
data->cmapWinList[1] = data->scaleInstance;
XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
}
}
static void
NewAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
StartRootPtrGrab(True, NULL);
}
static void
ReplaceAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
Arg wargs[2]; int n; hlPtr data;
n = 0;
XtSetArg(wargs[0], XtNuserData, &data); n++;
XtGetValues(w, wargs, n);
StartRootPtrGrab(False, data);
}
static void
PopupPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
Position scale_x, scale_y;
Dimension scale_height;
Position label_x, label_y;
Dimension label_height;
int n;
Arg wargs[3];
hlPtr data;
n = 0;
XtSetArg(wargs[0], XtNuserData, &data); n++;
XtGetValues(w, wargs, n);
n = 0;
XtSetArg(wargs[n], XtNheight, &scale_height); n++;
XtGetValues(w, wargs, n);
XtTranslateCoords(w, -1, -1, &scale_x, &scale_y);
XtRealizeWidget(data->pixShell);
n = 0;
XtSetArg(wargs[n], XtNheight, &label_height); n++;
XtGetValues(data->pixShell, wargs, n);
if ((double) event->xbutton.y / (double) scale_height > 0.5) {
label_x = scale_x;
label_y = scale_y;
}
else {
label_x = scale_x;
label_y = scale_y + scale_height - label_height;
}
n = 0;
XtSetArg(wargs[n], XtNx, label_x); n++;
XtSetArg(wargs[n], XtNy, label_y); n++;
XtSetValues(data->pixShell, wargs, n);
UpdatePixelAP(w, event, 0, 0);
}
static void
UpdatePixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
Position x, y;
Pixel pixel;
XColor color;
int n;
Arg wargs[3];
char string[80];
hlPtr data;
n = 0;
XtSetArg(wargs[0], XtNuserData, &data); n++;
XtGetValues(w, wargs, n);
if (SWGetImagePixel(w, event->xbutton.x, event->xbutton.y, &x, &y, &pixel))
XtPopdown(data->pixShell);
else {
color.pixel = pixel;
XQueryColor(dpy, data->win_info.colormap, &color);
sprintf(string, "Pixel %ld at (%d,%d) colored (%x,%x,%x).",
pixel, x + data->x, y + data->y,
color.red, color.green, color.blue);
n = 0;
XtSetArg(wargs[n], XtNlabel, string); n++;
XtSetValues(data->pixLabel, wargs, n);
XtPopup(data->pixShell, XtGrabNone);
}
}
static void
PopdownPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
int n;
Arg wargs[3];
hlPtr data = NULL;
n = 0;
XtSetArg(wargs[0], XtNuserData, &data); n++;
XtGetValues(w, wargs, n);
if (data)
XtPopdown(data->pixShell);
}
static void
SelectRegionAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
}
static void
CheckPoints(Position *x1, Position *x2, Position *y1, Position *y2)
{
Position tmp;
Boolean above, left;
Cursor newC;
above = (*y2 < *y1); left = (*x2 < *x1);
if (above&&left) newC = ulAngle;
else if (above&&!left) newC = urAngle;
else if (!above&&!left) newC = lrAngle;
else newC = llAngle;
XChangeActivePointerGrab
(dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
newC, CurrentTime);
if (*x2 < *x1) { tmp = *x1; *x1 = *x2; *x2 = tmp; }
if (*y2 < *y1) { tmp = *y1; *y1 = *y2; *y2 = tmp; }
}
static void
HighlightTO(XtPointer closure, XtIntervalId *id)
{
hlPtr data = (hlPtr)closure;
XGrabServer(dpy);
if (data->selectMode == drag) {
XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
data->x, data->y, data->width, data->height);
XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
data->x, data->y, data->width, data->height);
}
else if (data->selectMode == resize) {
Position x1 = data->homeX,
x2 = data->x,
y1 = data->homeY,
y2 = data->y;
CheckPoints(&x1, &x2, &y1, &y2);
XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
x1, y1, x2 - x1, y2 - y1);
XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
x1, y1, x2 - x1, y2 - y1);
}
XUngrabServer(dpy);
if (data->selectMode != done)
XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)data);
}
static void
CloseCB(Widget w, XtPointer clientData, XtPointer callData)
{
Widget shell = (Widget)clientData;
if (!--numXmags) exit(0);
XtPopdown(shell);
XtDestroyWidget(shell);
}
static void
ReplaceCB(Widget w, XtPointer clientData, XtPointer callData)
{
hlPtr data = (hlPtr)clientData;
StartRootPtrGrab(False, data);
}
static void
NewCB(Widget w, XtPointer clientData, XtPointer callData)
{
StartRootPtrGrab(True, NULL);
}
static void
SelectCB(Widget w, XtPointer clientData, XtPointer callData)
{
hlPtr data = (hlPtr)clientData;
SWGrabSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
}
static void
PasteCB(Widget w, XtPointer clientData, XtPointer callData)
{
hlPtr data = (hlPtr)clientData;
SWRequestSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
}
static void
SetupGC(void)
{
selectGCV.function = GXxor;
selectGCV.foreground = 1L;
selectGCV.subwindow_mode = IncludeInferiors;
selectGC = XtGetGC(toplevel, GCFunction|GCForeground|GCSubwindowMode,
&selectGCV);
}
static Window
FindWindow(int x, int y)
{
XWindowAttributes wa;
Window findW = DefaultRootWindow(dpy), stopW, childW;
stopW = findW;
while (stopW) {
XTranslateCoordinates(dpy, findW, stopW,
x, y, &x, &y, &childW);
findW = stopW;
if (childW &&
XGetWindowAttributes(dpy, childW, &wa) &&
wa.class != InputOutput)
break;
stopW = childW;
}
return findW;
}
static void
ResizeEH(Widget w, XtPointer closure, XEvent *event,
Boolean *continue_to_dispatch)
{
hlPtr data = (hlPtr)closure;
switch (event->type) {
case MotionNotify:
data->x = event->xmotion.x_root;
data->y = event->xmotion.y_root;
break;
case ButtonRelease:
GetImageAndAttributes(FindWindow(event->xmotion.x_root,
event->xmotion.y_root),
min(data->homeX,event->xbutton.x_root),
min(data->homeY,event->xbutton.y_root),
abs(data->homeX - event->xbutton.x_root),
abs(data->homeY - event->xbutton.y_root),
data);
if (data->newScale)
PopupNewScale(data);
else
SWSetImage(data->scaleInstance, data->image);
XtUngrabPointer(w, CurrentTime);
XtRemoveEventHandler(w, PointerMotionMask|ButtonReleaseMask,
True, ResizeEH, (XtPointer)data);
data->selectMode = done;
break;
}
}
static void
DragEH(Widget w, XtPointer closure, XEvent *event,
Boolean *continue_to_dispatch)
{
hlPtr data = (hlPtr)closure;
switch (event->type) {
case MotionNotify:
data->x = event->xmotion.x_root;
data->y = event->xmotion.y_root;
break;
case ButtonRelease:
if (event->xbutton.button == Button1) {
GetImageAndAttributes(FindWindow(event->xmotion.x_root,
event->xmotion.y_root),
event->xbutton.x_root,
event->xbutton.y_root,
srcWidth, srcHeight, data);
if (data->newScale)
PopupNewScale(data);
else
RedoOldScale(data);
XtUngrabPointer(w, CurrentTime);
XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
ButtonReleaseMask, True, DragEH,
(XtPointer)data);
data->selectMode = done;
}
break;
case ButtonPress:
if (event->xbutton.button == Button2) {
data->homeX = event->xbutton.x_root;
data->homeY = event->xbutton.y_root;
data->x = event->xbutton.x_root + srcWidth;
data->y = event->xbutton.y_root + srcHeight;
data->selectMode = resize;
XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
ButtonReleaseMask, True, DragEH, (XtPointer)data);
XChangeActivePointerGrab
(dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
lrAngle, CurrentTime);
XWarpPointer(dpy, None, None, 0, 0, 0, 0,
srcWidth, srcHeight);
XtAddEventHandler(w, PointerMotionMask|ButtonReleaseMask,
True, ResizeEH, (XtPointer)data);
}
break;
}
}
static void
StartRootPtrGrab(int new,
hlPtr data)
{
Window rootR, childR;
int rootX, rootY, winX, winY;
unsigned int mask;
hlPtr hlData;
XtGrabPointer
(root, False,
PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, None, ulAngle, CurrentTime);
XQueryPointer(dpy, DefaultRootWindow(dpy), &rootR, &childR,
&rootX, &rootY, &winX, &winY, &mask);
if (new) {
numXmags++;
hlData = (hlPtr)XtMalloc(sizeof(hlStruct));
}
else hlData = data;
hlData->newScale = new;
hlData->selectMode = drag;
hlData->x = rootX;
hlData->y = rootY;
hlData->gc = selectGC;
hlData->width = srcWidth;
hlData->height = srcHeight;
XtAddRawEventHandler
(root, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
True, DragEH, (XtPointer)hlData);
(void) XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)hlData);
}
static void
CreateRoot(void)
{
hlPtr data;
root = XtCreateWidget("root", rootWindowWidgetClass, toplevel, NULL, 0);
XtRealizeWidget(root);
if (XValue & srcStat && YValue &srcStat) {
numXmags = 1;
data = (hlPtr)XtMalloc(sizeof(hlStruct));
data = data;
data->newScale = True;
data->selectMode = drag;
data->x = srcX;
data->y = srcY;
data->gc = selectGC;
data->width = srcWidth;
data->height = srcHeight;
GetImageAndAttributes(RootWindow(dpy, scr), srcX, srcY, srcWidth,
srcHeight, data);
PopupNewScale(data);
return;
}
}
static void
GetImageAndAttributes(Window w, int x, int y, int width, int height,
hlPtr data)
{
XGetWindowAttributes(dpy, w, &data->win_info);
if (data->win_info.depth == DefaultDepth(dpy, scr)) {
if (x < 0) x = 0; if (y < 0) y = 0;
if (x + width > DisplayWidth(dpy,scr)) x = DisplayWidth(dpy,scr) - width;
if (y + height > DisplayHeight(dpy,scr))
y = DisplayHeight(dpy,scr) - height;
data->x = x; data->y = y;
data->image = XGetImage (dpy,
RootWindow(dpy, scr),
x, y,
width, height,
AllPlanes, ZPixmap);
}
else {
int xInWin, yInWin; Window childWin;
XTranslateCoordinates(dpy, DefaultRootWindow(dpy), w, x, y,
&xInWin, &yInWin, &childWin);
if (x + data->win_info.x < 0) x = abs(data->win_info.x);
if (y + data->win_info.y < 0) y = abs(data->win_info.y);
if (x + width > DisplayWidth(dpy,scr)) x = DisplayWidth(dpy,scr) - width;
if (y + height > DisplayHeight(dpy,scr))
y = DisplayHeight(dpy,scr) - height;
data->x = x; data->y = y;
data->image = XGetImage (dpy,
w,
xInWin, yInWin,
width, height,
AllPlanes, ZPixmap);
}
}
#define lowbit(x) ((x) & (~(x) + 1))
static int
Get_XColors(XWindowAttributes *win_info, XColor **colors)
{
int i, ncolors;
if (!win_info->colormap)
return(0);
ncolors = win_info->visual->map_entries;
if (!(*colors = (XColor *) XtMalloc (sizeof(XColor) * ncolors)))
XtError("Out of memory!");
if (win_info->visual->class == DirectColor ||
win_info->visual->class == TrueColor) {
Pixel red, green, blue, red1, green1, blue1;
red = green = blue = 0;
red1 = lowbit(win_info->visual->red_mask);
green1 = lowbit(win_info->visual->green_mask);
blue1 = lowbit(win_info->visual->blue_mask);
for (i=0; i<ncolors; i++) {
(*colors)[i].pixel = red|green|blue;
(*colors)[i].pad = 0;
red += red1;
if (red > win_info->visual->red_mask)
red = 0;
green += green1;
if (green > win_info->visual->green_mask)
green = 0;
blue += blue1;
if (blue > win_info->visual->blue_mask)
blue = 0;
}
} else {
for (i=0; i<ncolors; i++) {
(*colors)[i].pixel = i;
(*colors)[i].pad = 0;
}
}
XQueryColors(dpy, win_info->colormap, *colors, ncolors);
return(ncolors);
}
#define Intensity(cptr) (3.0*cptr->red+0.59*cptr->green+0.11*cptr->blue)
static Pixel
GetMaxIntensity(hlPtr data)
{
XColor *colors = NULL, *mptr, *tptr;
int i, ncolors;
if (data->win_info.colormap == DefaultColormap(dpy, scr))
return WhitePixel(dpy, scr);
ncolors = Get_XColors(&data->win_info, &colors);
mptr = tptr = colors; tptr++;
for (i=1; i<ncolors; i++) {
if ((int)Intensity(mptr) < (int)Intensity(tptr))
mptr = tptr;
tptr++;
}
if(mptr)
return mptr->pixel;
else
return WhitePixel(dpy, scr);
}
static Pixel
GetMinIntensity(hlPtr data)
{
XColor *colors = NULL, *mptr, *tptr;
int i, ncolors;
if (data->win_info.colormap == DefaultColormap(dpy, scr))
return BlackPixel(dpy, scr);
ncolors = Get_XColors(&data->win_info, &colors);
mptr = tptr = colors; tptr++;
for (i=1; i<ncolors; i++) {
if ((int)Intensity(mptr) > (int)Intensity(tptr))
mptr = tptr;
tptr++;
}
if(mptr)
return mptr->pixel;
else
return BlackPixel(dpy, scr);
}
static Widget pane1, pane2, pane3, cclose, replace, new, select_w, paste;
static void
PopupNewScale(hlPtr data)
{
Arg warg;
data->scaleShell =
XtVaCreatePopupShell("xmag", topLevelShellWidgetClass, toplevel,
XtNgeometry, (XtArgVal)options.geometry,
XtNtitle, (XtArgVal)options.title,
NULL);
pane1 = XtCreateManagedWidget("pane1", panedWidgetClass, data->scaleShell,
(Arg *) NULL, 0);
pane2 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
(Arg *) NULL, 0);
cclose = XtCreateManagedWidget("close", commandWidgetClass, pane2,
(Arg *) NULL, 0);
XtAddCallback(cclose, XtNcallback, CloseCB, (XtPointer)data->scaleShell);
replace = XtCreateManagedWidget("replace", commandWidgetClass, pane2,
(Arg *) NULL, 0);
XtAddCallback(replace, XtNcallback, ReplaceCB, (XtPointer)data);
new = XtCreateManagedWidget("new", commandWidgetClass, pane2,
(Arg *) NULL, 0);
XtAddCallback(new, XtNcallback, NewCB, (XtPointer)NULL);
select_w = XtCreateManagedWidget("select", commandWidgetClass, pane2,
(Arg *) NULL, 0);
XtAddCallback(select_w, XtNcallback, SelectCB, (XtPointer)data);
paste = XtCreateManagedWidget("paste", commandWidgetClass, pane2,
(Arg *) NULL, 0);
XtAddCallback(paste, XtNcallback, PasteCB, (XtPointer)data);
(void) XtCreateManagedWidget("helpLabel", labelWidgetClass, pane2,
(Arg *) NULL, 0);
pane3 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
(Arg *) NULL, 0);
data->scaleInstance =
XtVaCreateManagedWidget("scale", scaleWidgetClass,
pane3,
XtNvisual, (XtArgVal)data->win_info.visual,
XtNcolormap, (XtArgVal)data->win_info.colormap,
XtNdepth, (XtArgVal)data->win_info.depth,
XtNscaleX, (XtArgVal)options.mag,
XtNscaleY, (XtArgVal)options.mag,
NULL);
SWSetImage(data->scaleInstance, data->image);
XtOverrideTranslations
(data->scaleShell,
XtParseTranslationTable ("<Message>WM_PROTOCOLS: close()"));
XtSetArg(warg, XtNuserData, data);
XtSetValues(data->scaleInstance, &warg, 1);
data->pixShell =
XtVaCreatePopupShell("pixShell", overrideShellWidgetClass,
toplevel,
XtNvisual, (XtArgVal)data->win_info.visual,
XtNcolormap, (XtArgVal)data->win_info.colormap,
XtNdepth, (XtArgVal)data->win_info.depth,
XtNborderWidth, (XtPointer)0,
NULL);
data->pixLabel =
XtVaCreateManagedWidget("pixLabel", labelWidgetClass,
data->pixShell,
XtNforeground, (XtPointer)GetMaxIntensity(data),
XtNbackground, (XtPointer)GetMinIntensity(data),
XtNborderWidth, (XtPointer)0,
NULL);
XtInstallAllAccelerators(pane1, pane1);
if (data->newScale) {
XtPopup(data->scaleShell, XtGrabNone);
(void) XSetWMProtocols
(dpy, XtWindow(data->scaleShell), &wm_delete_window, 1);
}
if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
data->cmapWinList[0] = data->scaleShell;
data->cmapWinList[1] = data->scaleInstance;
XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
}
}
static void
RedoOldScale(hlPtr data)
{
Arg wargs[3];
int n;
Visual *oldVis;
int oldDepth;
Colormap oldCmap;
n=0;
XtSetArg(wargs[n], XtNvisual, &oldVis); n++;
XtSetArg(wargs[n], XtNdepth, &oldDepth); n++;
XtSetArg(wargs[n], XtNcolormap, &oldCmap); n++;
XtGetValues(data->scaleInstance, wargs, n);
if (oldVis == data->win_info.visual && oldDepth == data->win_info.depth
&& oldCmap == data->win_info.colormap) {
SWSetImage(data->scaleInstance, data->image);
return;
}
XtUnmanageChild(data->scaleInstance);
XtUnrealizeWidget(data->scaleInstance);
n=0;
XtSetArg(wargs[n], XtNcolormap, data->win_info.colormap); n++;
XtSetArg(wargs[n], XtNdepth, data->win_info.depth); n++;
XtSetArg(wargs[n], XtNvisual, data->win_info.visual); n++;
XtSetValues(data->scaleInstance, wargs, n);
n=0;
XtSetArg(wargs[n], XtNforeground, GetMaxIntensity(data)); n++;
XtSetArg(wargs[n], XtNbackground, GetMinIntensity(data)); n++;
XtSetValues(data->pixLabel, wargs, n);
SWSetImage(data->scaleInstance, data->image);
XtRealizeWidget(data->scaleInstance);
XtManageChild(data->scaleInstance);
}
static void
InitCursors(void)
{
ulAngle = XCreateFontCursor(dpy, XC_ul_angle);
urAngle = XCreateFontCursor(dpy, XC_ur_angle);
lrAngle = XCreateFontCursor(dpy, XC_lr_angle);
llAngle = XCreateFontCursor(dpy, XC_ll_angle);
}
static void
ParseSourceGeom(void)
{
srcStat =
XParseGeometry(options.source, &srcX, &srcY, &srcWidth, &srcHeight);
if (!srcWidth) srcWidth = SRCWIDTH;
if (!srcHeight) srcHeight = SRCHEIGHT;
if (XNegative & srcStat) srcX = DisplayWidth(dpy, scr) + srcX - srcWidth;
if (YNegative & srcStat) srcY = DisplayHeight(dpy, scr) + srcY - srcHeight;
}
int
main(int argc, char *argv[])
{
XSetErrorHandler(Error);
toplevel = XtAppInitialize(&app, "Xmag", optionDesc, XtNumber(optionDesc),
&argc, argv, NULL,
NULL, 0);
dpy = XtDisplay(toplevel);
scr = DefaultScreen(dpy);
XtGetApplicationResources(toplevel, (XtPointer) &options, resources,
XtNumber(resources), NULL, 0);
if (argc != 1) {
fprintf (stderr,
"usage: xmag [-source geom] [-mag magfactor] [-toolkitoption]\n");
exit(1);
}
ParseSourceGeom();
XtAppAddActions(app, actions_table, XtNumber(actions_table));
InitCursors();
SetupGC();
CreateRoot();
if (!(XValue & srcStat && YValue & srcStat))
StartRootPtrGrab(True, (hlPtr)NULL);
wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XtAppMainLoop(app);
exit(0);
}