|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 26766 (0x688e) Types: TextFile Names: »button.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/X/Dragon/button.c«
/****************************************************************************** * Dragon - a version of Mah-Jongg for X Windows * * Author: Gary E. Barnes March 1989 * * button.c - Deals with the command buttons on the board ****************************************************************************** * 4/24/89 GEB - When "Other" pressed, if "Samples" is on then turn it off * - before changing button menus. ******************************************************************************/ #include "main.h" #include <X11/Dialog.h> extern int Side_X; extern int Side_Y; extern int Shadow_X; extern int Shadow_Y; extern unsigned int Tile_Width; extern unsigned int Tile_Height; extern void Button_Expose(); static void Cheat(); static void Game_Exit(); extern void Hints(); static void New_Game(); static void Other(); extern void Read_Game(); static void Redraw_All(); extern void Restart_Game(); static void Restore_Game(); static void Save_Game(); extern void Show_Samples(); static void Sides(); static void Sync_All(); extern void Setup_New_Game(); extern void Write_Game(); typedef void (*ActionProc)(); typedef struct _Button_Rec { char *text; ActionProc action; Boolean toggle; Boolean hilite; int x; int y; int text_x; int text_y; XPoint border[6*4+4+1]; } Button_Rec, *Button; #define Button_NULL ((Button)0) #define NBUTTONS 8 Button_Rec Buttons1[NBUTTONS] = { { "New Game", New_Game, FALSE }, { "Restart", Restart_Game, FALSE }, { "Save", Save_Game, FALSE }, #define OTHER_BUTTON 3 { "Other", Other, TRUE }, { "Hint", Hints, FALSE }, { NULL }, { "Restore", Restore_Game, FALSE }, { "Quit", Game_Exit, FALSE }, }; Button_Rec Buttons2[NBUTTONS] = { { "Redraw", Redraw_All, FALSE }, { "Sides", Sides, FALSE }, #define SAMPLES_BUTTON 2 { "Samples", Show_Samples, TRUE }, { "Other", Other, TRUE }, { "Cheat", Cheat, TRUE }, { "Sync", Sync_All, TRUE }, { NULL }, { NULL }, }; static Button All_Buttons = &Buttons1[0]; static int Button_Width = 0; static int Button_Height = 0; static int Letter_Indent = 0; static int Letter_Height = 0; static int Letter_Width = 0; Widget Complaint = (Widget)NULL; Widget Complainer = (Widget)NULL; \f static void Complain_OK() /****************************************************************************** * Called when the "OK" button on our complaint is pressed. ******************************************************************************/ { XtPopdown( Complainer ); } /* Complain_OK */ \f void Complain( about ) String about; /****************************************************************************** * Pop up a dialog box and complain to the user. ******************************************************************************/ { #undef SETARG #define SETARG(name,value) \ DEBUG_ERROR(argi >= XtNumber(args),"BS args overrun!\n" ); \ XtSetArg( args[argi], name, (XtArgVal)value ); ++argi; Arg args[10]; int argi; /*--Create our widgets if this is a first time. */ if (Complaint == (Widget)NULL) { Complainer = XtCreatePopupShell( "complainer", transientShellWidgetClass, Dragon, (ArgList)NULL, (Cardinal)0 ); argi = 0; SETARG( XtNcursor, Dragon_Resources.Cursor ); Complaint = XtCreateManagedWidget( "complaint", dialogWidgetClass, Complainer, args, (Cardinal)argi ); XtDialogAddButton( Complaint, "OK", Complain_OK, (caddr_t)NULL ); } /*--Set the label on the complaint. */ argi = 0; SETARG( XtNlabel, about ); XtSetValues( Complaint, args, (Cardinal)argi ); /*--Realize and pop up the dialog box. */ { int xret, yret; Window child; (void)XTranslateCoordinates( XtDisplay(Dragon), XtWindow(Dragon), RootWindowOfScreen(XtScreen(Dragon)), 0, 0, &xret, &yret, &child ); XtMoveWidget( Complainer, xret, yret ); } XtPopup( Complainer, XtGrabNone ); XFlush( XtDisplay(Board) ); } /* Complain */ \f int Cheating = FALSE; /*ARGSUSED*/ static void Cheat( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; { DEBUG_CALL(Cheat); Cheating = !Cheating; DEBUG_RETURN(Cheat); } /* Cheat */ \f /*ARGSUSED*/ static void Game_Exit( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Called when we want to exit. ******************************************************************************/ { XEvent event2; DEBUG_CALL(Game_Exit); for (;;) { XNextEvent( XtDisplay(Board), &event2 ); if (event2.xany.type == ButtonRelease) { break; } } exit(0); } /* Game_Exit */ \f /*ARGSUSED*/ static void New_Game( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; { DEBUG_CALL(New_Game); Setup_New_Game(); XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE ); DEBUG_RETURN(New_Game); } /* New_Game */ \f /*ARGSUSED*/ static void Other( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Called to change button menus. ******************************************************************************/ { DEBUG_CALL(Other); if (All_Buttons == &Buttons1[0]) { All_Buttons = &Buttons2[0]; } else { /*--Turn off Samples mode if we are changing menus. */ if (Buttons2[SAMPLES_BUTTON].hilite) { (*(Buttons2[SAMPLES_BUTTON].action))(w, event, params, num_params); Buttons2[SAMPLES_BUTTON].hilite = FALSE; } All_Buttons = &Buttons1[0]; } All_Buttons[OTHER_BUTTON].hilite = !All_Buttons[OTHER_BUTTON].hilite; XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, (unsigned)(2*Tile_Height-Side_Y-Shadow_Y-1), FALSE ); Button_Expose( w, event, params, num_params ); DEBUG_RETURN(Other); } /* Other */ \f /*ARGSUSED*/ static void Redraw_All( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; { DEBUG_CALL(Redraw_All); XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE ); DEBUG_RETURN(Redraw_All); } /* Redraw_All */ \f /*ARGSUSED*/ static void Restore_Game( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Called to restore a previous game. ******************************************************************************/ { extern char *getenv(); char name[1024]; FILE *file; DEBUG_CALL(Restore_Game); (void)strcpy( &name[0], getenv( "HOME" ) ); (void)strcat( &name[0], "/.dragon-save" ); file = fopen( &name[0], "r" ); if (file == (FILE*)NULL) { Complain( "Cannot open the $HOME/.dragon-save file." ); } else { Read_Game( file ); (void)fclose( file ); Redraw_All( w, event, params, num_params ); } DEBUG_RETURN(Restore_Game); } /* Restore_Game */ \f /*ARGSUSED*/ static void Save_Game( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Called to save the current game. ******************************************************************************/ { extern char *getenv(); char name[1024]; FILE *file; DEBUG_CALL(Save_Game); (void)strcpy( &name[0], getenv( "HOME" ) ); (void)strcat( &name[0], "/.dragon-save" ); file = fopen( &name[0], "w" ); if (file == (FILE*)NULL) { Complain( "Cannot open the $HOME/.dragon-save file." ); } else { Write_Game( file ); (void)fclose( file ); } DEBUG_RETURN(Save_Game); } /* Save_Game */ \f /*ARGSUSED*/ static void Sides( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; { DEBUG_CALL(Cheat); if (Tile_Control & SHADOW) { if (Tile_Control & BLACKSIDE) { if (Tile_Control & GRAYSIDE) { Tile_Control &= ~(SHADOW | BLACKSIDE | GRAYSIDE); } else { Tile_Control &= ~SHADOW; Tile_Control |= GRAYSIDE; } } else { Tile_Control &= ~SHADOW; Tile_Control |= BLACKSIDE; } } else { Tile_Control |= SHADOW; } XClearArea( XtDisplay(Board), XtWindow(w), 0, 0, 0, 0, TRUE ); DEBUG_RETURN(Cheat); } /* Sides */ \f /*ARGSUSED*/ static void Sync_All( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; { static int onoff = FALSE; DEBUG_CALL(Sync_All); onoff = !onoff; Dragon_Resources.Debug = onoff; XSynchronize( XtDisplay(Board), onoff ); DEBUG_RETURN(Sync_All); } /* Sync_All */ \f void Do_Button_Configuration() /****************************************************************************** * Called when the Board changes Tile sizes. ******************************************************************************/ { #define BUTTONS_PER_LINE 4 #undef PNT #define PNT(X,Y) pnt->x = X; pnt->y = Y; ++pnt; int indent; int x, dx; int y, dy; int i, j; int f, s, t, l; XPoint *pnt; register Button but; /*--Buttons will be three tiles wide and 2/3'rd of a tile high. */ DEBUG_CALL(Do_Button_Configuration); Button_Width = 3 * Tile_Width; dx = Button_Width + Tile_Width / 2; Button_Height = 5 * Tile_Height / 9; dy = Tile_Height * 8 / 10; /*--Letters are as large as can fit within the buttons. */ indent = Button_Height / 5; Letter_Indent = indent + 2; s = Letter_Indent * 3 / 4; t = s / 2; f = indent - s + t; Letter_Height = Button_Height - (2 * indent) - 2; if ((Letter_Height & 1) == 0) { --Letter_Height; } Letter_Width = (Button_Width - (2 * indent) - 2) / 8 - 2; if ((Letter_Width & 1) == 0) { --Letter_Width; } /*--Now place the buttons. */ for (j = 1; j >= 0; --j) { if (j == 1) { but = &Buttons1[0]; } else { but = &Buttons2[0]; } x = indent + 12; y = indent + 4; for (i = 0; i < NBUTTONS; ++i) { if (but[i].text == NULL) { goto Next_Button; } l = strlen(but[i].text); if (l > 8) { (void)fprintf( stderr, "Button name too long: %s\n", but[i].text ); l = 8; } but[i].x = x; but[i].y = y; but[i].text_x = (Button_Width - l * (Letter_Width+2) + 2) / 2; but[i].text_y = indent + 1; pnt = &but[i].border[0]; PNT( x, y + indent ); PNT( f, 0 ); PNT( 0, -s ); PNT( -t, 0 ); PNT( 0, t ); PNT( s, 0 ); PNT( 0, -f ); PNT( Button_Width - 2 * indent, 0 ); PNT( 0, f ); PNT( s, 0 ); PNT( 0, -t ); PNT( -t, 0 ); PNT( 0, s ); PNT( f, 0 ); PNT( 0, Button_Height - 2*indent); PNT( -f, 0 ); PNT( 0, s ); PNT( t, 0 ); PNT( 0, -t ); PNT( -s, 0 ); PNT( 0, f ); PNT( -(Button_Width - 2*indent), 0 ); PNT( 0, -f ); PNT( -s, 0 ); PNT( 0, t ); PNT( t, 0 ); PNT( 0, -s ); PNT( -f, 0 ); PNT( 0, -Button_Height+2*indent ); Next_Button : if (i % BUTTONS_PER_LINE + 1 == BUTTONS_PER_LINE) { x = indent + 12; y += dy; } else { x += dx; } } } DEBUG_RETURN(Do_Button_Configuration); } /* Do_Button_Configuration */ \f void Draw_Text( str, x, y ) char *str; int x; int y; /****************************************************************************** * Called to draw the vector text in some button. ******************************************************************************/ { #ifdef WANTDEBUG static char *pntserr = "DT pnts overflow!\n"; #endif XPoint pnts[50]; int pnti; int h1; int w1; #undef PNT #define PNT(X,Y) \ DEBUG_ERROR( pnti >= XtNumber(pnts), pntserr ); \ pnts[pnti].x = X; pnts[pnti].y = Y; ++pnti ; /*--Position ourselves for the first letter. */ DEBUG_CALL(Draw_Text); h1 = Letter_Height - 1; w1 = Letter_Width - 1; /*--Loop over all letters in the text. */ for ( ; *str != '\000'; x+=Letter_Width+2,++str) { pnti = 0; switch (*str) { /*--The letters we have. */ case '0' : { int w6, h6, h26; h6 = h1 / 6; h26 = h1 - 4 * h6; w6 = w1 / 6; PNT( x, y+h6+h6 ); PNT( 0, h26 ); PNT( w6, h6 ); PNT( w6, h6 ); PNT( w1-4*w6, 0 ); PNT( w6, -h6 ); PNT( w6, -h6 ); PNT( 0, -h26 ); PNT( -w6, -h6 ); PNT( -w6, -h6 ); PNT( -(w1-4*w6),0 ); PNT( -w6, h6 ); PNT( -w6, h6 ); break; } case '1' : { PNT( x+(w1+1)/2,y ); PNT( 0, h1 ); break; } case '2' : { int w6, w46, h6, h6r; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h6r = (h1 - h6 * 6) / 2; PNT( x, y + h6 ); PNT( w6, -h6 ); PNT( w46, 0 ); PNT( w6, h6 ); PNT( 0, h6+h6r ); PNT( -w6, h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h1-5*h6-h6r); PNT( 0, h6 ); PNT( w1, 0 ); break; } case '3' : { int w6, w46, h6, h6r; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h6r = (h1 - h6 * 6) / 2; PNT( x, y + h6 ); PNT( w6, -h6 ); PNT( w46, 0 ); PNT( w6, h6 ); PNT( 0, h6+h6r ); PNT( -w6, h6 ); PNT( -w46/2, 0 ); PNT( w46/2, 0 ); PNT( w6, h6 ); PNT( 0, h1-5*h6-h6r); PNT( -w6, h6 ); PNT( -w46, 0 ); PNT( -w6, -h6 ); break; } case '4' : { int w23, h23; w23 = w1 * 2 / 3; h23 = h1 * 2 / 3; PNT( x + w1, y + h23 ); PNT( -w1, 0 ); PNT( w23, -h23 ); PNT( 0, h1 ); break; } case '5' : { int w6, w46, h6, h6r; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h6r = (h1 - h6 * 6) / 2; PNT( x + w1, y ); PNT( -w1, 0 ); PNT( 0, h1-3*h6-h6r); PNT( w1-w6, 0 ); PNT( w6, h6 ); PNT( 0, h6+h6r ); PNT( -w6, h6 ); PNT( -w46, 0 ); PNT( -w6, -h6 ); break; } case '6' : { int w6, w46, h6, h6r; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; if (((h6-w6) & 1) == 1) { --h6; } h6r = (h1 - h6 * 6) / 2; PNT( x + w1, y+h6 ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h1-2*h6); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, -h6 ); PNT( 0, -h6-h6r ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); break; } case '7' : { PNT( x, y ); PNT( w1, 0 ); PNT( -w1, h1 ); break; } case '8' : { int w6, w46, h6, h6r; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; if (((h6-w6) & 1) == 1) { --h6; } h6r = (h1 - h6 * 6) / 2; PNT( x + w1, y + h6 ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h6+h6r ); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, h6 ); PNT( 0, h1-5*h6-h6r); PNT( -w6, h6 ); PNT( -w46, 0 ); PNT( -w6, -h6 ); PNT( 0, -h1+5*h6+h6r); PNT( w6, -h6 ); PNT( w46, 0 ); PNT( w6, -h6 ); PNT( 0, -h6-h6r ); break; } case '9' : { int w6, w46, h6, h6r; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h6r = (h1 - h6 * 6) / 2; PNT( x, y+h1-h6 ); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, -h6 ); PNT( 0, -h1+2*h6); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h6+h6r); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, -h6 ); break; } case 'a' : case 'A' : { int h2, w2, w5l, w5r; h2 = h1 * 12 / 20; w2 = (w1+1) / 2; w5l = w1 / 5; w5r = w1 - w5l; PNT( x, y + h1 ); PNT( w5l, -(h1-h2)); PNT( w5r - w5l, 0 ); PNT( w2 - w5r, -h2 ); PNT( w5l - w2, h2 ); PNT( w5r - w5l, 0 ); PNT( w5l, h1-h2 ); break; } case 'b' : case 'B' : { int w6, h6; int h2; h2 = (h1+1) / 2; w6 = w1 / 6; h6 = h1 / 6; PNT( x, y + h1 ); PNT( 0, -h1 ); PNT( w1-w6, 0 ); PNT( w6, h6 ); PNT( 0, h2-h6-h6); PNT( -w6, h6 ); PNT( -(w1-w6), 0 ); PNT( w1-w6, 0 ); PNT( w6, h6 ); PNT( 0, h1-h2-h6-h6); PNT( -w6, h6 ); PNT( -(w1-w6), 0 ); break; } case 'c' : case 'C' : { int w6, w46, h6, h46; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h46 = h1 - h6 - h6; PNT( x + w1, y + h6 ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h46 ); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, -h6 ); break; } case 'd' : case 'D' : { int w6, w56, h6, h46; w6 = w1 / 6; w56 = w1 - w6; h6 = h1 / 6; h46 = h1 - h6 - h6; PNT( x, y ); PNT( w56, 0 ); PNT( w6, h6 ); PNT( 0, h46 ); PNT( -w6, h6 ); PNT( -w56, 0 ); PNT( 0, -h1 ); break; } case 'e' : case 'E' : { int h2, w2; h2 = (h1+1) / 2; w2 = (w1+1) / 2; PNT( x + w1, y ); PNT( -w1, 0 ); PNT( 0, h2 ); PNT( w2, 0 ); PNT( -w2, 0 ); PNT( 0, h1-h2 ); PNT( w1, 0 ); break; } case 'f' : case 'F' : { int h2, w2; h2 = (h1+1) / 2; w2 = (w1+1) / 2; PNT( x + w1, y ); PNT( -w1, 0 ); PNT( 0, h2 ); PNT( w2, 0 ); PNT( -w2, 0 ); PNT( 0, h1-h2 ); break; } case 'g' : case 'G' : { int w6, w46, h6, h46; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h46 = h1 - h6 - h6; PNT( x + w1, y + h6 ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h46 ); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, -h6 ); PNT( 0, h6-(h1+1)/2); PNT( -(w1+1)/2, 0 ); break; } case 'h' : case 'H' : { int h2 = (h1+1) / 2; PNT( x, y ); PNT( 0, h1 ); PNT( 0, -h2 ); PNT( w1, 0 ); PNT( 0, h2 ); PNT( 0, -h1 ); break; } case 'i' : case 'I' : { int w2 = (w1+1) / 2; PNT( x, y ); PNT( w1, 0 ); PNT( -w2, 0 ); PNT( 0, h1 ); PNT( -w2, 0 ); PNT( w1, 0 ); break; } case 'k' : case 'K' : { int h2 = (h1+1) / 2; PNT( x, y ); PNT( 0, h1 ); PNT( 0, -h2 ); PNT( w1, -(h1-h2)); PNT( -w1, h1-h2 ); PNT( w1, h2 ); break; } case 'l' : case 'L' : { PNT( x, y ); PNT( 0, h1 ); PNT( w1, 0 ); break; } case 'm' : case 'M' : { int w2 = (w1+1) / 2; PNT( x, y + h1 ); PNT( 0, -h1 ); PNT( w2, h1 ); PNT( w1 - w2, -h1 ); PNT( 0, h1 ); break; } case 'n' : case 'N' : PNT( x, y + h1 ); PNT( 0, -h1 ); PNT( w1, h1 ); PNT( 0, -h1 ); break; case 'o' : case 'O' : { int w6, w46, h6, h46; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h46 = h1 - h6 - h6; PNT( x + w1, y + h6 ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h46 ); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, -h6 ); PNT( 0, -h46 ); break; } case 'p' : case 'P' : { int w6, h6; int h2; h2 = (h1+1) / 2; w6 = w1 / 6; h6 = h1 / 6; PNT( x, y + h1 ); PNT( 0, -h1 ); PNT( w1-w6, 0 ); PNT( w6, h6 ); PNT( 0, h2-h6-h6); PNT( -w6, h6 ); PNT( -(w1-w6), 0 ); break; } case 'q' : case 'Q' : { int w6, w46, h6, h46; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h46 = h1 - h6 - h6; PNT( x + w1, y + h6 ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h46 ); PNT( w6, h6 ); PNT( w46, 0 ); PNT( -w6-w6, -h6 ); PNT( w6+w6, h6 ); PNT( w6, h6 ); PNT( -w6, -h6 ); PNT( w6, -h6 ); PNT( 0, -h46 ); break; } case 'r' : case 'R' : { int w6, h6; int h2; h2 = (h1+1) / 2; w6 = w1 / 6; h6 = h1 / 6; PNT( x, y + h1 ); PNT( 0, -h1 ); PNT( w1-w6, 0 ); PNT( w6, h6 ); PNT( 0, h2-h6-h6); PNT( -w6, h6 ); PNT( -(w1-w6), 0 ); PNT( w1-w6, 0 ); PNT( w6, h2 ); break; } case 's' : case 'S' : { int w6, w46, h6, h6r; w6 = w1 / 6; w46 = w1 - w6 - w6; h6 = h1 / 6; h6r = (h1 - h6 * 6) / 2; PNT( x + w1, y + h6 ); PNT( -w6, -h6 ); PNT( -w46, 0 ); PNT( -w6, h6 ); PNT( 0, h6+h6r ); PNT( w6, h6 ); PNT( w46, 0 ); PNT( w6, h6 ); PNT( 0, h6+h6r ); PNT( -w6, h6 ); PNT( -w46, 0 ); PNT( -w6, -h6 ); break; } case 't' : case 'T' : { int w2 = (w1+1) / 2; PNT( x, y ); PNT( w1, 0 ); PNT( -w2, 0 ); PNT( 0, h1 ); break; } case 'u' : case 'U' : { int w6, h6, h56; w6 = w1 / 6; h6 = h1 / 6; h56 = h1 - h6; PNT( x, y ); PNT( 0, h56 ); PNT( w6, h6 ); PNT( w1-w6-w6, 0 ); PNT( w6, -h6 ); PNT( 0, -h56 ); break; } case 'v' : case 'V' : { int w2; w2 = (w1+1) / 2; PNT( x, y ); PNT( w2, h1 ); PNT( w1-w2, -h1 ); break; } case 'w' : case 'W' : { int w4, w2; w4 = w1 / 4; w2 = (w1+1) / 2; PNT( x, y ); PNT( w4, h1 ); PNT( w2-w4, -h1 ); PNT( w1-w2-w4, h1 ); PNT( w4, -h1 ); break; } case 'y' : case 'Y' : { int h2, w2; h2 = (h1+1) / 2; w2 = (w1+1) / 2; PNT( x, y ); PNT( w2, h2 ); PNT( w1-w2, -h2 ); PNT( -(w1-w2), h2 ); PNT( -w2, h1-h2 ); break; } /*--Letters we don't have, and also blank. */ default : ; /* do nothing */ } /*--Draw the letter. */ DEBUG_OTHER(Draw_Text,1 char); if (pnti > 0) { XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC, pnts, (Cardinal)pnti, CoordModePrevious ); } } DEBUG_RETURN(Draw_Text); } /* Draw_Text */ \f void Draw_Score( score, x, y ) int score; int x; int y; /****************************************************************************** * Called to draw the score at x/y. ******************************************************************************/ { char scr[4]; unsigned int w = (Letter_Width+2) * 3 + 4; unsigned int h = Letter_Height + 6; if (score == 0) { int i, lx, ly; Letter_Height *= 3; Letter_Width *= 3; lx = Board->core.width/6; ly = Board->core.height/2 - 2 * Letter_Height;; for (i = 5; i > 0; --i) { Draw_Text( "You Win", lx, ly ); lx += 2*Letter_Width + 2; ly += Letter_Height + 5; } Letter_Height /= 3; Letter_Width /= 3; } y -= h + 2; XFillRectangle( XtDisplay(Board), XtWindow(Board), Reverse_GC, x, y, w, h ); XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC, x-2, y-2, w+4, h+4 ); XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC, x-1, y-1, w+2, h+2 ); XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC, x, y, w, h ); scr[0] = (score > 99 ? '0' + score / 100 : ' '); scr[1] = (score > 9 ? '0' + score / 10 % 10 : ' '); scr[2] = '0' + score % 10; scr[3] = '\000'; Draw_Text( scr, x+3, y+3 ); } /* Draw_Score */ \f static void Hilite( button ) Button button; /****************************************************************************** * Xor the hilite pattern on the button indicated. ******************************************************************************/ { XFillRectangle( XtDisplay(Board), XtWindow(Board), Xor_GC, button->x + 1, button->y + 1, (unsigned int)(Button_Width - 1), (unsigned int)(Button_Height - 1) ); } /* Hilite */ \f /*ARGSUSED*/ void Button_Expose( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Called when the Board receives an Expose event. ******************************************************************************/ { int i; /*--Loop over all buttons and display all "real" buttons. */ DEBUG_CALL(Button_Expose); for (i = 0; i < NBUTTONS; ++i) { if (All_Buttons[i].text == NULL) { continue; } /*--Clear the space for the button and then draw the outline. */ XFillRectangle( XtDisplay(Board), XtWindow(Board), Reverse_GC, All_Buttons[i].x, All_Buttons[i].y, (unsigned int)(Button_Width + 1), (unsigned int)(Button_Height + 1) ); XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC, All_Buttons[i].border, (Cardinal)XtNumber(All_Buttons[0].border), CoordModePrevious ); /*--Draw the text of the button and then do hiliting if we need it. */ Draw_Text( All_Buttons[i].text, All_Buttons[i].x + All_Buttons[i].text_x, All_Buttons[i].y + All_Buttons[i].text_y ); if (All_Buttons[i].hilite) { Hilite( &All_Buttons[i] ); } } DEBUG_RETURN(Button_Expose); } /* Button_Expose */ \f static void De_Hilite_All() /****************************************************************************** * Called to take the hilite off of any and all buttons everywhere. ******************************************************************************/ { int i; for (i = 0; i < NBUTTONS; ++i) { if (All_Buttons[i].text == NULL) { continue; } if (All_Buttons[i].hilite && !All_Buttons[i].toggle) { All_Buttons[i].hilite = FALSE; Hilite( &All_Buttons[i] ); XFlush( XtDisplay(Board) ); } } } /* De_Hitlite_All */ \f /*ARGSUSED*/ void Button_Press( w, event, params, num_params ) Widget w; XButtonEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Called when the Board receives a BtnDown event. ******************************************************************************/ { int i; /*--First we make sure that nobody is hilited. */ DEBUG_CALL(Button_Press); De_Hilite_All(); /*--See if some button just got clicked. */ for (i = 0; i < NBUTTONS; ++i) { if (All_Buttons[i].text == NULL) { continue; } if (event->x >= All_Buttons[i].x && event->x <= All_Buttons[i].x + Button_Width && event->y >= All_Buttons[i].y && event->y <= All_Buttons[i].y + Button_Height) { /*--Hilite this button and then do whatever it is supposed to do. */ All_Buttons[i].hilite = !All_Buttons[i].hilite; Hilite( &All_Buttons[i] ); XFlush( XtDisplay(Board) ); (*(All_Buttons[i].action))( w, event, params, num_params ); break; } } DEBUG_RETURN(Button_Press); } /* Button_Press */ \f /*ARGSUSED*/ void Button_Release( w, event, params, num_params ) Widget w; XButtonEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Called when the Board receives a BtnUp event. ******************************************************************************/ { /*--Turn off any and all button hilites. */ DEBUG_CALL(Button_Release); De_Hilite_All(); DEBUG_RETURN(Button_Release); } /* Button_Release */