#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include "CardImages.h"

struct NewWindow NewWindow;

#define INTUITION_REV 0
#define GRAPHICS_REV  0

extern struct Preferences  *GetPreferences ();
extern struct IntuiMessage *GetMsg         ();
extern struct Library      *OpenLibrary    ();
extern struct Message      *WaitPort       ();
extern struct Window       *OpenWindow     ();
extern struct ViewPort     *ViewPortAddress();

extern void     ClearMenuStrip    ();
extern void     CloseLibrary      ();
extern void     CloseWindow       ();
extern long    *DateStamp         ();
extern void     Delay             ();
extern void     DrawBorder        ();
extern void     EndRequest        ();
extern void     exit              ();
extern void     ModifyIDCMP       ();
extern void     OffMenu           ();
extern void     OnMenu            ();
extern int      printf            ();
extern ULONG    RangeRand();
extern void     RectFill          ();
extern void     ReplyMsg          ();
extern short    Request           ();
extern void     SetAPen           ();
extern void     SetMenuStrip      ();
extern void     SetRGB4           ();
extern void     SetWindowTitles   ();
extern short    VBeamPos          ();

struct GfxBase        *GfxBase         = NULL;
struct IntuitionBase  *IntuitionBase   = NULL;
struct IntuiMessage   *IntuiMessagePtr = NULL;
struct ViewPort       *ViewPortPtr     = NULL;
struct Window         *Window          = NULL;

int     Points =  0;
int Old_Points = -1;
int Cards_Remaining = 52;

int Round_Cnt = 1;

SHORT Border_Coordinates[10];

struct Border HighBorder = {
       -1, -1,               /* LeftEdge, TopEdge            */
        1,  0, JAM1,         /* FrontPen, BackPen, DrawMode  */
        5,                   /* Count                        */
        Border_Coordinates,  /* ptr to coordinate pairs      */
        NULL                 /* ptr to next Border structure */
        };

struct Border *HighLight = &HighBorder;

struct Border UnHighBorder = {
       -1, -1,               /* LeftEdge, TopEdge            */
        0,  0, JAM1,         /* FrontPen, BackPen, DrawMode  */
        5,                   /* Count                        */
        Border_Coordinates,  /* ptr to coordinate pairs      */
        NULL                 /* ptr to next Border structure */
        };

struct Border *UnHighLight = &UnHighBorder;

/* HEIGHT = (  TOP_MARGIN  ) + ( BOARD_HEIGHT * CARDHEIGHT ) +      */
/*          (  ( BOARD_HEIGHT * HORIZONTAL_GAP )                    */
/* WIDTH  = ( 2 * LEFT_MARGIN ) + ( BOARD_WIDTH  * CARDWIDTH  ) +   */
/*          (  (BOARD_WIDTH  - 1) * VERTICAL_GAP  )                 */
#define HEIGHT     92L
#define WIDTH     230L
#define LEFT_EDGE 200L
#define TOP_EDGE   13L


#define TOP_MARGIN   15
#define LEFT_MARGIN  10

#define BOARD_HEIGHT  2
#define BOARD_WIDTH   5

#define HORIZONTAL_GAP  5
#define VERTICAL_GAP    5

#define IN_DECK     -20
#define NOT_IN_DECK -30

#define EMPTY -10

#define NO_CARDS_LEFT -40

#define KING 13

#define NO  0
#define YES 1

#define ON_BACKGROUND 0
#define ON_CARD       1

/* menu pick item numbers */
#define ABOUT 0
#define HELP  1
#define GAME  2
#define ROUND 3

#define ROUND_MENU_NO 0
#define NORMAL_IDCMP_FLAGS CLOSEWINDOW | MOUSEBUTTONS   | MENUPICK |\
                           RAWKEY      | INACTIVEWINDOW
#include "req.h"
#include "menu.h"

struct Requester *About_Requester = &RequesterStructure2;
struct Requester *Help_Requester  = &RequesterStructure1;

struct Space_Info
       {
       int X,Y; /* orgin, upper left corner */
       int Current_Card;
       int Valid_Move;
       int High_Light_On;
       };

struct Space_Info Board[ BOARD_HEIGHT ][ BOARD_WIDTH ];

int Deck[CARDS];

