/* pick-lines.c 1.1 */ /* Copyright 1992, 1993 O'Reilly and Associates, Inc. Permission to use, copy, and modify this program is hereby granted, as long as this copyright notice appears in each copy of the program source code. */ #include "book_utils.h" static Display *dpy; static Window window; static PEXRenderer renderer; static int last_line = -1; static PEXColor echo_color, normal_color; /* Pick ids for the lines. */ #define LINE_A 0 #define LINE_B 1 #define LINE_C 2 /* A name for the lines. */ #define LINES 10 static PEXCoord lines[3][2] = {{{0.2, 0.8, 0.0}, {0.8, 0.8, 0.0}}, {{0.2, 0.5, 0.0}, {0.8, 0.5, 0.0}}, {{0.2, 0.2, 0.0}, {0.8, 0.2, 0.0}}}; void draw_lines() { PEXName names[2]; /* Add a name for the lines to the name set. */ names[0] = (PEXName)LINES; PEXAddToNameSet( dpy, renderer, PEXOCRender, 1, names ); /* Set the line attributes. */ PEXSetLineColor( dpy, renderer, PEXOCRender, PEXColorTypeRGB, &normal_color ); PEXSetLineWidth( dpy, renderer, PEXOCRender, 2.0 ); /* Assign pick id's to the lines and draw them. */ PEXSetPickID( dpy, renderer, PEXOCRender, LINE_A ); PEXPolyline( dpy, renderer, PEXOCRender, 2, lines[LINE_A] ); PEXSetPickID( dpy, renderer, PEXOCRender, LINE_B ); PEXPolyline( dpy, renderer, PEXOCRender, 2, lines[LINE_B] ); PEXSetPickID( dpy, renderer, PEXOCRender, LINE_C ); PEXPolyline( dpy, renderer, PEXOCRender, 2, lines[LINE_C] ); } void redraw() { PEXBeginRendering( dpy, window, renderer ); draw_lines(); PEXEndRendering( dpy, renderer, True ); XFlush( dpy ); /* No line is echoed now. */ last_line = -1; } static void echo( line ) int line; { PEXRendererAttributes rattrs; /* Set the renderer's clear-image attribute to False. */ rattrs.clear_image = False; PEXChangeRenderer( dpy, renderer, PEXRAClearImage, &rattrs ); PEXBeginRendering( dpy, window, renderer ); /* Unecho the last line echoed. */ if ( last_line >= 0 ) { PEXSetLineColor( dpy, renderer, PEXOCRender, PEXColorTypeRGB, &normal_color ); PEXPolyline( dpy, renderer, PEXOCRender, 2, lines[last_line] ); XFlush( dpy ); } /* Echo the newly picked line. */ PEXSetLineColor( dpy, renderer, PEXOCRender, PEXColorTypeRGB, &echo_color ); PEXPolyline( dpy, renderer, PEXOCRender, 2, lines[line] ); XFlush( dpy ); last_line = line; PEXEndRendering( dpy, renderer, True ); /* Reset the renderer's clear-image attribute to True. */ rattrs.clear_image = True; PEXChangeRenderer( dpy, renderer, PEXRAClearImage, &rattrs ); XFlush( dpy ); } static void resolve_pick( event ) XEvent *event; { int method, aperture_type, status, better; PEXPickRecord aperture; PEXPickPath *path; XWindowAttributes wattrs; /* Pick-last is always available. */ method = PEXPickLast; /* Determine the aperture by converting the pick point to DC. */ aperture_type = PEXPickDeviceDCHitBox; XGetWindowAttributes( dpy, window, &wattrs ); aperture.box.position.x = event->xbutton.x; aperture.box.position.y = wattrs.height - event->xbutton.y; aperture.box.distance = 2; /* 4-pixel wide aperture */ /* Resolve the pick. */ PEXBeginPickOne( dpy, window, renderer, (long)0, method, aperture_type, &aperture ); draw_lines(); path = PEXEndPickOne( dpy, renderer, &status, &better ); /* Echo it. The pick id tells which line. */ if ( status == PEXPick ) { echo( path->elements[0].pick_id ); PEXFreePickPaths( 1, path ); } else fprintf( stderr, "No pick.\n" ); } static void set_pick_filter( inclusion, exclusion ) PEXNameSet inclusion; PEXNameSet exclusion; { PEXName incl_list[1]; /* Add the line names to the pick filter's inclusion list. */ incl_list[0] = LINES; PEXChangeNameSet( dpy, inclusion, PEXNSReplace, 1, incl_list ); } #define WIN_GEOM "500x500+50+50" main( argc, argv ) int argc; char *argv[]; { XEvent event; XColor bkgd_colr; PEXExtensionInfo *pexinfo; XVisualInfo vis_info; XStandardColormap cmap_info; PEXColorApproxEntry capx_info; PEXRendererAttributes rattrs; int done = 0; if ( !(dpy = ora_init_pex( argv, &pexinfo ) ) ) exit(1); /* Picking is supported only in version 5.1 of PEX. */ if ( !VERSION_5_1( pexinfo ) ) { fprintf( stderr, "PEX Version 5.1 unavailable.\n" ); exit(1); } /* Determine the best visual to use. */ ora_find_best_visual( dpy, &vis_info ); /* Get a standard colormap for the visual. */ if ( !ora_get_standard_colormap( dpy, &vis_info, &cmap_info ) ) { fprintf ( stderr, "Cannot find a standard colormap\n" ); exit(1); } ora_set_stdcmap_approx( &vis_info, &cmap_info, &capx_info ); /* Create the window, specifying a gray background. */ bkgd_colr.red = bkgd_colr.green = bkgd_colr.blue = 0; bkgd_colr.flags = DoRed | DoGreen | DoBlue; window = ora_create_window( dpy, &vis_info, &cmap_info, WIN_GEOM, &bkgd_colr ); /* Set up the PEX renderer. */ if ( !STRUCTURE_SPT( pexinfo ) ) { fprintf( stderr, "Structures not supported.\n" ); exit(1); } renderer = ora_setup_renderer( dpy, window, &capx_info, &rattrs ); /* Set the renderer's background and clear-image attributes. */ rattrs.clear_image = True; rattrs.background_color.type = PEXColorTypeRGB; rattrs.background_color.value.rgb.red = 0.666; rattrs.background_color.value.rgb.green = 0.666; rattrs.background_color.value.rgb.blue = 0.666; PEXChangeRenderer( dpy, renderer, PEXRAClearImage | PEXRABackgroundColor, &rattrs ); /* Make the lines detectable. */ set_pick_filter( rattrs.pick_incl, rattrs.pick_excl ); /* Set the normal and echo colors. */ SET_COLOR( 1, 0, 0, normal_color ); /* red */ SET_COLOR( 1, 1, 1, echo_color ); /* white */ /* Read and respond to X events. */ XSelectInput( dpy, window, ExposureMask | ButtonPressMask ); while ( !done ) { XNextEvent( dpy, &event ); switch ( event.type ) { case Expose: while ( XCheckTypedWindowEvent( dpy, window, Expose, &event ) ) ; /* empty statement */ redraw(); break; case ButtonPress: switch ( event.xbutton.button ) { case Button1: resolve_pick( &event ); break; default: done = 1; break; } break; } } XCloseDisplay( dpy ); return 0; }