//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odtextpart
//
//   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========================================
//
// @(#) 1.38 com/src/samples/text/iodtext.cpp, odtextpart, od96nt, odnt9712d 3/7/97 13:03:11 [3/21/97 17:36:19]
/*
 *  This file was generated by the SOM Compiler and Emitter Framework.
 *  Generated using:
 *      SOM Emitter emitxtm.dll: Development
 */

#ifndef SOM_Module_textpart_Source
#define SOM_Module_textpart_Source
#endif

#define TextPart_Class_Source
#define M_TextPart_Class_Source

// Define VARIABLE_MACROS to use shorthand form _variablename for our
// instance variables.
#define VARIABLE_MACROS

#ifndef SOM_ODArbitrator_xh
#include <Arbitrat.xh>
#endif

#ifndef SOM_ODCanvas_xh
#include <Canvas.xh>
#endif

#ifndef SOM_ODDraft_xh
#include <Draft.xh>
#endif

#ifndef SOM_ODEmbeddedFramesIterator_xh
#include <EmbFrItr.xh>
#endif

#ifndef SOM_ODFacet_xh
#include <Facet.xh>
#endif

#ifndef SOM_ODFrameFacetIterator_xh
#include <FrFaItr.xh>
#endif

#ifndef SOM_Module_Foci_OpenDoc_Foci_defined
#include <Foci.xh>
#endif

#ifndef SOM_ODFrame_xh
#include <Frame.xh>
#endif

#ifndef SOM_ODMenubar_xh
#include <MenuBar.xh>
#endif

#ifndef SOM_ODSession_xh
#include <ODSessn.xh>
#endif

#ifndef SOM_ODShape_xh
#include <Shape.xh>
#endif

#ifndef SOM_ODStorageUnit_xh
#include <StorageU.xh>
#endif

#ifndef SOM_ODTransform_xh
#include <Trnsform.xh>
#endif

#ifndef SOM_ODWindow_xh
#include <Window.xh>
#endif

#ifndef SOM_ODWindowState_xh
#include <WinStat.xh>
#endif

#ifndef SOM_Module_xh5cStdTypes_OpenDoc_StdTypes_defined
#include <StdTypes.xh>
#endif

#include <StdProps.xh>

#ifndef _ODTYPESM_
#include <ODTypesM.xh>
#endif

#ifndef _ODMATH_
#include <odmath.h>
#endif

#if defined(_PLATFORM_WIN32_)

#ifndef SOM_ODWin32Canvas_xh
#include <WinPCanv.xh>
#endif

#endif // defined win32


#if defined(_PLATFORM_OS2_)

#ifndef SOM_ODOS2Canvas_xh
#include <OS2PCanv.xh>
#endif

#endif // defined OS2

#if defined(_PLATFORM_OS2_) || defined(_PLATFORM_WIN32_)
#ifndef SOM_ODScrollExtension_xh
#include <IODScrol.hpp>
#include <IODScrol.xh>
#endif
#endif

#include "iodtext.h"
#include "iodtext.xih"

// HELPER FUNCTIONS
inline void InitPropVal (Environment *ev, ODStorageUnit *su,
                         ODPropertyName propName, ODValueType valName)
{
    if (ODSUExistsThenFocus (ev, su, propName, valName))
         su->Remove (ev);

    ODSUAddPropValue (ev, su, propName, valName);

}


void WinPt2FramePt (Environment *ev, ODEventData *event, ODEventInfo *eventinfo,
                               ODPoint *cursorLocation, ODFacet *facet)
{

      TempODTransform xform = facet->AcquireWindowContentTransform(ev, kODNULL);
      cursorLocation->x = eventinfo->where.x;
      cursorLocation->y = eventinfo->where.y;

#ifdef ODDebug
      PRINT ("MouseClick before transform: (%d,%d).\n", cursorLocation->x, cursorLocation->y);
      PRINT ("MouseClick convert to integer: (%d,%d).\n", FixedToInt(cursorLocation->x), FixedToInt(cursorLocation->y));
#endif
      xform->InvertPoint (ev, cursorLocation);
#ifdef ODDebug
      PRINT ("MouseClick inverse of WindowContentTransform: (%d,%d).\n", cursorLocation->x, cursorLocation->y);
      PRINT ("MouseClick convert to integer: (%d,%d).\n", FixedToInt(cursorLocation->x), FixedToInt(cursorLocation->y));
#endif
}

SOM_Scope ODBoolean  SOMLINK TextPartImportFile(TextPart *somSelf,
                                                  Environment *ev,
                                                  ODFrame *frame)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartImportFile");
#ifdef ODDebug
    PRINT ("TextPart::ImportFile invoked.\n");
#endif

    ODBoolean result = kODFalse;
    char docName[kODMaxFileNameSize] = "";
    char* buffer = kODNULL;
    int dwBytesRead = 0;

  try {
    ODWindowState* WinStat =  _fSession->GetWindowState(ev);

    // Get our window handle, which will own the Import File Dialog
    // Use TempODWindow so this object won't have to be released.
#if defined(_PLATFORM_WIN32_)
    TempODWindow Window = WinStat->AcquireActiveWindow(ev);
#elif defined(_PLATFORM_OS2_)
    TempODWindow Window = WinStat->AcquireFrontRootWindow(ev);
#endif
    ODPlatformWindow hwnd = Window->GetPlatformWindow(ev);

    // Obtain the file name to import from the Import File Dialog
    if (PlatImportDlg(hwnd,docName))
      if (PlatReadFile(docName,buffer,dwBytesRead))
      {
         if (dwBytesRead > 0) {
            _fTextMgr->AddText(buffer, dwBytesRead);
            somSelf->ChangeNotification(ev, TP_TEXTCHANGED, frame,
                                        kODNULL, kODTrue, kODNULL);
         }
         result = kODTrue;
      }

    } catch(...) {
    }
      return result;
}

