DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T b

⟦c26789cd2⟧ TextFile

    Length: 26226 (0x6672)
    Types: TextFile
    Names: »button.c.orig«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/X/Dragon/button.c.orig« 

TextFile

/******************************************************************************
* Dragon - a version of Mah-Jongg for X Windows
*
* Author: Gary E. Barnes	March 1989
*
* button.c - Deals with the command buttons on the board
******************************************************************************/

#include "main.h"

#include <X11/Dialog.h>

extern int		Side_X;
extern int		Side_Y;
extern int		Shadow_X;
extern int		Shadow_Y;
extern unsigned int	Tile_Width;
extern unsigned int	Tile_Height;

extern void Button_Expose();
static void Cheat();
static void Game_Exit();
extern void Hints();
static void New_Game();
static void Other();
extern void Read_Game();
static void Redraw_All();
extern void Restart_Game();
static void Restore_Game();
static void Save_Game();
extern void Show_Samples();
static void Sides();
static void Sync_All();
extern void Setup_New_Game();
extern void Write_Game();

typedef void (*ActionProc)();

typedef struct _Button_Rec {
    char	*text;
    ActionProc	 action;
    Boolean	toggle;
    Boolean	hilite;
    int		 x;
    int		 y;
    int		 text_x;
    int		 text_y;
    XPoint	 border[6*4+4+1];
} Button_Rec, *Button;

#define Button_NULL	((Button)0)

#define NBUTTONS	8


Button_Rec	Buttons1[NBUTTONS] = {
    { "New Game",   New_Game,	  FALSE   },
    { "Restart",    Restart_Game, FALSE  },
    { "Save",	    Save_Game,    FALSE   },
    { "Other",	    Other,	  TRUE    },

    { "Hint",	    Hints,	  FALSE   },
    { NULL },
    { "Restore",    Restore_Game, FALSE  },
    { "Quit",	    Game_Exit,    FALSE },
};

Button_Rec	Buttons2[NBUTTONS] = {
    { "Redraw",	    Redraw_All,	  FALSE   },
    { "Sides",	    Sides,	  FALSE   },
    { "Samples",    Show_Samples, TRUE    },
    { "Other",	    Other,	  TRUE    },

    { "Cheat",	    Cheat,	  TRUE    },
    { "Sync",	    Sync_All,	  TRUE    },
    { NULL },
    { NULL },
};

static Button	All_Buttons	= &Buttons1[0];

static int	Button_Width  = 0;
static int	Button_Height = 0;

static int	Letter_Indent = 0;
static int	Letter_Height = 0;
static int	Letter_Width  = 0;

Widget		Complaint	= (Widget)NULL;
Widget		Complainer	= (Widget)NULL;

\f


static void Complain_OK()
/******************************************************************************
* Called when the "OK" button on our complaint is pressed.
******************************************************************************/
{
    XtPopdown( Complainer );
} /* Complain_OK */

\f


void Complain( about )
     String	about;
/******************************************************************************
* Pop up a dialog box and complain to the user.
******************************************************************************/
{
#undef SETARG
#define SETARG(name,value) \
    if (argi >= XtNumber(args)) {fprintf(stderr,"BS args overrun!\n");} \
    XtSetArg( args[argi], name,  value ); ++argi;

    Arg		args[10];
    int		argi;

/*--Create our widgets if this is a first time. */

    if (Complaint == (Widget)NULL) {
	Complainer =
	  XtCreatePopupShell( "complainer", transientShellWidgetClass,
			      Dragon, (ArgList)NULL, (Cardinal)0 );
	argi = 0;
	SETARG( XtNcursor,		Dragon_Resources.Cursor );
	Complaint =
	  XtCreateManagedWidget( "complaint", dialogWidgetClass,
				 Complainer, args, (Cardinal)argi );
	XtDialogAddButton( Complaint, "OK", Complain_OK, (caddr_t)NULL );
    }

/*--Set the label on the complaint. */

    argi = 0;
    SETARG(	XtNlabel,	about	);
    XtSetValues( Complaint, args, (Cardinal)argi );

/*--Realize and pop up the dialog box. */

    {	int		xret, yret;
	Window		child;
	(void)XTranslateCoordinates( XtDisplay(Dragon), XtWindow(Dragon),
				     RootWindowOfScreen(XtScreen(Dragon)),
				     0, 0, &xret, &yret, &child );
	XtMoveWidget( Complainer, xret, yret );
    }
    XtPopup( Complainer, XtGrabNone );
    XFlush( XtDisplay(Board) );

} /* Complain */

