// @(#) 1.25 nt/src/core/Info.cpp, odcore, od96nt, odnt9712d 3/19/97 15:51:39 [3/21/97 17:26:19]
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odcore
//
//   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========================================
//
//====START_GENERATED_PROLOG======================================
//
//
//
//   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========================================
//

/*
        File:           Info.cpp

        Contains:       implementation of the Info object including ShowPartFrameInfo

        Owned by:       Tantek  elik

        Copyright:      c 1993-94 by Apple Computer, Inc., all rights reserved.

        Change History (most recent first):

                <14>    10/31/94        CG              #1147225: Changing Kind now works.
                <13>    10/27/94        CG              #1147225: Changing Editors now works.
                <12>     10/7/94        CG              #1187539: Don't call ODSetPOName until file
                                                                        renaming has worked successfully.
                <11>     9/26/94        T               #1188044 Part Info Checkbox behaviour
                <10>     9/23/94        VL              1155579, 1184272: Use StorUtil to
                                                                        create/get container and its file.
                 <9>     9/22/94        eeh             #1188170: comment out NOTOKENIZE to enable
                                                                        changing views in PartInfo dialog.
                 <8>     9/20/94        CG              #1187136: put TRY-CATCH block around
                                                                        PlatformFile::Rename() call.
                 <7>     9/15/94        T               #1183571 implement Settings Extension
                 <6>     8/29/94        T               #1183567 StdTypIO routine implementation &
                                                                        fixup
                 <5>     8/26/94        T               #1166371 Part Info edit-text drawn too high
                 <4>     7/21/94        T               fixed call to EqualPascalStrings
                 <3>     7/11/94        T               fixed a few calls to InfoUtil functions
                 <2>     7/11/94        T               moved some functions from InfoUtil
                 <1>     7/11/94        T               first checked in
                 <0>      7/8/94        SV              SOMverted

*/

#define ODInfo_Class_Source
#define VARIABLE_MACROS
#include <Info.xih>


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

#ifndef SOM_ODHelp_xh
#include <ODHelp.xh>
#endif

#ifndef _HLPPANELS_
#include <hlppanls.h>
#endif

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

#ifndef SOM_ODDocument_xh
#include <Document.xh>
#endif

#ifndef SOM_ODContainer_xh
#include <ODCtr.xh>
#endif

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

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

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

#ifndef _INFODEFS_
#include "InfoDefs.h"
#endif

#ifndef SOM_Module_OpenDoc_StdProps_defined
#include <StdProps.xh>
#endif

#ifndef  _ODTYPESP_
#include <ODTypesP.h>
#endif

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

#ifndef _ODUTILS_
#include <ODUtils.h>
#endif

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

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

#ifndef SOM_ODPart_xh
#include <Part.xh>
#endif

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

#ifndef SOM_ODStorageUnitView_xh
#include <SUView.xh>
#endif

#ifndef SOM_ODSettingsExtension_xh
#include <Settings.xh>
#endif

#ifndef SOM_Module_OpenDoc_StandardExtensions_defined
#include <StdExts.xh>
#endif

#ifndef _PASCLSTR_
#include <PasclStr.h>
#endif

#ifndef _ODMEMORY_
#include <ODMemory.h>
#endif

#ifndef _PLFMFILE_
#include <PlfmFile.h>
#endif

#ifndef SOM_ODTypeList_xh
#include <TypeList.xh>
#endif

#ifndef SOM_ODTypeListIterator_xh
#include <TypLsItr.xh>
#endif

#ifndef _BNDNSUTL_
#include <BndNSUtl.h>
#endif

#ifndef _TEMPOBJ_
#include <TempObj.h>
#endif

#ifndef _EXCEPT_
#include <Except.h>
#endif

#ifndef _ITEXT_
#include <IText.h>
#endif

#ifndef _STORUTIL_
#include <StorUtil.h>
#endif

#ifndef _EDITRSET_
#include <EditrSet.h>
#endif

#ifndef _ISOSTR_
#include <ISOStr.h>
#endif

#ifndef SOM_ODPartWrapper_xh
#include <PartWrap.xh>
#endif

#ifndef SOM_ODNameSpace_xh
#include <namspac.xh>
#endif

#ifndef _STDTYPIO_
#include <StdTypIO.h>
#endif

#ifndef SOM_ODTranslation_xh
#include <Translt.xh>
#endif

#ifndef SOM_ODDispatcher_xh
#include <Disptch.xh>
#endif

#ifndef SOM_ODStorageSystem_xh
#include <ODStor.xh>
#endif

#ifndef SOM_ODNameSpaceManager_xh
#include <NmSpcMg.xh>
#endif

#ifndef _ORDCOLL_
#include <OrdColl.h>
#endif

#ifndef _ODRES_
#include <ODRES.H>
#endif

#ifndef _LinkSrc_
#include <LinkSrc.xh>
#endif

#ifndef _DOCMGR_
#include <DocMgr.xh>
#endif

#ifndef _ODPRTREG_
#include <ODPrtReg.xh>
#endif

#ifndef _ODPRTREIG_
#include <ODPrtRei.xh>
#endif

#include <langinfo.h>

#include <ODRegApi.h>

#ifndef SOM_ODWindowIterator_xh
#include <WinIter.xh>
#endif