SOM_Scope ODBoolean  SOMLINK TextPartExportFile(TextPart *somSelf,
                                                  Environment *ev)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartExportFile");
#ifdef ODDebug
    PRINT ("TextPart::ExportFile invoked.\n");
#endif

    ODBoolean result = kODFalse;
    char docName[kODMaxFileNameSize] = "";
    char* buffer = kODNULL;
    int bufferSize = 0;

  try {
    // Get our window handle, which will own the Export File Dialog
    // Use TempODWindow so this object won't have to be released.
    ODWindowState* WinStat =  _fSession->GetWindowState(ev);
#if defined(_PLATFORM_WIN32_)
    TempODWindow Window = WinStat->AcquireActiveWindow(ev);
#elif defined(_PLATFORM_OS2_)
    TempODWindow Window = WinStat->AcquireFrontRootWindow(ev);
#endif
    ODPlatformWindow hwnd = Window->GetPlatformWindow(ev);

    // Export all of TextPart's intrinsic content.
    bufferSize = _fTextMgr->GetText(&buffer);

    // Obtain the file name to save to from the Export File Dialog
    if (PlatExportDlg(hwnd,docName))
      if (PlatWriteFile(docName,buffer,bufferSize))
         result = kODTrue;

  } catch(...) {}

    if (buffer != kODNULL) delete buffer;

    return result;
}

SOM_Scope ODShape* SOMLINK TextPartAcquireEmbeddedClipShape(TextPart *somSelf,
                                                  Environment *ev,
                                                  ODFacet* facet)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartAcquireEmbeddedClipShape");
#ifdef ODDebug
    PRINT ("TextPart::AcquireEmbeddedClipShape invoked.\n");
#endif

    ODShape* embedShape;
    ODTransform* embedTransform;

  try {
    ODShape* clipShape = facet->CreateShape(ev);

    // Iterate through the embedded objects
    ALinkedList* objList = somSelf->GetEmbeddedObjects(ev);
    ContentObject *theObj = kODNULL;
    ALink *link;
    for(link = objList->First(ev);
        (theObj = (ContentObject*) link->Content(ev)) != kODNULL ;
        link = link->Next(ev)) {

       // For each embedded frame, subtract its usedshape in the
       // containing frame coordinates.
       if (theObj->_get_objType(ev) == COBJ_FRAMECLASS) {
          ODFrame* embed = ((ContentFrame*) theObj)->_get_myFrame(ev);
          embedShape = ODCopyAndRelease(ev, embed->AcquireUsedShape(ev,kODNULL));

          ODFrameFacetIterator* facetIter = embed->CreateFacetIterator(ev);
          embedTransform = ODCopyAndRelease(ev, facetIter->First(ev)->AcquireExternalTransform(ev,kODNULL));
          embedShape->Transform(ev,embedTransform);
          ODDeleteObject(facetIter);
       } /* end if */
       else {
          embedShape = facet->CreateShape(ev);
          ODRect boundingRect = theObj->_get_boundingRect(ev);
          embedShape->SetRectangle(ev, &boundingRect);
       } /* end else */

       clipShape->Union(ev,embedShape);
       embedShape->Release(ev);
    } /* endfor */

    return clipShape;

  } catch(...) {
     return kODNULL;
  }
}

// Get the correctly transformed used shape from the given facet
SOM_Scope void  SOMLINK TextPartGetFacetBoundingRect(TextPart *somSelf, Environment *ev,
                                ODFacet *facet, ODRect *clipRect)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartGetFacetBoundingRect");
#ifdef ODDebug
//  PRINT ("TextPart::GetFacetBoundingRect invoked.\n");
#endif

try {
    ODFrame* displayFrame = facet->GetFrame(ev);
    TempODShape drawShape = displayFrame->AcquireUsedShape(ev, kODNULL);

    // Make sure we are drawing the portion of our content that is currently
    // scrolled into view (AcquireFrameShape returns shape in frame coordinates-
    // transform that into our content coordinates).
    if (_fScrollExt) {
       TempODTransform internalXform = displayFrame->AcquireInternalTransform(ev,kODNULL);
       drawShape->InverseTransform(ev, internalXform);
    } /* endif */

    // Get the bounding box of our used shape.  This is the area we will
    // draw in.
    drawShape->GetBoundingBox(ev, clipRect);

} catch(...) {}
}

SOM_Scope void  SOMLINK TextPartsomInit(TextPart *somSelf)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartsomInit");
#ifdef ODDebug
    PRINT ("TextPart::somInit invoked.\n");
#endif

    TextPart_parent_BaseContainer_somInit(somSelf);
    _fMenuBar = kODNULL;
    _fSession = kODNULL;
    _fKeyFocus = kODNULL;
    _fPartWrapper = kODNULL;
    _fDraftReadOnly = kODFalse;
    _fScrollExt = kODNULL;
    _fTextMgr = kODNULL;
}

SOM_Scope void  SOMLINK TextPartsomUninit(TextPart *somSelf)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartsomUninit");
#ifdef ODDebug
    PRINT ("TextPart::somUninit invoked.\n");
#endif

    TextPart_parent_BaseContainer_somUninit(somSelf);
    delete _fTextMgr;

}

