/* @(#) 1.4 com/src/samples/piano/iodpiano.cpp, odpianopart, od96nt, odnt9712d 11/1/96 21:00:42 [3/21/97 17:38:16] */
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odother
//
//   CLASSES: none
//
//   ORIGINS: 82,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========================================
//
// ---- Piano Part --------------------------------------------------------
//
//
//

#ifndef OpenDoc_Sample_PianoPart
#include "iodpiano.h"
#endif

// The PianoModel class maintains the state of the piano keys

// Constructors / Destructors

PianoModel::PianoModel() : fState(CMD(QuarterNote)) { }
PianoModel::PianoModel(const PianoModel& model)     { }
PianoModel::~PianoModel()                           { }


// Getters and Setters
// used to save/restore the PianoModel
   short PianoModel::GetState(void)             { return fState; }
   void PianoModel::SetState(short state)       { fState=state; }




// -------------------------------------------------------------------------
// -----                                                               -----
// -----                  PianoPart    Class                          -----
// -----                                                               -----
// -----              Overriding Inherited Methods                     -----
// -----                                                               -----
// -------------------------------------------------------------------------




// ---- somInit ------------------------------------------------------------
//
//      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 PianoPartsomInit(PianoPart *somSelf)
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart","PianoPartsomInit");

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

    //  (2) initialize PianoPart attributes
    _fSession         = kODNULL;
    _fMenuBar         = kODNULL;
    _fStatusMsg       = kODNULL;

}




// ---- somUninit -------------------------------------------------------
//
//      Disposes of storage for the SOMObject of this part.
//
//      -> optional for all parts
//      -> somUninit must NOT fail



SOM_Scope       void
SOMLINK         PianoPartsomUninit
                (
                PianoPart   *somSelf        // in
                )
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart","PianoPartsomUninit");

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

}



// ---- HandleMouseDown --------------------------------------------------
//
// Description:   The HandleMouseDown method receives mouse-down events
//                and saves the point of where it occurred. Using
//                the facet dimensions, HandleMouseDown determines
//                which piano key was selected on the keyboard.
//


SOM_Scope       ODBoolean
SOMLINK         PianoPartHandleMouseDown
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODEventData     *event,         // in
                ODFrame         *frame,         // in
                ODFacet         *facet,         // in
                ODEventInfo     *eventInfo      // inout
                )
{
   PianoPartData *somThis = PianoPartGetData(somSelf);
   PianoPartMethodDebug("PianoPart","PianoPartHandleMouseDown");

   ODBoolean   eventHandled     = kODTrue;

   static  char  keyPressedMsg[256];

   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 the piano keyboard
         int xBox = (winRect.right  - winRect.left) / (_fWhiteKeys+2.0);
         int yBox = (winRect.bottom - winRect.top)  * 0.25;

         // xBoxMax is used to check if xMove is outside keyboard on right
         int  xBoxMax  = _fKeyWidth * _fWhiteKeys;

         // 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 piano key
         int  xMove    = ODFixedRound(mousePt.x) - xBox;
         int  yMove    = ODFixedRound(mousePt.y) - yBox;


         if ( xMove < 0 ) {
             // send backup command to StaffPart
             somSelf->ToStaffPart(ev, frame, CMD(BackupOne), 0, 0);
             _fStatusMsg="Backup One Note";
             }

         else if ( xMove > xBoxMax ) {
             // send skip forward command to StaffPart
             somSelf->ToStaffPart(ev, frame, CMD(SkipFwdOne), 0, 0);
             _fStatusMsg="Skip Forward One Note";
             }

         else if ( yMove < 0 ) {
             // send a rest command to StaffPart
             somSelf->ToStaffPart(ev, frame, CMD(RestSome), _fPianoModel->GetState(), 0);
             _fStatusMsg="Rest One Note";
             }

         else if( xMove>0 && yMove>0 ) {
             // send a note + key value to StaffPart
             int blackKey = _fKeyLength *0.60 + _fKeyWidth * 0.25;

             if( yMove < blackKey ) {
                 // we need to check if its a black key
                 _fKeyPressed  = (xMove + 0.0) / _fKeyWidth + 0.5;
                 _fKeyPressed--;

                 if( _fKeyPressed < 0 ) _fKeyPressed=0;

                 switch(_fKeyPressed%7) {
                   case 2: _fKeyPressed=0; break;   // no key between E/F
                   case 6: _fKeyPressed=0; break;   // no key between B/C

                   default:  // black keys are odd
                           _fKeyPressed = _fKeyPressed*2 + 1;
                           break;
                   }
                 }

             if(_fKeyPressed==0) {
                 // determine what white key was struck
                 _fKeyPressed = (xMove + 0.0) / _fKeyWidth;
                 _fKeyPressed = _fKeyPressed * 2;   // white keys are even
                 }

             sprintf(keyPressedMsg,"Key%02d.wav", _fKeyPressed);
             _fStatusMsg=keyPressedMsg;
             PlaySound( keyPressedMsg, NULL, (SND_LOOP | SND_ASYNC | SND_FILENAME) );
             somSelf->ToStaffPart(ev,  frame, CMD(OneNote), _fPianoModel->GetState(), _fKeyPressed);
             }

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

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

      else
         eventHandled=kODFalse;

    }
    catch(...)
    {
    }

    return eventHandled;

}