#ifdef _PLATFORM_NT_
//   currently scripting is only on NT/Win95
#include <screxten.xh>                      // for ODScriptExtension
#endif

/* System property sheet */
#include <windows.h>
#include <commctrl.h>
#include <prsht.h>              /* may move to commctrl.h */

#define SIZE 2048


typedef struct ODInfoDlgProgDataTag
{
    ODBoolean	allowEditing;
    ODFacet	*facet;
} ODInfoDlgProcData;

//==============================================================================
// Constants
//==============================================================================
//const ODPlatformType kODFileType_hfs = (ODPlatformType) 0x68667320;     // 'hfs '
const ODULong kODDateLength = 29; // Length of date in property notebook


//==============================================================================
// Scalar types
//==============================================================================
//typedef char ODHandleState;

//==============================================================================
// Static Globals
//==============================================================================

static ODTypeList*  ODInfo_kindList;
static ODEditor     ODInfo_editorID;
static ODEditor     ODInfo_currentEditorName;
static ODSShort     ODInfo_currentKindItem;
static ODSShort     ODInfo_currentEditorItem;

//==============================================================================
// Kind/Editor functions
//==============================================================================

void EnableApplModal(Environment *ev, ODWindowState *winstat, HWND hwnd,
                     BOOL enable);

void AddTypesToMenu(ODTypeList* typeList, ODType kindID,
                    MenuHandle editorMenu, ODSession* session);

void AddEditorsToMenu(ODTypeList* kindsList, ODEditor editorID,
                      MenuHandle editorMenu, ODSession* session);

int CreatePropSheet(HWND  hpwnd, ODFacet* facet, HINSTANCE resInst, ODBoolean allowEditing );

//==============================================================================
// InitInfo
//==============================================================================

SOM_Scope void  SOMLINK ODInfoInitInfo(ODInfo *somSelf, Environment *ev,
                ODSession* session)
{
    ODInfoData *somThis = ODInfoGetData(somSelf);
    ODInfoMethodDebug("ODInfo","ODInfoInitInfo");

        _fSession = session;
}

//==============================================================================
// ShowPartFrameInfo
//==============================================================================

SOM_Scope ODBoolean  SOMLINK ODInfoShowPartFrameInfo(ODInfo *somSelf, Environment *ev,
                ODFacet* facet, ODBoolean allowEditing)
{
        ODInfoData *somThis = ODInfoGetData(somSelf);
        ODInfoMethodDebug("ODInfo","ODInfoShowPartFrameInfo");

        int result;

        // Need to acquire frame and storage unit before using them. Put
        // them in temp object so that when the temp object is out of
        // scope, the object get released.
        TempODFrame frame = facet->GetFrame(ev);
        frame->Acquire(ev);
        TempODStorageUnit su = frame->GetStorageUnit(ev);
        su->Acquire(ev);
        ODSession* session = su->GetSession(ev);
        HINSTANCE resInst = session->GetWindowSystemData(ev)->resInstance;

        ODWindowState* WinStat = session->GetWindowState(ev);

        // Need to release the window. Use temp object to accomplish
        // the release when the temp object is out of scope.
        TempODWindow Window = WinStat->AcquireActiveWindow(ev);
        HWND hwnd = Window->GetPlatformWindow(ev);

        // Allow editing if the part says so and the draft permissions allow it
	if (allowEditing)
            allowEditing = su->GetDraft(ev)->GetPermissions(ev)
                               >= kODDPSharedWrite;

	// Use Apple's technique of forcing a part's externalization so
	// that all necessary data is sure to exist in the SU.
	TempODPart part = frame->AcquirePart(ev);
	if (su->GetDraft(ev)->GetPermissions(ev) >= kODDPSharedWrite)
	    part->Externalize(ev);

        // Before creating the dialog, disable mouse and keyboard inputs
        // to all the OD windows except the window that is going to own
        // the dialog. After dismissing the dialog, enable back all the
        // OD windows except the owner window for the dialog.
        EnableApplModal(ev, WinStat, hwnd, FALSE);
        result = CreatePropSheet(hwnd, facet, resInst, allowEditing);
        EnableApplModal(ev, WinStat, hwnd, TRUE);

        return result;
}


