//------------------------------------------------------------------------------------------------------
// Name       : export_.c
// Date       : 23.05.1996     Author : SM           System : Win32
//------------------------------------------------------------------------------------------------------
// This file contains the language-independent implementation of the module EXPORT_.DLL. All texts and
// resources that are language-dependent are located in an additional EXPORT.DLL, whose sources can be
// found in the subdirectories \E (for English) and \D (for German).
//------------------------------------------------------------------------------------------------------

#define USER_DATA_ID          "1.00-1995-08-10"

//------------------------------------------------------------------------------------------------------

#include        "windows.h"
#include        "windowsx.h"
#include        "stdlib.h"
#include        "stdio.h"
#include        "math.h"

#include        "e:\release4\toso40.h"          // Toso Interface 4.0 Definitions
#include        "dialog.h"

//------------------------------------------------------------------------------------------------------

typedef struct {
  STR32         TimeStamp;

  FILENAME      FileName;
} INF_HEADER;

//------ Language-dependent texts in EXPORT.DLL --------------------------------------------------------

DLL_IMPORT LPSTR
        eStartUpText    [],
        eDefaultName    [],
        eDialogText     [],
        eMessageText    [];

//------------------------------------------------------------------------------------------------------

static  HINSTANCE       hInstDLL,               // Instance handle of the main DLL
                        hLanguage,              // Instance handle of the language DLL
                        hGlobalInst;            // Instance handle of the serving application
static  HWND            hGlobalWnd;             // Main window handle of the serving application

//------------------------------------------------------------------------------------------------------

static  HBITMAP         hBitmap;
static  INF_HEADER      INFHeader;
static  int             gError;                 // Current error status ( 0 = OK )

//------------------------------------------------------------------------------------------------------

BOOL ModuleLoadSettings( void )
{
  BOOL          Result = FALSE;

  if( TosoProfileReadKeyOpen( "EXPORT", FALSE ) ) {
    if( TosoProfileReadData( "Init", (LPBYTE) &INFHeader, sizeof( INFHeader ) ) )
      Result = TRUE;
    TosoProfileReadKeyClose();

    INFHeader.TimeStamp[31] = 0x00;
    if( lstrcmp( INFHeader.TimeStamp, USER_DATA_ID ) )
      Result = FALSE;
  }

  if( !Result ) {
    lstrcpy( INFHeader.FileName, eDefaultName[0] );
  }
  return( Result );
}

//------------------------------------------------------------------------------------------------------

BOOL ModuleSaveSettings( void )
{
  BOOL          Result = FALSE;

  if( TosoProfileWriteKeyOpen( "EXPORT", FALSE ) ) {
    lstrcpy( INFHeader.TimeStamp, USER_DATA_ID );
    if( TosoProfileWriteData( "Init", (LPBYTE) &INFHeader, sizeof( INFHeader ) ) )
      Result = TRUE;
    TosoProfileWriteKeyClose();
  }
  return( Result );
}

//------------------------------------------------------------------------------------------------------
// This procedure is used as callback procedure for an object enumeration based on the interface
// procedure TosoEnumerateAll(). It simply runs through of the object described in EnumData and write
// the coordinates of all its definition points to the currently open file.
// After each coordinate pair written, it also updates the current progress indicator and checks whether
// the user has pressed the Cancel button to stop the export.

BOOL ModuleEnumCallback( const ENUMDEF_DATA* EnumData )
{
  DUMMYSTR      Text1, Text2;
  int           Count;

  switch( EnumData->EnumData ) {
    case ENUMDATA_CURVE:
    case ENUMDATA_AREA:
    case ENUMDATA_MARK:
      for( Count = 0; Count < EnumData->EnumCount; Count++ ) {
        TosoFileWriteShort      ( DB_POINT_ANY );
        TosoFileWriteCommaDouble( EnumData->PointPtr[Count].x );
        TosoFileWriteCommaDouble( EnumData->PointPtr[Count].y );
        TosoFileWriteSemi();

        if( TosoFileWriteError() ) {
          gError = 1;
          break;
        }

        wsprintf( Text1, eDialogText[3], TosoFileWriteCurrentLine() );
        wsprintf( Text2, eDialogText[4], ( TosoFileWriteCurrentSize() + 1023 ) / 1024 );
        TosoDialogUpdateProgress( Text1, Text2, NOPARAM, NOPARAM );

        if( TosoDialogIsCanceled() ) {
          gError = 999;
          break;
        }
      }
      break;
  }
  return( !gError );
}

//------------------------------------------------------------------------------------------------------
// This procedure performs the export. It starts the object enumeration (which writes coordinate pairs
// to the file).
// In addition, it initializes and display a progress indicator window to inform the user about the
// current progress and to allow him to cancel the export. Since the final file size is not known
// in advance, the progress indicator does not include a percent bar.

