/*
**  JAM(mbp) - The Joaquim-Andrew-Mats Message Base Proposal
**
**  JAM Windows Utility
**
**  Written by Mats Wallin
**
**  ----------------------------------------------------------------------
**
**  jamutilw.c (JAMmb)
**
**  JAM Windows Utility, display contents of a JAM messagebase
**
**  Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch, and
**  Mats Wallin. ALL RIGHTS RESERVED.
**
**  93-06-28    MW
**  Initial coding
*/

#define STRICT

#include <windows.h>
#include <commdlg.h>

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#include "jammb.h"

#include "jamutilw.h"
#include "dlgutilw.h"


#define MSGBOXTITLE       "JAM(mb) Windows Utility"

#if defined (__BORLANDC__)
#pragma warn -par
#endif

/*
**  Local variables
*/

static HWND       hMainWnd;
static HINSTANCE  hInstance;

static UINT32     MsgNo;

/*
**  Prototypes
*/

int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine, int nCmdShow );
int InitApplication( HINSTANCE hinstCurrent );
int InitInstance( HINSTANCE hinstCurrent, int nCmdShow );
LRESULT CALLBACK WndProcJamUtil( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
BOOL CALLBACK DlgProcMsgHdr( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
BOOL CALLBACK DlgProcSubFields( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
BOOL CALLBACK DlgProcMsgText( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
BOOL CALLBACK DlgProcHdrInfo( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
BOOL CALLBACK DlgProcGotoMsg( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
int OpenJAMbase( void );
int DisplayMsgHdr( HWND hDlg, UINT32 MsgNo );
int DisplayHdrInfo( HWND hDlg );
int DisplaySubfields( HWND hDlg, UINT32 MsgNo );
int DisplayMsgTxt( HWND hDlg, UINT32 MsgNo );
int cdecl DlgItemPrintf( HWND hDlg, int Id, LPSTR Fmt, ... );
LPSTR DispTime( UINT32 * pt );
LPSTR AttrToStr( UINT32 Attr );
LPSTR GetSubFldName( JAMSUBFIELD FAR * pSubFld );
LPSTR GetSubFldStr( JAMSUBFIELD FAR * pSubFld );


/* ---------------------------------------------------------------------- *
 *
 *  WinMain
 *
 * ---------------------------------------------------------------------- */

int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine, int nCmdShow )
{
  MSG   msg;

  if( hinstPrevious == NULL )
    if( !InitApplication( hinstCurrent ))
      return( FALSE );

  if( !InitInstance( hinstCurrent, nCmdShow ))
    return( FALSE );

  while( GetMessage( &msg, NULL, 0, 0 ))
    {
    TranslateMessage( &msg );
    DispatchMessage( &msg );
    }

  return(( int ) msg.wParam );
}


/* ---------------------------------------------------------------------- *
 *
 *  InitApplication
 *
 * ---------------------------------------------------------------------- */

int InitApplication( HINSTANCE hinstCurrent )
{
  WNDCLASS    WndClass;

  memset( &WndClass, '\0', sizeof( WndClass ));

  WndClass.style          = 0;
  WndClass.lpfnWndProc    = WndProcJamUtil;
  WndClass.cbClsExtra     = 0;
  WndClass.cbWndExtra     = 0;
  WndClass.hInstance      = hinstCurrent;
  WndClass.hIcon          = LoadIcon( hinstCurrent, MAKEINTRESOURCE( IDI_JAMUTILW ));
  WndClass.hCursor        = LoadCursor( NULL, IDC_ARROW );
  WndClass.hbrBackground  = ( HBRUSH ) ( COLOR_BACKGROUND + 1 );
  WndClass.lpszMenuName   = NULL;
  WndClass.lpszClassName  = "JAMUTILW";

  if( RegisterClass( &WndClass ) == NULL )
    return( FALSE );

  return( TRUE );
}


/* ---------------------------------------------------------------------- *
 *
 *  InitInstance
 *
 * ---------------------------------------------------------------------- */

int InitInstance( HINSTANCE hinstCurrent, int nCmdShow )
{
  hInstance = hinstCurrent;


  hMainWnd = CreateWindow(  "JAMUTILW",
                            MSGBOXTITLE,
                            WS_OVERLAPPEDWINDOW | WS_MINIMIZE | WS_VISIBLE,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            HWND_DESKTOP,
                            NULL,
                            hInstance,
                            NULL );

  if( hMainWnd == NULL )
    {
    MessageBox( NULL, "Unable to create main window", MSGBOXTITLE, MB_OK );
    return( FALSE );
    }

  PostMessage( hMainWnd, WM_COMMAND, IDM_FILE_OPEN, 0L );

  return( TRUE );
}


/* ---------------------------------------------------------------------- *
 *
 *  WndProcJamUtil
 *
 * ---------------------------------------------------------------------- */

LRESULT CALLBACK WndProcJamUtil( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
  DLGPROC   pDlgProcMsgHdr;
  int       stat;

  switch( msg )
    {
    case WM_COMMAND :
      switch( wParam )
        {
        case IDM_FILE_OPEN :
          if(( stat = OpenJAMbase( )) == 0 )
            {
            PostMessage( hMainWnd, WM_CLOSE, 0, 0L );
            }
          else if( stat > 0 )
            {
            if(( pDlgProcMsgHdr = ( DLGPROC ) MakeProcInstance(( FARPROC ) DlgProcMsgHdr, hInstance )) != NULL )
              {
              DialogBox( hInstance, "MSGHDR", hMainWnd, pDlgProcMsgHdr );
              FreeProcInstance(( FARPROC ) pDlgProcMsgHdr );
              }
            }

          JAMsysDeinitApiRec( &JamRec );
          PostMessage( hMainWnd, WM_COMMAND, IDM_FILE_OPEN, 0L );
          break;
        }
      break;
	case WM_DESTROY:
      PostQuitMessage(0);
	  return (0);
	}

  return( DefWindowProc( hWnd, msg, wParam, lParam ));
}


/* ---------------------------------------------------------------------- *
 *
 *  DlgProcMsgHdr
 *
 * ---------------------------------------------------------------------- */

BOOL CALLBACK DlgProcMsgHdr( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  char            Buf [128];
  DLGPROC         pDlgProc;
  RECT            rect;
  int             Width,
                  Height;
  HMENU           hMenu;

  switch( msg )
    {
    case WM_INITDIALOG :
      wsprintf( Buf, "Message Header: %s", ( LPSTR ) JamRec.BaseName );
      SetWindowText( hDlg, Buf );
/*
**  Add a About... menu item
*/
      if(( hMenu = GetSystemMenu( hDlg, FALSE )) != NULL )
        {
        AppendMenu( hMenu, MF_SEPARATOR, 0, NULL );
        AppendMenu( hMenu, MF_STRING, IDM_ABOUT, "&About..." );
        }
/*
**  Center the dialog on the screen
*/
      GetWindowRect( hDlg, &rect );
      Width = GetSystemMetrics( SM_CXSCREEN );
      Height = GetSystemMetrics( SM_CYSCREEN );
      SetWindowPos( hDlg, NULL,
                    ( Width - ( rect.right - rect.left )) / 2,
                    ( Height - ( rect.bottom - rect.top )) / 2,
                    0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
/*
**  Display the first message header
*/
      MsgNo = JamRec.HdrInfo.BaseMsgNum;
      if( !DisplayMsgHdr( hDlg, MsgNo ))
        {
        EndDialog( hDlg, FALSE );
        return( FALSE );
        }
      return( TRUE );

    case WM_COMMAND :
      switch( wParam )
        {
        case IDC_PREVIOUS :
          if( !DisplayMsgHdr( hDlg, --MsgNo ))
            MsgNo++;
          break;

        case IDC_NEXT :
          if( !DisplayMsgHdr( hDlg, ++MsgNo ))
            MsgNo--;
          break;

        case IDC_GOTO :
          {
          UINT32 OldMsgNo = MsgNo;

          if(( pDlgProc = ( DLGPROC ) MakeProcInstance(( FARPROC ) DlgProcGotoMsg, hInstance )) != NULL )
            {
            MsgNo = DialogBox( hInstance, "GOTOMSG", hDlg, pDlgProc );
            FreeProcInstance(( FARPROC ) pDlgProc );
            }
          if( MsgNo == 0 || !DisplayMsgHdr( hDlg, MsgNo ))
            MsgNo = OldMsgNo;
          break;
          }

        case IDC_FIELDS :
          if(( pDlgProc = ( DLGPROC ) MakeProcInstance(( FARPROC ) DlgProcSubFields, hInstance )) != NULL )
            {
            DialogBox( hInstance, "SUBFIELDS", hDlg, pDlgProc );
            FreeProcInstance(( FARPROC ) pDlgProc );
            }
          break;

        case IDC_TEXT :
          if(( pDlgProc = ( DLGPROC ) MakeProcInstance(( FARPROC ) DlgProcMsgText, hInstance )) != NULL )
            {
            DialogBox( hInstance, "MSGTEXT", hDlg, pDlgProc );
            FreeProcInstance(( FARPROC ) pDlgProc );
            }
          break;

        case IDC_HDRINFO :
          if(( pDlgProc = ( DLGPROC ) MakeProcInstance(( FARPROC ) DlgProcHdrInfo, hInstance )) != NULL )
            {
            DialogBox( hInstance, "HDRINFO", hDlg, pDlgProc );
            FreeProcInstance(( FARPROC ) pDlgProc );
            }
          break;

        case IDC_EXIT :
        case IDCANCEL :
          EndDialog( hDlg, TRUE );
          return( TRUE );
        }
      break;

    case WM_SYSCOMMAND :
      switch( wParam & 0xFFF0 )
        {
        case IDM_ABOUT :
          MessageBox( hDlg, "JAM(mb) Windows Utility\n"
                            "\n"
							"© 1993\tJoaquim Homrighausen\n"
							"\tAndrew Milner\n"
							"\tMats Birch\n\tMats Wallin\n\n"
							"ALL RIGHTS RESERVED.\n"
                            "\n"
                            "Written by Mats Wallin",
                            MSGBOXTITLE,
                            MB_OK|MB_ICONINFORMATION );
          break;
        }
      break;
    }

  return( FALSE );
}


/* ---------------------------------------------------------------------- *
 *
 *  DlgProcSubFields
 *
 * ---------------------------------------------------------------------- */

BOOL CALLBACK DlgProcSubFields( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  static int  TabStops [4] = {20, 44, 100, 128};
  char        Buf [128];

  switch( msg )
    {
    case WM_INITDIALOG :
      SendDlgItemMessage( hDlg, IDC_FLD_LISTBOX, LB_SETTABSTOPS,
                        sizeof( TabStops ) / sizeof( TabStops [0] ),
                        ( LPARAM ) ( int FAR * ) TabStops );

      wsprintf( Buf, "Message SubFields: %s", ( LPSTR ) JamRec.BaseName );
      SetWindowText( hDlg, Buf );
      DisplaySubfields( hDlg, MsgNo );
      return( TRUE );

    case WM_COMMAND :
      switch( wParam )
        {
        case IDOK :
        case IDCANCEL :
          EndDialog( hDlg, wParam == IDOK );
          break;
        }
    }

  return( FALSE );
}

/* ---------------------------------------------------------------------- *
 *
 *  DlgProcMsgText
 *
 * ---------------------------------------------------------------------- */

BOOL CALLBACK DlgProcMsgText( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  char    Buf [128];

  switch( msg )
    {
    case WM_INITDIALOG :
      wsprintf( Buf, "Message Text: %s", ( LPSTR ) JamRec.BaseName );
	  SetWindowText( hDlg, Buf );
	  DisplayMsgTxt( hDlg, MsgNo );
      return( TRUE );

    case WM_COMMAND :
      switch( wParam )
        {
        case IDOK :
        case IDCANCEL :
          EndDialog( hDlg, wParam == IDOK );
          break;
        }
    }

  return( FALSE );
}


/* ---------------------------------------------------------------------- *
 *
 *  DlgProcHdrInfo
 *
 * ---------------------------------------------------------------------- */

BOOL CALLBACK DlgProcHdrInfo( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  char    Buf [128];

  switch( msg )
    {
    case WM_INITDIALOG :
      wsprintf( Buf, "Header Info: %s", ( LPSTR ) JamRec.BaseName );
      SetWindowText( hDlg, Buf );

      DisplayHdrInfo( hDlg );
      return( TRUE );

    case WM_COMMAND :
      switch( wParam )
        {
        case IDOK :
          EndDialog( hDlg, TRUE );
          return( TRUE );

        case IDCANCEL :
          EndDialog( hDlg, FALSE );
          return( TRUE );
        }
    }

  return( FALSE );
}


/* ---------------------------------------------------------------------- *
 *
 *  DlgProcGotoMsg
 *
 * ---------------------------------------------------------------------- */

BOOL CALLBACK DlgProcGotoMsg( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  char    Buf [16];

  switch( msg )
    {
    case WM_COMMAND :
      switch( wParam )
        {
        case IDOK :
          SendDlgItemMessage( hDlg, IDC_MSGNO, WM_GETTEXT, sizeof( Buf ), ( LPARAM ) ( LPSTR ) Buf );
          EndDialog( hDlg, atoi( Buf ));
          return( TRUE );

        case IDCANCEL :
          EndDialog( hDlg, 0 );
          return( TRUE );
        }
    }

  return( FALSE );
}


/* ---------------------------------------------------------------------- *
 *
 *  OpenJAMbase
 *
 * ---------------------------------------------------------------------- */

int OpenJAMbase( void )
{
  static char     InitialDir [128] = "";
  OPENFILENAME    ofn;
  char            FileName [128];
  char            FilterStr [128];
  int             Len,
                  i;
  char            ch;

  memset( &ofn, '\0', sizeof( ofn ));
  FileName [0] = '\0';

  Len = LoadString( hInstance, IDS_FILTERS, FilterStr, sizeof( FilterStr ));
  ch = FilterStr [Len - 1];
  for( i = 0; i < Len; i++ )
    if( FilterStr [i] == ch )
      FilterStr [i] = '\0';

  ofn.lStructSize       = sizeof( ofn );
  ofn.hwndOwner         = hMainWnd;
  ofn.hInstance         = hInstance;
  ofn.lpstrFilter       = FilterStr;
  ofn.lpstrCustomFilter = NULL;
  ofn.nMaxCustFilter    = 0;
  ofn.nFilterIndex      = 1;
  ofn.lpstrFile         = FileName;
  ofn.nMaxFile          = sizeof( FileName );
  ofn.lpstrFileTitle    = NULL;
  ofn.nMaxFileTitle     = 0;
  ofn.lpstrInitialDir   = InitialDir;
  ofn.lpstrTitle        = NULL;
  ofn.Flags             = OFN_FILEMUSTEXIST|
                          OFN_HIDEREADONLY;
  ofn.nFileOffset       = 0;
  ofn.nFileExtension    = 0;
  ofn.lpstrDefExt       = "JHR";
  ofn.lCustData         = 0;
  ofn.lpfnHook          = NULL;
  ofn.lpTemplateName    = NULL;

  do
    {
    if( !GetOpenFileName( &ofn ))
      return( FALSE );

    if( ofn.nFileOffset )
      memcpy( InitialDir, FileName, ofn.nFileOffset );
    InitialDir [ofn.nFileOffset] = '\0';

    if( ofn.Flags & OFN_EXTENSIONDIFFERENT )
      MessageBox( hMainWnd, "Invalid extension choosen", MSGBOXTITLE, MB_OK );
    }
  while( ofn.Flags & OFN_EXTENSIONDIFFERENT );

  FileName [ofn.nFileExtension - 1] = '\0';


/*
**  Open the specified JAM messagebase
*/

  if( !JAMsysInitApiRec( &JamRec, FileName, WORKBUFSIZE ))
    {
    MessageBox( hMainWnd, "Unable to initialize APIREC structure", MSGBOXTITLE, MB_OK );
    return( -1 );
    }

  if( !JAMmbOpen( &JamRec ))
    {
    MessageBox( hMainWnd, "Unable to open specified JAM messagebase", MSGBOXTITLE, MB_OK );
    return( -1 );
    }

  return( TRUE );
}


/* ---------------------------------------------------------------------- *
 *
 *  DisplayMsgHdr
 *
 * ---------------------------------------------------------------------- */

int DisplayMsgHdr( HWND hDlg, UINT32 MsgNo )
{
  UINT32    TotalMsgs;

  if( MsgNo < JamRec.HdrInfo.BaseMsgNum )
    {
    char    Buf [128];

    wsprintf( Buf, "Invalid message number: %lu", MsgNo );
    MessageBox( hDlg, Buf, MSGBOXTITLE, MB_OK );
    return( FALSE );
    }

  TotalMsgs = _llseek( JamRec.IdxHandle, 0L, 2 ) / sizeof( JAMIDXREC );

  if(( MsgNo - JamRec.HdrInfo.BaseMsgNum ) >= TotalMsgs )
    {
    MessageBox( hDlg, "No more messages", MSGBOXTITLE, MB_OK );
    return( FALSE );
    }

  if( !JAMmbFetchMsgHdr( &JamRec, MsgNo, 0 ))
    {
    char    Buf [128];

    wsprintf( Buf, "Error reading message header, code: %d, errno: %d", JamRec.APImsg, JamRec.Errno );
    MessageBox( hDlg, Buf, MSGBOXTITLE, MB_OK );
    return( FALSE );
    }

  DlgItemPrintf( hDlg, IDC_MSGNUMBER,         "%lu", MsgNo );
  DlgItemPrintf( hDlg, IDC_TOTALMSGS,         "%lu", TotalMsgs );
  DlgItemPrintf( hDlg, IDC_HDR_SIGNATURE,     "<%02x><%02x><%02x><%02x>",
                                              JamRec.Hdr.Signature [0],
                                              JamRec.Hdr.Signature [1],
                                              JamRec.Hdr.Signature [2],
                                              JamRec.Hdr.Signature [3] );
  DlgItemPrintf( hDlg, IDC_HDR_REVISION,      "%04x", JamRec.Hdr.Revision );
  DlgItemPrintf( hDlg, IDC_HDR_SUBFLDLEN,     "%lu", JamRec.Hdr.SubfieldLen );
  DlgItemPrintf( hDlg, IDC_HDR_TIMESREAD,     "%lu", JamRec.Hdr.TimesRead );
  DlgItemPrintf( hDlg, IDC_HDR_MSGIDCRC,      "%08lx", JamRec.Hdr.MsgIdCRC );
  DlgItemPrintf( hDlg, IDC_HDR_REPLYCRC,      "%08lx", JamRec.Hdr.ReplyCRC );
  DlgItemPrintf( hDlg, IDC_HDR_REPLYTO,       "%lu", JamRec.Hdr.ReplyTo );
  DlgItemPrintf( hDlg, IDC_HDR_REPLY1ST,      "%lu", JamRec.Hdr.Reply1st );
  DlgItemPrintf( hDlg, IDC_HDR_REPLYNEXT,     "%lu", JamRec.Hdr.ReplyNext );
  DlgItemPrintf( hDlg, IDC_HDR_DATEWRITTEN,   "%s", DispTime( &JamRec.Hdr.DateWritten ));
  DlgItemPrintf( hDlg, IDC_HDR_DATERECEIVED,  "%s", DispTime( &JamRec.Hdr.DateReceived ));
  DlgItemPrintf( hDlg, IDC_HDR_DATEPROCESSED, "%s", DispTime( &JamRec.Hdr.DateProcessed ));
  DlgItemPrintf( hDlg, IDC_HDR_MSGNUM,        "%lu", JamRec.Hdr.MsgNum );
  DlgItemPrintf( hDlg, IDC_HDR_ATTRIBUTE,     "%s", AttrToStr( JamRec.Hdr.Attribute ));
  DlgItemPrintf( hDlg, IDC_HDR_ATTRIBUTE2,    "%lu", JamRec.Hdr.Attribute2 );
  DlgItemPrintf( hDlg, IDC_HDR_TXTOFFSET,     "%lu", JamRec.Hdr.TxtOffset );
  DlgItemPrintf( hDlg, IDC_HDR_TXTLEN,        "%lu", JamRec.Hdr.TxtLen );
  DlgItemPrintf( hDlg, IDC_HDR_PASSWORDCRC,   "%08lx", JamRec.Hdr.PasswordCRC );
  DlgItemPrintf( hDlg, IDC_HDR_COST,          "%u", JamRec.Hdr.Cost );

  return( TRUE );
}


/* ---------------------------------------------------------------------- *
 *
 *  DisplayHdrInfo
 *
 * ---------------------------------------------------------------------- */

int DisplayHdrInfo( HWND hDlg )
{
  UINT32    TotalMsgs;

/*
**  Read the header information record
*/

  if( !JAMmbUpdateHeaderInfo( &JamRec, 0 ))
    {
    char    Buf [128];

    wsprintf( Buf, "Error reading header info, code: %d, errno: %d\n", JamRec.APImsg, JamRec.Errno );
    MessageBox( hDlg, Buf, MSGBOXTITLE, MB_OK );
    return( FALSE );
    }


/*
**  Calculate the total (active + deleted) number of messages
*/

  TotalMsgs = _llseek( JamRec.IdxHandle, 0L, 2 ) / sizeof( JAMIDXREC );


/*
**  Display the information
*/

  DlgItemPrintf( hDlg, IDC_HDRINFO_SIGNATURE, "<%02x><%02x><%02x><%02x>",
                                              JamRec.HdrInfo.Signature [0],
                                              JamRec.HdrInfo.Signature [1],
                                              JamRec.HdrInfo.Signature [2],
                                              JamRec.HdrInfo.Signature [3] );


  DlgItemPrintf( hDlg, IDC_HDRINFO_DATECREATED, "%s", DispTime( &JamRec.HdrInfo.DateCreated ));
  DlgItemPrintf( hDlg, IDC_HDRINFO_MODCOUNTER,  "%lu", JamRec.HdrInfo.ModCounter );
  DlgItemPrintf( hDlg ,IDC_HDRINFO_ACTIVEMSGS,  "%lu", JamRec.HdrInfo.ActiveMsgs );
  DlgItemPrintf( hDlg, IDC_HDRINFO_PASSWORDCRC, "%08lx", JamRec.HdrInfo.PasswordCRC );
  DlgItemPrintf( hDlg, IDC_HDRINFO_BASEMSGNUM,  "%lu", JamRec.HdrInfo.BaseMsgNum );
  DlgItemPrintf( hDlg, IDC_HDRINFO_TOTALMSGS,   "%lu", TotalMsgs );
  DlgItemPrintf( hDlg, IDC_HDRINFO_DELETEDMSGS, "%lu", TotalMsgs - JamRec.HdrInfo.ActiveMsgs );

  return( TRUE );
}


/* ---------------------------------------------------------------------- *
 *
 *  DisplaySubfields
 *
 * ---------------------------------------------------------------------- */

int DisplaySubfields( HWND hDlg, UINT32 MsgNo )
{
  UINT32  SubFldLen = JamRec.Hdr.SubfieldLen,
          Len;


/*
**  Read the message header (and subfields)
*/

  if( !JAMmbFetchMsgHdr( &JamRec, JamRec.Hdr.MsgNum, 1 ))
    {
    char    Buf [128];

    wsprintf( Buf, "Error reading message header, code: %d, errno: %d", JamRec.APImsg, JamRec.Errno );
    MessageBox( hDlg, Buf, MSGBOXTITLE, MB_OK );
    return( FALSE );
    }


/*
**  If it wasn't possible to read all subfields into the buffer,
**  only process those that fit into the buffer
*/

  if( SubFldLen > JamRec.WorkLen )
    SubFldLen = JamRec.WorkLen;


/*
**  Display the ruler
*/

  SendDlgItemMessage( hDlg, IDC_FLD_LISTBOX, LB_ADDSTRING, 0,
                      ( LPARAM ) ( LPCSTR ) "HiID\tLoID\tName\tLen\tData" );


/*
**  And then all subfields
*/

  for(  JamRec.SubFieldPtr = ( JAMSUBFIELD FAR * ) JamRec.WorkBuf;

        JamRec.SubFieldPtr->DatLen + sizeof( JAMBINSUBFIELD ) <= SubFldLen;

        Len = JAMsysAlign( JamRec.SubFieldPtr->DatLen + sizeof( JAMBINSUBFIELD )),
        SubFldLen -= Len,
		JamRec.SubFieldPtr = ( JAMSUBFIELD FAR * ) JAMsysAddFarPtr( JamRec.SubFieldPtr, Len ))
    {
    char    Buf [256];

    wsprintf( Buf, "%u\t%u\t%-14.14s\t%lu\t\"%s\"",
                  JamRec.SubFieldPtr->HiID, JamRec.SubFieldPtr->LoID,
                  ( LPSTR ) GetSubFldName( JamRec.SubFieldPtr ),
                  JamRec.SubFieldPtr->DatLen,
                  ( LPSTR ) GetSubFldStr( JamRec.SubFieldPtr ));

    SendDlgItemMessage( hDlg, IDC_FLD_LISTBOX, LB_ADDSTRING, 0,
                      ( LPARAM ) ( LPCSTR ) Buf );
	}

	return (TRUE);

}


/* ---------------------------------------------------------------------- *
 *
 *  DisplayMsgTxt
 *
 * ---------------------------------------------------------------------- */

int DisplayMsgTxt( HWND hDlg, UINT32 MsgNo )
{
  int           First = 1,          /* Flag if this is the first read */
                Col = 0;
  UINT32        Pos = 0;
  HLOCAL        hMem;
  UINT          Size,
                BufSize;
  UCHAR8      * pBuf,
              * pBufStart;
  UCHAR8  FAR * p;


/*
**  Free the old edit control memory area
*/

  if(( hMem = ( HLOCAL ) SendDlgItemMessage( hDlg, IDC_TXT_EDIT, EM_GETHANDLE, 0, 0L )) == NULL )
    {
    char    Buf [128];

    wsprintf( Buf, "Unable to get handle of old edit control memory" );
    MessageBox( hDlg, Buf, MSGBOXTITLE, MB_OK );
    return( FALSE );
    }

  LocalFree( hMem );


/*
**  Allocate a new area, where the message text can be stored
*/

  for(  BufSize = 0xF000;
        BufSize > 0 && ( hMem = LocalAlloc( LHND, BufSize )) == NULL;
        BufSize -= 0x1000 )
    ;


/*
**  Fill this area with the messagetext
*/

  pBuf = pBufStart = LocalLock( hMem );
  Size = 0;

  while( TRUE )
    {
    if( !JAMmbFetchMsgTxt( &JamRec, First ))
      {
      char      Buf [128];

      wsprintf( Buf, "Error reading message text, code: %d, errno: %d", JamRec.APImsg, JamRec.Errno );
      MessageBox( hDlg, Buf, MSGBOXTITLE, MB_OK );
      LocalFree( hMem );
      return( FALSE );
      }

    if( JamRec.APImsg == JAMAPIMSG_NOMORETEXT )
      break;

    First = 0;

    for( p = ( UCHAR8 FAR * ) JamRec.WorkBuf; Pos < JamRec.WorkPos; Pos++, p++ )
      {
      if( Size + 7 >= BufSize )
        break;

      if( *p == '\r' )
        {
        strcpy(( CHAR8 * ) pBuf, "<0d>\r\n" );
        Size += 6;
        pBuf += 6;
        Col = 0;
        }

      else if( *p < ' ' )
        {
        wsprintf(( CHAR8 * ) pBuf, "<%02x>", *p );
        Size += 4;
        pBuf += 4;
        Col += 4;
        }
      else
        {
        if( Col > 70 && *p == ' ' )
          {
          *pBuf++ = '\r';
          *pBuf++ = '\n';
          Size += 2;
          Col = 0;
          }
        else
          {
          *pBuf++ = *p;
          Size++;
          Col++;
          }
        }
      }
    }

  *pBuf = '\0';

  OemToAnsi(( LPSTR ) pBufStart, ( LPSTR ) pBufStart );
  LocalUnlock( hMem );

  LocalReAlloc( hMem, Size + 1, 0 );

  SendDlgItemMessage( hDlg, IDC_TXT_EDIT, EM_SETHANDLE, ( WPARAM ) hMem, 0L );


  return( TRUE );
}


/* ---------------------------------------------------------------------- *
 *
 *  DlgItemPrintf
 *
 * ---------------------------------------------------------------------- */

int cdecl DlgItemPrintf( HWND hDlg, int Id, LPSTR Fmt, ...)
{
  char      Buf [256];
  int       Len;
  va_list   argptr;

  va_start( argptr, Fmt );
  Len = wvsprintf( Buf, Fmt, argptr );
  va_end( argptr );

  SetDlgItemText( hDlg, Id, Buf );

  return( Len );
}


/* ---------------------------------------------------------------------- *
 *
 *  DispTime
 *
 *    Converts the specified time to a ASCII string
 *
 *    Parameters:   UINT32 * pt             - # of seconds since 1970
 *
 *    Returns:      LPSTR                   - Ptr to buffer containing
 *                                            ASCII string
 *
 * ---------------------------------------------------------------------- */

LPSTR DispTime( UINT32 * pt )
{
  static CHAR8    MonthNames [12][4] = {"Jan","Feb","Mar","Apr","May","Jun",
                                        "Jul","Aug","Sep","Oct","Nov","Dec"};
  static CHAR8    Buffer [64];
  JAMTMptr        ptm;

  if( *pt == 0L )
    strcpy( Buffer, "<null>" );
  else
    {
    ptm = JAMsysLocalTime( pt );
    wsprintf( Buffer, "%s %d, %4d  %2d:%02d:%02d",
          ( LPSTR ) MonthNames [ptm->tm_mon], ptm->tm_mday, ptm->tm_year + 1900,
          ptm->tm_hour, ptm->tm_min, ptm->tm_sec );
    }

  return( Buffer );
}


/* ---------------------------------------------------------------------- *
 *
 *  AttrToStr
 *
 *    Convert the Attribute field to a ASCIIZ string containing all the
 *    attribute names
 *
 *    Parameters:   UINT32 Attr   - The attributes to convert
 *
 *    Returns:      LPSTR         - Ptr to buffer with attribute names
 *
 * ---------------------------------------------------------------------- */

LPSTR AttrToStr( UINT32 Attr )
{
  static CHAR8    Buf [256];
  CHAR8         * p = Buf;
  int             i;

  Buf [0] = '\0';

  for( i = 0; i < 32; i++ )
    {
    if( Attr & 0x00000001L )
      {
      if( p != Buf )
        {
        *p++ = ',';
        *p++ = ' ';
        }
      strcpy( p, AttrName [i] );
      p = strchr( p, '\0' );
      }

    Attr >>= 1;
    }

  return( Buf );
}


/* ---------------------------------------------------------------------- *
 *
 *  GetSubFldName
 *
 *    Get the name of the specified subfield
 *
 *    Parameters:   JAMSUBFIELD * pSubFld   - Ptr to subfield
 *
 *    Returns:      CHAR8 *                 - Name of subfield
 *
 * ---------------------------------------------------------------------- */

LPSTR GetSubFldName( JAMSUBFIELD FAR * pSubFld )
{
  int     i;

  for( i = 0; i < sizeof( SubFieldInfo ) / sizeof( SubFieldInfo [0] ); i++ )
    {
    if( pSubFld->LoID == SubFieldInfo [i].LoID &&
        pSubFld->HiID == SubFieldInfo [i].HiID )
      return( SubFieldInfo [i].pName );
    }

  return( "Undefined" );
}


/* ---------------------------------------------------------------------- *
 *
 *  GetSubFldStr
 *
 *    Convert the subfield contents to a string that can be displayed
 *
 *    Parameters:   JAMSUBFIELD * pSubFld   - Ptr to subfield
 *
 *    Returns:      CHAR8 *                 - Ptr to buffer containing
 *                                            subfield contents
 *
 * ---------------------------------------------------------------------- */

LPSTR GetSubFldStr( JAMSUBFIELD FAR * pSubFld )
{
  static UCHAR8   Buffer [256],
                * pBuf;
  UINT32          i;
  int             BufPos;

  for(  pBuf = Buffer, i = BufPos = 0;
        i < pSubFld->DatLen && BufPos + 5 < sizeof( Buffer );
        pBuf++, i++, BufPos++ )
    {
	if(( UCHAR8 ) *((UCHAR8 _JAMFAR *) JAMsysAddFarPtr ( pSubFld->Buffer, i )) < ' ' )
      {
	  wsprintf(( LPSTR ) pBuf, "<%02x>", ( UCHAR8 ) *((UCHAR8 _JAMFAR *) JAMsysAddFarPtr ( pSubFld->Buffer, i )) );
      BufPos += 3;
      pBuf += 3;
      }
    else
	  *pBuf = *((UCHAR8 _JAMFAR *) JAMsysAddFarPtr ( pSubFld->Buffer, i ));
    }

  *pBuf = '\0';

  OemToAnsi(( LPSTR ) Buffer, ( LPSTR ) Buffer );

  return(( LPSTR ) Buffer );
}
#if defined (__BORLANDC__)
#pragma warn .par
#endif


/* end of file "jamutilw.c" */

