mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (07/13/89)
Submitted-by: pokey@well.sf.ca.us (Jef Poskanzer) Posting-number: Volume 1, Issue 40 Archive-name: brushdmt #! /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 # brushdmt.1 # brushdmt.c # This archive created: Thu Jun 29 17:06:45 1989 # By: Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal) export PATH; PATH=/bin:$PATH echo shar: extracting "'README'" '(876 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else sed 's/^X//' << \SHAR_EOF > 'README' X brushdmt - alternate screen blanking program for Suns X Version 1.1 of 28jun89 X XBrushdmt is a cross between the screenblank daemon and the lockscreen Xprogram. Like screenblank, it works automatically, and it works no Xmatter which window system you are running, or even if you aren't Xrunning any window system. Like lockscreen, it does more interesting Xthings with your screen than just blanking it. X XSee the manual entry for more details. X XFiles in this distribution: X README this X brushdmt.1 manual entry X Makefile guess X brushdmt.c source code for screenblank replacement X XTo install: X Unpack the files. X Edit the Makefile, and define XREFRESH and SUNREFRESH appropriately. X Make. X XComments to: X pokey@well.sf.ca.us X {ucbvax, lll-crg, sun!pacbell, apple, hplabs}!well!pokey SHAR_EOF if test 876 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 876 characters)' fi fi # end of overwriting check echo shar: extracting "'Makefile'" '(1217 characters)' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# X# Makefile for brushdmt. X# X# Copyright (C) 1989 by Jef Poskanzer. X# X# Permission to use, copy, modify, and distribute this software and its X# documentation for any purpose and without fee is hereby granted, provided X# that the above copyright notice appear in all copies and that both that X# copyright notice and this permission notice appear in supporting X# documentation. This software is provided "as is" without express or X# implied warranty. X# X X# If you have X installed, define this to be a command that will run X# xrefresh. You may need to use a full pathname, since brushdmt will X# probably run as root and root usually has a narrow search path. If X# you do not have X, comment this out. XXREFRESH = -DXREFRESH=\"/usr/new/X10/xrefresh\" X X# If you use suntools, define this to point to shelltool. Once again, X# you may need to use a full pathname. If no one at your site ever uses X# sunstools, comment this out. X#SUNREFRESH = -DSUNREFRESH=\"/usr/bin/shelltool\" X Xall: brushdmt X Xbrushdmt: brushdmt.c X cc -O $(XREFRESH) $(SUNREFRESH) brushdmt.c -lpixrect -s -o brushdmt X Xshar: brushdmt.shar Xbrushdmt.shar: README Makefile brushdmt.1 brushdmt.c X shar -v -c -p X README Makefile brushdmt.1 brushdmt.c > $@ SHAR_EOF if test 1217 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 1217 characters)' fi fi # end of overwriting check echo shar: extracting "'brushdmt.1'" '(2419 characters)' if test -f 'brushdmt.1' then echo shar: will not over-write existing file "'brushdmt.1'" else sed 's/^X//' << \SHAR_EOF > 'brushdmt.1' X.TH brushdmt 1 "27 May 1989" X.SH NAME Xbrushdmt - alternate screen blanking program for Suns X.SH SYNOPSIS Xbrushdmt [-d <seconds>] [ [-j|-g] <rasterfile> ] ... X.SH DESCRIPTION XBrushdmt is a cross between the screenblank daemon and the lockscreen Xprogram. XLike screenblank, it works automatically, starting itself up after a Xspecified interval of idle time. XLike screenblank, it works no matter which window system you are running, Xor even if you aren't running any window system. XAnd like lockscreen, it does more interesting things Xwith your screen than just blanking it. X.PP XThe -d flag can be used to change the idle time interval that brushdmt Xwaits before starting itself up. XThe default interval is 600 seconds (10 minutes). X.PP XThe rest of the arguments, a list of rasterfiles with interspersed Xtype flags, control the animation that brushdmt displays. XThe rasterfiles are read in and animated in one of two Xways, jump mode or glide mode, as specified by the -j and -g flags. XJump mode is the default. XYou can mix the two modes freely; for example: X.nf X brushdmt cow.r cow.r cow.r -g triangle.r X.fi Xputs up three cows in jump mode and a triangle in glide mode. XIf no rasterfiles are given, a little white box with the current Xtime is constructed. X.PP XNote that while jump mode uses almost no CPU time, glide mode does Xuse a moderate amount -- about 3% of a 3/50 to glide each small raster. XBe considerate and don't over-use glide mode, since someone else Xmight want to use your workstation as a compute server while it's Xidle. X.PP XThe name of the program comes from the similar program at Xerox. XIn the Xerox world, "DMT" is the generic term for a screenblank program, Xderiving from the original one for the Alto. The original DMT actually Xdid "diagnostic memory tests", the later versions just took the name. XAnd "brush" is the Xerox term for a small raster file. X.SH "SEE ALSO" Xscreenblank(1), lockscreen(1), xrefresh(1) X.SH "BUGS / DEFICIENCIES" XThe refresh algorithm is less than optimal. X.SH AUTHOR XCopyright (C) 1989 by Jef Poskanzer. X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. SHAR_EOF if test 2419 -ne "`wc -c < 'brushdmt.1'`" then echo shar: error transmitting "'brushdmt.1'" '(should have been 2419 characters)' fi fi # end of overwriting check echo shar: extracting "'brushdmt.c'" '(10937 characters)' if test -f 'brushdmt.c' then echo shar: will not over-write existing file "'brushdmt.c'" else sed 's/^X//' << \SHAR_EOF > 'brushdmt.c' X/* X** brushdmt.c - an alternate screen blanking program for Suns X** X** Comments to: X** pokey@well.sf.ca.us X** {ucbvax, lll-crg, sun!pacbell, apple, hplabs}!well!pokey X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#define MAXBRUSHES 500 X#define MAXDELTA 5 X X#define DEFAULT_WAITING_SECS 600 X X#define BLANKING_SLEEPS_PERSEC 20 X X#define TRYS 50 X X#include <stdio.h> X#include <signal.h> X#include <sys/types.h> X#include <sys/time.h> X#include <sys/stat.h> X#include <pixrect/pixrect_hs.h> X X#define min(a,b) ( (a) < (b) ? (a) : (b) ) X XPixrect *disp_pr, *save_pr; Xint screen_saved = 0; Xint disp_w, disp_h; Xint brushes; XPixrect *brush[MAXBRUSHES]; Xint brush_w[MAXBRUSHES], brush_h[MAXBRUSHES]; Xint brush_type[MAXBRUSHES]; X#define BT_JUMP 0 X#define BT_GLIDE 1 Xint any_jumpers, any_gliders; Xint brush_x[MAXBRUSHES], brush_y[MAXBRUSHES]; Xint brush_dx[MAXBRUSHES], brush_dy[MAXBRUSHES]; XPixfont *font; Xint font_width, font_height, null_yoffset; X Xunsigned waiting_secs; Xunsigned blanking_usecs; X Xtime_t curr_time, last_time; X Xlong random(), time(); X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X int argn, type; X colormap_t colormap; X FILE *fd; X unsigned idle, idle_time(); X int sighandler(); X char *usage = "usage: %s [-d <seconds>] [ [-j|-g] <rasterfile> ] ...\n"; X X /* Open display. */ X if ( (disp_pr = pr_open( "/dev/fb" )) == (Pixrect *) 0 ) X { X (void) fprintf( stderr, "%s: error opening display\n", argv[0] ); X exit( 1 ); X } X disp_w = disp_pr->pr_size.x; X disp_h = disp_pr->pr_size.y; X if ( (save_pr = mem_create(disp_w,disp_h,disp_pr->pr_depth)) == (Pixrect *) 0 ) X { X (void) fprintf( X stderr, "%s: not enough memory to save display\n", argv[0] ); X exit( 1 ); X } X X /* Parse args. */ X argn = 1; X brushes = 0; X any_jumpers = any_gliders = 0; X type = BT_JUMP; X colormap.type = RMT_NONE; X waiting_secs = DEFAULT_WAITING_SECS; X X while ( argn < argc ) X { X if ( strcmp( argv[argn], "-d" ) == 0 ) X { X argn++; X if ( argn >= argc || X sscanf( argv[argn], "%d", &waiting_secs ) != 1 ) X { X (void) fprintf( stderr, usage, argv[0] ); X exit( 1 ); X } X } X else if ( strcmp( argv[argn], "-g" ) == 0 ) X type = BT_GLIDE; X else if ( strcmp( argv[argn], "-j" ) == 0 ) X type = BT_JUMP; X else if ( argv[argn][0] == '-' && argv[argn][1] != '\0' ) X { X (void) fprintf( stderr, usage, argv[0] ); X exit( 1 ); X } X else X { X if ( strcmp( argv[argn], "-" ) == 0 ) X fd = stdin; X else X if ( (fd = fopen( argv[argn], "r" )) == (FILE *) 0 ) X { X perror( argv[argn] ); X exit( 1 ); X } X if ( (brush[brushes] = pr_load(fd,&colormap)) == (Pixrect *) 0 ) X { X (void) fprintf( X stderr, "%s: error reading brush from %s\n", X argv[0], argv[argn] ); X exit( 1 ); X } X if ( fd != stdin ) X (void) fclose( fd ); X if ( brush[brushes]->pr_depth > disp_pr->pr_depth ) X { X (void) fprintf( X stderr, "%s: brush in %s is too deep for this display\n", X argv[0], argv[argn] ); X exit( 1 ); X } X brush_w[brushes] = brush[brushes]->pr_size.x; X brush_h[brushes] = brush[brushes]->pr_size.y; X brush_type[brushes] = type; X if ( ! newxy( brushes ) ) X { X (void) fprintf( X stderr, "%s: not enough room on the screen!\n", argv[0] ); X exit( 1 ); X } X if ( type == BT_JUMP ) X any_jumpers = 1; X else if ( type == BT_GLIDE ) X { X any_gliders = 1; X newdeltas( brushes ); X } X brushes++; X } X argn++; X } X X if ( brushes == 0 ) X { X if ( (font = pf_default( )) == (Pixfont *) 0 ) X { X (void) fprintf( stderr, "%s: error opening font\n", argv[0] ); X exit( 1 ); X } X font_width = font->pf_defaultsize.x; X font_height = font->pf_defaultsize.y; X brush[brushes] = (Pixrect *) 0; X brush_w[brushes] = 10 * font_width; X brush_h[brushes] = 3 * font_height; X brush_type[brushes] = type; X (void) newxy( brushes ); X if ( type == BT_JUMP ) X any_jumpers = 1; X else if ( type == BT_GLIDE ) X { X any_gliders = 1; X newdeltas( brushes ); X } X null_yoffset = X ( brush_h[brushes] - 2 * font_height ) / 2 - X font->pf_char[77].pc_home.y; X brushes++; X } X X srandom( (int) time( (long *) 0 ) ); X (void) signal( SIGHUP, sighandler ); X (void) signal( SIGINT, sighandler ); X (void) signal( SIGTERM, sighandler ); X (void) nice( 15 ); X X blanking_usecs = 1000000 / BLANKING_SLEEPS_PERSEC; X for ( ; ; ) X { X idle = 0; X do X { X sleep( waiting_secs - idle ); X } X while ( ( idle = idle_time( ) ) < waiting_secs ); X blank_init( ); X do X { X blank( ); X usleep( blanking_usecs ); X } X while ( idle_time( ) >= waiting_secs ); X blank_term( ); X } X } X Xblank_init( ) X { X int i; X X save_screen( ); X pr_rop( disp_pr, 0, 0, disp_w, disp_h, PIX_SET, (Pixrect *) 0, 0, 0 ); X for ( i = 0; i < brushes; i++ ) X draw_brush( i ); X last_time = curr_time; X } X Xblank( ) X { X int i; X X if ( any_jumpers ) X { X if ( curr_time != last_time ) X { X last_time = curr_time; X /* Handle jumpers. */ X for ( i = 0; i < brushes; i++ ) X if ( brush_type[i] == BT_JUMP ) X if ( random() % 3 == 0 ) X { X pr_rop( X disp_pr, brush_x[i], brush_y[i], brush_w[i], X brush_h[i], PIX_SET, (Pixrect *) 0, 0, 0 ); X (void) newxy( i ); X draw_brush( i ); X } X else if ( brush[i] == (Pixrect *) 0 ) X /* Always draw null brush, even if it doesn't move. */ X draw_brush( i ); X } X } X X if ( any_gliders ) X { X /* Handle gliders. */ X for ( i = 0; i < brushes; i++ ) X if ( brush_type[i] == BT_GLIDE ) X { X int oldx, oldy; X X oldx = brush_x[i]; X oldy = brush_y[i]; X if ( glidexy( i ) ) X { X /* Draw in new position. */ X draw_brush( i ); X /* Erase remains of old position. */ X if ( brush_dx[i] > 0 ) X pr_rop( X disp_pr, oldx, oldy, brush_dx[i], brush_h[i], X PIX_SET, (Pixrect *) 0, 0, 0 ); X else if ( brush_dx[i] < 0 ) X pr_rop( X disp_pr, oldx + brush_w[i] + brush_dx[i], oldy, X -brush_dx[i], brush_h[i], PIX_SET, X (Pixrect *) 0, 0, 0 ); X if ( brush_dy[i] > 0 ) X pr_rop( X disp_pr, oldx, oldy, brush_w[i], brush_dy[i], X PIX_SET, (Pixrect *) 0, 0, 0 ); X else if ( brush_dy[i] < 0 ) X pr_rop( X disp_pr, oldx, oldy + brush_h[i] + brush_dy[i], X brush_w[i], -brush_dy[i], PIX_SET, X (Pixrect *) 0, 0, 0 ); X } X } X } X } X Xblank_term( ) X { X restore_screen( ); X } X Xdraw_brush( i ) Xint i; X { X if ( brush[i] != (Pixrect *) 0 ) X pr_rop( X disp_pr, brush_x[i], brush_y[i], brush_w[i], brush_h[i], X PIX_SRC, brush[i], 0, 0 ); X else X { X /* Null brush. */ X char *timestr; X X pr_rop( X disp_pr, brush_x[i], brush_y[i], X brush_w[i], brush_h[i], PIX_CLR, (Pixrect *) 0, 0, 0 ); X /* X ** curr_time is kept up to date by idle_time(); otherwise we X ** would just do a time( 0 ) here. X */ X timestr = ctime( &curr_time ); X /* X ** Format of timestr: Wdy Mon DD HH:MM:SS YYYY\n X ** 0 5 10 15 20 X */ X /* First line: HH:MM:SS */ X timestr[19] = '\0'; X pr_text( X disp_pr, brush_x[i] + ( brush_w[i] - 8 * font_width ) / 2, X brush_y[i] + null_yoffset, PIX_SRC, font, &(timestr[11]) ); X /* Second line: Mon DD */ X timestr[10] = '\0'; X pr_text( X disp_pr, brush_x[i] + ( brush_w[i] - 6 * font_width ) / 2, X brush_y[i] + null_yoffset + font_height, PIX_SRC, font, X &(timestr[4]) ); X } X } X Xunsigned Xidle_time( ) X { X struct stat sb; X long mintime; X X curr_time = time( (long *) 0 ); X X my_stat( "/dev/mouse", &sb ); X mintime = curr_time - sb.st_atime; X mintime = min( mintime, curr_time - sb.st_mtime ); X X my_stat( "/dev/kbd", &sb ); X mintime = min( mintime, curr_time - sb.st_atime ); X mintime = min( mintime, curr_time - sb.st_mtime ); X X my_stat( "/dev/console", &sb ); X mintime = min( mintime, curr_time - sb.st_atime ); X mintime = min( mintime, curr_time - sb.st_mtime ); X X return mintime; X } X Xmy_stat( dev, sbP ) Xchar *dev; Xstruct stat *sbP; X { X if ( stat( dev, sbP ) < 0 ) X { X (void) fprintf( stderr, "stat" ); X perror( dev ); X exit( 1 ); X } X } X Xint Xnewxy( i ) Xint i; X { X int oldx, oldy; X int j; X X oldx = brush_x[i]; X oldy = brush_y[i]; X for ( j = 0; j < TRYS; j++ ) X { X brush_x[i] = random() % ( disp_w - brush_w[i] ); X brush_y[i] = random() % ( disp_h - brush_h[i] ); X if ( ! collision( i ) ) X return 1; X } X X brush_x[i] = oldx; X brush_y[i] = oldy; X return 0; X } X Xint Xglidexy( i ) Xint i; X { X int oldx, oldy; X int j; X X oldx = brush_x[i]; X oldy = brush_y[i]; X for ( j = 0; j < TRYS; j++ ) X { X brush_x[i] = oldx + brush_dx[i]; X brush_y[i] = oldy + brush_dy[i]; X if ( brush_x[i] >= 0 && brush_x[i] + brush_w[i] < disp_w && X brush_y[i] >= 0 && brush_y[i] + brush_h[i] < disp_h && X ! collision( i ) ) X return 1; X newdeltas( i ); X } X X brush_x[i] = oldx; X brush_y[i] = oldy; X return 0; X } X Xint collision( i ) Xint i; X { X int j; X register int x1, y1, w1, h1; X register int x2, y2, w2, h2; X X x1 = brush_x[i]; X y1 = brush_y[i]; X w1 = brush_w[i]; X h1 = brush_h[i]; X for ( j = 0; j < brushes; j++ ) X if ( j != i ) X { X x2 = brush_x[j]; X y2 = brush_y[j]; X w2 = brush_w[j]; X h2 = brush_h[j]; X if ( x1 < x2 + w2 && x2 < x1 + w1 && X y1 < y2 + h2 && y2 < y1 + h1 ) X return 1; X } X X return 0; X } X Xnewdeltas( i ) Xint i; X { X brush_dx[i] = random() % ( MAXDELTA * 2 ) - MAXDELTA; X if ( brush_dx[i] <= 0 ) brush_dx[i]--; X brush_dy[i] = random() % ( MAXDELTA * 2 ) - MAXDELTA; X if ( brush_dy[i] <= 0 ) brush_dy[i]--; X } X X/* ARGSUSED */ Xint Xsighandler( sig, code, scp ) Xint sig, code; Xstruct sigcontext *scp; X { X restore_screen( ); X exit( 0 ); X } X Xsave_screen( ) X { X pr_rop( save_pr, 0, 0, disp_w, disp_h, PIX_SRC, disp_pr, 0, 0 ); X screen_saved = 1; X } X Xrestore_screen( ) X { X if ( screen_saved ) X { X char command[200]; X X /* X ** Refresh the screen as well as we can, which is not very. X ** Perhaps no one will notice. X */ X pr_rop( disp_pr, 0, 0, disp_w, disp_h, PIX_SRC, save_pr, 0, 0 ); X X#ifdef XREFRESH X /* If X happens to be running, do a real refresh. */ X sprintf( command, "%s 2> /dev/null &", XREFRESH ); X (void) system( command ); X#endif XREFRESH X X#ifdef SUNREFRESH X /* If suntools happens to be running, do a real refresh. */ X sprintf( X command, X "%s -position 0 0 -size %d %d -label refresh true 2> /dev/null &", X SUNREFRESH, disp_w, disp_h ); X (void) system( command ); X#endif SUNREFRESH X X screen_saved = 0; X } X } SHAR_EOF if test 10937 -ne "`wc -c < 'brushdmt.c'`" then echo shar: error transmitting "'brushdmt.c'" '(should have been 10937 characters)' fi fi # end of overwriting check # End of shell archive exit 0