/* @(#) 1.59 nt/src/docshell/WinShUtl.cpp, odshell, od96nt, odnt9712d 3/18/97 14:18:42 [3/21/97 17:19:23] */
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odshell
//
//   CLASSES: none
//
//   ORIGINS: 27
//
//
//   (C) COPYRIGHT International Business Machines Corp. 1995,1996
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//   	
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//====END_GENERATED_PROLOG========================================
//

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  This file contains utility functions, primarily dialog related, used by   //
//  the Shell classes.                                                        //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#include <DocMgr.xh>
#include <WinShell.xh>
#include <WinStat.xh>
#include <Window.xh>
#include <CmdDefs.xh>
#include <WinIter.xh>
#include <ODPrtReg.xh>
#include <ODPrtRei.xh>

#ifdef _PLATFORM_WIN32_
#ifndef SOM_ODSession_xh
#include <ODSessn.xh>
#endif
#ifndef SOM_ODHelp_xh
#include <ODHelp.xh>
#endif
#ifndef _HLPPANELS_
#include <hlppanls.h>
#endif
#endif //_PLATFORM_WIN32_

#include <TempObj.h>
#include <ODTypes.h>
#include <DraftWn.h>
#include <ISOStr.h>
#include <ODRegApi.h>
#include <odres.h>
#include <stdio.h>
#include "DocShell.h"

/* System property sheet */
#include <commctrl.h>
#include <prsht.h>              

WinShell  *shell;

struct DocInfo {
    ODULong                  textType;
    char                     selText  [kODMaxLength];
    ODUShort                 selIndex;
    _IDL_SEQUENCE_ISOString  kindList;
};

// Used for the Draft History dialog.
struct DraftHistInfo {
    DraftWindow*  dwThis;
    DraftInfoRec* draftInfoRec;
};

// used for the Create Draft dialog.
struct DraftInfo {
    ODULong   draftNum;
    char      name     [kODMaxNameLength];
    char      comment  [kODMaxLength];
    ODBoolean cancel;
};

#include "ShellUtl.h"

#undef LOGGING
#define LOGGING 1

//------------------------------------------------------------------------------
// SetShell - Sets the shell static global variable for other functions
//              in this file to use.
//------------------------------------------------------------------------------
SOMEXTERN void SOMLINK SetShell(WinShell *somSelf)
{
    shell = somSelf;
}

//------------------------------------------------------------------------------
// SelectKindDlg - invokes the Select Part Kind Dialog.
//------------------------------------------------------------------------------
SOMEXTERN ODULong SOMLINK SelectKindDlg(Environment *ev, char* selText)
{
    DocInfo docInfo;
    WindowSystemData *windowSystemData = NULL;

    try
    {
      windowSystemData = shell->GetWindowSystemData(ev);
    }
    catch (ODException _exception)
    {
      LOG("Exception occured in SelectKindDlg.\n");
      throw;
    }

    // Make sure selText is initialized as a null string.
    selText[0] = '\0';

    // Initialize textType to kODCommandCancel
    docInfo.textType = kODCommandCancel;
    docInfo.kindList._length = 0;

    if (windowSystemData)
    DialogBoxParam(shell->GetWindowSystemData(ev)->resInstance,
                   MAKEINTRESOURCE(IDD_SELPARTKIND),
                   windowSystemData->parentWindow,
                   (FARPROC) SelectKindDialogFunc, (LPARAM) &docInfo);

    if ((docInfo.textType == kODKindName) && (docInfo.kindList._length))
        strcpy (selText,docInfo.kindList._buffer[docInfo.selIndex]);
    else if (docInfo.textType == kODFileName) 
        strcpy(selText,docInfo.selText);

    // Free the kind list that was saved in docInfo.kindList during the
    // dialog initialization.
    for ( int i = 0; i < docInfo.kindList._length; i++)
        SOMFree( docInfo.kindList._buffer[i]);
    SOMFree( docInfo.kindList._buffer);

    return docInfo.textType;
}

