[comp.sources.sun] v01i059: Zoom in on parts of a SunView screen

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (08/25/89)

Submitted-by: ecn!jack@nluug.nl (Jack van Wijk)
Posting-number: Volume 1, Issue 59
Archive-name: looking-glass


I submit the following tool for the comp.sources.sun group. It is a
looking-glass, which enables the user to look at the screen in detail.
In my opinion, it is better (more features) and faster than the
old glass (in the SUN User Group 87 tapes).

With compliments,

Jack van Wijk

---------- Netherlands Energy Research Foundation, ECN --------------
Jack (Jarke J.) van Wijk                  UUCP : jack@ecn.uucp
P.O. Box 1, 1755 ZG  Petten(NH)           ARPA : ecn!jack@nluug.nl
Holland    phone: +31 2246 4333                  ecn!jack@uunet.uu.net
---------------------------------------------------------------------------
: To unbundle, sh this file
echo README
cat >README <<'@@@ End of README'
Lglass is a SunView tool for looking at the screen.
Options are: user-selectable scale, color/bw, dynamic update, and dragging.
To make this tool, just type make.
@@@ End of README
echo Makefile
cat >Makefile <<'@@@ End of Makefile'
WINLIBS =  -lsuntool -lsunwindow -lpixrect 

lglass: lglass.o show.o
	cc -o $@ $(CFLAGS) lglass.o show.o $(WINLIBS)
@@@ End of Makefile
echo lglass.c
cat >lglass.c <<'@@@ End of lglass.c'
/*************************************************************************
 Lglass: screen viewer for the Sun Workstation running SunView
   Copyright (c) 1989 by Jack van Wijk
   7/24/89 @ Netherlands Energy Research Foundation, ECN

   This program may be redistributed without fee as long as this copyright
   notice is intact.

---------- Netherlands Energy Research Foundation, ECN ------------------
Jack (Jarke J.) van Wijk                  UUCP : jack@ecn.uucp
P.O. Box 1, 1755 ZG  Petten(NH)           ARPA : ecn!jack@nluug.nl
Holland    phone: +31 2246 4333                  ecn!jack@uunet.uu.net
*************************************************************************/

#include <stdio.h>
#include <sys/time.h>
#include <suntool/sunview.h>
#include <suntool/window.h>
#include <suntool/panel.h>
#include <suntool/canvas.h>

#define MAXSCALE		32	
#define SCALESTRINGS		"1", "2", "4", "8", "16", "32"
#define SCALEMENUSTRINGS	"zoom in", "zoom out"
#define UPDATEMENUSTRINGS	"off", "slow", "fast"
#define COLORSTRINGS		"B/W", "color"

Pixrect 	*scr_pr;
Frame		my_frame;
Canvas		my_canvas;
Panel_item	scale_item;
Cursor		std_cursor, select_cursor;
struct {
		int	depth;
		int	scale;
		int	curx;
		int	cury;
	} GV = { 1, 1, 500, 500 };

short select_data[] = {
#include "select.cursor"
};
mpr_static (select_pr, 16, 16, 1, select_data);

short glas_data[] = {
#include "lglass.icon"
};
mpr_static (glas_pr, 64, 64, 1, glas_data);

/*----------------------------------------------------------------------*/
scale_to_nr(scale)

	/* Map scale to number: 2**nr = scale	*/

int scale;
{
	int nr;

	for (nr= 0; scale > 1; scale /=2)
		nr++;
	return nr;
}

/*----------------------------------------------------------------------*/
nr_to_scale(nr)

	/* Map number to scale : 2**nr = scale	*/

int nr;
{
	int scale;

	for (scale = 1; nr > 0; nr--)
		scale *= 2;
	return scale;
}

/*----------------------------------------------------------------------*/
do_repaint()
{
	if (!window_get(my_frame, FRAME_CLOSED))
	{
		show_pic(GV.curx, GV.cury, GV.scale);
	}
}

/*----------------------------------------------------------------------*/
do_select(window, event, arg)