long Reg_2_Blue_Bits;
long Reg_2_Green_Bits;
long Reg_2_Red_Bits;
long Reg_3_Blue_Bits;
long Reg_3_Green_Bits;
long Reg_3_Red_Bits;
int  Pulse_Direction = 0;
long Pulse_Flag = FALSE;

void Close_Stuff ()
     {
     if ( Window              )
          {
          ClearMenuStrip( Window        );
          CloseWindow   ( Window        );
          }
     if ( IntuitionBase       )    CloseLibrary  ( IntuitionBase );
     if ( GfxBase             )    CloseLibrary  ( GfxBase       );
     }                                               /* end of Close_Stuff */

void Die ()
     {
     Close_Stuff ();
     exit ( -1 );
     }                                                       /* end of Die */

void Remove_Card_From_Deck( Rcard )
     int Rcard;
     {
     if (    (    0 <= Rcard   &&   Rcard < CARDS   )                   &&
              Rcard != JOKER   &&   Rcard != BLANK   &&  Rcard != BLACK     )
              Deck[ Rcard ] = NOT_IN_DECK;
        else  {
              /* Rcard is not a valid card.  Die gracefully */
              printf("Out of range card value received in Remove_Card_From_Deck \n");
              Die();        }
     }

void Put_Card_In_Deck( Pcard )
     int Pcard;
     {
     if (   (     0 <= Pcard   &&   Pcard < CARDS  )                    &&
              Pcard != JOKER   &&   Pcard != BLANK   &&  Pcard != BLACK     )
              Deck[ Pcard ] = IN_DECK;
        else  {
              printf("Out of range card value received in Put_Card_In_Deck \n");
              Die();        }
     }


void Init_Deck()
     {
     int i;

     for( i = 0   ;   i < CARDS   ;   i++ )
          Deck[ i ] = IN_DECK;

     Deck[ JOKER ] = NOT_IN_DECK;  /* not going to use these cards */
     Deck[ BLANK ] = NOT_IN_DECK;
     Deck[ BACK  ] = NOT_IN_DECK;
     Deck[ BLACK ] = NOT_IN_DECK;
     }                                                 /* end of Init_Deck */

void Init_Board()
    {
    int h,w;
     for(    h = 0  ;  h < BOARD_HEIGHT  ;  h++ )
        for( w = 0  ;  w < BOARD_WIDTH   ;  w++ ) {
           Board[h][w].X = LEFT_MARGIN +
                           (   w   *   ( CARDWIDTH   + HORIZONTAL_GAP )   );
           Board[h][w].Y = TOP_MARGIN  +
                           (   h   *   ( CARDHEIGHT  +  VERTICAL_GAP  )   );
           Board[h][w].Current_Card =  EMPTY;
           Board[h][w].Valid_Move    = NO;
           Board[h][w].High_Light_On = NO;
           }
    }                                                 /* end of Init_Board */

int Deal_A_Card()
    {
    int i;
    int Cards_Left;

    for(  i = (int)RangeRand( (long)CARDS ), Cards_Left = 5 ;
          Cards_Left > 0 ; Cards_Left-- );

    for(  i = (int)RangeRand((long)CARDS), Cards_Left = CARDS  ;
          Deck[i] == NOT_IN_DECK   &&   Cards_Left > 0         ;
          Cards_Left--                                             )     {
               i = i + 1;
               if ( i >= CARDS )
                                  i = 0;                                 }

    if (   ( Cards_Left > 0 )   &&   ( Deck[i] == IN_DECK )   )    {
                                Remove_Card_From_Deck( i );
                                return(  i );                      }
       else return( NO_CARDS_LEFT );
    }                                                /* end of Deal_A_Card */


int Card_Rank( C )
    int C;
    {
    return(   ( C % 14 )  +  1   );
    }                                                  /* end of Card_Rank */


void Mark_Card( h, w )
     int h, w;
     {
     if ( h < BOARD_HEIGHT  &&  w < BOARD_WIDTH )
        {
        Board[h][w].High_Light_On = YES;
        DrawBorder( Window->RPort, HighLight,
                    (long)Board[h][w].X, (long)Board[h][w].Y           );
        }
     else  {
              printf("Out of range h or w value received in Mark_Card \n");
              Die();        }
     }                                                 /* end of Mark_Card */