//--------------------------------------------------------------------------
// ReleaseAll
//
// This method is called prior to the object destructor being invoked.
// It must release all references to other objects.  If we are the Factory
// for the object we should also ensure the object is properly deleted
//--------------------------------------------------------------------------

SOM_Scope       void
SOMLINK         TextPartReleaseAll
                (
                TextPart        *somSelf,       // in
                Environment     *ev             // in
                )
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartReleaseAll");

    //--------------------------------------------------------------------
    // Release the extension we acquired in the initialize routine.
    // Put it in a try/catch block in case of failure, but ignore the
    // error since we're leaving.
    //--------------------------------------------------------------------
    if (_fScrollExt) {
       try {
         _fScrollExt->Release(ev);
         _fScrollExt = kODNULL ;
       }
       catch (ODException _exception) {
          PRINT("SOM exception occurred in TextPart::ReleaseAll\n");
          // Clear the exception, in case we got one
          SetErrorCodeEv(ev, kODNoError);
       }
    }

    TextPart_parent_BaseContainer_ReleaseAll(somSelf, ev);

}


SOM_Scope void  SOMLINK TextPartInitialize(TextPart *somSelf,
                                           Environment *ev,
                                           ODPart *partWrapper)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartInitialize");
#ifdef ODDebug
    PRINT ("TextPart::Initialize invoked.\n");
#endif

try {

    TextPart_parent_BaseContainer_Initialize(somSelf, ev, partWrapper);

    // Enable scrolling, so that if our text falls outside the frame shape
    // scroll bars will appear.
    if ( somSelf->HasExtension(ev, kODScrollExtension)) {
      _fScrollExt = somSelf->AcquireExtension(ev, kODScrollExtension);
      somSelf->EnableScrolling(ev, kODTrue, 0, 0);
    }

    // Create our TextMgr to format the text content.
    _fTextMgr = new TextMgr(somSelf);

    // Cache references to Session object and other global values
    _fSession    =   somSelf->GetStorageUnit(ev)->GetSession(ev);
    _fKeyFocus = _fSession->Tokenize(ev, kODKeyFocus);
    _fPartWrapper = partWrapper;
    _fMenuBar = somSelf->GetMenuBar(ev);
    _fDraftReadOnly = (somSelf->GetStorageUnit(ev)->
                       GetDraft(ev)->GetPermissions(ev) == kODDPReadOnly);

    // Set the original background color to white.  Base Container over-
    // writes the value if it is preserved in our storage unit.
#if defined(_PLATFORM_WIN32_)
    somSelf->SetBackgroundColor(ev,0x00FFFFFF);
#elif defined(_PLATFORM_OS2_)
    somSelf->SetBackgroundColor(ev,CLR_WHITE);
#endif

    // No need to call InstallMenuItems since our parent calls it.

} catch (...) {}

}

SOM_Scope void  SOMLINK TextPartInitPartFromStorage(TextPart *somSelf,
                                           Environment       *ev,
                                           ODStorageUnit     *fromSU,
                                           ODPart            *partWrapper)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartInitPartFromStorage");
#ifdef ODDebug
    PRINT ("TextPart::InitPartFromStorage invoked.\n");
#endif

    TextPart_parent_BaseContainer_InitPartFromStorage(somSelf, ev,
                                                      fromSU,
                                                      partWrapper);
try {
    // No need to call Initialize since our parent calls it.

    // Read in the text and send it to the Text Manager to read.
    // This is only done only when part comes up.  Do it before the facet
    // is added so we can know whether to display the scrollbars.
    char* itextBuff = kODNULL;
    ODULong itextBuffSize;
    ODIText* iBuffer = new ODIText;

//    if (ODGetITextProp(ev, fromSU,
//                           kODPropTextContents, kODIntlText, iBuffer))
//    {
//       itextBuff = GetITextPtr(iBuffer);
//       itextBuffSize = GetITextStringLength(iBuffer);
       // _fTextMgr->AddText(itextBuff, itextBuffSize);
//       delete itextBuff;
//    }

    char* buffer = kODNULL;
    ODULong bufferSize;

    if (ODSUExistsThenFocus (ev, fromSU, kODPropTextContents, kTypeAscii))
       {
         StorageUnitGetValue (fromSU, ev, sizeof (bufferSize),
                              (ODValue) &bufferSize);
         if (bufferSize != 0)
         {
             buffer = new char[bufferSize];
             if (buffer != kODNULL)
             {
                StorageUnitGetValue (fromSU, ev, bufferSize,
                                     (ODValue) buffer );
                _fTextMgr->AddText(buffer, bufferSize);
                delete buffer;
             }
         }
       }

} catch (...) {}
}

SOM_Scope ODBoolean  SOMLINK TextPartDrawContents(TextPart *somSelf,  Environment *ev,
                                     ODFacet* facet, ODShape* invalidShape)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartDrawContents");

    ODBoolean result = kODFalse;

