v03i092: Dragon -- Game of Mah-Jongg, Part03/10
Dan Heller
argv at island.uu.net
Sun Apr 30 17:41:14 AEST 1989
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 at 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 at 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
More information about the Comp.sources.x
mailing list