void UnMark_Card( h, w )
     int h, w;
     {
     if ( h < BOARD_HEIGHT  &&  w < BOARD_WIDTH )
        {
        Board[h][w].High_Light_On = NO;
        DrawBorder( Window->RPort, UnHighLight,
                    (long)Board[h][w].X, (long)Board[h][w].Y           );
        }
     else  {
              printf("Out of range h or w value received in UnMark_Card \n");
              Die();        }
     }                                               /* end of UnMark_Card */

void Put_Card_On_Board( h, w )
     int h, w;
     {
     int C;
     Delay( 2L );
     if ( h < BOARD_HEIGHT  &&  w < BOARD_WIDTH )
              {
              C = Deal_A_Card();
              if ( C != NO_CARDS_LEFT )
                 {
                 Board[h][w].Current_Card = C;
                 ShowCard(  Window->RPort, Board[h][w].Current_Card,
                            Board[h][w].X, Board[h][w].Y              );
                 }
              }
        else  {
              printf("Out of range h or w value received in Put_Card_On_Board \n");
              Die();        }
     }                                         /* end of Put_Card_On_Board */


void Display_Window_Title()
     {
     static char  Title_String[80];
     char *Title_Ptr = Title_String;
     short Position;

     if ( Cards_Remaining > 0 )
         sprintf(  Title_Ptr, " 13s    Cards %d ", Cards_Remaining );
     else sprintf( Title_Ptr, " 13s -- You Won ");
     for( Position = VBeamPos()                                          ;
          Position < Window->TopEdge + 20  ||
                                        Position > Window->TopEdge + 100 ;
          Position = VBeamPos()                                            );
     SetWindowTitles( Window, Title_Ptr, -1L );
     }                                      /* end of Display_Window_Title */


void Remove_Card_Off_Board( h, w )
     int h, w;
     {
     long Old_Fg_Pen;

     if ( h < BOARD_HEIGHT  &&  w < BOARD_WIDTH )
        {
        Cards_Remaining--;
        Display_Window_Title();
        Board[h][w].Current_Card = EMPTY;
        Old_Fg_Pen = Window->RPort->FgPen;
        SetAPen( Window->RPort, 0L );
        RectFill( Window->RPort,
                  (long)( Board[h][w].X ), (long)( Board[h][w].Y ),
                  (long)( Board[h][w].X + CARDWIDTH  - 1 ),
                  (long)( Board[h][w].Y + CARDHEIGHT - 1 )             );
        Board[h][w].Valid_Move    = NO;
        Board[h][w].High_Light_On = NO;
        DrawBorder( Window->RPort, UnHighLight,
                    (long)Board[h][w].X, (long)Board[h][w].Y           );
        SetAPen( Window->RPort, Old_Fg_Pen );
        }
     else  {
              printf("Out of range h or w value received in Remove_Card_Off_Board \n");
              Die();        }
     }                                     /* end of Remove_Card_Off_Board */

void Locate_First_Marked_Card( Start_h, Start_w, Found_h, Found_w )
     /* locates the first marked card starting at board location      */
     /* [Start_h][Start_w].  The search is done in row major order.   */
     /* The location is returned in Found_h and Found_w.  If a marked */
     /* card is not found, Found_h and Found_w are set to -1.         */
     int Start_h, Start_w, *Found_h, *Found_w;
     {
     int h, w;
     int Found;

     for(    h = 0, Found = NO                     ;
             h < BOARD_HEIGHT  &&  Found == NO     ;
             h++                                               )
        for( w = 0                                 ;
             w < BOARD_WIDTH    &&   Found == NO   ;
             w++                                             )
             if (  Board[h][w].High_Light_On == YES  )
                {
                Found = YES;
                *Found_h = h;
                *Found_w = w;
                }
     if (   Found == NO   )
        {
        *Found_h = -1;
        *Found_w = -1;
        }
     }                                  /* end of Locate_First_Marked_Card */


