/* @(#)Z 1.7.1.1 com/src/samples/t3part/iodt3.cpp, odt3part, od96nt, odnt9712d 97/03/21 17:36:12 (96/10/08 15:55:53) */
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odt3part
//
//   CLASSES: none
//
//   ORIGINS: 27
//
//
//   (C) COPYRIGHT International Business Machines Corp. 1995,1996
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//====END_GENERATED_PROLOG========================================
//

/*
 *  This file was generated by the SOM Compiler.
 *  Generated using:
 *     SOM incremental update: Development
 */


// *********************************************************************
//  File:      iodt3.cpp
//  Contains:  Implementation of an Embedded TicTacToe Game Part
// ************************************************************************


// ---- TicTacToe Game Part -----------------------------------------------
//
//      The embeddable TicTacToe game is a new and improved variation
//      of a timeless classic. The game has been implemented as an
//      Opendoc Container part, which allows other game parts to be
//      embedded within its squares.
//
//      The game board is laid out as nine numbered squares
//
//              0  //  1  //  2      which correspond to bit positions
//            -------------------    fXMap and fOMap internal class
//              3  //  4  //  5      variables. Available squares are
//            -------------------    determined by an OR of fXMap with
//              6  //  7  //  8      fOMap.
//
//

#ifndef OpenDoc_Sample_T3Part
#include "iodt3.h"
#endif


/*
*******************************************************************
** Name: static void Log(char *x, char *y)
**
** And redefine of: T3GamePartMethodDebug
**                  M_T3GamePartMethodDebug
**
** Description:  This function will output a message to the
**               utility MSGDISP.EXE for every call
**               the MethodDebug macros.  This allows
**               the developer to see the method calls
**               being made to this part in real-time.
**
** Parameters:   char *x;   //description of class
**               char *y;  //description of method
**
** Returns:      none
**
** Caution:      This function only exists if DEBUG is defined.
**
*******************************************************************
*/

// If debug is defined

#ifdef DEBUG
   #undef T3GamePartMethodDebug
   #undef M_T3GamePartMethodDebug

   #define T3GamePartMethodDebug(x,y) Log(x,y)
   #define M_T3GamePartMethodDebug(x,y) Log(x,y)

   #include <qprintf.h>  // output to MSGDISP.EXE

   static void Log (char *x, char *y)
   {
      qprintf ("%s:%s\n", x, y);
   }

#endif // DEBUG



// ---- T3GameModel ----------------------------------------------------------
//
//      The T3GameModel class manages the TicTacToe board during play
//      Moves are checked, winners are determined, and tie games are
//      handled.
//
//



// Constructors / Destructors

T3GameModel::T3GameModel() :  fXMap(0), fOMap(0) { }
T3GameModel::T3GameModel(const T3GameModel& model)  { }
T3GameModel::~T3GameModel() { }

// Getters / Setters

int  T3GameModel::GetXMove(int i) { return (fXMap & (1 << i)); }
int  T3GameModel::GetOMove(int i) { return (fOMap & (1 << i)); }

void T3GameModel::SetXMove(int i) { fXMap=(fXMap & (1 << i)); }
void T3GameModel::SetOMove(int i) { fOMap=(fOMap & (1 << i)); }

     // used to save/restore a gameboard
long T3GameModel::GetXMap(void) { return fXMap; }
long T3GameModel::GetOMap(void) { return fOMap; }

void T3GameModel::SetXMap(long xMap) { fXMap=xMap; }
void T3GameModel::SetOMap(long oMap) { fOMap=oMap; }



/*
*******************************************************************
** Name: int T3GameModel::DoXMove(int fXMove)
**
** Description:  Makes a move for X at specific position. Determines
**               if a valid move and if X wins.
**
** Parameters:   int fXMove;          // Position (1-9) on game board
**                                    // to play as an X
**
** Returns:      1 - True or success
**               0 - False
**               T3GameException::kInvalidMove - fXMove is not 1-9 or
**                                               is a position occupied
**                                               already by another X
**                                               or O.
**               T3GameException::kWinByX - fXMove causes X to win game.
**
**
**
*******************************************************************
*/
int T3GameModel::DoXMove(int fXMove)
{
   // Validate move, legal location and position not occupied already.
   if ( (fXMap | fOMap) & ( 1 << (fXMove-1) ) )
      throw T3GameException(T3GameException::kInvalidMove);

   // Add move to game board map
   fXMap=fXMap | (1 << (fXMove-1));

   if ( AnyWinner(fXMap) > 0 )
      throw T3GameException(T3GameException::kWinByX);

    return 1; // should return 1 for true else 0 false

} // T3GameModel::DoXMove()

/*
*******************************************************************
** Name: int T3GameModel::DoOMove(int fOMove)
**
** Description:  Makes a move for O at specific position. Determines
**               if a valid move and if O wins, or a tie.
**
** Parameters:   int fOMove;          // Position (1-9) on game board
**                                    // to play as an O.  A 0 (zero)
**                                    // indicates game is tied.
**
** Returns:      1 - True or success
**               0 - False
**               T3GameException::kTieGame - fOMove is 0 (zero) then
**                                           game is tied.
**               T3GameException::kWinByO - fOMove causes O to win game.
**
**
**
*******************************************************************
*/
int T3GameModel::DoOMove(int fOMove)
{
   // A zero move indicates a tie game.
   if ( fOMove==0 )
      throw T3GameException(T3GameException::kTieGame);

   // Add move to game board map
   fOMap=fOMap | (1 << (fOMove-1));

   if ( AnyWinner(fOMap) > 0)
      throw T3GameException(T3GameException::kWinByO);

   return 1;                      // should return 1 for true else 0 false
} // T3GameModel::DoOMove()