//------------------------------------------------------------------------------
// DraftHistoryDlg - invokes the Draft History Property Sheet.
//------------------------------------------------------------------------------
SOMEXTERN void SOMLINK DraftHistoryDlg(Environment *ev, DraftWindow *dwThis)
{
    PROPSHEETPAGE   sheet[MAXPROPPAGES];
    PROPSHEETHEADER head;
    DraftHistInfo   *dhInfo; 
    DraftInfoRec    *pTraverse;
    int             index = 0; 
    char 	    *pageTitle, *draftLabel;
    char 	    draftNum[kODNumLength +1];

    try
    {
      // 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, dwThis->GetWindow(), FALSE);
  
      // If there are drafts, create and invoke the draft history dialog.
      if (dwThis->GetDraftInfoList())
      {
        // Get Draft label from catalog.
        draftLabel = catgets(ODcat_handle, DOCSH_SET, DOCMSG_18, "Draft");
    
        // While there are drafts in the list, add them to the dialog list.
        // NOTE: Property Sheet can only contain MAXPROPPAGES number of pages.
        // If there are more than MAXPROPPAGES drafts, we simply don't 
        // display the earliest drafts.
        for (pTraverse = dwThis->GetDraftInfoList(); 
             (pTraverse != NULL) && (index < MAXPROPPAGES); 
             pTraverse = pTraverse->GetNext(), index++) 
        {
          // Allocate space to save vital information.
          dhInfo = (DraftHistInfo*) malloc (sizeof(DraftHistInfo));
    
          // Fill page title with draft number.
          pageTitle = (char *) malloc (strlen(draftLabel) + kODNumLength + 2);
          sprintf (draftNum, "%d", pTraverse->GetDraftNum());
          sprintf (pageTitle,"%s %s", draftLabel, draftNum);
    
          // Save pointer to Draft Window object caller, and DraftInfoRec 
          // associated with this page. 
          dhInfo->dwThis = dwThis;
          dhInfo->draftInfoRec = pTraverse;
    
          sheet[index].dwSize     = sizeof(PROPSHEETPAGE);
          sheet[index].dwFlags    = PSP_HASHELP | PSP_USETITLE;
          sheet[index].hInstance  = shell->GetWindowSystemData(ev)->resInstance;
          sheet[index].pszTemplate = MAKEINTRESOURCE(IDD_DRAFTHISTORYDLG);
          sheet[index].pfnDlgProc = (FARPROC) DraftDialogFunc;
          sheet[index].pszTitle   = pageTitle;
          sheet[index].lParam     = (LONG) dhInfo;
        }
    
        head.dwSize              = sizeof(PROPSHEETHEADER);
        head.dwFlags             = PSH_PROPSHEETPAGE | PSH_HASHELP;
        head.hwndParent          = dwThis->GetWindow();
        head.hInstance           = shell->GetWindowSystemData(ev)->resInstance;
        head.pszCaption          = catgets(ODcat_handle, DOCSH_SET, DOCMSG_77, 
                                                              "Draft History");
        head.nPages              = index;
        head.nStartPage          = 0;
        head.ppsp                = (LPCPROPSHEETPAGE) &sheet;
    
        PropertySheet(&head);
    
        // free memory allocated for each sheet.
        while (index > 0) 
        {
          index--;
          free ((void *) sheet[index].pszTitle);
          free ((void *) sheet[index].lParam);
        }
      }
      else // No drafts.
          MessageBox(dwThis->GetWindow(),
                     catgets(ODcat_handle,DOCSH_SET,DOCMSG_1,
                       "No drafts exist for this document."),
                     catgets(ODcat_handle,DOCSH_SET,DOCMSG_2,
                       "Information"),
                     MB_OK);
      
      EnableApplModal(ev, dwThis->GetWindow(), TRUE);

      // delete Draft Window object that invoked this function.
      delete dwThis;
  
    }
    catch (ODException _exception)
    {
       LOG("Exception occured in DraftWindow::DraftHistory\n");
       RestoreApplModal(dwThis->GetWindow());
       if (dwThis) delete dwThis;
       throw;
    }
}

//------------------------------------------------------------------------------
// CreateDraftDlg - invokes the Create Draft Dialog.
//------------------------------------------------------------------------------
SOMEXTERN void SOMLINK CreateDraftDlg(Environment *ev, ODULong draftNum)
{
    HWND hwnd = kODNULL;
    try
    {
      DraftInfo draftInfo;
      ODWindowState* WinStat = shell->GetWindowState(ev);

      // Need to encapsulate this so it will be released when going out
      // of scope.
      {
        // Use TempODWindow so this object won't have to be released.
        TempODWindow Window = WinStat->AcquireActiveWindow(ev);
        hwnd = Window->GetPlatformWindow(ev);
      }

      // Use a staticly defined variable to pass in draft number
      draftInfo.draftNum = draftNum;
      draftInfo.cancel = kODFalse;

      // 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, hwnd, FALSE);
      DialogBoxParam(shell->GetWindowSystemData(ev)->resInstance,
                     MAKEINTRESOURCE(IDD_CREATEDRAFTDLG), hwnd,
                     (FARPROC) CreateDialogFunc, (LPARAM) &draftInfo);

      EnableApplModal(ev, hwnd, TRUE);

      // If user didn't choose cancel on Create Draft dialog.
      if (!draftInfo.cancel)
      // Call DocumentManager to create draft.
      shell->GetActiveDocumentManager(ev)->CreateDraft(ev,
          draftInfo.draftNum,
          CreateIText(smRoman,langEnglish, draftInfo.name),
          CreateIText(smRoman,langEnglish, draftInfo.comment));

    }
    catch (ODException _exception)
    {
      LOG("OpenDoc exception occured in CreateDraftDlg\n");
      if (hwnd)
         RestoreApplModal(hwnd);
      throw;
    }
}

