jim@athsys.uucp (Jim Becker) (09/01/88)
Please excuse the following source posting to comp.windows.x, but I my stuff isn't complex enough for comp.sources.x to accept it.. The following is a program that clips arbitrary areas of the X display and saves them in Sun raster format, which is FrameMaker and other compatible. See intro comment for further details. -Jim Becker --skip or snip-- /* * snap.c -- Screen snapshot program for SUN raster images (SUN ONLY!) * * Snap is utility that allows the user to select (crop) a portion of an * X window display and save the bitmap image in a FrameMaker compatible * picture format. (FrameMaker is probabily trademarked by Frame, Inc.). * * The "snap" program functions from the command line, and is best if run * in a small window located away from the section(s) of the screen to be * snapshot. It has been written to poll for keyboard keys being held * down, and checks for the keys about three times a second. When it * notices a key of import has been depressed, the appropriate action is * taken. This polling behavior has been done for our requirements, as * we need to have snapshots of the current pointer and popups correct. * * Selection of the portion of the screen to snapshot is done by using a * "guide window". This is a heavy bordered empty window that frames the * portion of the screen that is the current subject of the capture * operation. This window is resized and positioned using the standard * window manager, and it's content is captured in the snapshot. Note * that it must be "behind" the windows of interest when the snapshot is * taken, else it will obscure the image to be captured. The snapshot(s) * taken will contain the entire area within the borders of the guide * window. * * Command line invokation of the program is simple, "snap [ <prefix> ]" * is used to start it. The <prefix> is the optional name that is used * for the stored images. Files that are created by snap are named using * the convention "<prefix>.Snn", where "nn" is the numeric photo number. * Multiple images can be captured during the run of the snap program, * and it appends the photo count to the name. The default <prefix> is * "Snap", yielding names "Snap.S01", "Snap.S02" etc. This makes it easy * to slide through all the names when Importing them into FrameMaker. * * All program selection is via the mechanism of holding down keys, and * the keys that are held down are fairly obscure ones on the Sun keyboard. * Most programs ignore these keys, but beware of editors and such that may * try to interpret these keys. "It seemed fine in all my tests.. (FLW)". * * The keys of interest are as follows: * * ALTERNATE -- Snapshot the screen image * * R13 -- Bring guide window to front * * R15 -- Push guide window to back * * R3 -- Exit the snap program * * * The key depression is not registered immediately, but as soon as * it is noticed a message is printed to the program startup window. * In addition, snapshots ring the terminal bell upon completion. Note * that there is a delay in place after the snapshot before the next, * but the auto-winder is working. Watch out for multiple like shots. * * To build: cc -o snap snap.c -lX11 -lm -lpixrect * * Created on a Sun -- only for a Sun !! * * Right2Copy (R2C) 1988 -- Athena Systems, Inc. * * Rev Date Who Reason * --- ----- --- ------ * V1.0 08/16 Jim Becker Initial creation * 08/23 Jim Becker Cleaned up and released to X * */ #include <ctype.h> #include <stdio.h> #include <pixrect/pixrect_hs.h> #include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #define ICON_NAME "*Snapper*" #define DEFAULT_NAME "Snap" #define SLEEP_DURATION 300000 #define PLACE 100 #define SIZE 400 #define BW 5 #define MIN(a,b) ((a) < (b) ? (a) : (b) ) #define MAX(a,b) ((a) > (b) ? (a) : (b) ) #define TRUE 1 #define FALSE 0 Display *mdisplay; Window mroot, oroot; GC mdefaultgc; int dwidth, dheight; int x, y; int wwidth, wheight; int ww = BW; char name[100]; int count; struct pixrect *screen; /* * init program - create guide window and place */ init() { XSizeHints xsize; int screenno; if( (mdisplay = XOpenDisplay( NULL ) ) == NULL ) { printf("Can't grab display !!\n" ); exit(1); } if( (screen = pr_open( "/dev/fb" ) ) == NULL ) { printf("Can't grab pixrect screen !!\n"); exit(1); } screenno = DefaultScreen(mdisplay); mroot = RootWindow(mdisplay,screenno); dwidth = DisplayWidth( mdisplay,screenno); dheight = DisplayHeight(mdisplay,screenno); mdefaultgc = DefaultGC(mdisplay,screenno); XSetSubwindowMode( mdisplay, mdefaultgc, IncludeInferiors ); oroot = XCreateSimpleWindow( mdisplay, mroot, PLACE,PLACE,SIZE,SIZE, ww,1, WhitePixel(mdisplay,screenno)); if( oroot == NULL ) { printf("Can't open viewing window!\n"); exit(1); } XChangeProperty( mdisplay, oroot, XA_WM_NAME, XA_STRING, 8, PropModeReplace, ICON_NAME, sizeof(ICON_NAME)-1 ); xsize.x = 0; xsize.y = 0; xsize.width = SIZE; xsize.height = SIZE; xsize.min_width = 0; xsize.min_height= 0; xsize.max_width = dwidth; xsize.max_height= dheight; xsize.flags = USPosition | USSize; XSetNormalHints( mdisplay, oroot, &xsize ); x = PLACE; y = PLACE; wheight = SIZE; wwidth = SIZE; XSelectInput( mdisplay, oroot, StructureNotifyMask ); XMapWindow( mdisplay, oroot ); } /* * terminate program */ term() { XDestroyWindow( mdisplay, oroot ); XCloseDisplay( mdisplay ); pr_close( screen ); } /* * handle resize of guide window */ resetsize( cevent ) XConfigureEvent *cevent; { /* get new location and size */ x = MAX(cevent->x,0); y = MAX(cevent->y,0); wwidth = cevent->width; wheight = cevent->height; /* crop to size of the physical screen */ if( (x + wwidth + ww*2) > dwidth ) wwidth = dwidth - x - ww*2; if( (y + wheight + ww*2) > dheight ) wheight = dheight - y - ww*2; } /* * ugly polling of the keymap for special keys. * * (Have checked return code to determine these key combos). */ checkkeymap( done ) short *done; { char keys[32]; char buffer[100]; XQueryKeymap( mdisplay, keys ); if( keys[3] & 0x04 ) { /* check for the "Alternate" key */ /* determine name of new file */ sprintf(buffer, "%s.S%02d", name, ++count); printf("Save to file '%s'...", buffer ); fflush(stdout); if( savecurrenttodisk( buffer ) ) printf(".done.\n"); else printf(".Error saving!!\n"); XBell( mdisplay, 100 ); return; } else if( keys[14] & 0x80 ) { /* check for the R13 key */ printf("Window to front.\n"); XRaiseWindow( mdisplay, oroot ); } else if( keys[15] & 0x02 ) { /* check for the R15 key */ printf("Window to back.\n"); XLowerWindow( mdisplay, oroot ); } else if( keys[3] & 0x40 ) { /* check for the R3 key */ printf("Done snapping.\n"); *done = TRUE; } else return FALSE; return TRUE; } /* * clip the current location and store the frame buffer to disk */ savecurrenttodisk( filename ) char *filename; { FILE *out; struct pixrect *clip; colormap_t *colormap = NULL; int type = RT_BYTE_ENCODED; /* RLL encoded */ int copy_flag = TRUE; out = fopen( filename, "w" ); if( out == NULL ) return FALSE; clip = pr_region( screen, x+ww, y+ww, wwidth, wheight ); pr_dump( clip, out, colormap, type, copy_flag ); fclose( out ); pr_destroy( clip ); return TRUE; } /* * === MAINLINE === */ main( argc, argv ) int argc; char **argv; { XEvent xevent; XButtonEvent *bevent = &xevent.xbutton; short done = FALSE; /* get the name prefix from the user or default */ if( argc >= 2 ) strcpy( name, *++argv ); else strcpy( name, DEFAULT_NAME ); /* initalize program, exits if error */ init(); /* loop until exit key is sensed */ while( !done ) { while( XPending( mdisplay ) ) { XNextEvent( mdisplay, &xevent ); switch( xevent.type ) { case ConfigureNotify: resetsize( &xevent ); break; } } /* check (poll) for keys. if found let user up before repeat */ if( checkkeymap( &done ) && !done ) sleep(1); else usleep(SLEEP_DURATION); } term(); exit(0); }