/* Callback for "View" page, Presentation */
BOOL APIENTRY view_page(HWND hWnd, UINT cmd, WPARAM wParam, LPARAM lParam)
   {

   Str255  partNameS255;

   Environment *ev = somGetGlobalEnvironment();
   static PROPSHEETPAGE *prop;

   ODSession* session ;
   ODBoolean isRootPart ;
   ODBoolean isRootPartOfDocument ;
   ODUShort viewval;
   ODSettingsExtension* settings;
   ODULong page_count;
   ODName* partName = kODNULL;
   ODInfoDlgProcData *dpData;

   switch (cmd)
   {
      case WM_INITDIALOG:
      {
         prop = (PROPSHEETPAGE *)lParam;

         dpData = (ODInfoDlgProcData*)prop->lParam;
         TempODFrame frame = dpData->facet->GetFrame(ev);
 
         // Need to acquire the frame before using it. Put it
         // in temp object so that the frame is released when
         // the temp object is out of scope.
         frame->Acquire(ev);
 
         // Need to release the part. Put it in temp object so that when
         // the temp object is out of scope, the part is released.
         TempODPart part = frame->AcquirePart(ev);
 
         TempODWindow window = dpData->facet->GetWindow(ev);
 
         // Need to acquire the window and storage unit before using them.
         // Put them in temp object so that they get released.
         window->Acquire(ev);
         TempODStorageUnit su = frame->GetStorageUnit(ev);
         su->Acquire(ev);
         session = su->GetSession(ev);
 
         // Need to release the containing frame. Use temp object
         // to accomplish the release.
         TempODFrame containingFrame = frame->AcquireContainingFrame(ev);
         isRootPart = (containingFrame == kODNULL);
         isRootPartOfDocument = isRootPart && window->IsRootWindow(ev);
 
         // Set up Name
         ODName* partName = kODNULL;
         partName = ODGetPOName(ev, part, kODNULL);
         IntlToStr(partName, (LPSTR)partNameS255);
         SetDlgItemText (hWnd, DID_NAME, (LPSTR)partNameS255);
         ODDisposePtr (partName);

         // set up viewas
         SendDlgItemMessage (hWnd, DID_VIEW, CB_INSERTSTRING, 0,
                (LPARAM)catgets(ODcat_handle, INFO_SET, INFO_1, "Frame") );
	 // use isRootPart instead of ...OfDocument so part windows are OK
         if (!(isRootPart))
         {
            SendDlgItemMessage (hWnd, DID_VIEW, CB_INSERTSTRING, 1,
               (LPARAM)catgets(ODcat_handle, INFO_SET, INFO_2, "Large Icon") );
            SendDlgItemMessage (hWnd, DID_VIEW, CB_INSERTSTRING, 2,
               (LPARAM)catgets(ODcat_handle, INFO_SET, INFO_3, "Small Icon") );
            SendDlgItemMessage (hWnd, DID_VIEW, CB_INSERTSTRING, 3,
               (LPARAM)catgets(ODcat_handle, INFO_SET, INFO_4, "Thumb Nail") );
         }

         viewval = 0;
         SendDlgItemMessage (hWnd, DID_VIEW, CB_SETCURSEL, viewval, 0L);

         // set up frozen
         CheckDlgButton(hWnd, DID_BUNDLED, frame->IsFrozen(ev));

         if (isRootPartOfDocument)
         {

            // set up stationery from aFrame and its part
            CheckDlgButton(hWnd, DID_STATIONARY, ODGetIsStationery(ev, frame));
            ShowWindow(GetDlgItem (hWnd, kPartInfoStationeryCheckbox), FALSE);
            ShowWindow(GetDlgItem(hWnd, kPartInfoStationeryText), FALSE);

            // set up show links from the window
            CheckDlgButton(hWnd, DID_SHOWLINKS, window->ShouldShowLinks(ev));

         }
         else
         {
            // disable Stationery button if NOT root
            HWND hChkBtn = GetDlgItem(hWnd, DID_STATIONARY);
            EnableWindow(hChkBtn, 0);

            // disable Show link Button if NOT root
            HWND hChkBtn2 = GetDlgItem(hWnd, DID_SHOWLINKS);
            EnableWindow(hChkBtn2, 0);
         }


         // Add settings pages if Part has Extension.
         if (part->HasExtension(ev,kODSettingsExtension))
         {
            settings = (ODSettingsExtension*)
                       (part->AcquireExtension(ev,kODSettingsExtension));

            settings->ShowSettingsPages(ev, dpData->facet, GetParent(hWnd));

            // Release the settings
            ODReleaseObject(ev, settings);
         }

         return TRUE;
      }

      case WM_COMMAND:
      {
        switch (HIWORD(wParam))
        {
          case BN_CLICKED:
            PropSheet_Changed(GetParent(hWnd), hWnd);
            break;
          case CBN_SELCHANGE:
            PropSheet_Changed(GetParent(hWnd), hWnd);
            break;
          case EN_CHANGE:
            PropSheet_Changed(GetParent(hWnd), hWnd);
            break;
        }
        break;
      }
      case WM_NOTIFY:
      {
         dpData = (ODInfoDlgProcData*)prop->lParam;

         switch (((NMHDR FAR *) lParam)->code)
         {
            case PSN_SETACTIVE:
            {
               // Initialize the controls.
               TempODFrame frame = dpData->facet->GetFrame(ev);

               // Need to acquire frame and storage unit before using them. 
               // Put them in temp object so that when the temp object is 
               // out of scope, the object get released.
               frame->Acquire(ev);
               TempODStorageUnit su = frame->GetStorageUnit(ev);
               su->Acquire(ev);
               session = su->GetSession(ev);
               ODTypeToken view = frame->GetViewType(ev);

               if (view == session->Tokenize(ev, kODViewAsFrame))
                       viewval = 0;
               else if (view == session->Tokenize(ev, kODViewAsLargeIcon))
                       viewval = 1;
               else if (view == session->Tokenize(ev, kODViewAsSmallIcon))
                       viewval = 2;
               else if (view == session->Tokenize(ev, kODViewAsThumbnail))
                       viewval = 3;

               SendDlgItemMessage (hWnd,DID_VIEW,CB_SETCURSEL,viewval,0L);

               break;
            }

            case PSN_APPLY:
            {
               if (dpData->allowEditing)
               {
                  TempODFrame frame = dpData->facet->GetFrame(ev);

                  // Need to acquire frame, window, and su before using. Put
                  // them in temp object so that they are released when
                  // the temp objects are out of scope.
                  frame->Acquire(ev);
                  TempODWindow window = dpData->facet->GetWindow(ev);
                  window->Acquire(ev);
                  TempODStorageUnit su = frame->GetStorageUnit(ev);
                  su->Acquire(ev);
                  session = su->GetSession(ev);

                  // Need to release the part. Put it in temp object so that when
                  // the temp object is out of scope, the part is released.
                  TempODPart part = frame->AcquirePart(ev);

                  // update Frozen
                  frame->SetFrozen(ev, IsDlgButtonChecked(hWnd, DID_BUNDLED));

                  // update Stationery
                  ODSetIsStationery(ev, frame, IsDlgButtonChecked(hWnd, DID_STATIONARY));

                  // update Show Links
                  window->SetShouldShowLinks(ev,IsDlgButtonChecked(hWnd, DID_SHOWLINKS));

                  // Update Name
                  GetDlgItemText(hWnd, DID_NAME, (LPSTR)partNameS255, sizeof(partNameS255)-1);
                  partName =StrToIntl((PSZ)partNameS255, kODNULL);
                  ODSetPOName(ev, part, partName);
                  ODDisposePtr (partName);

                  // support scripting's use of this name for the part, Notify the script
                  // extension of the new name.
#ifdef _PLATFORM_NT_
	          // currently scripting is supported only on NT/Win95
                  if (part->HasExtension(ev, kODScriptExtension))
                  {
                     ODScriptExtension *ScrExt =
                           (ODScriptExtension *) part->AcquireExtension(ev, kODScriptExtension) ;
                     ScrExt->setExtName(ev, (string) partNameS255) ;
                     ScrExt->Release(ev) ;
                  }
#endif

                  // update ViewAs
                  switch (SendDlgItemMessage (hWnd, DID_VIEW, CB_GETCURSEL, 0, 0L))
                  {
                        case 0: // view as frame
                                frame->ChangeViewType(ev, session->Tokenize(ev, kODViewAsFrame));
                                break;
                        case 1: // view as large icon
                                frame->ChangeViewType(ev, session->Tokenize(ev, kODViewAsLargeIcon));
                                break;
                        case 2: // view as small icon
                                frame->ChangeViewType(ev, session->Tokenize(ev, kODViewAsSmallIcon));
                                break;
                        case 3: // view as thumbnail
                                frame->ChangeViewType(ev, session->Tokenize(ev, kODViewAsThumbnail));
                                break;
                        default:
                                break;
                  }

               }
 
               SetWindowLong(hWnd, DWL_MSGRESULT, TRUE);
               break;
            }

            case PSN_HELP:
            {
               TempODFrame frame = dpData->facet->GetFrame(ev);
               frame->Acquire(ev);
               TempODStorageUnit su = frame->GetStorageUnit(ev);
               su->Acquire(ev);
               session = su->GetSession(ev);
               ODHelp * helpme = session->GetHelp(ev);
               helpme->DisplayHelp(ev,ODHELPFILE,SET_VIEW1_PANEL);
               break;
            }

            case PSN_KILLACTIVE:
                SetWindowLong(hWnd, DWL_MSGRESULT, FALSE);
                   return 1;
                   break;

            case PSN_RESET:
                SetWindowLong(hWnd, DWL_MSGRESULT, FALSE);
                   break;
         } 
         break;
      }
      case WM_HELP:
      {
         dpData = (ODInfoDlgProcData*)prop->lParam;
         TempODFrame frame = dpData->facet->GetFrame(ev);
         frame->Acquire(ev);
         TempODStorageUnit su = frame->GetStorageUnit(ev);
         su->Acquire(ev);
         session = su->GetSession(ev);
         ODHelp * helpme = session->GetHelp(ev);
         helpme->DisplayHelp(ev,ODHELPFILE,SET_VIEW1_PANEL);
         break;
      }
   }
   return FALSE;
   }