try {
    result = TextPart_parent_BaseContainer_DrawContents(somSelf, ev,
                                                 facet,
                                                 invalidShape);

     // Figure out if we are printing
      int printing = kODFalse;
#ifdef _PLATFORM_OS2_
     if (facet->GetCanvas(ev)->HasPlatformPrintJob(ev,kODPM)) {
#elif defined(_PLATFORM_WIN32_)
     if (facet->GetCanvas(ev)->HasPlatformPrintJob(ev,kODWin32)) {
#endif
        printing = kODTrue;
     } /* endif */

      // Get the rectangle within which the text should be drawn.
      ODRect rect;
      somSelf->GetFacetBoundingRect(ev,facet,&rect);

//    // Subtract the clipShape from our drawing shape so we don't draw over
//    // embedded shapes.
//    ODShape* clipShape = somSelf->AcquireEmbeddedClipShape(ev, facet);
//    if (clipShape == kODNULL)
//      return kODFalse;
//    drawShape->Subtract(ev,clipShape);
//    clipShape->Release(ev);

#ifdef _PLATFORM_OS2_
//    Comment out until we figure out why the region is being cut off
//    at the top and right.
//    HRGN hrgnClip = drawShape->GetRegion(ev);
//    GpiSetClipRegion(hdc, hrgnClip, NULL);
#endif

     // Create the drawing area and apply the content transforms
     HDC hdc;
     CFocus focus(facet, invalidShape, &hdc);

     // Set up our font attributes and draw the text for this hdc
     _fTextMgr->SetFont(hdc,printing);
     _fTextMgr->DrawText(hdc,rect);

     // Display the cursor if this facet corresponds to a window
     if (!printing)
     {
       _fTextMgr->DisplayCursor(facet,rect);
     } /* endif */

     result = kODTrue;
} catch (...) {}

    return result;
}

SOM_Scope       void SOMLINK TextPartReadContents(TextPart *somSelf,
                Environment     *ev,            // in
                ODStorageUnit   *fromSU,        // in
                BCCloneInfo     *cloneInfo,
                BCTransferKind  readKind
                )

{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartReadContents");
#ifdef ODDebug
    PRINT ("TextPart::ReadContents invoked.\n");
#endif

    // Read in our parent's contents first
    TextPart_parent_BaseContainer_ReadContents(somSelf, ev,
                                               fromSU,
                                               cloneInfo,
                                               readKind);
       // Set the scrolling dimensions so the extension can figure out when
       // our text falls outside the frame shape
       if (_fScrollExt) {
           somSelf->SetScrollableDimensions(ev, kODNULL,
                                      _fTextMgr->GetMaximumWidth(),
                                      _fTextMgr->GetTotalHeight());
       } /* end if _fScrollExt */
}

SOM_Scope       void SOMLINK TextPartWriteContents(TextPart *somSelf,
                Environment     *ev,            // in
                ODStorageUnit   *toSU,          // in
                BCCloneInfo     *cloneInfo,
                BCTransferKind  writeKind
                )

{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartWriteContents");
#ifdef ODDebug
    PRINT ("TextPart::WriteContents invoked.\n");
#endif

    char* buffer = kODNULL;
    ODULong bufferSize;

try {
    // Add a default kODPropName to this part's storageUnit for the
    // document properties notebook.  The notebook will maintain
    // it's persistence.  Do this before we call our parent so we
    // will have our own default name.
    if (ODSUExistsThenFocus (ev, toSU, kODPropName, kODIntlText)) {
       if (toSU->GetSize(ev) == 0) {
          // create string to place in kODPropName property
          ODIText* iTextPropName = CreateITextFromCharPtr(kTextPartPropertyName);

          // write the name into the kODPropName property
          ODSetITextProp(ev, toSU, kODPropName, kODIntlText, iTextPropName);
       }
    }

    // Write out our parent's contents
    TextPart_parent_BaseContainer_WriteContents(somSelf, ev,
                                               toSU,
                                               cloneInfo,
                                               writeKind);

    // Write out the contents and the size
    bufferSize = _fTextMgr->GetText(&buffer);
    InitPropVal (ev, toSU, kODPropTextContents, kTypeAscii);
    StorageUnitSetValue (toSU, ev, sizeof(bufferSize), (ODValue) &bufferSize);
    StorageUnitSetValue (toSU, ev, bufferSize, (ODValue) buffer);

    // If we have text to store, also write the internationalized value
    // to the storage unit
    if (bufferSize != 0) {
      // Specify 0 for the script code and language code
      ODIText* iBuffer = CreateITextWLen(0, 0, (ODUByte*) buffer, bufferSize );
      ODSetITextProp(ev, toSU, kODPropTextContents, kODIntlText, iBuffer);
    } /* endif */

} catch(...) {}

    if (buffer != kODNULL) delete buffer;
}

SOM_Scope       void SOMLINK TextPartWriteKindInfo(TextPart *somSelf,
                             Environment     *ev,
                             ODStorageUnit   *toSU )
{

    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartWriteKindInfo");
#ifdef ODDebug
    PRINT ("TextPart::WriteKindInfo invoked.\n");
#endif

    try
     {
        // write the part kind info attribute
        ODSUAddPropValue(ev, toSU, kODPropContents, kODKindTextPart);
        InitPropVal (ev, toSU, kODPropPreferredKind, kODKindTextPart);
     }
    catch(...) {}

}   // WriteKindInfo()

SOM_Scope       void
SOMLINK         TextPartWriteIconToSU(TextPart *somSelf,
                                      Environment *ev,
                                      ODStorageUnit *toSU)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart", "TextPartWriteIconToSU");
#ifdef ODDebug
    PRINT ("TextPart::WriteIconToSU invoked.\n");
#endif

#ifdef _PLATFORM_OS2_
// Customized icon support for OS2.

     HMODULE hmod;
     ULONG cbIconSize;
     PBYTE pIconData = NULL;
     CHAR Error[256] = "";

     DosLoadModule(Error, sizeof(Error), "iodtext", &hmod);

     if ( !DosQueryResourceSize( hmod, RT_POINTER, 100, &cbIconSize) &&
         !DosGetResource( hmod, RT_POINTER, 100, (PPVOID)&pIconData)  )
     {
        InitPropVal (ev, toSU,kODPropIconFamily , kODIconFamily);
        StorageUnitSetValue( toSU, ev, cbIconSize, (ODValue)pIconData );
        DosFreeResource(pIconData);
     }
     else
        PRINT("DosGetResource failed!\n");