void ModuleExport( HANDLE FileHandle, const LPSTR FileName )
{
  FILENAME      FileName2;
  DUMMYSTR      DummyStr;

  gError = 0;

  if( !TosoFileWriteInitDisk( FileHandle ) ) {
    gError = 1;
    return;
  }

  TosoFileSplitName( FileName, NULL, FileName2 );
  wsprintf( DummyStr, eDialogText[2], FileName2 );
  TosoDialogShowProgress( eDialogText[0], DummyStr, FALSE );

  TosoEnumerateAll( TosoDrawingGetActive(), FLAG_USE, FLAG_USE,
                    ENUMMODE_PLAIN | ENUMMODE_LINES | ENUMMODE_LINETYPES,
                    (TOSOENUMOBJECT_PROC) ModuleEnumCallback );

  TosoFileWriteShort( DB_END );
  TosoFileWriteSemi();

  if( !TosoFileWriteFlush() )
    gError = 1;

  TosoFileWriteExit();
  TosoDialogHideProgress();
}

//------------------------------------------------------------------------------------------------------
// This DLL entry procedure must exist in any DLL to be used in Win32. Since our DLL does all necessary
// initialization in its TosoModuleInit() procedure, this procedure is quite empty.

BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD Reason, LPVOID Dummy )
{
  switch( Reason ) {
    case DLL_PROCESS_ATTACH:
      hInstDLL = hInstance;
      break;

    case DLL_PROCESS_DETACH:
      hInstDLL = NULL;
      break;
  }
  return( TRUE );
}

//------------------------------------------------------------------------------------------------------
// This procedure is called when the module is loaded by the serving application. Its main tasks are:
// - Checking whether it is compatible with the given InterfaceVersion
// - Checking whether it is licensed to the given serial number (optional)
// - Storing of the serving application's instance and main windows handle for further use
// - Loading of the language-dependent library
// - Filling in the module ID structure whose address is passed in ModuleID
// - Loading of options from the registry database
// - Loading profiles
// - Allocating any static memory required

DLL_EXPORT BOOL TosoModuleInit( const LPSTR SerialNumber, HINSTANCE hMainInst, HWND hMainWnd,
                                                          int InterfaceVersion, MODULE_ID* ModuleID )
{
  if( InterfaceVersion < TOSO_INTERFACE_VERSION ) {
    MessageBox( hMainWnd, eMessageText[0], eDialogText[0], MB_OK );
    return( FALSE );
  }

  if( !lstrcmp( SerialNumber, "DEMO" ) )
    return( FALSE );

  hGlobalInst = hMainInst;
  hGlobalWnd  = hMainWnd;

  hLanguage = LoadLibrary( "EXPORT.DLL" );
  hBitmap = LoadBitmap( hLanguage, "IDB_COMMAND" );

  ModuleID->OwnerID    = DB_OWNER_TOSO;
  ModuleID->ModuleID   = 0x2000;
  ModuleID->ModuleCTRL = MODULECTRL_ALL;

  ModuleID->ModuleProc.InputPointInitProc = (TOSOINPUTPOINTINIT_PROC) NULL;
  ModuleID->ModuleProc.InputPointMoveProc = (TOSOINPUTPOINTMOVE_PROC) NULL;
  ModuleID->ModuleProc.InputPointExitProc = (TOSOINPUTPOINTEXIT_PROC) NULL;
  ModuleID->ModuleProc.InputDisplayProc   = (TOSOINPUTDISPLAY_PROC)   NULL;
  ModuleID->ModuleProc.InputParameterProc = (TOSOINPUTPARAMETER_PROC) NULL;
  ModuleID->ModuleProc.InputCancelProc    = (TOSOINPUTCANCEL_PROC)    NULL;
  ModuleID->ModuleProc.InputFinishProc    = (TOSOINPUTFINISH_PROC)    NULL;

  ModuleID->ModuleData.Type = MODULETYPE_EXPORT;

  ModuleID->ModuleData.InputData.CommandMode = COMMAND_DIRECT;
  ModuleID->ModuleData.MenuData.MenuEntry   = eStartUpText[1];
  ModuleID->ModuleData.MenuData.Description = eStartUpText[2];

  ModuleID->ModuleData.IconHandle  = hBitmap;
  ModuleID->ModuleData.IconXOffset = 0;
  ModuleID->ModuleData.IconYOffset = 0;
  ModuleID->ModuleData.IconMode    = 0;

  ModuleID->CommandData = NULL;

  ModuleLoadSettings();

  return( TRUE );
}

//------------------------------------------------------------------------------------------------------
// This procedure is called when the module is removed by the serving application. Its main tasks are:
// - Checking whether anything is to be saved. If so, it should display a message information the user
//   about it and allowing him to save those changes.
// - Freeing of all statically allocated memory.
// If this procedure return FALSE, the serving application will not be able to terminate. So please, do
// only return FALSE if shutting down the module now would severely damage or destroy user data.

DLL_EXPORT BOOL TosoModuleExit( void )
{
  ModuleSaveSettings();

  DeleteBitmap( hBitmap );

  return( TRUE );
}