/*
*******************************************************************
** Name: int T3GameModel::PickMove(void)
**
** Description:  Pick a move based on priority:   center 1st,
**               corners 2nd, edges 3rd
**
** Parameters:   none
**
** Returns:      1-9 -- Position on game board to play
**               0   -- no more moves, tie game.
**
*******************************************************************
*/
int T3GameModel::PickMove(void)
{
   int xoMap;

   xoMap=fXMap | fOMap;

   if ((xoMap & (1<<4)) == 0) return 5;     // choose center first if free

   if ((xoMap & (1<<0)) == 0) return 1;     // choose a corner
   if ((xoMap & (1<<2)) == 0) return 3;
   if ((xoMap & (1<<6)) == 0) return 7;
   if ((xoMap & (1<<8)) == 0) return 9;

   if ((xoMap & (1<<1)) == 0) return 2;     // lastly choose a side
   if ((xoMap & (1<<3)) == 0) return 4;
   if ((xoMap & (1<<5)) == 0) return 6;
   if ((xoMap & (1<<7)) == 0) return 8;

   return 0;                                // no more moves tie game

} // T3GameModel::PickMove()


/*
*******************************************************************
** Name: void T3GameModel::AnyWinners()
**
** Description:  Checks to see who won the game or was it a tie game
**
** Parameters:   none
**
** Returns:      If no exception thrown, no winner, no tie
**               T3GameException::kTieGame -- tie game
**               T3GameException::kWinByX  -- player X won
**               T3GameException::kWinByO  -- player O won
**
*******************************************************************
*/
void T3GameModel::AnyWinners()
{

   // if map full then tie game

   if ((fXMap|fOMap)==0x01FF) throw T3GameException(T3GameException::kTieGame);

   // any winning combinations then declare the winner

   if (AnyWinner(fXMap)>0)    throw T3GameException(T3GameException::kWinByX);
   if (AnyWinner(fOMap)>0)    throw T3GameException(T3GameException::kWinByO);

} // T3GameModel::AnyWinners()

/*
*******************************************************************
** Name: int T3GameModel::AnyWinner( long aMap )
**
** Description:  Checks to see if a board map contains a winner:
**               a sequence of 3 places occupied in a horizontal,
**               vertical or diagonal line.
**
** Parameters:   long aMap;  //  bitwise represenation of game board.
**                           //  Bit true (1) for each position occupied.
**                           //  Passed map is for X or for O only.
**
** Returns:      0 -- no winning combination
**               1 -- wining combination exists.
**
*******************************************************************
*/
int T3GameModel::AnyWinner(long aMap)
{

   // check for winning sequence

   if ((aMap & ((0x0007)<<0))==((0x0007)<<0)) return 1;    // horizontal: is it 1-2-3
   if ((aMap & ((0x0007)<<3))==((0x0007)<<3)) return 1;    // is it 4-5-6
   if ((aMap & ((0x0007)<<6))==((0x0007)<<6)) return 1;    // is it 7-8-9

   if ((aMap & ((0x0049)<<0))==((0x0049)<<0)) return 1;    // vertical: is it 1-4-7
   if ((aMap & ((0x0049)<<1))==((0x0049)<<1)) return 1;    // is it 2-5-8
   if ((aMap & ((0x0049)<<2))==((0x0049)<<2)) return 1;    // is it 3-6-9

   if ((aMap & ((0x0111)<<0))==((0x0111)<<0)) return 1;    // diagonal: is it 1-5-9
   if ((aMap & ((0x0054)<<0))==((0x0054)<<0)) return 1;    // is it 3-5-7

   return 0; // no win

} // T3GameModel::AnyWinner()




/*
*******************************************************************
** Name: void T3GameModel::MakeAMove(char whatCmd)
**
** Description:  Handle user interaction commands 1-9 or
**               N for New GAME.  If whatCmd '1'-'9', plays X
**               at that position and then has computer play O.
**
** Parameters:   char whatCmd; // Cmd's '1'-'9' indicate to play a X
**                             // at that position. 'N' indicates
**                             // new game.
**
** Returns:      none
**
** Caution:      This routine call other routines that issue
**               exceptions that are not caught, thus are
**               passed up from here:
**
**               T3GameException::kTieGame     -- tie game
**               T3GameException::kWinByX      -- player X won
**               T3GameException::kWinByO      -- player O won
**               T3GameException::kInvalidMove -- tried to play at
**                                                occupied position
**
*******************************************************************
*/
void T3GameModel::MakeAMove(char whatCmd)
{
   switch ( whatCmd )
   {
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
               // play X at position
               DoXMove(whatCmd-'0');
               // computer plays O
               DoOMove(PickMove());
               break;

      case 'N':
               // clear game board
               fXMap=0;
               fOMap=0;
               break;

      default:
               break;
   } // switch

} // T3GameMode::MakeAMove()



/*
*******************************************************************
** Name: T3GameException::   Constructors / Destructors
**                           / Assignment operators
**
** Description:  The T3GameException class handles the exceptions
**               thrown by the T3GameModel during TicTacToe play.
**               The model will throw one or more of the following
**               exception conditions:
**
**               T3GameException::kTieGame     -- tie game
**               T3GameException::kWinByX      -- player X won
**               T3GameException::kWinByO      -- player O won
**               T3GameException::kInvalidMove -- tried to play at
**                                                occupied position
**
*******************************************************************
*/


T3GameException::T3GameException() { }
T3GameException::T3GameException(EReason reason) { fData=reason; }
T3GameException::T3GameException(const T3GameException& copy) { fData=copy.fData; }
T3GameException::~T3GameException() { }

T3GameException& T3GameException::operator=(const T3GameException& copy)
{
   if( &copy != this )
      fData=copy.fData;

   return *this;
}
unsigned long T3GameException::GetReason() const { return fData; }
void T3GameException::Throw() const { throw *(T3GameException *)this; }

// -------------------------------------------------------------------------
// -----                                                               -----
// -----                  T3GamePart    Class                          -----
// -----                                                               -----
// -----              Overriding Inherited Methods                     -----
// -----                                                               -----
// -------------------------------------------------------------------------

/********************************************************************
** Name:       void somInit ( T3GamePart *somSelf )
**
** Class:      SOM class T3GamePart
**
** Description:
**
**      Initializes the instance variables in the SOMObject of this part.
**
**      -> does not call parent method (called automatically by SOM)
**      -> optional for all parts
**
**      -> somInit must NOT fail (code that might fail goes to InitPart)
**
******************************************************************
*/