void Locate_Mouse( MouseX, MouseY, h, w, Where )
     /*   Returns if the mouse is on the background.  If the mouse    */
     /*   is on a card, then the row & column are returned in h & w   */
     int MouseX, MouseY;
     int *h, *w;
     int *Where;
     {
     *Where = ON_CARD;
     /* find out which spot on the board was selected */
     *w = ( MouseX - LEFT_MARGIN )  /  ( CARDWIDTH + HORIZONTAL_GAP );
     if ( *w < BOARD_WIDTH )
        {
        if (   ( MouseX < Board[0][*w].X               )  ||
               ( MouseX > Board[0][*w].X + CARDWIDTH   )       )
           *Where = ON_BACKGROUND;
        }
     else *Where = ON_BACKGROUND;

     *h = ( MouseY - TOP_MARGIN )  /  ( CARDHEIGHT + VERTICAL_GAP );
     if ( *h < BOARD_HEIGHT )
        {
        if (   ( MouseY < Board[*h][0].Y              )  ||
               ( MouseY > Board[*h][0].Y + CARDHEIGHT )      )
           *Where = ON_BACKGROUND;
        }
     else *Where = ON_BACKGROUND;
     }                                              /* end of Locate_Mouse */


void Move_Card( MouseX, MouseY )
     int MouseX, MouseY;
     {
     int Selected_h, Selected_w;
     int Marked_h,   Marked_w;
     int Where;

     Locate_Mouse( MouseX, MouseY, &Selected_h, &Selected_w, &Where );
     if (  Where == ON_CARD )
        if ( Board[Selected_h][Selected_w].Current_Card != EMPTY ) {
           Locate_First_Marked_Card( 0, 0, &Marked_h, &Marked_w );
           if (  Card_Rank(Board[Selected_h][Selected_w].Current_Card)
                 != KING  ) {
              if (   Marked_h > -1   &&   Marked_w > -1   ) {
                 if ( Card_Rank( Board[Marked_h][Marked_w].Current_Card ) +
                      Card_Rank(Board[Selected_h][Selected_w].Current_Card)
                      == 13 ) {
                             Remove_Card_Off_Board( Marked_h,   Marked_w   );
                             Remove_Card_Off_Board( Selected_h, Selected_w );
                             Put_Card_On_Board(     Marked_h,   Marked_w   );
                             Put_Card_On_Board(     Selected_h, Selected_w );
                    } else  {
                             UnMark_Card( Marked_h,   Marked_w   );
                             Mark_Card(   Selected_h, Selected_w );
                             }
                 } else      Mark_Card( Selected_h, Selected_w );
              } else  {
                      if (   Marked_h > -1   &&   Marked_w > -1   )
                      UnMark_Card(   Marked_h,   Marked_w   );
                      Remove_Card_Off_Board( Selected_h, Selected_w );
                      Put_Card_On_Board(     Selected_h, Selected_w );
                      }
           }
     if ( Cards_Remaining < 1 )
        Pulse_Flag = TRUE;
     }                                                 /* end of Move_Card */


void Shuffle()
     {
     int h,w;
     int j;
     long v[3];

     DateStamp( v );
     for( RangeRand( (long)CARDS ), j = 0  ;
          j <= v[2]                        ;
          RangeRand( (long)CARDS ), j++     )  ;
     for (     h = 0 ; h < BOARD_HEIGHT ; h++ )
         for ( w = 0 ; w < BOARD_WIDTH  ; w++ )
             {
             Board[h][w].Current_Card = Deal_A_Card();
             ShowCard(  Window->RPort, Board[h][w].Current_Card,
                        Board[h][w].X, Board[h][w].Y              );
             }
     }                                                   /* end of Shuffle */


void Next_Game()
     {
     long Old_Fg_Pen;

     Points = 0;
     Cards_Remaining = 52;
     Display_Window_Title();

     Init_Deck();
     Init_Board();

     /* clear window */
     Old_Fg_Pen = Window->RPort->FgPen;
     SetAPen(  Window->RPort, 0L );
     RectFill( Window->RPort,
               (long)( LEFT_MARGIN - 1 ), (long)( TOP_MARGIN - 1 ),
               (long)( LEFT_MARGIN +
                       ( BOARD_WIDTH  * ( CARDWIDTH  + HORIZONTAL_GAP ) ) ),
               (long)( TOP_MARGIN - 2 +
                       ( BOARD_HEIGHT * ( CARDHEIGHT + VERTICAL_GAP  ) ) ) );
     SetAPen( Window->RPort, Old_Fg_Pen );
     Shuffle();
     }                                                 /* end of Next_Game */

