xmag.c revision 83d7c197
19aa228fdSmrg/* $Xorg: xmag.c,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
29aa228fdSmrg/*
39aa228fdSmrg
49aa228fdSmrgCopyright 1991, 1998  The Open Group
59aa228fdSmrg
69aa228fdSmrgPermission to use, copy, modify, distribute, and sell this software and its
79aa228fdSmrgdocumentation for any purpose is hereby granted without fee, provided that
89aa228fdSmrgthe above copyright notice appear in all copies and that both that
99aa228fdSmrgcopyright notice and this permission notice appear in supporting
109aa228fdSmrgdocumentation.
119aa228fdSmrg
129aa228fdSmrgThe above copyright notice and this permission notice shall be included
139aa228fdSmrgin all copies or substantial portions of the Software.
149aa228fdSmrg
159aa228fdSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
169aa228fdSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
179aa228fdSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
189aa228fdSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
199aa228fdSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
209aa228fdSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
219aa228fdSmrgOTHER DEALINGS IN THE SOFTWARE.
229aa228fdSmrg
239aa228fdSmrgExcept as contained in this notice, the name of The Open Group shall
249aa228fdSmrgnot be used in advertising or otherwise to promote the sale, use or
259aa228fdSmrgother dealings in this Software without prior written authorization
269aa228fdSmrgfrom The Open Group.
279aa228fdSmrg
289aa228fdSmrg*/
299aa228fdSmrg/* $XFree86: xmag.c,v 1.13 2003/05/27 22:27:07 tsi Exp $ */
309aa228fdSmrg
319aa228fdSmrg#include "config.h"
329aa228fdSmrg
339aa228fdSmrg#include <stdlib.h>		/* for exit() and abs() */
349aa228fdSmrg#include <stdio.h>
359aa228fdSmrg
369aa228fdSmrg#include <X11/Intrinsic.h>
379aa228fdSmrg#include <X11/StringDefs.h>
389aa228fdSmrg#include <X11/Xaw/Paned.h>
399aa228fdSmrg#include <X11/Xaw/Command.h>
409aa228fdSmrg#include <X11/Xaw/Label.h>
419aa228fdSmrg#include <X11/Shell.h>
429aa228fdSmrg#include <X11/cursorfont.h>
439aa228fdSmrg#include <X11/Xmu/Error.h>
449aa228fdSmrg#include "RootWin.h"
459aa228fdSmrg#include "Scale.h"
469aa228fdSmrg#include "CutPaste.h"
479aa228fdSmrg
489aa228fdSmrg#define SRCWIDTH  64
499aa228fdSmrg#define SRCHEIGHT 64
509aa228fdSmrg
519aa228fdSmrg#ifndef min
529aa228fdSmrg#define min(a, b) ((a) < (b) ? (a) : (b))
539aa228fdSmrg#endif
549aa228fdSmrg
5583d7c197Smrg#ifndef max
5683d7c197Smrg#define max(a, b) ((a) > (b) ? (a) : (b))
5783d7c197Smrg#endif
5883d7c197Smrg
599aa228fdSmrg
609aa228fdSmrg
619aa228fdSmrg/* highlight interval (in milliseconds) */
629aa228fdSmrg#define HLINTERVAL  100
639aa228fdSmrg
649aa228fdSmrg/* sleep between draw & erase of highlight
659aa228fdSmrg * 20 milliseconds - enough for screen refresh - not too long to annoy users
669aa228fdSmrg *  since we hold a server grab during this time
679aa228fdSmrg */
689aa228fdSmrg#define HLSLEEPINTERVAL 20 /* milliseconds */
699aa228fdSmrg
709aa228fdSmrg#ifdef HAVE_NANOSLEEP
719aa228fdSmrg#include <time.h>
729aa228fdSmrg#define HLSLEEP	    do { \
739aa228fdSmrg	struct timespec sleeptime = { 0 , HLSLEEPINTERVAL * 1000000 } ;	\
749aa228fdSmrg	nanosleep(&sleeptime, NULL); \
759aa228fdSmrg    } while(0)
769aa228fdSmrg#elif defined(HAVE_POLL)
779aa228fdSmrg#include <poll.h>
789aa228fdSmrg#define HLSLEEP	    poll(NULL, 0, HLSLEEPINTERVAL)
799aa228fdSmrg#elif defined(HAVE_SELECT)
809aa228fdSmrg#include <X11/Xpoll.h>
819aa228fdSmrg#define HLSLEEP	    do { \
829aa228fdSmrg	struct timeval sleeptime = { 0 , HLSLEEPINTERVAL * 1000 } ;	\
839aa228fdSmrg	select(0, NULL, NULL, NULL, &sleeptime); \
849aa228fdSmrg    } while(0)
859aa228fdSmrg#else
869aa228fdSmrg#define HLSLEEP	XSync(dpy, False)
879aa228fdSmrg#endif
889aa228fdSmrg
899aa228fdSmrg/* highlight mode */
909aa228fdSmrgtypedef enum { drag, resize, done } hlMode;
919aa228fdSmrg
929aa228fdSmrg/* highlight data structure */
939aa228fdSmrgtypedef struct {
949aa228fdSmrg  Boolean   newScale;
959aa228fdSmrg  hlMode    selectMode;
969aa228fdSmrg  GC        gc;
979aa228fdSmrg  XWindowAttributes win_info;
989aa228fdSmrg  XImage     *image;
999aa228fdSmrg  Position  homeX, homeY, x, y;
1009aa228fdSmrg  Dimension width, height;
1019aa228fdSmrg  Widget    scaleShell, scaleInstance, pixShell, pixLabel, cmapWinList [2];
1029aa228fdSmrg  } hlStruct, *hlPtr;
1039aa228fdSmrg
1049aa228fdSmrg
1059aa228fdSmrg
1069aa228fdSmrg/* global variables */
1079aa228fdSmrgstatic XtAppContext app;
1089aa228fdSmrgstatic Cursor ulAngle, urAngle, lrAngle, llAngle;
1099aa228fdSmrgstatic Display *dpy;
1109aa228fdSmrgstatic int scr;
1119aa228fdSmrgstatic GC selectGC;
1129aa228fdSmrgstatic XGCValues selectGCV;
1139aa228fdSmrgstatic Widget toplevel, root;
1149aa228fdSmrgstatic Atom wm_delete_window;
1159aa228fdSmrgstatic int numXmags = 0;
1169aa228fdSmrgstatic int srcStat, srcX, srcY;
1179aa228fdSmrgstatic unsigned int srcWidth, srcHeight;
1189aa228fdSmrg
1199aa228fdSmrg/* forward declarations */
1209aa228fdSmrg
1219aa228fdSmrgstatic int Error(Display *, XErrorEvent *);
1229aa228fdSmrgstatic void CloseAP(Widget, XEvent *, String *, Cardinal *);
1239aa228fdSmrgstatic void SetCmapPropsAP(Widget, XEvent *, String *, Cardinal *);
1249aa228fdSmrgstatic void UnsetCmapPropsAP(Widget, XEvent *, String *, Cardinal *);
1259aa228fdSmrgstatic void NewAP(Widget, XEvent *, String *, Cardinal *);
1269aa228fdSmrgstatic void ReplaceAP(Widget, XEvent *, String *, Cardinal *);
1279aa228fdSmrgstatic void PopupPixelAP(Widget, XEvent *, String *, Cardinal *);
1289aa228fdSmrgstatic void UpdatePixelAP(Widget, XEvent *, String *, Cardinal *);
1299aa228fdSmrgstatic void PopdownPixelAP(Widget, XEvent *, String *, Cardinal *);
1309aa228fdSmrgstatic void SelectRegionAP(Widget, XEvent *, String *, Cardinal *);
1319aa228fdSmrgstatic void CheckPoints(Position *, Position *, Position *, Position *);
1329aa228fdSmrgstatic void HighlightTO(XtPointer, XtIntervalId *);
1339aa228fdSmrgstatic void CloseCB(Widget, XtPointer, XtPointer);
1349aa228fdSmrgstatic void ReplaceCB(Widget, XtPointer, XtPointer);
1359aa228fdSmrgstatic void NewCB(Widget, XtPointer, XtPointer);
1369aa228fdSmrgstatic void SelectCB(Widget, XtPointer, XtPointer);
1379aa228fdSmrgstatic void PasteCB(Widget, XtPointer, XtPointer);
1389aa228fdSmrgstatic void SetupGC(void);
1399aa228fdSmrgstatic Window FindWindow(int, int);
1409aa228fdSmrgstatic void ResizeEH(Widget, XtPointer, XEvent *, Boolean *);
1419aa228fdSmrgstatic void DragEH(Widget, XtPointer, XEvent *, Boolean *);
1429aa228fdSmrgstatic void StartRootPtrGrab(int, hlPtr);
1439aa228fdSmrgstatic void CreateRoot(void);
1449aa228fdSmrgstatic void GetImageAndAttributes(Window, int, int, int, int, hlPtr);
1459aa228fdSmrgstatic int Get_XColors(XWindowAttributes *, XColor **);
1469aa228fdSmrgstatic Pixel GetMaxIntensity(hlPtr);
1479aa228fdSmrgstatic Pixel GetMinIntensity(hlPtr);
1489aa228fdSmrgstatic void PopupNewScale(hlPtr);
1499aa228fdSmrgstatic void RedoOldScale(hlPtr);
1509aa228fdSmrgstatic void InitCursors(void);
1519aa228fdSmrgstatic void ParseSourceGeom(void);
1529aa228fdSmrg
1539aa228fdSmrg/* application resources */
1549aa228fdSmrg
1559aa228fdSmrgtypedef struct { String geometry, source, mag, title; } OptionsRec;
1569aa228fdSmrgstatic OptionsRec options;
1579aa228fdSmrg
1589aa228fdSmrg#define Offset(field) XtOffsetOf(OptionsRec, field)
1599aa228fdSmrgstatic XtResource resources[] = {
1609aa228fdSmrg  {"geometry", "Geometry", XtRString, sizeof(String),
1619aa228fdSmrg     Offset(geometry), XtRString, (XtPointer)NULL},
1629aa228fdSmrg  {"mag", "Mag", XtRString, sizeof(String),
1639aa228fdSmrg     Offset(mag), XtRString, (XtPointer)"5.0"},
1649aa228fdSmrg  {"source", "Source", XtRString, sizeof(String),
1659aa228fdSmrg     Offset(source), XtRString, (XtPointer)"SRCWIDTHxSRCHEIGHT"},
1669aa228fdSmrg  {"title", XtCString, XtRString, sizeof(char *),
1679aa228fdSmrg     Offset(title), XtRString, "xmag"},
1689aa228fdSmrg};
1699aa228fdSmrg#undef Offset
1709aa228fdSmrg
1719aa228fdSmrgstatic XrmOptionDescRec optionDesc[] = {
1729aa228fdSmrg  {"-bd",         "*borderColor", XrmoptionSepArg, (XtPointer)NULL},
1739aa228fdSmrg  {"-bg",         "*background",   XrmoptionSepArg, (XtPointer)NULL},
1749aa228fdSmrg  {"-bw",         "*borderWidth", XrmoptionSepArg, (XtPointer)NULL},
1759aa228fdSmrg
1769aa228fdSmrg  {"-geometry", "*geometry", XrmoptionSepArg, (XtPointer)NULL},
1779aa228fdSmrg  {"-mag",      "*mag",                XrmoptionSepArg, (XtPointer)NULL},
1789aa228fdSmrg  {"-source",   "*source",             XrmoptionSepArg, (XtPointer)NULL},
1799aa228fdSmrg  {"-title",    "*title",              XrmoptionSepArg, (XtPointer)NULL},
1809aa228fdSmrg};
1819aa228fdSmrg
1829aa228fdSmrg
1839aa228fdSmrg
1849aa228fdSmrg/* action table */
1859aa228fdSmrg
1869aa228fdSmrgstatic XtActionsRec actions_table[] = {
1879aa228fdSmrg  {"close", CloseAP},
1889aa228fdSmrg  {"set-colors", SetCmapPropsAP},
1899aa228fdSmrg  {"unset-colors", UnsetCmapPropsAP},
1909aa228fdSmrg  {"new", NewAP},
1919aa228fdSmrg  {"replace", ReplaceAP},
1929aa228fdSmrg  {"popup-pixel", PopupPixelAP},
1939aa228fdSmrg  {"update-pixel", UpdatePixelAP},
1949aa228fdSmrg  {"popdown-pixel", PopdownPixelAP},
1959aa228fdSmrg  {"select-region", SelectRegionAP}
1969aa228fdSmrg};
1979aa228fdSmrg
1989aa228fdSmrg
1999aa228fdSmrg
2009aa228fdSmrg/*
2019aa228fdSmrg * Error() -- Error handler:  Catch a bad match in magnifing an
2029aa228fdSmrg *            area that contains bits of different depths.
2039aa228fdSmrg */
2049aa228fdSmrgstatic int
2059aa228fdSmrgError(Display *dpy, XErrorEvent *err)
2069aa228fdSmrg{
2079aa228fdSmrg  (void) XmuPrintDefaultErrorMessage (dpy, err, stderr);
2089aa228fdSmrg  return 0;
2099aa228fdSmrg}
2109aa228fdSmrg
2119aa228fdSmrg
2129aa228fdSmrg/*
2139aa228fdSmrg * CloseAP() -- Close this dialog.  If its the last one exit the program.
2149aa228fdSmrg *
2159aa228fdSmrg */
2169aa228fdSmrgstatic void			/* ARGSUSED */
2179aa228fdSmrgCloseAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
2189aa228fdSmrg{
2199aa228fdSmrg  Arg wargs[2]; int n; hlPtr data;
2209aa228fdSmrg  if (!--numXmags) exit(0);
2219aa228fdSmrg  if (event->type != ClientMessage) {
2229aa228fdSmrg    n = 0;			/* get user data */
2239aa228fdSmrg    XtSetArg(wargs[0], XtNuserData, &data); n++;
2249aa228fdSmrg    XtGetValues(w, wargs, n);
2259aa228fdSmrg    w = data->scaleShell;
2269aa228fdSmrg  }
2279aa228fdSmrg  XtPopdown(w);
2289aa228fdSmrg  XtDestroyWidget(w);
2299aa228fdSmrg}
2309aa228fdSmrg
2319aa228fdSmrg
2329aa228fdSmrg
2339aa228fdSmrg/*
2349aa228fdSmrg * SetCmapPropsAP() -- Put the scale widget first in WM_COLORMAP_WINDOWS
2359aa228fdSmrg *
2369aa228fdSmrg */
2379aa228fdSmrgstatic void			/* ARGSUSED */
2389aa228fdSmrgSetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
2399aa228fdSmrg{
2409aa228fdSmrg  Arg wargs[2]; int n; hlPtr data;
2419aa228fdSmrg  n = 0;			/* get user data */
2429aa228fdSmrg  XtSetArg(wargs[0], XtNuserData, &data); n++;
2439aa228fdSmrg  XtGetValues(w, wargs, n);
2449aa228fdSmrg  if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
2459aa228fdSmrg    data->cmapWinList[0] = data->scaleInstance;
2469aa228fdSmrg    data->cmapWinList[1] = data->scaleShell;
2479aa228fdSmrg    XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
2489aa228fdSmrg  }
2499aa228fdSmrg}
2509aa228fdSmrg
2519aa228fdSmrg
2529aa228fdSmrg
2539aa228fdSmrg/*
2549aa228fdSmrg * UnsetCmapPropsAP() -- Put the shell first in WM_COLORMAP_WINDOWS
2559aa228fdSmrg *
2569aa228fdSmrg */
2579aa228fdSmrgstatic void			/* ARGSUSED */
2589aa228fdSmrgUnsetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
2599aa228fdSmrg{
2609aa228fdSmrg  Arg wargs[2]; int n; hlPtr data;
2619aa228fdSmrg  n = 0;			/* get user data */
2629aa228fdSmrg  XtSetArg(wargs[0], XtNuserData, &data); n++;
2639aa228fdSmrg  XtGetValues(w, wargs, n);
2649aa228fdSmrg  if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
2659aa228fdSmrg    data->cmapWinList[0] = data->scaleShell;
2669aa228fdSmrg    data->cmapWinList[1] = data->scaleInstance;
2679aa228fdSmrg    XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
2689aa228fdSmrg  }
2699aa228fdSmrg}
2709aa228fdSmrg
2719aa228fdSmrg
2729aa228fdSmrg
2739aa228fdSmrg/*
2749aa228fdSmrg * NewAP() -- Create an additional xmag dialog. THIS IS A COPY OF NewEH
2759aa228fdSmrg *                                              FIND A BETTER WAY....
2769aa228fdSmrg */
2779aa228fdSmrgstatic void			/* ARGSUSED */
2789aa228fdSmrgNewAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
2799aa228fdSmrg{
2809aa228fdSmrg  StartRootPtrGrab(True, NULL);
2819aa228fdSmrg}
2829aa228fdSmrg
2839aa228fdSmrg
2849aa228fdSmrg
2859aa228fdSmrg/*
2869aa228fdSmrg * ReplaceAP() -- Replace this particular xmag dialog.
2879aa228fdSmrg */
2889aa228fdSmrgstatic void                     /* ARGSUSED */
2899aa228fdSmrgReplaceAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
2909aa228fdSmrg{
2919aa228fdSmrg  Arg wargs[2]; int n; hlPtr data;
2929aa228fdSmrg  n = 0;			/* get user data */
2939aa228fdSmrg  XtSetArg(wargs[0], XtNuserData, &data); n++;
2949aa228fdSmrg  XtGetValues(w, wargs, n);
2959aa228fdSmrg  StartRootPtrGrab(False, data);
2969aa228fdSmrg}
2979aa228fdSmrg
2989aa228fdSmrg
2999aa228fdSmrg
3009aa228fdSmrg/*
3019aa228fdSmrg * PopupPixelAP() -- Show pixel information.
3029aa228fdSmrg */
3039aa228fdSmrgstatic void			/* ARGSUSED */
3049aa228fdSmrgPopupPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
3059aa228fdSmrg{
3069aa228fdSmrg    Position scale_x, scale_y;
3079aa228fdSmrg    Dimension scale_height;
3089aa228fdSmrg    Position label_x, label_y;
3099aa228fdSmrg    Dimension label_height;
3109aa228fdSmrg    int n;
3119aa228fdSmrg    Arg wargs[3];
3129aa228fdSmrg    hlPtr data;
3139aa228fdSmrg
3149aa228fdSmrg    n = 0;			/* get user data */
3159aa228fdSmrg    XtSetArg(wargs[0], XtNuserData, &data); n++;
3169aa228fdSmrg    XtGetValues(w, wargs, n);
3179aa228fdSmrg
3189aa228fdSmrg    n = 0;
3199aa228fdSmrg    XtSetArg(wargs[n], XtNheight, &scale_height); n++;
3209aa228fdSmrg    XtGetValues(w, wargs, n);
3219aa228fdSmrg    XtTranslateCoords(w, -1, -1, &scale_x, &scale_y);
3229aa228fdSmrg
3239aa228fdSmrg    XtRealizeWidget(data->pixShell); /* to get the right height  */
3249aa228fdSmrg
3259aa228fdSmrg    n = 0;
3269aa228fdSmrg    XtSetArg(wargs[n], XtNheight, &label_height); n++;
3279aa228fdSmrg    XtGetValues(data->pixShell, wargs, n);
3289aa228fdSmrg
3299aa228fdSmrg    if ((double) event->xbutton.y / (double) scale_height > 0.5) {
3309aa228fdSmrg	label_x = scale_x;
3319aa228fdSmrg	label_y = scale_y;
3329aa228fdSmrg    }
3339aa228fdSmrg    else {
3349aa228fdSmrg	label_x = scale_x;
3359aa228fdSmrg	label_y = scale_y + scale_height - label_height;
3369aa228fdSmrg    }
3379aa228fdSmrg
3389aa228fdSmrg    n = 0;
3399aa228fdSmrg    XtSetArg(wargs[n], XtNx, label_x); n++;
3409aa228fdSmrg    XtSetArg(wargs[n], XtNy, label_y); n++;
3419aa228fdSmrg    XtSetValues(data->pixShell, wargs, n);
34283d7c197Smrg
34383d7c197Smrg    UpdatePixelAP(w, event, NULL, NULL);
3449aa228fdSmrg}
3459aa228fdSmrg
3469aa228fdSmrg
3479aa228fdSmrg
3489aa228fdSmrg/*
3499aa228fdSmrg * UpdatePixelAP() -- Update pixel information.
3509aa228fdSmrg */
3519aa228fdSmrgstatic void			/* ARGSUSED */
3529aa228fdSmrgUpdatePixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
3539aa228fdSmrg{
3549aa228fdSmrg    Position x, y;
3559aa228fdSmrg    Pixel pixel;
3569aa228fdSmrg    XColor color;
3579aa228fdSmrg    int n;
3589aa228fdSmrg    Arg wargs[3];
3599aa228fdSmrg    char string[80];
3609aa228fdSmrg    hlPtr data;
3619aa228fdSmrg
3629aa228fdSmrg    n = 0;
3639aa228fdSmrg    XtSetArg(wargs[0], XtNuserData, &data); n++;
3649aa228fdSmrg    XtGetValues(w, wargs, n);
3659aa228fdSmrg
3669aa228fdSmrg    if (SWGetImagePixel(w, event->xbutton.x, event->xbutton.y, &x, &y, &pixel))
3679aa228fdSmrg	XtPopdown(data->pixShell);
3689aa228fdSmrg    else {
3699aa228fdSmrg	color.pixel = pixel;
3709aa228fdSmrg	XQueryColor(dpy, data->win_info.colormap, &color);
3719aa228fdSmrg	sprintf(string, "Pixel %ld at (%d,%d) colored (%x,%x,%x).",
3729aa228fdSmrg		pixel, x + data->x, y + data->y,
3739aa228fdSmrg		color.red, color.green, color.blue);
3749aa228fdSmrg	n = 0;
3759aa228fdSmrg	XtSetArg(wargs[n], XtNlabel, string); n++;
3769aa228fdSmrg	XtSetValues(data->pixLabel, wargs, n);
3779aa228fdSmrg	XtPopup(data->pixShell, XtGrabNone);
3789aa228fdSmrg    }
3799aa228fdSmrg}
3809aa228fdSmrg
3819aa228fdSmrg
3829aa228fdSmrg
3839aa228fdSmrg/*
3849aa228fdSmrg * PopdownPixelAP() -- Remove pixel info.
3859aa228fdSmrg */
3869aa228fdSmrgstatic void			/* ARGSUSED */
3879aa228fdSmrgPopdownPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
3889aa228fdSmrg{
3899aa228fdSmrg  int n;
3909aa228fdSmrg  Arg wargs[3];
3919aa228fdSmrg  hlPtr data = NULL;
3929aa228fdSmrg
3939aa228fdSmrg  n = 0;
3949aa228fdSmrg  XtSetArg(wargs[0], XtNuserData, &data); n++;
3959aa228fdSmrg  XtGetValues(w, wargs, n);
3969aa228fdSmrg
3979aa228fdSmrg  if (data)
3989aa228fdSmrg    XtPopdown(data->pixShell);
3999aa228fdSmrg}
4009aa228fdSmrg
4019aa228fdSmrg
4029aa228fdSmrg
4039aa228fdSmrgstatic void			/* ARGSUSED */
4049aa228fdSmrgSelectRegionAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
4059aa228fdSmrg{
4069aa228fdSmrg/***** NOT SURE WHAT TO DO WITH THIS
4079aa228fdSmrg    if (app_resources.unmap)
4089aa228fdSmrg	XtUnmapWidget(toplevel);
4099aa228fdSmrg    Redisplay(XtDisplay(w), RootWindow(XtDisplay(w),
4109aa228fdSmrg				       DefaultScreen(XtDisplay(w))),
4119aa228fdSmrg	      source.width, source.height,
4129aa228fdSmrg	      app_resources.freq, app_resources.puls,
4139aa228fdSmrg	      ul_angle, lr_angle,
4149aa228fdSmrg	      app_resources.grab);
4159aa228fdSmrg
4169aa228fdSmrg    if (app_resources.unmap)
4179aa228fdSmrg	XtMapWidget(toplevel);
4189aa228fdSmrg******/
4199aa228fdSmrg}
4209aa228fdSmrg
4219aa228fdSmrg
4229aa228fdSmrg
4239aa228fdSmrg/*
4249aa228fdSmrg * CheckPoints() -- Change the cursor for the correct quadrant.
4259aa228fdSmrg *                  Make sure the first point is less than the second
4269aa228fdSmrg *                  for drawing the selection rectangle.
4279aa228fdSmrg *
4289aa228fdSmrg */
4299aa228fdSmrgstatic void
4309aa228fdSmrgCheckPoints(Position *x1, Position *x2, Position *y1, Position *y2)
4319aa228fdSmrg{
4329aa228fdSmrg  Position tmp;
4339aa228fdSmrg  Boolean above, left;
4349aa228fdSmrg  Cursor newC;
4359aa228fdSmrg  above = (*y2 < *y1); left = (*x2 < *x1);
4369aa228fdSmrg  if (above&&left) newC = ulAngle;
4379aa228fdSmrg  else if (above&&!left) newC = urAngle;
4389aa228fdSmrg  else if (!above&&!left) newC = lrAngle;
4399aa228fdSmrg  else newC = llAngle;
4409aa228fdSmrg  XChangeActivePointerGrab
4419aa228fdSmrg    (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
4429aa228fdSmrg     newC, CurrentTime);
4439aa228fdSmrg  if (*x2 < *x1) { tmp = *x1; *x1 = *x2; *x2 = tmp; }
4449aa228fdSmrg  if (*y2 < *y1) { tmp = *y1; *y1 = *y2; *y2 = tmp; }
4459aa228fdSmrg}
4469aa228fdSmrg
4479aa228fdSmrg
4489aa228fdSmrg
4499aa228fdSmrg/*
4509aa228fdSmrg * HighlightTO() -- Timer to highlight the selection box
4519aa228fdSmrg */
4529aa228fdSmrgstatic void
4539aa228fdSmrgHighlightTO(XtPointer closure, XtIntervalId *id)	/* ARGSUSED */
4549aa228fdSmrg{
4559aa228fdSmrg  hlPtr data = (hlPtr)closure;
4569aa228fdSmrg  XGrabServer(dpy);
4579aa228fdSmrg  if (data->selectMode == drag) {
4589aa228fdSmrg    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
4599aa228fdSmrg		   data->x, data->y, data->width, data->height);
4609aa228fdSmrg    XFlush(dpy);
4619aa228fdSmrg    HLSLEEP;
4629aa228fdSmrg    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
4639aa228fdSmrg		   data->x, data->y, data->width, data->height);
4649aa228fdSmrg  }
4659aa228fdSmrg  else if (data->selectMode == resize) {
4669aa228fdSmrg    Position x1 = data->homeX,
4679aa228fdSmrg             x2 = data->x,
4689aa228fdSmrg             y1 = data->homeY,
4699aa228fdSmrg             y2 = data->y;
4709aa228fdSmrg    CheckPoints(&x1, &x2, &y1, &y2);
4719aa228fdSmrg    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
4729aa228fdSmrg		   x1, y1, x2 - x1, y2 - y1);
4739aa228fdSmrg    XFlush(dpy);
4749aa228fdSmrg    HLSLEEP;
4759aa228fdSmrg    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
4769aa228fdSmrg		   x1, y1, x2 - x1, y2 - y1);
4779aa228fdSmrg  }
4789aa228fdSmrg  XUngrabServer(dpy);
4799aa228fdSmrg  if (data->selectMode != done)
4809aa228fdSmrg    XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)data);
4819aa228fdSmrg}
4829aa228fdSmrg
4839aa228fdSmrg
4849aa228fdSmrg
4859aa228fdSmrg/*
4869aa228fdSmrg * CloseCB() -- Delete this xmag dialog.  If its the only one on the screen
4879aa228fdSmrg *             then exit.
4889aa228fdSmrg */
4899aa228fdSmrgstatic void			/* ARGSUSED */
4909aa228fdSmrgCloseCB(Widget w, XtPointer clientData, XtPointer callData)
4919aa228fdSmrg{
4929aa228fdSmrg  Widget shell = (Widget)clientData;
4939aa228fdSmrg  if (!--numXmags) exit(0);
4949aa228fdSmrg  XtPopdown(shell);
4959aa228fdSmrg  XtDestroyWidget(shell);
4969aa228fdSmrg}
4979aa228fdSmrg
4989aa228fdSmrg
4999aa228fdSmrg
5009aa228fdSmrg/*
5019aa228fdSmrg * ReplaceCB() -- Replace this particular xmag dialog.
5029aa228fdSmrg */
5039aa228fdSmrgstatic void                     /* ARGSUSED */
5049aa228fdSmrgReplaceCB(Widget w, XtPointer clientData, XtPointer callData)
5059aa228fdSmrg{
5069aa228fdSmrg  hlPtr data = (hlPtr)clientData;
5079aa228fdSmrg  StartRootPtrGrab(False, data);
5089aa228fdSmrg}
5099aa228fdSmrg
5109aa228fdSmrg
5119aa228fdSmrg
5129aa228fdSmrg/*
5139aa228fdSmrg * NewCB() -- Create an additional xmag dialog.
5149aa228fdSmrg */
5159aa228fdSmrgstatic void			/* ARGSUSED */
5169aa228fdSmrgNewCB(Widget w, XtPointer clientData, XtPointer callData)
5179aa228fdSmrg{
5189aa228fdSmrg  StartRootPtrGrab(True, NULL);
5199aa228fdSmrg}
5209aa228fdSmrg
5219aa228fdSmrg
5229aa228fdSmrg
5239aa228fdSmrg/*
5249aa228fdSmrg * SelectCB() -- Own the primary selection.
5259aa228fdSmrg */
5269aa228fdSmrgstatic void			/* ARGSUSED */
5279aa228fdSmrgSelectCB(Widget w, XtPointer clientData, XtPointer callData)
5289aa228fdSmrg{
5299aa228fdSmrg  hlPtr data = (hlPtr)clientData;
5309aa228fdSmrg  SWGrabSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
5319aa228fdSmrg}
5329aa228fdSmrg
5339aa228fdSmrg
5349aa228fdSmrg
5359aa228fdSmrg/*
5369aa228fdSmrg * PasteCB() -- Paste from the primary selectin into xmag.
5379aa228fdSmrg */
5389aa228fdSmrgstatic void			/* ARGSUSED */
5399aa228fdSmrgPasteCB(Widget w, XtPointer clientData, XtPointer callData)
5409aa228fdSmrg{
5419aa228fdSmrg  hlPtr data = (hlPtr)clientData;
5429aa228fdSmrg  SWRequestSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
5439aa228fdSmrg}
5449aa228fdSmrg
5459aa228fdSmrg
5469aa228fdSmrg
5479aa228fdSmrg/*
5489aa228fdSmrg * SetupGC() -- Graphics context for magnification selection.
5499aa228fdSmrg */
5509aa228fdSmrgstatic void
5519aa228fdSmrgSetupGC(void)
5529aa228fdSmrg{
5539aa228fdSmrg    selectGCV.function = GXxor;
5549aa228fdSmrg    selectGCV.foreground = 0xffffffff;
5559aa228fdSmrg    selectGCV.subwindow_mode = IncludeInferiors;
5569aa228fdSmrg    selectGC = XtGetGC(toplevel, GCFunction|GCForeground|GCSubwindowMode,
5579aa228fdSmrg		       &selectGCV);
5589aa228fdSmrg}
5599aa228fdSmrg
5609aa228fdSmrg
5619aa228fdSmrg
5629aa228fdSmrg/*
5639aa228fdSmrg * FindWindow() -- Determin window the pointer is over.
5649aa228fdSmrg *
5659aa228fdSmrg */
5669aa228fdSmrgstatic Window
5679aa228fdSmrgFindWindow(int x, int y)	/* Locatation of cursor */
5689aa228fdSmrg{
5699aa228fdSmrg  XWindowAttributes wa;
5709aa228fdSmrg  Window findW = DefaultRootWindow(dpy), stopW, childW;
5719aa228fdSmrg
5729aa228fdSmrg  /* Setup for first window find */
5739aa228fdSmrg  stopW = findW;
5749aa228fdSmrg
5759aa228fdSmrg  while (stopW) {
5769aa228fdSmrg    XTranslateCoordinates(dpy, findW, stopW,
5779aa228fdSmrg			  x, y, &x, &y, &childW);
5789aa228fdSmrg    findW = stopW;
5799aa228fdSmrg    /* If child is not InputOutput (for example, InputOnly) */
5809aa228fdSmrg    /* then don't continue, return the present findW which */
5819aa228fdSmrg    /* can be the root, or a root child of class InputOutput */
5829aa228fdSmrg    if (childW &&
5839aa228fdSmrg	XGetWindowAttributes(dpy, childW, &wa) &&
5849aa228fdSmrg	wa.class != InputOutput)
5859aa228fdSmrg	break;
5869aa228fdSmrg    stopW = childW;
5879aa228fdSmrg  }
5889aa228fdSmrg  return findW;
5899aa228fdSmrg}
5909aa228fdSmrg
5919aa228fdSmrg
5929aa228fdSmrg
5939aa228fdSmrg/*
5949aa228fdSmrg * ResizeEH() -- Event Handler for resize of selection box.
5959aa228fdSmrg */
5969aa228fdSmrgstatic void
5979aa228fdSmrgResizeEH(Widget w, XtPointer closure, XEvent *event,
5989aa228fdSmrg	 Boolean *continue_to_dispatch)	/* ARGSUSED */
5999aa228fdSmrg{
6009aa228fdSmrg  hlPtr data = (hlPtr)closure;
6019aa228fdSmrg  switch (event->type) {
6029aa228fdSmrg  case MotionNotify:
6039aa228fdSmrg    data->x = event->xmotion.x_root;
6049aa228fdSmrg    data->y = event->xmotion.y_root;
6059aa228fdSmrg    break;
6069aa228fdSmrg  case ButtonRelease:
6079aa228fdSmrg    GetImageAndAttributes(FindWindow(event->xmotion.x_root,
6089aa228fdSmrg			event->xmotion.y_root),
6099aa228fdSmrg	     min(data->homeX,event->xbutton.x_root),
6109aa228fdSmrg	     min(data->homeY,event->xbutton.y_root),
6119aa228fdSmrg	     abs(data->homeX - event->xbutton.x_root),
6129aa228fdSmrg	     abs(data->homeY - event->xbutton.y_root),
6139aa228fdSmrg	     data);
6149aa228fdSmrg    if (data->newScale)
6159aa228fdSmrg      PopupNewScale(data);
6169aa228fdSmrg    else
6179aa228fdSmrg      SWSetImage(data->scaleInstance, data->image);
6189aa228fdSmrg    XtUngrabPointer(w, CurrentTime);
6199aa228fdSmrg/*****
6209aa228fdSmrg    XtRemoveRawEventHandler(w, PointerMotionMask|ButtonReleaseMask,
6219aa228fdSmrg			 True, ResizeEH, (XtPointer)data);
6229aa228fdSmrg*****/
6239aa228fdSmrg    XtRemoveEventHandler(w, PointerMotionMask|ButtonReleaseMask,
6249aa228fdSmrg			 True, ResizeEH, (XtPointer)data);
6259aa228fdSmrg    data->selectMode = done;
6269aa228fdSmrg    break;
6279aa228fdSmrg  }
6289aa228fdSmrg}
6299aa228fdSmrg
6309aa228fdSmrg
6319aa228fdSmrg
6329aa228fdSmrg/*
6339aa228fdSmrg * DragEH() -- Event Handler for draging selection box.
6349aa228fdSmrg */
6359aa228fdSmrgstatic void
6369aa228fdSmrgDragEH(Widget w, XtPointer closure, XEvent *event,
6379aa228fdSmrg       Boolean *continue_to_dispatch) /* ARGSUSED */
6389aa228fdSmrg{
6399aa228fdSmrg  hlPtr data = (hlPtr)closure;
6409aa228fdSmrg  switch (event->type) {
6419aa228fdSmrg  case MotionNotify:		/* drag mode */
6429aa228fdSmrg    data->x = event->xmotion.x_root;
6439aa228fdSmrg    data->y = event->xmotion.y_root;
6449aa228fdSmrg    break;
6459aa228fdSmrg  case ButtonRelease:		/* end drag mode */
6469aa228fdSmrg    if (event->xbutton.button == Button1) { /* get image */
6479aa228fdSmrg      /* Problem: You can't get bits with XGetImage outside of its window.
6489aa228fdSmrg       *          xmag will only do a GetImage on the actual window in the case
6499aa228fdSmrg       *          where the depth of the window does not match the depth of
6509aa228fdSmrg       *          the root window.
6519aa228fdSmrg       */
6529aa228fdSmrg      GetImageAndAttributes(FindWindow(event->xmotion.x_root,
6539aa228fdSmrg			  event->xmotion.y_root),
6549aa228fdSmrg	       event->xbutton.x_root,
6559aa228fdSmrg	       event->xbutton.y_root,
6569aa228fdSmrg	       srcWidth, srcHeight, data);
6579aa228fdSmrg      if (data->newScale)
6589aa228fdSmrg	PopupNewScale(data);
6599aa228fdSmrg      else
6609aa228fdSmrg	RedoOldScale(data);
6619aa228fdSmrg      XtUngrabPointer(w, CurrentTime);
6629aa228fdSmrg      XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
6639aa228fdSmrg			      ButtonReleaseMask, True, DragEH,
6649aa228fdSmrg			      (XtPointer)data);
6659aa228fdSmrg      data->selectMode = done;
6669aa228fdSmrg    }
6679aa228fdSmrg
6689aa228fdSmrg    break;
6699aa228fdSmrg  case ButtonPress:
6709aa228fdSmrg    if (event->xbutton.button == Button2) {	/* turn on resize mode */
6719aa228fdSmrg      data->homeX = event->xbutton.x_root;
6729aa228fdSmrg      data->homeY = event->xbutton.y_root;
6739aa228fdSmrg      data->x = event->xbutton.x_root + srcWidth;
6749aa228fdSmrg      data->y = event->xbutton.y_root + srcHeight;
6759aa228fdSmrg      data->selectMode = resize;
6769aa228fdSmrg      XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
6779aa228fdSmrg			   ButtonReleaseMask, True, DragEH, (XtPointer)data);
6789aa228fdSmrg      XChangeActivePointerGrab
6799aa228fdSmrg	(dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
6809aa228fdSmrg	 lrAngle, CurrentTime);
6819aa228fdSmrg      XWarpPointer(dpy, None, None, 0, 0, 0, 0,
6829aa228fdSmrg		   srcWidth, srcHeight);
6839aa228fdSmrg      XtAddEventHandler(w, PointerMotionMask|ButtonReleaseMask,
6849aa228fdSmrg			True, ResizeEH, (XtPointer)data);
6859aa228fdSmrg    }
6869aa228fdSmrg    break;
6879aa228fdSmrg  }
6889aa228fdSmrg}
6899aa228fdSmrg
6909aa228fdSmrg
6919aa228fdSmrg
6929aa228fdSmrg
6939aa228fdSmrg/*
6949aa228fdSmrg * StartRootPtrGrab() -- Bring up the selection box.
6959aa228fdSmrg *
6969aa228fdSmrg */
6979aa228fdSmrgstatic void
6989aa228fdSmrgStartRootPtrGrab(int new, 	/* do we cretate a new scale instance? */
6999aa228fdSmrg		 hlPtr data)	/* highligh data */
7009aa228fdSmrg{
7019aa228fdSmrg  Window    rootR, childR;
7029aa228fdSmrg  int       rootX, rootY, winX, winY;
7039aa228fdSmrg  unsigned  int mask;
7049aa228fdSmrg  hlPtr hlData;
7059aa228fdSmrg  XtGrabPointer
7069aa228fdSmrg    (root, False,
7079aa228fdSmrg     PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
7089aa228fdSmrg     GrabModeAsync, GrabModeAsync, None, ulAngle, CurrentTime);
7099aa228fdSmrg  XQueryPointer(dpy, DefaultRootWindow(dpy), &rootR, &childR,
7109aa228fdSmrg		&rootX, &rootY, &winX, &winY, &mask);
7119aa228fdSmrg  if (new) {
7129aa228fdSmrg    numXmags++;
7139aa228fdSmrg    hlData = (hlPtr)XtMalloc(sizeof(hlStruct));
7149aa228fdSmrg  }
7159aa228fdSmrg  else hlData = data;
7169aa228fdSmrg  hlData->newScale   = new;
7179aa228fdSmrg  hlData->selectMode = drag;
7189aa228fdSmrg  hlData->x          = rootX;
7199aa228fdSmrg  hlData->y          = rootY;
7209aa228fdSmrg  hlData->gc         = selectGC;
7219aa228fdSmrg  hlData->width      = srcWidth;
7229aa228fdSmrg  hlData->height     = srcHeight;
7239aa228fdSmrg  XtAddRawEventHandler
7249aa228fdSmrg    (root, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
7259aa228fdSmrg     True, DragEH, (XtPointer)hlData);
7269aa228fdSmrg  (void) XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)hlData);
7279aa228fdSmrg}
7289aa228fdSmrg
7299aa228fdSmrg
7309aa228fdSmrg
7319aa228fdSmrg/*
7329aa228fdSmrg * CreateRoot() -- Create a root window widget. If the user specified x and y
7339aa228fdSmrg *                 in his source geometry then use this to directly get the
7349aa228fdSmrg *                 image.
7359aa228fdSmrg */
7369aa228fdSmrgstatic void
7379aa228fdSmrgCreateRoot(void)
7389aa228fdSmrg{
7399aa228fdSmrg  hlPtr data;
7409aa228fdSmrg  root = XtCreateWidget("root", rootWindowWidgetClass, toplevel, NULL, 0);
7419aa228fdSmrg  XtRealizeWidget(root);
7429aa228fdSmrg  if (XValue & srcStat && YValue &srcStat) {
7439aa228fdSmrg    numXmags = 1;
7449aa228fdSmrg    data = (hlPtr)XtMalloc(sizeof(hlStruct));
7459aa228fdSmrg    data = data;
7469aa228fdSmrg    data->newScale   = True;
7479aa228fdSmrg    data->selectMode = drag;
7489aa228fdSmrg    data->x          = srcX;
7499aa228fdSmrg    data->y          = srcY;
7509aa228fdSmrg    data->gc         = selectGC;
7519aa228fdSmrg    data->width      = srcWidth;
7529aa228fdSmrg    data->height     = srcHeight;
7539aa228fdSmrg    GetImageAndAttributes(RootWindow(dpy, scr), srcX, srcY, srcWidth,
7549aa228fdSmrg			  srcHeight, data);
7559aa228fdSmrg    PopupNewScale(data);
7569aa228fdSmrg    return;
7579aa228fdSmrg  }
7589aa228fdSmrg}
7599aa228fdSmrg
7609aa228fdSmrg
7619aa228fdSmrg/*
7629aa228fdSmrg * GetImageAndAttributes() -- Get the image bits from the screen.
7639aa228fdSmrg *               We will also determin here the colormap, depth, and
7649aa228fdSmrg *               visual to be used for the magnification image.
7659aa228fdSmrg */
7669aa228fdSmrgstatic void
7679aa228fdSmrgGetImageAndAttributes(Window w, int x, int y, int width, int height,
7689aa228fdSmrg		      hlPtr data)
7699aa228fdSmrg{
77083d7c197Smrg    /* get parameters of window being magnified */
77183d7c197Smrg    XGetWindowAttributes(dpy, w, &data->win_info);
77283d7c197Smrg
77383d7c197Smrg    if (data->win_info.depth == DefaultDepth(dpy, scr)) {
77483d7c197Smrg	/* avoid off screen pixels */
77583d7c197Smrg	if (x < 0)
77683d7c197Smrg	    x = 0;
77783d7c197Smrg	if (y < 0)
77883d7c197Smrg	    y = 0;
77983d7c197Smrg	if (x + width > DisplayWidth(dpy,scr))
78083d7c197Smrg	    x = DisplayWidth(dpy,scr) - width;
78183d7c197Smrg	if (y + height > DisplayHeight(dpy,scr))
78283d7c197Smrg	    y = DisplayHeight(dpy,scr) - height;
78383d7c197Smrg	data->x = x; data->y = y;
78483d7c197Smrg	/* get image pixels */
78583d7c197Smrg	data->image = XGetImage (dpy,
78683d7c197Smrg				 RootWindow(dpy, scr),
78783d7c197Smrg				 x, y,
78883d7c197Smrg				 width, height,
78983d7c197Smrg				 AllPlanes, ZPixmap);
79083d7c197Smrg    }
79183d7c197Smrg    else {
79283d7c197Smrg	int	t0, t1;
79383d7c197Smrg	int	x0, x1, y0, y1;
79483d7c197Smrg	int	xInWin, yInWin;
79583d7c197Smrg	Window	childWin;
79683d7c197Smrg
79783d7c197Smrg	XTranslateCoordinates(dpy, DefaultRootWindow(dpy), w, x, y,
79883d7c197Smrg			      &xInWin, &yInWin, &childWin);
79983d7c197Smrg
80083d7c197Smrg	/* Avoid off screen pixels. Assume this routine is not
80183d7c197Smrg	 * called for totally offscreen windows. */
80283d7c197Smrg	x0 = max(x, 0);
80383d7c197Smrg	y0 = max(y, 0);
80483d7c197Smrg	x1 = min(DisplayWidth(dpy, scr),
80583d7c197Smrg		 min(x0 + width, x0 + (data->win_info.width - xInWin)));
80683d7c197Smrg	y1 = min(DisplayHeight(dpy, scr),
80783d7c197Smrg		 min(y0 + height, y0 + (data->win_info.height - yInWin)));
80883d7c197Smrg
80983d7c197Smrg	/* Try to use up to width x height pixels */
81083d7c197Smrg	if (x1 - x0 < width) {
81183d7c197Smrg	    t0 = x0;
81283d7c197Smrg	    t1 = max(0, x - xInWin + data->win_info.width -
81383d7c197Smrg		     DisplayWidth(dpy, scr));
81483d7c197Smrg	    x0 = max(0, x1 - min(width, data->win_info.width - t1));
81583d7c197Smrg	    xInWin -= t0 - x0;
81683d7c197Smrg	}
81783d7c197Smrg	if (y1 - y0 < height) {
81883d7c197Smrg	    t0 = y0;
81983d7c197Smrg	    t1 = max(0, y - yInWin + data->win_info.height -
82083d7c197Smrg		     DisplayHeight(dpy, scr));
82183d7c197Smrg	    y0 = max(0, y1 - min(height, data->win_info.height - t1));
82283d7c197Smrg	    yInWin -= t0 - y0;
82383d7c197Smrg	}
82483d7c197Smrg
82583d7c197Smrg	data->x = x0;
82683d7c197Smrg	data->y = y0;
82783d7c197Smrg	data->width = x1 - x0;
82883d7c197Smrg	data->height = y1 - y0;
82983d7c197Smrg
83083d7c197Smrg	data->image = XGetImage (dpy,
83183d7c197Smrg				 w,
83283d7c197Smrg				 xInWin, yInWin,
83383d7c197Smrg				 data->width, data->height,
83483d7c197Smrg				 AllPlanes, ZPixmap);
83583d7c197Smrg
83683d7c197Smrg    }
8379aa228fdSmrg}
8389aa228fdSmrg
8399aa228fdSmrg
8409aa228fdSmrg
8419aa228fdSmrg/*
8429aa228fdSmrg * Get_XColors() Get the XColors of all pixels in image - returns # of colors
8439aa228fdSmrg *               This function was taken from xwd (thanks Bob...)
8449aa228fdSmrg */
8459aa228fdSmrg#define lowbit(x) ((x) & (~(x) + 1))
8469aa228fdSmrgstatic int
8479aa228fdSmrgGet_XColors(XWindowAttributes *win_info, XColor **colors)
8489aa228fdSmrg{
8499aa228fdSmrg    int i, ncolors;
8509aa228fdSmrg
8519aa228fdSmrg    if (!win_info->colormap)
8529aa228fdSmrg        return(0);
8539aa228fdSmrg
8549aa228fdSmrg    ncolors = win_info->visual->map_entries;
8559aa228fdSmrg    if (!(*colors = (XColor *) XtMalloc (sizeof(XColor) * ncolors)))
8569aa228fdSmrg      XtError("Out of memory!");
8579aa228fdSmrg
8589aa228fdSmrg    if (win_info->visual->class == DirectColor ||
8599aa228fdSmrg        win_info->visual->class == TrueColor) {
8609aa228fdSmrg        Pixel red, green, blue, red1, green1, blue1;
8619aa228fdSmrg
8629aa228fdSmrg        red = green = blue = 0;
8639aa228fdSmrg        red1 = lowbit(win_info->visual->red_mask);
8649aa228fdSmrg        green1 = lowbit(win_info->visual->green_mask);
8659aa228fdSmrg        blue1 = lowbit(win_info->visual->blue_mask);
8669aa228fdSmrg        for (i=0; i<ncolors; i++) {
8679aa228fdSmrg          (*colors)[i].pixel = red|green|blue;
8689aa228fdSmrg          (*colors)[i].pad = 0;
8699aa228fdSmrg          red += red1;
8709aa228fdSmrg          if (red > win_info->visual->red_mask)
8719aa228fdSmrg            red = 0;
8729aa228fdSmrg          green += green1;
8739aa228fdSmrg          if (green > win_info->visual->green_mask)
8749aa228fdSmrg            green = 0;
8759aa228fdSmrg          blue += blue1;
8769aa228fdSmrg          if (blue > win_info->visual->blue_mask)
8779aa228fdSmrg            blue = 0;
8789aa228fdSmrg        }
8799aa228fdSmrg    } else {
8809aa228fdSmrg        for (i=0; i<ncolors; i++) {
8819aa228fdSmrg          (*colors)[i].pixel = i;
8829aa228fdSmrg          (*colors)[i].pad = 0;
8839aa228fdSmrg        }
8849aa228fdSmrg    }
8859aa228fdSmrg
8869aa228fdSmrg    XQueryColors(dpy, win_info->colormap, *colors, ncolors);
8879aa228fdSmrg
8889aa228fdSmrg    return(ncolors);
8899aa228fdSmrg}
8909aa228fdSmrg
8919aa228fdSmrg
8929aa228fdSmrg
8939aa228fdSmrg#define Intensity(cptr) (3.0*cptr->red+0.59*cptr->green+0.11*cptr->blue)
8949aa228fdSmrg
8959aa228fdSmrg/*
8969aa228fdSmrg * GetMaxIntensity() -- Find the maximum intensity pixel value for a colormap.
8979aa228fdSmrg */
8989aa228fdSmrgstatic Pixel
8999aa228fdSmrgGetMaxIntensity(hlPtr data)
9009aa228fdSmrg{
9019aa228fdSmrg  XColor *colors = NULL, *mptr, *tptr;
9029aa228fdSmrg  int i, ncolors;
9039aa228fdSmrg
9049aa228fdSmrg  if (data->win_info.colormap == DefaultColormap(dpy, scr))
9059aa228fdSmrg    return WhitePixel(dpy, scr);
9069aa228fdSmrg  ncolors = Get_XColors(&data->win_info, &colors);
9079aa228fdSmrg  mptr = tptr = colors; tptr++;
9089aa228fdSmrg  for (i=1; i<ncolors; i++) {
9099aa228fdSmrg    if ((int)Intensity(mptr) < (int)Intensity(tptr))
9109aa228fdSmrg      mptr = tptr;
9119aa228fdSmrg    tptr++;
9129aa228fdSmrg  }
9139aa228fdSmrg  /* Null pointer protection */
9149aa228fdSmrg  if(mptr)
9159aa228fdSmrg    return mptr->pixel;
9169aa228fdSmrg  else
9179aa228fdSmrg    return WhitePixel(dpy, scr);
9189aa228fdSmrg}
9199aa228fdSmrg
9209aa228fdSmrg/*
9219aa228fdSmrg * GetMinIntensity() -- Find the minimum intensity pixel value for a colormap.
9229aa228fdSmrg */
9239aa228fdSmrgstatic Pixel
9249aa228fdSmrgGetMinIntensity(hlPtr data)
9259aa228fdSmrg{
9269aa228fdSmrg  XColor *colors = NULL, *mptr, *tptr;
9279aa228fdSmrg  int i, ncolors;
9289aa228fdSmrg
9299aa228fdSmrg  if (data->win_info.colormap == DefaultColormap(dpy, scr))
9309aa228fdSmrg    return BlackPixel(dpy, scr);
9319aa228fdSmrg  ncolors = Get_XColors(&data->win_info, &colors);
9329aa228fdSmrg  mptr = tptr = colors; tptr++;
9339aa228fdSmrg  for (i=1; i<ncolors; i++)  {
9349aa228fdSmrg    if ((int)Intensity(mptr) > (int)Intensity(tptr))
9359aa228fdSmrg      mptr = tptr;
9369aa228fdSmrg    tptr++;
9379aa228fdSmrg  }
9389aa228fdSmrg  /* Null pointer protection */
9399aa228fdSmrg  if(mptr)
9409aa228fdSmrg    return mptr->pixel;
9419aa228fdSmrg  else
9429aa228fdSmrg    return BlackPixel(dpy, scr);
9439aa228fdSmrg}
9449aa228fdSmrg
9459aa228fdSmrg
9469aa228fdSmrg
9479aa228fdSmrg
9489aa228fdSmrgstatic Widget pane1, pane2, pane3, cclose, replace, new, select_w, paste;
9499aa228fdSmrg
9509aa228fdSmrg/*
9519aa228fdSmrg * PopupNewScale() -- Create and popup a new scale composite.
9529aa228fdSmrg */
9539aa228fdSmrgstatic void
9549aa228fdSmrgPopupNewScale(hlPtr data)
9559aa228fdSmrg{
9569aa228fdSmrg  Arg warg;
9579aa228fdSmrg
9589aa228fdSmrg  data->scaleShell =
9599aa228fdSmrg    XtVaCreatePopupShell("xmag", topLevelShellWidgetClass, toplevel,
9609aa228fdSmrg			 XtNgeometry, (XtArgVal)options.geometry,
9619aa228fdSmrg			 XtNtitle, (XtArgVal)options.title,
9629aa228fdSmrg			 NULL);
9639aa228fdSmrg  pane1 = XtCreateManagedWidget("pane1", panedWidgetClass, data->scaleShell,
9649aa228fdSmrg				(Arg *) NULL, 0);
9659aa228fdSmrg  pane2 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
9669aa228fdSmrg				(Arg *) NULL, 0);
9679aa228fdSmrg  cclose = XtCreateManagedWidget("close", commandWidgetClass, pane2,
9689aa228fdSmrg				 (Arg *) NULL, 0);
9699aa228fdSmrg  XtAddCallback(cclose, XtNcallback, CloseCB, (XtPointer)data->scaleShell);
9709aa228fdSmrg  replace = XtCreateManagedWidget("replace", commandWidgetClass, pane2,
9719aa228fdSmrg				  (Arg *) NULL, 0);
9729aa228fdSmrg  XtAddCallback(replace, XtNcallback, ReplaceCB, (XtPointer)data);
9739aa228fdSmrg  new = XtCreateManagedWidget("new", commandWidgetClass, pane2,
9749aa228fdSmrg			      (Arg *) NULL, 0);
9759aa228fdSmrg  XtAddCallback(new, XtNcallback, NewCB, (XtPointer)NULL);
9769aa228fdSmrg  select_w = XtCreateManagedWidget("select", commandWidgetClass, pane2,
9779aa228fdSmrg			      (Arg *) NULL, 0);
9789aa228fdSmrg  XtAddCallback(select_w, XtNcallback, SelectCB, (XtPointer)data);
9799aa228fdSmrg  paste = XtCreateManagedWidget("paste", commandWidgetClass, pane2,
9809aa228fdSmrg			      (Arg *) NULL, 0);
9819aa228fdSmrg  XtAddCallback(paste, XtNcallback, PasteCB, (XtPointer)data);
9829aa228fdSmrg  (void) XtCreateManagedWidget("helpLabel", labelWidgetClass, pane2,
9839aa228fdSmrg			       (Arg *) NULL, 0);
9849aa228fdSmrg  pane3 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
9859aa228fdSmrg				(Arg *) NULL, 0);
9869aa228fdSmrg  data->scaleInstance =
9879aa228fdSmrg    XtVaCreateManagedWidget("scale", scaleWidgetClass,
9889aa228fdSmrg			    pane3,
9899aa228fdSmrg			    XtNvisual, (XtArgVal)data->win_info.visual,
9909aa228fdSmrg			    XtNcolormap, (XtArgVal)data->win_info.colormap,
9919aa228fdSmrg			    XtNdepth, (XtArgVal)data->win_info.depth,
9929aa228fdSmrg			    XtNscaleX, (XtArgVal)options.mag,
9939aa228fdSmrg			    XtNscaleY, (XtArgVal)options.mag,
9949aa228fdSmrg			    NULL);
9959aa228fdSmrg  SWSetImage(data->scaleInstance, data->image);
9969aa228fdSmrg  XtOverrideTranslations
9979aa228fdSmrg    (data->scaleShell,
9989aa228fdSmrg     XtParseTranslationTable ("<Message>WM_PROTOCOLS: close()"));
9999aa228fdSmrg  XtSetArg(warg, XtNuserData, data);
10009aa228fdSmrg  XtSetValues(data->scaleInstance, &warg, 1);
10019aa228fdSmrg  data->pixShell =
10029aa228fdSmrg    XtVaCreatePopupShell("pixShell", overrideShellWidgetClass,
10039aa228fdSmrg			 toplevel,
10049aa228fdSmrg			 XtNvisual, (XtArgVal)data->win_info.visual,
10059aa228fdSmrg			 XtNcolormap, (XtArgVal)data->win_info.colormap,
10069aa228fdSmrg			 XtNdepth, (XtArgVal)data->win_info.depth,
10079aa228fdSmrg			 XtNborderWidth, (XtPointer)0,
10089aa228fdSmrg			 NULL);
10099aa228fdSmrg  data->pixLabel =
10109aa228fdSmrg    XtVaCreateManagedWidget("pixLabel", labelWidgetClass,
10119aa228fdSmrg			    data->pixShell,
10129aa228fdSmrg			    XtNforeground, (XtPointer)GetMaxIntensity(data),
10139aa228fdSmrg			    XtNbackground, (XtPointer)GetMinIntensity(data),
10149aa228fdSmrg			    XtNborderWidth, (XtPointer)0,
10159aa228fdSmrg			    NULL);
10169aa228fdSmrg  XtInstallAllAccelerators(pane1, pane1);	/* install accelerators */
10179aa228fdSmrg  if (data->newScale) {
10189aa228fdSmrg    XtPopup(data->scaleShell, XtGrabNone);
10199aa228fdSmrg    (void) XSetWMProtocols	/* ICCCM delete window */
10209aa228fdSmrg      (dpy, XtWindow(data->scaleShell), &wm_delete_window, 1);
10219aa228fdSmrg  }
10229aa228fdSmrg  if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
10239aa228fdSmrg    data->cmapWinList[0] = data->scaleShell;
10249aa228fdSmrg    data->cmapWinList[1] = data->scaleInstance;
10259aa228fdSmrg    XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
10269aa228fdSmrg  }
10279aa228fdSmrg}
10289aa228fdSmrg
10299aa228fdSmrg
10309aa228fdSmrg
10319aa228fdSmrg/*
10329aa228fdSmrg * RedoOldScale() -- If the visual, depth, or colormap has changed, unrealize
10339aa228fdSmrg *                   the scale widget and change its colormap/depth/visual.
10349aa228fdSmrg *                   Then re-realize it.  Also do this for the pixel display
10359aa228fdSmrg *                   widget.
10369aa228fdSmrg */
10379aa228fdSmrgstatic void
10389aa228fdSmrgRedoOldScale(hlPtr data)
10399aa228fdSmrg{
10409aa228fdSmrg  Arg wargs[3];
10419aa228fdSmrg  int n;
10429aa228fdSmrg  Visual *oldVis;
10439aa228fdSmrg  int oldDepth;
10449aa228fdSmrg  Colormap oldCmap;
10459aa228fdSmrg
10469aa228fdSmrg  n=0;
10479aa228fdSmrg  XtSetArg(wargs[n], XtNvisual, &oldVis); n++;
10489aa228fdSmrg  XtSetArg(wargs[n], XtNdepth, &oldDepth); n++;
10499aa228fdSmrg  XtSetArg(wargs[n], XtNcolormap, &oldCmap); n++;
10509aa228fdSmrg  XtGetValues(data->scaleInstance, wargs, n);
10519aa228fdSmrg  if (oldVis == data->win_info.visual && oldDepth == data->win_info.depth
10529aa228fdSmrg      && oldCmap == data->win_info.colormap) {
10539aa228fdSmrg    SWSetImage(data->scaleInstance, data->image);
10549aa228fdSmrg    return;
10559aa228fdSmrg  }
10569aa228fdSmrg  /* get width and height, save and reuse them */
10579aa228fdSmrg  XtUnmanageChild(data->scaleInstance);
10589aa228fdSmrg  XtUnrealizeWidget(data->scaleInstance);
10599aa228fdSmrg  n=0;
10609aa228fdSmrg  XtSetArg(wargs[n], XtNcolormap, data->win_info.colormap); n++;
10619aa228fdSmrg  XtSetArg(wargs[n], XtNdepth, data->win_info.depth); n++;
10629aa228fdSmrg  XtSetArg(wargs[n], XtNvisual, data->win_info.visual); n++;
10639aa228fdSmrg  XtSetValues(data->scaleInstance, wargs, n);
10649aa228fdSmrg  n=0;
10659aa228fdSmrg  XtSetArg(wargs[n], XtNforeground, GetMaxIntensity(data)); n++;
10669aa228fdSmrg  XtSetArg(wargs[n], XtNbackground, GetMinIntensity(data)); n++;
10679aa228fdSmrg  XtSetValues(data->pixLabel, wargs, n);
10689aa228fdSmrg  SWSetImage(data->scaleInstance, data->image);
10699aa228fdSmrg  XtRealizeWidget(data->scaleInstance);
10709aa228fdSmrg  XtManageChild(data->scaleInstance);
10719aa228fdSmrg}
10729aa228fdSmrg
10739aa228fdSmrg
10749aa228fdSmrg
10759aa228fdSmrg/*
10769aa228fdSmrg * InitCursors() -- Create our cursors for area selection.
10779aa228fdSmrg */
10789aa228fdSmrgstatic void
10799aa228fdSmrgInitCursors(void)
10809aa228fdSmrg{
10819aa228fdSmrg  ulAngle = XCreateFontCursor(dpy, XC_ul_angle);
10829aa228fdSmrg  urAngle = XCreateFontCursor(dpy, XC_ur_angle);
10839aa228fdSmrg  lrAngle = XCreateFontCursor(dpy, XC_lr_angle);
10849aa228fdSmrg  llAngle = XCreateFontCursor(dpy, XC_ll_angle);
10859aa228fdSmrg}
10869aa228fdSmrg
10879aa228fdSmrg
10889aa228fdSmrg
10899aa228fdSmrg/*
10909aa228fdSmrg * ParseSourceGeom() -- Determin dimensions of area to magnify from resources.
10919aa228fdSmrg */
10929aa228fdSmrgstatic void
10939aa228fdSmrgParseSourceGeom(void)
10949aa228fdSmrg{
10959aa228fdSmrg				/* source */
10969aa228fdSmrg  srcStat =
10979aa228fdSmrg    XParseGeometry(options.source, &srcX, &srcY, &srcWidth, &srcHeight);
10989aa228fdSmrg  if (!srcWidth) srcWidth = SRCWIDTH;
10999aa228fdSmrg  if (!srcHeight) srcHeight = SRCHEIGHT;
11009aa228fdSmrg  if (XNegative & srcStat) srcX = DisplayWidth(dpy, scr) + srcX - srcWidth;
11019aa228fdSmrg  if (YNegative & srcStat) srcY = DisplayHeight(dpy, scr) + srcY - srcHeight;
11029aa228fdSmrg				/* mag */
11039aa228fdSmrg}
11049aa228fdSmrg
11059aa228fdSmrg
11069aa228fdSmrg
11079aa228fdSmrg/*
11089aa228fdSmrg * Main program.
11099aa228fdSmrg */
11109aa228fdSmrgint
11119aa228fdSmrgmain(int argc, char *argv[])
11129aa228fdSmrg{
11139aa228fdSmrg  XSetErrorHandler(Error);
11149aa228fdSmrg
11159aa228fdSmrg				/* SUPPRESS 594 */
11169aa228fdSmrg  toplevel = XtAppInitialize(&app, "Xmag", optionDesc, XtNumber(optionDesc),
11179aa228fdSmrg			     &argc, argv, NULL,
11189aa228fdSmrg			     NULL, 0);
11199aa228fdSmrg
11209aa228fdSmrg  dpy = XtDisplay(toplevel);
11219aa228fdSmrg  scr = DefaultScreen(dpy);
11229aa228fdSmrg  XtGetApplicationResources(toplevel, (XtPointer) &options, resources,
11239aa228fdSmrg			    XtNumber(resources), NULL, 0);
11249aa228fdSmrg  if (argc != 1) {
11259aa228fdSmrg    fprintf (stderr,
11269aa228fdSmrg	    "usage:  xmag [-source geom] [-mag magfactor] [-toolkitoption]\n");
11279aa228fdSmrg    exit(1);
11289aa228fdSmrg  }
11299aa228fdSmrg
11309aa228fdSmrg
11319aa228fdSmrg  ParseSourceGeom();
11329aa228fdSmrg  XtAppAddActions(app, actions_table, XtNumber(actions_table));
11339aa228fdSmrg  InitCursors();
11349aa228fdSmrg  SetupGC();
11359aa228fdSmrg  CreateRoot();
11369aa228fdSmrg  if (!(XValue & srcStat && YValue & srcStat))
11379aa228fdSmrg    StartRootPtrGrab(True, (hlPtr)NULL);
11389aa228fdSmrg  wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
11399aa228fdSmrg  XtAppMainLoop(app);
11409aa228fdSmrg  exit(0);
11419aa228fdSmrg}
1142