SOM_Scope void  SOMLINK T3GamePartsomInit(T3GamePart *somSelf)
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartsomInit");

    //  (1) call parent's method before starting
    T3GamePart_parent_BaseContainer_somInit(somSelf);

    //  (2) initialize T3GamePart attributes
    _fGameModel       = kODNULL;
    _fGameSquare      = kODNULL;
    _fMySquare        = kODNULL;

    _fSession         = kODNULL;
    _fMenuBar         = kODNULL;
    _fStatusMsg       = kODNULL;

    _fWinner          = kODNULL;
    _fInvMoveMsg      = kODNULL;
    _fOWinsMsg        = kODNULL;
    _fXWinsMsg        = kODNULL;
    _fTieGameMsg      = kODNULL;
    _fTicTacToeMsg    = kODNULL;

    _fXToken          = kODNULL;
    _fOToken          = kODNULL;

} // T3GamePartsomInit()




/*
*******************************************************************
** Name:       void somUninit ( T3GamePart *somSelf )
**
** Class:      SOM class T3GamePart
**
** Description:
**
**      Disposes of storage for the SOMObject of this part.
**
**      -> optional for all parts
**
**      -> somUninit must NOT fail
**
** Parameters:   T3GamePart *somSelf;  // in
**
** Returns:      none
**
**
*******************************************************************
*/
SOM_Scope       void
SOMLINK         T3GamePartsomUninit
                (
                T3GamePart   *somSelf        // in
                )
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartsomUninit");

    // call parent's method after you're finished and before you exit
    T3GamePart_parent_BaseContainer_somUninit(somSelf);

} // T3GamePartsomUninit()



/*
*******************************************************************
** Name:          ODBoolean HandleMouseUp
**                   (
**                   T3GamePart      *somSelf,       // in
**                   Environment     *ev,            // in
**                   ODEventData     *event,         // in
**                   ODFrame         *frame,         // in
**                   ODFacet         *facet,         // in
**                   ODEventInfo     *eventInfo      // inout
**                   )
**
** Class:         SOM class T3GamePart
**
** Description:   The HandleMouseUp method recieves mouse-up events
**                and saves the point of where it occurred. Using
**                the facet dimensions, HandleMouseUp determines
**                which square was selected on the TicTacToe board.
**
**
** Parameters:    T3GamePart *somSelf;            // in
**                Environment     *ev,            // in
**                ODEventData     *event,         // in
**                ODFrame         *frame,         // in
**                ODFacet         *facet,         // in
**                ODEventInfo     *eventInfo      // inout
**
** Returns:       kODTrue -- Event handled
**                kODFalse -- Event not handled
**
**
*******************************************************************
*/

SOM_Scope       ODBoolean
SOMLINK         T3GamePartHandleMouseUp
                (
                T3GamePart      *somSelf,       // in
                Environment     *ev,            // in
                ODEventData     *event,         // in
                ODFrame         *frame,         // in
                ODFacet         *facet,         // in
                ODEventInfo     *eventInfo      // inout
                )
{
   T3GamePartData *somThis = T3GamePartGetData(somSelf);
   T3GamePartMethodDebug("T3GamePart","T3GamePartHandleMouseUp");

   ODBoolean   eventHandled     = kODTrue;

   try
   {
      if ( facet != kODNULL && somSelf->ActivateFrame(ev, frame))
      {
         TempODTransform xform = facet->AcquireWindowFrameTransform(ev,kODNULL);

         // Get Bounding Box in OD coords
         TempODShape shape = frame->AcquireFrameShape(ev,facet->GetCanvas(ev));

         ODRect odRect;
         shape->GetBoundingBox(ev,&odRect);

         // Now convert to windows coords
         Rect winRect;

         SetRect(&winRect, FixedToInt(odRect.left),
                           FixedToInt(odRect.top),
                           FixedToInt(odRect.right),
                           FixedToInt(odRect.bottom));

         // Next determine dimensions of a game square
         int xBox = (winRect.right - winRect.left)/3;
         int yBox = (winRect.bottom - winRect.top)/3;

         // Extract the mouse position from the event params
         ODPoint mousePt;
         mousePt.x = ODIntToFixed(LOWORD(event->lParam));
         mousePt.y = ODIntToFixed(HIWORD(event->lParam));

         // Transform to the embedded game's coords
         xform->InvertPoint(ev,&mousePt);

         // and calculate the selected square
         int  xMove    = ODFixedRound(mousePt.x)/xBox;
         int  yMove    = ODFixedRound(mousePt.y)/yBox;

         // Add '0' to convert to ASCII value for the game engine
         _fGameSquare  = xMove+ 3*yMove + 1 +'0';


         eventHandled=T3GamePart_parent_BaseContainer_HandleMouseUp(somSelf, ev,
                            event,frame, facet, eventInfo);

         try
         {
            if(frame->IsRoot(ev))
               _fGameModel->AnyWinners();
            else
               _fGameModel->MakeAMove(_fGameSquare);

         } // end of try block


         catch (const T3GameException e)
         {
            unsigned long rc=e.GetReason();

            // INVALID MOVE: Reset the board
            if (rc == (unsigned long)T3GameException::kInvalidMove)
            {
               if(_fWinner!=kODNULL)
               {
                  _fWinner=kODNULL;
                  _fStatusMsg=_fTicTacToeMsg;
               }
               else
                  _fStatusMsg=_fInvMoveMsg;

               _fGameModel->MakeAMove('N');
            }
            // X WINS: Draw a BIG X and notify the container
            else if (rc==(unsigned long)T3GameException::kWinByX)
            {
               _fStatusMsg=_fXWinsMsg;
               _fWinner=_fXToken;

               // Tell the containing game that X wins

               if(!frame->IsRoot(ev)) // if not root part
               {
                  // Acquire the ODPart via the frame handle
                  TempODFrame cf = frame->AcquireContainingFrame(ev);
                  TempODPart  cp = cf->AcquirePart(ev);

                  // OpenDoc returns ODPartWrapper handle. You need to get
                  // the actual real ODPart to get at subclassed methods
                  if(cp->HasExtension(ev,kT3GameExtension)) {
                      T3GamePart *tp = (T3GamePart *)cp->GetRealPart(ev);
                      tp->WonByX(ev,_fMySquare);
                      cp->ReleaseRealPart(ev);
                      }

                } // if not root part

            } // else if kWinByX

            // O WINS: Draw a BIG O and notify the container
            else if (rc==(unsigned long)T3GameException::kWinByO) {
                _fStatusMsg=_fOWinsMsg;
                _fWinner=_fOToken;

                // Tell the containing game that O wins
                if(!frame->IsRoot(ev)) {
                    // Acquire the ODPart via the frame handle
                    TempODFrame cf = frame->AcquireContainingFrame(ev);
                    TempODPart  cp = cf->AcquirePart(ev);

                    // OpenDoc returns ODPartWrapper handle. You need to get
                    // the actual real ODPart to get at subclassed methods
                    if(cp->HasExtension(ev,kT3GameExtension)) {
                        T3GamePart *tp = (T3GamePart *)cp->GetRealPart(ev);
                        tp->WonByO(ev,_fMySquare);
                        cp->ReleaseRealPart(ev);
                        }
                    }
                }

            // TIE GAME: Reset the game board for another game
            else if (rc==(unsigned long)T3GameException::kTieGame) {
                _fStatusMsg=_fTieGameMsg;
                _fWinner=kODNULL;

                _fGameModel->MakeAMove('N');
            } // end of if/else/else block
         }   // end of CATCH block

         facet->Invalidate(ev,kODNULL,kODNULL);
      }   // end of if we have a FACET

      else
         eventHandled=kODFalse;

    }
    catch(...)
    {
    }

    return eventHandled;

} // T3GamePartHandleMouseUp()