//------------------------------------------------------------------------------
// ConfirmCloseDlg - invokes a confirmation dialog when close is selected from
//                   document menu or window menu and draft has unsaved changes.
//------------------------------------------------------------------------------
SOMEXTERN ODULong SOMLINK ConfirmCloseDlg(Environment *ev)
{

    int result;
    HWND hwnd = kODNULL;

    try
    {
      ODWindowState* WinStat = shell->GetWindowState(ev);
      // Use TempODWindow so this object won't have to be released.
      TempODWindow Window = WinStat->AcquireActiveWindow(ev);
      hwnd = Window->GetPlatformWindow(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, hwnd, FALSE);
      result =
           MessageBox(hwnd,
                      catgets(ODcat_handle,DOCSH_SET,DOCMSG_8,
                        "Do you want to save your changes?"),
                      catgets(ODcat_handle,DOCSH_SET,DOCMSG_9,
                        "Close Confirmation"),
                      MB_YESNOCANCEL);
      EnableApplModal(ev, hwnd, TRUE);

    }
    catch (ODException _exception)
    {
      LOG("OpenDoc exception occured in ConfirmCloseDlg\n");
      if (hwnd)
         RestoreApplModal(hwnd);
      throw;
    }

    switch (result) {
      case IDNO:
         return kODCommandDiscardChanges;
      case IDYES:
         return kODCommandSaveChanges;
      case IDCANCEL:
      default:
         return kODCommandCancel;
    }
}

//------------------------------------------------------------------------------
// ConfirmExitDlg - invokes an exit confirmation dialog when close is
//                   selected from document or window menu and draft has
//                   no unsaved changes.
//------------------------------------------------------------------------------
SOMEXTERN ODULong SOMLINK ConfirmExitDlg(Environment *ev)
{

    int result;
    HWND hwnd = kODNULL;

    try
    {
      ODWindowState* WinStat = shell->GetWindowState(ev);
      // Use TempODWindow so this object won't have to be released.
      TempODWindow Window = WinStat->AcquireActiveWindow(ev);
      hwnd = Window->GetPlatformWindow(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, hwnd, FALSE);
      result =
           MessageBox(hwnd,
                      catgets(ODcat_handle,DOCSH_SET,DOCMSG_25,
                        "Do you want to close this document?"),
                      catgets(ODcat_handle,DOCSH_SET,DOCMSG_26,
                        "Exit Confirmation"),
                      MB_YESNO);
      EnableApplModal(ev, hwnd, TRUE);

    }
    catch (ODException _exception)
    {
      LOG("OpenDoc exception occured in ConfirmExitDlg\n");
      if (hwnd)
         RestoreApplModal(hwnd);
      throw;
    }

    switch (result) {
      case IDYES:
         return kODCommandDiscardChanges;
      case IDNO:
      default:
         return kODCommandCancel;
    }
}

//------------------------------------------------------------------------------
// ConfirmRevertDlg - invokes a dialog confirming user's request to revert to
//                    a previous draft.
//------------------------------------------------------------------------------
SOMEXTERN ODBoolean SOMLINK ConfirmRevertDlg(Environment *ev)

{
    int result;
    HWND hwnd = kODNULL;

    try
    {

      ODWindowState* WinStat = shell->GetWindowState(ev);
      // Use TempODWindow so this object won't have to be released.
      TempODWindow Window = WinStat->AcquireActiveWindow(ev);
      hwnd = Window->GetPlatformWindow(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, hwnd, FALSE);
      result = MessageBox(hwnd,
                    catgets(ODcat_handle,DOCSH_SET,DOCMSG_10,
                      "Do you want to revert to the last saved version of this document?"),
                    catgets(ODcat_handle,DOCSH_SET,DOCMSG_11,
                      "Revert Confirmation"),
                    MB_OKCANCEL);
      EnableApplModal(ev, hwnd, TRUE);

    }
    catch (ODException _exception)
    {
      LOG("OpenDoc exception occured in ConfirmRevertDlg\n");
      if (hwnd)
         RestoreApplModal(hwnd);
      throw;
    }

    switch (result) {
      case IDOK:
         return kODTrue;
      case IDCANCEL:
      default:
         return kODFalse;
    }

}

//------------------------------------------------------------------------------
// AboutDlg - invokes Message Box dialog when "OpenDoc Information" is
//            selected from the Help menu.
//------------------------------------------------------------------------------
SOMEXTERN void SOMLINK AboutDlg (Environment *ev)

{
      HWND hwnd = 0;
      ODWindowState* winState = shell->GetWindowState(ev);

      // Need to encapsulate this so it will be released when going out
      // of scope.
      {
        // Use TempODWindow so this object won't have to be released.
        TempODWindow Window = winState->AcquireActiveWindow(ev);
        hwnd = Window->GetPlatformWindow(ev);
      }

      EnableApplModal(ev, hwnd, FALSE);
      MessageBox(hwnd,
                 catgets(ODcat_handle,DOCSH_SET,DOCMSG_16,
                 "          IBM OpenDoc(R)  Version 1.2\n\n(c) Copyright IBM 1997, all rights reserved.\n\nOpenDoc is a trademark of Apple Computer Inc.,\nregistered in the United States and other countries."),
                 catgets(ODcat_handle,DOCSH_SET,DOCMSG_2,
                 "Information"),
                 MB_OK | MB_ICONINFORMATION);
      EnableApplModal(ev, hwnd, TRUE);
}