#endif // _PLATFORM_OS2_

}

SOM_Scope ODBoolean  SOMLINK TextPartHandleEvent(TextPart *somSelf,
                                                  Environment *ev,
                                                 ODEventData* event,
                                                 ODFrame* frame,
                                                 ODFacet* facet,
                                                 ODEventInfo* eventInfo)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartHandleEvent");
#ifdef ODDebug
//    PRINT ("TextPart::HandleEvent invoked.\n");
#endif

    ODBoolean eventHandled = kODFalse;
    ODBoolean scrollHandled = kODFalse;  // Scroll events can be processed twice

#if defined(_PLATFORM_WIN32_)
    switch (event->message) {
#elif defined(_PLATFORM_OS2_)
    switch (event->msg) {
#endif
    case WM_SETFOCUS:
          #ifdef ODDebug
             PRINT("TextPart: WM_SETFOCUS received.\n");
          #endif
          break;
#if defined(_PLATFORM_WIN32_)
    case WM_KILLFOCUS:
          #ifdef ODDebug
             PRINT("TextPart: WM_KILLFOCUS received.\n");
          #endif
          break;
#elif defined(_PLATFORM_OS2_)
    case WM_FOCUSCHANGE:
          #ifdef ODDebug
              PRINT("TextPart: WM_FOCUSCHANGE received.\n");
          #endif
          break;
#endif
       // Check if we are being deactivated.
    case kODEvtActivate:
          #if defined(_PLATFORM_WIN32_)
             if (LOWORD(event->wParam) == WA_INACTIVE) {
          #elif defined(_PLATFORM_OS2_)
             if (SHORT1FROMMP(event->mp1) == kODFalse) {
          #endif
          #ifdef ODDebug
//               PRINT("TextPart: Inactivate message received.\n");
          #endif
               TempODFrame keyOwner = _fSession->GetArbitrator(ev)->AcquireFocusOwner(ev, _fKeyFocus);
               if (keyOwner == frame) {
                  HWND hwnd = facet->GetFacetHWND(ev);
                  _fTextMgr->DeleteCursor(hwnd);
               } /* endif */
             } else {
          #ifdef ODDebug
//               PRINT("TextPart: Activate message received.\n");
          #endif
             }
          break;

    // After handling the scrolling event pass it on as a key event so we
    // can process the cursor if necessary.
    case kODEvtKeyDown:
          #ifdef ODDebug
          PRINT("TextPart: kODEvtKeyDown received.\n");
          #endif
          scrollHandled = somSelf->HandleScrollEvent(ev, frame, event);
          eventHandled = somSelf->HandleKeyEvent(ev, event, frame, facet, eventInfo);
          break;
    // BaseContainer only calls HandleKeyEvent for kODEvtKeyUp.
    case WM_CHAR:
          #ifdef ODDebug
          PRINT("TextPart: WM_CHAR received.\n");
          #endif
          eventHandled = somSelf->HandleKeyEvent(ev, event, frame, facet, eventInfo);
          break;
    case kODEvtKeyUp:
          #ifdef ODDebug
          PRINT("TextPart: kODEvtKeyUp received.\n");
          #endif
          eventHandled = somSelf->HandleKeyEvent(ev, event, frame, facet, eventInfo);
          break;
    default:
          break;
    } /* endswitch */

    if (!eventHandled && !scrollHandled)
       eventHandled = TextPart_parent_BaseContainer_HandleEvent(somSelf, ev,
                                                                event,
                                                                frame,
                                                                facet,
                                                                eventInfo);
    return eventHandled;
}

SOM_Scope void  SOMLINK TextPartInstallMenuItems(TextPart *somSelf,
                                                  Environment *ev,
                                                 ODMenuBar* menuBar)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartInstallMenuItems");
#ifdef ODDebug
    PRINT ("TextPart::InstallMenuItems invoked.\n");
#endif

try {
    TextPart_parent_BaseContainer_InstallMenuItems(somSelf, ev,
                                                   menuBar);
#if defined(__IBMCPP__) || defined(_IBMR2)
    nl_catd txNLSCat;       // NLS message catalog handle
    char *menuText;         // pointer for NLS message
    setlocale(LC_ALL,"");

    txNLSCat=catopen(TX_NLS_CATALOG, NL_CAT_LOCALE);   // Open NLS message catalog
#else
    char menuText[256];
#endif

    menuBar->Acquire(ev);

    ODPlatformMenuItem *mi = new ODPlatformMenuItem;

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

    // add a menu separator line to OPTIONS menu
    mi->id=CMD(Dash);
    #if defined(_PLATFORM_WIN32_)
        mi->afAttribute=MF_SEPARATOR;
    #elif defined(_PLATFORM_OS2_)
        mi->afAttribute=CA_TITLESEPARATOR;
    #endif


    // add IMPORT menu selection to OPTIONS menu
    mi->id=kODCommandImport;
    menuBar->AddMenuItemLast(ev, kODOptionsMenuID, kODNULL, mi);
#if defined(__IBMCPP__) || defined(_IBMR2)
    menuText=catgets(txNLSCat, TP_MSG_SET, TP_MSG_IMPORT_MENU, "Import");
#else
    strcpy (menuText, "Import");
#endif
    menuBar->SetMenuItemText(ev, kODOptionsMenuID, kODCommandImport, menuText);

    // add EXPORT menu selection to OPTIONS menu
    mi->id=kODCommandExport;
    menuBar->AddMenuItemLast(ev, kODOptionsMenuID, kODNULL, mi);
#if defined(__IBMCPP__) || defined(_IBMR2)
    menuText=catgets(txNLSCat, TP_MSG_SET, TP_MSG_EXPORT_MENU, "Export");
#else
    strcpy (menuText, "Export");
#endif
    menuBar->SetMenuItemText(ev, kODOptionsMenuID, kODCommandExport, menuText);

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

    delete mi;                      // cleanup menuitem buffer

#if defined(__IBMCPP__) || defined(_IBMR2)
    catclose(txNLSCat);             // close the message catalog
#endif

} catch(...) {}

}


