/*--------------------------------------------------------------------------*\
   Module:     cpl.c
   
   Purpose: The main entry point for the Control Panel, and the main
        top level dialog proc(s).
   
   History:
      7/27/93 CBB - Created
\*--------------------------------------------------------------------------*/

#include  <windows.h>
#include  <windowsx.h>
#include  <cpl.h>
#include  "tapicpl.h"        
#include  "help.h"
#include  "init.h"

#include  "drv.h"
#include  "util.h"
#include  "resource.h"
#include  "debug.h"
#include  <malloc.h>
#include  <prsht.h>  /* for PropertySheet defs */

//------------------
// Private Constants
//------------------
#ifdef CTL3D
#define  CTL3D_REGISTER       12       // ordinals for using CTL3D.DLL
#define  CTL3D_AUTOSUBCLASS   16
#define  CTL3D_UN_REGISTER    13
#define  CTL3D_COLOR_CHANGE   6
#endif /* CTL3D */

//-------------
// Private Data
//-------------
CPL   gCPL;       // app global

#ifndef _WIN32
#pragma code_seg ( "CPL_MAIN" )
#endif

// the following are not to be translated, so they can be static
#ifndef _WIN32  // don't need ctl3d.dll
#ifdef CTL3D
static char SEG_CPL gszCtl3DLib[] = "CTL3D.DLL";
#endif /* CTL3D */
#endif

//--------------------
// Function Prototypes
//--------------------
UINT PRIVATE   _ErrDoPropertySheet( HWND, WORD, DLGPROC, LPARAM );



extern UINT WINAPI ErrRefreshProviderList();




#ifdef CTL3D
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
VOID FAR PASCAL CplSysColorChange()
{
   FARPROC  lpfnCtl3DColorChange;

   // 3D control stuff
   //-----------------
   if ( gCPL.hCtl3DInst != NULL )      // does not happen very often
   {         
      lpfnCtl3DColorChange = GetProcAddress( gCPL.hCtl3DInst, MAKEINTRESOURCE( CTL3D_COLOR_CHANGE ));
      
      if ( lpfnCtl3DColorChange != NULL )
     (*lpfnCtl3DColorChange)();     // let him know
   }  // end if               
}
#endif /* CTL3D */

/*--------------------------------------------------------------------------*\

   Function:   CplInit
   
   Purpose:    Initalizes for the init dialog.  We postpone doing some 
           initalizing until now, so that the control panel won't take
           years to load...
   
\*--------------------------------------------------------------------------*/
UINT PRIVATE   CplInit( HWND     hWnd,
            BOOL     fUse3d,
            LPUINT   lpuUpdated )

{
   UINT  uResult;
   UINT  uOldErrMode;

   extern CPL     gCPL;       // app global

   gCPL.uInstances++;            // ONECPL:  CANNOT be used by multiple apps!
   
   if ( gCPL.uInstances == 1 )   // ONECPL
   {
      gCPL.hWnd = hWnd;          // ONECPL

#ifndef _WIN32
#ifdef CTL3D
      if ( fUse3d && (LOBYTE(LOWORD( GetVersion())) < 4))      // only for win3.1 and below
      {

          // init 3D control stuff
          //----------------------
          uOldErrMode = (UINT)SetErrorMode( SEM_NOOPENFILEERRORBOX );  // turn off that it can't find the library!
     
          gCPL.hCtl3DInst = LoadLibrary( gszCtl3DLib );
     
          SetErrorMode( uOldErrMode );                                 // restore the error mode!
     
          if (  gCPL.hCtl3DInst <= HINSTANCE_ERROR )
          {
              gCPL.hCtl3DInst = NULL;    // set back to default
          }
          else
          {
              // get all the procs that we need
              lpfnCtl3DRegister = GetProcAddress( gCPL.hCtl3DInst, MAKEINTRESOURCE( CTL3D_REGISTER ));
              lpfnCtl3DAutoSubclass = GetProcAddress( gCPL.hCtl3DInst, MAKEINTRESOURCE( CTL3D_AUTOSUBCLASS ));

              if ((lpfnCtl3DRegister == NULL) || (lpfnCtl3DAutoSubclass == NULL))
              {
                  // ah, didn't work, don't worry too much about it
                  FreeLibrary( gCPL.hCtl3DInst );
                  gCPL.hCtl3DInst = NULL;
              }
              else
              {      
                  // ok, looks like everything worked, register the lib
                  //---------------------------------------------------
                  (*lpfnCtl3DRegister)( gCPL.hCplInst );
                  (*lpfnCtl3DAutoSubclass)( gCPL.hCplInst );
              }

          }
      }
#endif /* CTL3D */
#endif
   
      *lpuUpdated = FALSE;       // I don't want to talk about it!

      // Initialize the list of service providers
      //-----------------------------------------
      if ( ErrRefreshProviderList() != CPL_SUCCESS )
      {
          return CPL_ERR_TAPI_FAILURE;
      }
      
      uResult = CPL_SUCCESS;                         // ONECPL
   }   
   else
   {
       /* Find the first instance main window, and post a message to it to tell it to activate itself */
       HWND hTopWindow = GetLastActivePopup( gCPL.hWnd );   // ONECPL

       ShowWindow( hTopWindow, SW_RESTORE );          // ONECPL
       BringWindowToTop( hTopWindow );                // ONECPL

       uResult = CPL_ERR_ALREADY_INITIALIZED;         // ONECPL
   }

   return( uResult );

}



