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

#ifdef S4OS2PM
#define  INCL_WINSYS
#define  INCL_WINWINDOWMGR
#define  INCL_DOSPROCESS
#define  INCL_GPIPRIMITIVES
#define  INCL_GPILCIDS
#endif

#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif
#include "t4test.h"

#ifdef S4WINDOWS
#ifdef __ZTC__
#ifndef NULL
#define NULL 0
#endif
#endif
#ifdef DLL
#define TEST_EXPORT _export
#endif
#else
#ifdef S4UNIX
#ifdef S4CURSES
/*       #include <curses.h>  */
#else
/*       #include <tinfo.h>   */
#endif
#else
#include <conio.h>
#endif
#endif

#ifdef S4WINDOWS
HCURSOR hHourGlass, hSaveCursor ;
#endif

#ifdef S4WINDOWS
void S4FUNCTION d4display_init( D4DISPLAY *disp, HWND h )
{
  HDC hdc ;
  TEXTMETRIC tm ;

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

#ifdef S4MEDIUM
char pointer[100] ;   /* argument list for medium memory model */
#endif
#endif
#ifdef S4OS2PM
void S4FUNCTION d4display_init( D4DISPLAY *disp, HWND h )
{
  HPS hps ;
  FONTMETRICS tm ;
  LONG lmlen ;


  memset( disp, 0, sizeof(D4DISPLAY) ) ;
  disp->hWnd = h ;
  hps = WinGetPS(disp->hWnd) ;
  GpiQueryFontMetrics( hps, lmlen, &tm ) ;
  disp->tm = tm ;
  /*      memcpy( &disp->tm, tm, sizeof( FONTMENTRICS ) ) ; */
  WinReleasePS( hps ) ;
  disp->x = 0 ;
  disp->y = 0 ;
  disp->did_close = 0 ;
  disp->did_quit  = 0 ;
}
#endif

void  S4FUNCTION d4display_str( D4DISPLAY *disp, char *str, int is_new_line )
{
#ifndef S4NO_OUT
#ifdef S4OS2PM
  HPS    hps ;
  RECTL  rect ;
  POINTL pt ;
  SIZEL size ;
  int len, height, width, i ;
  char blank_line[180] ;

  while ( disp->display_set == 1 )   /* a display message not processed is waiting */
    ;

  disp->display_set = 1 ;  /* mark a message as pending */

  len = strlen( str ) ;

  memcpy( disp->str, str, len ) ;
  disp->len = len ;
  disp->is_new_line = is_new_line ;

  WinInvalidateRegion( disp->hWnd, (HRGN)NULL, FALSE );

  return ;
#else
#ifdef S4WINDOWS
  RECT rect ;
  HDC hdc ;
  int len, height, width ;
  DWORD dword ;
  char blank_line[180] ;
  SIZE size;

  memset(blank_line, 32, 179) ;
  blank_line[179] = '\0' ;

  hdc = GetDC(disp->hWnd) ;
  len = strlen(str) ;

  dword = GetTextExtentPoint( hdc, str, len, &size ) ;
  height = size.cy ;
  width  = size.cx ;

  if ( is_new_line )
  {
    disp->x = 0 ;
    disp->y += height + disp->tm.tmExternalLeading ;
  }

  GetClientRect( disp->hWnd, &rect ) ;

  if ( (disp->y+height) > rect.bottom )
  {
    disp->y = 0 ;
    InvalidateRect( disp->hWnd, &rect, 1 ) ;
  }

  TextOut( hdc, disp->x,disp->y, str, len ) ;

  if ( (disp->y+(2*height)) > rect.bottom )
    TextOut( hdc, 0, 0, blank_line, strlen(blank_line) ) ;
  else
    TextOut( hdc, 0, (disp->y+height+disp->tm.tmExternalLeading), blank_line, strlen(blank_line) ) ;

  disp->x += width ;

  ReleaseDC(disp->hWnd,hdc) ;
#else
  if ( is_new_line )
  {
    printf( "\n%s", str ) ;
    disp->x = 1 ;
  }
  else
  {
    if (disp->x == 0)
    {
      printf( "\r%s", str ) ;
      disp->x = 1 ;
    }
    else
    {
      printf( "%s", str ) ;
      disp->x = 1 ;
    }
  }
#endif
#endif
#endif
}

void  S4FUNCTION d4display_num( D4DISPLAY *disp, long num, int is_new_line )
{
#ifndef S4NO_OUT
  char str[13] ;
  char *ptr ;

  ptr = str ;
  c4ltoa45( num, ptr, sizeof(str)-1 ) ;
  str[12] = '\0' ;
  d4display_str( disp, str, is_new_line ) ;
#endif
}

int S4FUNCTION d4display_quit( D4DISPLAY *disp )
{
#ifdef S4WINDOWS
  /* If there is a message, the message is processed. */
  /* If the message says quit, then TRUE is returned. */
  if ( disp->did_quit ) return 1 ;

  for (;;)
  {
    if ( ! disp->did_close )
      if ( ! PeekMessage( disp->lpmsg, disp->hWnd, 0, 0, PM_NOREMOVE ) )
        return 0 ;

    if ( ! GetMessage( disp->lpmsg, disp->hWnd, 0, 0 ) )
    {
#ifndef S4TESTING
      MessageBox( disp->hWnd, "", "Program Completed", MB_OK ) ;
#endif
      disp->did_quit = 1 ;
      return 1 ;
    }

    TranslateMessage(disp->lpmsg);
    DispatchMessage(disp->lpmsg);
  }
#else
  disp = disp ;  /* avoid compiler warnings */
  return 0 ;
#endif
}

void  S4FUNCTION d4display_wait( D4DISPLAY *disp )
{
#ifdef S4WINDOWS
  hHourGlass = LoadCursor( NULL, IDC_WAIT ) ;

  SetCapture( disp->hWnd ) ;
  hSaveCursor = SetCursor(hHourGlass) ;
#else
  disp = disp ;  /* avoid compiler warnings */
#endif
}


void  S4FUNCTION d4display_start()
{
#ifdef S4WINDOWS
  SetCursor(hSaveCursor) ;
  ReleaseCapture() ;
#endif
}


#ifdef S4WINDOWS
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
}
#else
void S4FUNCTION d4parsestring_init( D4PARSE_STR *p_str, int n, char **p )
{
  p_str->n_parms = n - 1 ;
  p_str->parms   = p ;
  p_str->i_parm  = 0 ;
}
#endif