SOM_Scope ODBoolean  SOMLINK TextPartHandleMenuEvent(TextPart *somSelf,
                                                 Environment *ev,
                                                 ODFrame* frame,
                                                 ODEventData* event)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartHandleMenuEvent");
#ifdef ODDebug
    PRINT ("TextPart::HandleMenuEvent invoked.\n");
#endif

    ODBoolean   eventHandled     = kODFalse;
    long        eventMessage;

try{

#if defined(_PLATFORM_WIN32_)
    switch(LOWORD(event->wParam)) // determine which menu pulldown it was
#elif defined(_PLATFORM_OS2_)
    switch(LONGFROMMP(event->mp1))
#endif
        {
         case CMD(Import):
              if (somSelf->ImportFile(ev,frame)) {
                 frame->Invalidate (ev, kODNULL, kODNULL);
                 ODUpdateID updateID = _fSession->UniqueUpdateID(ev);
                 frame->ContentUpdated (ev, updateID);
              }
              eventHandled=kODTrue;
              break;
         case CMD(Export):
              somSelf->ExportFile(ev);
              eventHandled=kODTrue;
              break;
         case CMD(Delete):
              // Call parent in case we have selected content objects to delete.
              TextPart_parent_BaseContainer_HandleMenuEvent(somSelf, ev, frame, event);

              // Now handle the delete key.
              eventMessage = ACCEL_KEY;
              _fTextMgr->ProcessKeyInput(eventMessage, kODCommandDelete);

              // Set changed flags if necessary.
              if (eventMessage == TEXT_CHANGED) {
                 somSelf->ChangeNotification(ev, TP_TEXTCHANGED, frame,
                                             kODNULL, kODTrue, kODNULL);
                 frame->Invalidate(ev,kODNULL,kODNULL);
              }
              eventHandled = kODTrue;
              break;
         default:
              break;
        } /* endswitch*/

    if (!eventHandled)
       eventHandled = TextPart_parent_BaseContainer_HandleMenuEvent(somSelf, ev,
                                                    frame, event);

} catch(...) {}

    return eventHandled;
}


SOM_Scope void  SOMLINK TextPartAdjustMenus(TextPart *somSelf,
                                             Environment *ev,
                                            ODFrame* frame)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartAdjustMenus");
#ifdef ODDebug
    PRINT ("TextPart::AdjustMenus invoked.\n");
#endif

try {
    TextPart_parent_BaseContainer_AdjustMenus(somSelf, ev, frame);

      // Enable menu options that change our content only for writeable drafts.
      _fMenuBar->EnableMenuItem(ev, kODOptionsMenuID, CMD(Import), !_fDraftReadOnly);
      _fMenuBar->EnableMenuItem(ev, kODOptionsMenuID, CMD(Export), _fTextMgr->HasText());

      // Delete key must be enabled whenever text is present.  Otherwise, use our parent's
      // setting of the delete key enablement.
      if (_fTextMgr->HasText())
         _fMenuBar->EnableMenuItem(ev, IDMS_EDIT, CMD(Delete), !_fDraftReadOnly);

} catch(...) {}

}

SOM_Scope void  SOMLINK TextPartFacetAdded(TextPart *somSelf,
                                            Environment *ev,
                                            ODFacet* facet)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartFacetAdded");
#ifdef ODDebug
    PRINT ("TextPart::FacetAdded invoked.\n");
#endif

try {
      TextPart_parent_BaseContainer_FacetAdded(somSelf, ev, facet);

      ODCanvas* canvas = facet->GetCanvas(ev);

      // if this is our drawing canvas, set up the default font attributes
      if (canvas->IsDynamic(ev) && !canvas->IsOffscreen(ev))
      {
          HWND hwnd = facet->GetFacetHWND(ev);
#ifdef _PLATFORM_OS2_
          HPS hdc = WinGetPS(hwnd);
#elif defined(_PLATFORM_WIN32_)
          HDC hdc = GetDC(hwnd);
#endif
          _fTextMgr->SetFont(hdc,kODFalse);  // Set font for drawing

          // Set the scrolling dimensions so the extension can figure out when
          // our text falls outside the frame shape
          if (_fScrollExt) {
              somSelf->SetScrollableDimensions(ev, kODNULL,
                                      _fTextMgr->GetMaximumWidth(),
                                      _fTextMgr->GetTotalHeight());
          } /* end if _fScrollExt */

      } /* end if drawing canvas */

} catch(...) {}

}

SOM_Scope void SOMLINK TextPartFocusAcquired(TextPart* somSelf,
                       Environment     *ev,
                       ODTypeToken      focus,      // string token of kOD*Focus
                       ODFrame         *ownerFrame) // display frame that owns focus
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartFocusAcquired");
#ifdef ODDebug
//  PRINT ("TextPart::FocusAcquired invoked.\n");
#endif

