/*
* xmag - simple magnifying glass application
*
* $XConsortium: xmag.c,v 1.29 89/12/10 17:23:58 rws Exp $
*
* Copyright 1988 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. M.I.T. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* Author: Jim Fulton, MIT X Consortium
*
* Revision History:
* 11-15-90 MultiVis changes made by: Milind M. Pansare
* milind@Eng.Sun.COM
*
*/
/*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <X11/cursorfont.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef ALLPLANES
#endif
#include "multivis.h"
#ifdef __SUNPRO_C
/* prevent "Function has no return statement" error for shhh() */
#pragma does_not_return(exit)
#endif
/* w1 is TrueColor 24 bit */
/* mw is the window that is finally
mapped , w or w1 */
/* start MultiVisual Fix */
int num_vis;
We'll use this for output */
static XImage *CreateImageFromImg(void);
#ifdef ALLPLANES
#endif /* ALLPLANES */
/* end MultiVisual Fix */
char *back_color);
unsigned long back_pixel);
unsigned long back_pixel);
static int IsMultiVis (int multivisFromMvLib);
static void DrawPixWindow (char *str);
static void UnmapPixWindow (void);
static void
{
if (dpy) {
XCloseDisplay (dpy);
}
}
static void
Usage (void)
{
static const char *help_message[] = {
"where options include:",
" -display displaystring X server to contact",
" -geometry geomstring size and location of enlargement",
" -source geomstring size and location of area to be enlarged",
" -mag magfactor integral amount by which area is enlarged",
" -bw pixels border width in pixels",
" -bd color border color",
" -bg colororpixelvalue background color or %pixel number",
" -fn fontname name of font for examining enlarged pixels",
" -z grab server during dynamics and XGetImage",
"",
"Options may be abbreviated to the shortest unambiguous prefix.",
"",
}, **cpp;
}
Exit (1);
}
int
{
int i; /* iterator variable */
ProgramName = argv[0];
for (i = 1; i < argc; i++) {
switch (arg[1]) {
case 'd': /* -display displaystring */
displayname = argv[i];
continue;
case 'g': /* -geometry geomstring */
continue;
case 's': /* -source geomstring */
source_geometry = argv[i];
continue;
case 'm': /* -mag magnification */
continue;
case 'b':
switch (arg[2]) {
case 'w': /* -bw pixels */
continue;
case 'd': /* -bd color */
border_color = argv[i];
continue;
case 'g': /* -bg colororpixel*/
back_color = argv[i];
continue;
} /* end switch */
Usage ();
/* NOTREACHED */
case 'z': /* -z */
continue;
case 'f': /* -font fontname */
continue;
default:
Usage ();
/* NOTREACHED */
} /* end switch */
} else { /* any command line parameters */
Usage ();
/* NOTREACHED */
} /* end if else */
} /* end for */
if (!dpy) {
Exit (1);
}
/*
* set the fatal error handler to be an innocuous wimp that
* exits quietly
*/
/*
XSetIOErrorHandler(shhh);
*/
#ifdef ALLPLANES
{
int tmp;
}
#endif /* ALLPLANES */
/*
* get defaults (would be nice to use the resource manager instead)
*/
if (!source_geometry)
if (!source_geometry)
if (magnification < 1) {
}
if (border_width < 0) {
}
if (!border_color)
if (!border_color)
if (!back_color)
if (!back_color)
/*
* set up globals
*/
Exit(1);
/* start MultiVisual fix */
/* The default visual is TrueColor, 24 bit... */
def_vis_is_ok = 1;
}
/* end MultiVisual fix */
}
else
/* start MultiVisual Fix */
== NULL)
/* end MultiVisual Fix */
/*
* do the work
*/
Exit (0);
}
/*
* Do the setup for the magnification. Use the geometry, source_geometry,
* and magnification to figure out how big of an area to magnify, and by
* how much it should be enlarged according to the following relations:
*
* magnification = window.geometry.width / source_geometry.width
* magnification = window.geometry.height / source_geometry.height
*
* Thus, only two of the three values may be specified by the user. The
* following values are used to indicate that the default should be taken:
*
* Variable blank value default value
*
* magnification 0 5
* window NULL "320x320-0-0"
* source NULL "64x64"
*
* If a location is not specified for the source, a square centered on the
* pointer will be displayed that can be dragged around the screen.
*/
void
char *window_geometry, /* size and location of enlargement */
char *source_geometry, /* size and location of area */
int magnification, /* enlargement ratio */
char *border_color, /* name of color to use for border */
int border_width, /* width of border */
char *back_color) /* color name or pixel value */
{
source_geom_mask = window_geom_mask = 0;
#define valNothing 0
params = valNothing;
if (window_geometry) {
&window_hints.x, &window_hints.y,
(unsigned int *)&window_hints.width,
(unsigned int *)&window_hints.height);
if (tmp) {
if (tmp == SizeValues)
else
}
}
if (source_geometry) {
&source_hints.x, &source_hints.y,
(unsigned int *)&source_hints.width,
(unsigned int *)&source_hints.height);
if (tmp) {
if (tmp == SizeValues)
else
}
}
/*
* Check to make sure that user didn't give -geometry, -source, and -mag
*/
magnification = 0;
params &= ~valMagnification;
}
/*
* Verify the input and compute the appropriate sizes
*/
Exit (1);
}
window_hints.height <= 0)) {
Exit (1);
}
source_hints.height <= 0)) {
Exit (1);
}
switch (params) {
case valMagnification:
goto mag_and_cur;
case valWindow:
/* fall through */
case valMagnification|valWindow:
break;
case valNothing:
/* fall through */
case valSource:
/* fall through */
case valMagnification|valSource:
break;
break;
}
/*
* At this point, both hints structures contain the appropriate width
* and height fields. Now we need to do the placement calculations.
*/
/*
* Set the flags entries so that we know what we have
*/
source_hints.flags = 0;
window_hints.flags = 0;
} else {
}
case 0:
break;
case XNegative:
break;
case YNegative:
break;
default:
break;
}
if (back_color) {
register char *s = back_color + 1;
if (!*s) Usage ();
if (*s == '0') {
s++;
fmt = "%lo";
}
if (*s == 'x' || *s == 'X') {
s++;
fmt = "%lx";
}
}
}
/*
* Make the enlargment window, but don't map it
*/
/* start MultiVisual Fix */
/*
* If the worst has happened, and we have a mix of Visuals to
* work from, then we insist on a TrueColor 24 bit Visual.
*This makes life (a bit) simpler.
*/
if (def_vis_is_ok) {
window_hints.x, window_hints.y,
border_width, 24,
}
else {
/* The default visual is not 24 bit True Color,
Create a colormap for this visual */
valuemask |= CWColormap;
window_hints.x, window_hints.y,
border_width, 24,
}
/* We assume that there's going to be a 24 bit TrueColor Visual
to display the Image we create. Also, that each of R,G,B
masks will be 8 bits. We now need to calculate the
R, G, B offsets & order in the pixel.
CAUTION: We also assume that the upper 8 bits of each of RGB in the
XColor are the significant 8 bits, and discard the lower
8 bits */
/* This visual is no good for us */
if (w1) {
}
}
else {
}
}
/* At this moment, create both windows.. later decide which one to map */
/* end MultiVisual Fix */
window_hints.x, window_hints.y,
/* start MultiVisual Fix */
if (w1) {
}
/* end MultiVisual Fix */
/*
* Make up a dummy GC
*/
/* repaint_image fills in foreground */
&gcv);
/* start MultiVisual Fix */
if (w1)
&gcv);
/* end MultiVisual Fix */
/*
* Do the work. If the user specified the location of the source,
* then just that one spot, otherwise do some dynamics.
*/
if (do_grab) {
}
} else {
do {
if (do_grab) {
}
back_pixel));
}
return;
}
static void
{
register int x, y;
unsigned int mask;
if (!invGC) { /* make it the first time */
GCForeground), &gcv);
if (!invGC) {
Exit (1);
}
}
Exit (1);
}
/*
* Do the loop looking for a button press, drawing the image each time;
* since other clients may be running, make sure that the xor segments all
* get drawn at the same time.
*/
case ButtonRelease:
break;
default:
continue;
} /* end switch */
Exit (1);
}
register int i;
/* clip to screen */
if (x < 0) x = 0;
if (y < 0) y = 0;
/* fill in the outline box */
for (i = 0; i < NPOINTS; i += 4) {
if (i == (NPOINTS - 1)) break;
}
}
#ifdef ALLPLANES
if (allplanes) {
}
else {
#endif /* ALLPLANES */
#ifdef ALLPLANES
}
#endif /* ALLPLANES */
}
shp->x = x;
shp->y = y;
return;
}
static Bool
int magnification,
unsigned long back_pixel)
{
int i;
/*
* Don't get bits that are off the edges of the screen
*/
if (x < 0) x = 0;
if (y < 0) y = 0;
/* start MultiVisual Fix */
/* Initialise the MultiVisual Routines */
/* Get a list of intersecting windows, with their visual details */
#ifdef SHAPE
#else /* ! SHAPE */
#endif /* SHAPE */
/* Check if we have a multiVis on our hands */
if (multiVis) {
/* Creat an Image where mvDoWindows.. will operate */
printf("mvCreatImg failed\n");
Exit(1);
}
/* Convert the map into an XImage */
image = CreateImageFromImg();
}
else {
"%s: Warning -- source windows differ in VisualClass or ColorMap\n",
}
}
else if (num_vis == 1) {
}
else { /* Duh ? */
printf("Where are all the visuals ? \n");
Exit(1);
}
/* end MultiVisual Fix */
if (do_grab) {
XUngrabServer (dpy);
}
if (!image) { /* clean up */
/* start MultiVisual fix */
/* Nothing to do, as we assume that the program will exit when we return */
/* end MultiVisual fix */
return (False);
}
/*
* Map the window and do the work. Space means do another;
* Button1 press displays pixel value.
* q, Q, or ^C mean quit.
*/
/* start MultiVisual Fix */
if (multiVis) {
if (!w1) { /* But we *insisted* on a TrueColor Window ! */
printf("Couldn't get a TrueColor 24 bit window...\n");
Exit(1);
}
}
else {
mw = w;
}
/* end MultiVisual Fix */
case ClientMessage:
exit(0);
}
break;
case Expose:
break;
case ButtonRelease:
break;
case ButtonPress:
continue;
first = 1;
while (1) { /* loop until button released */
unsigned int mask;
x /= magnification; y /= magnification;
/* look for new pixel */
/* start MultiVisual Fix */
if (multiVis) {
"Pixel at (%d,%d): %3lx (%04x, %04x, %04x)",
}
/* end MultiVisual Fix */
else {
"Pixel at (%d,%d): %3lx (%04x, %04x, %04x)",
} else {
}
}
DrawPixWindow (str);
}
} else
break;
}
UnmapPixWindow ();
break;
case KeyPress:
keybuffer[0] == '\003')) {
} /* else ignore */
break;
}
}
/*
* free the image and return
*/
/* start MultiVisual Fix */
if (num_vis > 1) {
/* Reset the mvLib */
mvReset();
}
if (!multiVis) {
}
/* end MultiVisual Fix */
return (domore);
}
static void
int magnification,
unsigned long back_pixel)
{
/*
* figure out where in the image we have to start and end
*/
/*
* clip to image size
*/
/*
* Repaint the image; be somewhat clever by only drawing when the pixel
* changes or when we run out of lines.
*/
/*
* iterate over scanlines (rows)
*/
r_width = 0; /* have done nothing so far */
/*
* iterate over pixels in scanline (columns)
*/
/*
* If the current pixel is different from the previous pixel,
* then we need to set the drawing color and do the previous
* rectangle. We can also avoid extra calls to XChangeGC by
* keeping track of the last value we set (note that this may
* be different from gcv.foreground if the latter is the same
* as back_pixel). This is most useful when magnifying the
* background stipple pattern on monochrome displays.
*/
/*
* We only need to draw the rectangle if it isn't background.
*/
}
} /* end if */
r_width = 0;
} /* end if */
r_width += magnification;
} /* end for */
/*
* draw final rectangle on line
*/
}
} /* end if */
} /* end for */
return;
}
static void
int bot)
{
/* creates a small window inside of 'wind', at the top or bottom,
suitable for displaying one line of text. Also loads in a font
if necessary; John Bradley, University of Pennsylvania */
int x,y;
if (!pixfinfo) {
if (!pixfinfo) {
Exit (1);
}
}
/* start MultiVisual fix */
/**** don't use CreateSimpleWindow when there is the possibility
of Multiple visuals ......
pixwind = XCreateSimpleWindow (dpy, wind, 0, y, w, thigh,
0, None, BlackPixel (dpy, screen));
******/
/*
* Note that all these fileds need to be set, as the
* default CopyFromParent values may cause BadMatch
* errors, if the depth of the parent is different.
*/
/* We don't care for the border pixel, but must set it
* anyways, to any value at all, for the above reasons.
*/
/* Make a GC ... */
&gcv);
/* End MultiVisual Fix */
} else {
}
}
static void
{
}
static void
UnmapPixWindow(void)
{
/* start MultiVisual Fix */
/* end MultiVisual Fix */
}
/* start MultiVisual Fix */
/*
* Create an XImage from the Img we have.
* Note that this routine has nothing to
* do with the MultiVisual Mechanism.
* It is a matter of policy that XMag chooses to
* do all output to a 24 bit true color visual.
* Selecting the best visual to display Img
* is a totally distinct problem. XMag
* solves it simplistically, by insisting on 24bit TrueColor.
* The TrueColor visual is assumed to provide a
* linear ramp in each primary.
*/
static XImage *
CreateImageFromImg(void)
{
int x, y;
for (y = 0; y < ht; y++) {
for (x=0; x < wd; x++) {
unsigned long pixel;
<<red_shift)
<<blue_shift)
<<green_shift);
}
}
return image;
}
static int
shhh(
{
/* be quiet */
exit(1);
}
/*
* Based on what mvLib returns, determine the best thing to do ...
*/
int
{
switch (multivisFromMvLib) {
case 0: /* No multiVis problems, do it the simple way */
return 0;
case 1: /* Definitely a multidepth problem */
return 1;
case 2: /* no depth problem , but colormap or visual class mismatch */
/* do a best effort... if 24bit window exists, use the mvLib
else do a simple GetImage, and warn user that displayed image
may not show true colors. */
if (w1) /* have TrueColor capability */
return 1;
/* else , best effort */
"%s: Warning - source window has different colormap or visual than root\n Image displayed using colormap and visual of root\n",
return 0;
}
return 0;
}
/* end MultiVisual Fix */