/*
*******************************************************************
** Name: void Draw ( T3GamePart *somSelf, Environment *ev,
**                             ODFacet *facet, ODShape *invalidShape )
**
** Class:         SOM class T3GamePart
**
** Description:   Draws the game board.
**
** Parameters:    T3GamePart      *somSelf,       // in
**                Environment     *ev,            // in
**                ODFacet         *facet,         // in
**                ODShape         *invalidShape   // in
**
** Returns:       none
**
*******************************************************************
*/
SOM_Scope       void
SOMLINK         T3GamePartDraw
                (
                T3GamePart      *somSelf,       // in
                Environment     *ev,            // in
                ODFacet         *facet,         // in
                ODShape         *invalidShape   // in
                )
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartDraw");


    try
    {
        T3GamePart_parent_BaseContainer_Draw(somSelf,ev,facet,invalidShape);

        // get the drawing canvas
        ODWin32Canvas *pc = (ODWin32Canvas *)facet->GetCanvas(ev)->GetPlatformCanvas(ev,kODWin32);

        // do we have the window if not then no need to draw anything
        if(pc->HasWindow(ev))
        {
            // yes, then get a Windows device context
            ODFrame* displayFrame = facet->GetFrame(ev);

            // Get the frame bounding rectangle and convert to Window's rectangle
            ODRect rect;
            TempODShape shape = displayFrame->AcquireFrameShape(ev, facet->GetCanvas(ev));

            // Retrieve fMySquare on first time draw, so we know how to
            // report game win/loss status to containing game
            if(_fMySquare==kODNULL) {

                if(displayFrame->IsRoot(ev)) _fMySquare='0';
                else {
                    // Acquire the ODPart via the frame handle
                    TempODFrame cf = displayFrame->AcquireContainingFrame(ev);
                    TempODPart  cp = cf->AcquirePart(ev);

                    // OpenDoc returns ODPartWrapper handle. You need to get
                    // the actual real ODPart to get at subclassed methods
                    if(cp->HasExtension(ev,kT3GameExtension)) {
                        T3GamePart *tp = (T3GamePart *)cp->GetRealPart(ev);
                        _fMySquare=tp->WhoAmI(ev);
                        cp->ReleaseRealPart(ev);
                        }
                    }
                }

            shape->GetBoundingBox(ev, &rect);
            Rect frameRect;
               SetRect(&frameRect, FixedToInt(rect.left),
                       FixedToInt(rect.top),
                       FixedToInt(rect.right),
                       FixedToInt(rect.bottom));

            HDC hdc;



            // Use the focuslib code to set up transforms and clipping
            CFocus Focus(facet, invalidShape, &hdc);

            // Create a solid brush
            HBRUSH hbr;
            if(displayFrame->IsRoot(ev)) hbr=CreateSolidBrush(RGB(0,0,128));
            else hbr=CreateSolidBrush(RGB(0,128,0));

            // Fill the rectangle with the brush
            FillRect (hdc, &frameRect, hbr);

            // Get rid of the brush
            DeleteObject (hbr);

            // Set up a font for the text - ensure it doesn't get too small
            LOGFONT labelFont;
            memset(&labelFont, 0, sizeof(labelFont));
            labelFont.lfPitchAndFamily = FF_SCRIPT;
            labelFont.lfItalic = 1;
            labelFont.lfHeight = (frameRect.bottom - frameRect.top) / 8;
            if(labelFont.lfHeight<8) labelFont.lfHeight=8;
            labelFont.lfQuality = PROOF_QUALITY;
            lstrcpy((LPSTR)labelFont.lfFaceName, (LPSTR)"Cursive");

            // Create the font and select it
            HFONT hFont = CreateFontIndirect(&labelFont);
            HFONT hOldFont;
            hOldFont = SelectObject(hdc, hFont);

            // Set background to transparent and text color to white
            SetBkMode(hdc, TRANSPARENT);
            SetTextColor(hdc, 0x00FFFFFF);

            // draw status line
            DrawText(hdc,
                     _fStatusMsg,
                     strlen(_fStatusMsg),
                     &frameRect,
                     DT_CENTER | DT_VCENTER | DT_SINGLELINE);

            somSelf->DrawSelectionBorder (ev, facet, invalidShape);

            // Compute the board dimensions
            int xLeng = frameRect.right  - frameRect.left;
            int yLeng = frameRect.bottom - frameRect.top;

            // divide by 3 because its a  3x3 game board
            int xBox = xLeng / 3 ;
            int yBox = yLeng / 3 ;

            if(_fWinner==kODNULL) {

                HPEN hPen, oldPen;

                // Create a thick (5 pixel) BLACK pen
                hPen=CreatePen(PS_SOLID, 5, RGB(0,0,0));

                // Select it and save the old pen for restoration
                oldPen=SelectObject(hdc,hPen);

                if(oldPen != NULL) {

                    int i =0;

                    for (i=0; i<4; i++) {

                        // draw the horizontals
                        POINT horLine[] = { {frameRect.left, frameRect.top + i*yBox}, {frameRect.right, frameRect.top+i*yBox} };
                        Polyline(hdc,horLine,2);

                        // draw the verticals
                        POINT verLine[] = { {frameRect.left + i*xBox, frameRect.top}, {frameRect.left + i*xBox, frameRect.bottom} };
                        Polyline(hdc,verLine,2);
                        }

                    // Set up a font for the text - ensure it doesn't get too small
                    memset(&labelFont, 0, sizeof(labelFont));
                    labelFont.lfPitchAndFamily = FF_SCRIPT;
                    labelFont.lfItalic = 1;
                    labelFont.lfHeight = yBox - yBox/5;
                    labelFont.lfQuality = PROOF_QUALITY;
                    lstrcpy((LPSTR)labelFont.lfFaceName, (LPSTR)"Cursive");

                    // Create the font and select it
                    hFont = CreateFontIndirect(&labelFont);
                    SelectObject(hdc, hFont);

                    // Set background to transparent and text color to white
                    SetBkMode(hdc, TRANSPARENT);
                    SetTextColor(hdc, 0x00FFFFFF);

                    for (i=0; i<9; i++) {
                        char *markAs=" ";

                        if(_fGameModel->GetOMove(i)) markAs=_fOToken;
                        if(_fGameModel->GetXMove(i)) markAs=_fXToken;

                        if(markAs!=" ") {
                            RECT theBox;

                            theBox.left   = frameRect.left + (i%3)*xBox + xBox/10;
                            theBox.right  = frameRect.left + (i%3)*xBox + (4*xBox)/5;
                            theBox.top    = frameRect.top + (i/3)*yBox + yBox/10;
                            theBox.bottom = frameRect.top + (i/3)*yBox + (4*yBox)/5;

                            DrawText(hdc,
                                       markAs,
                                         strlen(markAs),
                                           &theBox,
                                             DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                            } // end of if MarkAs

                        }  // end of for loop that marks squares

                    // restore the old pen
                    SelectObject(hdc,oldPen);
                    } // end of if oldpen

                } //end of if fStatusMsg
            else {

                // Set up a font for the text - ensure it doesn't get too small
                memset(&labelFont, 0, sizeof(labelFont));
                labelFont.lfPitchAndFamily = FF_SCRIPT;
                labelFont.lfItalic = 1;
                labelFont.lfHeight = yLeng- yLeng/5;
                labelFont.lfQuality = PROOF_QUALITY;
                lstrcpy((LPSTR)labelFont.lfFaceName, (LPSTR)"Cursive");

                // Create the font and select it
                hFont = CreateFontIndirect(&labelFont);
                SelectObject(hdc, hFont);

                // Set background to transparent and text color to white
                SetBkMode(hdc, TRANSPARENT);
                SetTextColor(hdc, 0x00FFFFFF);

                // Display the winner
                DrawText(hdc,
                           _fWinner,
                             strlen(_fWinner),
                               &frameRect,
                                 DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                }


            // Remove the temporary font
            SelectObject(hdc, hOldFont);
            DeleteObject(hFont);

        } // end of DO-WE-HAVE-A-WINDOW


    }
    catch(...)
    {
    }


} // T3GamePartDraw()


/*
*******************************************************************
** Name: void T3GamePartInitialize
**
** Class:        SOM class T3GamePart
**
** Description:  The Initialize method is called each time a
**               TicTacToe game is first started in OpenDoc. It
**               creates the GAME menu and calls its parent to
**               create the part embedding machinery.
**
*******************************************************************
*/

SOM_Scope void  SOMLINK T3GamePartInitialize(T3GamePart *somSelf,
                                             Environment *ev,
                                             ODPart* partWrapper)
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart", "T3GamePartInitialize");


    try
    {

        // call the parent to initialize the Container features
        T3GamePart_parent_BaseContainer_Initialize(somSelf, ev, partWrapper);

        _fPartWrapper=partWrapper;

        // Establish part's locale
        nl_catd nlsCat;                 // NLS message catalog handle
        char *nlsText;                   // pointer for NLS message

        setlocale(LC_ALL,"");

        nlsCat=catopen(T3_NLS_CATALOG, NL_CAT_LOCALE);


        // Initialize Game Engine
        _fGameModel = new T3GameModel();


        // Initialize Games Messages based on Locale
        _fInvMoveMsg =catgets(nlsCat, T3_MSG_SET, T3_INVMOVE, "Invalid Move! Please try again.");
        _fXWinsMsg   =catgets(nlsCat, T3_MSG_SET, T3_XWINS,   "X Wins the Game!");
        _fOWinsMsg   =catgets(nlsCat, T3_MSG_SET, T3_OWINS,   "O Wins the Game!");
        _fTieGameMsg =catgets(nlsCat, T3_MSG_SET, T3_TIEGAME, "Tie Game!");

        // Initialize theWelcoming message and Status Message
        _fTicTacToeMsg=catgets(nlsCat, T3_MSG_SET, T3_TTTANYONE, "TicTacToe Anyone!");
        _fStatusMsg=_fTicTacToeMsg;

        // Initialize Game Tokens based on Locale
        _fXToken=catgets(nlsCat, T3_MSG_SET, T3_XTOKEN, "X");
        _fOToken=catgets(nlsCat, T3_MSG_SET, T3_OTOKEN, "O");




         //-------//   Create MenuBar for T3GamePart Part   //------//

#if 0
        _fMenuBar = somSelf->GetStorageUnit(ev)
                           ->GetSession(ev)
                           ->GetWindowState(ev)->CopyBaseMenuBar(ev);

        _fMenuBar->Acquire(ev);

        // add GAME menu to MenuBar line
        ODPlatformMenu newMenu = (ODPlatformMenu)CreateMenu();
        ODPlatformMenuItem *mi = new ODPlatformMenuItem;

        mi->id=kODGameMenuID;
        _fMenuBar->AddMenuLast(ev, kODGameMenuID, newMenu, _fPartWrapper);

        mi->afAttribute=0;                      //  use default attributes

        // add NEWGAME selection item to GAME menu
        mi->id=CMD(NewGame);
        _fMenuBar->AddMenuItemLast(ev, kODGameMenuID, kODNULL, mi);
        nlsText=catgets(nlsCat, T3_MSG_SET, T3_NEWGAME, "NewGame");
        _fMenuBar->SetMenuItemText(ev, kODGameMenuID, mi->id, nlsText);

        // add QUITGAME selection item to GAME menu
        mi->id=CMD(QuitGame);
        _fMenuBar->AddMenuItemLast(ev, kODGameMenuID, kODNULL, mi);
        nlsText=catgets(nlsCat, T3_MSG_SET, T3_QUITGAME, "QuitGame");
        _fMenuBar->SetMenuItemText(ev, kODGameMenuID, mi->id, nlsText);


        // we can now release the MenuBar
        _fMenuBar->Release(ev);

        delete mi;                      // cleanup menuitem buffer
#endif
        catclose(nlsCat);               // close the message catalog


    }
    catch(...)
    {
    }

} // T3GamePartInitialize()