//------------------------------------------------------------------------------
// OpenFileDlg - invokes the common Windows Open File dialog box.
//------------------------------------------------------------------------------
SOMEXTERN void SOMLINK OpenFileDlg(HWND hwnd, char* docName)
{
    Environment* ev = somGetGlobalEnvironment();

    // MAX_PATH is a Windows defined constant located in one of the windows .h
    // files.  It cannot be changed.
    char    		szFile[MAX_PATH];
    OPENFILENAME 	of;

    // Display the common fileopen dialog

    memset( &of, '\0', sizeof( of ) );
    lstrcpy( szFile, "*.od" );

    of.lStructSize  	= sizeof( OPENFILENAME );
    of.hwndOwner    	= hwnd;
    of.lpstrFilter  	= (LPSTR) catgets(ODcat_handle,DOCSH_SET,DOCMSG_14,
                          "OpenDoc Documents (*.od)\0*.od\0All (*.*)\0*.*\0");
    of.lpstrCustomFilter= NULL;
    of.nFilterIndex 	= 1;
    of.lpstrFile    	= (LPSTR) szFile;
    of.nMaxFile     	= MAX_PATH;
    of.lpstrInitialDir 	= NULL;
    of.lpstrTitle   	= NULL;
    of.Flags        	= OFN_HIDEREADONLY|OFN_FILEMUSTEXIST;
    of.lpstrDefExt  	= "od";

    try
    {
       // 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, hwnd, FALSE);
       // return the selected filename
       if (GetOpenFileName(&of))
         lstrcpy((LPSTR) docName, of.lpstrFile);
       EnableApplModal(ev, hwnd, TRUE);
    }
    catch (ODException _exception)
    {
      LOG("OpenDoc exception occured in OpenFileDlg\n");
      if (hwnd)
         RestoreApplModal(hwnd);
      throw;
    }
}


//------------------------------------------------------------------------------
// SaveFileDlg - invokes the common Windows Save File dialog box.
//------------------------------------------------------------------------------
SOMEXTERN PlatformFile* SOMLINK SaveFileDlg(Environment *ev)
{

    char    		szFile[MAX_PATH];
    OPENFILENAME 	of;
    PlatformFile        *file = kODNULL;
    HWND                hwnd = kODNULL;

    // Display the common fileopen dialog

    try
    {
      memset( &of, '\0', sizeof( of ) );
      lstrcpy( szFile, "*.od" );

      ODWindowState* WinStat = shell->GetWindowState(ev);
      // Use TempODWindow so this object won't have to be released.
      TempODWindow Window = WinStat->AcquireActiveWindow(ev);
      hwnd = Window->GetPlatformWindow(ev);

      of.lStructSize  	= sizeof( OPENFILENAME );
      of.hwndOwner    	= hwnd;
      of.lpstrFilter  	= (LPSTR) catgets(ODcat_handle,DOCSH_SET,DOCMSG_14,
                          "OpenDoc Documents (*.od)\0*.od\0All (*.*)\0*.*\0");
      of.lpstrCustomFilter= NULL;
      of.nFilterIndex 	= 1;
      of.lpstrFile    	= (LPSTR) szFile;
      of.nMaxFile     	= MAX_PATH;
      of.lpstrInitialDir= NULL;
      of.lpstrTitle   	= NULL;
      of.Flags        	= OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|
                          OFN_EXTENSIONDIFFERENT|OFN_PATHMUSTEXIST;
      of.lpstrDefExt  	= "od";

      // 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, hwnd, FALSE);
      // If the user selects a file then create a new file object and
      //    specify the file name.
      if (GetSaveFileName(&of))
      {
	  file = new PlatformFile;
          file->Specify((ODFileSpec *) of.lpstrFile);
      }
      EnableApplModal(ev, hwnd, TRUE);

    }
    catch (ODException _exception)
    {
       LOG("OpenDoc exception occured in SaveFileDlg\n");

       // Clean up
       if (file)
          delete file;
       file = kODNULL;

       if (hwnd)
          RestoreApplModal(hwnd);
       throw;
    }

    return file;
}