try {
   TextPart_parent_BaseContainer_FocusAcquired(somSelf, ev, focus, ownerFrame);

   // Create the cursor when we gain the keyboard focus if the draft is writeable.
   if (focus == _fKeyFocus && !_fDraftReadOnly) {
      ODFrameFacetIterator* facetItr = ownerFrame->CreateFacetIterator(ev);
      HWND hwnd = facetItr->First(ev)->GetFacetHWND(ev);
      _fTextMgr->CreateCursor(hwnd);
      delete facetItr;
   } /* endif */


} catch(...) {}

}

SOM_Scope void SOMLINK TextPartFocusLost(TextPart* somSelf,
                       Environment     *ev,
                       ODTypeToken      focus,      // string token of kOD*Focus
                       ODFrame         *ownerFrame) // display frame which lost focus
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartFocusLost");
#ifdef ODDebug
//  PRINT ("TextPart::FocusLost invoked.\n");
#endif

try {
   // Delete the cursor when we gain the keyboard focus if the draft was writeable.
   if (focus == _fKeyFocus && !_fDraftReadOnly) {
      ODFrameFacetIterator* facetItr = ownerFrame->CreateFacetIterator(ev);
      HWND hwnd = facetItr->First(ev)->GetFacetHWND(ev);
      _fTextMgr->DeleteCursor(hwnd);
      delete facetItr;
   }
   TextPart_parent_BaseContainer_FocusLost(somSelf, ev, focus, ownerFrame);
} catch(...) {}

}

SOM_Scope ODBoolean SOMLINK TextPartHandleMouseClick(TextPart* somSelf,
                                    Environment     *ev,
                                    ODEventData     *event,
                                    ODFrame         *frame,
                                    ODFacet         *facet,
                                    ODEventInfo     *eventInfo)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartHandleMouseClick");
#ifdef ODDebug
//  PRINT ("TextPart::HandleMouseClick invoked.\n");
#endif

    ODBoolean   eventHandled     = kODFalse;

try {

   // If our parent isn't expecting a mouse click and nothing is selected and
   // the draft is writeable, then use the mouse click to position the cursor.
   if ((somSelf->GetMouseMode(ev) == kMouseModeNull) &&
       (somSelf->GetSelectedObjects(ev)->Count(ev) == 0) &&
       !_fDraftReadOnly)
   {
      // Get the window and the position of the mouse click
      HWND hwnd = facet->GetFacetHWND(ev);
      ODPoint cursorLocation;
      WinPt2FramePt (ev, event, eventInfo, &cursorLocation, facet);

      // Get the bounding box of our used shape.  We use this to determine
      // which paragraph and character the mouse click corresponds to.
      ODRect rect;
      somSelf->GetFacetBoundingRect(ev,facet,&rect);

      // Set the cursor to the location of the mouse click
      _fTextMgr->SetCursor(hwnd, cursorLocation, rect);
      _fTextMgr->DisplayCursor(facet, rect);
      eventHandled = kODTrue;
   } else {
      eventHandled = TextPart_parent_BaseContainer_HandleMouseClick (somSelf, ev,
                               event, frame, facet, eventInfo);
   } /* endif */

} catch(...) {}
   return eventHandled;
}

SOM_Scope ODBoolean SOMLINK TextPartHandleKeyEvent(TextPart* somSelf,
                                    Environment     *ev,
                                    ODEventData     *event,
                                    ODFrame         *frame,
                                    ODFacet         *facet,
                                    ODEventInfo     *eventInfo)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartHandleKeyEvent");

    ODBoolean   eventHandled = kODFalse;
    short       keyEvent;
    long        eventMessage;

try {

// On OS/2, the WM_CHAR event is generated for both a key down and key up.
// Unlike windows, the key event code for WM_CHAR can be either an ASCII
// value OR it can be a virtual key code.  So on OS2 we must examine the
// flags in mp1 to determine if this is a character or virtual key.
#ifdef _PLATFORM_OS2_
    short fsflags = SHORT1FROMMP(event->mp1);

    // Don't handle key up events- only key down
    if ((fsflags & KC_KEYUP) != 0) {
       return eventHandled;
    } /* endif */

    // Distinguish between character input and other keys
    if ((fsflags & KC_CHAR) != 0) { // Is this a character?
      eventMessage = CHARACTER_KEY;
      keyEvent = SHORT1FROMMP(event->mp2); // Get Character key code
    } else {
      eventMessage = VIRTUAL_KEY;
      keyEvent = SHORT2FROMMP(event->mp2); // Get Virtual key code
    }

#elif defined(_PLATFORM_WIN32_)
// On Windows, the WM_CHAR event is a subset of a key down event.  Only
// printable characters generate the WM_CHAR event, but all keys generate
// the kODEvtKeyDown event.  The key event code for WM_CHAR is the ASCII value
// of the character, but the key event code for kODEvtKeyDown is a virtual key
// value provided by the Windows dispatcher.  The virtual key value is
// usually different from the ASCII value, so we need to process WM_CHAR
// messages separately from kODEvtKeyDown messages on Windows.
    if (event->message == WM_CHAR) {
      eventMessage = CHARACTER_KEY;
    } else {
      eventMessage = VIRTUAL_KEY;
    } /* endif */
    keyEvent = event->wParam;
#endif //_PLATFORM_WIN32_

    // The dispatcher generates a kODEvtKeyUp message for both OS2 and NT.
    // The only key up message we want to process is the insert key.  Since
    // multiple key downs are possible for each key up, it's best to process
    // the insert key only on key up to know what insert mode we're in.

#ifdef _PLATFORM_WIN32_
    if (event->message == kODEvtKeyUp)
#elif defined(_PLATFORM_OS2_)
    if (event->msg == kODEvtKeyUp)
#endif
       if (keyEvent == VK_INSERT) {
          _fTextMgr->ToggleInsertMode();
          return kODTrue;
       } else {
          return kODFalse;
       }

    // Don't pass on the character events if we're in a read only draft.
    if (eventMessage == CHARACTER_KEY && _fDraftReadOnly)
#ifdef _PLATFORM_WIN32_
          Beep(300,150);
#elif defined(_PLATFORM_OS2_)
          DosBeep(300,50);
#endif
    else
       eventHandled = _fTextMgr->ProcessKeyInput(eventMessage, keyEvent);

    if (!eventHandled)
       eventHandled = TextPart_parent_BaseContainer_HandleKeyEvent (somSelf, ev,
                               event, frame, facet, eventInfo);
    else {
       // Set changed flag if necessary.
       if (eventMessage == TEXT_CHANGED) {
          somSelf->ChangeNotification(ev, TP_TEXTCHANGED, frame,
                                      kODNULL, kODTrue, kODNULL);
       }
       frame->Invalidate(ev,kODNULL,kODNULL);
    }
} catch(...) {}
    return eventHandled;
}

