Listing 4

/*
 *     shape1.c
 *     An Xlib program using the SHAPE
 *     extension from X11 Release 4.
 *     Written for the C Users Journal.
 *
 *     Link with the X library, e.g.,
 *
 *     cc -o shape1 shape1.c -lXext -lX11
 *
 *     Define SYSV if you have malloc()
 *     declared in stdlib.h.
 *
 *     14 Dec 90
 */

#include <stdio.h>

#ifdef SYSV
#include <stdlib.h>
#endif

#include  <X11/Xlib.h>
#include  <X11/Xutil.h>
#include  <X11/keysymdef.h>
#include  <X11/keysym.h>
#include  <X11/extensions/shape.h>

/*
 *     We have a hard-coded size and location
 */
#define X_LOCATION             10
#define Y_LOCATION             20
#define WIDTH                  400
#define HEIGHT                 300
#define MAX_STRING_LENGTH      400

#define MAX_RECTS              100

/*
 *     Use xlsfonts to find a font name
 *     that is available on your system.
 */
/* #define FONT_NAME  "fixed" */
#define FONT_NAME     "variable"


main( argc, argv )

int     argc;
char    *argv[];

{       /* main */
       Display         *display;
       int             screen;
       Window          rootwindow;
       Window          window;
       XSizeHints      *sizehints;
       XWMHints        *wmhints;
       GC              gc;
       XEvent          event;
       int             done;
       XFontStruct     *font;
       int             shape_status, major_version, minor_version;
       XRectangle      rectangles[ MAX_RECTS + 1 ];
       int             i, number_rectangles, x, y;
       char            message[ MAX_STRING_LENGTH + 4 ];

       /*
        * Connect to an X server.
        */
       display = XOpenDisplay( (char *) NULL );

       if ( display == (Display*) NULL )
              {
              fprintf( stderr, "Error opeing in display\n" );
              exit( 1 );
              }

       screen     = DefaultScreen( display );
       rootwindow = RootWindow( display, screen );

       /*
        * Create a window, note reversed
        * order of colors
        */
       window = XCreateSimpleWindow( display,
                     rootwindow,    /* parent */
                     X_LOCATION, Y_LOCATION,
                     WIDTH, HEIGHT,
                     1,             /* border width */
                     WhitePixel( display, screen ),
                     BlackPixel( display, screen ) );


       /*
        * Set up Window Manager Hints for keyboard input
        */
       wmhints = (XWMHints *) malloc( sizeof(XWMHints) );

       wmhints->flags = InputHint;
       wmhints->input = True;

       XSetWMHints(display, window, wmhints );

       free( wmhints );

       /*
        * Set up hints about the window
        */
       sizehints = (XSizeHints *) malloc( sizeof(XSizeHints) );

       sizehints->x      = X_LOCATION;
       sizehints->y      = Y_LOCATION;
       sizehints->width  = WIDTH;
       sizehints->height = HEIGHT;
       sizehints->flags  = PPosition | PSize;

       /*
        * Use XSetWMProperties() in R4
        *
        */
       XSetStandardProperties( display, window,
              "Shape1",        /* window name */
              "Shape1",        /* icon name */
              (Pixmap) None,   /* Icon pixmap */
              argv, argc,
              sizehints );

       free( sizehints );

       /*
        * Ask for Expose, mouse (Button) and keyboard input
        */
       XSelectInput( display, window,
              ButtonPressMask | ExposureMask | KeyPressMask );

       /*
        * Load up a font.
        */
       font = XLoadQueryFont( display, FONT_NAME );

       if ( font == (XFontStruct *) NULL )
              {
              fprintf( stderr, "Error in loading %s font.\n",
                     FONT_NAME );

              XCloseDisplay( display );
              exit( 1 );
              }

       /*
        * Create a Graphics Context (GC) for drawing text
        */
       gc = XCreateGC( display, window,
              0L, (XGCValues *) NULL );

       XSetForeground( display, gc,
              WhitePixel( display, screen ) );

       /*
        * Set the background color, to,
        * this time to black, since the
        * foreground is white.
        */
       XSetBackground( display, gc,
              BlackPixel( display, screen ) );

       /*
        * Set the GC to draw in the given font.
        */
       XSetFont( display, gc, font->fid );

       /*
        * Check if we have the SHAPE extension
        */
       shape_status = XShapeQueryVersion( display,
              &major_version,
              &minor_version );

       if( shape_status )
              {
              sprintf( message,
                     "SHAPE extension supported at version %d.%d\n",
                     major_version, minor_version );

              /*
               * Set up some rectangles
               */
              i = 0;
              for ( x = 0; x < WIDTH; x += 50 )
                     {
                     for( y = 0; y < HEIGHT; y += 50 )
                            {
                            i++;

                     if ( i >= MAX_RECTS )
                            {
                            i = MAX_RECTS - 1;
                            }

                     rectangles[i].width   = 45;
                     rectangles[i].height  = 45;

                     rectangles[i].x = x;
                     rectangles[i].y = y;
                     }

              }

       /*
        * Make our window's shape be the set of rectangles
        */
       number_rectangles = i;
       XShapeCombineRectangles( display,
              window,
              ShapeBounding,
              0, 0,            /* x, y, offsets */
              rectangles,
              number_rectangles,
              ShapeSet,
              Unsorted );      /* we haven't sorted the rects */
       }
else
       {
       sprintf( message,
              "Sorry, the SHAPE extension is not available" );
       }
/*
 * Make Window appear on the screen
 */
XMapWindow( display, window );
XFlush( display );

done = False;

while( !done )
       {
       XNextEvent( display, &event );

       switch( event.type )
              {
              case ButtonPress:
                     XCloseDisplay( display );

                     exit( 0 );
                     break;
              case Expose:
                     /*
                      * Only redraw when all
                      * Expose events are in
                      */
                     if ( event.xexpose.count == 0 )
                            {
                            RedrawText( display, window,
                                   gc, message );
                            }
                     break;
              }
       }

}      /* main */

RedrawText( display, window, gc, string )

Display *display;
Window  window;
GC      gc;
char    string[];

{       /* RedrawText */

       XDrawImageString( display, window, gc,
              5, 20,         /* location */
              string,
              strlen( string ) );

#define MESSAGE "Click a Mouse Button to Exit"

       XDrawImageString( display, window, gc,
              5, 40,         /* location */
              MESSAGE,
              strlen( MESSAGE ) );

       XFlush( display );

}       /* RedrawText */

/* End of File */