\f


int	Cheating = FALSE;

/*ARGSUSED*/
static void Cheat( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
{

    DEBUG_CALL(Cheat);
    Cheating = !Cheating;
    DEBUG_RETURN(Cheat);

} /* Cheat */

\f


/*ARGSUSED*/
static void Game_Exit( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
/******************************************************************************
* Called when we want to exit.
******************************************************************************/
{
    XEvent	event2;

    DEBUG_CALL(Game_Exit);
    for (;;) {
	XNextEvent( XtDisplay(Board), &event2 );
	if (event2.xany.type == ButtonRelease) { break; }
    }
    exit(0);

} /* Game_Exit */

\f


/*ARGSUSED*/
static void New_Game( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
{

    DEBUG_CALL(New_Game);
    Setup_New_Game();
    XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE );
    DEBUG_RETURN(New_Game);

} /* New_Game */

\f


/*ARGSUSED*/
static void Other( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
/******************************************************************************
* Called to change button menus.
******************************************************************************/
{

    DEBUG_CALL(Other);
    if (All_Buttons == &Buttons1[0]) {
	All_Buttons = &Buttons2[0];
    } else {
	All_Buttons = &Buttons1[0];
    }
    All_Buttons[3].hilite = !All_Buttons[3].hilite;
    XClearArea( XtDisplay(Board), XtWindow(w),
	        0, 0, 0, (unsigned)(2*Tile_Height-Side_Y-Shadow_Y-1), FALSE );
    Button_Expose( w, event, params, num_params );
    DEBUG_RETURN(Other);

} /* Other */

\f


/*ARGSUSED*/
static void Redraw_All( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
{

    DEBUG_CALL(Redraw_All);
    XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE );
    DEBUG_RETURN(Redraw_All);

} /* Redraw_All */

\f


/*ARGSUSED*/
static void Restore_Game( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
/******************************************************************************
* Called to restore a previous game.
******************************************************************************/
{
    extern char *getenv();
    char	 name[1024];
    FILE	*file;

    DEBUG_CALL(Restore_Game);
    strcpy( &name[0], getenv( "HOME" ) );
    strcat( &name[0], "/.dragon-save" );
    file = fopen( &name[0], "r" );
    if (file == (FILE*)NULL) {
	Complain( "Cannot open the $HOME/.dragon-save file." );
    } else {
	Read_Game( file );
	(void)fclose( file );
	Redraw_All( w, event, params, num_params );
    }
    DEBUG_RETURN(Restore_Game);

} /* Restore_Game */

\f


/*ARGSUSED*/
static void Save_Game( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
/******************************************************************************
* Called to save the current game.
******************************************************************************/
{
    extern char *getenv();
    char	 name[1024];
    FILE	*file;

    DEBUG_CALL(Save_Game);
    strcpy( &name[0], getenv( "HOME" ) );
    strcat( &name[0], "/.dragon-save" );
    file = fopen( &name[0], "w" );
    if (file == (FILE*)NULL) {
	Complain( "Cannot open the $HOME/.dragon-save file." );
    } else {
	Write_Game( file );
	(void)fclose( file );
    }
    DEBUG_RETURN(Save_Game);

} /* Save_Game */

\f


/*ARGSUSED*/
static void Sides( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
{

    DEBUG_CALL(Cheat);
    if (Tile_Control & SHADOW) {
	if (Tile_Control & BLACKSIDE) {
	    if (Tile_Control & GRAYSIDE) {
		Tile_Control &= ~(SHADOW | BLACKSIDE | GRAYSIDE);
	    } else {
		Tile_Control &= ~SHADOW;
		Tile_Control |= GRAYSIDE;
	    }
	} else {
	    Tile_Control &= ~SHADOW;
	    Tile_Control |= BLACKSIDE;
	}
    } else {
	Tile_Control |= SHADOW;
    }
    XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE );
    DEBUG_RETURN(Cheat);

} /* Sides */

\f


/*ARGSUSED*/
static void Sync_All( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
{
    static int	onoff = FALSE;

    DEBUG_CALL(Sync_All);
    onoff = !onoff;
    Dragon_Resources.Debug = onoff;
    XSynchronize( XtDisplay(Board), onoff );
    DEBUG_RETURN(Sync_All);

} /* Sync_All */

\f


void Do_Button_Configuration()
/******************************************************************************
* Called when the Board changes Tile sizes.
******************************************************************************/
{
#define BUTTONS_PER_LINE 4
#undef PNT
#define PNT(X,Y)	pnt->x = X; pnt->y = Y; ++pnt;
    int		 indent;
    int		 x, dx;
    int		 y, dy;
    int		 i, j;
    int		 f, s, t, l;
    XPoint	*pnt;
    register Button	but;

/*--Buttons will be three tiles wide and 2/3'rd of a tile high. */

    DEBUG_CALL(Do_Button_Configuration);
    Button_Width = 3 * Tile_Width;
    dx = Button_Width + Tile_Width / 2;
    Button_Height = 5 * Tile_Height / 9;
    dy = Tile_Height * 8 / 10;

/*--Letters are as large as can fit within the buttons. */

    indent = Button_Height / 5;
    Letter_Indent = indent + 2;
    s = Letter_Indent * 3 / 4;
    t = s / 2;
    f = indent - s + t;
    Letter_Height = Button_Height - (2 * indent) - 2;
    if ((Letter_Height & 1) == 0) { --Letter_Height; }
    Letter_Width  = (Button_Width - (2 * indent) - 2) / 8 - 2;
    if ((Letter_Width & 1) == 0) { --Letter_Width; }
    
/*--Now place the buttons. */

    for (j = 1; j >= 0; --j) {
	if (j == 1) {
	    but = &Buttons1[0];
	} else {
	    but = &Buttons2[0];
	}
	x = indent + 12;
	y = indent + 4;
	for (i = 0; i < NBUTTONS; ++i) {
	    if (but[i].text == NULL) { goto Next_Button; }
	    l = strlen(but[i].text);
	    if (l > 8) {
		fprintf( stderr, "Button name too long: %s\n",
			 but[i].text );
		l = 8;
	    }
	    but[i].x = x;
	    but[i].y = y;
	    but[i].text_x = (Button_Width - l * (Letter_Width+2) + 2) / 2;
	    but[i].text_y = indent + 1;

	    pnt = &but[i].border[0];
	    PNT( x,				y + indent		);
	    PNT( f,				0			);
	    PNT( 0,				-s			);
	    PNT( -t,				0			);
	    PNT( 0,				t			);
	    PNT( s,				0			);
	    PNT( 0,				-f			);
	    PNT( Button_Width - 2 * indent,	0			);
	    PNT( 0,				f			);
	    PNT( s,				0			);
	    PNT( 0,				-t			);
	    PNT( -t,				0			);
	    PNT( 0,				s			);
	    PNT( f,				0			);
	    PNT( 0,				Button_Height - 2*indent);
	    PNT( -f,				0			);
	    PNT( 0,				s			);
	    PNT( t,				0			);
	    PNT( 0,				-t			);
	    PNT( -s,				0			);
	    PNT( 0,				f			);
	    PNT( -(Button_Width - 2*indent),	0			);
	    PNT( 0,				-f			);
	    PNT( -s,				0			);
	    PNT( 0,				t			);
	    PNT( t,				0			);
	    PNT( 0,				-s			);
	    PNT( -f,				0			);
	    PNT( 0,				-Button_Height+2*indent	);

	  Next_Button :
	    if (i % BUTTONS_PER_LINE + 1 == BUTTONS_PER_LINE) {
		x = indent + 12;
		y += dy;
	    } else {
		x += dx;
	    }
	}
    }
    DEBUG_RETURN(Do_Button_Configuration);

} /* Do_Button_Configuration */

\f


void Draw_Text( str, x, y )
     char	*str;
     int	 x;
     int	 y;
/******************************************************************************
* Called to draw the vector text in some button.
******************************************************************************/
{
    static char pntserr[] = "DT pnts overflow!\n";
    XPoint	pnts[50];
    int		pnti;
    int		h1;
    int		w1;

#undef PNT
#define PNT(X,Y) \
    if (pnti >= XtNumber(pnts)){fprintf(stderr,pntserr);} \
    pnts[pnti].x = X; pnts[pnti].y = Y; ++pnti
    ;

/*--Position ourselves for the first letter. */

    DEBUG_CALL(Draw_Text);
    h1 = Letter_Height - 1;
    w1 = Letter_Width - 1;

/*--Loop over all letters in the text. */

    for ( ; *str != '\000'; x+=Letter_Width+2,++str) {
	pnti = 0;
	switch (*str) {

/*--The letters we have. */

	  case '0' :
	    {	int	w6, h6, h26;

		h6 = h1 / 6;
		h26 = h1 - 4 * h6;
		w6 = w1 / 6;

		PNT( x,		y+h6+h6	);
		PNT( 0,		h26	);
		PNT( w6,	h6	);
		PNT( w6,	h6	);
		PNT( 2*w6,	0	);
		PNT( w6,	-h6	);
		PNT( w6,	-h6	);
		PNT( 0,		-h26	);
		PNT( -w6,	-h6	);
		PNT( -w6,	-h6	);
		PNT( -2*w6,	0	);
		PNT( -w6,	h6	);
		PNT( -w6,	h6	);
		break;
	    }

	  case '1' :
	    {
		PNT( x+(w1+1)/2,y	);
		PNT( 0,		h1	);
		break;
	    }

	  case '2' :
	    {	int	w6, w46, h6, h6r;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h6r = (h1 - h6 * 6) / 2;

		PNT( x,		y + h6	);
		PNT( w6,	-h6	);
		PNT( w46,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h6+h6r	);
		PNT( -w6,	h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h1-5*h6-h6r);
		PNT( 0,		h6	);
		PNT( w1,	0	);
		break;
	    }

	  case '3' :
	    {	int	w6, w46, h6, h6r;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h6r = (h1 - h6 * 6) / 2;

		PNT( x,		y + h6	);
		PNT( w6,	-h6	);
		PNT( w46,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h6+h6r	);
		PNT( -w6,	h6	);
		PNT( -w46/2,	0	);
		PNT( w46/2,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h1-5*h6-h6r);
		PNT( -w6,	h6	);
		PNT( -w46,	0	);
		PNT( -w6,	-h6	);
		break;
	    }

	  case '4' :
	    {	int	w23, h23;

		w23 = w1 * 2 / 3;
		h23 = h1 * 2 / 3;

		PNT( x + w1,	y + h23	);
		PNT( -w1,	0	);
		PNT( w23,	-h23	);
		PNT( 0,		h1	);
		break;
	    }

	  case '5' :
	    {	int	w6, w46, h6, h6r;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h6r = (h1 - h6 * 6) / 2;

		PNT( x + w1,	y	);
		PNT( -w1,	0	);
		PNT( 0,		h1-3*h6-h6r);
		PNT( w1-w6,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h6+h6r	);
		PNT( -w6,	h6	);
		PNT( -w46,	0	);
		PNT( -w6,	-h6	);
		break;
	    }

	  case '6' :
	    {	int	w6, w46, h6, h6r;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		if (((h6-w6) & 1) == 1) { --h6; }
		h6r = (h1 - h6 * 6) / 2;

		PNT( x + w1,	y+h6	);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h1-2*h6);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	-h6	);
		PNT( 0,		-h6-h6r );
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		break;
	    }

	  case '7' :
	    {
		PNT( x,		y	);
		PNT( w1,	0	);
		PNT( -w1,	h1	);
		break;
	    }

	  case '8' :
	    {	int	w6, w46, h6, h6r;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		if (((h6-w6) & 1) == 1) { --h6; }
		h6r = (h1 - h6 * 6) / 2;

		PNT( x + w1,	y + h6	);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h6+h6r	);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h1-5*h6-h6r);
		PNT( -w6,	h6	);
		PNT( -w46,	0	);
		PNT( -w6,	-h6	);
		PNT( 0,		-h1+5*h6+h6r);
		PNT( w6,	-h6	);
		PNT( w46,	0	);
		PNT( w6,	-h6	);
		PNT( 0,		-h6-h6r	);
		break;
	    }

          case '9' :
	    {	int	w6, w46, h6, h6r;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h6r = (h1 - h6 * 6) / 2;

		PNT( x,		y+h1-h6	);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	-h6	);
		PNT( 0,		-h1+2*h6);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h6+h6r);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	-h6	);
		break;
	    }


	  case 'a' : case 'A' :
	    {	int	h2, w2, w5l, w5r;

		h2 = h1 * 12 / 20;
		w2 = (w1+1) / 2;
		w5l = w1 / 5;
		w5r = w1 - w5l;

		PNT( x,		y + h1	);
		PNT( w5l,	-(h1-h2));
		PNT( w5r - w5l,	0	);
		PNT( w2 - w5r,	-h2	);
		PNT( w5l - w2,	h2	);
		PNT( w5r - w5l,	0	);
		PNT( w5l,	h1-h2	);
		break;
	    }

	  case 'b' : case 'B' :
	    {	int	w6, h6;
		int	h2;

		h2 = (h1+1) / 2;
		w6 = w1 / 6;
		h6 = h1 / 6;

		PNT( x,		y + h1  );
		PNT( 0,		-h1	);
		PNT( w1-w6,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h2-h6-h6);
		PNT( -w6,	h6	);
		PNT( -(w1-w6),	0	);
		PNT( w1-w6,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h1-h2-h6-h6);
		PNT( -w6,	h6	);
		PNT( -(w1-w6),	0	);
		break;
	    }

	  case 'c' : case 'C' :
	    {	int	w6, w46, h6, h46;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h46 = h1 - h6 - h6;

		PNT( x + w1,	y + h6	);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h46	);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	-h6	);
		break;
	    }

	  case 'd' : case 'D' :
	    {	int	w6, w56, h6, h46;

		w6 = w1 / 6;
		w56 = w1 - w6;
		h6 = h1 / 6;
		h46 = h1 - h6 - h6;

		PNT( x,		y	);
		PNT( w56,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h46	);
		PNT( -w6,	h6	);
		PNT( -w56,	0	);
		PNT( 0,		-h1	);
		break;
	    }

	  case 'e' : case 'E' :
	    {	int	h2, w2;

		h2 = (h1+1) / 2;
		w2 = (w1+1) / 2;

		PNT( x + w1,	y );
		PNT( -w1,	0 );
		PNT( 0,		h2 );
		PNT( w2,	0 );
		PNT( -w2,	0 );
		PNT( 0,		h1-h2 );
		PNT( w1,	0 );
		break;
	    }

	  case 'f' : case 'F' :
	    {	int	h2, w2;

		h2 = (h1+1) / 2;
		w2 = (w1+1) / 2;

		PNT( x + w1,	y );
		PNT( -w1,	0 );
		PNT( 0,		h2 );
		PNT( w2,	0 );
		PNT( -w2,	0 );
		PNT( 0,		h1-h2 );
		break;
	    }

	  case 'g' : case 'G' :
	    {	int	w6, w46, h6, h46;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h46 = h1 - h6 - h6;

		PNT( x + w1,	y + h6	);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h46	);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	-h6	);
		PNT( 0,		h6-(h1+1)/2);
		PNT( -(w1+1)/2,	0	);
		break;
	    }

	  case 'h' : case 'H' :
	    {	int	h2 = (h1+1) / 2;

		PNT( x,		y	);
		PNT( 0,		h1	);
		PNT( 0,		-h2	);
		PNT( w1,	0	);
		PNT( 0,		h2	);
		PNT( 0,		-h1	);
		break;
	    }

	  case 'i' : case 'I' :
	    {	int	w2 = (w1+1) / 2;

		PNT( x,		y	);
		PNT( w1,	0	);
		PNT( -w2,	0	);
		PNT( 0,		h1	);
		PNT( -w2,	0	);
		PNT( w1,	0	);
		break;
	    }

	  case 'k' : case 'K' :
	    { 	int	h2 = (h1+1) / 2;

		PNT( x,		y	);
		PNT( 0,		h1	);
		PNT( 0,		-h2	);
		PNT( w1,	-(h1-h2));
		PNT( -w1,	h1-h2	);
		PNT( w1,	h2	);
		break;
	    }

	  case 'l' : case 'L' :
	    {	PNT( x,		y );
		PNT( 0,		h1 );
		PNT( w1,	0 );
		break;
	    }

	  case 'm' : case 'M' :
	    {	int	w2 = (w1+1) / 2;

		PNT( x,		y + h1	);
		PNT( 0,		-h1	);
		PNT( w2,	h1	);
		PNT( w1 - w2,	-h1	);
		PNT( 0,		h1	);
		break;
	    }

	  case 'n' : case 'N' :
	    PNT( x,	y + h1	);
	    PNT( 0,	-h1	);
	    PNT( w1,	h1	);
	    PNT( 0,	-h1	);
	    break;

	  case 'o' : case 'O' :
	    {	int	w6, w46, h6, h46;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h46 = h1 - h6 - h6;

		PNT( x + w1,	y + h6	);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h46	);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	-h6	);
		PNT( 0,		-h46	);
		break;
	    }

	  case 'p' : case 'P' :
	    {	int	w6, h6;
		int	h2;

		h2 = (h1+1) / 2;
		w6 = w1 / 6;
		h6 = h1 / 6;

		PNT( x,		y + h1  );
		PNT( 0,		-h1	);
		PNT( w1-w6,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h2-h6-h6);
		PNT( -w6,	h6	);
		PNT( -(w1-w6),	0	);
		break;
	    }

	  case 'q' : case 'Q' :
	    {	int	w6, w46, h6, h46;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h46 = h1 - h6 - h6;

		PNT( x + w1,	y + h6	);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h46	);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( -w6-w6,	-h6	);
		PNT( w6+w6,	h6	);
		PNT( w6,	h6	);
		PNT( -w6,	-h6	);
		PNT( w6,	-h6	);
		PNT( 0,		-h46	);
		break;
	    }

	  case 'r' : case 'R' :
	    {	int	w6, h6;
		int	h2;

		h2 = (h1+1) / 2;
		w6 = w1 / 6;
		h6 = h1 / 6;

		PNT( x,		y + h1  );
		PNT( 0,		-h1	);
		PNT( w1-w6,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h2-h6-h6);
		PNT( -w6,	h6	);
		PNT( -(w1-w6),	0	);
		PNT( w1-w6,	0	);
		PNT( w6,	h2	);
		break;
	    }

	  case 's' : case 'S' :
	    {	int	w6, w46, h6, h6r;

		w6 = w1 / 6;
		w46 = w1 - w6 - w6;
		h6 = h1 / 6;
		h6r = (h1 - h6 * 6) / 2;

		PNT( x + w1,	y + h6	);
		PNT( -w6,	-h6	);
		PNT( -w46,	0	);
		PNT( -w6,	h6	);
		PNT( 0,		h6+h6r	);
		PNT( w6,	h6	);
		PNT( w46,	0	);
		PNT( w6,	h6	);
		PNT( 0,		h6+h6r	);
		PNT( -w6,	h6	);
		PNT( -w46,	0	);
		PNT( -w6,	-h6	);
		break;
	    }

	  case 't' : case 'T' :
	    {	int	w2 = (w1+1) / 2;

		PNT( x,		y	);
		PNT( w1,	0	);
		PNT( -w2,	0	);
		PNT( 0,		h1	);
		break;
	    }

	  case 'u' : case 'U' :
	    {	int	w6, h6, h56;

		w6 = w1 / 6;
		h6 = h1 / 6;
		h56 = h1 - h6;

		PNT( x,		y	);
		PNT( 0,		h56	);
		PNT( w6,	h6	);
		PNT( w1-w6-w6,	0	);
		PNT( w6,	-h6	);
		PNT( 0,		-h56	);
		break;
	    }

	  case 'v' : case 'V' :
	    {	int	w2;

		w2 = (w1+1) / 2;

		PNT( x,		y	);
		PNT( w2,	h1	);
		PNT( w1-w2,	-h1	);
		break;
	    }

	  case 'w' : case 'W' :
	    {	int	w4, w2;

		w4 = w1 / 4;
		w2 = (w1+1) / 2;

		PNT( x,		y	);
		PNT( w4,	h1	);
		PNT( w2-w4,	-h1	);
		PNT( w1-w2-w4,	h1	);
		PNT( w4,	-h1	);
		break;
	    }

	  case 'y' : case 'Y' :
	    {	int	h2, w2;

		h2 = (h1+1) / 2;
		w2 = (w1+1) / 2;

		PNT( x,		y	);
		PNT( w2,	h2	);
		PNT( w1-w2,	-h2	);
		PNT( -(w1-w2),	h2	);
		PNT( -w2,	h1-h2	);
		break;
	    }