SOM_Scope void SOMLINK TextPartChangeNotification(TextPart *somSelf,
                Environment     *ev,
                ODULong         reason,
                ODFrame         *frame,
                ContentObject  *content,
                ODBoolean       bPropagate,
                ODUpdateID      updateID)
{
    TextPartData *somThis = TextPartGetData(somSelf);
    TextPartMethodDebug("TextPart","TextPartChangeNotification");
try {
    TextPart_parent_BaseContainer_ChangeNotification(somSelf, ev,
                    reason, frame, content, bPropagate, updateID);

    if (reason == TP_TEXTCHANGED) {
       if (_fScrollExt) {
           somSelf->SetScrollableDimensions(ev, frame,
                                 _fTextMgr->GetMaximumWidth(),
                                 _fTextMgr->GetTotalHeight());
       }
       somSelf->GetStorageUnit(ev)->GetDraft(ev)->SetChangedFromPrev(ev);
    } /* endif */
} catch(...) {}
}

SOM_Scope ISOString  SOMLINK M_TextPartclsGetODPartHandlerName(M_TextPart *somSelf,
                                                                Environment *ev)
{
    /* M_TextPartData *somThis = M_TextPartGetData(somSelf); */
    M_TextPartMethodDebug("M_TextPart","M_TextPartclsGetODPartHandlerName");
#ifdef ODDebug
    PRINT ("TextPart::clsGetODPartHandlerName invoked.\n");
#endif

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

    return (ISOString) handlerName;
}

SOM_Scope string  SOMLINK M_TextPartclsGetODPartHandlerDisplayName(M_TextPart *somSelf,
                                                                    Environment *ev)
{
    /* M_TextPartData *somThis = M_TextPartGetData(somSelf); */
    M_TextPartMethodDebug("M_TextPart","M_TextPartclsGetODPartHandlerDisplayName");
#ifdef ODDebug
    PRINT ("TextPart::clsGetODPartHandlerDisplayName invoked.\n");
#endif

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

    return displayName;
}

SOM_Scope _IDL_SEQUENCE_PartKindInfo  SOMLINK M_TextPartclsGetODPartKinds(M_TextPart *somSelf,
                                                                           Environment *ev)
{
    /* M_TextPartData *somThis = M_TextPartGetData(somSelf); */
    M_TextPartMethodDebug("M_TextPart","M_TextPartclsGetODPartKinds");
#ifdef ODDebug
    PRINT ("TextPart::clsGetODPartKinds invoked.\n");
#endif

    _IDL_SEQUENCE_PartKindInfo TextPartInfo;

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

    // Copy the information into the structure
    strcpy(info->partKindName , kODKindTextPart);
    strcpy(info->partKindDisplayName, kTextPartKindDisplayName);
    strcpy(info->filenameFilters, "");
    strcpy(info->filenameTypes, "");
    strcpy(info->categories, kTextPartCategory);
    strcpy(info->categoryDisplayName, "");
    strcpy(info->objectID, "");

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

    return TextPartInfo;
}

SOM_Scope string  SOMLINK M_TextPartclsGetOLE2ClassId(M_TextPart *somSelf,
                                                       Environment *ev)
{
    /* M_TextPartData *somThis = M_TextPartGetData(somSelf); */
    M_TextPartMethodDebug("M_TextPart","M_TextPartclsGetOLE2ClassId");
#ifdef ODDebug
    PRINT ("TextPart::clsGetOLE2ClassId invoked.\n");
#endif

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


    string OLE2 = "{fa005380-e962-11cf-b257-08005a49d940}";
    string OLE2ClassId = (string)SOMMalloc(strlen(OLE2)+1);
    strcpy(OLE2ClassId,OLE2);

    return OLE2ClassId;
}

SOM_Scope string  SOMLINK M_TextPartclsGetWindowsIconFileName(M_TextPart *somSelf,
                                                               Environment *ev)
{
    /* M_TextPartData *somThis = M_TextPartGetData(somSelf); */
    M_TextPartMethodDebug("M_TextPart","M_TextPartclsGetWindowsIconFileName");
#ifdef ODDebug
    PRINT ("TextPart::clsGetWindowsIconFileName invoked.\n");
#endif

    string fileName = (string) SOMMalloc (strlen(kTextPartIconFileName)+1);
    strcpy(fileName,kTextPartIconFileName);
    return fileName;
}


