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