char *S4FUNCTION d4parsestring_nparm( D4PARSE_STR *p_str )
{
#ifdef S4WINDOWS
  unsigned i ;
  char *new_ptr ;

  if ( p_str->ptr == 0 )
    return (char *) p_str->ptr ;

  while (p_str->ptr[0] == ' ' )
    p_str->ptr++ ;

  for ( i = 0; ; i++ )
    if ( p_str->ptr[i] == 0 || p_str->ptr[i] == ' ' )
    {
      new_ptr = p_str->ptr ;
      p_str->ptr += i ;
      return  (char *) new_ptr ;
    }
#else
  p_str->i_parm++ ;
  if (p_str->i_parm > p_str->n_parms)
    return (char *) "" ;
  return  (char *) p_str->parms[p_str->i_parm] ;
#endif
}

ERROR_DATA t4error_data[] =
{
{ t4err_field,    "Field Error" },
{ t4err_append,   "append failure" },
{ t4err_append_blank,  "d4append_blank() failure" },
{ t4err_count,    "d4reccount() returned an incorrect count" },
{ t4err_go,       "d4go()/d4top()/d4bottom() failure" },
{ t4err_data,     "open()/create() returned a null value" },
{ t4err_write,    "d4write()/f4write() failed" },
{ t4err_close,    "d4close() failed" },
{ t4err_lock,     "locking failure" },
{ t4err_unlock,   "unlocking failure" },
{ t4err_recno,    "unexpected d4recno() value" },
{ t4err_deleted,  "unexpected d4deleted() value" },
{ t4err_pack,     "d4pack() failure" },
{ t4err_zap,      "d4zap() failure" },
{ t4err_n_fields, "d4num_fields() failure" },
{ t4err_name,     "Naming error" },
{ t4err_memory,   "Memory error" },
{ t4err_general,  "General test failure" },
{ t4err_sort,     "Sorting failure" },
{ t4err_check,    "d4check()/i4check()/..check() failed" },
{ t4err_tag,      "tag function failure" },
{ t4err_seek,     "seek failure" },
{ t4err_reindex,  "reindex failure" },
{ t4err_skip,     "skip failure" },
{ t4err_parm,     "Missing command line parameter(s)" },
{ t4err_expr,     "Expression error" },
{ t4err_memo,     "Memo error" },
{ t4err_flush,    "Flushing failure" },
{ t4err_opt,      "Optimization error" },
{ t4err_date,     "Date error" },
{ t4err_position, "Position function error" },
{ t4err_relate,   "Relation error" },
{ t4err_read,     "File Reading error" },
{ 0, 0 },
} ;

