19aa228fdSmrg/* 29aa228fdSmrg 39aa228fdSmrgCopyright 1991, 1998 The Open Group 49aa228fdSmrg 59aa228fdSmrgPermission to use, copy, modify, distribute, and sell this software and its 69aa228fdSmrgdocumentation for any purpose is hereby granted without fee, provided that 79aa228fdSmrgthe above copyright notice appear in all copies and that both that 89aa228fdSmrgcopyright notice and this permission notice appear in supporting 99aa228fdSmrgdocumentation. 109aa228fdSmrg 119aa228fdSmrgThe above copyright notice and this permission notice shall be included 129aa228fdSmrgin all copies or substantial portions of the Software. 139aa228fdSmrg 149aa228fdSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 159aa228fdSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 169aa228fdSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 179aa228fdSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 189aa228fdSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 199aa228fdSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 209aa228fdSmrgOTHER DEALINGS IN THE SOFTWARE. 219aa228fdSmrg 229aa228fdSmrgExcept as contained in this notice, the name of The Open Group shall 239aa228fdSmrgnot be used in advertising or otherwise to promote the sale, use or 249aa228fdSmrgother dealings in this Software without prior written authorization 259aa228fdSmrgfrom The Open Group. 269aa228fdSmrg 279aa228fdSmrg*/ 289aa228fdSmrg 2915106172Smrg#ifdef HAVE_CONFIG_H 309aa228fdSmrg#include "config.h" 3115106172Smrg#endif 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 */ 900c7e83b2Smrgtypedef enum { drag, resize, done } hlMode; 919aa228fdSmrg 929aa228fdSmrg/* highlight data structure */ 930c7e83b2Smrgtypedef struct { 949aa228fdSmrg Boolean newScale; 959aa228fdSmrg hlMode selectMode; 969aa228fdSmrg GC gc; 970c7e83b2Smrg 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; 1110c7e83b2Smrgstatic 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}, 1750c7e83b2Smrg 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/* 2010c7e83b2Smrg * Error() -- Error handler: Catch a bad match in magnifying an 2029aa228fdSmrg * area that contains bits of different depths. 2039aa228fdSmrg */ 2040c7e83b2Smrgstatic int 205e2f3d188SmrgError(Display *display, XErrorEvent *err) 2069aa228fdSmrg{ 207e2f3d188Smrg (void) XmuPrintDefaultErrorMessage (display, err, stderr); 2089aa228fdSmrg return 0; 2099aa228fdSmrg} 2109aa228fdSmrg 2119aa228fdSmrg 2129aa228fdSmrg/* 2139aa228fdSmrg * CloseAP() -- Close this dialog. If its the last one exit the program. 2140c7e83b2Smrg * 2159aa228fdSmrg */ 216e2f3d188Smrgstatic void 217e2f3d188SmrgCloseAP(Widget w, XEvent *event, 218e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 2199aa228fdSmrg{ 2209aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2219aa228fdSmrg if (!--numXmags) exit(0); 2229aa228fdSmrg if (event->type != ClientMessage) { 2239aa228fdSmrg n = 0; /* get user data */ 2249aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2250c7e83b2Smrg XtGetValues(w, wargs, n); 2269aa228fdSmrg w = data->scaleShell; 2279aa228fdSmrg } 2289aa228fdSmrg XtPopdown(w); 2299aa228fdSmrg XtDestroyWidget(w); 2309aa228fdSmrg} 2319aa228fdSmrg 2329aa228fdSmrg 2339aa228fdSmrg 2349aa228fdSmrg/* 2359aa228fdSmrg * SetCmapPropsAP() -- Put the scale widget first in WM_COLORMAP_WINDOWS 2360c7e83b2Smrg * 2379aa228fdSmrg */ 238e2f3d188Smrgstatic void 239e2f3d188SmrgSetCmapPropsAP(Widget w, _X_UNUSED XEvent *event, 240e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 2419aa228fdSmrg{ 2429aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2439aa228fdSmrg n = 0; /* get user data */ 2449aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2459aa228fdSmrg XtGetValues(w, wargs, n); 2469aa228fdSmrg if (data->win_info.colormap != DefaultColormap(dpy, scr)) { 2479aa228fdSmrg data->cmapWinList[0] = data->scaleInstance; 2489aa228fdSmrg data->cmapWinList[1] = data->scaleShell; 2499aa228fdSmrg XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2); 2509aa228fdSmrg } 2519aa228fdSmrg} 2529aa228fdSmrg 2539aa228fdSmrg 2549aa228fdSmrg 2559aa228fdSmrg/* 2569aa228fdSmrg * UnsetCmapPropsAP() -- Put the shell first in WM_COLORMAP_WINDOWS 2570c7e83b2Smrg * 2589aa228fdSmrg */ 259e2f3d188Smrgstatic void 260e2f3d188SmrgUnsetCmapPropsAP(Widget w, _X_UNUSED XEvent *event, 261e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 2629aa228fdSmrg{ 2639aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2649aa228fdSmrg n = 0; /* get user data */ 2659aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2669aa228fdSmrg XtGetValues(w, wargs, n); 2679aa228fdSmrg if (data->win_info.colormap != DefaultColormap(dpy, scr)) { 2689aa228fdSmrg data->cmapWinList[0] = data->scaleShell; 2699aa228fdSmrg data->cmapWinList[1] = data->scaleInstance; 2709aa228fdSmrg XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2); 2719aa228fdSmrg } 2729aa228fdSmrg} 2739aa228fdSmrg 2749aa228fdSmrg 2759aa228fdSmrg 2769aa228fdSmrg/* 2779aa228fdSmrg * NewAP() -- Create an additional xmag dialog. THIS IS A COPY OF NewEH 2789aa228fdSmrg * FIND A BETTER WAY.... 2799aa228fdSmrg */ 280e2f3d188Smrgstatic void 281e2f3d188SmrgNewAP(_X_UNUSED Widget w, _X_UNUSED XEvent *event, 282e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 2839aa228fdSmrg{ 2849aa228fdSmrg StartRootPtrGrab(True, NULL); 2859aa228fdSmrg} 2869aa228fdSmrg 2879aa228fdSmrg 2889aa228fdSmrg 2899aa228fdSmrg/* 2909aa228fdSmrg * ReplaceAP() -- Replace this particular xmag dialog. 2919aa228fdSmrg */ 292e2f3d188Smrgstatic void 293e2f3d188SmrgReplaceAP(Widget w, _X_UNUSED XEvent *event, 294e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 2959aa228fdSmrg{ 2969aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2979aa228fdSmrg n = 0; /* get user data */ 2989aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2990c7e83b2Smrg XtGetValues(w, wargs, n); 3009aa228fdSmrg StartRootPtrGrab(False, data); 3019aa228fdSmrg} 3029aa228fdSmrg 3039aa228fdSmrg 3049aa228fdSmrg 3059aa228fdSmrg/* 3069aa228fdSmrg * PopupPixelAP() -- Show pixel information. 3079aa228fdSmrg */ 308e2f3d188Smrgstatic void 309e2f3d188SmrgPopupPixelAP(Widget w, XEvent *event, 310e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 3119aa228fdSmrg{ 3129aa228fdSmrg Position scale_x, scale_y; 3139aa228fdSmrg Dimension scale_height; 3149aa228fdSmrg Position label_x, label_y; 3159aa228fdSmrg Dimension label_height; 3169aa228fdSmrg int n; 3179aa228fdSmrg Arg wargs[3]; 3189aa228fdSmrg hlPtr data; 3199aa228fdSmrg 3209aa228fdSmrg n = 0; /* get user data */ 3219aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 3229aa228fdSmrg XtGetValues(w, wargs, n); 3239aa228fdSmrg 3249aa228fdSmrg n = 0; 3259aa228fdSmrg XtSetArg(wargs[n], XtNheight, &scale_height); n++; 3269aa228fdSmrg XtGetValues(w, wargs, n); 3279aa228fdSmrg XtTranslateCoords(w, -1, -1, &scale_x, &scale_y); 3280c7e83b2Smrg 3299aa228fdSmrg XtRealizeWidget(data->pixShell); /* to get the right height */ 3309aa228fdSmrg 3319aa228fdSmrg n = 0; 3329aa228fdSmrg XtSetArg(wargs[n], XtNheight, &label_height); n++; 3339aa228fdSmrg XtGetValues(data->pixShell, wargs, n); 3340c7e83b2Smrg 3359aa228fdSmrg if ((double) event->xbutton.y / (double) scale_height > 0.5) { 3369aa228fdSmrg label_x = scale_x; 3379aa228fdSmrg label_y = scale_y; 3389aa228fdSmrg } 3399aa228fdSmrg else { 3409aa228fdSmrg label_x = scale_x; 3419aa228fdSmrg label_y = scale_y + scale_height - label_height; 3429aa228fdSmrg } 3439aa228fdSmrg 3449aa228fdSmrg n = 0; 3459aa228fdSmrg XtSetArg(wargs[n], XtNx, label_x); n++; 3469aa228fdSmrg XtSetArg(wargs[n], XtNy, label_y); n++; 3479aa228fdSmrg XtSetValues(data->pixShell, wargs, n); 34883d7c197Smrg 34983d7c197Smrg UpdatePixelAP(w, event, NULL, NULL); 3509aa228fdSmrg} 3519aa228fdSmrg 3529aa228fdSmrg 3539aa228fdSmrg 3549aa228fdSmrg/* 3559aa228fdSmrg * UpdatePixelAP() -- Update pixel information. 3569aa228fdSmrg */ 357e2f3d188Smrgstatic void 358e2f3d188SmrgUpdatePixelAP(Widget w, XEvent *event, 359e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 3609aa228fdSmrg{ 3619aa228fdSmrg Position x, y; 3629aa228fdSmrg Pixel pixel; 3639aa228fdSmrg XColor color; 3649aa228fdSmrg int n; 3659aa228fdSmrg Arg wargs[3]; 3669aa228fdSmrg char string[80]; 3679aa228fdSmrg hlPtr data; 3689aa228fdSmrg 3699aa228fdSmrg n = 0; 3709aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 3719aa228fdSmrg XtGetValues(w, wargs, n); 3729aa228fdSmrg 3739aa228fdSmrg if (SWGetImagePixel(w, event->xbutton.x, event->xbutton.y, &x, &y, &pixel)) 3749aa228fdSmrg XtPopdown(data->pixShell); 3759aa228fdSmrg else { 3769aa228fdSmrg color.pixel = pixel; 3779aa228fdSmrg XQueryColor(dpy, data->win_info.colormap, &color); 3780c7e83b2Smrg snprintf(string, sizeof(string), 3790c7e83b2Smrg "Pixel %ld at (%d,%d) colored (%x,%x,%x).", 3800c7e83b2Smrg pixel, x + data->x, y + data->y, 3810c7e83b2Smrg color.red, color.green, color.blue); 3829aa228fdSmrg n = 0; 3830c7e83b2Smrg XtSetArg(wargs[n], XtNlabel, string); n++; 3849aa228fdSmrg XtSetValues(data->pixLabel, wargs, n); 3859aa228fdSmrg XtPopup(data->pixShell, XtGrabNone); 3869aa228fdSmrg } 3879aa228fdSmrg} 3889aa228fdSmrg 3899aa228fdSmrg 3909aa228fdSmrg 3919aa228fdSmrg/* 3929aa228fdSmrg * PopdownPixelAP() -- Remove pixel info. 3939aa228fdSmrg */ 394e2f3d188Smrgstatic void 395e2f3d188SmrgPopdownPixelAP(Widget w, _X_UNUSED XEvent *event, 396e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 3979aa228fdSmrg{ 3989aa228fdSmrg int n; 3999aa228fdSmrg Arg wargs[3]; 4009aa228fdSmrg hlPtr data = NULL; 4010c7e83b2Smrg 4029aa228fdSmrg n = 0; 4039aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 4049aa228fdSmrg XtGetValues(w, wargs, n); 4059aa228fdSmrg 4069aa228fdSmrg if (data) 4079aa228fdSmrg XtPopdown(data->pixShell); 4089aa228fdSmrg} 4099aa228fdSmrg 4109aa228fdSmrg 4119aa228fdSmrg 412e2f3d188Smrgstatic void 413e2f3d188SmrgSelectRegionAP(_X_UNUSED Widget w, _X_UNUSED XEvent *event, 414e2f3d188Smrg _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 4150c7e83b2Smrg{ 4160c7e83b2Smrg/***** NOT SURE WHAT TO DO WITH THIS 4179aa228fdSmrg if (app_resources.unmap) 4189aa228fdSmrg XtUnmapWidget(toplevel); 4199aa228fdSmrg Redisplay(XtDisplay(w), RootWindow(XtDisplay(w), 4209aa228fdSmrg DefaultScreen(XtDisplay(w))), 4210c7e83b2Smrg source.width, source.height, 4220c7e83b2Smrg app_resources.freq, app_resources.puls, 4239aa228fdSmrg ul_angle, lr_angle, 4249aa228fdSmrg app_resources.grab); 4259aa228fdSmrg 4269aa228fdSmrg if (app_resources.unmap) 4279aa228fdSmrg XtMapWidget(toplevel); 4289aa228fdSmrg******/ 4299aa228fdSmrg} 4309aa228fdSmrg 4319aa228fdSmrg 4329aa228fdSmrg 4330c7e83b2Smrg/* 4349aa228fdSmrg * CheckPoints() -- Change the cursor for the correct quadrant. 4350c7e83b2Smrg * Make sure the first point is less than the second 4369aa228fdSmrg * for drawing the selection rectangle. 4379aa228fdSmrg * 4389aa228fdSmrg */ 4390c7e83b2Smrgstatic void 4409aa228fdSmrgCheckPoints(Position *x1, Position *x2, Position *y1, Position *y2) 4419aa228fdSmrg{ 4420c7e83b2Smrg Position tmp; 4439aa228fdSmrg Boolean above, left; 4449aa228fdSmrg Cursor newC; 4450c7e83b2Smrg above = (*y2 < *y1); left = (*x2 < *x1); 4469aa228fdSmrg if (above&&left) newC = ulAngle; 4479aa228fdSmrg else if (above&&!left) newC = urAngle; 4489aa228fdSmrg else if (!above&&!left) newC = lrAngle; 4499aa228fdSmrg else newC = llAngle; 4509aa228fdSmrg XChangeActivePointerGrab 4519aa228fdSmrg (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 4529aa228fdSmrg newC, CurrentTime); 4539aa228fdSmrg if (*x2 < *x1) { tmp = *x1; *x1 = *x2; *x2 = tmp; } 4549aa228fdSmrg if (*y2 < *y1) { tmp = *y1; *y1 = *y2; *y2 = tmp; } 4559aa228fdSmrg} 4569aa228fdSmrg 4579aa228fdSmrg 4589aa228fdSmrg 4599aa228fdSmrg/* 4609aa228fdSmrg * HighlightTO() -- Timer to highlight the selection box 4619aa228fdSmrg */ 4629aa228fdSmrgstatic void 463e2f3d188SmrgHighlightTO(XtPointer closure, _X_UNUSED XtIntervalId *id) 4649aa228fdSmrg{ 4659aa228fdSmrg hlPtr data = (hlPtr)closure; 4669aa228fdSmrg XGrabServer(dpy); 4679aa228fdSmrg if (data->selectMode == drag) { 4680c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4699aa228fdSmrg data->x, data->y, data->width, data->height); 4709aa228fdSmrg XFlush(dpy); 4719aa228fdSmrg HLSLEEP; 4720c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4739aa228fdSmrg data->x, data->y, data->width, data->height); 4749aa228fdSmrg } 4750c7e83b2Smrg else if (data->selectMode == resize) { 4769aa228fdSmrg Position x1 = data->homeX, 4779aa228fdSmrg x2 = data->x, 4789aa228fdSmrg y1 = data->homeY, 4799aa228fdSmrg y2 = data->y; 4809aa228fdSmrg CheckPoints(&x1, &x2, &y1, &y2); 4810c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4829aa228fdSmrg x1, y1, x2 - x1, y2 - y1); 4839aa228fdSmrg XFlush(dpy); 4849aa228fdSmrg HLSLEEP; 4850c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4869aa228fdSmrg x1, y1, x2 - x1, y2 - y1); 4879aa228fdSmrg } 4889aa228fdSmrg XUngrabServer(dpy); 4899aa228fdSmrg if (data->selectMode != done) 4909aa228fdSmrg XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)data); 4919aa228fdSmrg} 4929aa228fdSmrg 4939aa228fdSmrg 4949aa228fdSmrg 4959aa228fdSmrg/* 4969aa228fdSmrg * CloseCB() -- Delete this xmag dialog. If its the only one on the screen 4979aa228fdSmrg * then exit. 4989aa228fdSmrg */ 499e2f3d188Smrgstatic void 500e2f3d188SmrgCloseCB(_X_UNUSED Widget w, XtPointer clientData, _X_UNUSED XtPointer callData) 5019aa228fdSmrg{ 5029aa228fdSmrg Widget shell = (Widget)clientData; 5039aa228fdSmrg if (!--numXmags) exit(0); 5049aa228fdSmrg XtPopdown(shell); 5059aa228fdSmrg XtDestroyWidget(shell); 5069aa228fdSmrg} 5079aa228fdSmrg 5089aa228fdSmrg 5099aa228fdSmrg 5109aa228fdSmrg/* 5119aa228fdSmrg * ReplaceCB() -- Replace this particular xmag dialog. 5129aa228fdSmrg */ 513e2f3d188Smrgstatic void 514e2f3d188SmrgReplaceCB(_X_UNUSED Widget w, XtPointer clientData, _X_UNUSED XtPointer callData) 5159aa228fdSmrg{ 5169aa228fdSmrg hlPtr data = (hlPtr)clientData; 5179aa228fdSmrg StartRootPtrGrab(False, data); 5189aa228fdSmrg} 5199aa228fdSmrg 5209aa228fdSmrg 5219aa228fdSmrg 5229aa228fdSmrg/* 5239aa228fdSmrg * NewCB() -- Create an additional xmag dialog. 5249aa228fdSmrg */ 525e2f3d188Smrgstatic void 526e2f3d188SmrgNewCB(_X_UNUSED Widget w, _X_UNUSED XtPointer clientData, _X_UNUSED XtPointer callData) 5279aa228fdSmrg{ 5289aa228fdSmrg StartRootPtrGrab(True, NULL); 5299aa228fdSmrg} 5309aa228fdSmrg 5319aa228fdSmrg 5329aa228fdSmrg 5339aa228fdSmrg/* 5349aa228fdSmrg * SelectCB() -- Own the primary selection. 5359aa228fdSmrg */ 536e2f3d188Smrgstatic void 537e2f3d188SmrgSelectCB(_X_UNUSED Widget w, XtPointer clientData, _X_UNUSED XtPointer callData) 5389aa228fdSmrg{ 5399aa228fdSmrg hlPtr data = (hlPtr)clientData; 5409aa228fdSmrg SWGrabSelection(data->scaleInstance, XtLastTimestampProcessed(dpy)); 5419aa228fdSmrg} 5429aa228fdSmrg 5439aa228fdSmrg 5449aa228fdSmrg 5459aa228fdSmrg/* 546f5087fa3Smrg * PasteCB() -- Paste from the primary selection into xmag. 5479aa228fdSmrg */ 548e2f3d188Smrgstatic void 549e2f3d188SmrgPasteCB(_X_UNUSED Widget w, XtPointer clientData, _X_UNUSED XtPointer callData) 5509aa228fdSmrg{ 5519aa228fdSmrg hlPtr data = (hlPtr)clientData; 5529aa228fdSmrg SWRequestSelection(data->scaleInstance, XtLastTimestampProcessed(dpy)); 5539aa228fdSmrg} 5549aa228fdSmrg 5559aa228fdSmrg 5569aa228fdSmrg 5579aa228fdSmrg/* 5589aa228fdSmrg * SetupGC() -- Graphics context for magnification selection. 5599aa228fdSmrg */ 5600c7e83b2Smrgstatic void 5619aa228fdSmrgSetupGC(void) 5629aa228fdSmrg{ 5639aa228fdSmrg selectGCV.function = GXxor; 5649aa228fdSmrg selectGCV.foreground = 0xffffffff; 5659aa228fdSmrg selectGCV.subwindow_mode = IncludeInferiors; 5669aa228fdSmrg selectGC = XtGetGC(toplevel, GCFunction|GCForeground|GCSubwindowMode, 5679aa228fdSmrg &selectGCV); 5680c7e83b2Smrg} 5699aa228fdSmrg 5709aa228fdSmrg 5719aa228fdSmrg 5729aa228fdSmrg/* 5730c7e83b2Smrg * FindWindow() -- Determine window the pointer is over. 5749aa228fdSmrg * 5759aa228fdSmrg */ 5760c7e83b2Smrgstatic Window 5770c7e83b2SmrgFindWindow(int x, int y) /* Location of cursor */ 5789aa228fdSmrg{ 5799aa228fdSmrg XWindowAttributes wa; 5809aa228fdSmrg Window findW = DefaultRootWindow(dpy), stopW, childW; 5819aa228fdSmrg 5829aa228fdSmrg /* Setup for first window find */ 5839aa228fdSmrg stopW = findW; 5849aa228fdSmrg 5859aa228fdSmrg while (stopW) { 5860c7e83b2Smrg XTranslateCoordinates(dpy, findW, stopW, 5879aa228fdSmrg x, y, &x, &y, &childW); 5889aa228fdSmrg findW = stopW; 5899aa228fdSmrg /* If child is not InputOutput (for example, InputOnly) */ 5909aa228fdSmrg /* then don't continue, return the present findW which */ 5919aa228fdSmrg /* can be the root, or a root child of class InputOutput */ 5929aa228fdSmrg if (childW && 5939aa228fdSmrg XGetWindowAttributes(dpy, childW, &wa) && 5949aa228fdSmrg wa.class != InputOutput) 5959aa228fdSmrg break; 5969aa228fdSmrg stopW = childW; 5979aa228fdSmrg } 5989aa228fdSmrg return findW; 5999aa228fdSmrg} 6009aa228fdSmrg 6019aa228fdSmrg 6029aa228fdSmrg 6039aa228fdSmrg/* 6049aa228fdSmrg * ResizeEH() -- Event Handler for resize of selection box. 6059aa228fdSmrg */ 6060c7e83b2Smrgstatic void 6070c7e83b2SmrgResizeEH(Widget w, XtPointer closure, XEvent *event, 608e2f3d188Smrg _X_UNUSED Boolean *continue_to_dispatch) 6099aa228fdSmrg{ 6109aa228fdSmrg hlPtr data = (hlPtr)closure; 6119aa228fdSmrg switch (event->type) { 6129aa228fdSmrg case MotionNotify: 6139aa228fdSmrg data->x = event->xmotion.x_root; 6140c7e83b2Smrg data->y = event->xmotion.y_root; 6159aa228fdSmrg break; 6169aa228fdSmrg case ButtonRelease: 6179aa228fdSmrg GetImageAndAttributes(FindWindow(event->xmotion.x_root, 6189aa228fdSmrg event->xmotion.y_root), 6199aa228fdSmrg min(data->homeX,event->xbutton.x_root), 6209aa228fdSmrg min(data->homeY,event->xbutton.y_root), 6219aa228fdSmrg abs(data->homeX - event->xbutton.x_root), 6229aa228fdSmrg abs(data->homeY - event->xbutton.y_root), 6239aa228fdSmrg data); 6249aa228fdSmrg if (data->newScale) 6259aa228fdSmrg PopupNewScale(data); 6260c7e83b2Smrg else 6279aa228fdSmrg SWSetImage(data->scaleInstance, data->image); 6289aa228fdSmrg XtUngrabPointer(w, CurrentTime); 6299aa228fdSmrg/***** 6309aa228fdSmrg XtRemoveRawEventHandler(w, PointerMotionMask|ButtonReleaseMask, 6319aa228fdSmrg True, ResizeEH, (XtPointer)data); 6329aa228fdSmrg*****/ 6339aa228fdSmrg XtRemoveEventHandler(w, PointerMotionMask|ButtonReleaseMask, 6349aa228fdSmrg True, ResizeEH, (XtPointer)data); 6359aa228fdSmrg data->selectMode = done; 6369aa228fdSmrg break; 6379aa228fdSmrg } 6389aa228fdSmrg} 6399aa228fdSmrg 6409aa228fdSmrg 6419aa228fdSmrg 6429aa228fdSmrg/* 6430c7e83b2Smrg * DragEH() -- Event Handler for dragging selection box. 6449aa228fdSmrg */ 6450c7e83b2Smrgstatic void 6460c7e83b2SmrgDragEH(Widget w, XtPointer closure, XEvent *event, 647e2f3d188Smrg _X_UNUSED Boolean *continue_to_dispatch) 6489aa228fdSmrg{ 6499aa228fdSmrg hlPtr data = (hlPtr)closure; 6509aa228fdSmrg switch (event->type) { 6519aa228fdSmrg case MotionNotify: /* drag mode */ 6529aa228fdSmrg data->x = event->xmotion.x_root; 6539aa228fdSmrg data->y = event->xmotion.y_root; 6549aa228fdSmrg break; 6559aa228fdSmrg case ButtonRelease: /* end drag mode */ 6569aa228fdSmrg if (event->xbutton.button == Button1) { /* get image */ 6579aa228fdSmrg /* Problem: You can't get bits with XGetImage outside of its window. 6589aa228fdSmrg * xmag will only do a GetImage on the actual window in the case 6599aa228fdSmrg * where the depth of the window does not match the depth of 6609aa228fdSmrg * the root window. 6619aa228fdSmrg */ 6620c7e83b2Smrg GetImageAndAttributes(FindWindow(event->xmotion.x_root, 6639aa228fdSmrg event->xmotion.y_root), 6640c7e83b2Smrg event->xbutton.x_root, 6659aa228fdSmrg event->xbutton.y_root, 6669aa228fdSmrg srcWidth, srcHeight, data); 6679aa228fdSmrg if (data->newScale) 6689aa228fdSmrg PopupNewScale(data); 6699aa228fdSmrg else 6709aa228fdSmrg RedoOldScale(data); 6719aa228fdSmrg XtUngrabPointer(w, CurrentTime); 6729aa228fdSmrg XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask| 6739aa228fdSmrg ButtonReleaseMask, True, DragEH, 6749aa228fdSmrg (XtPointer)data); 6759aa228fdSmrg data->selectMode = done; 6769aa228fdSmrg } 6779aa228fdSmrg 6789aa228fdSmrg break; 6790c7e83b2Smrg case ButtonPress: 6809aa228fdSmrg if (event->xbutton.button == Button2) { /* turn on resize mode */ 6810c7e83b2Smrg data->homeX = event->xbutton.x_root; 6829aa228fdSmrg data->homeY = event->xbutton.y_root; 6839aa228fdSmrg data->x = event->xbutton.x_root + srcWidth; 6840c7e83b2Smrg data->y = event->xbutton.y_root + srcHeight; 6859aa228fdSmrg data->selectMode = resize; 6869aa228fdSmrg XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask| 6879aa228fdSmrg ButtonReleaseMask, True, DragEH, (XtPointer)data); 6889aa228fdSmrg XChangeActivePointerGrab 6899aa228fdSmrg (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 6909aa228fdSmrg lrAngle, CurrentTime); 6910c7e83b2Smrg XWarpPointer(dpy, None, None, 0, 0, 0, 0, 6929aa228fdSmrg srcWidth, srcHeight); 6930c7e83b2Smrg XtAddEventHandler(w, PointerMotionMask|ButtonReleaseMask, 6949aa228fdSmrg True, ResizeEH, (XtPointer)data); 6959aa228fdSmrg } 6969aa228fdSmrg break; 6979aa228fdSmrg } 6989aa228fdSmrg} 6999aa228fdSmrg 7009aa228fdSmrg 7019aa228fdSmrg 7029aa228fdSmrg 7039aa228fdSmrg/* 7049aa228fdSmrg * StartRootPtrGrab() -- Bring up the selection box. 7050c7e83b2Smrg * 7069aa228fdSmrg */ 7079aa228fdSmrgstatic void 7080c7e83b2SmrgStartRootPtrGrab(int new, /* do we create a new scale instance? */ 7090c7e83b2Smrg hlPtr data) /* highlight data */ 7109aa228fdSmrg{ 7119aa228fdSmrg Window rootR, childR; 7129aa228fdSmrg int rootX, rootY, winX, winY; 7139aa228fdSmrg unsigned int mask; 7149aa228fdSmrg hlPtr hlData; 7159aa228fdSmrg XtGrabPointer 7169aa228fdSmrg (root, False, 7179aa228fdSmrg PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 7189aa228fdSmrg GrabModeAsync, GrabModeAsync, None, ulAngle, CurrentTime); 7190c7e83b2Smrg XQueryPointer(dpy, DefaultRootWindow(dpy), &rootR, &childR, 7209aa228fdSmrg &rootX, &rootY, &winX, &winY, &mask); 7219aa228fdSmrg if (new) { 7229aa228fdSmrg numXmags++; 7239aa228fdSmrg hlData = (hlPtr)XtMalloc(sizeof(hlStruct)); 7249aa228fdSmrg } 7259aa228fdSmrg else hlData = data; 7269aa228fdSmrg hlData->newScale = new; 7279aa228fdSmrg hlData->selectMode = drag; 7289aa228fdSmrg hlData->x = rootX; 7299aa228fdSmrg hlData->y = rootY; 7309aa228fdSmrg hlData->gc = selectGC; 7319aa228fdSmrg hlData->width = srcWidth; 7329aa228fdSmrg hlData->height = srcHeight; 7339aa228fdSmrg XtAddRawEventHandler 7340c7e83b2Smrg (root, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 7359aa228fdSmrg True, DragEH, (XtPointer)hlData); 7369aa228fdSmrg (void) XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)hlData); 7379aa228fdSmrg} 7389aa228fdSmrg 7399aa228fdSmrg 7409aa228fdSmrg 7419aa228fdSmrg/* 7429aa228fdSmrg * CreateRoot() -- Create a root window widget. If the user specified x and y 7430c7e83b2Smrg * in the source geometry then use this to directly get the 7449aa228fdSmrg * image. 7459aa228fdSmrg */ 7469aa228fdSmrgstatic void 7479aa228fdSmrgCreateRoot(void) 7489aa228fdSmrg{ 7499aa228fdSmrg hlPtr data; 7509aa228fdSmrg root = XtCreateWidget("root", rootWindowWidgetClass, toplevel, NULL, 0); 7519aa228fdSmrg XtRealizeWidget(root); 7520c7e83b2Smrg if (XValue & srcStat && YValue &srcStat) { 7539aa228fdSmrg numXmags = 1; 7549aa228fdSmrg data = (hlPtr)XtMalloc(sizeof(hlStruct)); 755e2f3d188Smrg 7569aa228fdSmrg data->newScale = True; 7579aa228fdSmrg data->selectMode = drag; 7589aa228fdSmrg data->x = srcX; 7599aa228fdSmrg data->y = srcY; 7609aa228fdSmrg data->gc = selectGC; 7619aa228fdSmrg data->width = srcWidth; 7629aa228fdSmrg data->height = srcHeight; 7630c7e83b2Smrg GetImageAndAttributes(RootWindow(dpy, scr), srcX, srcY, srcWidth, 7649aa228fdSmrg srcHeight, data); 7659aa228fdSmrg PopupNewScale(data); 7669aa228fdSmrg return; 7679aa228fdSmrg } 7689aa228fdSmrg} 7699aa228fdSmrg 7709aa228fdSmrg 7710c7e83b2Smrg/* 7729aa228fdSmrg * GetImageAndAttributes() -- Get the image bits from the screen. 7730c7e83b2Smrg * We will also determine here the colormap, depth, and 7740c7e83b2Smrg * visual to be used for the magnification image. 7759aa228fdSmrg */ 7760c7e83b2Smrgstatic void 7770c7e83b2SmrgGetImageAndAttributes(Window w, int x, int y, int width, int height, 7789aa228fdSmrg hlPtr data) 7799aa228fdSmrg{ 78083d7c197Smrg /* get parameters of window being magnified */ 78183d7c197Smrg XGetWindowAttributes(dpy, w, &data->win_info); 78283d7c197Smrg 78383d7c197Smrg if (data->win_info.depth == DefaultDepth(dpy, scr)) { 78483d7c197Smrg /* avoid off screen pixels */ 78583d7c197Smrg if (x < 0) 78683d7c197Smrg x = 0; 78783d7c197Smrg if (y < 0) 78883d7c197Smrg y = 0; 78983d7c197Smrg if (x + width > DisplayWidth(dpy,scr)) 79083d7c197Smrg x = DisplayWidth(dpy,scr) - width; 79183d7c197Smrg if (y + height > DisplayHeight(dpy,scr)) 79283d7c197Smrg y = DisplayHeight(dpy,scr) - height; 79383d7c197Smrg data->x = x; data->y = y; 79483d7c197Smrg /* get image pixels */ 79583d7c197Smrg data->image = XGetImage (dpy, 79683d7c197Smrg RootWindow(dpy, scr), 79783d7c197Smrg x, y, 79883d7c197Smrg width, height, 79983d7c197Smrg AllPlanes, ZPixmap); 80083d7c197Smrg } 80183d7c197Smrg else { 80283d7c197Smrg int t0, t1; 80383d7c197Smrg int x0, x1, y0, y1; 80483d7c197Smrg int xInWin, yInWin; 80583d7c197Smrg Window childWin; 80683d7c197Smrg 80783d7c197Smrg XTranslateCoordinates(dpy, DefaultRootWindow(dpy), w, x, y, 80883d7c197Smrg &xInWin, &yInWin, &childWin); 80983d7c197Smrg 81083d7c197Smrg /* Avoid off screen pixels. Assume this routine is not 81183d7c197Smrg * called for totally offscreen windows. */ 81283d7c197Smrg x0 = max(x, 0); 81383d7c197Smrg y0 = max(y, 0); 81483d7c197Smrg x1 = min(DisplayWidth(dpy, scr), 81583d7c197Smrg min(x0 + width, x0 + (data->win_info.width - xInWin))); 81683d7c197Smrg y1 = min(DisplayHeight(dpy, scr), 81783d7c197Smrg min(y0 + height, y0 + (data->win_info.height - yInWin))); 81883d7c197Smrg 81983d7c197Smrg /* Try to use up to width x height pixels */ 82083d7c197Smrg if (x1 - x0 < width) { 82183d7c197Smrg t0 = x0; 82283d7c197Smrg t1 = max(0, x - xInWin + data->win_info.width - 82383d7c197Smrg DisplayWidth(dpy, scr)); 82483d7c197Smrg x0 = max(0, x1 - min(width, data->win_info.width - t1)); 82583d7c197Smrg xInWin -= t0 - x0; 82683d7c197Smrg } 82783d7c197Smrg if (y1 - y0 < height) { 82883d7c197Smrg t0 = y0; 82983d7c197Smrg t1 = max(0, y - yInWin + data->win_info.height - 83083d7c197Smrg DisplayHeight(dpy, scr)); 83183d7c197Smrg y0 = max(0, y1 - min(height, data->win_info.height - t1)); 83283d7c197Smrg yInWin -= t0 - y0; 83383d7c197Smrg } 83483d7c197Smrg 83583d7c197Smrg data->x = x0; 83683d7c197Smrg data->y = y0; 83783d7c197Smrg data->width = x1 - x0; 83883d7c197Smrg data->height = y1 - y0; 83983d7c197Smrg 84083d7c197Smrg data->image = XGetImage (dpy, 84183d7c197Smrg w, 84283d7c197Smrg xInWin, yInWin, 84383d7c197Smrg data->width, data->height, 84483d7c197Smrg AllPlanes, ZPixmap); 84583d7c197Smrg 84683d7c197Smrg } 8479aa228fdSmrg} 8489aa228fdSmrg 8499aa228fdSmrg 8509aa228fdSmrg 8519aa228fdSmrg/* 8529aa228fdSmrg * Get_XColors() Get the XColors of all pixels in image - returns # of colors 8539aa228fdSmrg * This function was taken from xwd (thanks Bob...) 8549aa228fdSmrg */ 8559aa228fdSmrg#define lowbit(x) ((x) & (~(x) + 1)) 8560c7e83b2Smrgstatic int 8579aa228fdSmrgGet_XColors(XWindowAttributes *win_info, XColor **colors) 8589aa228fdSmrg{ 8599aa228fdSmrg int i, ncolors; 8600c7e83b2Smrg 8619aa228fdSmrg if (!win_info->colormap) 8629aa228fdSmrg return(0); 8630c7e83b2Smrg 8649aa228fdSmrg ncolors = win_info->visual->map_entries; 8659aa228fdSmrg if (!(*colors = (XColor *) XtMalloc (sizeof(XColor) * ncolors))) 8669aa228fdSmrg XtError("Out of memory!"); 8670c7e83b2Smrg 8689aa228fdSmrg if (win_info->visual->class == DirectColor || 8699aa228fdSmrg win_info->visual->class == TrueColor) { 8709aa228fdSmrg Pixel red, green, blue, red1, green1, blue1; 8710c7e83b2Smrg 8729aa228fdSmrg red = green = blue = 0; 8739aa228fdSmrg red1 = lowbit(win_info->visual->red_mask); 8749aa228fdSmrg green1 = lowbit(win_info->visual->green_mask); 8759aa228fdSmrg blue1 = lowbit(win_info->visual->blue_mask); 8769aa228fdSmrg for (i=0; i<ncolors; i++) { 8779aa228fdSmrg (*colors)[i].pixel = red|green|blue; 8789aa228fdSmrg (*colors)[i].pad = 0; 8799aa228fdSmrg red += red1; 8809aa228fdSmrg if (red > win_info->visual->red_mask) 8819aa228fdSmrg red = 0; 8829aa228fdSmrg green += green1; 8839aa228fdSmrg if (green > win_info->visual->green_mask) 8849aa228fdSmrg green = 0; 8859aa228fdSmrg blue += blue1; 8869aa228fdSmrg if (blue > win_info->visual->blue_mask) 8879aa228fdSmrg blue = 0; 8889aa228fdSmrg } 8899aa228fdSmrg } else { 8909aa228fdSmrg for (i=0; i<ncolors; i++) { 8919aa228fdSmrg (*colors)[i].pixel = i; 8929aa228fdSmrg (*colors)[i].pad = 0; 8939aa228fdSmrg } 8949aa228fdSmrg } 8950c7e83b2Smrg 8969aa228fdSmrg XQueryColors(dpy, win_info->colormap, *colors, ncolors); 8970c7e83b2Smrg 8989aa228fdSmrg return(ncolors); 8999aa228fdSmrg} 9009aa228fdSmrg 9019aa228fdSmrg 9029aa228fdSmrg 9039aa228fdSmrg#define Intensity(cptr) (3.0*cptr->red+0.59*cptr->green+0.11*cptr->blue) 9049aa228fdSmrg 9059aa228fdSmrg/* 9069aa228fdSmrg * GetMaxIntensity() -- Find the maximum intensity pixel value for a colormap. 9079aa228fdSmrg */ 9089aa228fdSmrgstatic Pixel 9099aa228fdSmrgGetMaxIntensity(hlPtr data) 9109aa228fdSmrg{ 9119aa228fdSmrg XColor *colors = NULL, *mptr, *tptr; 9129aa228fdSmrg int i, ncolors; 9139aa228fdSmrg 9140c7e83b2Smrg if (data->win_info.colormap == DefaultColormap(dpy, scr)) 9159aa228fdSmrg return WhitePixel(dpy, scr); 9160c7e83b2Smrg ncolors = Get_XColors(&data->win_info, &colors); 9179aa228fdSmrg mptr = tptr = colors; tptr++; 9189aa228fdSmrg for (i=1; i<ncolors; i++) { 9190c7e83b2Smrg if ((int)Intensity(mptr) < (int)Intensity(tptr)) 9209aa228fdSmrg mptr = tptr; 9219aa228fdSmrg tptr++; 9229aa228fdSmrg } 9239aa228fdSmrg /* Null pointer protection */ 9249aa228fdSmrg if(mptr) 9259aa228fdSmrg return mptr->pixel; 9269aa228fdSmrg else 9279aa228fdSmrg return WhitePixel(dpy, scr); 9289aa228fdSmrg} 9299aa228fdSmrg 9309aa228fdSmrg/* 9319aa228fdSmrg * GetMinIntensity() -- Find the minimum intensity pixel value for a colormap. 9329aa228fdSmrg */ 9339aa228fdSmrgstatic Pixel 9349aa228fdSmrgGetMinIntensity(hlPtr data) 9359aa228fdSmrg{ 9369aa228fdSmrg XColor *colors = NULL, *mptr, *tptr; 9379aa228fdSmrg int i, ncolors; 9389aa228fdSmrg 9390c7e83b2Smrg if (data->win_info.colormap == DefaultColormap(dpy, scr)) 9409aa228fdSmrg return BlackPixel(dpy, scr); 9410c7e83b2Smrg ncolors = Get_XColors(&data->win_info, &colors); 9429aa228fdSmrg mptr = tptr = colors; tptr++; 9439aa228fdSmrg for (i=1; i<ncolors; i++) { 9449aa228fdSmrg if ((int)Intensity(mptr) > (int)Intensity(tptr)) 9450c7e83b2Smrg mptr = tptr; 9469aa228fdSmrg tptr++; 9479aa228fdSmrg } 9489aa228fdSmrg /* Null pointer protection */ 9499aa228fdSmrg if(mptr) 9509aa228fdSmrg return mptr->pixel; 9519aa228fdSmrg else 9529aa228fdSmrg return BlackPixel(dpy, scr); 9539aa228fdSmrg} 9549aa228fdSmrg 9559aa228fdSmrg 9569aa228fdSmrg 9579aa228fdSmrg 9589aa228fdSmrgstatic Widget pane1, pane2, pane3, cclose, replace, new, select_w, paste; 9599aa228fdSmrg 9609aa228fdSmrg/* 9619aa228fdSmrg * PopupNewScale() -- Create and popup a new scale composite. 9629aa228fdSmrg */ 9630c7e83b2Smrgstatic void 9649aa228fdSmrgPopupNewScale(hlPtr data) 9659aa228fdSmrg{ 9669aa228fdSmrg Arg warg; 9679aa228fdSmrg 9680c7e83b2Smrg data->scaleShell = 9690c7e83b2Smrg XtVaCreatePopupShell("xmag", topLevelShellWidgetClass, toplevel, 9709aa228fdSmrg XtNgeometry, (XtArgVal)options.geometry, 9719aa228fdSmrg XtNtitle, (XtArgVal)options.title, 9729aa228fdSmrg NULL); 9739aa228fdSmrg pane1 = XtCreateManagedWidget("pane1", panedWidgetClass, data->scaleShell, 9749aa228fdSmrg (Arg *) NULL, 0); 9759aa228fdSmrg pane2 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1, 9769aa228fdSmrg (Arg *) NULL, 0); 9779aa228fdSmrg cclose = XtCreateManagedWidget("close", commandWidgetClass, pane2, 9789aa228fdSmrg (Arg *) NULL, 0); 9799aa228fdSmrg XtAddCallback(cclose, XtNcallback, CloseCB, (XtPointer)data->scaleShell); 9809aa228fdSmrg replace = XtCreateManagedWidget("replace", commandWidgetClass, pane2, 9819aa228fdSmrg (Arg *) NULL, 0); 9829aa228fdSmrg XtAddCallback(replace, XtNcallback, ReplaceCB, (XtPointer)data); 9839aa228fdSmrg new = XtCreateManagedWidget("new", commandWidgetClass, pane2, 9849aa228fdSmrg (Arg *) NULL, 0); 9859aa228fdSmrg XtAddCallback(new, XtNcallback, NewCB, (XtPointer)NULL); 9869aa228fdSmrg select_w = XtCreateManagedWidget("select", commandWidgetClass, pane2, 9879aa228fdSmrg (Arg *) NULL, 0); 9889aa228fdSmrg XtAddCallback(select_w, XtNcallback, SelectCB, (XtPointer)data); 9899aa228fdSmrg paste = XtCreateManagedWidget("paste", commandWidgetClass, pane2, 9909aa228fdSmrg (Arg *) NULL, 0); 9919aa228fdSmrg XtAddCallback(paste, XtNcallback, PasteCB, (XtPointer)data); 9929aa228fdSmrg (void) XtCreateManagedWidget("helpLabel", labelWidgetClass, pane2, 9939aa228fdSmrg (Arg *) NULL, 0); 9949aa228fdSmrg pane3 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1, 9959aa228fdSmrg (Arg *) NULL, 0); 9960c7e83b2Smrg data->scaleInstance = 9970c7e83b2Smrg XtVaCreateManagedWidget("scale", scaleWidgetClass, 9989aa228fdSmrg pane3, 9999aa228fdSmrg XtNvisual, (XtArgVal)data->win_info.visual, 10009aa228fdSmrg XtNcolormap, (XtArgVal)data->win_info.colormap, 10019aa228fdSmrg XtNdepth, (XtArgVal)data->win_info.depth, 10029aa228fdSmrg XtNscaleX, (XtArgVal)options.mag, 10039aa228fdSmrg XtNscaleY, (XtArgVal)options.mag, 10049aa228fdSmrg NULL); 10059aa228fdSmrg SWSetImage(data->scaleInstance, data->image); 10069aa228fdSmrg XtOverrideTranslations 10079aa228fdSmrg (data->scaleShell, 10089aa228fdSmrg XtParseTranslationTable ("<Message>WM_PROTOCOLS: close()")); 10099aa228fdSmrg XtSetArg(warg, XtNuserData, data); 10109aa228fdSmrg XtSetValues(data->scaleInstance, &warg, 1); 10110c7e83b2Smrg data->pixShell = 10120c7e83b2Smrg XtVaCreatePopupShell("pixShell", overrideShellWidgetClass, 10139aa228fdSmrg toplevel, 10149aa228fdSmrg XtNvisual, (XtArgVal)data->win_info.visual, 10159aa228fdSmrg XtNcolormap, (XtArgVal)data->win_info.colormap, 10169aa228fdSmrg XtNdepth, (XtArgVal)data->win_info.depth, 10179aa228fdSmrg XtNborderWidth, (XtPointer)0, 10189aa228fdSmrg NULL); 10190c7e83b2Smrg data->pixLabel = 10200c7e83b2Smrg XtVaCreateManagedWidget("pixLabel", labelWidgetClass, 10210c7e83b2Smrg data->pixShell, 10229aa228fdSmrg XtNforeground, (XtPointer)GetMaxIntensity(data), 10239aa228fdSmrg XtNbackground, (XtPointer)GetMinIntensity(data), 10249aa228fdSmrg XtNborderWidth, (XtPointer)0, 10259aa228fdSmrg NULL); 10269aa228fdSmrg XtInstallAllAccelerators(pane1, pane1); /* install accelerators */ 10279aa228fdSmrg if (data->newScale) { 10289aa228fdSmrg XtPopup(data->scaleShell, XtGrabNone); 10299aa228fdSmrg (void) XSetWMProtocols /* ICCCM delete window */ 10309aa228fdSmrg (dpy, XtWindow(data->scaleShell), &wm_delete_window, 1); 10319aa228fdSmrg } 10329aa228fdSmrg if (data->win_info.colormap != DefaultColormap(dpy, scr)) { 10330c7e83b2Smrg data->cmapWinList[0] = data->scaleShell; 10349aa228fdSmrg data->cmapWinList[1] = data->scaleInstance; 10359aa228fdSmrg XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2); 10369aa228fdSmrg } 10379aa228fdSmrg} 10389aa228fdSmrg 10399aa228fdSmrg 10409aa228fdSmrg 10419aa228fdSmrg/* 10429aa228fdSmrg * RedoOldScale() -- If the visual, depth, or colormap has changed, unrealize 10439aa228fdSmrg * the scale widget and change its colormap/depth/visual. 10449aa228fdSmrg * Then re-realize it. Also do this for the pixel display 10459aa228fdSmrg * widget. 10469aa228fdSmrg */ 10479aa228fdSmrgstatic void 10489aa228fdSmrgRedoOldScale(hlPtr data) 10499aa228fdSmrg{ 10509aa228fdSmrg Arg wargs[3]; 10519aa228fdSmrg int n; 10529aa228fdSmrg Visual *oldVis; 10539aa228fdSmrg int oldDepth; 10549aa228fdSmrg Colormap oldCmap; 10559aa228fdSmrg 10569aa228fdSmrg n=0; 10579aa228fdSmrg XtSetArg(wargs[n], XtNvisual, &oldVis); n++; 10589aa228fdSmrg XtSetArg(wargs[n], XtNdepth, &oldDepth); n++; 10599aa228fdSmrg XtSetArg(wargs[n], XtNcolormap, &oldCmap); n++; 10600c7e83b2Smrg XtGetValues(data->scaleInstance, wargs, n); 10619aa228fdSmrg if (oldVis == data->win_info.visual && oldDepth == data->win_info.depth 10629aa228fdSmrg && oldCmap == data->win_info.colormap) { 10630c7e83b2Smrg SWSetImage(data->scaleInstance, data->image); 10649aa228fdSmrg return; 10659aa228fdSmrg } 10669aa228fdSmrg /* get width and height, save and reuse them */ 10679aa228fdSmrg XtUnmanageChild(data->scaleInstance); 10689aa228fdSmrg XtUnrealizeWidget(data->scaleInstance); 10699aa228fdSmrg n=0; 10709aa228fdSmrg XtSetArg(wargs[n], XtNcolormap, data->win_info.colormap); n++; 10719aa228fdSmrg XtSetArg(wargs[n], XtNdepth, data->win_info.depth); n++; 10729aa228fdSmrg XtSetArg(wargs[n], XtNvisual, data->win_info.visual); n++; 10739aa228fdSmrg XtSetValues(data->scaleInstance, wargs, n); 10749aa228fdSmrg n=0; 10759aa228fdSmrg XtSetArg(wargs[n], XtNforeground, GetMaxIntensity(data)); n++; 10769aa228fdSmrg XtSetArg(wargs[n], XtNbackground, GetMinIntensity(data)); n++; 10779aa228fdSmrg XtSetValues(data->pixLabel, wargs, n); 10780c7e83b2Smrg SWSetImage(data->scaleInstance, data->image); 10799aa228fdSmrg XtRealizeWidget(data->scaleInstance); 10809aa228fdSmrg XtManageChild(data->scaleInstance); 10819aa228fdSmrg} 10829aa228fdSmrg 10839aa228fdSmrg 10849aa228fdSmrg 10859aa228fdSmrg/* 10869aa228fdSmrg * InitCursors() -- Create our cursors for area selection. 10879aa228fdSmrg */ 10889aa228fdSmrgstatic void 10899aa228fdSmrgInitCursors(void) 10909aa228fdSmrg{ 10919aa228fdSmrg ulAngle = XCreateFontCursor(dpy, XC_ul_angle); 10929aa228fdSmrg urAngle = XCreateFontCursor(dpy, XC_ur_angle); 10939aa228fdSmrg lrAngle = XCreateFontCursor(dpy, XC_lr_angle); 10949aa228fdSmrg llAngle = XCreateFontCursor(dpy, XC_ll_angle); 10959aa228fdSmrg} 10969aa228fdSmrg 10979aa228fdSmrg 10989aa228fdSmrg 10999aa228fdSmrg/* 11000c7e83b2Smrg * ParseSourceGeom() -- Determine dimensions of area to magnify from resources. 11019aa228fdSmrg */ 11020c7e83b2Smrgstatic void 11039aa228fdSmrgParseSourceGeom(void) 11049aa228fdSmrg{ 11059aa228fdSmrg /* source */ 11060c7e83b2Smrg srcStat = 11079aa228fdSmrg XParseGeometry(options.source, &srcX, &srcY, &srcWidth, &srcHeight); 11089aa228fdSmrg if (!srcWidth) srcWidth = SRCWIDTH; 11099aa228fdSmrg if (!srcHeight) srcHeight = SRCHEIGHT; 11109aa228fdSmrg if (XNegative & srcStat) srcX = DisplayWidth(dpy, scr) + srcX - srcWidth; 11119aa228fdSmrg if (YNegative & srcStat) srcY = DisplayHeight(dpy, scr) + srcY - srcHeight; 11129aa228fdSmrg /* mag */ 11139aa228fdSmrg} 11149aa228fdSmrg 11159aa228fdSmrg 11169aa228fdSmrg 1117e2f3d188Smrgstatic void _X_NORETURN 1118e2f3d188Smrgusage(const char *progname, int exitval) 1119e2f3d188Smrg{ 1120e2f3d188Smrg fprintf (stderr, 1121e2f3d188Smrg "usage: %s [-source geom] [-mag magfactor] [-toolkitoption]\n" 1122e2f3d188Smrg " %s [-help|-version]\n", 1123e2f3d188Smrg progname, progname); 1124e2f3d188Smrg exit (exitval); 1125e2f3d188Smrg} 1126e2f3d188Smrg 11279aa228fdSmrg/* 11289aa228fdSmrg * Main program. 11299aa228fdSmrg */ 11300c7e83b2Smrgint 11319aa228fdSmrgmain(int argc, char *argv[]) 11329aa228fdSmrg{ 1133e2f3d188Smrg /* Handle args that don't require opening a display */ 1134e2f3d188Smrg for (int n = 1; n < argc; n++) { 1135e2f3d188Smrg const char *argn = argv[n]; 1136e2f3d188Smrg /* accept single or double dash for -help & -version */ 1137e2f3d188Smrg if (argn[0] == '-' && argn[1] == '-') { 1138e2f3d188Smrg argn++; 1139e2f3d188Smrg } 1140e2f3d188Smrg if (strcmp(argn, "-help") == 0) { 1141e2f3d188Smrg usage(argv[0], 0); 1142e2f3d188Smrg } 1143e2f3d188Smrg if (strcmp(argn, "-version") == 0) { 1144e2f3d188Smrg puts(PACKAGE_STRING); 1145e2f3d188Smrg exit(0); 1146e2f3d188Smrg } 1147e2f3d188Smrg } 1148e2f3d188Smrg 11499aa228fdSmrg XSetErrorHandler(Error); 11500c7e83b2Smrg 11519aa228fdSmrg toplevel = XtAppInitialize(&app, "Xmag", optionDesc, XtNumber(optionDesc), 11529aa228fdSmrg &argc, argv, NULL, 11539aa228fdSmrg NULL, 0); 11549aa228fdSmrg 11559aa228fdSmrg dpy = XtDisplay(toplevel); 11569aa228fdSmrg scr = DefaultScreen(dpy); 11579aa228fdSmrg XtGetApplicationResources(toplevel, (XtPointer) &options, resources, 11589aa228fdSmrg XtNumber(resources), NULL, 0); 11599aa228fdSmrg if (argc != 1) { 1160e2f3d188Smrg fputs("Unknown argument(s):", stderr); 1161e2f3d188Smrg for (int n = 1; n < argc; n++) { 1162e2f3d188Smrg fprintf(stderr, " %s", argv[n]); 1163e2f3d188Smrg } 1164e2f3d188Smrg fputs("\n\n", stderr); 1165e2f3d188Smrg usage(argv[0], 1); 11669aa228fdSmrg } 11670c7e83b2Smrg 11689aa228fdSmrg 11699aa228fdSmrg ParseSourceGeom(); 11709aa228fdSmrg XtAppAddActions(app, actions_table, XtNumber(actions_table)); 11719aa228fdSmrg InitCursors(); 11729aa228fdSmrg SetupGC(); 11739aa228fdSmrg CreateRoot(); 11749aa228fdSmrg if (!(XValue & srcStat && YValue & srcStat)) 11759aa228fdSmrg StartRootPtrGrab(True, (hlPtr)NULL); 11769aa228fdSmrg wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 11779aa228fdSmrg XtAppMainLoop(app); 11789aa228fdSmrg exit(0); 11799aa228fdSmrg} 1180