/* Callback for "BIND" page, Binding */
BOOL CALLBACK bind_page(HWND hWnd, UINT cmd, WPARAM wParam, LPARAM lParam)
   {

   Environment *ev = somGetGlobalEnvironment();
   static PROPSHEETPAGE *prop1;
   ODType  kindID;
   ODInfoDlgProcData *dpData;
   static ODBoolean partSaved;

   switch (cmd)
   {
      case WM_INITDIALOG:
      {
        prop1 = (PROPSHEETPAGE *)lParam;

        dpData = (ODInfoDlgProcData*)prop1->lParam;
        TempODFrame frame = dpData->facet->GetFrame(ev);
        // Need to acquire the frame before using it. Put it
        // in temp object so that the frame is released when
        // the temp object is out of scope.
        frame->Acquire(ev);

        // Need to release the part. Put it in temp object so
        // that when the temp object is out of scope, the part
        // is released.
        TempODPart part = frame->AcquirePart(ev);

        // Need to acquire the storage unit before using it
        TempODStorageUnit su = part->GetStorageUnit(ev);
        su->Acquire(ev);
        ODSession* session = su->GetSession(ev);

        // get editorID
        ODInfo_editorID = GetCurrentEditorForPart(part);
        kindID = ODGetKind(ev, part);

        // check for existence of the Part's storage unit
        if ( (part->GetStorageUnit(ev))->Exists(ev, kODPropContents, kODNULL, 0) )
        {
           //      set up Kind Menu
           ODInfo_kindList = new ODTypeList;
           ODInfo_kindList->InitTypeList(ev,(ODTypeList*) kODNULL);
           ContentValueTypes(su, ODInfo_kindList);

           HWND hKindList = GetDlgItem(hWnd, DID_KIND);
           AddTypesToMenu(ODInfo_kindList, kindID, hKindList, session);

           //      set up Category static text
           // $$$$$ for now just put in the user string of the first category of the first kind
           // should put in user string of the first category of the CURRENT kind
           HWND hCategory = GetDlgItem(hWnd, DID_CATEGORY);
           SetCategory(ODInfo_editorID, kindID, hCategory, session);

           //      set up Editor Menu
           HWND hEditorList = GetDlgItem(hWnd, DID_EDITOR);
           AddEditorsToMenu(ODInfo_kindList, ODInfo_editorID, hEditorList, session);

           partSaved = kODTrue;
        }
        else // list was empty, return error code saying so
        {
           WARNMSG(WARN_INDEX(AMSG_902),
               "Part's properties cannot be displayed until Document is saved.");
           partSaved = kODFalse;
        }

        return TRUE;
      }

      case WM_COMMAND:
      {
        if (HIWORD(wParam) == LBN_SELCHANGE)
            PropSheet_Changed(GetParent(hWnd), hWnd);

        break;
      }

      case WM_NOTIFY:
      {
        switch (((NMHDR FAR *) lParam)->code)
        {
           case PSN_SETACTIVE:
           // Initialize the controls.
           {
              dpData = (ODInfoDlgProcData*)prop1->lParam;
              TempODFrame frame = dpData->facet->GetFrame(ev);
              // Need to acquire the frame before using it. Put it
              // in temp object so that the frame is released when
              // the temp object is out of scope.
              frame->Acquire(ev);

              // Need to release the part. Put it in temp object so
              // that when the temp object is out of scope, the part
              // is released.
              TempODPart part = frame->AcquirePart(ev);

              break;
           }

           case PSN_APPLY:
           {
               dpData = (ODInfoDlgProcData*)prop1->lParam;
               if (dpData->allowEditing && partSaved)
               {
                 TempODFrame frame = dpData->facet->GetFrame(ev);

                 // Need to acquire the frame before using it. Put it
                 // in temp object so that the frame is released when
                 // the temp object is out of scope.
                 frame->Acquire(ev);

                 // Need to release the part. Put it in temp object so
                 // that when the temp object is out of scope, the part
                 // is released.
                 TempODPart part = frame->AcquirePart(ev);

                 // Need to acquire the storage unit before using it
                 TempODStorageUnit su = frame->GetStorageUnit(ev);
                 su->Acquire(ev);
                 ODSession* session = su->GetSession(ev);

                 // update Kind
                 ODSShort kindItem = (ODSShort) SendDlgItemMessage (hWnd, DID_KIND,
                        CB_GETCURSEL, 0, 0);
                 ODType  oldKind, newKind;
                 if (kindItem != ODInfo_currentKindItem)
                 {
                    oldKind  =  GetThisKindFromList( ODInfo_currentKindItem, ODInfo_kindList );
                    newKind  =  GetThisKindFromList( kindItem, ODInfo_kindList );
                 }
                 else
                 {
                    oldKind  =  GetThisKindFromList( ODInfo_currentKindItem, ODInfo_kindList );
                    newKind  =  GetThisKindFromList( ODInfo_currentKindItem, ODInfo_kindList );
                 }

                 // update Editor
                 ODSShort editorItem = (ODSShort) SendDlgItemMessage (hWnd, DID_EDITOR,
                        CB_GETCURSEL, 0, 0);
                 if (editorItem != ODInfo_currentEditorItem)
                 {

                    ODInfo_editorID = ODInfo_currentEditorName;

                    if ( EditorSupportsKind_Reg(ODInfo_editorID,  oldKind, session ))
                    {
                            // change kind first, then editor
                            part->ChangeKind(ev, newKind);
                            ChangeEditor( part, ODInfo_editorID);

                    }
                    else
                    {
                            // change editor first, then kind
                            ChangeEditor( part, ODInfo_editorID);
                            part->ChangeKind(ev, newKind);
                    }

                 }
                 else
                   if (kindItem != ODInfo_currentKindItem) part->ChangeKind(ev, newKind);
               }

               SetWindowLong(hWnd,     DWL_MSGRESULT, TRUE);
                   break;
           }

           case PSN_HELP:
           {
               dpData = (ODInfoDlgProcData*)prop1->lParam;
               TempODFrame frame  = dpData->facet->GetFrame(ev);
               frame->Acquire(ev);
               TempODStorageUnit su = frame->GetStorageUnit(ev);
               su->Acquire(ev);
               ODSession* session = su->GetSession(ev);
               ODHelp   * helpme  = session->GetHelp(ev);
               helpme->DisplayHelp(ev,ODHELPFILE,SET_TYPE_PANEL);
               break;
           }

           case PSN_KILLACTIVE:
                SetWindowLong(hWnd,     DWL_MSGRESULT, FALSE);
                return 1;
                break;

           case PSN_RESET:
                SetWindowLong(hWnd,     DWL_MSGRESULT, FALSE);
                break;
        }
        break;
      }

      case WM_HELP:
      {
           dpData = (ODInfoDlgProcData*)prop1->lParam;
           TempODFrame frame  = dpData->facet->GetFrame(ev);
           frame->Acquire(ev);
           TempODStorageUnit su = frame->GetStorageUnit(ev);
           su->Acquire(ev);
           ODSession* session = su->GetSession(ev);
           ODHelp   * helpme  = session->GetHelp(ev);
           helpme->DisplayHelp(ev,ODHELPFILE,SET_TYPE_PANEL);
           break;
      }
   }  // switch (cmd)
   return FALSE;
   }

