xmag.c revision 15106172
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 2059aa228fdSmrgError(Display *dpy, XErrorEvent *err) 2069aa228fdSmrg{ 2079aa228fdSmrg (void) XmuPrintDefaultErrorMessage (dpy, err, stderr); 2089aa228fdSmrg return 0; 2099aa228fdSmrg} 2109aa228fdSmrg 2119aa228fdSmrg 2129aa228fdSmrg/* 2139aa228fdSmrg * CloseAP() -- Close this dialog. If its the last one exit the program. 2140c7e83b2Smrg * 2159aa228fdSmrg */ 2169aa228fdSmrgstatic void /* ARGSUSED */ 2179aa228fdSmrgCloseAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 2189aa228fdSmrg{ 2199aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2209aa228fdSmrg if (!--numXmags) exit(0); 2219aa228fdSmrg if (event->type != ClientMessage) { 2229aa228fdSmrg n = 0; /* get user data */ 2239aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2240c7e83b2Smrg XtGetValues(w, wargs, n); 2259aa228fdSmrg w = data->scaleShell; 2269aa228fdSmrg } 2279aa228fdSmrg XtPopdown(w); 2289aa228fdSmrg XtDestroyWidget(w); 2299aa228fdSmrg} 2309aa228fdSmrg 2319aa228fdSmrg 2329aa228fdSmrg 2339aa228fdSmrg/* 2349aa228fdSmrg * SetCmapPropsAP() -- Put the scale widget first in WM_COLORMAP_WINDOWS 2350c7e83b2Smrg * 2369aa228fdSmrg */ 2379aa228fdSmrgstatic void /* ARGSUSED */ 2389aa228fdSmrgSetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 2399aa228fdSmrg{ 2409aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2419aa228fdSmrg n = 0; /* get user data */ 2429aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2439aa228fdSmrg XtGetValues(w, wargs, n); 2449aa228fdSmrg if (data->win_info.colormap != DefaultColormap(dpy, scr)) { 2459aa228fdSmrg data->cmapWinList[0] = data->scaleInstance; 2469aa228fdSmrg data->cmapWinList[1] = data->scaleShell; 2479aa228fdSmrg XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2); 2489aa228fdSmrg } 2499aa228fdSmrg} 2509aa228fdSmrg 2519aa228fdSmrg 2529aa228fdSmrg 2539aa228fdSmrg/* 2549aa228fdSmrg * UnsetCmapPropsAP() -- Put the shell first in WM_COLORMAP_WINDOWS 2550c7e83b2Smrg * 2569aa228fdSmrg */ 2579aa228fdSmrgstatic void /* ARGSUSED */ 2589aa228fdSmrgUnsetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 2599aa228fdSmrg{ 2609aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2619aa228fdSmrg n = 0; /* get user data */ 2629aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2639aa228fdSmrg XtGetValues(w, wargs, n); 2649aa228fdSmrg if (data->win_info.colormap != DefaultColormap(dpy, scr)) { 2659aa228fdSmrg data->cmapWinList[0] = data->scaleShell; 2669aa228fdSmrg data->cmapWinList[1] = data->scaleInstance; 2679aa228fdSmrg XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2); 2689aa228fdSmrg } 2699aa228fdSmrg} 2709aa228fdSmrg 2719aa228fdSmrg 2729aa228fdSmrg 2739aa228fdSmrg/* 2749aa228fdSmrg * NewAP() -- Create an additional xmag dialog. THIS IS A COPY OF NewEH 2759aa228fdSmrg * FIND A BETTER WAY.... 2769aa228fdSmrg */ 2779aa228fdSmrgstatic void /* ARGSUSED */ 2789aa228fdSmrgNewAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 2799aa228fdSmrg{ 2809aa228fdSmrg StartRootPtrGrab(True, NULL); 2819aa228fdSmrg} 2829aa228fdSmrg 2839aa228fdSmrg 2849aa228fdSmrg 2859aa228fdSmrg/* 2869aa228fdSmrg * ReplaceAP() -- Replace this particular xmag dialog. 2879aa228fdSmrg */ 2889aa228fdSmrgstatic void /* ARGSUSED */ 2899aa228fdSmrgReplaceAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 2909aa228fdSmrg{ 2919aa228fdSmrg Arg wargs[2]; int n; hlPtr data; 2929aa228fdSmrg n = 0; /* get user data */ 2939aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 2940c7e83b2Smrg XtGetValues(w, wargs, n); 2959aa228fdSmrg StartRootPtrGrab(False, data); 2969aa228fdSmrg} 2979aa228fdSmrg 2989aa228fdSmrg 2999aa228fdSmrg 3009aa228fdSmrg/* 3019aa228fdSmrg * PopupPixelAP() -- Show pixel information. 3029aa228fdSmrg */ 3039aa228fdSmrgstatic void /* ARGSUSED */ 3049aa228fdSmrgPopupPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 3059aa228fdSmrg{ 3069aa228fdSmrg Position scale_x, scale_y; 3079aa228fdSmrg Dimension scale_height; 3089aa228fdSmrg Position label_x, label_y; 3099aa228fdSmrg Dimension label_height; 3109aa228fdSmrg int n; 3119aa228fdSmrg Arg wargs[3]; 3129aa228fdSmrg hlPtr data; 3139aa228fdSmrg 3149aa228fdSmrg n = 0; /* get user data */ 3159aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 3169aa228fdSmrg XtGetValues(w, wargs, n); 3179aa228fdSmrg 3189aa228fdSmrg n = 0; 3199aa228fdSmrg XtSetArg(wargs[n], XtNheight, &scale_height); n++; 3209aa228fdSmrg XtGetValues(w, wargs, n); 3219aa228fdSmrg XtTranslateCoords(w, -1, -1, &scale_x, &scale_y); 3220c7e83b2Smrg 3239aa228fdSmrg XtRealizeWidget(data->pixShell); /* to get the right height */ 3249aa228fdSmrg 3259aa228fdSmrg n = 0; 3269aa228fdSmrg XtSetArg(wargs[n], XtNheight, &label_height); n++; 3279aa228fdSmrg XtGetValues(data->pixShell, wargs, n); 3280c7e83b2Smrg 3299aa228fdSmrg if ((double) event->xbutton.y / (double) scale_height > 0.5) { 3309aa228fdSmrg label_x = scale_x; 3319aa228fdSmrg label_y = scale_y; 3329aa228fdSmrg } 3339aa228fdSmrg else { 3349aa228fdSmrg label_x = scale_x; 3359aa228fdSmrg label_y = scale_y + scale_height - label_height; 3369aa228fdSmrg } 3379aa228fdSmrg 3389aa228fdSmrg n = 0; 3399aa228fdSmrg XtSetArg(wargs[n], XtNx, label_x); n++; 3409aa228fdSmrg XtSetArg(wargs[n], XtNy, label_y); n++; 3419aa228fdSmrg XtSetValues(data->pixShell, wargs, n); 34283d7c197Smrg 34383d7c197Smrg UpdatePixelAP(w, event, NULL, NULL); 3449aa228fdSmrg} 3459aa228fdSmrg 3469aa228fdSmrg 3479aa228fdSmrg 3489aa228fdSmrg/* 3499aa228fdSmrg * UpdatePixelAP() -- Update pixel information. 3509aa228fdSmrg */ 3519aa228fdSmrgstatic void /* ARGSUSED */ 3529aa228fdSmrgUpdatePixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 3539aa228fdSmrg{ 3549aa228fdSmrg Position x, y; 3559aa228fdSmrg Pixel pixel; 3569aa228fdSmrg XColor color; 3579aa228fdSmrg int n; 3589aa228fdSmrg Arg wargs[3]; 3599aa228fdSmrg char string[80]; 3609aa228fdSmrg hlPtr data; 3619aa228fdSmrg 3629aa228fdSmrg n = 0; 3639aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 3649aa228fdSmrg XtGetValues(w, wargs, n); 3659aa228fdSmrg 3669aa228fdSmrg if (SWGetImagePixel(w, event->xbutton.x, event->xbutton.y, &x, &y, &pixel)) 3679aa228fdSmrg XtPopdown(data->pixShell); 3689aa228fdSmrg else { 3699aa228fdSmrg color.pixel = pixel; 3709aa228fdSmrg XQueryColor(dpy, data->win_info.colormap, &color); 3710c7e83b2Smrg snprintf(string, sizeof(string), 3720c7e83b2Smrg "Pixel %ld at (%d,%d) colored (%x,%x,%x).", 3730c7e83b2Smrg pixel, x + data->x, y + data->y, 3740c7e83b2Smrg color.red, color.green, color.blue); 3759aa228fdSmrg n = 0; 3760c7e83b2Smrg XtSetArg(wargs[n], XtNlabel, string); n++; 3779aa228fdSmrg XtSetValues(data->pixLabel, wargs, n); 3789aa228fdSmrg XtPopup(data->pixShell, XtGrabNone); 3799aa228fdSmrg } 3809aa228fdSmrg} 3819aa228fdSmrg 3829aa228fdSmrg 3839aa228fdSmrg 3849aa228fdSmrg/* 3859aa228fdSmrg * PopdownPixelAP() -- Remove pixel info. 3869aa228fdSmrg */ 3879aa228fdSmrgstatic void /* ARGSUSED */ 3889aa228fdSmrgPopdownPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 3899aa228fdSmrg{ 3909aa228fdSmrg int n; 3919aa228fdSmrg Arg wargs[3]; 3929aa228fdSmrg hlPtr data = NULL; 3930c7e83b2Smrg 3949aa228fdSmrg n = 0; 3959aa228fdSmrg XtSetArg(wargs[0], XtNuserData, &data); n++; 3969aa228fdSmrg XtGetValues(w, wargs, n); 3979aa228fdSmrg 3989aa228fdSmrg if (data) 3999aa228fdSmrg XtPopdown(data->pixShell); 4009aa228fdSmrg} 4019aa228fdSmrg 4029aa228fdSmrg 4039aa228fdSmrg 4049aa228fdSmrgstatic void /* ARGSUSED */ 4059aa228fdSmrgSelectRegionAP(Widget w, XEvent *event, String *params, Cardinal *num_params) 4060c7e83b2Smrg{ 4070c7e83b2Smrg/***** NOT SURE WHAT TO DO WITH THIS 4089aa228fdSmrg if (app_resources.unmap) 4099aa228fdSmrg XtUnmapWidget(toplevel); 4109aa228fdSmrg Redisplay(XtDisplay(w), RootWindow(XtDisplay(w), 4119aa228fdSmrg DefaultScreen(XtDisplay(w))), 4120c7e83b2Smrg source.width, source.height, 4130c7e83b2Smrg app_resources.freq, app_resources.puls, 4149aa228fdSmrg ul_angle, lr_angle, 4159aa228fdSmrg app_resources.grab); 4169aa228fdSmrg 4179aa228fdSmrg if (app_resources.unmap) 4189aa228fdSmrg XtMapWidget(toplevel); 4199aa228fdSmrg******/ 4209aa228fdSmrg} 4219aa228fdSmrg 4229aa228fdSmrg 4239aa228fdSmrg 4240c7e83b2Smrg/* 4259aa228fdSmrg * CheckPoints() -- Change the cursor for the correct quadrant. 4260c7e83b2Smrg * Make sure the first point is less than the second 4279aa228fdSmrg * for drawing the selection rectangle. 4289aa228fdSmrg * 4299aa228fdSmrg */ 4300c7e83b2Smrgstatic void 4319aa228fdSmrgCheckPoints(Position *x1, Position *x2, Position *y1, Position *y2) 4329aa228fdSmrg{ 4330c7e83b2Smrg Position tmp; 4349aa228fdSmrg Boolean above, left; 4359aa228fdSmrg Cursor newC; 4360c7e83b2Smrg above = (*y2 < *y1); left = (*x2 < *x1); 4379aa228fdSmrg if (above&&left) newC = ulAngle; 4389aa228fdSmrg else if (above&&!left) newC = urAngle; 4399aa228fdSmrg else if (!above&&!left) newC = lrAngle; 4409aa228fdSmrg else newC = llAngle; 4419aa228fdSmrg XChangeActivePointerGrab 4429aa228fdSmrg (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 4439aa228fdSmrg newC, CurrentTime); 4449aa228fdSmrg if (*x2 < *x1) { tmp = *x1; *x1 = *x2; *x2 = tmp; } 4459aa228fdSmrg if (*y2 < *y1) { tmp = *y1; *y1 = *y2; *y2 = tmp; } 4469aa228fdSmrg} 4479aa228fdSmrg 4489aa228fdSmrg 4499aa228fdSmrg 4509aa228fdSmrg/* 4519aa228fdSmrg * HighlightTO() -- Timer to highlight the selection box 4529aa228fdSmrg */ 4539aa228fdSmrgstatic void 4549aa228fdSmrgHighlightTO(XtPointer closure, XtIntervalId *id) /* ARGSUSED */ 4559aa228fdSmrg{ 4569aa228fdSmrg hlPtr data = (hlPtr)closure; 4579aa228fdSmrg XGrabServer(dpy); 4589aa228fdSmrg if (data->selectMode == drag) { 4590c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4609aa228fdSmrg data->x, data->y, data->width, data->height); 4619aa228fdSmrg XFlush(dpy); 4629aa228fdSmrg HLSLEEP; 4630c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4649aa228fdSmrg data->x, data->y, data->width, data->height); 4659aa228fdSmrg } 4660c7e83b2Smrg else if (data->selectMode == resize) { 4679aa228fdSmrg Position x1 = data->homeX, 4689aa228fdSmrg x2 = data->x, 4699aa228fdSmrg y1 = data->homeY, 4709aa228fdSmrg y2 = data->y; 4719aa228fdSmrg CheckPoints(&x1, &x2, &y1, &y2); 4720c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4739aa228fdSmrg x1, y1, x2 - x1, y2 - y1); 4749aa228fdSmrg XFlush(dpy); 4759aa228fdSmrg HLSLEEP; 4760c7e83b2Smrg XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 4779aa228fdSmrg x1, y1, x2 - x1, y2 - y1); 4789aa228fdSmrg } 4799aa228fdSmrg XUngrabServer(dpy); 4809aa228fdSmrg if (data->selectMode != done) 4819aa228fdSmrg XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)data); 4829aa228fdSmrg} 4839aa228fdSmrg 4849aa228fdSmrg 4859aa228fdSmrg 4869aa228fdSmrg/* 4879aa228fdSmrg * CloseCB() -- Delete this xmag dialog. If its the only one on the screen 4889aa228fdSmrg * then exit. 4899aa228fdSmrg */ 4909aa228fdSmrgstatic void /* ARGSUSED */ 4919aa228fdSmrgCloseCB(Widget w, XtPointer clientData, XtPointer callData) 4929aa228fdSmrg{ 4939aa228fdSmrg Widget shell = (Widget)clientData; 4949aa228fdSmrg if (!--numXmags) exit(0); 4959aa228fdSmrg XtPopdown(shell); 4969aa228fdSmrg XtDestroyWidget(shell); 4979aa228fdSmrg} 4989aa228fdSmrg 4999aa228fdSmrg 5009aa228fdSmrg 5019aa228fdSmrg/* 5029aa228fdSmrg * ReplaceCB() -- Replace this particular xmag dialog. 5039aa228fdSmrg */ 5049aa228fdSmrgstatic void /* ARGSUSED */ 5059aa228fdSmrgReplaceCB(Widget w, XtPointer clientData, XtPointer callData) 5069aa228fdSmrg{ 5079aa228fdSmrg hlPtr data = (hlPtr)clientData; 5089aa228fdSmrg StartRootPtrGrab(False, data); 5099aa228fdSmrg} 5109aa228fdSmrg 5119aa228fdSmrg 5129aa228fdSmrg 5139aa228fdSmrg/* 5149aa228fdSmrg * NewCB() -- Create an additional xmag dialog. 5159aa228fdSmrg */ 5169aa228fdSmrgstatic void /* ARGSUSED */ 5179aa228fdSmrgNewCB(Widget w, XtPointer clientData, XtPointer callData) 5189aa228fdSmrg{ 5199aa228fdSmrg StartRootPtrGrab(True, NULL); 5209aa228fdSmrg} 5219aa228fdSmrg 5229aa228fdSmrg 5239aa228fdSmrg 5249aa228fdSmrg/* 5259aa228fdSmrg * SelectCB() -- Own the primary selection. 5269aa228fdSmrg */ 5279aa228fdSmrgstatic void /* ARGSUSED */ 5289aa228fdSmrgSelectCB(Widget w, XtPointer clientData, XtPointer callData) 5299aa228fdSmrg{ 5309aa228fdSmrg hlPtr data = (hlPtr)clientData; 5319aa228fdSmrg SWGrabSelection(data->scaleInstance, XtLastTimestampProcessed(dpy)); 5329aa228fdSmrg} 5339aa228fdSmrg 5349aa228fdSmrg 5359aa228fdSmrg 5369aa228fdSmrg/* 5379aa228fdSmrg * PasteCB() -- Paste from the primary selectin into xmag. 5389aa228fdSmrg */ 5399aa228fdSmrgstatic void /* ARGSUSED */ 5409aa228fdSmrgPasteCB(Widget w, XtPointer clientData, XtPointer callData) 5419aa228fdSmrg{ 5429aa228fdSmrg hlPtr data = (hlPtr)clientData; 5439aa228fdSmrg SWRequestSelection(data->scaleInstance, XtLastTimestampProcessed(dpy)); 5449aa228fdSmrg} 5459aa228fdSmrg 5469aa228fdSmrg 5479aa228fdSmrg 5489aa228fdSmrg/* 5499aa228fdSmrg * SetupGC() -- Graphics context for magnification selection. 5509aa228fdSmrg */ 5510c7e83b2Smrgstatic void 5529aa228fdSmrgSetupGC(void) 5539aa228fdSmrg{ 5549aa228fdSmrg selectGCV.function = GXxor; 5559aa228fdSmrg selectGCV.foreground = 0xffffffff; 5569aa228fdSmrg selectGCV.subwindow_mode = IncludeInferiors; 5579aa228fdSmrg selectGC = XtGetGC(toplevel, GCFunction|GCForeground|GCSubwindowMode, 5589aa228fdSmrg &selectGCV); 5590c7e83b2Smrg} 5609aa228fdSmrg 5619aa228fdSmrg 5629aa228fdSmrg 5639aa228fdSmrg/* 5640c7e83b2Smrg * FindWindow() -- Determine window the pointer is over. 5659aa228fdSmrg * 5669aa228fdSmrg */ 5670c7e83b2Smrgstatic Window 5680c7e83b2SmrgFindWindow(int x, int y) /* Location of cursor */ 5699aa228fdSmrg{ 5709aa228fdSmrg XWindowAttributes wa; 5719aa228fdSmrg Window findW = DefaultRootWindow(dpy), stopW, childW; 5729aa228fdSmrg 5739aa228fdSmrg /* Setup for first window find */ 5749aa228fdSmrg stopW = findW; 5759aa228fdSmrg 5769aa228fdSmrg while (stopW) { 5770c7e83b2Smrg XTranslateCoordinates(dpy, findW, stopW, 5789aa228fdSmrg x, y, &x, &y, &childW); 5799aa228fdSmrg findW = stopW; 5809aa228fdSmrg /* If child is not InputOutput (for example, InputOnly) */ 5819aa228fdSmrg /* then don't continue, return the present findW which */ 5829aa228fdSmrg /* can be the root, or a root child of class InputOutput */ 5839aa228fdSmrg if (childW && 5849aa228fdSmrg XGetWindowAttributes(dpy, childW, &wa) && 5859aa228fdSmrg wa.class != InputOutput) 5869aa228fdSmrg break; 5879aa228fdSmrg stopW = childW; 5889aa228fdSmrg } 5899aa228fdSmrg return findW; 5909aa228fdSmrg} 5919aa228fdSmrg 5929aa228fdSmrg 5939aa228fdSmrg 5949aa228fdSmrg/* 5959aa228fdSmrg * ResizeEH() -- Event Handler for resize of selection box. 5969aa228fdSmrg */ 5970c7e83b2Smrgstatic void 5980c7e83b2SmrgResizeEH(Widget w, XtPointer closure, XEvent *event, 5999aa228fdSmrg Boolean *continue_to_dispatch) /* ARGSUSED */ 6009aa228fdSmrg{ 6019aa228fdSmrg hlPtr data = (hlPtr)closure; 6029aa228fdSmrg switch (event->type) { 6039aa228fdSmrg case MotionNotify: 6049aa228fdSmrg data->x = event->xmotion.x_root; 6050c7e83b2Smrg data->y = event->xmotion.y_root; 6069aa228fdSmrg break; 6079aa228fdSmrg case ButtonRelease: 6089aa228fdSmrg GetImageAndAttributes(FindWindow(event->xmotion.x_root, 6099aa228fdSmrg event->xmotion.y_root), 6109aa228fdSmrg min(data->homeX,event->xbutton.x_root), 6119aa228fdSmrg min(data->homeY,event->xbutton.y_root), 6129aa228fdSmrg abs(data->homeX - event->xbutton.x_root), 6139aa228fdSmrg abs(data->homeY - event->xbutton.y_root), 6149aa228fdSmrg data); 6159aa228fdSmrg if (data->newScale) 6169aa228fdSmrg PopupNewScale(data); 6170c7e83b2Smrg else 6189aa228fdSmrg SWSetImage(data->scaleInstance, data->image); 6199aa228fdSmrg XtUngrabPointer(w, CurrentTime); 6209aa228fdSmrg/***** 6219aa228fdSmrg XtRemoveRawEventHandler(w, PointerMotionMask|ButtonReleaseMask, 6229aa228fdSmrg True, ResizeEH, (XtPointer)data); 6239aa228fdSmrg*****/ 6249aa228fdSmrg XtRemoveEventHandler(w, PointerMotionMask|ButtonReleaseMask, 6259aa228fdSmrg True, ResizeEH, (XtPointer)data); 6269aa228fdSmrg data->selectMode = done; 6279aa228fdSmrg break; 6289aa228fdSmrg } 6299aa228fdSmrg} 6309aa228fdSmrg 6319aa228fdSmrg 6329aa228fdSmrg 6339aa228fdSmrg/* 6340c7e83b2Smrg * DragEH() -- Event Handler for dragging selection box. 6359aa228fdSmrg */ 6360c7e83b2Smrgstatic void 6370c7e83b2SmrgDragEH(Widget w, XtPointer closure, XEvent *event, 6389aa228fdSmrg Boolean *continue_to_dispatch) /* ARGSUSED */ 6399aa228fdSmrg{ 6409aa228fdSmrg hlPtr data = (hlPtr)closure; 6419aa228fdSmrg switch (event->type) { 6429aa228fdSmrg case MotionNotify: /* drag mode */ 6439aa228fdSmrg data->x = event->xmotion.x_root; 6449aa228fdSmrg data->y = event->xmotion.y_root; 6459aa228fdSmrg break; 6469aa228fdSmrg case ButtonRelease: /* end drag mode */ 6479aa228fdSmrg if (event->xbutton.button == Button1) { /* get image */ 6489aa228fdSmrg /* Problem: You can't get bits with XGetImage outside of its window. 6499aa228fdSmrg * xmag will only do a GetImage on the actual window in the case 6509aa228fdSmrg * where the depth of the window does not match the depth of 6519aa228fdSmrg * the root window. 6529aa228fdSmrg */ 6530c7e83b2Smrg GetImageAndAttributes(FindWindow(event->xmotion.x_root, 6549aa228fdSmrg event->xmotion.y_root), 6550c7e83b2Smrg event->xbutton.x_root, 6569aa228fdSmrg event->xbutton.y_root, 6579aa228fdSmrg srcWidth, srcHeight, data); 6589aa228fdSmrg if (data->newScale) 6599aa228fdSmrg PopupNewScale(data); 6609aa228fdSmrg else 6619aa228fdSmrg RedoOldScale(data); 6629aa228fdSmrg XtUngrabPointer(w, CurrentTime); 6639aa228fdSmrg XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask| 6649aa228fdSmrg ButtonReleaseMask, True, DragEH, 6659aa228fdSmrg (XtPointer)data); 6669aa228fdSmrg data->selectMode = done; 6679aa228fdSmrg } 6689aa228fdSmrg 6699aa228fdSmrg break; 6700c7e83b2Smrg case ButtonPress: 6719aa228fdSmrg if (event->xbutton.button == Button2) { /* turn on resize mode */ 6720c7e83b2Smrg data->homeX = event->xbutton.x_root; 6739aa228fdSmrg data->homeY = event->xbutton.y_root; 6749aa228fdSmrg data->x = event->xbutton.x_root + srcWidth; 6750c7e83b2Smrg data->y = event->xbutton.y_root + srcHeight; 6769aa228fdSmrg data->selectMode = resize; 6779aa228fdSmrg XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask| 6789aa228fdSmrg ButtonReleaseMask, True, DragEH, (XtPointer)data); 6799aa228fdSmrg XChangeActivePointerGrab 6809aa228fdSmrg (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 6819aa228fdSmrg lrAngle, CurrentTime); 6820c7e83b2Smrg XWarpPointer(dpy, None, None, 0, 0, 0, 0, 6839aa228fdSmrg srcWidth, srcHeight); 6840c7e83b2Smrg XtAddEventHandler(w, PointerMotionMask|ButtonReleaseMask, 6859aa228fdSmrg True, ResizeEH, (XtPointer)data); 6869aa228fdSmrg } 6879aa228fdSmrg break; 6889aa228fdSmrg } 6899aa228fdSmrg} 6909aa228fdSmrg 6919aa228fdSmrg 6929aa228fdSmrg 6939aa228fdSmrg 6949aa228fdSmrg/* 6959aa228fdSmrg * StartRootPtrGrab() -- Bring up the selection box. 6960c7e83b2Smrg * 6979aa228fdSmrg */ 6989aa228fdSmrgstatic void 6990c7e83b2SmrgStartRootPtrGrab(int new, /* do we create a new scale instance? */ 7000c7e83b2Smrg hlPtr data) /* highlight data */ 7019aa228fdSmrg{ 7029aa228fdSmrg Window rootR, childR; 7039aa228fdSmrg int rootX, rootY, winX, winY; 7049aa228fdSmrg unsigned int mask; 7059aa228fdSmrg hlPtr hlData; 7069aa228fdSmrg XtGrabPointer 7079aa228fdSmrg (root, False, 7089aa228fdSmrg PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 7099aa228fdSmrg GrabModeAsync, GrabModeAsync, None, ulAngle, CurrentTime); 7100c7e83b2Smrg XQueryPointer(dpy, DefaultRootWindow(dpy), &rootR, &childR, 7119aa228fdSmrg &rootX, &rootY, &winX, &winY, &mask); 7129aa228fdSmrg if (new) { 7139aa228fdSmrg numXmags++; 7149aa228fdSmrg hlData = (hlPtr)XtMalloc(sizeof(hlStruct)); 7159aa228fdSmrg } 7169aa228fdSmrg else hlData = data; 7179aa228fdSmrg hlData->newScale = new; 7189aa228fdSmrg hlData->selectMode = drag; 7199aa228fdSmrg hlData->x = rootX; 7209aa228fdSmrg hlData->y = rootY; 7219aa228fdSmrg hlData->gc = selectGC; 7229aa228fdSmrg hlData->width = srcWidth; 7239aa228fdSmrg hlData->height = srcHeight; 7249aa228fdSmrg XtAddRawEventHandler 7250c7e83b2Smrg (root, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 7269aa228fdSmrg True, DragEH, (XtPointer)hlData); 7279aa228fdSmrg (void) XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)hlData); 7289aa228fdSmrg} 7299aa228fdSmrg 7309aa228fdSmrg 7319aa228fdSmrg 7329aa228fdSmrg/* 7339aa228fdSmrg * CreateRoot() -- Create a root window widget. If the user specified x and y 7340c7e83b2Smrg * in the source geometry then use this to directly get the 7359aa228fdSmrg * image. 7369aa228fdSmrg */ 7379aa228fdSmrgstatic void 7389aa228fdSmrgCreateRoot(void) 7399aa228fdSmrg{ 7409aa228fdSmrg hlPtr data; 7419aa228fdSmrg root = XtCreateWidget("root", rootWindowWidgetClass, toplevel, NULL, 0); 7429aa228fdSmrg XtRealizeWidget(root); 7430c7e83b2Smrg if (XValue & srcStat && YValue &srcStat) { 7449aa228fdSmrg numXmags = 1; 7459aa228fdSmrg data = (hlPtr)XtMalloc(sizeof(hlStruct)); 7469aa228fdSmrg data = data; 7479aa228fdSmrg data->newScale = True; 7489aa228fdSmrg data->selectMode = drag; 7499aa228fdSmrg data->x = srcX; 7509aa228fdSmrg data->y = srcY; 7519aa228fdSmrg data->gc = selectGC; 7529aa228fdSmrg data->width = srcWidth; 7539aa228fdSmrg data->height = srcHeight; 7540c7e83b2Smrg GetImageAndAttributes(RootWindow(dpy, scr), srcX, srcY, srcWidth, 7559aa228fdSmrg srcHeight, data); 7569aa228fdSmrg PopupNewScale(data); 7579aa228fdSmrg return; 7589aa228fdSmrg } 7599aa228fdSmrg} 7609aa228fdSmrg 7619aa228fdSmrg 7620c7e83b2Smrg/* 7639aa228fdSmrg * GetImageAndAttributes() -- Get the image bits from the screen. 7640c7e83b2Smrg * We will also determine here the colormap, depth, and 7650c7e83b2Smrg * visual to be used for the magnification image. 7669aa228fdSmrg */ 7670c7e83b2Smrgstatic void 7680c7e83b2SmrgGetImageAndAttributes(Window w, int x, int y, int width, int height, 7699aa228fdSmrg hlPtr data) 7709aa228fdSmrg{ 77183d7c197Smrg /* get parameters of window being magnified */ 77283d7c197Smrg XGetWindowAttributes(dpy, w, &data->win_info); 77383d7c197Smrg 77483d7c197Smrg if (data->win_info.depth == DefaultDepth(dpy, scr)) { 77583d7c197Smrg /* avoid off screen pixels */ 77683d7c197Smrg if (x < 0) 77783d7c197Smrg x = 0; 77883d7c197Smrg if (y < 0) 77983d7c197Smrg y = 0; 78083d7c197Smrg if (x + width > DisplayWidth(dpy,scr)) 78183d7c197Smrg x = DisplayWidth(dpy,scr) - width; 78283d7c197Smrg if (y + height > DisplayHeight(dpy,scr)) 78383d7c197Smrg y = DisplayHeight(dpy,scr) - height; 78483d7c197Smrg data->x = x; data->y = y; 78583d7c197Smrg /* get image pixels */ 78683d7c197Smrg data->image = XGetImage (dpy, 78783d7c197Smrg RootWindow(dpy, scr), 78883d7c197Smrg x, y, 78983d7c197Smrg width, height, 79083d7c197Smrg AllPlanes, ZPixmap); 79183d7c197Smrg } 79283d7c197Smrg else { 79383d7c197Smrg int t0, t1; 79483d7c197Smrg int x0, x1, y0, y1; 79583d7c197Smrg int xInWin, yInWin; 79683d7c197Smrg Window childWin; 79783d7c197Smrg 79883d7c197Smrg XTranslateCoordinates(dpy, DefaultRootWindow(dpy), w, x, y, 79983d7c197Smrg &xInWin, &yInWin, &childWin); 80083d7c197Smrg 80183d7c197Smrg /* Avoid off screen pixels. Assume this routine is not 80283d7c197Smrg * called for totally offscreen windows. */ 80383d7c197Smrg x0 = max(x, 0); 80483d7c197Smrg y0 = max(y, 0); 80583d7c197Smrg x1 = min(DisplayWidth(dpy, scr), 80683d7c197Smrg min(x0 + width, x0 + (data->win_info.width - xInWin))); 80783d7c197Smrg y1 = min(DisplayHeight(dpy, scr), 80883d7c197Smrg min(y0 + height, y0 + (data->win_info.height - yInWin))); 80983d7c197Smrg 81083d7c197Smrg /* Try to use up to width x height pixels */ 81183d7c197Smrg if (x1 - x0 < width) { 81283d7c197Smrg t0 = x0; 81383d7c197Smrg t1 = max(0, x - xInWin + data->win_info.width - 81483d7c197Smrg DisplayWidth(dpy, scr)); 81583d7c197Smrg x0 = max(0, x1 - min(width, data->win_info.width - t1)); 81683d7c197Smrg xInWin -= t0 - x0; 81783d7c197Smrg } 81883d7c197Smrg if (y1 - y0 < height) { 81983d7c197Smrg t0 = y0; 82083d7c197Smrg t1 = max(0, y - yInWin + data->win_info.height - 82183d7c197Smrg DisplayHeight(dpy, scr)); 82283d7c197Smrg y0 = max(0, y1 - min(height, data->win_info.height - t1)); 82383d7c197Smrg yInWin -= t0 - y0; 82483d7c197Smrg } 82583d7c197Smrg 82683d7c197Smrg data->x = x0; 82783d7c197Smrg data->y = y0; 82883d7c197Smrg data->width = x1 - x0; 82983d7c197Smrg data->height = y1 - y0; 83083d7c197Smrg 83183d7c197Smrg data->image = XGetImage (dpy, 83283d7c197Smrg w, 83383d7c197Smrg xInWin, yInWin, 83483d7c197Smrg data->width, data->height, 83583d7c197Smrg AllPlanes, ZPixmap); 83683d7c197Smrg 83783d7c197Smrg } 8389aa228fdSmrg} 8399aa228fdSmrg 8409aa228fdSmrg 8419aa228fdSmrg 8429aa228fdSmrg/* 8439aa228fdSmrg * Get_XColors() Get the XColors of all pixels in image - returns # of colors 8449aa228fdSmrg * This function was taken from xwd (thanks Bob...) 8459aa228fdSmrg */ 8469aa228fdSmrg#define lowbit(x) ((x) & (~(x) + 1)) 8470c7e83b2Smrgstatic int 8489aa228fdSmrgGet_XColors(XWindowAttributes *win_info, XColor **colors) 8499aa228fdSmrg{ 8509aa228fdSmrg int i, ncolors; 8510c7e83b2Smrg 8529aa228fdSmrg if (!win_info->colormap) 8539aa228fdSmrg return(0); 8540c7e83b2Smrg 8559aa228fdSmrg ncolors = win_info->visual->map_entries; 8569aa228fdSmrg if (!(*colors = (XColor *) XtMalloc (sizeof(XColor) * ncolors))) 8579aa228fdSmrg XtError("Out of memory!"); 8580c7e83b2Smrg 8599aa228fdSmrg if (win_info->visual->class == DirectColor || 8609aa228fdSmrg win_info->visual->class == TrueColor) { 8619aa228fdSmrg Pixel red, green, blue, red1, green1, blue1; 8620c7e83b2Smrg 8639aa228fdSmrg red = green = blue = 0; 8649aa228fdSmrg red1 = lowbit(win_info->visual->red_mask); 8659aa228fdSmrg green1 = lowbit(win_info->visual->green_mask); 8669aa228fdSmrg blue1 = lowbit(win_info->visual->blue_mask); 8679aa228fdSmrg for (i=0; i<ncolors; i++) { 8689aa228fdSmrg (*colors)[i].pixel = red|green|blue; 8699aa228fdSmrg (*colors)[i].pad = 0; 8709aa228fdSmrg red += red1; 8719aa228fdSmrg if (red > win_info->visual->red_mask) 8729aa228fdSmrg red = 0; 8739aa228fdSmrg green += green1; 8749aa228fdSmrg if (green > win_info->visual->green_mask) 8759aa228fdSmrg green = 0; 8769aa228fdSmrg blue += blue1; 8779aa228fdSmrg if (blue > win_info->visual->blue_mask) 8789aa228fdSmrg blue = 0; 8799aa228fdSmrg } 8809aa228fdSmrg } else { 8819aa228fdSmrg for (i=0; i<ncolors; i++) { 8829aa228fdSmrg (*colors)[i].pixel = i; 8839aa228fdSmrg (*colors)[i].pad = 0; 8849aa228fdSmrg } 8859aa228fdSmrg } 8860c7e83b2Smrg 8879aa228fdSmrg XQueryColors(dpy, win_info->colormap, *colors, ncolors); 8880c7e83b2Smrg 8899aa228fdSmrg return(ncolors); 8909aa228fdSmrg} 8919aa228fdSmrg 8929aa228fdSmrg 8939aa228fdSmrg 8949aa228fdSmrg#define Intensity(cptr) (3.0*cptr->red+0.59*cptr->green+0.11*cptr->blue) 8959aa228fdSmrg 8969aa228fdSmrg/* 8979aa228fdSmrg * GetMaxIntensity() -- Find the maximum intensity pixel value for a colormap. 8989aa228fdSmrg */ 8999aa228fdSmrgstatic Pixel 9009aa228fdSmrgGetMaxIntensity(hlPtr data) 9019aa228fdSmrg{ 9029aa228fdSmrg XColor *colors = NULL, *mptr, *tptr; 9039aa228fdSmrg int i, ncolors; 9049aa228fdSmrg 9050c7e83b2Smrg if (data->win_info.colormap == DefaultColormap(dpy, scr)) 9069aa228fdSmrg return WhitePixel(dpy, scr); 9070c7e83b2Smrg ncolors = Get_XColors(&data->win_info, &colors); 9089aa228fdSmrg mptr = tptr = colors; tptr++; 9099aa228fdSmrg for (i=1; i<ncolors; i++) { 9100c7e83b2Smrg if ((int)Intensity(mptr) < (int)Intensity(tptr)) 9119aa228fdSmrg mptr = tptr; 9129aa228fdSmrg tptr++; 9139aa228fdSmrg } 9149aa228fdSmrg /* Null pointer protection */ 9159aa228fdSmrg if(mptr) 9169aa228fdSmrg return mptr->pixel; 9179aa228fdSmrg else 9189aa228fdSmrg return WhitePixel(dpy, scr); 9199aa228fdSmrg} 9209aa228fdSmrg 9219aa228fdSmrg/* 9229aa228fdSmrg * GetMinIntensity() -- Find the minimum intensity pixel value for a colormap. 9239aa228fdSmrg */ 9249aa228fdSmrgstatic Pixel 9259aa228fdSmrgGetMinIntensity(hlPtr data) 9269aa228fdSmrg{ 9279aa228fdSmrg XColor *colors = NULL, *mptr, *tptr; 9289aa228fdSmrg int i, ncolors; 9299aa228fdSmrg 9300c7e83b2Smrg if (data->win_info.colormap == DefaultColormap(dpy, scr)) 9319aa228fdSmrg return BlackPixel(dpy, scr); 9320c7e83b2Smrg ncolors = Get_XColors(&data->win_info, &colors); 9339aa228fdSmrg mptr = tptr = colors; tptr++; 9349aa228fdSmrg for (i=1; i<ncolors; i++) { 9359aa228fdSmrg if ((int)Intensity(mptr) > (int)Intensity(tptr)) 9360c7e83b2Smrg mptr = tptr; 9379aa228fdSmrg tptr++; 9389aa228fdSmrg } 9399aa228fdSmrg /* Null pointer protection */ 9409aa228fdSmrg if(mptr) 9419aa228fdSmrg return mptr->pixel; 9429aa228fdSmrg else 9439aa228fdSmrg return BlackPixel(dpy, scr); 9449aa228fdSmrg} 9459aa228fdSmrg 9469aa228fdSmrg 9479aa228fdSmrg 9489aa228fdSmrg 9499aa228fdSmrgstatic Widget pane1, pane2, pane3, cclose, replace, new, select_w, paste; 9509aa228fdSmrg 9519aa228fdSmrg/* 9529aa228fdSmrg * PopupNewScale() -- Create and popup a new scale composite. 9539aa228fdSmrg */ 9540c7e83b2Smrgstatic void 9559aa228fdSmrgPopupNewScale(hlPtr data) 9569aa228fdSmrg{ 9579aa228fdSmrg Arg warg; 9589aa228fdSmrg 9590c7e83b2Smrg data->scaleShell = 9600c7e83b2Smrg XtVaCreatePopupShell("xmag", topLevelShellWidgetClass, toplevel, 9619aa228fdSmrg XtNgeometry, (XtArgVal)options.geometry, 9629aa228fdSmrg XtNtitle, (XtArgVal)options.title, 9639aa228fdSmrg NULL); 9649aa228fdSmrg pane1 = XtCreateManagedWidget("pane1", panedWidgetClass, data->scaleShell, 9659aa228fdSmrg (Arg *) NULL, 0); 9669aa228fdSmrg pane2 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1, 9679aa228fdSmrg (Arg *) NULL, 0); 9689aa228fdSmrg cclose = XtCreateManagedWidget("close", commandWidgetClass, pane2, 9699aa228fdSmrg (Arg *) NULL, 0); 9709aa228fdSmrg XtAddCallback(cclose, XtNcallback, CloseCB, (XtPointer)data->scaleShell); 9719aa228fdSmrg replace = XtCreateManagedWidget("replace", commandWidgetClass, pane2, 9729aa228fdSmrg (Arg *) NULL, 0); 9739aa228fdSmrg XtAddCallback(replace, XtNcallback, ReplaceCB, (XtPointer)data); 9749aa228fdSmrg new = XtCreateManagedWidget("new", commandWidgetClass, pane2, 9759aa228fdSmrg (Arg *) NULL, 0); 9769aa228fdSmrg XtAddCallback(new, XtNcallback, NewCB, (XtPointer)NULL); 9779aa228fdSmrg select_w = XtCreateManagedWidget("select", commandWidgetClass, pane2, 9789aa228fdSmrg (Arg *) NULL, 0); 9799aa228fdSmrg XtAddCallback(select_w, XtNcallback, SelectCB, (XtPointer)data); 9809aa228fdSmrg paste = XtCreateManagedWidget("paste", commandWidgetClass, pane2, 9819aa228fdSmrg (Arg *) NULL, 0); 9829aa228fdSmrg XtAddCallback(paste, XtNcallback, PasteCB, (XtPointer)data); 9839aa228fdSmrg (void) XtCreateManagedWidget("helpLabel", labelWidgetClass, pane2, 9849aa228fdSmrg (Arg *) NULL, 0); 9859aa228fdSmrg pane3 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1, 9869aa228fdSmrg (Arg *) NULL, 0); 9870c7e83b2Smrg data->scaleInstance = 9880c7e83b2Smrg XtVaCreateManagedWidget("scale", scaleWidgetClass, 9899aa228fdSmrg pane3, 9909aa228fdSmrg XtNvisual, (XtArgVal)data->win_info.visual, 9919aa228fdSmrg XtNcolormap, (XtArgVal)data->win_info.colormap, 9929aa228fdSmrg XtNdepth, (XtArgVal)data->win_info.depth, 9939aa228fdSmrg XtNscaleX, (XtArgVal)options.mag, 9949aa228fdSmrg XtNscaleY, (XtArgVal)options.mag, 9959aa228fdSmrg NULL); 9969aa228fdSmrg SWSetImage(data->scaleInstance, data->image); 9979aa228fdSmrg XtOverrideTranslations 9989aa228fdSmrg (data->scaleShell, 9999aa228fdSmrg XtParseTranslationTable ("<Message>WM_PROTOCOLS: close()")); 10009aa228fdSmrg XtSetArg(warg, XtNuserData, data); 10019aa228fdSmrg XtSetValues(data->scaleInstance, &warg, 1); 10020c7e83b2Smrg data->pixShell = 10030c7e83b2Smrg XtVaCreatePopupShell("pixShell", overrideShellWidgetClass, 10049aa228fdSmrg toplevel, 10059aa228fdSmrg XtNvisual, (XtArgVal)data->win_info.visual, 10069aa228fdSmrg XtNcolormap, (XtArgVal)data->win_info.colormap, 10079aa228fdSmrg XtNdepth, (XtArgVal)data->win_info.depth, 10089aa228fdSmrg XtNborderWidth, (XtPointer)0, 10099aa228fdSmrg NULL); 10100c7e83b2Smrg data->pixLabel = 10110c7e83b2Smrg XtVaCreateManagedWidget("pixLabel", labelWidgetClass, 10120c7e83b2Smrg data->pixShell, 10139aa228fdSmrg XtNforeground, (XtPointer)GetMaxIntensity(data), 10149aa228fdSmrg XtNbackground, (XtPointer)GetMinIntensity(data), 10159aa228fdSmrg XtNborderWidth, (XtPointer)0, 10169aa228fdSmrg NULL); 10179aa228fdSmrg XtInstallAllAccelerators(pane1, pane1); /* install accelerators */ 10189aa228fdSmrg if (data->newScale) { 10199aa228fdSmrg XtPopup(data->scaleShell, XtGrabNone); 10209aa228fdSmrg (void) XSetWMProtocols /* ICCCM delete window */ 10219aa228fdSmrg (dpy, XtWindow(data->scaleShell), &wm_delete_window, 1); 10229aa228fdSmrg } 10239aa228fdSmrg if (data->win_info.colormap != DefaultColormap(dpy, scr)) { 10240c7e83b2Smrg data->cmapWinList[0] = data->scaleShell; 10259aa228fdSmrg data->cmapWinList[1] = data->scaleInstance; 10269aa228fdSmrg XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2); 10279aa228fdSmrg } 10289aa228fdSmrg} 10299aa228fdSmrg 10309aa228fdSmrg 10319aa228fdSmrg 10329aa228fdSmrg/* 10339aa228fdSmrg * RedoOldScale() -- If the visual, depth, or colormap has changed, unrealize 10349aa228fdSmrg * the scale widget and change its colormap/depth/visual. 10359aa228fdSmrg * Then re-realize it. Also do this for the pixel display 10369aa228fdSmrg * widget. 10379aa228fdSmrg */ 10389aa228fdSmrgstatic void 10399aa228fdSmrgRedoOldScale(hlPtr data) 10409aa228fdSmrg{ 10419aa228fdSmrg Arg wargs[3]; 10429aa228fdSmrg int n; 10439aa228fdSmrg Visual *oldVis; 10449aa228fdSmrg int oldDepth; 10459aa228fdSmrg Colormap oldCmap; 10469aa228fdSmrg 10479aa228fdSmrg n=0; 10489aa228fdSmrg XtSetArg(wargs[n], XtNvisual, &oldVis); n++; 10499aa228fdSmrg XtSetArg(wargs[n], XtNdepth, &oldDepth); n++; 10509aa228fdSmrg XtSetArg(wargs[n], XtNcolormap, &oldCmap); n++; 10510c7e83b2Smrg XtGetValues(data->scaleInstance, wargs, n); 10529aa228fdSmrg if (oldVis == data->win_info.visual && oldDepth == data->win_info.depth 10539aa228fdSmrg && oldCmap == data->win_info.colormap) { 10540c7e83b2Smrg SWSetImage(data->scaleInstance, data->image); 10559aa228fdSmrg return; 10569aa228fdSmrg } 10579aa228fdSmrg /* get width and height, save and reuse them */ 10589aa228fdSmrg XtUnmanageChild(data->scaleInstance); 10599aa228fdSmrg XtUnrealizeWidget(data->scaleInstance); 10609aa228fdSmrg n=0; 10619aa228fdSmrg XtSetArg(wargs[n], XtNcolormap, data->win_info.colormap); n++; 10629aa228fdSmrg XtSetArg(wargs[n], XtNdepth, data->win_info.depth); n++; 10639aa228fdSmrg XtSetArg(wargs[n], XtNvisual, data->win_info.visual); n++; 10649aa228fdSmrg XtSetValues(data->scaleInstance, wargs, n); 10659aa228fdSmrg n=0; 10669aa228fdSmrg XtSetArg(wargs[n], XtNforeground, GetMaxIntensity(data)); n++; 10679aa228fdSmrg XtSetArg(wargs[n], XtNbackground, GetMinIntensity(data)); n++; 10689aa228fdSmrg XtSetValues(data->pixLabel, wargs, n); 10690c7e83b2Smrg SWSetImage(data->scaleInstance, data->image); 10709aa228fdSmrg XtRealizeWidget(data->scaleInstance); 10719aa228fdSmrg XtManageChild(data->scaleInstance); 10729aa228fdSmrg} 10739aa228fdSmrg 10749aa228fdSmrg 10759aa228fdSmrg 10769aa228fdSmrg/* 10779aa228fdSmrg * InitCursors() -- Create our cursors for area selection. 10789aa228fdSmrg */ 10799aa228fdSmrgstatic void 10809aa228fdSmrgInitCursors(void) 10819aa228fdSmrg{ 10829aa228fdSmrg ulAngle = XCreateFontCursor(dpy, XC_ul_angle); 10839aa228fdSmrg urAngle = XCreateFontCursor(dpy, XC_ur_angle); 10849aa228fdSmrg lrAngle = XCreateFontCursor(dpy, XC_lr_angle); 10859aa228fdSmrg llAngle = XCreateFontCursor(dpy, XC_ll_angle); 10869aa228fdSmrg} 10879aa228fdSmrg 10889aa228fdSmrg 10899aa228fdSmrg 10909aa228fdSmrg/* 10910c7e83b2Smrg * ParseSourceGeom() -- Determine dimensions of area to magnify from resources. 10929aa228fdSmrg */ 10930c7e83b2Smrgstatic void 10949aa228fdSmrgParseSourceGeom(void) 10959aa228fdSmrg{ 10969aa228fdSmrg /* source */ 10970c7e83b2Smrg srcStat = 10989aa228fdSmrg XParseGeometry(options.source, &srcX, &srcY, &srcWidth, &srcHeight); 10999aa228fdSmrg if (!srcWidth) srcWidth = SRCWIDTH; 11009aa228fdSmrg if (!srcHeight) srcHeight = SRCHEIGHT; 11019aa228fdSmrg if (XNegative & srcStat) srcX = DisplayWidth(dpy, scr) + srcX - srcWidth; 11029aa228fdSmrg if (YNegative & srcStat) srcY = DisplayHeight(dpy, scr) + srcY - srcHeight; 11039aa228fdSmrg /* mag */ 11049aa228fdSmrg} 11059aa228fdSmrg 11069aa228fdSmrg 11079aa228fdSmrg 11089aa228fdSmrg/* 11099aa228fdSmrg * Main program. 11109aa228fdSmrg */ 11110c7e83b2Smrgint 11129aa228fdSmrgmain(int argc, char *argv[]) 11139aa228fdSmrg{ 11149aa228fdSmrg XSetErrorHandler(Error); 11150c7e83b2Smrg 11169aa228fdSmrg /* SUPPRESS 594 */ 11179aa228fdSmrg toplevel = XtAppInitialize(&app, "Xmag", optionDesc, XtNumber(optionDesc), 11189aa228fdSmrg &argc, argv, NULL, 11199aa228fdSmrg NULL, 0); 11209aa228fdSmrg 11219aa228fdSmrg dpy = XtDisplay(toplevel); 11229aa228fdSmrg scr = DefaultScreen(dpy); 11239aa228fdSmrg XtGetApplicationResources(toplevel, (XtPointer) &options, resources, 11249aa228fdSmrg XtNumber(resources), NULL, 0); 11259aa228fdSmrg if (argc != 1) { 11269aa228fdSmrg fprintf (stderr, 11279aa228fdSmrg "usage: xmag [-source geom] [-mag magfactor] [-toolkitoption]\n"); 11289aa228fdSmrg exit(1); 11299aa228fdSmrg } 11300c7e83b2Smrg 11319aa228fdSmrg 11329aa228fdSmrg ParseSourceGeom(); 11339aa228fdSmrg XtAppAddActions(app, actions_table, XtNumber(actions_table)); 11349aa228fdSmrg InitCursors(); 11359aa228fdSmrg SetupGC(); 11369aa228fdSmrg CreateRoot(); 11379aa228fdSmrg if (!(XValue & srcStat && YValue & srcStat)) 11389aa228fdSmrg StartRootPtrGrab(True, (hlPtr)NULL); 11399aa228fdSmrg wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 11409aa228fdSmrg XtAppMainLoop(app); 11419aa228fdSmrg exit(0); 11429aa228fdSmrg} 1143