//------------------------------------------------------------------------------------------------------
// This procedure serves as hook procedure for the comman file open dialog window. It manages the Infos
// button that has been added to the standard GetSaveFileName dialog template.
// In a more sophisticated export module, the common dialog would also contain a Options button which
// would also be managed in this procedure.

UINT CALLBACK TosoModuleGetFileNameHook( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
  switch( message ) {
    case WM_INITDIALOG:                                 // Initialize dialog box
      TosoDialogCenter( hDlg );                         // Center dialog window
      return( 1 );

    case WM_COMMAND:
      switch( GET_WM_COMMAND_ID( wParam, lParam ) ) {
        case IDD_BUTTON0:                               // Infos
          MessageBox( hDlg, eStartUpText[0], eDialogText[0], MB_OK );
          return( 1 );
      }
      break;

    case WM_ENTERIDLE:
      return( TosoDialogEnterIdle( hDlg, wParam, lParam ) );

    default:
      if( message == TosoDialogHelpMessage() ) {
        WinHelp( hDlg, "EXPORT.HLP", HELP_CONTEXT, 1 );
        return( 1 );
      }
      break;
  }
  return( 0 );                                          // Didn't process a message
}

//------------------------------------------------------------------------------------------------------
// This procedure is called when a module's command is chosen by the user. For an export filter, its
// main tasks are:
// - Prompting the user for the file name of the export file. This should usually be done by means of
//   common dialog windows extended by some additional buttons like Infos and Options
// - Opening the export file
// - Calling the basic export procedure
// - Closing the export file
// - Error handling and display

DLL_EXPORT BOOL TosoModuleCommand( int CommandID, int ExecMode )
{
  static  OPENFILENAME  OpenData;
  static  FILENAME      FileName;
  HANDLE                FileHandle;
  DUMMYSTR              DummyStr;
  DWORD                 CmnDlgError;
  BOOL                  Result = FALSE;

  if( CommandID != 0 )
    return( FALSE );

// Check whether a help topic is to be displayed instead of starting a command.

  if( ExecMode == MODULEEXEC_HELP ) {
    WinHelp( hGlobalWnd, "EXPORT.HLP", HELP_CONTEXT, 1 );
    return( FALSE );
  }

  lstrcpy( FileName, INFHeader.FileName );

  OpenData.lStructSize       = sizeof( OPENFILENAME );
  OpenData.hwndOwner         = hGlobalWnd;
  OpenData.hInstance         = hLanguage;
  OpenData.lpstrFilter       = eDialogText[1];
  OpenData.lpstrCustomFilter = NULL;
  OpenData.nMaxCustFilter    = 0;
  OpenData.nFilterIndex      = 1;
  OpenData.lpstrFile         = FileName;
  OpenData.nMaxFile          = sizeof( FileName );
  OpenData.lpstrFileTitle    = NULL;
  OpenData.nMaxFileTitle     = 0;
  OpenData.lpstrInitialDir   = NULL;
  OpenData.lpstrTitle        = eDialogText[0];
  OpenData.Flags             = OFN_HIDEREADONLY | OFN_NONETWORKBUTTON | OFN_SHOWHELP |
                               OFN_ENABLEHOOK | OFN_ENABLETEMPLATE | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
  OpenData.nFileOffset       = 0;
  OpenData.nFileExtension    = 0;
  OpenData.lpstrDefExt       = eDefaultName[2];
  OpenData.lCustData         = NOPARAM;
  OpenData.lpfnHook          = (LPOFNHOOKPROC) TosoModuleGetFileNameHook;
  OpenData.lpTemplateName    = "GETFILENAME";

  Result = GetSaveFileName( &OpenData );                // Open common dialog window

  if( !Result )                                         // TRUE=OK, FALSE=cancel or error
    CmnDlgError = CommDlgExtendedError();               // 0=cancel, else error number

  if( !Result ) {                                       // Cancel
    if( CmnDlgError ) {                                 // Error in common dialog
      wsprintf( DummyStr, eMessageText[3], CmnDlgError );
      MessageBox( hGlobalWnd, DummyStr, eDialogText[0], MB_OK );
    }
    return( TRUE );
  }
  else                                                  // Store the selected file name
    lstrcpy( INFHeader.FileName, FileName );

  Result = FALSE;
  SetCursor( LoadCursor( NULL, IDC_WAIT ) );

  if( TosoFileCreate( &FileHandle, FileName ) ) {

    ModuleExport( FileHandle, FileName );

    TosoFileClose( FileHandle );
    switch( gError ) {
      case 999:
        TosoFileDelete( FileName );
        MessageBox( hGlobalWnd, eMessageText[2], eDialogText[0], MB_OK );
        Result = TRUE;
        break;

      case 0:
        Result = TRUE;
        break;

      default:
        TosoFileDelete( FileName );
        MessageBox( hGlobalWnd, eMessageText[4], eDialogText[0], MB_OK );
        Result = FALSE;
        break;
    }
  }
  return( Result );
}