/* Callback for "DOCU" page, Document */
BOOL CALLBACK docu_page(HWND hWnd, UINT cmd, WPARAM wParam, LPARAM lParam)
   {

   Str255  aStr255, partCommentsS255;
   Environment *ev = somGetGlobalEnvironment();
   static PROPSHEETPAGE *prop2;
   char theDate[kODDateLength]    = "";
   ODName* partComments;
   ODFacet* facet;
   ODInfoDlgProcData *dpData;

   switch (cmd)
   {
      case WM_INITDIALOG:
      {
        prop2 = (PROPSHEETPAGE *)lParam;

        dpData = (ODInfoDlgProcData*)prop2->lParam;
        TempODFrame frame = dpData->facet->GetFrame(ev);
        // Need to acquire the frame before using it. Put it
        // in temp object so that the frame is released when
        // the temp object is out of scope.
        frame->Acquire(ev);

        // Need to release the part. Put it in temp object so
        // that when the temp object is out of scope, the part
        // is released.
        TempODPart part = frame->AcquirePart(ev);

        // set up Comments
        partComments = kODNULL;
        partComments = ODGetPOComments(ev, part, kODNULL);
        SendDlgItemMessage(hWnd, DID_COMMENTS, EM_SETLIMITTEXT, sizeof(partCommentsS255), 0L);
        IntlToStr(partComments, (LPSTR)partCommentsS255);
        SetDlgItemText(hWnd, DID_COMMENTS,(LPCSTR)partCommentsS255);
        ODDisposePtr (partComments);

        // set up size
        SetDlgItemInt(hWnd, DID_DATASIZE, ODGetPOSize(ev, part), FALSE);


        // Need to acquire the storage unit before using it. Put it
        // in temp object so that the storage unit is released when
        // the temp object is out of scope.
        TempODStorageUnit partSU = part->GetStorageUnit(ev);
        partSU->Acquire(ev);

        // set up created date
        char* dateFormat = nl_langinfo(D_T_FMT);
        time_t theTime = ODGetCreationDate(ev, partSU);
        if (theTime)
        {
          struct tm *timeptr = localtime((const time_t*) &theTime);
          strftime(theDate, kODDateLength, dateFormat, timeptr);
          SetDlgItemText (hWnd, DID_CRDATE, theDate);
        }

        // set up modified date
        theTime = ODGetModificationDate(ev, partSU);
        if (theTime)
        {
          struct tm *timeptr = localtime((const time_t*) &theTime);
          strftime(theDate, kODDateLength, dateFormat, timeptr);
          SetDlgItemText (hWnd, DID_MODDATE, theDate);
        }

        // set up by
        ODName* partUser = kODNULL;
        partUser = ODGetModifiedBy(ev, partSU, kODNULL);
        IntlToStr(partUser, (LPSTR)aStr255);
        SetDlgItemText(hWnd, DID_MODBY, (LPSTR)aStr255);
        ODDisposePtr (partUser);

        // set up Draft ID
        SetDlgItemInt(hWnd, DID_KEY, partSU->GetID(ev), FALSE);

        return TRUE;
      }

      case WM_COMMAND:
      {
        if (HIWORD(wParam) ==  EN_CHANGE)
            PropSheet_Changed(GetParent(hWnd), hWnd);
        break;
      }

      case WM_NOTIFY:
      {
        switch (((NMHDR FAR *) lParam)->code)
        {

           case PSN_SETACTIVE:      //
                // Initialize the controls.
                break;

           case PSN_APPLY:          // APPLY
           {
              dpData = (ODInfoDlgProcData*)prop2->lParam;
              if (dpData->allowEditing)
              {
                // Need to acquire frame. Put in temp object so they
                // are released when the temp objects are out of scope.
                TempODFrame frame = dpData->facet->GetFrame(ev);
                frame->Acquire(ev);

                 // Need to release the part. Put it in temp object so that when
                 // the temp object is out of scope, the part is released.
                TempODPart part = frame->AcquirePart(ev);

                // Update Comments
                GetDlgItemText(hWnd, DID_COMMENTS, (LPSTR)partCommentsS255,
                               sizeof(partCommentsS255)-1);
                partComments =StrToIntl((LPSTR)partCommentsS255, kODNULL);
                ODSetPOComments(ev, part, partComments);
                ODDisposePtr (partComments);
              }

              SetWindowLong(hWnd, DWL_MSGRESULT, TRUE);
              break;
           }

           case PSN_HELP:
           {
              dpData = (ODInfoDlgProcData*)prop2->lParam;
              TempODFrame frame = dpData->facet->GetFrame(ev);
              frame->Acquire(ev);
              TempODStorageUnit su = frame->GetStorageUnit(ev);
              su->Acquire(ev);
              ODSession * session = su->GetSession(ev);
              ODHelp    * helpme  = session->GetHelp(ev);
              helpme->DisplayHelp(ev,ODHELPFILE,SET_FILE1_PANEL);
              break;
           }

           case PSN_KILLACTIVE:     // OK

                SetWindowLong(hWnd, DWL_MSGRESULT, FALSE);

                return 1;
                break;

           case PSN_RESET:          // CANCEL
                SetWindowLong(hWnd, DWL_MSGRESULT, FALSE);
                break;
        }
        break;
      }
      case WM_HELP:
      {
        dpData = (ODInfoDlgProcData*)prop2->lParam;
        TempODFrame frame = dpData->facet->GetFrame(ev);
        frame->Acquire(ev);
        TempODStorageUnit su = frame->GetStorageUnit(ev);
        su->Acquire(ev);
        ODSession * session = su->GetSession(ev);
        ODHelp    * helpme  = session->GetHelp(ev);
        helpme->DisplayHelp(ev,ODHELPFILE,SET_FILE1_PANEL);
      }
        break;
   }
   return FALSE;
   }


