//******************************************************************************
//
//  PROGRAM: listfile.c
//
//  PURPOSE: Provides, via DDE, a list of host files to the PC/3270 receive
//           files function.
//
//  1.  Each instance of this application corresponds to one session
//      instance. This allows load button enablement on a session by session
//      basis.
//
//  2.  Invocation:  LISTFILE  /x   where "x" is the alpha session ID. A .. Z
//
//         Copyright (c) 1991, 1996 IBM Corporation. All rights reserved.
//
//         Provided on an "AS IS" basis, no warranty expressed or implied.
//
//******************************************************************************

#include <windows.h>                // required for all Windows applications

#include <string.h>                 // String functions
#include <ctype.h>                  // toupper function

#include "listfile.h"               // specific to this program

#define MAIN
#include "listdata.h"               // Global Data

//******************************************************************************
//
// Local Function Definitions
//
//******************************************************************************

BOOL NEAR GetSessionID( LPSTR );

//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT
//
//  FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
//
//  PURPOSE: calls initialization functions, and processes the application
//           message loop.
//
//  COMMENTS:
//
//      Windows recognizes this function by name as the initial entry point
//      for the program.  This function calls the application initialization
//      routine, if no other instance of the program is running, and always
//      calls the instance initialization routine.  It then executes a message
//      retrieval and dispatch loop that is the top-level control structure
//      for the remainder of execution.  The loop is terminated when a WM_QUIT
//      message is received, at which time this function exits the application
//      instance by returning the value passed by PostQuitMessage().
//
//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpzCmdLine, int nCmdShow)
{
  MSG msg;

  if ( !GetSessionID(lpzCmdLine) )             // Get Session ID A .. H
  {                                            //
    LoadString(hInstance, LS_COMMAND_LINE_ERROR1, zMsgBuffer, sizeof(zMsgBuffer));
    MessageBox(NULL, (LPSTR) zMsgBuffer, (LPSTR) ListFileClassName, MB_OK | MB_ICONQUESTION );
    return( FALSE );                           //
  }                                            //
                                               //
  if (!hPrevInstance)                          //
  {                                            //
    if (!RegisterApplicationClass(hInstance))  //
    {                                          //
      return( FALSE );                         //
    }                                          //
  }                                            //
                                               //
  if (!InitInstance(hInstance, nCmdShow))      //
  {                                            //
    return( FALSE );                           //
  }                                            //
                                               //
  if ( !InitDDE() )                            //
  {                                            //
    return( FALSE );                           //
  }                                            //
                                               //
  // ** Dispatch messages until a WM_QUIT message is received.
                                               //
  while( GetMessage((LPMSG)&msg, (HWND)NULL, (UINT)NULL, (UINT)NULL) )
  {                                            //
    TranslateMessage(&msg);                    // Translates virtual key codes
    DispatchMessage(&msg);                     // Dispatches message to window
  }                                            //
                                               // Return the PostQuitMessage()
  return (msg.wParam);                         // Value
}                                              //
                                               //
                                               //
//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT
//
//  FUNCTION: RegisterApplicationClass(HANDLE)
//
//  PURPOSE: Initializes window data and registers window class
//
//  This function is called at initialization time only if no other
//  instances of the application are running.  This function performs
//  initialization tasks that can be done once for any number of running
//  instances.
//
//  In this case, we initialize a window class by filling out a data
//  structure of type WNDCLASS and calling the Windows RegisterClass()
//  function.  Since all instances of this application use the same window
//  class, we only need to do this when the first instance is initialized.
//
//
//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT

BOOL RegisterApplicationClass( HANDLE hInstance )
{
  WNDCLASS  wc;

  // Fill in window class structure with parameters that describe the
  // main window.

  wc.hInstance     = hInstance;
  wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(LISTICON));
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.style         = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  wc.lpszMenuName  = MAKEINTRESOURCE(LISTMENU);
  wc.lpszClassName = ListFileClassName;
  wc.lpfnWndProc   = ListFileWndProc;

  // Register the window class and return FALSE if the call fails

  if( !RegisterClass(&wc) )
  {
    return(FALSE);
  }

  // Fill in window class structure with parameters that describe the
  // hidden window used to converse with session to obtain the file name
  // list.

  wc.hInstance     = hInstance;              // Hidden window
  wc.hIcon         = NULL;                   // does not need much ...
  wc.hCursor       = NULL;
  wc.hbrBackground = NULL;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.style         = 0;
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = FileListClassName;
  wc.lpfnWndProc   = FileListWndProc;

  // Register the window class and return FALSE if the call fails

  return( RegisterClass(&wc) );
}