#ifdef S4WINDOWS
void  S4FUNCTION t4warn( int err_code, char *desc )
{
  char error_str[257] ;
  int pos, i ;

  strcpy( error_str, T4_ERROR_WAR ) ;
  strcat( error_str, " #: " ) ;
  c4ltoa45( err_code, (char far *)error_str+16, 4 ) ;
  pos =  20 ;

  error_str[pos++] = '\n' ;

  for ( i=0; t4error_data[i].error_num != 0; i++ )
    if ( t4error_data[i].error_num == err_code )
    {
      strcpy( error_str+pos, t4error_data[i].error_data ) ;
      pos +=  strlen( t4error_data[i].error_data ) ;
      error_str[pos++] = '\n' ;
      break ;
    }

  if ( strlen(desc)+pos+4 < sizeof(error_str) )
  {
    strcpy( error_str+pos, desc ) ;
    pos +=  strlen(desc) ;
    error_str[pos++] = '\n' ;
  }

  error_str[pos] =  0 ;

  OemToAnsi( error_str, error_str ) ;

#ifdef S4TESTING
  u4write_err( error_str ) ;
#else
  MessageBox( 0, error_str, E4_ERROR_CDS, MB_OK | MB_ICONSTOP ) ;
#endif
}

void S4FUNCTION t4severe( int err_code, char *desc )
{
  char error_str[257] ;
  int pos, i ;

  strcpy( error_str, T4_ERROR_SEV ) ;
  strcat( error_str, " #: " ) ;
  c4ltoa45( err_code, (char far *)error_str+16, 4 ) ;
  pos =  20 ;

  error_str[pos++] = '\n' ;

  for ( i=0; t4error_data[i].error_num != 0; i++ )
    if ( t4error_data[i].error_num == err_code )
    {
      strcpy( error_str+pos, t4error_data[i].error_data ) ;
      pos +=  strlen( t4error_data[i].error_data ) ;
      error_str[pos++] = '\n' ;
      break ;
    }

  if ( strlen(desc)+pos+4 < sizeof(error_str) )
  {
    strcpy( error_str+pos, desc ) ;
    pos +=  strlen(desc) ;
    error_str[pos++] = '\n' ;
  }

  error_str[pos] =  0 ;

  OemToAnsi( error_str, error_str ) ;

#ifdef S4TESTING
  u4write_err( error_str ) ;
  u4terminate() ;
#else
  MessageBox( 0, error_str, E4_ERROR_CDS, MB_OK | MB_ICONSTOP ) ;
  FatalAppExit( 0, error_str ) ;
#endif
}
#else
#ifdef S4OS2PM