/*
*******************************************************************
** Name: void ReadContents
**
** Class:        SOM class T3GamePart
**
** Description:  The ReadContents method retrieves a suspended
**               game from Bento storage.
**
**
*******************************************************************
*/

SOM_Scope void  SOMLINK T3GamePartReadContents(T3GamePart *somSelf,
                                                Environment *ev,
                                               ODStorageUnit* fromSU,
                                               BCCloneInfo* cloneInfo,
                                               BCTransferKind readKind)
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartReadContents");


    try
    {
        // call parent's ReadContents
        T3GamePart_parent_BaseContainer_ReadContents(somSelf, ev,
                                                     fromSU, cloneInfo,
                                                     readKind);

        long xMap;
        long oMap;

        if ( fromSU->Exists(ev, kODPropContents, kT3PropXMap, 0) )
        {
            fromSU->Focus(ev, kODPropContents, kODPosUndefined, kT3PropXMap, 0, kODPosUndefined);
            StorageUnitGetValue(fromSU, ev, sizeof(long), (ODValue)&xMap);

            _fGameModel->SetXMap(xMap);
        }

        if ( fromSU->Exists(ev, kODPropContents, kT3PropOMap, 0) )
        {
            fromSU->Focus(ev, kODPropContents, kODPosUndefined, kT3PropOMap, 0, kODPosUndefined);
            StorageUnitGetValue(fromSU, ev, sizeof(long), (ODValue)&oMap);

            _fGameModel->SetOMap(oMap);
        }

    }
    catch(...)
    {
    }


} // T3GamePartReadContents()