/*--------------------------------------------------------------------------*\

   Function:   CplClose
   
   Purpose:    The dialog is being closed, write any necessary chagnes out,
           clean up all left over memmory and all that stuff...
   
\*--------------------------------------------------------------------------*/
UINT PUBLIC CplClose( UINT  uCommand )

   {
   UINT  uResult;
   FARPROC  lpfnCtl3DUnregister;
   extern CPL     gCPL;       // app global

   if (glpProviderList)
   {
    GlobalFreePtr(glpProviderList);
    glpProviderList = NULL;
   }
   
   // write any changes out to the ini file
   //--------------------------------------                  
   gCPL.uInstances = (gCPL.uInstances == 0) ? 0 : (gCPL.uInstances - 1);         // can be used by multiple apps!
   
   if ( gCPL.uInstances == 0 )
      {
      // delete all the left over lists
      //-------------------------------

#ifdef CTL3D
      if ( gCPL.hCtl3DInst != NULL )
     {         
     // clear 3D control stuff
     //-----------------------   
     lpfnCtl3DUnregister = GetProcAddress( gCPL.hCtl3DInst, MAKEINTRESOURCE( CTL3D_UN_REGISTER ));
     
     if ( lpfnCtl3DUnregister != NULL )
        (*lpfnCtl3DUnregister)( gCPL.hCplInst );     // let him know
        
     FreeLibrary( gCPL.hCtl3DInst );
     gCPL.hCtl3DInst = NULL;
     }  // end if
#endif /* CTL3D */
      }  // end if
      
   uResult = CPL_SUCCESS;
   
#ifndef _WIN32
      LocalCompact( CPL_HEAP_SIZE );     // shrink the local heap (WIN32 obsolete)
#endif      
      return( uResult );
}  // end function CplClose


/*--------------------------------------------------------------------------*\

   Function:   CplApplet
   
   Purpose: The Control Panel entry point, call back funcition...
   
\*--------------------------------------------------------------------------*/
extern char far gszHelpFile[];                                         

LONG
#if WIN32
 APIENTRY
#else
 EXPORT  