//----------------------------------------------------------------------------
// CreateDialogFunc - Dialog Box Function for Create Draft confirmation dialog
//----------------------------------------------------------------------------
SOMEXTERN BOOL SOMLINK CALLBACK CreateDialogFunc(HWND hdwnd, UINT message,
                               WPARAM wParam, LPARAM draftInfo)
{
  char         DraftNumStr[kODNumLength];
  ODBoolean    retCode = kODTrue;

    switch (message)
    {
      //------------------------------------------------------
      //  Initialize the create draft dialog
      //------------------------------------------------------
      case WM_INITDIALOG:
      {
          // save handle to the DraftInfo structure passed in as lparam
          SetWindowLong(hdwnd, GWL_USERDATA, (DWORD) draftInfo);

          // Increment the draft number
          ((DraftInfo*) draftInfo)->draftNum++;

          // Need to convert draft # to an ascii string for dialog.
          sprintf(DraftNumStr,"%d",((DraftInfo*) draftInfo)->draftNum);

          // Set the draft number in dialog message
          SetDlgItemText(hdwnd, DID_DRAFTNUM, DraftNumStr);

          // Limit the amount of text that can be entered in the name
          // and comments fields
          SendDlgItemMessage(hdwnd,DID_DRAFTNAME,EM_SETLIMITTEXT,
                                                 kODMaxNameLength,0);
          SendDlgItemMessage(hdwnd,DID_DRAFTCOMMENT,EM_SETLIMITTEXT,
                                                 kODMaxLength,0);

          break;
      }

      case WM_HELP:
      {
        Environment* ev = somGetGlobalEnvironment();
        try
        {
          ODSession * session = shell->GetSession(ev);
          ODHelp    * helpme  = session->GetHelp(ev);
          helpme->DisplayHelp(ev,ODHELPFILE,IDMS_DR_DRAFT_CREATEDRAFT_PANEL);
        }
        catch (ODException _exception)
        {
           SetErrorCodeEv(ev, kODNoError);
        }

        break;
      }

      case WM_COMMAND:
      {
        // retrieve handle to the DraftInfo structure attached to window.
        // in WM_INITDIALOG case above.
        draftInfo = GetWindowLong(hdwnd, GWL_USERDATA);

        switch (LOWORD(wParam))
        {
          // User cancelled dialog
          case IDCANCEL:
          {
              // Need to pass this information back to caller.
              ((DraftInfo*) draftInfo)->cancel = kODTrue;

              EndDialog(hdwnd,0);
              break;
          }

          // User asked to go ahead and save a draft.
          case IDOK:
          {

              // Get the text from the name field.
              GetDlgItemText(hdwnd, DID_DRAFTNAME,
                             ((DraftInfo*) draftInfo)->name, kODMaxNameLength);

              // Get the text from the comment field.
              GetDlgItemText(hdwnd, DID_DRAFTCOMMENT,
                             ((DraftInfo*) draftInfo)->comment, kODMaxLength);

              EndDialog(hdwnd,0);
              break;
           }

          case DID_HELP:
          {
            Environment* ev = somGetGlobalEnvironment();
            try
            {
              ODSession * session = shell->GetSession(ev);
              ODHelp    * helpme  = session->GetHelp(ev);
              helpme->DisplayHelp(ev,ODHELPFILE,IDMS_DR_DRAFT_CREATEDRAFT_PANEL);
            }
            catch (ODException _exception)
            {
               SetErrorCodeEv(ev, kODNoError);
            }

            break;
          }

           default:
              retCode = kODFalse;

        } // switch (LOWORD(wParam))

        break;

      } // case WM_COMMAND

      default:
        retCode = kODFalse;

    } // switch (message)

  return retCode;
}