/*
*******************************************************************
** Name: void WriteContents
**
** Class:        SOM class T3GamePart
**
** Description:  The WriteContents method writes out TicTacToe
**               info for suspended games.
**
*******************************************************************
*/

SOM_Scope void  SOMLINK T3GamePartWriteContents(T3GamePart *somSelf,
                                                 Environment *ev,
                                                ODStorageUnit* toSU,
                                                BCCloneInfo* cloneInfo,
                                                BCTransferKind writeKind)
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart", "T3GamePartWriteContents");

    try
    {
        // call parent's WriteContents
        T3GamePart_parent_BaseContainer_WriteContents(somSelf, ev,
                                                      toSU, cloneInfo,
                                                      writeKind);
        long xMap= _fGameModel->GetXMap();
        long oMap= _fGameModel->GetOMap();

        // Ensure an XMap property is present
        if (!toSU->Exists(ev, kODPropContents, kT3PropXMap, 0) )
             toSU->AddProperty(ev,kODPropContents)->AddValue(ev,kT3PropXMap);

        // Write the XMap value to storage
        toSU->Focus(ev, kODPropContents, kODPosUndefined, kT3PropXMap, 0, kODPosUndefined);
        StorageUnitSetValue(toSU, ev, sizeof(long), (ODValue) &xMap);

        // Ensure an OMap property is present
        if (!toSU->Exists(ev, kODPropContents, kT3PropOMap, 0) )
             toSU->AddProperty(ev,kODPropContents)->AddValue(ev,kT3PropOMap);

        // Write the OMap value to storage
        toSU->Focus(ev, kODPropContents, kODPosUndefined, kT3PropOMap, 0, kODPosUndefined);
        StorageUnitSetValue(toSU, ev, sizeof(long), (ODValue) &oMap);

    }
    catch(...)
    {
    }


} // T3GamePartWriteContents()

/*
*******************************************************************
**
** Name: ODBoolean HandleMenuEvent ( T3GamePart      *somSelf,
**                                   Environment     *ev,
**                                   ODFrame         *frame,
**                                   ODEventData     *event )
**
** Class:        SOM class T3GamePart
**
** Description:  Handles menu commands
**                  N   -- New Game
**                  Q   -- Quit Game
**
** Parameters:   T3GamePart      *somSelf,       // in
**               Environment     *ev,            // in
**               ODFrame         *frame,         // in
**               ODEventData     *event          // in
**
**
** Returns:      ODBoolean kODTrue -- Event handled
**                         kODFalse -- Event not handled
**
**
*******************************************************************
*/
SOM_Scope       ODBoolean
SOMLINK         T3GamePartHandleMenuEvent
                (
                T3GamePart      *somSelf,       // in
                Environment     *ev,            // in
                ODFrame         *frame,         // in
                ODEventData     *event          // in
                )
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartHandleMenuEvent");

    ODBoolean   eventHandled     = kODFalse;

    try
    {


        switch(LOWORD(event->wParam)) // determine which menu pulldown it was
        {
            case CMD(NewGame):
                 _fGameModel->MakeAMove('N');
                 eventHandled=kODTrue;
                 break;

            case CMD(QuitGame):
                 _fGameModel->MakeAMove('Q');
                 eventHandled=kODTrue;
                 break;

            default:
                 eventHandled=T3GamePart_parent_BaseContainer_HandleMenuEvent(somSelf,ev,frame,event);
                 break;

        } // endswitch which menu pulldown?


    }
    catch(...)
    {
    }

    return eventHandled;

} // T3GamePartHandleMenuEvent()