/*--Letters we don't have, and also blank. */

	  default :
	    ; /* do nothing */
	}

/*--Draw the letter. */

	DEBUG_OTHER(Draw_Text,1 char);
	if (pnti > 0) {
	    XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
		        pnts, (Cardinal)pnti, CoordModePrevious );
	}
    }
    DEBUG_RETURN(Draw_Text);

} /* Draw_Text */

\f


void Draw_Score( score, x, y )
     int	score;
     int	x;
     int	y;
/******************************************************************************
* Called to draw the score at x/y.
******************************************************************************/
{
    char		scr[4];
    unsigned int	w = (Letter_Width+2) * 3 + 4;
    unsigned int	h = Letter_Height + 6;

    if (score == 0) {
	int	i, lx, ly;
	Letter_Height *= 3;
	Letter_Width *= 3;
	lx = Board->core.width/6;
	ly = Board->core.height/2 - 2 * Letter_Height;;
	for (i = 5; i > 0; --i) {
	    Draw_Text( "You Win", lx, ly );
	    lx += 2*Letter_Width + 2;
	    ly += Letter_Height + 5;
	}
	Letter_Height /= 3;
	Letter_Width /= 3;
    }

    y -= h + 2;
    XFillRectangle( XtDisplay(Board), XtWindow(Board), Reverse_GC,
		    x, y, w, h );
    XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
		    x-2, y-2, w+4, h+4 );
    XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
		    x-1, y-1, w+2, h+2 );
    XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
		    x, y, w, h );
    scr[0] = (score > 99 ? '0' + score / 100     : ' ');
    scr[1] = (score >  9 ? '0' + score / 10 % 10 : ' ');
    scr[2] = 		   '0' + score % 10;
    scr[3] = '\000';
    Draw_Text( scr, x+3, y+3 );

} /* Draw_Score */