Window	window;
Event	*event;
caddr_t	arg;
{
	static int	lx, ly, dragging = 0;
	int		dx, dy, value, i;
	static Menu	scale_menu = NULL;

	dx = (event_x(event) - (int) window_get(window, WIN_WIDTH )/2)
			/GV.scale;
	dy = (event_y(event) - (int) window_get(window, WIN_HEIGHT)/2)
			/GV.scale; 

	switch (event_id(event))
	{
		case MS_LEFT:
			if (event_is_up(event))
	   			show_pic(GV.curx+dx, GV.cury+dy, GV.scale);
			break;

		case MS_MIDDLE:
			if (event_is_down(event))
			{
				lx = dx;
				ly = dy;
				dragging = 1;
			}
			else
				dragging = 0;
			break;

		case LOC_MOVE:
		case LOC_DRAG:
			if (!dragging) break;
			show_pic(GV.curx+lx-dx, GV.cury+ly-dy, GV.scale);
			lx = dx;
			ly = dy;
			break;
			
			
		case MS_RIGHT:
				scale_menu = menu_create(MENU_STRINGS,
					SCALEMENUSTRINGS, 0,
					0);
			value = (int) menu_show(scale_menu, window, event, 0);
			if (value == 0)
				return;
			if (value == 1 && GV.scale < MAXSCALE)
				GV.scale *= 2;
			else if (value == 2 && GV.scale > 1)
				GV.scale /= 2;
			else
				return;

			panel_set_value(scale_item, scale_to_nr(GV.scale));
	   		show_pic(GV.curx+dx, GV.cury+dy, GV.scale);
			break;
	}
}

/*----------------------------------------------------------------------*/
do_set_scale(item, value, event)

Panel_item	item;
int		value;
Event		*event;
{
	show_pic(GV.curx, GV.cury, nr_to_scale(value));
}

/*----------------------------------------------------------------------*/
do_set_color(item, value, event)

Panel_item	item;
int		value;
Event		*event;
{
	if (value == 0)
		GV.depth = 1;
	else
		GV.depth = 8;

	window_set(my_canvas,
		CANVAS_FAST_MONO, (GV.depth == 1 ? TRUE : FALSE),
		0);
	reset_plane_groups();
	reset_colortable();
	do_repaint();
}

#define ITIMER_NULL ((struct itimerval *) NULL)
/*----------------------------------------------------------------------*/
do_set_update(item, value, event)

Panel_item	item;
int		value;
Event		*event;
{
	static int my_client_object;
	static int *my_client = &my_client_object;

	struct itimerval timerval;

	if (value == 0)
		notify_set_itimer_func(my_client, do_repaint, ITIMER_REAL,
			NULL, ITIMER_NULL);
	else
	{
		timerval.it_value.tv_usec = 0;
		timerval.it_value.tv_sec  = 1;
		if (value == 1)
		{
			timerval.it_interval.tv_usec = 0;
			timerval.it_interval.tv_sec  = 1;
		}
		else
		{
			timerval.it_interval.tv_usec = 200;
			timerval.it_interval.tv_sec  = 0;
		}

		do_repaint();
		notify_set_itimer_func(my_client, do_repaint, ITIMER_REAL,
			&timerval, ITIMER_NULL);
	}
}

/*----------------------------------------------------------------------*/
do_done()
{
	window_set(my_frame, FRAME_CLOSED, TRUE, 0);
}

/*----------------------------------------------------------------------*/
do_quit()
{
	if (window_destroy(my_frame))
		exit(0);
}
		
/*----------------------------------------------------------------------*/
reset_colortable()
{
#define CMS_NAME	"GLASS_COLOUR"
#define CMS_SIZE	256

	u_char	red[CMS_SIZE], green[CMS_SIZE], blue[CMS_SIZE];
	Pixwin	*pw;

	if (GV.depth > 1)
	{
		pw = canvas_pixwin(my_canvas);
		pr_getcolormap(scr_pr, 0, 256, red, green, blue);
		pw_setcmsname(pw, CMS_NAME);
		pw_putcolormap(pw, 0, CMS_SIZE, red, green, blue);
	}
}

/*----------------------------------------------------------------------*/
static void select_proc(window, event)