// ---- HasExtension ----------------------------------------------------
//
// Description:   The HasExtension method is queried by other parts to
//                see what "extensions" are available. For the T3GamePart
//                the WhoAmI, WonByX, and WonByO methods can be called to
//                update the container's gameboard.
//


SOM_Scope       ODBoolean
SOMLINK         T3GamePartHasExtension
                (
                T3GamePart      *somSelf,       // in
                Environment     *ev,            // in
                ODType          extName         // in
                )

{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartHasExtension");

    ODBoolean doWeHandleIt;

    if(strcmp(extName,kT3GameExtension)==0) {
      doWeHandleIt=kODTrue;
      }
    else {
      // call parent's method after you're finished and before you exit
      doWeHandleIt=T3GamePart_parent_BaseContainer_HasExtension(somSelf,ev,extName);
      }

    return doWeHandleIt;
}


// -------------------------------------------------------------------------
// -----                                                               -----
// -----                  T3GamePart    Class                          -----
// -----                                                               -----
// -----              T3GamePart Specific  Methods                     -----
// -----                                                               -----
// -------------------------------------------------------------------------


/*
*******************************************************************
** Name: short WhoAmI ( T3GamePart *somSelf, Environment *ev )
**
** Class:        SOM class T3GamePart
**
** Description:  Description of this function.
**
** Parameters:   T3GamePart      *somSelf,       // in
**               Environment     *ev,            // in
**
** Returns:      This method is called by the embedded game part to
**               determine which square it owns in the containing
**               game.
**
*******************************************************************
*/
SOM_Scope       short
SOMLINK         T3GamePartWhoAmI
                (
                T3GamePart      *somSelf,       // in
                Environment     *ev             // in
                )
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartWhoAmI");



    return _fGameSquare;

} // T3GamePartWhoAmI()


/*
*******************************************************************
** Name: void WonByX ( T3GamePart *somSelf, Environment *ev,
**                     short       winningSquare )
**
** Class:        SOM class T3GamePart
**
** Description:  This method is called by the embedded game part to
**               tell the containing game part that X has won the
**               square.
**
** Parameters:   T3GamePart      *somSelf,       // in
**               Environment     *ev,            // in
**               short           winningSquare   // in
**
** Returns:      none
**
*******************************************************************
*/
SOM_Scope       void
SOMLINK         T3GamePartWonByX
                (
                T3GamePart      *somSelf,       // in
                Environment     *ev,            // in
                short           winningSquare   // in
                )
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartWonByX");



    _fGameModel->SetXMove(winningSquare);
} // T3GamePartWonByX()


/*
*******************************************************************
** Name: void WonByO ( T3GamePart *somSelf, Environment *ev,
**                     short       winningSquare )
**
** Class:        SOM class T3GamePart
**
** Description:  This method is called by the embedded game part to
**               tell the containing game part that O has won the
**               square.
**
** Parameters:   T3GamePart      *somSelf,       // in
**               Environment     *ev,            // in
**               short           winningSquare   // in
**
** Returns:      none
**
*******************************************************************
*/
SOM_Scope       void
SOMLINK         T3GamePartWonByO
                (
                T3GamePart      *somSelf,       // in
                Environment     *ev,            // in
                short           winningSquare   // in
                )
{
    T3GamePartData *somThis = T3GamePartGetData(somSelf);
    T3GamePartMethodDebug("T3GamePart","T3GamePartWonByO");

    _fGameModel->SetOMove(winningSquare);

} // T3GamePartWonByX()



// -------------------------------------------------------------------------
// -----                                                               -----
// -----                T3GamePart    MetaClass                        -----
// -----                                                               -----
// -----              Overriding Inherited Methods                     -----
// -----                                                               -----
// -------------------------------------------------------------------------



/*
*******************************************************************
** Name: ISOstring clsGetODPartHandlerName( M_T3GamePart *somSelf,
**                                  Environment *ev )
**
** Class:        SOM class M_T3GamePart
**
** Description:   Returns the T3GamePart internal Part Handler name.
**                Gets name from global konstant: kPartHandlerName.
**
** Parameters:   M_T3GamePart *somSelf;    // in
**               Environment *ev;          // in
**
** Returns:      Returns an allocated ISOstring containing the
**               part handler name.
**
** Caution:      The returned ISOstring is allocated in this routine.
**
*******************************************************************
*/

SOM_Scope       ISOString
SOMLINK         M_T3GamePartclsGetODPartHandlerName
                (
                M_T3GamePart    *somSelf,       // in
                Environment *ev                 // in
                )

{
//  M_T3GamePartData *somThis = M_T3GamePartGetData(somSelf);
    M_T3GamePartMethodDebug("M_T3GamePart","M_T3GamePartclsGetODPartHandlerName");


    string handlerName = (string)SOMMalloc(strlen(kPartHandlerName)+1);
    strcpy(handlerName,kPartHandlerName);


    return (ISOString) handlerName;

} // M_T3GamePartclsGetODPartHandlerName()