#endif
CPlApplet( HWND   hWndCpl,
            UINT   uMessage,
            LPARAM lParam1,
            LPARAM lParam2 )
{
   FUNC_ENTRY( "CPlApplet" )
    
   UINT  uResult;
   UINT  uUpdated;
   LONG  lResult;
   LONG  lAppletNum;
   LPCPLINFO   lpCplInfo;
   LPNEWCPLINFO   lpNewCplInfo;
   extern CPL     gCPL;       // app global

   lAppletNum = lParam1;      // start's at zero
   lResult = 0;               // default return value

   switch ( uMessage ) 
   {
      case CPL_INIT:

          DBGOUT((10, "CPL_INIT"));

          // first message, sent once
          lResult = InitApplets( hWndCpl );
          break;


      case CPL_GETCOUNT:
          DBGOUT((10, "CPL_GETCOUNT - returning %d", gCPL.uCplApplets));

          // return the number of applets supported
          lResult = gCPL.uCplApplets;
          break;


      case CPL_INQUIRE:       
          DBGOUT((10, "CPL_INQUIRE"));

         // get info about each applet -sent once per app
         //----------------------------------------------
         if ( lAppletNum < (LONG)gCPL.uCplApplets )
         {
             lpCplInfo  = (LPCPLINFO)lParam2;

             lpCplInfo->idIcon = (int)gCPL.taTeleApplet[lAppletNum].uIconResId;
             lpCplInfo->idName = (int)gCPL.taTeleApplet[lAppletNum].uNameResId;
             lpCplInfo->idInfo = (int)gCPL.taTeleApplet[lAppletNum].uStatusLineResId;
             lpCplInfo->lData  = gCPL.taTeleApplet[lAppletNum].lPrivateData;
        
             lResult = TRUE;
         }  // end if
         break;


      case CPL_NEWINQUIRE:
          DBGOUT((10, "CPL_NEWINQUIRE"));

         // new version of CPL_INQUIRE, return info about each applet
         //----------------------------------------------------------
         if ( lAppletNum < (LONG)gCPL.uCplApplets )
         {
            lpNewCplInfo  = (LPNEWCPLINFO)lParam2;
        
            lpNewCplInfo->dwFlags       = 0;
            lpNewCplInfo->dwSize        = sizeof(NEWCPLINFO);
            lpNewCplInfo->lData         = gCPL.taTeleApplet[lAppletNum].lPrivateData;
// Win95b 12364            lpNewCplInfo->dwHelpContext = gCPL.taTeleApplet[lAppletNum].dwHelpContext;
            lpNewCplInfo->dwHelpContext = 0;
           
         
            if ( !gCPL.taTeleApplet[lAppletNum].hIcon )         
               {
               // load the icon
               lpNewCplInfo->hIcon = LoadIcon( gCPL.hCplInst, MAKEINTRESOURCE(gCPL.taTeleApplet[lAppletNum].uIconResId));
           
               if ( !lpNewCplInfo->hIcon )
              {
                 FErrorRpt( hWndCpl, CPL_ERR_MEMORY );
                 break;      // will return false by default
              }
          
               gCPL.taTeleApplet[lAppletNum].hIcon = lpNewCplInfo->hIcon;     // save it so we can delete it
               }  // end if


            LpszGetStr( lpNewCplInfo->szName, gCPL.taTeleApplet[lAppletNum].uNameResId, CPL_MAX_TITLE );
            LpszGetStr( lpNewCplInfo->szInfo, gCPL.taTeleApplet[lAppletNum].uStatusLineResId, CPL_MAX_STATUS_LINE );
            lstrcpy (lpNewCplInfo->szHelpFile, gszHelpFile);
             
            lResult = TRUE;
            }  // end if
         break;
     

      case CPL_SELECT: 
          DBGOUT((10, "CPL_SELECT"));

          // application selected, who cares...
          break;


      case CPL_DBLCLK: 
          DBGOUT((10, "CPL_DBLCLK"));

          //----------------
          // show the dialog
          //----------------
          if ( lAppletNum < (LONG)gCPL.uCplApplets )
          {
              //
              // Verify single instance, initialize provider list
              //
              uResult = CplInit( hWndCpl, TRUE, &uUpdated );

              if ( uResult == CPL_SUCCESS )
              {
                  // Get windows directory, set default path for driver additions.
                  wsInfParseInit();  // initialize Multimedia

                  DEBOUT( "Creating Property Sheet" );

                  uResult = _ErrDoPropertySheet(
                      (HWND) hWndCpl,
                      (WORD) gCPL.taTeleApplet[lAppletNum].uDialogResId,
                      (DLGPROC) gCPL.taTeleApplet[lAppletNum].dlgprcDialog,
                      (LPARAM) uUpdated
                      );

                  DEBOUT( "Finished Creating Property Sheet" );
                    
                  infClose(NULL);

                  // Free up 3-D lib
                  if ((uResult = CplClose( uUpdated )) != CPL_SUCCESS )
                  {
                      CplClose( IDCANCEL );    // just make sure all the mem is cleaned up!
                  }
               
              } // end if
                
              if ( uResult != CPL_SUCCESS )                   // hum, things don't look to good
              {
                  FErrorRpt( hWndCpl, uResult );
                  CplClose( IDCANCEL );    // just make sure all the mem is cleaned up!
              }

          }
                   
          break;


      case CPL_STOP: 
          DBGOUT((10, "CPL_STOP"));

          // sent once per app before CPL_EXIT
          break;


      case CPL_EXIT: 
          DBGOUT((10, "CPL_EXIT"));

          // sent once before FreeLibrary called
          InitCleanupApplets();
          break;


      default:
          break;

      }  // end case
      
   return( lResult );

}



