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