\f


static void Hilite( button )
     Button	button;
/******************************************************************************
* Xor the hilite pattern on the button indicated.
******************************************************************************/
{

    XFillRectangle( XtDisplay(Board), XtWindow(Board), Xor_GC,
		    button->x + 1,
		    button->y + 1,
		    (unsigned int)(Button_Width - 1),
		    (unsigned int)(Button_Height - 1) );

} /* Hilite */

\f


/*ARGSUSED*/
void Button_Expose( w, event, params, num_params )
     Widget	w;
     XEvent	*event;
     String	*params;
     Cardinal	*num_params;
/******************************************************************************
* Called when the Board receives an Expose event.
******************************************************************************/
{
    int		i;

/*--Loop over all buttons and display all "real" buttons. */

    DEBUG_CALL(Button_Expose);
    for (i = 0; i < NBUTTONS; ++i) {
	if (All_Buttons[i].text == NULL) { continue; }

/*--Clear the space for the button and then draw the outline. */

	XFillRectangle( XtDisplay(Board), XtWindow(Board), Reverse_GC,
		        All_Buttons[i].x,
		        All_Buttons[i].y,
		        (unsigned int)(Button_Width + 1),
		        (unsigned int)(Button_Height + 1) );
	XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
		    All_Buttons[i].border,
		    (Cardinal)XtNumber(All_Buttons[0].border),
		    CoordModePrevious );

/*--Draw the text of the button and then do hiliting if we need it. */

	Draw_Text( All_Buttons[i].text,
		   All_Buttons[i].x + All_Buttons[i].text_x,
		   All_Buttons[i].y + All_Buttons[i].text_y );
	if (All_Buttons[i].hilite) {
	    Hilite( &All_Buttons[i] );
	}
    }
    DEBUG_RETURN(Button_Expose);

} /* Button_Expose */