//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
UINT PRIVATE _ErrDoPropertySheet( HWND hwndOwner, WORD idResource, 
                                             DLGPROC dlgProc, LPARAM lParam )
{
    // Property sheet junk
   HPROPSHEETPAGE rPages[8];
   PROPSHEETPAGE psp;
   PROPSHEETHEADER psh;
   
    /****************************************************

                            PROPERTY SHEET
                                    
    ****************************************************/

    /*
     * ALERT! ALERT!
     *
     * In order for PropertySheets to work correctly, we need
     * to mark tapi.dll as a Windows 4.0 app. For this we need
     * to use rc.exe and rcpp.exe from the \chico\dev\sdk\bin
     * directory (\chico\dev is on \\guilo\slm).
     * 
     */
     
   psh.dwSize = sizeof(psh);
   psh.dwFlags = PSH_NOAPPLYNOW | PSH_PROPTITLE;
   psh.hwndParent = hwndOwner;
   psh.hInstance = gCPL.hCplInst;
   psh.pszCaption = MAKEINTRESOURCE(IDS_DIALOG_TITLE);
   psh.nPages = 0;
   psh.nStartPage = 0;
   psh.phpage = rPages;

   /* Define Location page */
   psp.dwSize = sizeof(psp);
   psp.dwFlags = PSP_DEFAULT;
   psp.hInstance = gCPL.hCplInst;
   psp.pszTemplate = MAKEINTRESOURCE(idResource);
   psp.pfnDlgProc = dlgProc;
   psp.lParam = lParam;

//   DBGOUT((1, "Calling CreatePropertySheetPage"));

   psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);

//   DBGOUT((1, "Done with CreatePropertySheetPage"));

   if (psh.phpage[psh.nPages])
       psh.nPages++;

//   DBGOUT((1, "Calling PropertySheet"));

   if (PropertySheet(&psh) < 0)
   {
//        DBGOUT((1, "... which failed"));
        return CPL_ERR_DIALOG_BOX;
   }
   else
      return 0;
}



//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#ifdef MSJ_PROP_SHEET
UINT PRIVATE _ErrDoPropertySheet( HWND hwndOwner, WORD idResource, 
                                             DLGPROC dlgProc, LPARAM lParam )
{
    // Property sheet junk
   PROPSHEETPAGE   psp[1];
   PROPSHEETHEADER psh;
   
    /****************************************************

                            PROPERTY SHEET
                                    
    ****************************************************/

    /*
     * ALERT! ALERT!
     *
     * In order for PropertySheets to work correctly, we need
     * to mark tapi.dll as a Windows 4.0 app. For this we need
     * to use rc.exe and rcpp.exe from the \chico\dev\sdk\bin
     * directory (\chico\dev is on \\guilo\slm).
     * 
     */
     
    psp[0].dwSize = sizeof(PROPSHEETPAGE);
    psp[0].dwFlags = PSP_DEFAULT;
    psp[0].hInstance = gCPL.hCplInst;
    psp[0].pszTemplate = MAKEINTRESOURCE(idResource);
    psp[0].pfnDlgProc = dlgProc;
    psp[0].lParam = lParam;

    psh.dwSize = sizeof(psh);
    psh.dwFlags = PSH_NOAPPLYNOW;
    psh.hwndParent = hwndOwner;
    psh.hInstance = gCPL.hCplInst;
    psh.pszCaption = MAKEINTRESOURCE(IDS_DIALOG_TITLE);
    psh.nPages = sizeof(psp)/sizeof(PROPSHEETPAGE);
    psh.ppsp = (LPCPROPSHEETPAGE)&psp;
    
    if (PropertySheet(&psh) < 0)
        return CPL_ERR_DIALOG_BOX;
    else
        return 0;
}
#endif /* MSJ_PROP_SHEET */