SOM_Scope void  SOMLINK ODInfosomInit(ODInfo *somSelf)
{
         ODInfoData *somThis = ODInfoGetData(somSelf);
         ODInfoMethodDebug("ODInfo","ODInfosomInit");

         ODInfo_parent_ODObject_somInit(somSelf);
}

SOM_Scope void  SOMLINK ODInfosomUninit(ODInfo *somSelf)
{
         ODInfoData *somThis = ODInfoGetData(somSelf);
         ODInfoMethodDebug("ODInfo","ODInfosomUninit");

         ODInfo_parent_ODObject_somUninit(somSelf);
}



int CreatePropSheet(HWND  hpwnd, ODFacet* facet, HINSTANCE resInst, ODBoolean allowEditing )

   {

   PROPSHEETPAGE sheet[3];
   PROPSHEETHEADER head;
   ODInfoDlgProcData dpData;
   int result;

   dpData.allowEditing = allowEditing;
   dpData.facet = facet;

   InitCommonControls();

// Init sheet 0-3

   sheet[0].dwSize      = sizeof(PROPSHEETPAGE);
   sheet[0].dwFlags     = PSP_HASHELP;
   sheet[0].hInstance   = resInst;
   sheet[0].pszTemplate = MAKEINTRESOURCE(IDD_PRESENTATIONPAGEDLG);
   sheet[0].pfnDlgProc  = (FARPROC) view_page;
   //sheet[0].lParam      = (LONG) facet;
   sheet[0].lParam      = (LONG) &dpData;

   sheet[1].dwSize      = sizeof(PROPSHEETPAGE);
   sheet[1].dwFlags     = PSP_HASHELP;
   sheet[1].hInstance   = resInst;
   sheet[1].pszTemplate = MAKEINTRESOURCE(IDD_VIEWPAGEDLG);
   sheet[1].pfnDlgProc  = (FARPROC) bind_page;
   //sheet[1].lParam      = (LONG) facet;
   sheet[1].lParam      = (LONG) &dpData;

   sheet[2].dwSize      = sizeof(PROPSHEETPAGE);
   sheet[2].dwFlags     = PSP_HASHELP;
   sheet[2].hInstance   = resInst;
   sheet[2].pszTemplate = MAKEINTRESOURCE(IDD_FILEPAGE1DLG);
   sheet[2].pfnDlgProc  = (FARPROC) docu_page;  /* Callbacks */
   //sheet[2].lParam      = (LONG) facet;
   sheet[2].lParam      = (LONG) &dpData;

   head.dwSize     = sizeof(PROPSHEETHEADER);
   head.dwFlags    = PSH_PROPSHEETPAGE | PSH_HASHELP;
   head.hwndParent = hpwnd;
   head.hInstance  = resInst;
   head.pszCaption = catgets(ODcat_handle, INFO_SET, INFO_11, "Document Properties");
   head.nPages     = sizeof(sheet) / sizeof(PROPSHEETPAGE);
   head.nStartPage = 0;
   head.ppsp       = (LPCPROPSHEETPAGE) &sheet;

   result = PropertySheet(&head);

   return result;
   }