//----------------------------------------------------------------------------
// SelectKindDialogFunc - Dialog Box Function for Select Part Kind dialog.
//----------------------------------------------------------------------------
SOMEXTERN BOOL SOMLINK CALLBACK SelectKindDialogFunc(HWND hdwnd, UINT message,
                               WPARAM wParam, LPARAM docInfo)
{
  ODBoolean retCode = kODTrue;

  switch (message)
  {
      //------------------------------------------------------
      //  Initialize the select part kind dialog
      //------------------------------------------------------
      case WM_INITDIALOG:
      {
        // save handle to the DraftInfo structure passed in as lparam
        SetWindowLong(hdwnd, GWL_USERDATA, (DWORD) docInfo);

        Environment              *ev = somGetGlobalEnvironment();
        ISOString                displayName;
        ODSession                *session;
        ODPartHandlerRegistryInt *registry;
        _IDL_SEQUENCE_ISOString  kindList;

        try
        {
           // Get the registered part kind display names
           session = shell->GetSession(ev);
           registry = session->GetRegistry(ev);
           kindList = registry->GetPartKindList(ev, kODNULL,kODNULL);
           
           // Hold onto registry information to pass back to caller.
           ((DocInfo*) docInfo)->kindList = kindList;

           // If there are part kinds registered
           if (kindList._length)
           {
               for ( int i = 0; i < kindList._length; i++)
               {
                   // Get display name to show in the dialog.
                   displayName = registry->GetKindDisplayNameFromKind(ev,
                                                       kindList._buffer[i]);
                   SendDlgItemMessage(hdwnd, DID_KINDLIST, LB_ADDSTRING, 0,
                                                           (LPARAM)displayName);
               }

               // Set maximum width of dialog list entries.
               SendDlgItemMessage(hdwnd, DID_KINDLIST, LB_SETHORIZONTALEXTENT,
                                                               (WPARAM) 800, 0);

               // Set the cursor position to the 1st entry.
               SendDlgItemMessage(hdwnd, DID_KINDLIST, LB_SETCURSEL, 0, 0);

           } else {
               WARNMSG(WARN_INDEX(AMSG_560),
                  "Docshell: Couldn't load Part Kind list.");

               ((DocInfo *) docInfo)->textType = kODNoRootPart;

               EndDialog(hdwnd, 0);
           }

        }
        catch (ODException _exception)
        {
           EndDialog(hdwnd, 0);

           // Free data structure returned by registry.
           ((DocInfo *) docInfo)->textType = kODNoRootPart;
           for ( int i = 0; i <  kindList._length; i++)
              SOMFree( kindList._buffer[i]);
           SOMFree( kindList._buffer);

           throw;
        }
        break;
      }

      case WM_HELP:
      {
        Environment* ev = somGetGlobalEnvironment();
        try
        {
          ODSession * session = shell->GetSession(ev);
          ODHelp    * helpme  = session->GetHelp(ev);
          helpme->DisplayHelp(ev,ODHELPFILE,IDMS_SELECT_ROOT_KIND_PANEL);
        }
        catch (ODException _exception)
        {
           SetErrorCodeEv(ev, kODNoError);
        }

        break;
      }

      case WM_COMMAND:
      {
        // retrieve handle to the selPartKind structure attached to window.
        // in WM_INITDIALOG case above.
        docInfo = GetWindowLong(hdwnd, GWL_USERDATA);

        switch (LOWORD(wParam))
        {
          // User cancelled dialog
          case IDCANCEL:
          {
            ((DocInfo*) docInfo)->textType = kODCommandCancel;
            EndDialog(hdwnd,0);
            break;
          }

          // user double clicks in Kinds List.
          case DID_KINDLIST:
          {
            if(HIWORD(wParam)==LBN_DBLCLK)
              {
                ((DocInfo*) docInfo)->selIndex = 
                    SendDlgItemMessage(hdwnd, DID_KINDLIST, LB_GETCURSEL, 0, 0);

                ((DocInfo*) docInfo)->textType = kODKindName;

                EndDialog(hdwnd,0);
              }

            break;
          }

          case IDOK:
          {
            ((DocInfo*) docInfo)->selIndex = 
                    SendDlgItemMessage(hdwnd, DID_KINDLIST, LB_GETCURSEL, 0, 0);

            ((DocInfo*) docInfo)->textType = kODKindName;

            EndDialog(hdwnd,0);
            break;
          }

          case DID_OPENFILE:
          {
            
            // Initialized selection text to NULL so we know whether
            // anything is selected within the Open File dialog, or 
            // whether cancel was chosen.
            ((DocInfo*) docInfo)->selText[0] = '\0';

            // Display the Open File dialog and return the result.
            OpenFileDlg (hdwnd,((DocInfo*) docInfo)->selText);

            // If a filename was selected, end select kind dialog.
            if (((DocInfo*) docInfo)->selText[0] != '\0')
            {
              EndDialog(hdwnd,0);
              ((DocInfo*) docInfo)->textType = kODFileName;
            }
            break;
          }

          case DID_HELP:
          {
            Environment* ev = somGetGlobalEnvironment();
            try
            {
              ODSession * session = shell->GetSession(ev);
              ODHelp    * helpme  = session->GetHelp(ev);
              helpme->DisplayHelp(ev,ODHELPFILE,IDMS_SELECT_ROOT_KIND_PANEL);
            }
            catch (ODException _exception)
            {
               SetErrorCodeEv(ev, kODNoError);
            }

            break;
          }

          default:
            retCode = kODFalse;

        } // switch (LOWORD(wParam))

        break;

      } // case WM_COMMAND

      default:
        retCode = kODFalse;

  } // switch (message)

  return retCode;
}