//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT
//
//  FUNCTION:  InitInstance(HANDLE, int)
//
//  PURPOSE:  Saves instance handle and creates main window
//
//  This function is called at initialization time for every instance of
//  this application.  This function performs initialization tasks that
//  are unique to this instance.
//
//  In this case, we save the instance handle in a static variable and
//  create and display the main program window.
//
//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT

BOOL InitInstance(HANDLE hInstance, int iCmdShow)
{
  HWND hWnd;
  int iX, iY;

  // Save the instance handle in static variable, which will be used in
  // many subsequence calls from this application to Windows.

  hGlobalInst = hInstance;

  // Create a main window for this application instance.

  iX = GetSystemMetrics( SM_CXSCREEN );
  iY = GetSystemMetrics( SM_CYSCREEN );

  LoadString(hInstance, LS_TITLE_TEXT, zMsgBuffer, sizeof(zMsgBuffer));

  strcat(zMsgBuffer, zCmdLineSessionID);

  hWnd = CreateWindow(
      ListFileClassName,               // See RegisterClass() call.
      zMsgBuffer,                      // Text for window title bar.
      WS_OVERLAPPEDWINDOW,             // Window style.
      (iX / 4),                        // Horizontal position.
      (iY / 4),                        // Vertical position.
      (iX / 2),                        // Width
      (iY / 2),                        // Height
      NULL,                            // Overlapped windows have no parent.
      NULL,                            // Use the window class menu.
      hInstance,                       // This instance owns this window.
      NULL                             // Pointer not needed.
  );

  // If window could not be created, return FALSE

  if ( hWnd == NULL )
  {
    return(FALSE);
  }

  hGlobalWnd = hWnd;                   // Save Window Handle

  // Make the window visible; update its client area; and return "success"

  ShowWindow(hWnd, SW_MINIMIZE);       // Show the window
  UpdateWindow(hWnd);                  // Sends WM_PAINT message
                                       //
  // Create the Hidden window          //
                                       //
  hWndHidden = CreateWindow(           //
      FileListClassName,               // See RegisterClass() call.
      "",                              // Text for window title bar.
      WS_OVERLAPPEDWINDOW,             // Window style.
      (iX / 4),                        // Horizontal position.
      (iY / 4),                        // Vertical position.
      (iX / 2),                        // Width
      (iY / 2),                        // Height
      NULL,                            // Overlapped windows have no parent.
      NULL,                            // Use the window class menu.
      hInstance,                       // This instance owns this window.
      NULL                             // Pointer not needed.
  );                                   //
                                       //
  // If window could not be created, return FALSE
                                       //
  if ( hWndHidden == NULL )            //
  {                                    //
    return(FALSE);                     //
  }                                    //
                                       //
  return(TRUE);                        // Return success
}

//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT
//
//  FUNCTION: ListFileWndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Main Window Procedure for LISTFILE application
//
//  This procedure handles most all of the message traffic for the
//  application. When this procedure receive a WM_QUIT message the application
//  will terminate by exiting the while message loop in the function WinMain.
//
//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT

long WINAPI ListFileWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  FARPROC      lpProcModalDialog;
  PAINTSTRUCT  ps;

  switch (message)
  {
    case WM_COMMAND:
      switch( wParam )
      {
        case ID_ABOUT:
          lpProcModalDialog = MakeProcInstance(About, hGlobalInst);
          DialogBox(hGlobalInst, MAKEINTRESOURCE(ABOUTBOX), hWnd, lpProcModalDialog);
          FreeProcInstance(lpProcModalDialog);
          break;

        default:
          return( DefWindowProc(hWnd, message, wParam, lParam) );
          break;
      }
      break;

    case WM_PAINT:   // Paint a Message in the client area
      BeginPaint(hWnd, (LPPAINTSTRUCT) &ps );
      strcpy(zMsgBuffer, "ListFile Sample Application");
      TextOut(ps.hdc, 10, 100, (LPSTR) zMsgBuffer, strlen(zMsgBuffer) );
      strcpy(zMsgBuffer, "Copyright (c) 1991, 1996 IBM Corporation");
      TextOut(ps.hdc, 10, 120, (LPSTR) zMsgBuffer, strlen(zMsgBuffer) );
      strcpy(zMsgBuffer, "                    All rights reserved.");
      TextOut(ps.hdc, 10, 140, (LPSTR) zMsgBuffer, strlen(zMsgBuffer) );
      EndPaint(hWnd, (LPPAINTSTRUCT) &ps );
      break;

    case WM_DESTROY:                  // Destroy the Window
      Terminate( CONVERSATIONS );     // Terminate DDE conversations
      PostQuitMessage(0);             //
      break;                          //

    //** ** ** ** ** ** ** ** ** ** ** ** ** **
    //
    //  DDE Messages .....
    //
    //** ** ** ** ** ** ** ** ** ** ** ** ** **

    case WM_DDE_INITIATE:
      ListDDEInitiate(hWnd, message, wParam, lParam);
      break;

    case WM_DDE_POKE:
      ListDDEPoke(hWnd, message, wParam, lParam);
      break;

    case WM_DDE_REQUEST:
      ListDDERequest(hWnd, message, wParam, lParam);
      break;

    case WM_DDE_TERMINATE:
      ListDDETerminate(hWnd, message, wParam, lParam);
      break;

    default:                          // Pass on all unprocessed messages
      return( DefWindowProc(hWnd, message, wParam, lParam) );
      break;
  }
  return( FALSE );
}

//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT
//
//  FUNCTION: FileListWndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Window Procedure for the LISTFILE to Session DDE conversation
//
//  This window is used to manage the DDE conversation between LISTFILE
//  and the PC/3270 session where the CMS LISTFILE command is issued and the
//  resulting host file list is obtained.
//
//**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT**BOX-COMMENT

long WINAPI FileListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
  {
    // ** ** ** ** ** ** ** ** ** ** **
    //
    //  DDE Messages .....
    //
    // ** ** ** ** ** ** ** ** ** ** **

    case WM_DDE_ACK:
      FileDDEAck(hWnd, message, wParam, lParam);
      break;

    case WM_DDE_DATA:
      FileDDEData(hWnd, message, wParam, lParam);
      break;

    case WM_DDE_TERMINATE:
      FileDDETerminate(hWnd, message, wParam, lParam);
      break;

    default:
      return( DefWindowProc(hWnd, message, wParam, lParam) );
      break;
  }
  return( FALSE );
}

//******************************************************************************
//
//  FUNCTION: About(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Dialog procedure for the "About" dialog box
//
//  COMMENTS:
//
//      No initialization is needed for this particular dialog box, but TRUE
//      must be returned to Windows.
//
//      Wait for user to click on "Ok" button, then close the dialog box.
//
//******************************************************************************

BOOL WINAPI About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch( message )                    // case on the message ID
  {                                    //
    case WM_INITDIALOG:                // Init dialog
      return(TRUE);                    //
      break;                           //
                                       //
    case WM_COMMAND:                   //
      switch( wParam )                 //
      {                                //
        case IDOK:                     //
        case IDCANCEL:                 //
          EndDialog(hDlg, TRUE);       //
          return(TRUE);                //
          break;                       //
                                       //
        default:                       //
          break;                       //
      }                                //
      break;                           //
  }                                    //
  return(FALSE);                       //
}

//******************************************************************************
//
//  GetSessionID - Parse the short session name from the incoming command
//                 line
//
//  The command line for a session instance will be
//
//     session  /x         x = session ID
//
//******************************************************************************

BOOL NEAR GetSessionID( LPSTR lpzCmdLine )
{
  int i, iLength = lstrlen(lpzCmdLine);

  for( i = 0; i < iLength; i++ )
  {
    if( *lpzCmdLine++ == '/' )
    {
      uchar cID = *lpzCmdLine;                      //

      cID = toupper( cID );

      if( 'A' <= cID && cID <= 'Z' )
      {
        zCmdLineSessionID[0] = (uchar) cID;         // setup string
        zCmdLineSessionID[1] = NULL_CHAR;           // Null Terminator
        return(TRUE);
      }
    }
  }
  return(FALSE);
}