//------------------------------------------------------------------------------
// AddTypesToMenu
//------------------------------------------------------------------------------

void AddTypesToMenu(ODTypeList* typeList, ODType kindID,
                    MenuHandle kindMenu, ODSession* session)
{
  ODSShort                item = 0;
  ODSShort                i = 0;
  ISOString               displayname;
  ODPartHandlerRegistryInt* ODRegistry;
  Environment*            ev = somGetGlobalEnvironment();

        ODRegistry = session -> GetRegistry(ev);
        ODTypeListIterator* typeIter = typeList->CreateTypeListIterator(ev);

        for (ODType type = typeIter->First(ev);
                typeIter->IsNotComplete(ev);
                type = typeIter->Next(ev))
        {
           // convert kind name to appropriate display name for dialogue
           displayname = ODRegistry->GetKindDisplayNameFromKind(ev,type);

           // Copy the PartKind list to dialog box
           SendMessage(kindMenu, LB_ADDSTRING, 0, (LPARAM)displayname);

        }

        // expand horizontal field in part kind list box
        SendMessage(kindMenu, LB_SETHORIZONTALEXTENT, (WPARAM) 800, 0);

        // Set the cursor position to the 1st entry.
        SendMessage(kindMenu, LB_SETCURSEL, 0, 0);

        // initialize currentKindItem to part kind index
        item = 0;
        for (ODType kind = typeIter->First(ev);
              typeIter->IsNotComplete(ev);
              kind = typeIter->Next(ev), ++item)
        {
              if (ODISOStrEqual(kind, kindID))
                      break;
        }

        ODInfo_currentKindItem = item;

        ODDeleteObject( typeIter );

}

