[comp.sources.x] v03i092: Dragon -- Game of Mah-Jongg, Part03/10

argv@island.uu.net (Dan Heller) (04/30/89)

Submitted-by: Gary E. Barnes <igor!amber!geb>
Posting-number: Volume 3, Issue 92
Archive-name: dragon/part03

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 3 (of 10)."
# Contents:  button.c icon.c main.c main.h
# Wrapped by argv@island on Sun Apr 30 00:17:55 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'button.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'button.c'\"
else
echo shar: Extracting \"'button.c'\" \(26226 characters\)
sed "s/^X//" >'button.c' <<'END_OF_FILE'
X/******************************************************************************
X* Dragon - a version of Mah-Jongg for X Windows
X*
X* Author: Gary E. Barnes	March 1989
X*
X* button.c - Deals with the command buttons on the board
X******************************************************************************/
X
X#include "main.h"
X
X#include <X11/Dialog.h>
X
Xextern int		Side_X;
Xextern int		Side_Y;
Xextern int		Shadow_X;
Xextern int		Shadow_Y;
Xextern unsigned int	Tile_Width;
Xextern unsigned int	Tile_Height;
X
Xextern void Button_Expose();
Xstatic void Cheat();
Xstatic void Game_Exit();
Xextern void Hints();
Xstatic void New_Game();
Xstatic void Other();
Xextern void Read_Game();
Xstatic void Redraw_All();
Xextern void Restart_Game();
Xstatic void Restore_Game();
Xstatic void Save_Game();
Xextern void Show_Samples();
Xstatic void Sides();
Xstatic void Sync_All();
Xextern void Setup_New_Game();
Xextern void Write_Game();
X
Xtypedef void (*ActionProc)();
X
Xtypedef struct _Button_Rec {
X    char	*text;
X    ActionProc	 action;
X    Boolean	toggle;
X    Boolean	hilite;
X    int		 x;
X    int		 y;
X    int		 text_x;
X    int		 text_y;
X    XPoint	 border[6*4+4+1];
X} Button_Rec, *Button;
X
X#define Button_NULL	((Button)0)
X
X#define NBUTTONS	8
X
X
XButton_Rec	Buttons1[NBUTTONS] = {
X    { "New Game",   New_Game,	  FALSE   },
X    { "Restart",    Restart_Game, FALSE  },
X    { "Save",	    Save_Game,    FALSE   },
X    { "Other",	    Other,	  TRUE    },
X
X    { "Hint",	    Hints,	  FALSE   },
X    { NULL },
X    { "Restore",    Restore_Game, FALSE  },
X    { "Quit",	    Game_Exit,    FALSE },
X};
X
XButton_Rec	Buttons2[NBUTTONS] = {
X    { "Redraw",	    Redraw_All,	  FALSE   },
X    { "Sides",	    Sides,	  FALSE   },
X    { "Samples",    Show_Samples, TRUE    },
X    { "Other",	    Other,	  TRUE    },
X
X    { "Cheat",	    Cheat,	  TRUE    },
X    { "Sync",	    Sync_All,	  TRUE    },
X    { NULL },
X    { NULL },
X};
X
Xstatic Button	All_Buttons	= &Buttons1[0];
X
Xstatic int	Button_Width  = 0;
Xstatic int	Button_Height = 0;
X
Xstatic int	Letter_Indent = 0;
Xstatic int	Letter_Height = 0;
Xstatic int	Letter_Width  = 0;
X
XWidget		Complaint	= (Widget)NULL;
XWidget		Complainer	= (Widget)NULL;
X
X
Xstatic void Complain_OK()
X/******************************************************************************
X* Called when the "OK" button on our complaint is pressed.
X******************************************************************************/
X{
X    XtPopdown( Complainer );
X} /* Complain_OK */
X
X
Xvoid Complain( about )
X     String	about;
X/******************************************************************************
X* Pop up a dialog box and complain to the user.
X******************************************************************************/
X{
X#undef SETARG
X#define SETARG(name,value) \
X    if (argi >= XtNumber(args)) {fprintf(stderr,"BS args overrun!\n");} \
X    XtSetArg( args[argi], name,  value ); ++argi;
X
X    Arg		args[10];
X    int		argi;
X
X/*--Create our widgets if this is a first time. */
X
X    if (Complaint == (Widget)NULL) {
X	Complainer =
X	  XtCreatePopupShell( "complainer", transientShellWidgetClass,
X			      Dragon, (ArgList)NULL, (Cardinal)0 );
X	argi = 0;
X	SETARG( XtNcursor,		Dragon_Resources.Cursor );
X	Complaint =
X	  XtCreateManagedWidget( "complaint", dialogWidgetClass,
X				 Complainer, args, (Cardinal)argi );
X	XtDialogAddButton( Complaint, "OK", Complain_OK, (caddr_t)NULL );
X    }
X
X/*--Set the label on the complaint. */
X
X    argi = 0;
X    SETARG(	XtNlabel,	about	);
X    XtSetValues( Complaint, args, (Cardinal)argi );
X
X/*--Realize and pop up the dialog box. */
X
X    {	int		xret, yret;
X	Window		child;
X	(void)XTranslateCoordinates( XtDisplay(Dragon), XtWindow(Dragon),
X				     RootWindowOfScreen(XtScreen(Dragon)),
X				     0, 0, &xret, &yret, &child );
X	XtMoveWidget( Complainer, xret, yret );
X    }
X    XtPopup( Complainer, XtGrabNone );
X    XFlush( XtDisplay(Board) );
X
X} /* Complain */
X
X
Xint	Cheating = FALSE;
X
X/*ARGSUSED*/
Xstatic void Cheat( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X{
X
X    DEBUG_CALL(Cheat);
X    Cheating = !Cheating;
X    DEBUG_RETURN(Cheat);
X
X} /* Cheat */
X
X
X/*ARGSUSED*/
Xstatic void Game_Exit( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X/******************************************************************************
X* Called when we want to exit.
X******************************************************************************/
X{
X    XEvent	event2;
X
X    DEBUG_CALL(Game_Exit);
X    for (;;) {
X	XNextEvent( XtDisplay(Board), &event2 );
X	if (event2.xany.type == ButtonRelease) { break; }
X    }
X    exit(0);
X
X} /* Game_Exit */
X
X
X/*ARGSUSED*/
Xstatic void New_Game( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X{
X
X    DEBUG_CALL(New_Game);
X    Setup_New_Game();
X    XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE );
X    DEBUG_RETURN(New_Game);
X
X} /* New_Game */
X
X
X/*ARGSUSED*/
Xstatic void Other( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X/******************************************************************************
X* Called to change button menus.
X******************************************************************************/
X{
X
X    DEBUG_CALL(Other);
X    if (All_Buttons == &Buttons1[0]) {
X	All_Buttons = &Buttons2[0];
X    } else {
X	All_Buttons = &Buttons1[0];
X    }
X    All_Buttons[3].hilite = !All_Buttons[3].hilite;
X    XClearArea( XtDisplay(Board), XtWindow(w),
X	        0, 0, 0, (unsigned)(2*Tile_Height-Side_Y-Shadow_Y-1), FALSE );
X    Button_Expose( w, event, params, num_params );
X    DEBUG_RETURN(Other);
X
X} /* Other */
X
X
X/*ARGSUSED*/
Xstatic void Redraw_All( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X{
X
X    DEBUG_CALL(Redraw_All);
X    XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE );
X    DEBUG_RETURN(Redraw_All);
X
X} /* Redraw_All */
X
X
X/*ARGSUSED*/
Xstatic void Restore_Game( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X/******************************************************************************
X* Called to restore a previous game.
X******************************************************************************/
X{
X    extern char *getenv();
X    char	 name[1024];
X    FILE	*file;
X
X    DEBUG_CALL(Restore_Game);
X    strcpy( &name[0], getenv( "HOME" ) );
X    strcat( &name[0], "/.dragon-save" );
X    file = fopen( &name[0], "r" );
X    if (file == (FILE*)NULL) {
X	Complain( "Cannot open the $HOME/.dragon-save file." );
X    } else {
X	Read_Game( file );
X	(void)fclose( file );
X	Redraw_All( w, event, params, num_params );
X    }
X    DEBUG_RETURN(Restore_Game);
X
X} /* Restore_Game */
X
X
X/*ARGSUSED*/
Xstatic void Save_Game( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X/******************************************************************************
X* Called to save the current game.
X******************************************************************************/
X{
X    extern char *getenv();
X    char	 name[1024];
X    FILE	*file;
X
X    DEBUG_CALL(Save_Game);
X    strcpy( &name[0], getenv( "HOME" ) );
X    strcat( &name[0], "/.dragon-save" );
X    file = fopen( &name[0], "w" );
X    if (file == (FILE*)NULL) {
X	Complain( "Cannot open the $HOME/.dragon-save file." );
X    } else {
X	Write_Game( file );
X	(void)fclose( file );
X    }
X    DEBUG_RETURN(Save_Game);
X
X} /* Save_Game */
X
X
X/*ARGSUSED*/
Xstatic void Sides( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X{
X
X    DEBUG_CALL(Cheat);
X    if (Tile_Control & SHADOW) {
X	if (Tile_Control & BLACKSIDE) {
X	    if (Tile_Control & GRAYSIDE) {
X		Tile_Control &= ~(SHADOW | BLACKSIDE | GRAYSIDE);
X	    } else {
X		Tile_Control &= ~SHADOW;
X		Tile_Control |= GRAYSIDE;
X	    }
X	} else {
X	    Tile_Control &= ~SHADOW;
X	    Tile_Control |= BLACKSIDE;
X	}
X    } else {
X	Tile_Control |= SHADOW;
X    }
X    XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE );
X    DEBUG_RETURN(Cheat);
X
X} /* Sides */
X
X
X/*ARGSUSED*/
Xstatic void Sync_All( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X{
X    static int	onoff = FALSE;
X
X    DEBUG_CALL(Sync_All);
X    onoff = !onoff;
X    Dragon_Resources.Debug = onoff;
X    XSynchronize( XtDisplay(Board), onoff );
X    DEBUG_RETURN(Sync_All);
X
X} /* Sync_All */
X
X
Xvoid Do_Button_Configuration()
X/******************************************************************************
X* Called when the Board changes Tile sizes.
X******************************************************************************/
X{
X#define BUTTONS_PER_LINE 4
X#undef PNT
X#define PNT(X,Y)	pnt->x = X; pnt->y = Y; ++pnt;
X    int		 indent;
X    int		 x, dx;
X    int		 y, dy;
X    int		 i, j;
X    int		 f, s, t, l;
X    XPoint	*pnt;
X    register Button	but;
X
X/*--Buttons will be three tiles wide and 2/3'rd of a tile high. */
X
X    DEBUG_CALL(Do_Button_Configuration);
X    Button_Width = 3 * Tile_Width;
X    dx = Button_Width + Tile_Width / 2;
X    Button_Height = 5 * Tile_Height / 9;
X    dy = Tile_Height * 8 / 10;
X
X/*--Letters are as large as can fit within the buttons. */
X
X    indent = Button_Height / 5;
X    Letter_Indent = indent + 2;
X    s = Letter_Indent * 3 / 4;
X    t = s / 2;
X    f = indent - s + t;
X    Letter_Height = Button_Height - (2 * indent) - 2;
X    if ((Letter_Height & 1) == 0) { --Letter_Height; }
X    Letter_Width  = (Button_Width - (2 * indent) - 2) / 8 - 2;
X    if ((Letter_Width & 1) == 0) { --Letter_Width; }
X    
X/*--Now place the buttons. */
X
X    for (j = 1; j >= 0; --j) {
X	if (j == 1) {
X	    but = &Buttons1[0];
X	} else {
X	    but = &Buttons2[0];
X	}
X	x = indent + 12;
X	y = indent + 4;
X	for (i = 0; i < NBUTTONS; ++i) {
X	    if (but[i].text == NULL) { goto Next_Button; }
X	    l = strlen(but[i].text);
X	    if (l > 8) {
X		fprintf( stderr, "Button name too long: %s\n",
X			 but[i].text );
X		l = 8;
X	    }
X	    but[i].x = x;
X	    but[i].y = y;
X	    but[i].text_x = (Button_Width - l * (Letter_Width+2) + 2) / 2;
X	    but[i].text_y = indent + 1;
X
X	    pnt = &but[i].border[0];
X	    PNT( x,				y + indent		);
X	    PNT( f,				0			);
X	    PNT( 0,				-s			);
X	    PNT( -t,				0			);
X	    PNT( 0,				t			);
X	    PNT( s,				0			);
X	    PNT( 0,				-f			);
X	    PNT( Button_Width - 2 * indent,	0			);
X	    PNT( 0,				f			);
X	    PNT( s,				0			);
X	    PNT( 0,				-t			);
X	    PNT( -t,				0			);
X	    PNT( 0,				s			);
X	    PNT( f,				0			);
X	    PNT( 0,				Button_Height - 2*indent);
X	    PNT( -f,				0			);
X	    PNT( 0,				s			);
X	    PNT( t,				0			);
X	    PNT( 0,				-t			);
X	    PNT( -s,				0			);
X	    PNT( 0,				f			);
X	    PNT( -(Button_Width - 2*indent),	0			);
X	    PNT( 0,				-f			);
X	    PNT( -s,				0			);
X	    PNT( 0,				t			);
X	    PNT( t,				0			);
X	    PNT( 0,				-s			);
X	    PNT( -f,				0			);
X	    PNT( 0,				-Button_Height+2*indent	);
X
X	  Next_Button :
X	    if (i % BUTTONS_PER_LINE + 1 == BUTTONS_PER_LINE) {
X		x = indent + 12;
X		y += dy;
X	    } else {
X		x += dx;
X	    }
X	}
X    }
X    DEBUG_RETURN(Do_Button_Configuration);
X
X} /* Do_Button_Configuration */
X
X
Xvoid Draw_Text( str, x, y )
X     char	*str;
X     int	 x;
X     int	 y;
X/******************************************************************************
X* Called to draw the vector text in some button.
X******************************************************************************/
X{
X    static char pntserr[] = "DT pnts overflow!\n";
X    XPoint	pnts[50];
X    int		pnti;
X    int		h1;
X    int		w1;
X
X#undef PNT
X#define PNT(X,Y) \
X    if (pnti >= XtNumber(pnts)){fprintf(stderr,pntserr);} \
X    pnts[pnti].x = X; pnts[pnti].y = Y; ++pnti
X    ;
X
X/*--Position ourselves for the first letter. */
X
X    DEBUG_CALL(Draw_Text);
X    h1 = Letter_Height - 1;
X    w1 = Letter_Width - 1;
X
X/*--Loop over all letters in the text. */
X
X    for ( ; *str != '\000'; x+=Letter_Width+2,++str) {
X	pnti = 0;
X	switch (*str) {
X
X/*--The letters we have. */
X
X	  case '0' :
X	    {	int	w6, h6, h26;
X
X		h6 = h1 / 6;
X		h26 = h1 - 4 * h6;
X		w6 = w1 / 6;
X
X		PNT( x,		y+h6+h6	);
X		PNT( 0,		h26	);
X		PNT( w6,	h6	);
X		PNT( w6,	h6	);
X		PNT( 2*w6,	0	);
X		PNT( w6,	-h6	);
X		PNT( w6,	-h6	);
X		PNT( 0,		-h26	);
X		PNT( -w6,	-h6	);
X		PNT( -w6,	-h6	);
X		PNT( -2*w6,	0	);
X		PNT( -w6,	h6	);
X		PNT( -w6,	h6	);
X		break;
X	    }
X
X	  case '1' :
X	    {
X		PNT( x+(w1+1)/2,y	);
X		PNT( 0,		h1	);
X		break;
X	    }
X
X	  case '2' :
X	    {	int	w6, w46, h6, h6r;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h6r = (h1 - h6 * 6) / 2;
X
X		PNT( x,		y + h6	);
X		PNT( w6,	-h6	);
X		PNT( w46,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h6+h6r	);
X		PNT( -w6,	h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h1-5*h6-h6r);
X		PNT( 0,		h6	);
X		PNT( w1,	0	);
X		break;
X	    }
X
X	  case '3' :
X	    {	int	w6, w46, h6, h6r;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h6r = (h1 - h6 * 6) / 2;
X
X		PNT( x,		y + h6	);
X		PNT( w6,	-h6	);
X		PNT( w46,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h6+h6r	);
X		PNT( -w6,	h6	);
X		PNT( -w46/2,	0	);
X		PNT( w46/2,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h1-5*h6-h6r);
X		PNT( -w6,	h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	-h6	);
X		break;
X	    }
X
X	  case '4' :
X	    {	int	w23, h23;
X
X		w23 = w1 * 2 / 3;
X		h23 = h1 * 2 / 3;
X
X		PNT( x + w1,	y + h23	);
X		PNT( -w1,	0	);
X		PNT( w23,	-h23	);
X		PNT( 0,		h1	);
X		break;
X	    }
X
X	  case '5' :
X	    {	int	w6, w46, h6, h6r;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h6r = (h1 - h6 * 6) / 2;
X
X		PNT( x + w1,	y	);
X		PNT( -w1,	0	);
X		PNT( 0,		h1-3*h6-h6r);
X		PNT( w1-w6,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h6+h6r	);
X		PNT( -w6,	h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	-h6	);
X		break;
X	    }
X
X	  case '6' :
X	    {	int	w6, w46, h6, h6r;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		if (((h6-w6) & 1) == 1) { --h6; }
X		h6r = (h1 - h6 * 6) / 2;
X
X		PNT( x + w1,	y+h6	);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h1-2*h6);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	-h6	);
X		PNT( 0,		-h6-h6r );
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		break;
X	    }
X
X	  case '7' :
X	    {
X		PNT( x,		y	);
X		PNT( w1,	0	);
X		PNT( -w1,	h1	);
X		break;
X	    }
X
X	  case '8' :
X	    {	int	w6, w46, h6, h6r;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		if (((h6-w6) & 1) == 1) { --h6; }
X		h6r = (h1 - h6 * 6) / 2;
X
X		PNT( x + w1,	y + h6	);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h6+h6r	);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h1-5*h6-h6r);
X		PNT( -w6,	h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	-h6	);
X		PNT( 0,		-h1+5*h6+h6r);
X		PNT( w6,	-h6	);
X		PNT( w46,	0	);
X		PNT( w6,	-h6	);
X		PNT( 0,		-h6-h6r	);
X		break;
X	    }
X
X          case '9' :
X	    {	int	w6, w46, h6, h6r;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h6r = (h1 - h6 * 6) / 2;
X
X		PNT( x,		y+h1-h6	);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	-h6	);
X		PNT( 0,		-h1+2*h6);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h6+h6r);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	-h6	);
X		break;
X	    }
X
X
X	  case 'a' : case 'A' :
X	    {	int	h2, w2, w5l, w5r;
X
X		h2 = h1 * 12 / 20;
X		w2 = (w1+1) / 2;
X		w5l = w1 / 5;
X		w5r = w1 - w5l;
X
X		PNT( x,		y + h1	);
X		PNT( w5l,	-(h1-h2));
X		PNT( w5r - w5l,	0	);
X		PNT( w2 - w5r,	-h2	);
X		PNT( w5l - w2,	h2	);
X		PNT( w5r - w5l,	0	);
X		PNT( w5l,	h1-h2	);
X		break;
X	    }
X
X	  case 'b' : case 'B' :
X	    {	int	w6, h6;
X		int	h2;
X
X		h2 = (h1+1) / 2;
X		w6 = w1 / 6;
X		h6 = h1 / 6;
X
X		PNT( x,		y + h1  );
X		PNT( 0,		-h1	);
X		PNT( w1-w6,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h2-h6-h6);
X		PNT( -w6,	h6	);
X		PNT( -(w1-w6),	0	);
X		PNT( w1-w6,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h1-h2-h6-h6);
X		PNT( -w6,	h6	);
X		PNT( -(w1-w6),	0	);
X		break;
X	    }
X
X	  case 'c' : case 'C' :
X	    {	int	w6, w46, h6, h46;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h46 = h1 - h6 - h6;
X
X		PNT( x + w1,	y + h6	);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h46	);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	-h6	);
X		break;
X	    }
X
X	  case 'd' : case 'D' :
X	    {	int	w6, w56, h6, h46;
X
X		w6 = w1 / 6;
X		w56 = w1 - w6;
X		h6 = h1 / 6;
X		h46 = h1 - h6 - h6;
X
X		PNT( x,		y	);
X		PNT( w56,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h46	);
X		PNT( -w6,	h6	);
X		PNT( -w56,	0	);
X		PNT( 0,		-h1	);
X		break;
X	    }
X
X	  case 'e' : case 'E' :
X	    {	int	h2, w2;
X
X		h2 = (h1+1) / 2;
X		w2 = (w1+1) / 2;
X
X		PNT( x + w1,	y );
X		PNT( -w1,	0 );
X		PNT( 0,		h2 );
X		PNT( w2,	0 );
X		PNT( -w2,	0 );
X		PNT( 0,		h1-h2 );
X		PNT( w1,	0 );
X		break;
X	    }
X
X	  case 'f' : case 'F' :
X	    {	int	h2, w2;
X
X		h2 = (h1+1) / 2;
X		w2 = (w1+1) / 2;
X
X		PNT( x + w1,	y );
X		PNT( -w1,	0 );
X		PNT( 0,		h2 );
X		PNT( w2,	0 );
X		PNT( -w2,	0 );
X		PNT( 0,		h1-h2 );
X		break;
X	    }
X
X	  case 'g' : case 'G' :
X	    {	int	w6, w46, h6, h46;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h46 = h1 - h6 - h6;
X
X		PNT( x + w1,	y + h6	);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h46	);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	-h6	);
X		PNT( 0,		h6-(h1+1)/2);
X		PNT( -(w1+1)/2,	0	);
X		break;
X	    }
X
X	  case 'h' : case 'H' :
X	    {	int	h2 = (h1+1) / 2;
X
X		PNT( x,		y	);
X		PNT( 0,		h1	);
X		PNT( 0,		-h2	);
X		PNT( w1,	0	);
X		PNT( 0,		h2	);
X		PNT( 0,		-h1	);
X		break;
X	    }
X
X	  case 'i' : case 'I' :
X	    {	int	w2 = (w1+1) / 2;
X
X		PNT( x,		y	);
X		PNT( w1,	0	);
X		PNT( -w2,	0	);
X		PNT( 0,		h1	);
X		PNT( -w2,	0	);
X		PNT( w1,	0	);
X		break;
X	    }
X
X	  case 'k' : case 'K' :
X	    { 	int	h2 = (h1+1) / 2;
X
X		PNT( x,		y	);
X		PNT( 0,		h1	);
X		PNT( 0,		-h2	);
X		PNT( w1,	-(h1-h2));
X		PNT( -w1,	h1-h2	);
X		PNT( w1,	h2	);
X		break;
X	    }
X
X	  case 'l' : case 'L' :
X	    {	PNT( x,		y );
X		PNT( 0,		h1 );
X		PNT( w1,	0 );
X		break;
X	    }
X
X	  case 'm' : case 'M' :
X	    {	int	w2 = (w1+1) / 2;
X
X		PNT( x,		y + h1	);
X		PNT( 0,		-h1	);
X		PNT( w2,	h1	);
X		PNT( w1 - w2,	-h1	);
X		PNT( 0,		h1	);
X		break;
X	    }
X
X	  case 'n' : case 'N' :
X	    PNT( x,	y + h1	);
X	    PNT( 0,	-h1	);
X	    PNT( w1,	h1	);
X	    PNT( 0,	-h1	);
X	    break;
X
X	  case 'o' : case 'O' :
X	    {	int	w6, w46, h6, h46;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h46 = h1 - h6 - h6;
X
X		PNT( x + w1,	y + h6	);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h46	);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	-h6	);
X		PNT( 0,		-h46	);
X		break;
X	    }
X
X	  case 'p' : case 'P' :
X	    {	int	w6, h6;
X		int	h2;
X
X		h2 = (h1+1) / 2;
X		w6 = w1 / 6;
X		h6 = h1 / 6;
X
X		PNT( x,		y + h1  );
X		PNT( 0,		-h1	);
X		PNT( w1-w6,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h2-h6-h6);
X		PNT( -w6,	h6	);
X		PNT( -(w1-w6),	0	);
X		break;
X	    }
X
X	  case 'q' : case 'Q' :
X	    {	int	w6, w46, h6, h46;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h46 = h1 - h6 - h6;
X
X		PNT( x + w1,	y + h6	);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h46	);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( -w6-w6,	-h6	);
X		PNT( w6+w6,	h6	);
X		PNT( w6,	h6	);
X		PNT( -w6,	-h6	);
X		PNT( w6,	-h6	);
X		PNT( 0,		-h46	);
X		break;
X	    }
X
X	  case 'r' : case 'R' :
X	    {	int	w6, h6;
X		int	h2;
X
X		h2 = (h1+1) / 2;
X		w6 = w1 / 6;
X		h6 = h1 / 6;
X
X		PNT( x,		y + h1  );
X		PNT( 0,		-h1	);
X		PNT( w1-w6,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h2-h6-h6);
X		PNT( -w6,	h6	);
X		PNT( -(w1-w6),	0	);
X		PNT( w1-w6,	0	);
X		PNT( w6,	h2	);
X		break;
X	    }
X
X	  case 's' : case 'S' :
X	    {	int	w6, w46, h6, h6r;
X
X		w6 = w1 / 6;
X		w46 = w1 - w6 - w6;
X		h6 = h1 / 6;
X		h6r = (h1 - h6 * 6) / 2;
X
X		PNT( x + w1,	y + h6	);
X		PNT( -w6,	-h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	h6	);
X		PNT( 0,		h6+h6r	);
X		PNT( w6,	h6	);
X		PNT( w46,	0	);
X		PNT( w6,	h6	);
X		PNT( 0,		h6+h6r	);
X		PNT( -w6,	h6	);
X		PNT( -w46,	0	);
X		PNT( -w6,	-h6	);
X		break;
X	    }
X
X	  case 't' : case 'T' :
X	    {	int	w2 = (w1+1) / 2;
X
X		PNT( x,		y	);
X		PNT( w1,	0	);
X		PNT( -w2,	0	);
X		PNT( 0,		h1	);
X		break;
X	    }
X
X	  case 'u' : case 'U' :
X	    {	int	w6, h6, h56;
X
X		w6 = w1 / 6;
X		h6 = h1 / 6;
X		h56 = h1 - h6;
X
X		PNT( x,		y	);
X		PNT( 0,		h56	);
X		PNT( w6,	h6	);
X		PNT( w1-w6-w6,	0	);
X		PNT( w6,	-h6	);
X		PNT( 0,		-h56	);
X		break;
X	    }
X
X	  case 'v' : case 'V' :
X	    {	int	w2;
X
X		w2 = (w1+1) / 2;
X
X		PNT( x,		y	);
X		PNT( w2,	h1	);
X		PNT( w1-w2,	-h1	);
X		break;
X	    }
X
X	  case 'w' : case 'W' :
X	    {	int	w4, w2;
X
X		w4 = w1 / 4;
X		w2 = (w1+1) / 2;
X
X		PNT( x,		y	);
X		PNT( w4,	h1	);
X		PNT( w2-w4,	-h1	);
X		PNT( w1-w2-w4,	h1	);
X		PNT( w4,	-h1	);
X		break;
X	    }
X
X	  case 'y' : case 'Y' :
X	    {	int	h2, w2;
X
X		h2 = (h1+1) / 2;
X		w2 = (w1+1) / 2;
X
X		PNT( x,		y	);
X		PNT( w2,	h2	);
X		PNT( w1-w2,	-h2	);
X		PNT( -(w1-w2),	h2	);
X		PNT( -w2,	h1-h2	);
X		break;
X	    }
X
X/*--Letters we don't have, and also blank. */
X
X	  default :
X	    ; /* do nothing */
X	}
X
X/*--Draw the letter. */
X
X	DEBUG_OTHER(Draw_Text,1 char);
X	if (pnti > 0) {
X	    XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		        pnts, (Cardinal)pnti, CoordModePrevious );
X	}
X    }
X    DEBUG_RETURN(Draw_Text);
X
X} /* Draw_Text */
X
X
Xvoid Draw_Score( score, x, y )
X     int	score;
X     int	x;
X     int	y;
X/******************************************************************************
X* Called to draw the score at x/y.
X******************************************************************************/
X{
X    char		scr[4];
X    unsigned int	w = (Letter_Width+2) * 3 + 4;
X    unsigned int	h = Letter_Height + 6;
X
X    if (score == 0) {
X	int	i, lx, ly;
X	Letter_Height *= 3;
X	Letter_Width *= 3;
X	lx = Board->core.width/6;
X	ly = Board->core.height/2 - 2 * Letter_Height;;
X	for (i = 5; i > 0; --i) {
X	    Draw_Text( "You Win", lx, ly );
X	    lx += 2*Letter_Width + 2;
X	    ly += Letter_Height + 5;
X	}
X	Letter_Height /= 3;
X	Letter_Width /= 3;
X    }
X
X    y -= h + 2;
X    XFillRectangle( XtDisplay(Board), XtWindow(Board), Reverse_GC,
X		    x, y, w, h );
X    XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		    x-2, y-2, w+4, h+4 );
X    XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		    x-1, y-1, w+2, h+2 );
X    XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		    x, y, w, h );
X    scr[0] = (score > 99 ? '0' + score / 100     : ' ');
X    scr[1] = (score >  9 ? '0' + score / 10 % 10 : ' ');
X    scr[2] = 		   '0' + score % 10;
X    scr[3] = '\000';
X    Draw_Text( scr, x+3, y+3 );
X
X} /* Draw_Score */
X
X
Xstatic void Hilite( button )
X     Button	button;
X/******************************************************************************
X* Xor the hilite pattern on the button indicated.
X******************************************************************************/
X{
X
X    XFillRectangle( XtDisplay(Board), XtWindow(Board), Xor_GC,
X		    button->x + 1,
X		    button->y + 1,
X		    (unsigned int)(Button_Width - 1),
X		    (unsigned int)(Button_Height - 1) );
X
X} /* Hilite */
X
X
X/*ARGSUSED*/
Xvoid Button_Expose( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X/******************************************************************************
X* Called when the Board receives an Expose event.
X******************************************************************************/
X{
X    int		i;
X
X/*--Loop over all buttons and display all "real" buttons. */
X
X    DEBUG_CALL(Button_Expose);
X    for (i = 0; i < NBUTTONS; ++i) {
X	if (All_Buttons[i].text == NULL) { continue; }
X
X/*--Clear the space for the button and then draw the outline. */
X
X	XFillRectangle( XtDisplay(Board), XtWindow(Board), Reverse_GC,
X		        All_Buttons[i].x,
X		        All_Buttons[i].y,
X		        (unsigned int)(Button_Width + 1),
X		        (unsigned int)(Button_Height + 1) );
X	XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		    All_Buttons[i].border,
X		    (Cardinal)XtNumber(All_Buttons[0].border),
X		    CoordModePrevious );
X
X/*--Draw the text of the button and then do hiliting if we need it. */
X
X	Draw_Text( All_Buttons[i].text,
X		   All_Buttons[i].x + All_Buttons[i].text_x,
X		   All_Buttons[i].y + All_Buttons[i].text_y );
X	if (All_Buttons[i].hilite) {
X	    Hilite( &All_Buttons[i] );
X	}
X    }
X    DEBUG_RETURN(Button_Expose);
X
X} /* Button_Expose */
X
X
Xstatic void De_Hilite_All()
X/******************************************************************************
X* Called to take the hilite off of any and all buttons everywhere.
X******************************************************************************/
X{
X    int		i;
X
X    for (i = 0; i < NBUTTONS; ++i) {
X	if (All_Buttons[i].text == NULL) { continue; }
X	if (All_Buttons[i].hilite && !All_Buttons[i].toggle) {
X	    All_Buttons[i].hilite = FALSE;
X	    Hilite( &All_Buttons[i] );
X	    XFlush( XtDisplay(Board) );
X	}
X    }
X
X} /* De_Hitlite_All */
X
X
X/*ARGSUSED*/
Xvoid Button_Press( w, event, params, num_params )
X     Widget		w;
X     XButtonEvent	*event;
X     String		*params;
X     Cardinal		*num_params;
X/******************************************************************************
X* Called when the Board receives a BtnDown event.
X******************************************************************************/
X{
X    int		i;
X
X/*--First we make sure that nobody is hilited. */
X
X    DEBUG_CALL(Button_Press);
X    De_Hilite_All();
X
X/*--See if some button just got clicked. */
X
X    for (i = 0; i < NBUTTONS; ++i) {
X	if (All_Buttons[i].text == NULL) { continue; }
X	if (event->x >= All_Buttons[i].x &&
X	    event->x <= All_Buttons[i].x + Button_Width &&
X	    event->y >= All_Buttons[i].y &&
X	    event->y <= All_Buttons[i].y + Button_Height) {
X
X/*--Hilite this button and then do whatever it is supposed to do. */
X
X	    All_Buttons[i].hilite = !All_Buttons[i].hilite;
X	    Hilite( &All_Buttons[i] );
X	    XFlush( XtDisplay(Board) );
X	    (*(All_Buttons[i].action))( w, event, params, num_params );
X	    break;
X	}
X    }
X    DEBUG_RETURN(Button_Press);
X
X} /* Button_Press */
X
X
X/*ARGSUSED*/
Xvoid Button_Release( w, event, params, num_params )
X     Widget		w;
X     XButtonEvent	*event;
X     String		*params;
X     Cardinal		*num_params;
X/******************************************************************************
X* Called when the Board receives a BtnUp event.
X******************************************************************************/
X{
X
X/*--Turn off any and all button hilites. */
X
X    DEBUG_CALL(Button_Release);
X    De_Hilite_All();
X    DEBUG_RETURN(Button_Release);
X
X} /* Button_Release */
END_OF_FILE
if test 26226 -ne `wc -c <'button.c'`; then
    echo shar: \"'button.c'\" unpacked with wrong size!