// ---- HandleMouseUp ----------------------------------------------------
//
// Description:   The HandleMouseUp method receives mouse-up events
//                and saves the point of where it occurred. The Piano
//                Part's HandleMouseUp indicates that a piano key is
//                no longer being pressed.
//


SOM_Scope       ODBoolean
SOMLINK         PianoPartHandleMouseUp
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODEventData     *event,         // in
                ODFrame         *frame,         // in
                ODFacet         *facet,         // in
                ODEventInfo     *eventInfo      // inout
                )
{
   PianoPartData *somThis = PianoPartGetData(somSelf);
   PianoPartMethodDebug("PianoPart","PianoPartHandleMouseUp");

   ODBoolean   eventHandled     = kODTrue;

   try
   {
      if ( facet != kODNULL && somSelf->ActivateFrame(ev, frame))
      {
          _fKeyPressed=0;
          PlaySound(NULL,NULL,NULL);    // turn off the sound
          eventHandled=PianoPart_parent_BaseContainer_HandleMouseUp(somSelf, ev,
                             event,frame, facet, eventInfo);

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

      else
         eventHandled=kODFalse;

    }
    catch(...)
    {
    }

    return eventHandled;

}



// ---- Draw ------------------------------------------------------------
//
//      The Draw method is called each time the screen needs to be redrawn
//      either due to resizing, window overlap, or update calls.
//
//

SOM_Scope       void
SOMLINK         PianoPartDraw
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODFacet         *facet,         // in
                ODShape         *invalidShape   // in
                )
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart","PianoPartDraw");


    try
    {
        PianoPart_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));


            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 BLACK brush
            HBRUSH hbr;
            hbr=CreateSolidBrush(RGB(0,0,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, 0x0000FFFF);

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

            // Restore the old font settings
            SelectObject(hdc, hOldFont);
            DeleteObject(hFont);

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

            // Compute the keyboard dimensions
            _fKeyWidth  = (frameRect.right  - frameRect.left)/(_fWhiteKeys+2.0);    // + 2 for border
            _fKeyLength = (frameRect.bottom - frameRect.top) * 0.75;

            frameRect.left  += _fKeyWidth;
            frameRect.top    = frameRect.bottom - _fKeyLength;
            frameRect.right -= _fKeyWidth;

            // Create a solid WHITE brush
            hbr=CreateSolidBrush(RGB(255,255,255));

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

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

            HPEN hPen, hOldPen;

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

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

            for(int i=0; i<_fWhiteKeys; i++) {

                // draw the Key Spacers
                int keyOffset = frameRect.left + i*_fKeyWidth;
                POINT vLine[] = { {keyOffset, frameRect.top},
                                  {keyOffset, frameRect.bottom} };
                Polyline(hdc,vLine,2);
                }


            // restore Old Pen settings
            SelectObject(hdc, hOldPen);
            DeleteObject(hPen);

            // Create a thick  BLACK pen
            int keyWidth = _fKeyWidth - 4;
            hPen=CreatePen(PS_SOLID, keyWidth, RGB(0,0,0));

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

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

                // draw the BLACK keys
                if((i%7)==3 || (i%7)==0) continue;

                int keyOffset = frameRect.left + i*_fKeyWidth;
                int keyDescend = frameRect.top + _fKeyLength*0.60;

                POINT vLine[] = { {keyOffset, frameRect.top},
                                  {keyOffset, keyDescend} };
                Polyline(hdc,vLine,2);
                }


            // restore Old Pen settings
            SelectObject(hdc, hOldPen);
            DeleteObject(hPen);

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

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

            // draw the horizontals
            POINT hLine[] = { {frameRect.left,  frameRect.top},
                              {frameRect.right, frameRect.top} };

            Polyline(hdc,hLine,2);

            // restore Old Pen Settings
            SelectObject(hdc,hOldPen);
            DeleteObject(hPen);

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


    }
    catch(...)
    {
    }


}




// ---- Initialize -----------------------------------------------------
//
//      The Initialize method is called each time a Piano is first started
//      in OpenDoc. It creates the PIANO menu and calls its parent to
//      create the part embedding menu.
//
//