//------------------------------------------------------------------------------
// AddEditorsToMenu
//------------------------------------------------------------------------------

void AddEditorsToMenu(ODTypeList* kindsList, ODEditor editorID,
                      MenuHandle editorMenu, ODSession* session)
{

    ODSShort   unique;
    ODSShort   i,j;
    ODSShort   item;
    ODSShort  list_loaded = FALSE;
    enum {STR_COUNT =  50};
    char *strarray[STR_COUNT] = {NULL};

    unsigned  long          size;
    ODPartHandlerRegistryInt* ODRegistry;
    _IDL_SEQUENCE_ISOString PartHandlerList;


        Environment*            ev = somGetGlobalEnvironment();
        ODRegistry = session -> GetRegistry(ev);

        ODTypeListIterator* kindIter = kindsList->CreateTypeListIterator(ev);
        for (ODType kind = kindIter->First(ev);
                kindIter->IsNotComplete(ev);
                kind = kindIter->Next(ev) )
        {

           // retrieve PartHandler list from Registry
           // this is a buffer that the Registry allocates and we need to dispose of.
           PartHandlerList = ODRegistry-> GetPartHandlerList( ev, kind, 0);

           //   if (GetUserEditorFromEditor(nsm, editor, &name))
           // if the list is not empty, continue
           if ( PartHandlerList. _length ) {
               list_loaded = TRUE;
           }

           // Copy the PartHandler list to dialog box
           for ( i = 0; i < PartHandlerList. _length; i++)
           {

              for ( j = 0, unique = TRUE; strarray[j]; j++)
              {
                 if (strcmp(PartHandlerList. _buffer[i],strarray[j]) == 0 )
                 {
                    // set unique to false if duplicate editor exists in string array
                    unique = FALSE;
                 }
              }

              if (unique ==  TRUE)
              {
                 // Copy the PartHandler list to dialog box if first occurrence
                 SendMessage(editorMenu, LB_ADDSTRING, 0,
                 (LPARAM)(ODRegistry->GetHandlerDisplayNameFromHandler(ev,PartHandlerList. _buffer[i])));


                 // copy Part Handler name to string for duplicate check
                 strarray[j] = new char[strlen(PartHandlerList. _buffer[i])+1];
                 strcpy ( strarray[j], PartHandlerList. _buffer[i] );

              }
           }

           // now free up the buffer we got from the Registry
           for ( i = 0; i < PartHandlerList. _length; i++)
           {
                     SOMFree( PartHandlerList. _buffer[i]);
           }
           SOMFree( PartHandlerList. _buffer);

        }



        // If list was loaded, set up list boxes.
        if ( list_loaded == TRUE )
        {
           // expand horizontal field in part editor list box2
           SendMessage(editorMenu, LB_SETHORIZONTALEXTENT, (WPARAM) 800, 0);

           // set editor name to current editor
           ODInfo_currentEditorName = editorID;

           // Set the cursor position to the current editor in list box
           for ( item = 0;  strarray[item] != NULL; item++)
           {
              if (strcmp(strarray[item], editorID ) == 0 )
              {
                 SendMessage(editorMenu, LB_SETCURSEL, (WPARAM)item, 0);
                 // set editor index to current editor
                 ODInfo_currentEditorItem = item;
                 break;
              }
           }


           // free up Part Handler Strings, strarray
           for ( i = 0; strarray[i] != NULL; i++)
           {
               delete[] strarray[i];
               strarray[i] = NULL;
           }


        }
        else // list was empty, return error code saying so
        {

            WARNMSG(WARN_INDEX(AMSG_903),
              "Couldn't load Part Handler list.");
        }

}

//------------------------------------------------------------------------------
// EnableApplModal - Simulates application modality by disabling/enabling
//                   all the OD windows except the window which owns the dialog.
//------------------------------------------------------------------------------
void EnableApplModal(Environment *ev, ODWindowState *winState, HWND hwnd,
                     BOOL enable)
{
    ODWindowIterator *iter = kODNULL;
    ODWindow         *curWindow;

    SOM_TRY
        // Disable/Enable mouse and keyboard input to all the OD windows
        // except the one which is going to own the display dialog.
        //
        // Note: The window which is going to own the display dialog is
        //       disable/enable by the system.
        iter = winState->CreateWindowIterator(ev);
        for (curWindow = iter->First(ev); iter->IsNotComplete(ev);
             curWindow = iter->Next(ev))
        {
            HWND platformWindow = curWindow->GetPlatformWindow(ev);
            if (platformWindow != hwnd)
               EnableWindow(platformWindow, enable);
        }
        ODDeleteObject(iter);

    SOM_CATCH_ALL
        LOG("SOM exception occured in EnableApplModal");
        ODDeleteObject(iter);

    SOM_ENDTRY
}