Window		window;
Event		*event;
{
	static  int dragging = 0;
	int	cx, cy;

	switch (event_id(event))
	{
	case MS_LEFT:
		if (event_is_down(event) || 
		   (event_is_up(event) && dragging > 5))
			exit_grab(window, event);
		dragging = 0;
		break;

	case LOC_DRAG:
		dragging++;
		get_abs_pos(window, event_x(event), event_y(event), 
			&cx, &cy);
		show_pic(cx, cy, GV.scale);
		break;
		
	default:
		panel_default_handle_event(window, event); 
		break;
	}
}

/*----------------------------------------------------------------------*/
static void init_grab_proc(item, event)

Panel_item	item;
Event		*event;
{
	Panel	panel;

	if (event_action(event) == MS_LEFT && event_is_down(event))
	{
		panel  = (Window) panel_get(item, PANEL_PARENT_PANEL);

		window_set(panel,
			WIN_GRAB_ALL_INPUT, TRUE, 
			WIN_EVENT_PROC, select_proc, 
			WIN_CURSOR, select_cursor, 
			0);

	}
}

/*----------------------------------------------------------------------*/
exit_grab(window, event)

Window	window;
Event	*event;
{
	int	cx, cy;

		/* Disable grab all input and get look-up table */

	window_set(window, WIN_GRAB_ALL_INPUT, FALSE, 0);
	reset_colortable();

		/* Set std_cursor invisible, grab all input, and get image */

	cursor_set(std_cursor, CURSOR_SHOW_CURSOR, FALSE, 0);
	window_set(window, 
		WIN_GRAB_ALL_INPUT, TRUE,
		WIN_CURSOR, std_cursor,
		0);
	get_abs_pos(window, event_x(event), event_y(event), &cx, &cy);
	show_pic(cx, cy, GV.scale);

		/* Set std_cursor visible, and reset grab all input	*/

	cursor_set(std_cursor, CURSOR_SHOW_CURSOR, TRUE, 0);
	window_set(window, 
		WIN_GRAB_ALL_INPUT, FALSE,
		WIN_EVENT_PROC, NULL, 
		WIN_CURSOR, std_cursor, 
		0);
}

/*----------------------------------------------------------------------*/
show_pic(cx, cy, scale)

int	cx, cy;
register int scale;
{
	int	dw, dh, dws, dhs;
	Pixwin	*pw;

	pw = canvas_pixwin(my_canvas);

	dw = (int) window_get(my_canvas, WIN_WIDTH);
	dh = (int) window_get(my_canvas, WIN_HEIGHT);
	dws = dw/scale;
	dhs = dh/scale;

	if (cx - dws/2 <= 0) cx = dws/2;
	if (cy - dhs/2 <= 0) cy = dhs/2;

	if (cx + dws/2 >= scr_pr->pr_width)  cx = scr_pr->pr_width - dws/2;
	if (cy + dhs/2 >= scr_pr->pr_height) cy = scr_pr->pr_height- dhs/2;

	GV.curx  = cx;
	GV.cury  = cy;
	GV.scale = scale;

	show_scaled(pw, 0, 0, dw, dh, scale, scr_pr, cx - dws/2, cy - dhs/2);
}

/*----------------------------------------------------------------------*/
get_abs_pos(win, rx, ry, cx, cy)

Window	win;
int	rx, ry, *cx, *cy;
{
	*cx = rx;
	*cy = ry;

	while (1)
	{
		*cx += (int) window_get(win, WIN_X) + 
		       (int) window_get(win, WIN_LEFT_MARGIN);
		*cy += (int) window_get(win, WIN_Y) +
		       (int) window_get(win, WIN_TOP_MARGIN);
		win = (Window) window_get(win, WIN_OWNER);
		if (win == NULL)
			break;
	}
}

/*----------------------------------------------------------------------*/
reset_plane_groups()
{
	int groups[10];

	pr_available_plane_groups(scr_pr, 10, groups);

	if (GV.depth == 8 && groups[PIXPG_8BIT_COLOR])
		pr_set_plane_group(scr_pr, PIXPG_8BIT_COLOR);
	else if (GV.depth == 1 && groups[PIXPG_8BIT_COLOR])
		pr_set_plane_group(scr_pr, PIXPG_OVERLAY);
	else 
	{
		pr_set_plane_group(scr_pr, PIXPG_MONO);
		GV.depth = 1;
	}
}

