/*********************************************************************
  d4switch.c   (c)Copyright Sequiter Software Inc., 1990-1993.
  All rights reserved.

  This example program is a Windows application similar in operation to
  d4exampl.c

  *********************************************************************/

#include "d4all.h"

#ifdef __TURBOC__
extern unsigned _stklen = 10000 ;
#endif


/*********** Structure Declarations **********************************/

typedef struct
{
#ifdef S4WINDOWS
#ifdef S4MEDIUM
  char *ptr ;
#else
  LPSTR  ptr ;
#endif
#else
  int          n_parms ;
  int          i_parm ;
  char       **parms ;
#endif
} D4PARSE_STR;

typedef struct
{
  HWND      hWnd ;
  HANDLE    hInst ;
  D4PARSE_STR  parse_str ;
  int          x,y ;

#ifdef S4WINDOWS
  TEXTMETRIC   tm ;
  LPMSG        lpmsg ;
  MSG          msg ;  /* Last Message */
  int          did_close ;
  int          did_quit ;
  HCURSOR      hSaveCursor ;
#endif
} D4DISPLAY;

/*********** Function Prototype and Global Variable Declarations *****/

int verify_switches() ;
void S4FUNCTION d4display_str( char *, int ) ;
long S4FUNCTION u4switch() ;

D4DISPLAY display ;

#ifdef S4WINDOWS

HCURSOR hHourGlass, hSaveCursor ;
extern MSG msg ;
extern TEXTMETRIC tm ;

int PASCAL WinMan(HANDLE, HANDLE, LPSTR, int) ;
BOOL InitApplication(HANDLE) ;
BOOL InitInstance(HANDLE, int) ;
long FAR PASCAL _export MainWndProc(HWND, UINT, UINT, LONG) ;

void S4FUNCTION d4display_init( HWND ) ;
void S4FUNCTION d4parsestring_init( D4PARSE_STR *, LPSTR ) ;
int S4FUNCTION d4display_quit() ;


/*********** Windows initialization functions ************************/

BOOL InitApplication(HANDLE hInstance)
{
  WNDCLASS  wc;

  wc.style = NULL;
  wc.lpfnWndProc = MainWndProc;

  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  wc.lpszMenuName =  "TestMenu";
  wc.lpszClassName = "TestWClass";

  return (RegisterClass(&wc));
}


BOOL InitInstance( HANDLE hInstance, int nCmdShow)
{
  HWND   hWnd;

  hWnd = CreateWindow(
    "TestWClass",
    "Test CodeBase",
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    NULL,
    NULL,
    hInstance,
    NULL
    );

  if (!hWnd)
    return (FALSE);

  SetTimer( hWnd, hWnd, 1000, NULL ) ;

  d4display_init( hWnd ) ;
  display.hInst = hInstance ;     /* for t4filter.c */

  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  return (TRUE);
}