/*
*******************************************************************
** Name: string clsGetODPartHandlerDisplayName( M_T3GamePart *somSelf,
**                                  Environment *ev )
**
** Class:        SOM class M_T3GamePart
**
** Description:  Defines and returns the T3GamePart displayable name.
**               Gets the name from global konstant: kPartHandlerName.
**
** Parameters:   M_T3GamePart *somSelf;    // in
**               Environment *ev;          // in
**
** Returns:      Returns an allocated string containing the
**               part handler display name.
**
** Caution:      The return string is allocated in this routine.
**
*******************************************************************
*/
SOM_Scope       string
SOMLINK         M_T3GamePartclsGetODPartHandlerDisplayName
                (
                M_T3GamePart    *somSelf,       // in
                Environment *ev                 // in
                )
{
//  M_T3GamePartData *somThis = M_T3GamePartGetData(somSelf);
    M_T3GamePartMethodDebug("M_T3GamePart","M_T3GamePartclsGetODPartHandlerDisplayName") ;



    string displayName = (string)SOMMalloc(strlen(kPartHandlerName)+1);
    strcpy(displayName,kPartHandlerName);

    return displayName;

} // M_T3GamePartclsGetODPartHandlerDisplayName()



/*
*******************************************************************
** Name:         _IDL_SEQUENCE_PartKindInfo clsGetODPartKinds
**                ( M_T3GamePart *somSelf, Environment *ev )
**
** Class:        SOM class M_T3GamePart
**
** Description:  Queries the OpenDoc registry for PartKind info.
**               Information is taken from these global konstants
**               kPartKindName, kPartKindDisplayName, kPartCategory.
**
** Parameters:   M_T3GamePart *somSelf;    // in
**               Environment *ev;          // in
**
** Returns:      Returns allocated partkind info.
**
** Cautions:     This routine allocates memory for the returned
**               partkindinfo structure and its member variables.
**
*******************************************************************
*/

SOM_Scope       _IDL_SEQUENCE_PartKindInfo
SOMLINK         M_T3GamePartclsGetODPartKinds
                (
                M_T3GamePart    *somSelf,       // in
                Environment *ev                 // in
                )
{
//  M_T3GamePartData *somThis = M_T3GamePartGetData(somSelf);
    M_T3GamePartMethodDebug("M_T3GamePart","M_T3GamePartclsGetODPartKinds");



    _IDL_SEQUENCE_PartKindInfo partKindInfo;

    // Create structure PartKindInfo  and allocate memory for its fields
    PartKindInfo * info       =  (PartKindInfo *)SOMMalloc(sizeof(PartKindInfo));
    info->partKindName        =  (ISOString) SOMMalloc(strlen(kPartKindName) + 1);
    info->partKindDisplayName =  (string)SOMMalloc(strlen(kPartKindDisplayName)+1);
    info->filenameFilters     =  (string)SOMMalloc(strlen("")+1);
    info->filenameTypes       =  (string)SOMMalloc(strlen("")+1);
    info->categories          =  (string)SOMMalloc(strlen(kPartCategory)+1);
    info->categoryDisplayName =  (string)SOMMalloc(strlen(kPartCategory)+1);
    info->objectID            =  (string)SOMMalloc(strlen("")+1);

    // Copy the information into the structure
    strcpy(info->partKindName , kPartKindName);
    strcpy(info->partKindDisplayName, kPartKindDisplayName);
    strcpy(info->filenameFilters, "");
    strcpy(info->filenameTypes, "");
    strcpy(info->categories, kPartCategory);
    strcpy(info->categoryDisplayName, kPartCategory);
    strcpy(info->objectID, "");

    partKindInfo._maximum = 1;
    partKindInfo._length = 1;
    partKindInfo._buffer = info;



    return partKindInfo;

} // M_T3GamePartclsGetODPartKinds()



/*
*******************************************************************
** Name: string clsGetOLE2ClassId ( M_T3GamePart *somSelf,
**                                  Environment *ev )
**
** Class:        SOM class M_T3GamePart
**
** Description:  Returns the OLE2 Class ID defined for this part.
**
** Parameters:   M_T3GamePart *somSelf;    // in
**               Environment *ev;          // in
**
** Returns:      Returns an allocated string containing the
**               OLE2 Class ID defined for this part.
**
** Caution:      The return string is allocated in this routine.
**
*******************************************************************
*/
SOM_Scope       string
SOMLINK         M_T3GamePartclsGetOLE2ClassId
                (
                M_T3GamePart    *somSelf,       // in
                Environment *ev                 // in
                )
{
//  M_T3GamePartData *somThis = M_T3GamePartGetData(somSelf);
    M_T3GamePartMethodDebug("M_T3GamePart","M_T3GamePartclsGetOLE2ClassId");


    // OLE2 Class ID is determined by running the tool UUIDGEN.EXE
    // found in the IBM VAC++ %CPPMAIN%\SDK\BIN directory
    // this tool is guaranteed to generate a unique ID based on your
    // network address and the time of day (DCE Standard)


    char *kID = "{e3a54f70-c6db-11cf-b419-08005ac0e889}";

    string OLE2ClassID = (string)SOMMalloc(strlen(kID)+1);
    strcpy(OLE2ClassID,kID);



    return OLE2ClassID;

} // M_T3GamePartclsGetOLE2ClassId()



/*
*******************************************************************
** Name: string clsGetWindowsIconFileName ( M_T3GamePart *somSelf,
**                                          Environment *ev )
**
** Class:        SOM class M_T3GamePart
**
** Description:  Returns the Windows Icon Filename defined for this
**               part.
**
** Parameters:   M_T3GamePart *somSelf;    // in
**               Environment *ev;          // in
**
** Returns:      Returns the Windows Icon Filename defined for this
**               part.
**
**
*******************************************************************
*/

SOM_Scope       string
SOMLINK         M_T3GamePartclsGetWindowsIconFileName
                (
                M_T3GamePart    *somSelf,       // in
                Environment *ev                 // in
                )
{
//  M_T3GamePartData *somThis = M_T3GamePartGetData(somSelf);
    M_T3GamePartMethodDebug("M_T3GamePart","M_T3GamePartclsGetWindowsIconFileName");

    string windowsIcon = (string)SOMMalloc(strlen(kWindowsIcon)+1);
    strcpy(windowsIcon,kWindowsIcon);

    return windowsIcon;

} // M_T3GamePartclsGetWindowsIconFileName()