/*----------------------------------------------------------------------*/
init_screen()
{
	scr_pr = pr_open("/dev/fb");
	reset_plane_groups();
}

/*----------------------------------------------------------------------*/
main(argc, argv)
int argc;
char *argv[];
{
	Panel	panel;
	Icon	icon;

	init_screen();
	init_scaletable(MAXSCALE);

	icon      = icon_create(ICON_IMAGE, &glas_pr, 0);
	my_frame  = window_create(NULL, FRAME, 
			FRAME_LABEL, "lglass",
			FRAME_ICON,  icon,
			FRAME_ARGS,  argc, argv, 
			0);

	panel  = window_create(my_frame, PANEL, 0); 

	panel_create_item(panel, PANEL_BUTTON,
		PANEL_LABEL_IMAGE, panel_button_image(panel, "Select", 0, 0),
		PANEL_EVENT_PROC, init_grab_proc, 0);

	panel_create_item(panel, PANEL_BUTTON,
		PANEL_LABEL_IMAGE, panel_button_image(panel, "Redraw", 0, 
				0),
		PANEL_NOTIFY_PROC, do_repaint, 0);

	panel_create_item(panel, PANEL_BUTTON,
		PANEL_LABEL_IMAGE, panel_button_image(panel, "Done", 0, 
				0),
		PANEL_NOTIFY_PROC, do_done, 0);

	panel_create_item(panel, PANEL_BUTTON,
		PANEL_LABEL_IMAGE, panel_button_image(panel, "Quit", 0, 
				0),
		PANEL_NOTIFY_PROC, do_quit, 0);

	window_fit_width(panel);
	window_fit_width(my_frame);

	scale_item = panel_create_item(panel, PANEL_CHOICE,
		PANEL_LABEL_STRING, "Scale :",
		PANEL_CHOICE_STRINGS, SCALESTRINGS, 0,
		PANEL_NOTIFY_PROC, do_set_scale, 
		0);

	panel_create_item(panel, PANEL_CHOICE,
		PANEL_LABEL_STRING, "Update:",
		PANEL_CHOICE_STRINGS, UPDATEMENUSTRINGS, 0,
		PANEL_NOTIFY_PROC, do_set_update, 
		0);

	panel_create_item(panel, PANEL_CHOICE,
		PANEL_LABEL_STRING, "Color :",
		PANEL_CHOICE_STRINGS, COLORSTRINGS, 0,
		PANEL_NOTIFY_PROC, do_set_color, 
		0);

	window_fit(panel);

	std_cursor = cursor_copy((Cursor) window_get(panel, WIN_CURSOR));
	select_cursor = cursor_create(CURSOR_IMAGE, &select_pr, 
			CURSOR_XHOT, 2,
			CURSOR_YHOT, 2,
			0);

	my_canvas = window_create(my_frame, CANVAS,
		CANVAS_RETAINED, FALSE,
		CANVAS_REPAINT_PROC, do_repaint,
		CANVAS_FAST_MONO, (GV.depth == 1 ? TRUE : FALSE),
		WIN_X, 0,
		WIN_BELOW, panel,
		WIN_HEIGHT, (int) window_get(panel, WIN_WIDTH),
		WIN_EVENT_PROC, do_select,
		0);
	window_fit(my_frame);
	window_main_loop(my_frame);
}
@@@ End of lglass.c
echo show.c
cat >show.c <<'@@@ End of show.c'
/*************************************************************************
 Lglass: screen viewer for the Sun Workstation running SunView
   Copyright (c) 1989 by Jack van Wijk
   7/24/89 @ Netherlands Energy Research Foundation, ECN

   This program may be redistributed without fee as long as this copyright
   notice is intact.

---------- Netherlands Energy Research Foundation, ECN ------------------
Jack (Jarke J.) van Wijk                  UUCP : jack@ecn.uucp
P.O. Box 1, 1755 ZG  Petten(NH)           ARPA : ecn!jack@nluug.nl
Holland    phone: +31 2246 4333                  ecn!jack@uunet.uu.net
*************************************************************************/

#include <suntool/sunview.h>
#include <suntool/window.h>

static u_char **scaletable;