\f


static void De_Hilite_All()
/******************************************************************************
* Called to take the hilite off of any and all buttons everywhere.
******************************************************************************/
{
    int		i;

    for (i = 0; i < NBUTTONS; ++i) {
	if (All_Buttons[i].text == NULL) { continue; }
	if (All_Buttons[i].hilite && !All_Buttons[i].toggle) {
	    All_Buttons[i].hilite = FALSE;
	    Hilite( &All_Buttons[i] );
	    XFlush( XtDisplay(Board) );
	}
    }

} /* De_Hitlite_All */

\f


/*ARGSUSED*/
void Button_Press( w, event, params, num_params )
     Widget		w;
     XButtonEvent	*event;
     String		*params;
     Cardinal		*num_params;
/******************************************************************************
* Called when the Board receives a BtnDown event.
******************************************************************************/
{
    int		i;

/*--First we make sure that nobody is hilited. */

    DEBUG_CALL(Button_Press);
    De_Hilite_All();

/*--See if some button just got clicked. */

    for (i = 0; i < NBUTTONS; ++i) {
	if (All_Buttons[i].text == NULL) { continue; }
	if (event->x >= All_Buttons[i].x &&
	    event->x <= All_Buttons[i].x + Button_Width &&
	    event->y >= All_Buttons[i].y &&
	    event->y <= All_Buttons[i].y + Button_Height) {

/*--Hilite this button and then do whatever it is supposed to do. */

	    All_Buttons[i].hilite = !All_Buttons[i].hilite;
	    Hilite( &All_Buttons[i] );
	    XFlush( XtDisplay(Board) );
	    (*(All_Buttons[i].action))( w, event, params, num_params );
	    break;
	}
    }
    DEBUG_RETURN(Button_Press);

} /* Button_Press */

\f


/*ARGSUSED*/
void Button_Release( w, event, params, num_params )
     Widget		w;
     XButtonEvent	*event;
     String		*params;
     Cardinal		*num_params;
/******************************************************************************
* Called when the Board receives a BtnUp event.
******************************************************************************/
{

/*--Turn off any and all button hilites. */

    DEBUG_CALL(Button_Release);
    De_Hilite_All();
    DEBUG_RETURN(Button_Release);

} /* Button_Release */