//----------------------------------------------------------------------------
// Dialog Box Function for viewing document drafts
//----------------------------------------------------------------------------
SOMEXTERN BOOL SOMLINK CALLBACK DraftDialogFunc(HWND hdwnd, UINT message, 
                                                   WPARAM wParam, LPARAM lParam)
{
  PROPSHEETPAGE        *prop;
  Environment          *ev = somGetGlobalEnvironment();
  ODULong              result, index;
  DraftHistInfo        *dhInfo = kODNULL;
  DraftWindow          *dwThis = kODNULL;
  DraftInfoRec         *dInfoRec = kODNULL;
  ODBoolean            retCode = kODTrue;
  ODBoolean            dialogDismissed = kODFalse;
  ODIText              *tmpName, *tmpComment;
  char                 name[kODMaxNameLength] = "";
  char                 date[kODDateLength]    = "";
  char                 comments[kODMaxLength] = "";

  try
  {

    switch (message)
    {
      //------------------------------------------------------
      //  Initialize the draft page.
      //------------------------------------------------------
      case WM_INITDIALOG:
      {
        // get necessary information from incoming lParam structure 
        prop = (PROPSHEETPAGE*) lParam;
        dhInfo = (DraftHistInfo*) prop->lParam;
        dInfoRec = (DraftInfoRec*) dhInfo->draftInfoRec;
        
        if (!dInfoRec) break;

        // save handle to this object structure passed in as lParam
        SetWindowLong(hdwnd, GWL_USERDATA, lParam);

        // Initialize the locale.
        setlocale (LC_ALL, "");

        // Get the name of last user to modify draft
        if (tmpName = dInfoRec->GetModUser())
        {
           GetITextString(tmpName, name);
           SetDlgItemText(hdwnd, DID_CREATOR, name);
        }
  
        // Get the date the draft was last modified 
        ODULong time = dInfoRec->GetSavedDate();
        if (time)
        {
          char* dateFormat = nl_langinfo(D_T_FMT);
          struct tm *timeptr = localtime((const time_t*) &time);
          strftime (date, sizeof(date) - 1, dateFormat, timeptr);
          SetDlgItemText(hdwnd, DID_CREATED, date);
        }
 
        if (tmpComment = dInfoRec->GetComment())
        {
          GetITextString(tmpComment, comments);
          SetDlgItemText(hdwnd, DID_CMNT, comments);
        }

        // Disable the Delete button if document is read-only
        ODDraft* draft = shell->GetActiveDocumentManager(ev)->GetDraft(ev);
        if (draft && !(draft->GetPermissions(ev) >= kODDPSharedWrite))
        {
          hdwnd = GetDlgItem(hdwnd, DID_DELETE);
          EnableWindow(hdwnd, 0);
        }

        // Disable the cancel button and change text of OK to Close.
        // This will make for sense to the user since this dialog doesn't
        // allow any modifications which makes the Cancel button behave
        // exactly like the OK button.
        PropSheet_CancelToClose(prop);

        break;

      } // WM_INITDIALOG

      case WM_HELP:
      {
        ODSession * session = shell->GetSession(ev);
        ODHelp    * helpme  = session->GetHelp(ev);
        helpme->DisplayHelp(ev,ODHELPFILE, IDMS_DOC_DRAFTS_PANEL);
        break;
      }

      case WM_COMMAND:
      {
        // Retrieve handle to dhInfo.
        prop = (PROPSHEETPAGE*) GetWindowLong(hdwnd, GWL_USERDATA);
        dhInfo = (DraftHistInfo*) prop->lParam;
        dwThis = (DraftWindow*) dhInfo->dwThis;
        dInfoRec = (DraftInfoRec*) dhInfo->draftInfoRec;

        // Break out if there is a problem retrieving these structures
        if (!dwThis || !dInfoRec) break;

        switch (LOWORD(wParam))
        {
          case DID_OPEN:
          {
            if (!(dwThis->OpenDraft(NULL, dInfoRec)))
              WARNMSG(WARN_INDEX(AMSG_890),
                "CPPOD0402 - Unable to open draft.");
            else
            {
              // Send message to close entire property sheet down.
              HWND parent = GetParent(hdwnd);
              SendMessage(parent, WM_COMMAND,(WPARAM) IDOK, 
                          (LPARAM) GetDlgItem(parent, IDOK));
              dialogDismissed = kODTrue;
            }
            break;

          } // case DID_OPEN

          case DID_DELETE:
          {
            // Display confirmation dialog and let the DeleteDialogProc
            // take the steps necessary to delete based on users response.
            result = MessageBox(hdwnd,
                         catgets(ODcat_handle,DOCSH_SET,DOCMSG_5,
                           "Are you sure you want to delete this draft?"),
                         catgets(ODcat_handle,DOCSH_SET,DOCMSG_6,
                           "Delete Confirmation"),
                         MB_OKCANCEL);

            if (result == IDOK)
            {
	      // Need to disable the draft history dialog. Otherwise, if
	      // a warning message is displayed in DeleteDraft method of
	      // document manager, then the user can go to the draft
	      // history window to close the draft history dialog causing
	      // docshell to trap when returning from docmgr.
	      EnableWindow(hdwnd, FALSE);

{             // This is a hack to get around a problem with the call to 
              // PropSheet_RemovePage below.  It won't remove the page based 
              // on the PROPSHEETPAGE* passed in as it is supposed 
              // to, so I have to find the index of the page to remove.
              // The only way to do this is to traverse the list of 
              // DraftInfoRecs associated with dwThis and get the position of  
              // the one that matches dInfoRec.  This has to be done before I
              // remove the draft and thus the DraftInfoRec associated with it.
              index = 0;  
              for (DraftInfoRec* pTraverse = dwThis->GetDraftInfoList();
                   pTraverse != NULL;
                   index++, pTraverse = pTraverse->GetNext()) 
                if (pTraverse == dInfoRec) break;
}

              // Remove the draft from the dialog list and storage.  
              if (dwThis->RemoveDraft(NULL, dInfoRec))
              {
                // Need to disable all the ODwindows because if
                // the draft above the deleted draft is opened, then
                // the window containing the above draft is closed and
                // opened again to point to the correct draft due to
                // collapse of draft. By doing so, the new window opened
                // is not disabled.
	        EnableApplModal(ev, NULL, FALSE);

                // Remove draft page.
                PropSheet_RemovePage(GetParent(hdwnd), index, prop);
              }
              else
                // notify user of failure
                WARNMSG(WARN_INDEX(AMSG_900), 
                         "CPPOD0403 - Unable to delete draft.");
   
	      // Enable back the draft history dialog.
	      EnableWindow(hdwnd, TRUE);

              // Set draft history dialog to be the active window
              SetActiveWindow(hdwnd);

              // Need to reaquire the list from the document manager in
              // the event that by deleting the last element on the list,
              // the head list pointed to by fDraftInfoList has changed.
              dwThis->SetDraftInfoList(
                         dwThis->GetActiveDocumentManager()->GetDraftList(ev));

              // if the draft history info list is now empty, end dialog.
              if (!dwThis->GetDraftInfoList())
              {
                EndDialog(hdwnd,0);
                dialogDismissed = kODTrue;
              }

            } // result == IDOK

            break;
          } // case DID_DELETE

          case IDCANCEL:     // Escape pressed.  Need to cleanup.
          {
            // Set indicator since this case will cause dialog to be dismissed.
            dialogDismissed = kODTrue;

            break;
          }

          default:
            retCode = kODFalse;
            break;
        }
        break;
      } // WM_COMMAND

      case WM_NOTIFY:
      {
        prop = (PROPSHEETPAGE*) GetWindowLong(hdwnd, GWL_USERDATA);
        dhInfo = (DraftHistInfo*) prop->lParam;
        dwThis = (DraftWindow*) dhInfo->dwThis;
        dInfoRec = (DraftInfoRec*) dhInfo->draftInfoRec;

        // Break out if there is a problem retrieving these structures
        if (!dwThis || !dInfoRec) break;
        
        switch (((NMHDR FAR *) lParam)->code)
        {
          case PSN_SETACTIVE:      
          {
            // Set return code.
            SetWindowLong(hdwnd, DWL_MSGRESULT, 0);

            break;
          }

          case PSN_APPLY:     // OK button pressed since APPLY is diabled.
          {
            // Set return code.
            SetWindowLong(hdwnd, DWL_MSGRESULT, PSNRET_NOERROR);

            // Set indicator since this case will cause dialog to be dismissed.
            dialogDismissed = kODTrue;

            break;
          }

          case PSN_KILLACTIVE:     // OK
          {
            // Allow window to lose activation.
            SetWindowLong(hdwnd, DWL_MSGRESULT, FALSE);

            break;
          }

          case PSN_RESET:     // Cancel pressed.  Need to cleanup.
          {
            // Set indicator since this case will cause dialog to be dismissed.
            dialogDismissed = kODTrue;

            break;
          }

          case PSN_HELP:
          {
            ODSession * session = shell->GetSession(ev);
            ODHelp    * helpme  = session->GetHelp(ev);

            helpme->DisplayHelp(ev,ODHELPFILE, IDMS_DOC_DRAFTS_PANEL);

            break;
          }

          default:
            retCode = kODFalse;
            break;
        } 

        break;

      } // WM_NOTIFY

      default:
          retCode = kODFalse;

    } // switch (message)

  }
  catch (ODException _exception)
  {
    LOG("OpenDoc exception occured in DraftDialogFunc\n");

    // If dialog hasn't already been dismissed, dismiss it.
    if (!dialogDismissed)
      EndDialog(hdwnd,0);

    throw;
  }

  return retCode;
}