/*----------------------------------------------------------------------*/
init_scaletable(max_scale)
int	max_scale;
{
	int i, j, k, bit, scale, srcbit;
	u_char *tab;

	scaletable = (u_char **) 
		     malloc((scale_to_nr(max_scale)+1)*sizeof(u_char *));
	scale = 2;
	for (scale = 2, i=1; 
	     scale < 64; 
	     i++, scale *=2) /* For each scale a set */
	{
		scaletable[i] = (u_char *) malloc(16*scale/2);
		tab = scaletable[i];
		for (j = 0; j < 16; j++) /* For each nibble */
		for (k = scale/2-1; k>=0; k--) /* For each scaled nibble */
		{
			*tab = 0;
			for (bit = 7; bit >= 0; bit--) /* For each bit of dst */
			{
			   srcbit = (8*k+bit)/scale; /* inverse mapping */
				if ((j >> srcbit) & 1)
					*tab |= 1 << bit;
			}
			tab++;
		}
	}
}
	
/*----------------------------------------------------------------------*/
static mem_scale8(mem_src, mem_dst, dh, scale)

Pixrect	*mem_src, *mem_dst;
int	dh, scale;
{
	register u_char	*lxsrc, *lxdst, *lxmax;
	u_char	*lysrc, *lydst, *lymax;
	int		lbsrc, lbdst;
	int	i;

		/* Calculate memory locations */

	lbsrc = mpr_d(mem_src)->md_linebytes;
	lbdst = mpr_d(mem_dst)->md_linebytes;

	lysrc = (u_char *) mpr_d(mem_src)->md_image;
	lydst = (u_char *) mpr_d(mem_dst)->md_image;
	lymax = lysrc + (dh/scale+1)*lbsrc;

		/* Scale image in memory */

	for (;lysrc < lymax; lysrc += lbsrc, lydst += scale*lbdst)
	{
		lxsrc = lysrc;
		lxdst = lydst;
		lxmax = lxsrc + lbsrc;

		for (; lxsrc < lxmax; lxsrc++)
		{
			for (i=0; i < scale; i++) 
				*lxdst++ = *lxsrc;
		}
		for (i=1; i < scale; i++)
			memcpy(lydst+i*lbdst, lydst, lbdst);
	}
}

/*----------------------------------------------------------------------*/
static mem_scale1(mem_src, mem_dst, dh, scale)

Pixrect	*mem_src, *mem_dst;
int	dh, scale;
{
	int		lbsrc, lbdst;
	register u_char	*lxsrc, *lxdst, *lxmax;
	u_char		*lysrc, *lydst, *lymax;
	register u_char	*tab, *v1, *v2;
	register int	i, nscale;

	tab = scaletable[scale_to_nr(scale)];

	lbsrc = mpr_d(mem_src)->md_linebytes;
	lbdst = mpr_d(mem_dst)->md_linebytes;

	lysrc = (u_char *) mpr_d(mem_src)->md_image;
	lydst = (u_char *) mpr_d(mem_dst)->md_image;
	lymax = lysrc + (dh/scale+1)*lbsrc;

	nscale= scale / 2;

	for (;lysrc < lymax; lysrc += lbsrc, lydst += scale*lbdst)
	{
		lxsrc = lysrc;
		lxdst = lydst;
		lxmax = lxsrc + lbsrc;

		for (; lxsrc < lxmax; lxsrc++)
		{
			v1 = tab + (*lxsrc >> 4) * nscale;
			v2 = tab + (*lxsrc & 15) * nscale;
			if (nscale == 1)
			{
				*lxdst++ = *v1;
				*lxdst++ = *v2;
			}
			else
			{
				memcpy(lxdst, v1, nscale);
				lxdst += nscale;
				memcpy(lxdst, v2, nscale);
				lxdst += nscale;
			}
		}
		for (i=1; i < scale; i++)
			memcpy(lydst+i*lbdst, lydst, lbdst);
	}
}

/*----------------------------------------------------------------------*/
show_scaled(pw, dx, dy, dw, dh, scale, pr, sx, sy)