fi
# end of 'button.c'
fi
if test -f 'icon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'icon.c'\"
else
echo shar: Extracting \"'icon.c'\" \(8840 characters\)
sed "s/^X//" >'icon.c' <<'END_OF_FILE'
X/******************************************************************************
X* Dragon - a version of Mah-Jongg for X Windows
X*
X* Author: Gary E. Barnes	March 1989
X*
X* icon.c - Deals with our icon.  Setup and execution.
X******************************************************************************/
X
X#include "main.h"
X
X#include "ic/dragon_icon32.ic"
X#include "ic/dragon_icon64.ic"
X
Xextern char * malloc();
Xextern        free();
Xextern Pixmap XCreateTile();
X
X
XGC	Icon_GC = (GC)0;		/* GC used for Icon window. */
X
X
X/*ARGSUSED*/
Xstatic void Icon_Expose( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X/******************************************************************************
X* Called when our Icon window receives an Expose event.  This is only called
X* when we are using an Icon window.  If we managed to use an Icon pixmap then
X* this routine is not called at all.
X******************************************************************************/
X{
X    Display	*dpy = XtDisplay(w);
X    Window	 win = XtWindow(w);
X    XImage       ximage;
X    XGCValues	 gcv;
X    unsigned int wid  = 64;
X    unsigned int hei  = 64;
X    unsigned int bw = 0;
X    unsigned int depth;
X    int		 x, y;
X    Window	 root;
X    unsigned int size;
X
X/*--Figure out how big our window is. */
X
X    DEBUG_CALL(Icon_Expose);
X    XGetGeometry( dpy, win, &root, &x, &y,
X		  &wid, &hei, &bw, &depth );
X    if (wid < 64 || hei < 64) {
X	size = 32;
X    } else {
X	size = 64;
X    }
X
X/*--Get a GC and create an image of an appropriate size using one of our
X *  preexisting Icon images. */
X
X    if (Icon_GC == (GC)0) {
X	if (Dragon_Resources.Reverse_Video) {
X	    gcv.background = BlackPixelOfScreen(XtScreen(w));
X	    gcv.foreground = WhitePixelOfScreen(XtScreen(w));
X	} else {
X	    gcv.foreground = BlackPixelOfScreen(XtScreen(w));
X	    gcv.background = WhitePixelOfScreen(XtScreen(w));
X	}
X	Icon_GC = XtGetGC( w, GCForeground|GCBackground, &gcv );
X    }
X    ximage.height  = size;
X    ximage.width   = size;
X    ximage.depth   = 1;
X    ximage.xoffset = 0;
X    ximage.format  = XYBitmap;
X    ximage.data    =
X      (size == 64 ? &dragon_icon64_bits[0] :&dragon_icon32_bits[0]);
X    ximage.byte_order       = LSBFirst;
X    ximage.bitmap_unit      = 8;
X    ximage.bitmap_bit_order = LSBFirst;
X    ximage.bitmap_pad       = 8;
X    ximage.bytes_per_line   = (size+7)/8;
X
X/*--Draw the bitmap on the window. */
X
X    XClearWindow( dpy, win );
X    XPutImage( dpy, win, Icon_GC, &ximage, 0, 0,
X	       (int)(wid-size)/2, (int)(hei-size)/2,
X	       (unsigned int)size, (unsigned int)size );
X    DEBUG_RETURN(Icon_Expose);
X
X} /* Icon_Expose */
X
X
Xvoid Icon_Setup( args, argn, argi )
X     Arg	*args;
X     int	 argn;
X     int	*argi;
X/******************************************************************************
X*   args - Specifies the ArgList to fill in
X*   argn - Specifies the length of args
X*   argi - Specifies the ArgList allocation index
X*
X* Called to handle all of the Icon setup for our main shell.
X******************************************************************************/
X{
X    XIconSize	*ic;
X    int		 nic;
X    int		 i;
X    int		 size;
X    int		 accept;
X    Pixmap	 Icon_Pixmap = (Pixmap)NULL;
X    unsigned int W, H;
X    int  	 X, Y;
X    unsigned long flags;
X    int	  	 scr;
X
X#define SETARG(name,value) \
X    if (*argi >= argn) {fprintf(stderr,"IS args overrun!\n");} \
X    XtSetArg( args[*argi], name,  value ); ++*argi;
X
X/*--If we've been asked to set up the Icon geometry then do that. */
X
X    DEBUG_CALL(Icon_Setup);
X    for(scr = 0;			/* Figure out which screen we are on.*/
X	XtScreen(Dragon) != ScreenOfDisplay(XtDisplay(Dragon),scr);
X	scr++);
X
X    flags = XParseGeometry( Dragon_Resources.Icon_Geometry,
X			    &X, &Y, &W, &H );
X    if (flags & XValue) {
X	SETARG( XtNiconX, X );
X    }
X    if (flags & YValue) {
X	SETARG( XtNiconY, Y );
X    }
X
X/*--Set/Get the Icon_Name. */
X
X    if (Dragon_Resources.Icon_Name == NULL) {
X	SETARG( XtNiconName, "Dragon" );
X    }
X
X/*--Set up the Icon pixmap or window.  We try to use a pixmap instead of a
X *  window because it is simply less overhead. If there are supported Icon
X *  pixmap sizes then maybe we can use an icon pixmap. */
X
X    if (XGetIconSizes( XtDisplay(Dragon), 
X		       RootWindowOfScreen(XtScreen(Dragon)),
X		       &ic,
X		       &nic )) {
X
X/*--Run over all of the sizes.  We try to get a 64x64 pixmap but we are willing
X *  to settle for a 32x32.  We grab the first size that allows us to create
X *  a pixmap of exactly one of these sizes.  If we cannot find an exact match
X *  then "accept" is set to point to an acceptable size. */
X
X	size = 64;
X	accept = -1;
X	for (;;) {
X	    for (i = 0; i <= nic; ++i) {
X		if (ic[i].max_width < size ||
X		    ic[i].max_height < size) {
X		    continue;			/* Size completely wrong */
X		}
X		if (accept < 0 ||
X		    ic[i].max_width  < ic[accept].max_width ||
X		    ic[i].max_height < ic[accept].max_height) {
X		    accept = i;			/* Size is acceptable */
X		}
X		if (ic[i].min_width <= size &&
X		    size-ic[i].min_width % ic[i].width_inc == 0 &&
X		    ic[i].min_height <= size &&
X		    size-ic[i].min_height & ic[i].height_inc == 0) {
X		    Icon_Pixmap =		/* Size is perfect */
X		      XCreateTile( XtDisplay(Dragon),
X				   RootWindowOfScreen(XtScreen(Dragon)),
X				   (size == 64
X				    ? &dragon_icon64_bits[0]
X				    : &dragon_icon32_bits[0]), 
X				   size, size );
X		}
X	    }
X	    if (Icon_Pixmap != (Pixmap)NULL || 	/* Stop on success */
X		accept >= 0 ||			/* Stop on acceptable */
X		size == 32) { break; }		/* Stop when exhausted */
X	    size = 32;
X	}
X
X/*--If we don't have a pixmap yet and if accept is set then set up an "odd
X *  size" (from our viewpoint) pixmap. */
X
X	if (Icon_Pixmap == (Pixmap)NULL && accept >= 0) {
X	    char	*data;
X	    char	*orig;
X	    char	*ptr;
X	    int		 w, wb, h, hb;
X	    int		 inc;
X
X/*--Figure out which of our pixmaps we will copy into this odd pixmap. */
X
X	    if (ic[accept].max_width < 64 ||
X		ic[accept].max_height < 64) {
X		orig = &dragon_icon32_bits[0];
X		size = 32 / 8;
X	    } else {
X		orig = &dragon_icon64_bits[0];
X		size = 64 / 8;
X	    }
X
X/*--Calculate the exact size of the pixmap that we will be using; size is in
X *  bits (w,h) and also in bytes (wb,hb). */
X
X	    w = ic[accept].min_width;
X	    if (w < size) {
X		inc = ic[accept].width_inc;
X		w = w + (size - w + inc - 1) / inc * inc;
X	    }
X	    h = ic[accept].min_height;
X	    if (h < size) {
X		inc = ic[accept].height_inc;
X		h = h + (size - h + inc - 1) / inc * inc;
X	    }
X	    wb = (w + 7) / 8;
X	    hb = (h + 7) / 8;
X
X/*--Allocate space for the pixmap and copy our existing pixmap into it. */
X
X	    data = (char*)malloc( (unsigned)(wb * hb) );
X	    for (ptr = data, nic = size;
X		 nic >= 0;
X		 ptr += wb, orig += size,--nic) {
X		bcopy( orig, ptr, size );
X	    }
X
X/*--Create the pixmap and free up the data area. */
X
X	    Icon_Pixmap =
X	      XCreateTile( XtDisplay(Dragon),
X			   RootWindowOfScreen(XtScreen(Dragon)),
X			   data, w, h );
X	    free( data );
X	}
X	XFree( ic );
X    }
X
X/*--If we managed to create a pixmap then use that.  Otherwise we need a window
X *  for our icon. */
X
X    if (Icon_Pixmap != NULL) {
X	DEBUG_OTHER(Icon_Setup,Icon Pixmap);
X	SETARG( XtNiconPixmap, Icon_Pixmap );
X    } else {
X
X	/* No Pixmap found (or possibly none supported).  Try an Icon
X	 * window instead. */
X
X	static char	actions[] = "<Expose>: IconExpose()\n";
X	XtActionsRec	SomeActions[1];
X	Arg		SomeArgs[5];
X	int		SomeArgsi;
X	Widget		Icon_Shell;
X	Widget		Icon_Core;
X
X#define LCLARG(name,value) \
X	if (SomeArgsi >= XtNumber(SomeArgs)) \
X	  {fprintf(stderr,"IS SomeArgs overrun!\n");} \
X	XtSetArg( SomeArgs[SomeArgsi], name,  value ); ++SomeArgsi;
X        ;
X
X/*--Create a shell to contain the Icon window. */
X
X	DEBUG_OTHER(Icon_Setup,Icon Window);
X	SomeArgsi = 0;
X	LCLARG( XtNgeometry,		Dragon_Resources.Icon_Geometry);
X	LCLARG( XtNmappedWhenManaged,	FALSE );
X
X	Icon_Shell = XtCreateApplicationShell( "dragonicon", 
X					       topLevelShellWidgetClass,
X					       SomeArgs, (Cardinal)SomeArgsi );
X
X/*--We want the Icon window to be 64x64 if possible; and, when the Icon window
X *  gets Expose events we want to call the IconExpose routine to redraw the
X *  window. */
X
X	SomeActions[0].string = "IconExpose";
X	SomeActions[0].proc   = (XtActionProc)Icon_Expose;
X	XtAddActions( SomeActions, (Cardinal)1 );
X	    
X	SomeArgsi = 0;
X	LCLARG( XtNtranslations,	XtParseTranslationTable( actions ) );
X
X	Icon_Core = XtCreateManagedWidget( "drawable", widgetClass,
X					   Icon_Shell,
X					   SomeArgs, (Cardinal)SomeArgsi );
X	if (flags & WidthValue) {
X	    Icon_Core->core.width = W;
X	}
X	if (flags & HeightValue) {
X	    Icon_Core->core.height = H;
X	}
X
X/*--Realize and use the Icon window. */
X
X	XtRealizeWidget( Icon_Shell );
X	SETARG( XtNiconWindow, XtWindow(Icon_Shell) );
X    }
X    DEBUG_RETURN(Icon_Setup);
X
X} /* Icon_Setup */
END_OF_FILE
if test 8840 -ne `wc -c <'icon.c'`; then
    echo shar: \"'icon.c'\" unpacked with wrong size!
fi
# end of 'icon.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(13495 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/******************************************************************************
X* Dragon - a version of Mah-Jongg for X Windows
X*
X* Author: Gary E. Barnes	March 1989
X*
X* main.c - The mainline code.
X******************************************************************************/
X
X#define _MAIN_C_
X
X#include "main.h"
X#include <X11/ShellP.h>
X#include "ic/background.ic"
X#include "ic/gray.ic"
X#include "ic/shadow.ic"
X
Xextern void Icon_Setup();
Xextern void Board_Setup();
X
X
X/******************************************************************************
X* Dragon Resources
X******************************************************************************/
X
Xstatic int		def_DCTime	= 250;	/* ms for double click */
Xstatic Boolean		def_FALSE	= FALSE;
Xstatic Boolean		def_TRUE	= TRUE;
X
X#define offset(field)	XtOffset( Dragon_Resources_Ptr, field )
X#define BOOLEAN(name,class,field,default) \
X    {name, class, XtRBoolean, sizeof(Boolean), offset(field), XtRBoolean, \
X     (caddr_t)default}
X#define CURSOR(name,class,field,default) \
X    {name, class, XtRCursor, sizeof(Cursor), offset(field), \
X     XtRString, (caddr_t)default}
X#define FONT(name,class,field,default) \
X    {name, class, XtRFontStruct, sizeof(XFontStruct*), offset(field), \
X     XtRString, (caddr_t)default}
X#define INT(name,class,field,default) \
X    {name, class, XtRInt, sizeof(int), offset(field), XtRInt, (caddr_t)default}
X#define STRING(name,class,field,default) \
X    {name, class, XtRString, sizeof(String), offset(field), XtRString, \
X     (caddr_t)default}
X
Xstatic XtResource dragon_resources[] = {
X  CURSOR ( "cursor",        XtCCursor,       Cursor,	         "hand2"     ),
X  BOOLEAN( "debug",	    "Debug",	     Debug,		 &def_FALSE  ),
X  INT    ( "doubleClick",   "DoubleClick",   Double_Click_Time,  &def_DCTime ),
X  STRING ( XtNgeometry,     XtCGeometry,     Geometry,		 "444x339"   ),
X  STRING ( "iconGeometry",  "IconGeometry",  Icon_Geometry,      "64x64"     ),
X  BOOLEAN( "iconic",        "Iconic",        Iconic,             &def_FALSE  ),
X  STRING ( XtNiconName,	    XtCIconName,     Icon_Name,		 NULL 	     ),
X  BOOLEAN( XtNreverseVideo, XtCReverseVideo, Reverse_Video,      &def_FALSE  ),
X  BOOLEAN( "tileShadows",   "TileShadows",   Tile_Shadows,	 &def_TRUE  ),
X  STRING ( "tileSides",	    "TileSides",     Tile_Sides,	 "gray"	     ),
X};
X
X#undef offset
X#undef BOOLEAN
X#undef FONT
X#undef INT
X#undef STRING
X
X
X/******************************************************************************
X* Dragon Command Line Options
X******************************************************************************/
X
Xstatic XrmOptionDescRec command_line_options[] = {
X{"-cursor",      ".cursor",          XrmoptionSepArg,  (caddr_t)NULL  },
X{"-debug",	 ".debug",	     XrmoptionNoArg,   (caddr_t)"on"  },
X{"-double",      ".doubleClick",     XrmoptionSepArg,  (caddr_t)NULL  },
X{"-geometry",    ".geometry", 	     XrmoptionSepArg,  (caddr_t)NULL  },
X{"-icongeometry",".iconGeometry",    XrmoptionSepArg,  (caddr_t)NULL  },
X{"-iconic",      ".iconic",	     XrmoptionNoArg,   (caddr_t)"on"  },
X{"+iconic",      ".iconic",	     XrmoptionNoArg,   (caddr_t)"off" },
X{"-iconname",	 ".iconName",	     XrmoptionSepArg,  (caddr_t)NULL  },
X{"-reverse",     "*reverseVideo",    XrmoptionNoArg,   (caddr_t)"on"  },
X{"+reverse",     "*reverseVideo",    XrmoptionNoArg,   (caddr_t)"off" },
X{"-shadows",	 ".tileShadows",     XrmoptionNoArg,   (caddr_t)"off"  },
X{"+shadows",	 ".tileShadows",     XrmoptionNoArg,   (caddr_t)"on" },
X{"-sides",	 ".tileSides",	     XrmoptionSepArg,  (caddr_t)"line"},
X};
X
Xtypedef struct {
X  String	name;
X  String	desc;
X} Option_Help;
X
Xstatic Option_Help command_line_help[] = {
X{"-help",      		 "print out this message"},
X{"-display displayname", "X server to contact"},
X{"-cursor name",	 "name of the cursor to use"},
X{"-double time",	 "double-click time limit in milliseconds"},
X{"-font name",		 "font to use for buttons and messages"},
X{"-geometry WxH+X+Y",	 "size (in pixels) and position of the board"},
X{"-icongeometry WxH+X+Y","size (in pixels) and position of the program icon"},
X{"-/+iconic",            "begin program as an icon"},
X{"-iconname name",	 "name to use with the program icon"},
X{"-/+reverse",		 "turn on/off reverse video"},
X{"-/+shadows",		 "turn on/off tile shadows"},
X{"-sides line/black/gray","set the style for tile sides"},
X{ NULL, NULL }
X};
X
X
Xstatic void Command_Line_Usage( Bad_Option )
X     String	Bad_Option;
X/******************************************************************************
X*   Bad_Option	- Specifies the unfathomable command line option we received
X*
X* Called when we find an unrecognized command line option.  We spit out a
X* Unix-sytle usage message and die.
X******************************************************************************/
X{
X    Option_Help	*opt;
X    int		 col;
X
X    (void)fprintf( stderr, "%s:  unrecognized command line option [%s]\n\n",
X		   Program_Name, Bad_Option );
X
X    (void)fprintf( stderr, "usage:  %s", Program_Name );
X    col = 8 + strlen(Program_Name);
X    for (opt = command_line_help; opt->name; opt++) {
X	int len = 3 + strlen(opt->name);	/* space[string] */
X	if (col + len > 79) {
X	    (void)fprintf (stderr, "\n   ");	/* 3 spaces */
X	    col = 3;
X	}
X	(void)fprintf (stderr, " [%s]", opt->name);
X	col += len;
X    }
X
X    (void)fprintf( stderr, "\n\nType %s -help for a more help.\n",
X		   Program_Name );
X    exit( 1 );
X
X} /* Command_Line_Usage */
X
X
Xstatic void Command_Line_Help()
X/******************************************************************************
X* Called when the -help switch is used.  Put out our extended help message.
X******************************************************************************/
X{
X    Option_Help	*opt;
X
X    (void)fprintf( stderr, "usage:\n        %s [options]\n\n",
X		   Program_Name);
X    (void)fprintf( stderr, "Where the options are:\n");
X    for (opt = command_line_help; opt->name; opt++) {
X	(void)fprintf( stderr, "    %-24s %s\n", opt->name, opt->desc );
X    }
X    (void)fprintf( stderr, "\n" );
X    exit( 0 );
X
X} /* Command_Line_Help */
X
X
XPixmap XCreateTile( display, d, data, width, height )
X     Display	    *display;
X     Drawable	     d;
X     char	    *data;
X     unsigned int    width, height;
X/******************************************************************************
X* Converted form of XCreatePixmapFromBitmapData.  Use our GC and don't bother
X* the Server for another one.
X******************************************************************************/
X{
X    XImage ximage;
X    Pixmap pix;
X
X    pix = XCreatePixmap( display, d, width, height, 1 );
X    if (pix == (Pixmap)0) return (Pixmap)0;
X
X    ximage.height = height;
X    ximage.width = width;
X    ximage.depth = 1;
X    ximage.xoffset = 0;
X    ximage.format = XYBitmap;
X    ximage.data = data;
X    ximage.byte_order = LSBFirst;
X    ximage.bitmap_unit = 8;
X    ximage.bitmap_bit_order = LSBFirst;
X    ximage.bitmap_pad = 8;
X    ximage.bytes_per_line = (width+7)/8;
X
X    XPutImage( display, pix, Normal_GC, &ximage, 0, 0, 0, 0, width, height );
X    return pix;
X} /* XCreateTile */
X
X
Xstatic void GC_Setup()
X/******************************************************************************
X* Set up the GC's that we will be using for drawing.
X******************************************************************************/
X{
X    XGCValues	gcv;
X    Pixel	pix;
X
X/*--Xor_GC - fg = black, bg = white, func = xor */
X
X    gcv.function = GXxor;
X    gcv.foreground = BlackPixelOfScreen(XtScreen(Dragon));
X    gcv.background = WhitePixelOfScreen(XtScreen(Dragon));
X    Xor_GC = XtGetGC( Dragon,
X		      GCFunction|GCForeground|GCBackground,
X		      &gcv );
X
X/*--Normal_GC - fg = black, bg = white, func = copy */
X
X    gcv.function = GXcopy;
X    if (Dragon_Resources.Reverse_Video) {
X	gcv.background = BlackPixelOfScreen(XtScreen(Dragon));
X	gcv.foreground = WhitePixelOfScreen(XtScreen(Dragon));
X    }
X    Normal_GC = XtGetGC( Dragon, GCFunction|GCForeground|GCBackground, &gcv );
X
X/*--Gray_GC - fg = black, bg = white, func = copy, tile = Gray */
X
X    gcv.tile = XCreateTile( XtDisplay(Board), XtWindow(Board),
X			    gray_bits, gray_width, gray_height );
X    if (gcv.tile == None) {
X	fprintf( stderr, "Can't allocate gray pixmap.\n" );
X	exit(1);
X    }
X    gcv.fill_style = FillTiled;
X    Gray_GC = XtGetGC( Dragon,
X		       GCFunction|GCForeground|GCBackground|GCTile|GCFillStyle,
X		       &gcv );
X
X/*--Over_GC - fg = black, bg = white, func = or */
X
X    if (Dragon_Resources.Reverse_Video) {
X	gcv.function = GXand;
X    } else {
X	gcv.function = GXor;
X    }
X    gcv.tile =
X      XCreateTile( XtDisplay(Board), XtWindow(Board),
X		   shadow_bits, shadow_width, shadow_height );
X    if (gcv.tile == None) {
X	fprintf( stderr, "Can't allocate shadow pixmap.\n" );
X	exit(1);
X    }
X    gcv.fill_style = FillTiled;
X    Over_GC = XtGetGC( Dragon,
X		       GCFunction|GCForeground|GCBackground|GCTile|GCFillStyle,
X		       &gcv );
X
X/*--Reverse_GC - fg = white, bg = black, func = copy */
X
X    gcv.function = GXcopy;
X    pix = gcv.background;
X    gcv.background = gcv.foreground;
X    gcv.foreground = pix;
X    Reverse_GC = XtGetGC( Dragon, GCFunction|GCForeground|GCBackground, &gcv );
X
X} /* GC_Setup */
X
X
Xint main (argc, argv)
X     int	 argc;
X     String	*argv;
X/******************************************************************************
X* Our Main-Line Code.
X******************************************************************************/
X{
X    Arg		 args[40];
X    int		 argi = 0;
X
X#undef SETARG
X#define SETARG(name,value) \
X    if (argi >= XtNumber(args)) {fprintf(stderr,"main, args overrun!\n");} \
X    XtSetArg( args[argi], name,  value ); ++argi;
X
X/*--Start up the toolkit.  This creates a shell widget.  Unfortunately the
X *  only way the toolkit allows you to specify default application resources
X *  is by having a /usr/lib/X11/app-defaults/Application resouce file.  I'm
X *  not interested in doing this.  If some site wants to create one in order
X *  to customize the program then that is fine.  However, I want my program
X *  to be "standalone"; ie. if you have the binary executable then you have
X *  all you *must-have*.  So, I will Destroy this widget shortly. */
X
X    Program_Name = argv[0];
X    Dragon =
X      XtInitialize ( "dragon", "Dragon",
X		     command_line_options, XtNumber(command_line_options),
X		     &argc, argv );
X
X/*--See if there is anything left on the command line. */
X
X    for (++argv, --argc; argc > 0; ++argv, --argc) {
X	if (strcmp( argv[0], "-help" ) == 0) { Command_Line_Help(); }
X	Command_Line_Usage( argv[0] );
X    }
X
X/*--Now get the application resources. */
X
X    DEBUG_OTHER(main,XtGetApplicationResources);
X    XtGetApplicationResources( Dragon, (caddr_t)&Dragon_Resources,
X			       dragon_resources, XtNumber(dragon_resources),
X			       (ArgList)NULL, (Cardinal)0 );
X			  
X/*--Set up our icon. */
X
X    DEBUG_OTHER(main,Icon_Setup);
X    Icon_Setup( args, (int)XtNumber(args), &argi );
X
X/*--Now set up our "real" application shell. */
X
X    DEBUG_OTHER(main,XtDestroyWidget);
X    XtDestroyWidget( Dragon );
X
X/*--Set up various other controls on our top level widget that we require. */
X
X    SETARG( XtNminWidth,	450 );
X    SETARG( XtNminHeight,	340 );
X    SETARG( XtNwidthInc,	210 );
X    SETARG( XtNheightInc,	160 );
X    SETARG( XtNminAspectX,	1333 );
X    SETARG( XtNminAspectY,	1000 );
X    SETARG( XtNmaxAspectX,	1333 );
X    SETARG( XtNmaxAspectY,	1000 );
X    SETARG( XtNgeometry,	Dragon_Resources.Geometry );
X    if (Dragon_Resources.Reverse_Video) {
X	SETARG( XtNbackground, BlackPixelOfScreen(XtScreen(Dragon)) );
X	SETARG( XtNforeground, WhitePixelOfScreen(XtScreen(Dragon)) );
X    } else {
X	SETARG( XtNforeground, BlackPixelOfScreen(XtScreen(Dragon)) );
X	SETARG( XtNbackground, WhitePixelOfScreen(XtScreen(Dragon)) );
X    }
X
X    SETARG( XtNallowShellResize, TRUE );
X    SETARG( XtNinput,		 TRUE );
X    if (argi > XtNumber(args)) {
X	(void)fprintf(stderr, "assert: args?\n");
X	exit(1);
X    }
X    DEBUG_OTHER(main,XtCreateApplicationShell);
X    Dragon = XtCreateApplicationShell( "dragon", 
X				       topLevelShellWidgetClass,
X				       args, (Cardinal)argi );
X    argi = 0;
X
X/*--Check the tile controls. */
X
X    Tile_Control = 0;
X    if (Dragon_Resources.Tile_Shadows) { Tile_Control |= SHADOW; }
X    if (strcmp( Dragon_Resources.Tile_Sides, "black" ) == 0) {
X	Tile_Control |= BLACKSIDE;
X    } else if (strcmp( Dragon_Resources.Tile_Sides, "gray" ) == 0) {
X	Tile_Control |= BLACKSIDE | GRAYSIDE;
X    } else if (strcmp( Dragon_Resources.Tile_Sides, "line" ) != 0) {
X	fprintf(stderr,"-side option not given line, gray, or black value.\n");
X    }
X
X/*--Create the board that we will be using; realize it too. */
X
X    DEBUG_OTHER(main,Board_Setup);
X    Board_Setup();
X
X/*--Set up our GC's. */
X
X    DEBUG_OTHER(main,GC_Setup);
X    GC_Setup();
X
X/*--Now make it all appear in front of the user. */
X
X    {	Pixmap	pix;
X	pix = XCreateTile( XtDisplay(Board), XtWindow(Board),
X			   background_bits, background_width,
X			   background_height);
X	if (pix == None) {
X	    fprintf( stderr, "Can't allocate background pixmap.\n" );
X	    exit(1);
X	}
X	XSetWindowBackgroundPixmap( XtDisplay(Board), XtWindow(Board), pix );
X    }
X
X/*--Now do the real thing. */
X
X    DEBUG_OTHER(main,XtMainLoop);
X    XtMainLoop();
X
X} /* main */
X
X#if 0
X*/* print out the name of a widget; NOTE: no \n printed so printout is not
X* * flushed until our caller does one. */
X*
X*void spit(w)
X*     Widget	w;
X*{
X*    if (w == NULL) return;
X*    spit( w->core.parent );
X*    fprintf( stderr, ".%s", w->core.name );
X*}
X#endif /* 0 */
END_OF_FILE
if test 13495 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'main.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.h'\"
else
echo shar: Extracting \"'main.h'\" \(3020 characters\)
sed "s/^X//" >'main.h' <<'END_OF_FILE'
X/******************************************************************************
X* Dragon - a version of Mah-Jongg for X Windows
X*
X* Author: Gary E. Barnes	March 1989
X*
X* main.h - #include'ed into all source files.
X******************************************************************************/
X
X#include <stdio.h>
X#include <X11/Xlib.h>
X
X#include <X11/Intrinsic.h>
X#include <X11/IntrinsicP.h>
X#include <X11/Shell.h>
X#include <X11/Simple.h>
X#include <X11/StringDefs.h>
X
X#define TRUE	1
X#define FALSE	0
X
X#ifdef _MAIN_C_
X#define VAR(A)		A
X#define VARI(A,B)	A = B
X#else
X#define VAR(A)		extern A
X#define VARI(A,B)	extern A
X#endif
X
X
X/******************************************************************************
X* Dragon Resources
X******************************************************************************/
X
Xtypedef struct _Dragon_Resources_Rec{
X    Cursor		Cursor;			/* Name of cursor to use */
X    Boolean		Debug;			/* Debug printouts */
X    int			Double_Click_Time;	/* Time (ms) between clicks */
X    String		Geometry;		/* Geometry for the board */
X    String		Icon_Geometry;		/* Geometry for our icon */
X    Boolean		Iconic;			/* Do we start as an icon? */
X    String		Icon_Name;		/* Name for the icon */
X    Boolean		Reverse_Video;		/* Do all in reverse? */
X    Boolean		Tile_Shadows;		/* Want shadows? */
X    String		Tile_Sides;		/* What side type? */
X} Dragon_Resources_Rec, *Dragon_Resources_Ptr;
X
X#define DEBUG_CALL(Name) \
X  if (Dragon_Resources.Debug) { \
X    fprintf( stderr, "Name call\n" ); fflush(stderr); \
X  }
X#define DEBUG_RETURN(Name) \
X  if (Dragon_Resources.Debug) { \
X    fprintf( stderr, "Name return\n" ); fflush(stderr); \
X  }
X#define DEBUG_OTHER(Name,Other) \
X  if (Dragon_Resources.Debug) { \
X    fprintf( stderr, "Name Other\n" ); fflush(stderr); \
X  }
X
X/******************************************************************************
X* Bitmap/Image Initialization Structure
X******************************************************************************/
X
Xtypedef struct _XImage_Init {
X    XImage	*image;
X    char	*bits;
X    int		 width;
X    int		 height;
X} XImage_Init;
X
X
X
X/******************************************************************************
X* Global State
X******************************************************************************/
X
Xtypedef enum { s_Normal, s_Sample } Display_State;
X
XVARI( Display_State	Board_State,		s_Normal );
X
XVAR( Dragon_Resources_Rec  Dragon_Resources );	/* Application resources */
X
XVAR( Widget		   Dragon );		/* The top level widget */
XVAR( Widget		   Board );		/* Our main drawable */
X
XVAR( String		   Program_Name );	/* Name of program in cmd */
X
XVAR( int		   Tile_Control );	/* Control bits */
X
X#define SHADOW		(1<<0)
X#define BLACKSIDE	(1<<1)
X#define GRAYSIDE	(1<<2)
X
XVAR( GC			   Gray_GC );		/* fg=blk, bg=wht, fcn=copy */
XVAR( GC			   Normal_GC );		/* fg=blk, bg=wht, fcn=copy */
XVAR( GC			   Over_GC );		/* fg=blk, bg=wht, fcn=or */
XVAR( GC			   Reverse_GC );	/* fg=wht, bg=blk, fcn=copy */
XVAR( GC			   Xor_GC );		/* fg=blk, bg=wht, fcn=xor */
END_OF_FILE
if test 3020 -ne `wc -c <'main.h'`; then
    echo shar: \"'main.h'\" unpacked with wrong size!
fi
# end of 'main.h'
fi
echo shar: End of archive 3 \(of 10\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 10 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0