void Wait_On_Requester()
    {
    struct IntuiMessage *IntuiMessagePtr;
    struct IntuiMessage local_msg;
    register int i;
    unsigned char *source, *dest;

    ModifyIDCMP( Window, REQCLEAR );
    while( 1 )
             {
             IntuiMessagePtr = (struct IntuiMessage *)GetMsg(Window->UserPort);
             if ( IntuiMessagePtr == NULL )
                                           WaitPort( Window->UserPort );
                else
                        {   /* exit on Requester clear message */
                        source = (unsigned char *)IntuiMessagePtr;
                        dest   = (unsigned char *)&local_msg;
                        for ( i = 0; i < sizeof(struct IntuiMessage); i++)
                            *dest++ = *source++;
                        ReplyMsg( IntuiMessagePtr );
                        if ( local_msg.Class == REQCLEAR )
                           break;
                        }
             }
    ModifyIDCMP( Window, NORMAL_IDCMP_FLAGS );
    }                                         /* end of Wait_On_Requester */


void Menu_Request( IntuiMessagePtr )
     struct IntuiMessage *IntuiMessagePtr;
     {
     USHORT code;

     code = IntuiMessagePtr->Code;

     switch( ITEMNUM(code) ) {
           case ABOUT:
                         if ( Request( About_Requester, Window ) == TRUE )
                              Wait_On_Requester();
                         break;
           case HELP:
                         if ( Request( Help_Requester, Window ) == TRUE )
                              Wait_On_Requester();
                         break;
           case GAME:
                         Next_Game();
                         break;
           default:
                         break;
           }
     }                                              /* end of Menu_Request */

void Reset_Color_Registers()
     {
     long Red_Bits;
     long Blue_Bits;
     long Green_Bits;
     struct Preferences Current_Preferences;

     /* set color registers 2 & 3 to the current Preferences values */
     GetPrefs(  &Current_Preferences, sizeof(Current_Preferences) );
     Blue_Bits  = (long)((     Current_Preferences.color2        & 0x000f  ));
     Green_Bits = (long)(( ( Current_Preferences.color2 >> 4 ) & 0x000f  ));
     Red_Bits   = (long)(( ( Current_Preferences.color2 >> 8 ) & 0x000f  ));
     SetRGB4(   ViewPortPtr, 2L, Red_Bits, Green_Bits, Blue_Bits );
     Blue_Bits  = (long)((   Current_Preferences.color3        & 0x000f  ));
     Green_Bits = (long)(( ( Current_Preferences.color3 >> 4 ) & 0x000f  ));
     Red_Bits   = (long)(( ( Current_Preferences.color3 >> 8 ) & 0x000f  ));
     SetRGB4(   ViewPortPtr, 3L, Red_Bits, Green_Bits, Blue_Bits );
     Pulse_Flag = FALSE;
     }                                     /* end of Reset_Color_Registers */


long HandleEvent( IntuiMessagePtr )
    struct IntuiMessage *IntuiMessagePtr;
    {
    struct IntuiMessage local_msg;
    register int i;
    unsigned char *source, *dest;
    long result; /* return 0 if main should close and exit */

    source = (unsigned char *)IntuiMessagePtr; /* original IntuiMessage */
    dest   = (unsigned char *)&local_msg;      /* local copy of         */
                                               /* IntuiMessage          */

    for ( i = 0; i < sizeof(struct IntuiMessage); i++)
        *dest++ = *source++;  /* make a local copy of the message */
    ReplyMsg( IntuiMessagePtr );

    switch( local_msg.Class )
        {
        case MOUSEBUTTONS:
                if ( local_msg.Code == SELECTDOWN )
                   Move_Card( local_msg.MouseX, local_msg.MouseY );
                result = 1L;
                break;
        case MENUPICK:
                Reset_Color_Registers();
                Menu_Request( &local_msg );
                result = 1L;
                break;
        case CLOSEWINDOW:
                Reset_Color_Registers();
                result = FALSE; /* tell main to close and exit */
                break;
        case INACTIVEWINDOW:
                Reset_Color_Registers();
                result = 1L;
                break;
        case RAWKEY:
                if ( local_msg.Code == 0x5F )
                   if ( Request( Help_Requester, Window ) == TRUE )
                      Wait_On_Requester();
                result = 1L;
                break;
        default:
                result = 1L;
                break;
        }
    RangeRand(  (long)CARDS  ) ;
    for(   ; GetMsg( Window->UserPort ) != 0L ; )
        ReplyMsg( IntuiMessagePtr );

    return( result );

    }                                                /* end of HandleEvent */