Pixwin	*pw;
int	dx, dy, dw, dh, scale;
Pixrect	*pr;
int	sx, sy;
{
	static Pixrect	*mem_src=NULL, *mem_dst=NULL;

	if (scale == 1)
	{
		pw_write(pw, dx, dy, dw, dh,
			PIX_SRC, 
			pr, sx, sy);
		return;
	}

		/* Allocate memory buffers */

	if (mem_src == NULL || 
	    mem_src->pr_width != dw/scale + 1 || 
	    mem_src->pr_height!= dh/scale + 1 ||
	    mem_src->pr_depth != pr->pr_depth)
	{
		if (mem_src != NULL)
			pr_destroy(mem_src);
		mem_src = mem_create(dw/scale+1, dh/scale+1, pr->pr_depth);
	}

	if (mem_dst == NULL || 
	    mem_dst->pr_width != (dw/scale + 1)*scale || 
	    mem_dst->pr_height!= (dh/scale + 1)*scale ||
	    mem_dst->pr_depth != pr->pr_depth)
	{
		if (mem_dst != NULL)
			pr_destroy(mem_dst);
		mem_dst = mem_create((dw/scale + 1)*scale,
				     (dh/scale + 1)*scale,
				     pr->pr_depth);
	}

		/* Read source image into memory	*/

	pr_rop(mem_src, 0, 0, 
		(dw/scale +1)*scale,
		(dh/scale +1)*scale,
		PIX_SRC,
		pr,
		sx, sy);

		/* Scale memory to memory	*/

	if (pr->pr_depth == 8)
		mem_scale8(mem_src, mem_dst, dh, scale);
	else
		mem_scale1(mem_src, mem_dst, dh, scale);

		/* Copy memory to destination pixwin	*/

	pw_write(pw, dx, dy, dw, dh,
		PIX_SRC, 
		mem_dst,
		0, 0);
}
@@@ End of show.c
echo select.cursor
cat >select.cursor <<'@@@ End of select.cursor'
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x1F00,0x2080,0x4040,0x8020,0x8020,0x8020,0x8020,0x8020,
	0x4060,0x20D0,0x1FA8,0x0054,0x002A,0x0015,0x000A,0x0004
@@@ End of select.cursor
echo lglass.icon
cat >lglass.icon <<'@@@ End of lglass.icon'
/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
 */
	0x8888,0x8888,0x8FF8,0x8888,0x8888,0x8888,0xFFFF,0x8888,
	0x2222,0x2223,0xF007,0xE222,0x2222,0x222F,0x8FF8,0xFA22,
	0x8888,0x889C,0x7C0F,0x1C88,0x8888,0x88B9,0x8C0C,0xCE88,
	0x2222,0x22E6,0x0C0C,0x33A2,0x2222,0x23CC,0x0C0C,0x0962,
	0x8888,0x8990,0xC0C0,0xC4C8,0x8888,0x8B20,0xC0C0,0xC268,
	0x2222,0x2640,0xC0C0,0xC132,0x2222,0x2AC0,0xC0C0,0xC0AA,
	0x8888,0x8D0C,0x0C0C,0x0C58,0x8888,0x990C,0x0C0C,0x0C4C,
	0x2222,0x3A0C,0x0C0C,0x0C2E,0x2222,0x3A0C,0x0C0C,0x0C2E,
	0x8888,0xB4C0,0xC0C0,0xC0D6,0x8888,0xB4C0,0xC0C0,0xC0D6,
	0x2222,0x34C0,0xC0C0,0xC0D6,0x2222,0x68C0,0xC0C0,0xC0CB,
	0x8888,0xEC0C,0x0C0C,0x0C0B,0x8888,0xEC0C,0x0C0C,0x0C0B,
	0x2222,0x6C0C,0x0C0C,0x0C0B,0x2222,0x6C0C,0x0C0C,0x0C0B,
	0x8888,0xE8C0,0xC0C0,0xC0CB,0x8888,0xE8C0,0xC0C0,0xC0CB,
	0x2222,0x68C0,0xC0C0,0xC0CB,0x2222,0x68C0,0xC0C0,0xC0CB,
	0x8888,0xB40C,0x0C0C,0x0C16,0x8888,0xB40C,0x0C0C,0x0C16,
	0x2222,0x340C,0x0C0C,0x0C16,0x2222,0x3A0C,0x0C0C,0x0C2E,
	0x8888,0x9AC0,0xC0C0,0xC0EC,0x8888,0x99C0,0xC0C0,0xC0CC,
	0x2222,0x2DC0,0xC0C0,0xC0DA,0x2222,0x2AC0,0xC0C0,0xC0BA,
	0x8888,0x9E4C,0x0C0C,0x0D38,0x8888,0xBB2C,0x0C0C,0x0E68,
	0x2222,0x669C,0x0C0C,0x0CE2,0x2222,0x198C,0x0C0C,0x09E2,
	0x8889,0x1766,0xC0C0,0xF388,0x888B,0x0EE9,0xC0C0,0xCE88,
	0x2226,0xE5D4,0x70C7,0x1E22,0x222D,0xB3BF,0x8FF8,0xFA22,
	0x889B,0x71BB,0xF007,0xE888,0x88B6,0xE878,0xFFFF,0x8888,
	0x226D,0xDE62,0x2FFA,0x2222,0x22DB,0xBA22,0x2222,0x2222,
	0x89B7,0x7688,0x8888,0x8888,0x8B6E,0xED88,0x8888,0x8888,
	0x26DD,0xDBA2,0x2222,0x2222,0x2DBB,0xB622,0x2222,0x2222,
	0x9B77,0x6C88,0x8888,0x8888,0xB6EE,0xD888,0x8888,0x8888,
	0x6DDD,0xB222,0x2222,0x2222,0x3BBB,0x6222,0x2222,0x2222,
	0x9776,0xC888,0x8888,0x8888,0x8EED,0x8888,0x8888,0x8888,
	0x2DDB,0x2222,0x2222,0x2222,0x23B6,0x2222,0x2222,0x2222,
	0x8B6C,0x8888,0x8888,0x8888,0x88D8,0x8888,0x8888,0x8888,
	0x22B2,0x2222,0x2222,0x2222,0x2262,0x2222,0x2222,0x2222