SOM_Scope       void
SOMLINK         PianoPartInitialize
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODPart          *partWrapper    // in
                )
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart", "PianoPartInitialize");


    try
    {

        // call the parent to initialize the Container features
        PianoPart_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(PP_NLS_CATALOG, NL_CAT_LOCALE);

        // Initialize Game Engine
        _fPianoModel = new PianoModel();


        // Initialize the Piano message and Status Message
        _fPianoMsg=catgets(nlsCat, PP_MSG_SET, PP_PIANO_TITLE, "I B M");
        _fStatusMsg=_fPianoMsg;


        _fOctaves=4;
        _fWhiteKeys= _fOctaves * 7 ;


         //-------//   Create MenuBar for PianoPart Part   //------//

        _fMenuBar = somSelf->GetMenuBar(ev);

        _fMenuBar->Acquire(ev);

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

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

        mi->afAttribute=0;                      //  use default attributes
        _fMenuBar->SetMenuItemText(ev, ID_BASEMENUBAR, mi->id, "Piano");

        // add WHOLE NOTE selection item to Piano menu
        mi->id=CMD(WholeNote);
        _fMenuBar->AddMenuItemLast(ev, kODPianoMenuID, kODNULL, mi);
        nlsText=catgets(nlsCat, PP_MSG_SET, PP_WHOLENOTE, "Whole Note");
        _fMenuBar->SetMenuItemText(ev, kODPianoMenuID, mi->id, nlsText);

        // add HALF NOTE selection item to Piano menu
        mi->id=CMD(HalfNote);
        _fMenuBar->AddMenuItemLast(ev, kODPianoMenuID, kODNULL, mi);
        nlsText=catgets(nlsCat, PP_MSG_SET, PP_PLAYSONG, "1/2 Note");
        _fMenuBar->SetMenuItemText(ev, kODPianoMenuID, mi->id, nlsText);

        // add QUARTER NOTE selection item to Piano menu
        mi->id=CMD(QuarterNote);
        _fMenuBar->AddMenuItemLast(ev, kODPianoMenuID, kODNULL, mi);
        nlsText=catgets(nlsCat, PP_MSG_SET, PP_QUARTERNOTE, "1/4 Note");
        _fMenuBar->SetMenuItemText(ev, kODPianoMenuID, mi->id, nlsText);

        // add EIGHTH NOTE selection item to Piano menu
        mi->id=CMD(EighthNote);
        _fMenuBar->AddMenuItemLast(ev, kODPianoMenuID, kODNULL, mi);
        nlsText=catgets(nlsCat, PP_MSG_SET, PP_EIGHTHNOTE, "1/8 Note");
        _fMenuBar->SetMenuItemText(ev, kODPianoMenuID, mi->id, nlsText);


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

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


    }
    catch(...)
    {
    }

}




// ---- ReadContents -------------------------------------------------
//
//

SOM_Scope       void
SOMLINK         PianoPartReadContents
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODStorageUnit   *fromSU,        // in
                BCCloneInfo     *cloneInfo,     // in
                BCTransferKind  readKind        // in
                )
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart","PianoPartReadContents");


    short state;


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

        if ( fromSU->Exists(ev, kODPropContents, kPianoProp, 0) )
        {
            fromSU->Focus(ev, kODPropContents, kODPosUndefined, kPianoProp, 0, kODPosUndefined);
            StorageUnitGetValue(fromSU, ev, sizeof(short), (ODValue)&state );

            _fPianoModel->SetState(state);
        }

    }
    catch(...)
    {
    }


}



// ---- WriteContents -------------------------------------------------
//
//

SOM_Scope       void
SOMLINK         PianoPartWriteContents
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODStorageUnit   *toSU,          // in
                BCCloneInfo     *cloneInfo,     // in
                BCTransferKind  writeKind       // in
                )
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart", "PianoPartWriteContents");


    short state;

    try
    {
        // call parent's WriteContents
        PianoPart_parent_BaseContainer_WriteContents(somSelf, ev,
                                                      toSU, cloneInfo,
                                                      writeKind);
        // Ensure an XMap property is present
        if (!toSU->Exists(ev, kODPropContents, kPianoProp, 0) )
             toSU->AddProperty(ev,kODPropContents)->AddValue(ev,kPianoProp);

        // Write the XMap value to storage
        state=_fPianoModel->GetState();
        toSU->Focus(ev, kODPropContents, kODPosUndefined, kPianoProp, 0, kODPosUndefined);
        StorageUnitSetValue(toSU, ev, sizeof(short), (ODValue) &state);

    }
    catch(...)
    {
    }


}



// ---- HandleMenuEvent ---------------------------------------------------
//
//