long FAR PASCAL _export MainWndProc( HWND hWnd, UINT message, UINT wParam,
                                    LONG lParam)
{
  switch (message)
  {
  case WM_DESTROY:
    PostQuitMessage(0);
    break;

  case WM_CLOSE:
    display.did_close =  1 ;
    return (DefWindowProc(hWnd, message, wParam, lParam));

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

/************ display text in Windows functions ***********************/

void S4FUNCTION d4parsestring_init( D4PARSE_STR *p_str, LPSTR p )
{
  memset( p_str, 0, sizeof(D4PARSE_STR) ) ;

#ifdef S4MEDIUM
  lstrcpy( pointer, p ) ;
  p_str->ptr = pointer ;
#else
  p_str->ptr =  p ;
#endif
}

void S4FUNCTION d4display_init( HWND h )
{
  HDC hdc ;
  TEXTMETRIC tm ;

  memset( &display, 0, sizeof(D4DISPLAY) ) ;
  display.hWnd =  h ;
  display.lpmsg = &(display.msg) ;
  hdc =  GetDC(display.hWnd) ;
  GetTextMetrics( hdc, &tm ) ;
  display.tm = tm ;
  ReleaseDC(display.hWnd,hdc) ;
  display.x =  0 ;
  display.y =  0 ;
  display.did_close =  0 ;
  display.did_quit  =  0 ;
}


int S4FUNCTION d4display_quit( )
{
  /* If there is a message, the message is processed. */
  /* If the message says quit, then TRUE is returned. */
  if ( display.did_quit ) return 1 ;

  for (;;)
  {
    if ( ! display.did_close )
      if ( ! PeekMessage( display.lpmsg, display.hWnd, 0, 0, PM_NOREMOVE ) )
        return 0 ;

    if ( ! GetMessage( display.lpmsg, display.hWnd, 0, 0 ) )
    {
      MessageBox( display.hWnd, "", "Program Completed", MB_OK ) ;
      display.did_quit =  1 ;
      return 1 ;
    }

    TranslateMessage(display.lpmsg);
    DispatchMessage(display.lpmsg);
  }
}
#endif

void  S4FUNCTION d4display_str( char *str, int is_new_line )
{                               
#ifdef S4WINDOWS
  RECT rect ;
  HDC hdc ;
  int len, height, width ;
  DWORD dword ;
  char blank_line[180] ;
  
  memset(blank_line, 32, 179) ;
  blank_line[179] = '\0' ;
  
  hdc =  GetDC(display.hWnd) ;
  len =   strlen(str) ;
  
  dword =  GetTextExtent( hdc, str, len ) ;
  height =  HIWORD( dword ) ;
  width  =  LOWORD( dword ) ;
  
  if ( is_new_line )
  {
    display.x  =  0 ;
    display.y +=  height +  display.tm.tmExternalLeading ;
  }
  
  GetClientRect( display.hWnd, &rect ) ;
  
  if ( (display.y+height) > rect.bottom )
  {
    display.y =  0 ;
    InvalidateRect( display.hWnd, &rect, 1 ) ;
  }
  
  TextOut( hdc, display.x,display.y, str, len ) ;
  
  if ( (display.y+(2*height)) > rect.bottom )
    TextOut( hdc, 0, 0, blank_line, strlen(blank_line) ) ;
  else   
    TextOut( hdc, 0, (display.y+height+display.tm.tmExternalLeading), blank_line, strlen(blank_line) ) ;
  
  display.x +=  width ;
  
  ReleaseDC(display.hWnd,hdc) ;
#else
  if ( is_new_line )
  {
    printf( "\n%s", str ) ;
    display.x = 1 ;
  }
  else
    if (display.x == 0)
    {
      printf( "\r%s", str ) ;
      display.x = 1 ;
    }
    else
    {
      printf( "%s", str ) ;
      display.x = 1 ;
    }
#endif
}

/*********************************************************************/

#ifndef S4WINDOWS
void main()
{
#else
  int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,
                     int nCmdShow)
  {
    if (!hPrevInstance)
      if (!InitApplication(hInstance))
        return (FALSE);
    
    if (!InitInstance(hInstance, nCmdShow))
      return (FALSE);
    
    d4parsestring_init( &display.parse_str, lpCmdLine ) ;
#endif

    if (verify_switches())
    {
      d4display_str( "** ERROR ** Switch Configuration Confliction.", 1 ) ;
      d4display_str( " Your current switches in 'd4all.h' do not match the library.", 1 ) ;
    }
    else
      d4display_str( "\nSwitches Verified Successfully!", 1 ) ;

#ifdef S4WINDOWS
    PostQuitMessage(0) ;
    
    for (;;)
    {
      if (d4display_quit() )
        return (display.msg.wParam) ;
    }
#else 
    exit(0) ;
#endif
  }

  int verify_switches()
  {
    long d4switch ;

    d4switch = u4switch() ;

    d4display_str( " ", 1 ) ;
    d4display_str( " ", 1 ) ;
    d4display_str( "Library Conditional Compilation Switches:", 1 ) ;
    if( d4switch & 1 )
      d4display_str( "S4FOX - FoxPro Index File Compatibility", 1 ) ;
    if( d4switch & 2 )
      d4display_str( "S4CLIPPER - Clipper Index File Compatibility", 1 ) ;
    if( d4switch & 4 )
      d4display_str( "S4MDX - dBASE IV Index File Compatibility", 1 ) ;
    if( d4switch & 8 )
      d4display_str( "S4NDX - dBASE III or III PLUS Index File Compatibility", 1 ) ;
    if( d4switch & 0x10 )
      d4display_str( "S4DLL - Microsoft Windows DLL (S4DLL_BUILD on Library Build)", 1 ) ;
    if( d4switch & 0x20 )
      d4display_str( "S4WINDOWS - Microsoft Windows Static with Static Library", 1 ) ;
    if( d4switch & 0x40 )
      d4display_str( "S4OS2 - OS/2", 1 ) ;
    if( d4switch & 0x40 )
      d4display_str( "S4CODE_SCREENS - CodeScreens output Functions", 1 ) ;
    if( d4switch & 0x100 ) 
      d4display_str( "S4DEBUG - Extensive CodeBase Error Checking", 1 ) ;
    if( d4switch & 0x200 )
      d4display_str( "S4ERROR_HOOK - Custom Error Function", 1 ) ;
    if( d4switch & 0x400 )
      d4display_str( "\nS4LOCK_CHECK - Internal CodeBase Locking Diagnostics", 1 ) ;
    if( d4switch & 0x800 )
      d4display_str( "\nS4LOCK_HOOK - Custom Lock Failure Function", 1 ) ;
    if( d4switch & 0x1000 )
      d4display_str( "\nS4MAX - Maximum Memory Allocation Testing", 1 ) ;
    if( d4switch & 0x2000 )
      d4display_str( "\nS4MEMO_OFF - Memo File support source code removed", 1 ) ;
    if( d4switch & 0x4000 )
      d4display_str( "\nS4OLD_CODE - Support Functions from CodeBase 4.5", 1 ) ;
    if( d4switch & 0x8000 )
      d4display_str( "\nS4OPTIMIZE_OFF - Memory Optimization source code removed", 1 ) ;
    if( d4switch & 0x10000 )
      d4display_str( "\nS4PORTABLE - Maximum Portability", 1 ) ;
    if( d4switch & 0x20000 )
      d4display_str( "\nS4SAFE  - Immediate File Length Updates", 1 ) ;
    if( d4switch & 0x40000 )
      d4display_str( "\nS4SINGLE  - Multi-user support source code removed", 1 ) ;

#ifdef S4OPTIMIZE_OFF
    if( (d4switch & 0x8000)  ==  0 )
    {
      d4display_str( "***ERROR***:  S4OPTIMIZE_OFF must be used in Library Build too.", 1 ) ;
      return 1 ;
    }
#else
    if( d4switch & 0x8000  )
    {
      d4display_str( "***ERROR***:  S4OPTIMIZE_OFF must be off in Library Build too.", 1 ) ;
      return 1 ;
    }
#endif

#ifdef S4FOX
    if( (d4switch & 1)  == 0 )
    {
      d4display_str( "***ERROR***:  S4FOX must be used in Library Build too.", 1 ) ;
      return 1 ;
    }
#endif

#ifdef S4CLIPPER
    if( (d4switch & 2)  == 0 )
    {
      d4display_str( "***ERROR***:  S4CLIPPER must be used in Library Build too.", 1 ) ;
      return 1 ;
    }
#endif

#ifdef S4MDX
    if( (d4switch & 4)  == 0 )
    {
      d4display_str( "***ERROR***:  S4MDX must be used in Library Build too.", 1 ) ;
      return 1 ;
    }
#endif

#ifdef S4NDX
    if( (d4switch & 8)  == 0 )
    {
      d4display_str( "***ERROR***:  S4NDX must be used in Library Build too.", 1 ) ;
      return 1 ;
    }
#endif
    return 0 ;
  }

#ifdef S4FOX
#define S4FORMAT 1
#endif

#ifdef S4CLIPPER
#ifdef S4FORMAT
  error Choose only one CodeBase index file compatibility option.
#endif
#define S4FORMAT 2
#endif

#ifdef S4MDX
#ifdef S4FORMAT
    error Choose only one CodeBase index file compatibility option.
#endif
#define S4FORMAT 4
#endif

#ifdef S4NDX
#ifdef S4FORMAT
      error Choose only one CodeBase index file compatibility option.
#endif
#define S4FORMAT 8
#endif

#ifndef S4FORMAT
        error You must define either S4FOX, S4CLIPPER, S4NDX or S4MDX
#endif

#ifdef S4DLL
#define S4OPERATING 0x10
#ifndef S4DLL_BUILD
          error When building a CodeBase DLL, use the S4DLL_BUILD switch.
#endif
#endif

#ifdef S4WINDOWS
#undef S4OPERATING
#define S4OPERATING 0x20
#endif

#ifdef S4OS2
#ifdef S4OPERATING
            error Choose one of CodeBase switches S4DLL/S4WINDOWS, S4OS2, and S4CODE_SCREENS
#endif
#define S4OPERATING 0x40
#endif

#ifdef S4CODE_SCREENS
#ifdef S4OPERATING
              error Choose one of CodeBase switches S4DLL/S4WINDOWS, S4OS2, and S4CODE_SCREENS
#endif
#define S4OPERATING 0x80
#endif

#ifndef S4OPERATING
#define S4OPERATING 0
#endif

#ifdef S4DEBUG
#define S4DEBUG_VAL  0x100
#else
#define S4DEBUG_VAL  0
#endif

#ifdef S4ERROR_HOOK
#define S4ERROR_HOOK_VAL 0x200
#else
#define S4ERROR_HOOK_VAL 0
#endif

#ifdef S4LOCK_CHECK
#define S4LOCK_CHECK_VAL 0x400
#else
#define S4LOCK_CHECK_VAL 0
#endif

#ifdef S4LOCK_HOOK
#define S4LOCK_HOOK_VAL 0x800
#else
#define S4LOCK_HOOK_VAL 0
#endif

#ifdef S4MAX
#define S4MAX_VAL 0x1000
#else
#define S4MAX_VAL 0
#endif

#ifdef S4MEMO_OFF
#define S4MEMO_OFF_VAL 0x2000
#else
#define S4MEMO_OFF_VAL 0
#endif

#ifdef S4OLD_CODE
#define S4OLD_CODE_VAL 0x4000
#else
#define S4OLD_CODE_VAL 0
#endif

#ifdef S4OPTIMIZE_OFF
#define S4OPTIMIZE_OFF_VAL 0x8000
#else
#define S4OPTIMIZE_OFF_VAL 0
#endif

#ifdef S4PORTABLE
#define S4PORTABLE_VAL 0x10000
#else
#define S4PORTABLE_VAL 0
#endif

#ifdef S4SAFE 
#define S4SAFE_VAL 0x20000
#else
#define S4SAFE_VAL 0
#endif

#ifdef S4SINGLE 
#define S4SINGLE_VAL 0x40000
#else
#define S4SINGLE_VAL 0
#endif

                long S4FUNCTION u4switch()
                {
                  return (long) ( S4FORMAT + S4OPERATING + S4DEBUG_VAL + S4ERROR_HOOK_VAL +
                                 S4LOCK_CHECK_VAL + S4LOCK_HOOK_VAL + S4MAX_VAL +
                                 S4MEMO_OFF_VAL + S4OLD_CODE_VAL + S4OPTIMIZE_OFF_VAL +
                                 S4PORTABLE_VAL + S4SAFE_VAL + S4SINGLE_VAL ) ;
                }