/* uses the display object and d4display_str() function for boxing message */
void S4FUNCTION t4warn( int err_code, char *desc )
{
  int pos, i ;

  while ( display.display_set == 1 )   /* a display message not processed is waiting */
    ;

  display.display_set = 1 ;  /* mark a message as pending */

  strcpy( display.str, T4_ERROR_WAR ) ;
  strcat( display.str, " #: " ) ;
  c4ltoa45( err_code, (char *)display.str+16, 4 ) ;
  pos = 20 ;

  display.str[pos++] = '\n' ;

  for ( i=0; t4error_data[i].error_num != 0; i++ )
    if ( t4error_data[i].error_num == err_code )
    {
      strcpy( display.str+pos, t4error_data[i].error_data ) ;
      pos +=  strlen( t4error_data[i].error_data ) ;
      display.str[pos++] = '\n' ;
      break ;
    }

  if ( strlen(desc)+pos+4 < sizeof(display.str) )
  {
    strcpy( display.str+pos, desc ) ;
    pos +=  strlen(desc) ;
    display.str[pos++] = '\n' ;
  }

  display.str[pos] = 0 ;  /* display routine will set back to 1 */

  WinPostMsg(hwndMain, EM_CODEBASE_ERROR, (MPARAM)NULL, (MPARAM)NULL);

  return ;
}

void S4FUNCTION t4severe( int err_code, char *desc )
{
  int pos, i ;

  while ( display.display_set == 1 )   /* a display message not processed is waiting */
    ;

  display.display_set = 1 ;  /* mark a message as pending */

  strcpy( display.str, T4_ERROR_SEV ) ;
  strcat( display.str, " #: " ) ;
#ifdef S4OS2PM
  c4ltoa45( err_code, (char *)display.str+16, 4 ) ;
#else
  c4ltoa45( err_code, (char far *)display.str+16, 4 ) ;
#endif
  pos =  20 ;

  display.str[pos++] = '\n' ;

  for ( i=0; t4error_data[i].error_num != 0; i++ )
    if ( t4error_data[i].error_num == err_code )
    {
      strcpy( display.str+pos, t4error_data[i].error_data ) ;
      pos +=  strlen( t4error_data[i].error_data ) ;
      display.str[pos++] = '\n' ;
      break ;
    }

  if ( strlen(desc)+pos+4 < sizeof(display.str) )
  {
    strcpy( display.str+pos, desc ) ;
    pos +=  strlen(desc) ;
    display.str[pos++] = '\n' ;
  }

  display.str[pos] =  0 ;
  WinPostMsg(hwndMain, EM_CODEBASE_ERROR, (MPARAM)NULL, (MPARAM)NULL);
  DosExit(EXIT_THREAD, 0L);
}
#else
static void  e4error_out( char *ptr )
{
#ifdef S4UNIX
  printf("%s", ptr ) ;
#else
#ifdef S4TESTING
  u4write_err( ptr ) ;
#else
  write( 1, ptr, (unsigned int) strlen(ptr) ) ;
#endif
#endif
}

static void display( int err_code )
{
  char buf[11] ;
  int i ;

  c4ltoa45( (long) err_code, buf, 6 ) ;
  buf[6] =  0 ;
  e4error_out( buf ) ;

  for ( i = 0; t4error_data[i].error_data != 0; i++ )
    if ( t4error_data[i].error_num == err_code )
    {
      e4error_out( "\r\n" ) ;
      e4error_out( t4error_data[i].error_data ) ;
      break ;
    }
}

void S4FUNCTION t4warn( int err_code, char *desc )
{
  e4error_out( T4_ERROR_WAR ) ;
  display( err_code ) ;

  e4error_out( "\r\n" ) ;
  e4error_out( desc ) ;
}

void S4FUNCTION t4severe( int err_code, char *desc )
{
  e4error_out( T4_ERROR_SEV ) ;
  display( err_code ) ;

  e4error_out( "\r\n" ) ;
  e4error_out( desc ) ;

#ifndef S4TESTING
#ifdef S4UNIX
  getchar() ;
#else
  getch() ;
#endif
#endif
  exit(1) ;
}
#endif  /* S4OS2PM */
#endif  /* S4WINDOWS */

#ifdef S4ERROR_HOOK
void S4FUNCTION e4hook( CODE4 S4PTR *c4, int err_code, char *desc1, char *desc2, char *desc3 )
{
  t4severe( err_code, desc1 ) ;
}
#endif