void Pulse ()
     {
     Delay( 1L );
     if ( Reg_3_Red_Bits > 14 )
        Pulse_Direction = 1;
     if ( Reg_3_Red_Bits == 0 )
        Pulse_Direction = 0;
     if ( Pulse_Direction == 0 )   {
                                  Reg_3_Red_Bits++;
                                  Reg_2_Red_Bits--;   }
        else                  {
                                  Reg_3_Red_Bits--;
                                  Reg_2_Red_Bits++;   }
     if ( Round_Cnt >= 3 || Round_Cnt == 1 )
        SetRGB4( ViewPortPtr, 3L,
                 Reg_3_Red_Bits, Reg_3_Green_Bits, Reg_3_Blue_Bits );
     if ( Round_Cnt == 2 || Round_Cnt == 1 )
        SetRGB4( ViewPortPtr, 2L,
                 Reg_2_Red_Bits, Reg_2_Green_Bits, Reg_2_Blue_Bits );
     }                                                     /* end of Pulse */


void _cli_parse() { }
void _wb_parse() { }


main()
    {
     int i;

   IntuitionBase = (struct IntuitionBase *)
      OpenLibrary("intuition.library",(long)INTUITION_REV);
   if(IntuitionBase == NULL)
      Die();

   GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",(long)GRAPHICS_REV);
   if(GfxBase == NULL)
      Die();

   NewWindow.LeftEdge    =  LEFT_EDGE;
   NewWindow.TopEdge     =   TOP_EDGE;
   NewWindow.Width       = WIDTH;
   NewWindow.Height      = HEIGHT;
   NewWindow.DetailPen   =   0;
   NewWindow.BlockPen    =   1;
   NewWindow.Flags       = WINDOWCLOSE | SMART_REFRESH | ACTIVATE |
                           WINDOWDRAG  | WINDOWDEPTH                   ;
   NewWindow.IDCMPFlags  = NORMAL_IDCMP_FLAGS;
   NewWindow.Type        = WBENCHSCREEN;
   NewWindow.FirstGadget = NULL;
   NewWindow.CheckMark   = NULL;
   NewWindow.Screen      = NULL;
   NewWindow.BitMap      = NULL;
   NewWindow.MinWidth    = 0;    /*    use     */
   NewWindow.MinHeight   = 0;    /*    the     */
   NewWindow.MaxWidth    = 0;    /*  initial   */
   NewWindow.MaxHeight   = 0;    /*  settings  */

   Border_Coordinates[0] = 0;
   Border_Coordinates[1] = 0;

   Border_Coordinates[2] = (SHORT)( CARDWIDTH + 1 );
   Border_Coordinates[3] = 0;

   Border_Coordinates[4] = (SHORT)( CARDWIDTH  + 1 );
   Border_Coordinates[5] = (SHORT)( CARDHEIGHT + 1 );

   Border_Coordinates[6] = 0;
   Border_Coordinates[7] = (SHORT)( CARDHEIGHT + 1 );

   Border_Coordinates[8] = 0;
   Border_Coordinates[9] = 0;

   if(( Window = (struct Window *) OpenWindow(&NewWindow)) == NULL)
      Die();

   ViewPortPtr = ViewPortAddress( Window );

   Reg_2_Blue_Bits  =  0L;
   Reg_2_Green_Bits =  0L;
   Reg_2_Red_Bits   =  0L;
   Reg_3_Blue_Bits  =  0L;
   Reg_3_Green_Bits =  0L;
   Reg_3_Red_Bits   = 15L;

   Display_Window_Title();
   SetMenuStrip(    Window, &Menu1    );
   OffMenu( Window, (long)( (SHIFTITEM( ROUND        )) +
                            (SHIFTMENU( ROUND_MENU_NO))   ) );
   Next_Game();

   while( 1 )
            {
            IntuiMessagePtr = (struct IntuiMessage *)GetMsg(Window->UserPort);
            if ( IntuiMessagePtr == NULL ) {
               if (  Pulse_Flag == TRUE  )
                                   Pulse();
                  else             WaitPort( Window->UserPort ); }
                else
                        {   /* exit on close message */
                            if (  HandleEvent ( IntuiMessagePtr ) == FALSE  )
                                break;   }
            }

   Close_Stuff();
   exit(TRUE);
   }