@@@ End of lglass.icon
echo lglass.man
cat >lglass.man <<'@@@ End of lglass.man'
.TH LGLASS 1 "24 July 1989"
.SH NAME
lglass\- look at your screen through a looking-glass
.SH SYNOPSIS
.B lglass
.SH DESCRIPTION
.LP
\fILglass\fP is SunView-based tool for examining the screen.
At each moment an area around a selected spot is displayed at a
user-definable scale.
After start-up a window appears, divided in two sub-windows:
a control-panel for setting options, and a canvas for showing the
selected part of the screen.
The buttons have the following meaning:
.IP \fBSelect\fP 10
Enables the user to change the currently selected spot on the screen.
After pressing the button, the cursor changes to a looking-glass.
When the left mouse-button is pressed, a new spot is selected, and
the area around it is displayed in the canvas.
With the middle-button down, the spot can be dragged, and the currently
selected area is modified dynamically.
When the middle-button is released, the selection is made.
.IP \fBRedraw\fP 10
Redraw the canvas according to the current setting.
.IP \fBDone\fP 10
Close the window.
A looking-glass icon appears.
.IP \fBQuit\fP 10
Quit from lglass.
.LP
The choices below the buttons mean:
.IP \fBScale\fP 10
Select the scale for enlarging the screen.
.IP \fBUpdate\fP 10
Select the mode for updating the canvas: \fIoff\fP - no update;
\fIslow\fP - update canvas each second; and \fIfast\fP - update canvas
each 1/5th second.
.IP \fBColor\fP 10
Select whether black-and-white planes, or color-planes must be shown.
.LP
Further the scaled image can be modified when the cursor is inside
the canvas. 
With the \fIleft-button\fP a new spot can be selected: the canvas is redrawn,
with the selected spot at the center of the canvas.
With the \fImiddle-button\fP the image can be dragged.
When the \fIright-button\fP is pressed, a menu appears showing \fBzoom in,
zoom out\fP.
After a choice is made, the canvas is redrawn at a modified scale,
with the selected spot at the center of the canvas.
.SH AUTHOR
Jack van Wijk, ECN, PO box 1, 1755 ZG  Petten (NH), Holland.
.SH BUGS
Please contact me about bugs and wishes.
.SH NOTES
The development of \fIlglass\fP is part of a research project of the
\fINetherlands Energy Research Foundation (ECN), Petten (NH),
Holland\fP.
@@@ End of lglass.man
exit 0