//------------------------------------------------------------------------------
// ODDocumentWindowProc - Standard window procedure to run docshell window
//                        events
//------------------------------------------------------------------------------
SOMEXTERN LRESULT SOMLINK CALLBACK ODDocumentWindowProc(HWND window, UINT message,
                                                     WPARAM wParam, LPARAM lParam)
{

  Environment* ev = somGetGlobalEnvironment();
  ODBoolean handled = kODFalse;

  ODEventData *event = new ODEventData;
  event->hwnd = window;
  event->message = message;
  event->wParam = wParam;
  event->lParam = lParam;

  try
  {

    // Offer all messages to the dispatcher
    handled =  shell->DispatchEvent(ev, event);

    // Offer unhandled messages to the default window proc
    if (!handled)
       handled = DefWindowProc( window, message, wParam, lParam );


  }
  catch (ODException _exception)
  {
     LOG("OpenDoc exception occured in ODDocumentWindowProc\n");
     // Clear the exception 
     SetErrorCodeEv(ev, kODNoError);
  }

  delete event;
  return (handled);

}


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

    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.
	ODWindowState *windowState = shell->GetWindowState(ev);
        if (windowState)
        {
            iter = windowState->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);
        }

    }
    catch (ODException _exception)
    {
        LOG("OpenDoc exception occured in EnableApplModal\n");
        ODDeleteObject(iter);
        throw;
    }
}


//------------------------------------------------------------------------------
// ReadOnlyDlg - brings up an alert dialog to warn user that the document
//                   is read-only and ask user whether to continue or not.
//------------------------------------------------------------------------------
SOMEXTERN ODBoolean SOMLINK ReadOnlyDlg(Environment *ev)
{

    int result;
    HWND hwnd = kODNULL;

    try
    {
      result = MessageBox(shell->GetWindowSystemData(ev)->parentWindow,
                      catgets(ODcat_handle,DOCSH_SET,DOCMSG_100,
                        "You are about to open a read-only document and will not be able to make changes to it. Do you want to open the document anyway?"),
                      catgets(ODcat_handle,DOCSH_SET,DOCMSG_101,
                        "Open Confirmation"),
                      MB_YESNO);
    }
    catch (ODException _exception)
    {
      LOG("OpenDoc exception occured in ReadOnlyDlg\n");
      throw;
    }

    switch (result) {
      case IDYES:
         return kODTrue;
      case IDNO:
      default:
         return kODFalse;
    }
}
