schwartz@swatsun.UUCP (04/13/87)
Here is a fun toy for your Sun workstation. It is the latest (last?) revision of a magnifying glass program that displays a blown up image of the area near the cursor in a window. To unpack, cd to a clean directory and feed the following to /bin/sh : ------------- Snip Here ------------------------------------------: #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # Makefile # glass.c # glass.icon # patchlevel.h # This archive created: Sun Apr 12 21:12:02 1987 export PATH; PATH=/bin:$PATH if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' This is about the magnifying glass for Sun3s. The program, glass, takes one argument, which quantifies the magnification it is to do. If no argument is supplied, glass assumes you mean no magnification. Glass opens it's own window to display the magnified image. The image is a region to the upper left of the cursor, the direction the cursor points, with the lower right corner of the window corresponding to the tip of the cursor. To compile, use the makefile provided. Glass has several shortcomings right now. o There should be a way to dynamically set the magnification factor. This is easy to do, but who has time? o The program is too slow for small magnification. Unary magnification is fast since a single bitblit is all that is needed, and large magnification is fast, since there aren't many pixels to do. I'd be happy if Sun would add a "pr_mag" to the sunview library, and thereby get the job done without going through all the indirection that users have to. o Glass eats up all your spare cycles. Maybe this isn't too bad, especially if you don't use it all the time. Also fixing it (via nice or sleep) might make it slower than you like. o Lint complains about all the sunview library calls that are defined in header files and not used. Too bad. If anyone decides to fix these, please mail me a copy of the changes. I, of course, will post any changes I make. -- Scott Schwartz USmail: Swarthmore College Swarthmore PA, 19081 UUCP: ...seismo!bpa!swatsun!schwartz SHAR_EOF fi # end of overwriting check if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else cat << \SHAR_EOF > 'Makefile' # Makefile to compile magnifying glass # by Scott Schwartz, Dec 1986 # flags. normally just -O CFLAGS=-O LIBS= -lsuntool -lsunwindow -lpixrect # dependencies for glass glass: glass.o cc $(CFLAGS) -o glass glass.o $(LIBS) glass.o: glass.c patchlevel.h Makefile cc $(CFLAGS) -c glass.c # utility stuff clean: rm -f glass glass.o lint: lint -hx glass.c $(LIBS) shar: shar README Makefile glass.c glass.icon patchlevel.h >glass.shar SHAR_EOF chmod +x 'Makefile' fi # end of overwriting check if test -f 'glass.c' then echo shar: will not over-write existing file "'glass.c'" else cat << \SHAR_EOF > 'glass.c' /* * Magnifying glass (for Sun-3 workstations) * * Copyright 1986, 1987 by Scott Schwartz * This program may be copied with the provision that this copyright * message remains, and that further distribution of this code and it's * derivatives is not subject to additional restrictions. * * compile with -lsuntool -lsunwindow -lpixrect * * vi: set ts=8 * * revision history: * 10 Nov 86 initial coding Scott Schwartz * * version 1.0 25 Nov 86 * modified to draw big pixels with raster-ops ses * * version 1.1 27 Jan 87 * does magnification in memory, ses * to avoid screen access * * version 1.2 27 Jan 87 * flood destination with white, ses/af * then draw only black spots * */ #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #include <pixrect/pixrect_hs.h> /* useful macros */ #define EVER ;; #define break_when(condition) if (condition) break #define error(msg) { fprintf(stderr, "%s: %s\n", argv[0], msg); exit(1); } /* forward declarations */ extern char *getenv(), *sprintf(); extern Notify_error notify_dispatch(); static Notify_value notice_destroy_event(); extern void pw_mag(); extern void view(); /* constants */ static char frame_label[] = "Magnifying Glass 1.2"; static short icon_image[] = { #include "glass.icon" }; DEFINE_ICON_FROM_IMAGE(icon, icon_image); #define NILPR ((Pixrect *)0) #define screen_max_x 1152 #define screen_max_y 900 #define max_mag 100 /* global vars */ static Pixrect *tmpsrc; /* working space, to avoid screen access */ static Pixrect *tmpdst; static int done = 0; /* * main routine */ main(argc,argv) int argc; char **argv; { /* externals */ extern Pixrect *tmpsrc, *tmpdst; /* things to magnify */ char *parent; /* name of the parent window, usually win0 */ Pixrect *srcpr; /* the source pixrect, i.e. the whole screen */ int rootfd; /* file descriptor for root window, for cursor location */ /* things to draw on */ Frame frame; /* the actual window frame */ Canvas canvas; /* our particular canvas, filling the frame */ /* misc */ int mag = 1; /* magnification in output window */ char *magstr = "x99999"; /* allocate space for actual string */ int retcode; /* dissociate from parent process */ if (fork()) exit(0); /* open rootwindow */ parent = getenv("WINDOW_PARENT"); if (parent==NULL) error("can't get WINDOW_PARENT from environment.") rootfd = open(parent, O_RDONLY, 0); if (rootfd<0) perror(argv[0]); /* open frame buffer */ srcpr = pr_open("/dev/fb"); if (srcpr==NILPR) perror(argv[0]); /* create output window */ frame = window_create(NULL, FRAME, FRAME_LABEL, frame_label, FRAME_ICON, &icon, WIN_HEIGHT, 200, WIN_WIDTH, 200, FRAME_ARGC_PTR_ARGV, &argc, argv, 0); /* handle arguments */ if (argc > 1) { retcode = sscanf(argv[1], "%d", &mag); if (retcode <= 0) error("problem evaluating arguments\nUsage: glass magnification [suntools-options]"); mag = (mag > max_mag) ? max_mag : mag; } /* allocate static pixrects */ tmpsrc = mem_create(screen_max_x, screen_max_y, 1); tmpdst = mem_create(screen_max_x, screen_max_y, 1); /* gather data on output pixwin */ canvas = window_create(frame, CANVAS, 0); /* set up frame label, and activate window */ (void)sprintf(magstr, "%s x%d", frame_label, mag); window_set(frame, FRAME_LABEL, magstr, WIN_SHOW, TRUE, 0); /* set up an interposed event handler so we know when to quit */ (void)notify_interpose_destroy_func(frame, notice_destroy_event); /* copy input to output forever */ for (EVER) { (void) notify_dispatch(); break_when(done); if (window_get(frame, FRAME_CLOSED)) sleep(1); else view(rootfd, srcpr, canvas, mag); } } /* * view does the work of displaying the (possibly) magnified image * at the location indicated by rootfd (mouse). view copies srcpr to dstpw. */ void view(rootfd, srcpr, canvas, mag) int rootfd; /* root window, for mouse data */ Pixrect *srcpr; /* screen source pixrect */ Canvas canvas; int mag; { /* constants */ int maxy = (srcpr->pr_size.y); int maxx = (srcpr->pr_size.x); Pixwin *dstpw = canvas_pixwin(canvas); /* local vars */ int x,y; int w, h; /* * read mouse coords from vuid register. sadly, the sunview * programmers guide is not clear on this. appendix A tells some, * but you have to look at <sundev/vuid_event.h> to see what * virtual events you can find out about. luckily, the mouse is * one of them. */ x = win_get_vuid_value(rootfd, LOC_X_ABSOLUTE); y = win_get_vuid_value(rootfd, LOC_Y_ABSOLUTE); /* * find out how big our drawing surface is. */ w = (int) window_get(canvas, CANVAS_WIDTH); h = (int) window_get(canvas, CANVAS_HEIGHT); /* * draw on it. */ if (mag<=1) { x = min(maxx-w, max(x-w, 0)); y = min(maxy-h, max(y-h, 0)); pw_rop(dstpw, 0, 0, w, h, PIX_SRC, srcpr, x, y); } else { x = min(maxx-w/mag, max(x-w/mag, 0)); y = min(maxy-h/mag, max(y-h/mag, 0)); pw_mag(dstpw, 0, 0, w, h, mag, srcpr, x, y); } } /* * pw_mag copies a magnified view of spr to dpw using pixel replication. * the arguments are the same as those to the pw_rop library call, except * that magnification is passed instead of raster-op. */ void pw_mag(dpw, dx, dy, w, h, mag, spr, sx, sy) Pixwin *dpw; /* destination pixwin */ int dx, dy; /* destination x,y */ int w, h; /* width and height of block to copy */ int mag; /* magnification */ Pixrect *spr; /* source pixrect */ int sx,sy; /* location in source to copy from */ { /* locals */ register short si, sj; register short di, dj; register short jmax = h/mag, imax = w/mag; Pixrect r; /* holds the size of the drawing region when */ /* gaining access to the screen */ r.pr_size.x = w; r.pr_size.y = h; /* make off screen copy of source */ pr_rop(tmpsrc, 0, 0, w, h, PIX_SRC|PIX_DONTCLIP, spr, sx, sy); /* * mangify.... * flood destination with white (why not?) * for each black pixel in the source * draw a large square on the destination */ pr_rop(tmpdst, 0, 0, w, h, PIX_CLR|PIX_DONTCLIP, tmpdst, 0, 0); for (sj=0, dj=0; sj<=jmax; ++sj, dj+=mag) { for (si=0, di=0; si<=imax; ++si, di+=mag) { if (pr_get(tmpsrc, si, sj)!=0) pr_rop(tmpdst, di, dj, mag, mag, PIX_SET|PIX_DONTCLIP, tmpdst, 0, 0); } } /* draw */ pw_lock(dpw, &r); pw_rop(dpw, dx, dy, w, h, PIX_SRC, tmpdst, 0, 0); pw_unlock(dpw); } /* * a service routine that gets called when the frame is destroyed * by someone selecting 'quit'. this is basically right out of the * manual. */ static Notify_value notice_destroy_event(frame, status) Frame *frame; Destroy_status status; { if (status != DESTROY_CHECKING) { done = 1; (void) notify_stop(); } return (notify_next_destroy_func(frame,status)); } SHAR_EOF fi # end of overwriting check if test -f 'glass.icon' then echo shar: will not over-write existing file "'glass.icon'" else cat << \SHAR_EOF > 'glass.icon' /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 */ 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8BF8,0x8888,0x8888, 0x2222,0x1CC7,0x2222,0x2222,0x2222,0x70C1,0xE222,0x2222, 0x8888,0xC0C0,0xE888,0x8888,0x888B,0xC0C0,0xF888,0x8888, 0x2226,0x0C0C,0x0E22,0x2222,0x2224,0x0C0C,0x0C22,0x2222, 0x888C,0x0C0C,0x0E88,0x8888,0x889C,0x0C0C,0x0F08,0x8888, 0x2230,0xC0C0,0xC122,0x2222,0x2230,0xC0C0,0xC1A2,0x2222, 0x88A0,0xC0C0,0xC088,0x8888,0x88A0,0xC0C0,0xC088,0x8888, 0x2240,0x0000,0x0062,0x2222,0x2246,0x0C0C,0x0C62,0x2222, 0x88C6,0x0C0C,0x0C48,0x8888,0x88C6,0x0C0C,0x0C48,0x8888, 0x2246,0x0C0C,0x0C62,0x2222,0x2240,0x0000,0x0062,0x2222, 0x88C0,0xC0C0,0xC1C8,0x8888,0x88A0,0xC0C0,0xC188,0x8888, 0x2220,0xC0C0,0xC1A2,0x2222,0x2230,0xC0C0,0xC1A2,0x2222, 0x8890,0x0000,0x0188,0x8888,0x8896,0x0C0C,0x0F88,0x8888, 0x222E,0x0C0C,0x0F22,0x2222,0x2226,0x0C0C,0x0FA2,0x2222, 0x888E,0x0C0C,0x0FC8,0x8888,0x888B,0xC0C0,0xFFC8,0x8888, 0x2222,0xC0C0,0xE7F2,0x2222,0x2222,0x70C1,0xE3F2,0x2222, 0x8888,0x9CCF,0x09F8,0x8888,0x8888,0x8BF8,0x88FC,0x8888, 0x2222,0x2222,0x227E,0x2222,0x2222,0x2222,0x223F,0x2222, 0x8888,0x8888,0x889F,0x8888,0x8888,0x8888,0x888F,0xC888, 0x2222,0x2222,0x2227,0xE222,0x2222,0x2222,0x2223,0xF222, 0x8888,0x8888,0x8889,0xF888,0x8888,0x8888,0x8888,0xF888, 0x2222,0x2222,0x2222,0x7A22,0x2222,0x2222,0x2222,0x3222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222 SHAR_EOF fi # end of overwriting check if test -f 'patchlevel.h' then echo shar: will not over-write existing file "'patchlevel.h'" else cat << \SHAR_EOF > 'patchlevel.h' #define PATCHLEVEL 2 SHAR_EOF fi # end of overwriting check # End of shell archive exit 0 -- Scott Schwartz @ Swarthmore College Computer Science Program UUCP: ...{{seismo,ihnp4}!bpa, cbmvax!vu-vlsi, sun!liberty}!swatsun!schwartz AT&T: (215)-328-8610 /* lab phone */
mark@mimsy.UUCP (04/15/87)
Here is an improved version of the magnifying glass program for the Sun-3. I have changed it to use the classic rasterop algorithm for magnifiying, which speed up magnifying quite a bit. I also added panels to dynamically change the frequency of updating (so it doesn't eat all the cpu cycles) and the amount of magnification. Thanks to Scott Schwartz, who wrote the original, for making something to change! -mark Spoken: Mark Weiser ARPA: mark@mimsy.umd.edu Phone: +1-301-454-7817 After May 15, 1987: weiser@parcvax.xerox.com -------cut here------------------------------ PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH export PATH all=FALSE if [ x$1 = x-a ]; then all=TRUE fi echo Extracting README sed 's/^X//' <<'//go.sysin dd *' >README This is about the magnifying glass for Sun3s. The program, glass, takes one argument, which quantifies the magnification it is to do. If no argument is supplied, glass assumes you mean no magnification. Glass opens it's own window to display the magnified image. The image is a region to the upper left of the cursor, the direction the cursor points, with the lower right corner of the window corresponding to the tip of the cursor. To compile, use the makefile provided. If anyone decides to fix these, please mail me a copy of the changes. I, of course, will post any changes I make. -- Scott Schwartz USmail: Swarthmore College Swarthmore PA, 19081 UUCP: ...seismo!bpa!swatsun!schwartz //go.sysin dd * if [ `wc -c < README` != 716 ]; then made=FALSE echo error transmitting README -- echo length should be 716, not `wc -c < README` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 README echo -n ' '; ls -ld README fi echo Extracting Makefile sed 's/^X//' <<'//go.sysin dd *' >Makefile # Makefile to compile magnifying glass # by Scott Schwartz, Dec 1986 # flags. normally just -O CFLAGS=-g LIBS= -lsuntool -lsunwindow -lpixrect # dependencies for glass glass: glass.o cc $(CFLAGS) -o glass glass.o $(LIBS) glass.o: glass.c patchlevel.h Makefile cc $(CFLAGS) -c glass.c # utility stuff clean: rm -f glass glass.o lint: lint -hx glass.c $(LIBS) shar: makescript -o glass.shar README Makefile glass.c glass.icon patchlevel.h //go.sysin dd * if [ `wc -c < Makefile` != 448 ]; then made=FALSE echo error transmitting Makefile -- echo length should be 448, not `wc -c < Makefile` else made=TRUE fi if [ $made = TRUE ]; then chmod 755 Makefile echo -n ' '; ls -ld Makefile fi echo Extracting glass.c sed 's/^X//' <<'//go.sysin dd *' >glass.c X/* * Magnifying glass (for Sun-3 workstations) * * Copyright 1986, 1987 by Scott Schwartz * Lots of changes by, but not Copyrighted by, Mark Weiser. * This program may be copied with the provision that this copyright * message remains, and that further distribution of this code and it's * derivatives is not subject to additional restrictions. * * compile with -lsuntool -lsunwindow -lpixrect * * vi: set ts=8 * * revision history: * 10 Nov 86 initial coding Scott Schwartz * * version 1.0 25 Nov 86 * modified to draw big pixels with raster-ops ses * * version 1.1 27 Jan 87 * does magnification in memory, ses * to avoid screen access * * version 1.2 27 Jan 87 * flood destination with white, ses/af * then draw only black spots * * version 2.0 15 Apr 87 mark weiser * vastly faster magnification algorithm using only 2k blits * instead of k**2 (where k is the height or width of the final). * Also added a panel for friendliness, and stopped using *all* the cpu! */ #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #include <suntool/panel.h> #include <pixrect/pixrect_hs.h> X/* useful macros */ #define error(msg) { fprintf(stderr, "%s: %s\n", argv[0], msg); exit(1); } X/* forward declarations */ extern char *getenv(), *sprintf(); extern Notify_error notify_dispatch(); static Notify_value notice_destroy_event(); extern void pw_mag(); extern void view(); void update(); void glass_time_proc(); Notify_value update_value_proc(); X/* constants */ static char frame_label[] = "Magnifying Glass 2.0"; static short icon_image[] = { #include "glass.icon" }; DEFINE_ICON_FROM_IMAGE(icon, icon_image); #define NILPR ((Pixrect *)0) #define screen_max_x 1152 #define screen_max_y 900 #define max_mag 100 X/* global vars */ typedef struct pixrect Pixrect; /* for 3.2 compatibility. */ static Pixrect *tmpsrc; /* working space, to avoid screen access */ static Pixrect *tmpdst; static int done = 0; Pixrect *srcpr; /* the source pixrect, i.e. the whole screen */ int rootfd; /* file descriptor for root window, for cursor location */ Frame frame; /* the actual window frame */ Canvas canvas; /* our particular canvas, filling the frame */ int mag = 1; /* magnification in output window */ int delay = 1000; X/* * main routine */ main(argc,argv) int argc; char **argv; { /* externals */ extern Pixrect *tmpsrc, *tmpdst; /* things to magnify */ char *parent; /* name of the parent window, usually win0 */ /* things to draw on */ Panel panel; /* misc */ char *magstr = "x99999"; /* allocate space for actual string */ int retcode; /* open rootwindow */ parent = getenv("WINDOW_PARENT"); if (parent==NULL) error("can't get WINDOW_PARENT from environment.") rootfd = open(parent, O_RDONLY, 0); if (rootfd<0) perror(argv[0]); /* open frame buffer */ srcpr = pr_open("/dev/fb"); if (srcpr==NILPR) perror(argv[0]); /* create output window */ frame = window_create(NULL, FRAME, FRAME_LABEL, frame_label, FRAME_ICON, &icon, FRAME_ARGC_PTR_ARGV, &argc, argv, 0); panel = window_create(frame, PANEL, 0); (void) panel_create_item(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Mag:", PANEL_VALUE, 1, PANEL_MIN_VALUE, 1, PANEL_MAX_VALUE, 8, PANEL_SHOW_RANGE, FALSE, PANEL_SHOW_VALUE, TRUE, PANEL_SLIDER_WIDTH, 100, PANEL_NOTIFY_PROC, update_value_proc, PANEL_CLIENT_DATA, &mag, 0); (void) panel_create_item(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Delay:", PANEL_VALUE, 10000, PANEL_MIN_VALUE, 1000, PANEL_MAX_VALUE, 999999, PANEL_SHOW_RANGE, FALSE, PANEL_SHOW_VALUE, FALSE, PANEL_SLIDER_WIDTH, 100, PANEL_NOTIFY_PROC, update_value_proc, PANEL_CLIENT_DATA, &delay, PANEL_ITEM_X, ATTR_COL(0), PANEL_ITEM_Y, ATTR_ROW(1), 0); window_fit_height(panel); /* handle arguments */ if (argc > 1) { retcode = sscanf(argv[1], "%d", &mag); if (retcode <= 0) error("problem evaluating arguments\nUsage: glass magnification [suntools-options]"); mag = (mag > max_mag) ? max_mag : mag; } /* allocate static pixrects */ tmpsrc = mem_create(screen_max_x, screen_max_y, 1); tmpdst = mem_create(screen_max_x, screen_max_y, 1); /* gather data on output pixwin */ canvas = window_create(frame, CANVAS, WIN_HEIGHT, 200, WIN_WIDTH, 200, 0); window_fit(frame); /* set up an interposed event handler so we know when to quit */ (void)notify_interpose_destroy_func(frame, notice_destroy_event); /* start us in a second */ do_with_delay(glass_time_proc, 1, 0); /* copy input to output forever */ window_main_loop(frame); exit(0); } X/* * Thing to do at intervals. */ void glass_time_proc() { if (done) return; view(rootfd, srcpr, canvas, mag); if (window_get(frame, FRAME_CLOSED)) { do_with_delay(glass_time_proc, 2, 0); } else { do_with_delay(glass_time_proc, 0, delay); } } X/* * view does the work of displaying the (possibly) magnified image * at the location indicated by rootfd (mouse). view copies srcpr to dstpw. */ void view(rootfd, srcpr, canvas, mag) int rootfd; /* root window, for mouse data */ Pixrect *srcpr; /* screen source pixrect */ Canvas canvas; int mag; { /* constants */ int maxy = (srcpr->pr_size.y); int maxx = (srcpr->pr_size.x); Pixwin *dstpw = canvas_pixwin(canvas); /* local vars */ int x,y; int w, h; /* * read mouse coords from vuid register. sadly, the sunview * programmers guide is not clear on this. appendix A tells some, * but you have to look at <sundev/vuid_event.h> to see what * virtual events you can find out about. luckily, the mouse is * one of them. */ x = win_get_vuid_value(rootfd, LOC_X_ABSOLUTE); y = win_get_vuid_value(rootfd, LOC_Y_ABSOLUTE); /* * find out how big our drawing surface is. */ w = (int) window_get(canvas, CANVAS_WIDTH); h = (int) window_get(canvas, CANVAS_HEIGHT); /* * draw on it. */ if (mag<=1) { x = min(maxx-w, max(x-w, 0)); y = min(maxy-h, max(y-h, 0)); update(dstpw, 0, 0, w, h, PIX_SRC, srcpr, x, y); } else { x = min(maxx-w/mag, max(x-w/mag, 0)); y = min(maxy-h/mag, max(y-h/mag, 0)); pw_mag(dstpw, 0, 0, w, h, mag, srcpr, x, y); } } X/* * pw_mag copies a magnified view of spr to dpw using pixel replication. * the arguments are the same as those to the pw_rop library call, except * that magnification is passed instead of raster-op. */ void pw_mag(dpw, dx, dy, w, h, mag, spr, sx, sy) Pixwin *dpw; /* destination pixwin */ int dx, dy; /* destination x,y */ int w, h; /* width and height of block to copy */ int mag; /* magnification */ Pixrect *spr; /* source pixrect */ int sx,sy; /* location in source to copy from */ { /* locals */ register short si, sj; register short di, dj; register short jmax = h/mag + 1, imax = w/mag + 1; register short x, y, delta; Pixrect r; /* holds the size of the drawing region when */ /* gaining access to the screen */ r.pr_size.x = w; r.pr_size.y = h; /* make off screen copy of source */ pr_rop(tmpsrc, 0, 0, w, h, PIX_SRC|PIX_DONTCLIP, spr, sx, sy); for (x = 0; x < imax; x += 1) { for (delta = 0; delta < mag; delta += 1) { pr_rop(tmpdst, x*mag+delta, 0, 1, jmax, PIX_SRC|PIX_DONTCLIP, tmpsrc, x, 0); } } for (y = jmax; y >= 0; y -= 1) { for (delta = 0; delta < mag; delta += 1) { pr_rop(tmpdst, 0, y*mag+delta, w, 1, PIX_SRC|PIX_DONTCLIP, tmpdst, 0, y); } } /* draw */ update(dpw, dx, dy, w, h, PIX_SRC, tmpdst, 0, 0); } X/* for debugging purposes, mostly */ void update(dpw, dx, dy, w, h, mag, spr, sx, sy) Pixwin *dpw; /* destination pixwin */ int dx, dy; /* destination x,y */ int w, h; /* width and height of block to copy */ int mag; /* magnification */ Pixrect *spr; /* source pixrect */ int sx,sy; /* location in source to copy from */ { pw_rop(dpw, dx, dy, w, h, mag, spr, sx, sy); } X/* * a service routine that gets called when the frame is destroyed * by someone selecting 'quit'. this is basically right out of the * manual. */ static Notify_value notice_destroy_event(frame, status) Frame *frame; Destroy_status status; { if (status != DESTROY_CHECKING) { done = 1; } return (notify_next_destroy_func(frame,status)); } X/* * The routines below I have found enormously handy when dispatching * things via the notifier. Use them in good health, or bad. I do. * -mark weiser */ X/* * Call procedure f in a little while. */ do_with_delay(f, secs, usecs) void (*f)(); int secs, usecs; { Notify_value do_the_call(); struct itimerval timer; /* Sigh, so much work just to wait a bit before starting up. */ timer.it_interval.tv_usec = 0; timer.it_interval.tv_sec = 0; timer.it_value.tv_usec = usecs; timer.it_value.tv_sec = secs; notify_set_itimer_func(f, do_the_call, ITIMER_REAL, &timer, NULL); } X/* * Wrapper to make sure procedures from do_with_delay return good values * to the notifier. */ Notify_value do_the_call(f, which) void (*f)(); { (*f)(); return NOTIFY_DONE; } Notify_value update_value_proc(item, value) Panel_item item; { int *ptr; ptr = (int *)panel_get(item, PANEL_CLIENT_DATA); *ptr = value; return NOTIFY_DONE; } //go.sysin dd * if [ `wc -c < glass.c` != 9192 ]; then made=FALSE echo error transmitting glass.c -- echo length should be 9192, not `wc -c < glass.c` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 glass.c echo -n ' '; ls -ld glass.c fi echo Extracting glass.icon sed 's/^X//' <<'//go.sysin dd *' >glass.icon X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 */ 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8BF8,0x8888,0x8888, 0x2222,0x1CC7,0x2222,0x2222,0x2222,0x70C1,0xE222,0x2222, 0x8888,0xC0C0,0xE888,0x8888,0x888B,0xC0C0,0xF888,0x8888, 0x2226,0x0C0C,0x0E22,0x2222,0x2224,0x0C0C,0x0C22,0x2222, 0x888C,0x0C0C,0x0E88,0x8888,0x889C,0x0C0C,0x0F08,0x8888, 0x2230,0xC0C0,0xC122,0x2222,0x2230,0xC0C0,0xC1A2,0x2222, 0x88A0,0xC0C0,0xC088,0x8888,0x88A0,0xC0C0,0xC088,0x8888, 0x2240,0x0000,0x0062,0x2222,0x2246,0x0C0C,0x0C62,0x2222, 0x88C6,0x0C0C,0x0C48,0x8888,0x88C6,0x0C0C,0x0C48,0x8888, 0x2246,0x0C0C,0x0C62,0x2222,0x2240,0x0000,0x0062,0x2222, 0x88C0,0xC0C0,0xC1C8,0x8888,0x88A0,0xC0C0,0xC188,0x8888, 0x2220,0xC0C0,0xC1A2,0x2222,0x2230,0xC0C0,0xC1A2,0x2222, 0x8890,0x0000,0x0188,0x8888,0x8896,0x0C0C,0x0F88,0x8888, 0x222E,0x0C0C,0x0F22,0x2222,0x2226,0x0C0C,0x0FA2,0x2222, 0x888E,0x0C0C,0x0FC8,0x8888,0x888B,0xC0C0,0xFFC8,0x8888, 0x2222,0xC0C0,0xE7F2,0x2222,0x2222,0x70C1,0xE3F2,0x2222, 0x8888,0x9CCF,0x09F8,0x8888,0x8888,0x8BF8,0x88FC,0x8888, 0x2222,0x2222,0x227E,0x2222,0x2222,0x2222,0x223F,0x2222, 0x8888,0x8888,0x889F,0x8888,0x8888,0x8888,0x888F,0xC888, 0x2222,0x2222,0x2227,0xE222,0x2222,0x2222,0x2223,0xF222, 0x8888,0x8888,0x8889,0xF888,0x8888,0x8888,0x8888,0xF888, 0x2222,0x2222,0x2222,0x7A22,0x2222,0x2222,0x2222,0x3222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222 //go.sysin dd * if [ `wc -c < glass.icon` != 1933 ]; then made=FALSE echo error transmitting glass.icon -- echo length should be 1933, not `wc -c < glass.icon` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 glass.icon echo -n ' '; ls -ld glass.icon fi echo Extracting patchlevel.h sed 's/^X//' <<'//go.sysin dd *' >patchlevel.h #define PATCHLEVEL 2 //go.sysin dd * if [ `wc -c < patchlevel.h` != 21 ]; then made=FALSE echo error transmitting patchlevel.h -- echo length should be 21, not `wc -c < patchlevel.h` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 patchlevel.h echo -n ' '; ls -ld patchlevel.h fi -- Spoken: Mark Weiser ARPA: mark@mimsy.umd.edu Phone: +1-301-454-7817 After May 15, 1987: weiser@parcvax.xerox.com
mark@mimsy.UUCP (Mark Weiser) (04/21/87)
Sigh. Here is yet another improved version. This one has the ability to 'lock' the glass to a particular screen location, instead of always following the cursor, and also works for color. For some reason apparently the colors are not always the same in the original and magnified images, however. Enjoy again. ------------------------------ : Run this shell script with "sh" not "csh" PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH export PATH all=FALSE if [ x$1 = x-a ]; then all=TRUE fi echo Extracting README sed 's/^X//' <<'//go.sysin dd *' >README This is about the magnifying glass for Sun3s. The program, glass, takes one argument, which quantifies the magnification it is to do. If no argument is supplied, glass assumes you mean no magnification. Glass opens it's own window to display the magnified image. The image is a region to the upper left of the cursor, the direction the cursor points, with the lower right corner of the window corresponding to the tip of the cursor. To compile, use the makefile provided. -- Scott Schwartz USmail: Swarthmore College Swarthmore PA, 19081 UUCP: ...seismo!bpa!swatsun!schwartz Magnification can be changed, and the screen update time changed, with sliders in the glass tool. Also, the magnifier can be 'locked' onto a given screen position. Also, color now works. -mark weiser ARPA: mark@mimsy.umd.edu After May 15, 1987: weiser@parcvax.xerox.com //go.sysin dd * if [ `wc -c < README` != 879 ]; then made=FALSE echo error transmitting README -- echo length should be 879, not `wc -c < README` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 README echo -n ' '; ls -ld README fi echo Extracting glass.man sed 's/^X//' <<'//go.sysin dd *' >glass.man X.TH glass 1 "April 15, 1987" X.AT 3 X.SH NAME glass \- a magnifying window X.SH SYNOPSIS X.B glass [[options] ]... X.SH DESCRIPTION Try it. X.SH AUTHOR Scott Schwartz did the first version. Mark Weiser did a lot of fiddling, including the sliders, locking, and a better magnification algorithm. //go.sysin dd * if [ `wc -c < glass.man` != 290 ]; then made=FALSE echo error transmitting glass.man -- echo length should be 290, not `wc -c < glass.man` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 glass.man echo -n ' '; ls -ld glass.man fi echo Extracting Makefile sed 's/^X//' <<'//go.sysin dd *' >Makefile # Makefile to compile magnifying glass # by Scott Schwartz, Dec 1986 # flags. normally just -O CFLAGS=-g LIBS= -lsuntool -lsunwindow -lpixrect # dependencies for glass glass: glass.o cc $(CFLAGS) -o glass glass.o $(LIBS) glass.o: glass.c patchlevel.h Makefile cc $(CFLAGS) -c glass.c # utility stuff clean: rm -f glass glass.o lint: lint -hx glass.c $(LIBS) shar: makescript -o glass.shar README glass.man Makefile glass.c glass.icon patchlevel.h //go.sysin dd * if [ `wc -c < Makefile` != 458 ]; then made=FALSE echo error transmitting Makefile -- echo length should be 458, not `wc -c < Makefile` else made=TRUE fi if [ $made = TRUE ]; then chmod 755 Makefile echo -n ' '; ls -ld Makefile fi echo Extracting glass.c sed 's/^X//' <<'//go.sysin dd *' >glass.c X/* * Magnifying glass (for Sun-3 workstations) * * Copyright 1986, 1987 by Scott Schwartz * This program may be copied with the provision that this copyright * message remains, and that further distribution of this code and it's * derivatives is not subject to additional restrictions. * * Lots of changes, but no Copyright, by Mark Weiser. * * compile with -lsuntool -lsunwindow -lpixrect * * vi: set ts=8 * * revision history: * 10 Nov 86 initial coding Scott Schwartz * * version 1.0 25 Nov 86 * modified to draw big pixels with raster-ops ses * * version 1.1 27 Jan 87 * does magnification in memory, ses * to avoid screen access * * version 1.2 27 Jan 87 * flood destination with white, ses/af * then draw only black spots * * version 2.0 15 Apr 87 mark weiser * vastly faster magnification algorithm using only 2k blits * instead of k**2 (where k is the height or width of the final). * Also added a panel for friendliness, and stopped using *all* the cpu! * * version 2.1 17 Apr 87 mark weiser * added locking. * * version 2.2 20 Apr 87 mark weiser * added changes for color suns (not tested here). */ #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #include <suntool/panel.h> #include <suntool/textsw.h> #include <pixrect/pixrect_hs.h> X/* I HATE these macros -mdw */ #undef min #undef max X/* useful macros */ #define ERROR(msg) { fprintf(stderr, "%s: %s\n", argv[0], msg); exit(1); } X/* forward declarations */ extern char *getenv(), *sprintf(); extern Notify_error notify_dispatch(); static Notify_value notice_destroy_event(); extern void pw_mag(); extern void view(); void update(); void glass_time_proc(); void lock_proc(), unlock_proc(); Notify_value update_value_proc(); X/* constants */ static char frame_label[] = "Magnifying Glass 2.2"; static short icon_image[] = { #include "glass.icon" }; DEFINE_ICON_FROM_IMAGE(icon, icon_image); #define NILPR ((struct pixrect *)0) #define SCREEN_MAX_X 1152 #define SCREEN_MAX_Y 900 #define MAX_MAG 32 X/* global vars */ static struct pixrect *tmpsrc; /* working space, to avoid screen access */ static struct pixrect *tmpdst; static int done = 0; struct pixrect *srcpr; /* the source pixrect, i.e. the whole screen */ int rootfd; /* file descriptor for root window, for cursor location */ X/* things to draw on */ Panel panel; XFrame frame; /* the actual window frame */ Canvas canvas; /* our particular canvas, filling the frame */ int mag = 1; /* magnification in output window */ int delay = 1000; int locked = 0; int locked_x, locked_y; Panel_item time_left_item; X/* * main routine */ main(argc,argv) int argc; char **argv; { /* externals */ extern struct pixrect *tmpsrc, *tmpdst; /* things to magnify */ char *parent; /* name of the parent window, usually win0 */ /* misc */ char *magstr = "x99999"; /* allocate space for actual string */ int retcode; /* open rootwindow */ parent = getenv("WINDOW_PARENT"); if (parent==NULL) ERROR("can't get WINDOW_PARENT from environment.") rootfd = open(parent, O_RDONLY, 0); if (rootfd<0) perror(argv[0]); /* open frame buffer */ srcpr = pr_open("/dev/fb"); if (srcpr==NILPR) perror(argv[0]); /* create output window */ frame = window_create(NULL, FRAME, FRAME_LABEL, frame_label, FRAME_ICON, &icon, FRAME_ARGC_PTR_ARGV, &argc, argv, 0); /* handle arguments */ if (argc > 1) { retcode = sscanf(argv[1], "%d", &mag); if (retcode <= 0) ERROR("problem evaluating arguments\nUsage: glass magnification [suntools-options]"); mag = (mag > MAX_MAG) ? MAX_MAG : mag; } panel = window_create(frame, PANEL, 0); (void) panel_create_item(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Mag:", PANEL_VALUE, mag, PANEL_MIN_VALUE, 1, PANEL_MAX_VALUE, MAX_MAG, PANEL_SHOW_RANGE, FALSE, PANEL_SHOW_VALUE, TRUE, PANEL_SLIDER_WIDTH, 100, PANEL_NOTIFY_PROC, update_value_proc, PANEL_CLIENT_DATA, &mag, 0); (void) panel_create_item(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Delay:", PANEL_VALUE, 10000, PANEL_MIN_VALUE, 1000, PANEL_MAX_VALUE, 999999, PANEL_SHOW_RANGE, FALSE, PANEL_SHOW_VALUE, FALSE, PANEL_SLIDER_WIDTH, 100, PANEL_NOTIFY_PROC, update_value_proc, PANEL_CLIENT_DATA, &delay, PANEL_ITEM_X, ATTR_COL(0), PANEL_ITEM_Y, ATTR_ROW(1), 0); (void) panel_create_item(panel, PANEL_BUTTON, PANEL_LABEL_IMAGE, panel_button_image(panel, "Lock", 6, 0), PANEL_NOTIFY_PROC, lock_proc, PANEL_ITEM_X, ATTR_COL(0), PANEL_ITEM_Y, ATTR_ROW(2), 0); (void) panel_create_item(panel, PANEL_BUTTON, PANEL_LABEL_IMAGE, panel_button_image(panel, "Unlock", 6, 0), PANEL_NOTIFY_PROC, unlock_proc, 0); time_left_item = panel_create_item(panel, PANEL_SLIDER, PANEL_LABEL_STRING, "Time Left:", PANEL_VALUE, 10, PANEL_MIN_VALUE, 0, PANEL_MAX_VALUE, 10, PANEL_SHOW_RANGE, FALSE, PANEL_SHOW_VALUE, FALSE, PANEL_SLIDER_WIDTH, 100, PANEL_ITEM_X, ATTR_COL(0), PANEL_ITEM_Y, ATTR_ROW(2), PANEL_SHOW_ITEM, FALSE, 0); window_fit_height(panel); /* allocate static pixrects */ /* (If the last parameter is change from 1 to 8, this might work for color -mdw */ tmpsrc = mem_create(SCREEN_MAX_X, SCREEN_MAX_Y, srcpr->pr_depth); tmpdst = mem_create(SCREEN_MAX_X, SCREEN_MAX_Y, srcpr->pr_depth); /* gather data on output pixwin */ canvas = window_create(frame, CANVAS, WIN_HEIGHT, 200, WIN_WIDTH, 200, 0); window_fit(frame); /* set up an interposed event handler so we know when to quit */ (void)notify_interpose_destroy_func(frame, notice_destroy_event); /* start us in a second */ do_with_delay(glass_time_proc, 1, 0); /* copy input to output forever */ window_main_loop(frame); exit(0); } X/* * Thing to do at intervals. */ void glass_time_proc() { if (done) return; if (window_get(frame, FRAME_CLOSED)) { do_with_delay(glass_time_proc, 2, 0); } else { view(rootfd, srcpr, canvas, mag); do_with_delay(glass_time_proc, 0, delay); } } X/* * view does the work of displaying the (possibly) magnified image * at the location indicated by rootfd (mouse). view copies srcpr to dstpw. */ void view(rootfd, srcpr, canvas, mag) int rootfd; /* root window, for mouse data */ struct pixrect *srcpr; /* screen source pixrect */ Canvas canvas; int mag; { /* constants */ int maxy = (srcpr->pr_size.y); int maxx = (srcpr->pr_size.x); Pixwin *dstpw = canvas_pixwin(canvas); /* local vars */ int x,y; int w, h; /* * read mouse coords from vuid register. sadly, the sunview * programmers guide is not clear on this. appendix A tells some, * but you have to look at <sundev/vuid_event.h> to see what * virtual events you can find out about. luckily, the mouse is * one of them. */ if (locked) { x = locked_x; y = locked_y; } else { x = win_get_vuid_value(rootfd, LOC_X_ABSOLUTE); y = win_get_vuid_value(rootfd, LOC_Y_ABSOLUTE); } /* * find out how big our drawing surface is. */ w = (int) window_get(canvas, CANVAS_WIDTH); h = (int) window_get(canvas, CANVAS_HEIGHT); /* * draw on it. */ if (mag<=1) { x = min(maxx-w, max(x-w, 0)); y = min(maxy-h, max(y-h, 0)); update(dstpw, 0, 0, w, h, PIX_SRC, srcpr, x, y); } else { x = min(maxx-w/mag, max(x-w/mag, 0)); y = min(maxy-h/mag, max(y-h/mag, 0)); pw_mag(dstpw, 0, 0, w, h, mag, srcpr, x, y); } } X/* * pw_mag copies a magnified view of spr to dpw using pixel replication. * the arguments are the same as those to the pw_rop library call, except * that magnification is passed instead of raster-op. */ void pw_mag(dpw, dx, dy, w, h, mag, spr, sx, sy) Pixwin *dpw; /* destination pixwin */ int dx, dy; /* destination x,y */ int w, h; /* width and height of block to copy */ int mag; /* magnification */ struct pixrect *spr; /* source pixrect */ int sx,sy; /* location in source to copy from */ { /* locals */ register short si, sj; register short di, dj; register short jmax = h/mag + 1, imax = w/mag + 1; register short x, y, delta; struct pixrect r; /* holds the size of the drawing region when */ /* gaining access to the screen */ r.pr_size.x = w; r.pr_size.y = h; /* make off screen copy of source */ pr_rop(tmpsrc, 0, 0, w, h, PIX_SRC|PIX_DONTCLIP, spr, sx, sy); for (x = 0; x < imax; x += 1) { for (delta = 0; delta < mag; delta += 1) { pr_rop(tmpdst, x*mag+delta, 0, 1, jmax, PIX_SRC|PIX_DONTCLIP, tmpsrc, x, 0); } } for (y = jmax; y >= 0; y -= 1) { for (delta = 0; delta < mag; delta += 1) { pr_rop(tmpdst, 0, y*mag+delta, w, 1, PIX_SRC|PIX_DONTCLIP, tmpdst, 0, y); } } /* draw */ update(dpw, dx, dy, w, h, PIX_SRC, tmpdst, 0, 0); } X/* for debugging purposes, mostly */ void update(dpw, dx, dy, w, h, mag, spr, sx, sy) Pixwin *dpw; /* destination pixwin */ int dx, dy; /* destination x,y */ int w, h; /* width and height of block to copy */ int mag; /* magnification */ struct pixrect *spr; /* source pixrect */ int sx,sy; /* location in source to copy from */ { pw_rop(dpw, dx, dy, w, h, mag, spr, sx, sy); } X/* * a service routine that gets called when the frame is destroyed * by someone selecting 'quit'. this is basically right out of the * manual. */ static Notify_value notice_destroy_event(frame, status) Frame *frame; Destroy_status status; { if (status != DESTROY_CHECKING) { done = 1; } return (notify_next_destroy_func(frame,status)); } X/* * The routines below I have found enormously handy when dispatching * things via the notifier. Use them in good health, or bad. I do. * -mark weiser */ X/* * Call procedure f in a little while. */ do_with_delay(f, secs, usecs) void (*f)(); int secs, usecs; { Notify_value do_the_call(); struct itimerval timer; /* Sigh, so much work just to wait a bit before starting up. */ timer.it_interval.tv_usec = 0; timer.it_interval.tv_sec = 0; timer.it_value.tv_usec = usecs; timer.it_value.tv_sec = secs; notify_set_itimer_func(f, do_the_call, ITIMER_REAL, &timer, NULL); } X/* * Wrapper to make sure procedures from do_with_delay return good values * to the notifier. */ Notify_value do_the_call(f, which) void (*f)(); { (*f)(); return NOTIFY_DONE; } Notify_value update_value_proc(item, value) Panel_item item; { int *ptr; ptr = (int *)panel_get(item, PANEL_CLIENT_DATA); *ptr = value; return NOTIFY_DONE; } void lock_proc(item, event) Panel_item; Event *event; { extern void do_the_lock(); popup_msg(frame, event, "After buttoning 'Done' in this window,\n\ you will have ten (10) seconds to put the\n\ cursor someplace. At the end of 10 seconds,\n\ glass will be locked into looking at that position."); locked = 0; } void unlock_proc() { locked = 0; } void do_the_lock() { static void popup_textsw_done(); locked_x = win_get_vuid_value(rootfd, LOC_X_ABSOLUTE); locked_y = win_get_vuid_value(rootfd, LOC_Y_ABSOLUTE); locked = 1; } X/* * The stuff below is some standard hacks I have started using, * especially in the 'sdi' game. I have inserted them here for convenience. * -mark weiser */ static Frame popup_frame = NULL; static Textsw popup_text; static Panel popup_panel; static Panel_item popup_msg_item; static void popup_yes_proc(), popup_no_proc(), popup_textsw_done(); X/* * Fake an event, so anyone can popup a message. */ easy_pop(msg) char *msg; { Event event; event_x(&event) = (int)window_get(frame, WIN_X); event_y(&event) = (int)window_get(frame, WIN_Y); popup_msg(frame, &event, msg); } X/* * Pop up a message inside a textsw. Since textsw's don't really * popup (in SunOS 3.2), just display it and put up a 'done' button * to kill it when the user is done. * Frame should be the frame in which Event occured. Msg can * contain imbedded newlines. */ popup_msg(frame, event, msg) XFrame *frame; Event *event; char *msg; { int lines = count_lines(msg); if (popup_frame != NULL) { /* Can only do one of these at a time. */ return; } init_popup_msg(frame, msg, lines); textsw_insert(popup_text, msg, strlen(msg)); window_set(popup_frame, WIN_X, event_x(event), WIN_Y, event_y(event), WIN_SHOW, TRUE, 0); } X/* * A helper proc to do all the work of window creation for message popups */ init_popup_msg(baseframe, msg, lines) XFrame baseframe; char *msg; { popup_frame = window_create(baseframe, FRAME, WIN_ERROR_MSG, "Can't create window.", 0); popup_panel = window_create(popup_frame, PANEL, /* WIN_BELOW, popup_text, */ WIN_X, ATTR_COL(0), /* bug workaround, should not be necessary */ 0); panel_create_item(popup_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE, panel_button_image(popup_panel, "Done", 4, NULL), PANEL_NOTIFY_PROC, popup_textsw_done, 0); window_fit(popup_panel); popup_text = window_create(popup_frame, TEXTSW, WIN_ERROR_MSG, "Can't create window.", WIN_ROWS, min(30, lines), WIN_COLUMNS, max_line(msg)+3, TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY, TEXTSW_CONTENTS, msg, TEXTSW_BROWSING, TRUE, TEXTSW_DISABLE_LOAD, TRUE, TEXTSW_DISABLE_CD, TRUE, 0); window_fit(popup_frame); } void timeout_proc() { int val = (int)panel_get_value(time_left_item); if (val > 0) { panel_set(time_left_item, PANEL_VALUE, val-1, 0); do_with_delay(timeout_proc, 1, 0); } else { panel_set(time_left_item, PANEL_SHOW_ITEM, FALSE, 0); panel_paint(panel, PANEL_CLEAR); do_the_lock(); } } X/* A helper for killing message popups. */ static void popup_textsw_done() { window_set(popup_frame, FRAME_NO_CONFIRM, TRUE, 0); window_destroy(popup_frame); popup_frame = NULL; panel_set(time_left_item, PANEL_SHOW_ITEM, TRUE, PANEL_VALUE, 10, 0); do_with_delay(timeout_proc, 1, 0); } X/* * Find the size of the longest line in a string of lines separated by newlines */ max_line(s) char *s; { int max = 0, count = 0; while (*s) { if (*s++ == '\n') { if (count > max) max = count; count = 0; continue; } count += 1; } if (count > max) max = count; return max; } X/* * Count the number of lines in a string of lines separated by newlines. */ count_lines(s) char *s; { int count = 0; while (*s) { if (*s++ == '\n') count += 1; } return count+1; } X/* need functions, not macros, because of non-idempotent funcall arguments */ max(x,y) { return x<y ? y : x; } min(x,y) { return x<y ? x : y; } //go.sysin dd * if [ `wc -c < glass.c` != 14320 ]; then made=FALSE echo error transmitting glass.c -- echo length should be 14320, not `wc -c < glass.c` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 glass.c echo -n ' '; ls -ld glass.c fi echo Extracting glass.icon sed 's/^X//' <<'//go.sysin dd *' >glass.icon X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 */ 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8BF8,0x8888,0x8888, 0x2222,0x1CC7,0x2222,0x2222,0x2222,0x70C1,0xE222,0x2222, 0x8888,0xC0C0,0xE888,0x8888,0x888B,0xC0C0,0xF888,0x8888, 0x2226,0x0C0C,0x0E22,0x2222,0x2224,0x0C0C,0x0C22,0x2222, 0x888C,0x0C0C,0x0E88,0x8888,0x889C,0x0C0C,0x0F08,0x8888, 0x2230,0xC0C0,0xC122,0x2222,0x2230,0xC0C0,0xC1A2,0x2222, 0x88A0,0xC0C0,0xC088,0x8888,0x88A0,0xC0C0,0xC088,0x8888, 0x2240,0x0000,0x0062,0x2222,0x2246,0x0C0C,0x0C62,0x2222, 0x88C6,0x0C0C,0x0C48,0x8888,0x88C6,0x0C0C,0x0C48,0x8888, 0x2246,0x0C0C,0x0C62,0x2222,0x2240,0x0000,0x0062,0x2222, 0x88C0,0xC0C0,0xC1C8,0x8888,0x88A0,0xC0C0,0xC188,0x8888, 0x2220,0xC0C0,0xC1A2,0x2222,0x2230,0xC0C0,0xC1A2,0x2222, 0x8890,0x0000,0x0188,0x8888,0x8896,0x0C0C,0x0F88,0x8888, 0x222E,0x0C0C,0x0F22,0x2222,0x2226,0x0C0C,0x0FA2,0x2222, 0x888E,0x0C0C,0x0FC8,0x8888,0x888B,0xC0C0,0xFFC8,0x8888, 0x2222,0xC0C0,0xE7F2,0x2222,0x2222,0x70C1,0xE3F2,0x2222, 0x8888,0x9CCF,0x09F8,0x8888,0x8888,0x8BF8,0x88FC,0x8888, 0x2222,0x2222,0x227E,0x2222,0x2222,0x2222,0x223F,0x2222, 0x8888,0x8888,0x889F,0x8888,0x8888,0x8888,0x888F,0xC888, 0x2222,0x2222,0x2227,0xE222,0x2222,0x2222,0x2223,0xF222, 0x8888,0x8888,0x8889,0xF888,0x8888,0x8888,0x8888,0xF888, 0x2222,0x2222,0x2222,0x7A22,0x2222,0x2222,0x2222,0x3222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222, 0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, 0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222 //go.sysin dd * if [ `wc -c < glass.icon` != 1933 ]; then made=FALSE echo error transmitting glass.icon -- echo length should be 1933, not `wc -c < glass.icon` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 glass.icon echo -n ' '; ls -ld glass.icon fi echo Extracting patchlevel.h sed 's/^X//' <<'//go.sysin dd *' >patchlevel.h #define PATCHLEVEL 2 //go.sysin dd * if [ `wc -c < patchlevel.h` != 21 ]; then made=FALSE echo error transmitting patchlevel.h -- echo length should be 21, not `wc -c < patchlevel.h` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 patchlevel.h echo -n ' '; ls -ld patchlevel.h fi -- Spoken: Mark Weiser ARPA: mark@mimsy.umd.edu Phone: +1-301-454-7817 After May 15, 1987: weiser@parcvax.xerox.com