SOM_Scope       ODBoolean
SOMLINK         PianoPartHandleMenuEvent
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODFrame         *frame,         // in
                ODEventData     *event          // in
                )
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart","PianoPartHandleMenuEvent");

    ODBoolean   eventHandled     = kODFalse;

    try
    {


        switch(LOWORD(event->wParam)) // determine which menu pulldown it was
        {
            case CMD(WholeNote):
            case CMD(HalfNote):
            case CMD(QuarterNote):
            case CMD(EighthNote):
                 _fPianoModel->SetState(LOWORD(event->wParam));
                 eventHandled=kODTrue;
                 break;

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

        } // endswitch which menu pulldown?


    }
    catch(...)
    {
    }

    return eventHandled;

}




// -------------------------------------------------------------------------
// -----                                                               -----
// -----                  PianoPart    Class                           -----
// -----                                                               -----
// -----              PianoPart Specific  Methods                      -----
// -----                                                               -----
// -------------------------------------------------------------------------




// ---- ToStaffPart --------------------------------------------------------
//
//      ToStaffPart sends Piano commands to the containing StaffPart
//      document. StaffPart will in turn edit its song buffer.
//
//

SOM_Scope       void
SOMLINK         PianoPartToStaffPart
                (
                PianoPart       *somSelf,       // in
                Environment     *ev,            // in
                ODFrame         *frame,         // in
                short           cmd,            // in
                short           noteType,       // in
                short           whatKey         // in
                )
{
    PianoPartData *somThis = PianoPartGetData(somSelf);
    PianoPartMethodDebug("PianoPart","PianoPartToStaffPart");


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

            // OpenDoc returns an ODPartWrapper pointer
            // You need to dereference it to get a pointer to the
            // real part's dll so you can call methods that aren't
            // available in the ODPartWrapper (mimics ODPart)

            if(cp->HasExtension(ev,kStaffExtension)) {
              StaffPart *sp = (StaffPart *)cp->GetRealPart(ev);
              sp->ToStaffPart(ev, cf, cmd, noteType, whatKey);
              cp->ReleaseRealPart(ev);
              }
            }



    }
    catch(...)
    {
    }

}



// -------------------------------------------------------------------------
// -----                                                               -----
// -----                PianoPart    MetaClass                         -----
// -----                                                               -----
// -----              Overriding Inherited Methods                     -----
// -----                                                               -----
// -------------------------------------------------------------------------



// ---- clsGetODPartHandlerName --------------------------------------------
//
//

SOM_Scope       ISOString
SOMLINK         M_PianoPartclsGetODPartHandlerName
                (
                M_PianoPart     *somSelf,       // in
                Environment     *ev             // in
                )

{
//  M_PianoPartData *somThis = M_PianoPartGetData(somSelf);
    M_PianoPartMethodDebug("M_PianoPart","M_PianoPartclsGetODPartHandlerName");


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


    return (ISOString) handlerName;

}



// ---- clsGetODPartHandlerDisplayName ------------------------------------
//
//

SOM_Scope       string
SOMLINK         M_PianoPartclsGetODPartHandlerDisplayName
                (
                M_PianoPart     *somSelf,       // in
                Environment     *ev             // in
                )
{
//  M_PianoPartData *somThis = M_PianoPartGetData(somSelf);
    M_PianoPartMethodDebug("M_PianoPart","M_PianoPartclsGetODPartHandlerDisplayName") ;



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

    return displayName;

}



// ---- clsGetODPartKinds -------------------------------------------------
//
//

SOM_Scope       _IDL_SEQUENCE_PartKindInfo
SOMLINK         M_PianoPartclsGetODPartKinds
                (
                M_PianoPart     *somSelf,       // in
                Environment     *ev             // in
                )
{
//  M_PianoPartData *somThis = M_PianoPartGetData(somSelf);
    M_PianoPartMethodDebug("M_PianoPart","M_PianoPartclsGetODPartKinds");



    _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;

}



// ---- clsGetOLE2ClassId -------------------------------------------------
//
//

SOM_Scope       string
SOMLINK         M_PianoPartclsGetOLE2ClassId
                (
                M_PianoPart     *somSelf,       // in
                Environment     *ev             // in
                )
{
//  M_PianoPartData *somThis = M_PianoPartGetData(somSelf);
    M_PianoPartMethodDebug("M_PianoPart","M_PianoPartclsGetOLE2ClassId");


    // 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 = "{cea8ea30-07fa-11d0-b476-08005ac0e889}";

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



    return OLE2ClassID;

}



// ---- clsGetWindowsIconFileName ----------------------------------------
//
//

SOM_Scope       string
SOMLINK         M_PianoPartclsGetWindowsIconFileName
                (
                M_PianoPart     *somSelf,       // in
                Environment     *ev             // in
                )
{
//  M_PianoPartData *somThis = M_PianoPartGetData(somSelf);
    M_PianoPartMethodDebug("M_PianoPart","M_PianoPartclsGetWindowsIconFileName");

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

    return windowsIcon;

}
