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