]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/db/dbtest.cpp
Sizing fixes for generic control.
[wxWidgets.git] / samples / db / dbtest.cpp
index f9cb9c08351ba36e12f227f6f3f75ca993898272..211f6ca7c3b3fafa69384c09b39e48a13ff57898 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Name:        dbtest.cpp
 ///////////////////////////////////////////////////////////////////////////////
 // Name:        dbtest.cpp
-// Purpose:     wxWindows database demo app
+// Purpose:     wxWidgets database demo app
 // Author:      George Tasker
 // Modified by:
 // Created:     1998
 // Author:      George Tasker
 // Modified by:
 // Created:     1998
     donated by the development team at Remstar International.
 
     The table this sample is based on is developer contact table, and shows
     donated by the development team at Remstar International.
 
     The table this sample is based on is developer contact table, and shows
-    some of the simple uses of the database classes wxDB and wxTable.
+    some of the simple uses of the database classes wxDb and wxDbTable.
 
  *  SYNOPSIS END
  */
 
 
  *  SYNOPSIS END
  */
 
-#ifdef __GNUG__
-#pragma implementation "dbtest.h"
-#endif
-
 #include  "wx/wxprec.h"
 
 #ifdef    __BORLANDC__
 #include  "wx/wxprec.h"
 
 #ifdef    __BORLANDC__
 #endif  //__BORLANDC__
 
 #ifndef WX_PRECOMP
 #endif  //__BORLANDC__
 
 #ifndef WX_PRECOMP
-#include  <wx/wx.h>
+#include  "wx/wx.h"
 #endif //WX_PRECOMP
 
 #endif //WX_PRECOMP
 
-#ifdef __WXGTK__
+#if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMAC__)
 #include "db.xpm"
 #endif
 
 #include <stdio.h>                  /* Included strictly for reading the text file with the database parameters */
 
 #include "db.xpm"
 #endif
 
 #include <stdio.h>                  /* Included strictly for reading the text file with the database parameters */
 
-#include <wx/db.h>                  /* Required in the file which will get the data source connection */
-#include <wx/dbtable.h>             /* Has the wxTable object from which all data objects will inherit their data table functionality */
+//#include "wx/db.h"                  /* Required in the file which will get the data source connection */
+//#include "wx/dbtable.h"             /* Has the wxDbTable object from which all data objects will inherit their data table functionality */
+
+//extern wxDbList WXDLLEXPORT *PtrBegDbList;    /* from db.cpp, used in getting back error results from db connections */
 
 
-extern wxDbList WXDLLEXPORT *PtrBegDbList;    /* from db.cpp, used in getting back error results from db connections */
+#if wxUSE_GRID
+#include "wx/grid.h"
+#include "wx/generic/gridctrl.h"
+#include "wx/dbgrid.h"
+
+#define CHOICEINT
+#endif
 
 #include "dbtest.h"                 /* Header file for this demonstration program */
 #include "listdb.h"                 /* Code to support the "Lookup" button on the editor dialog */
 
 IMPLEMENT_APP(DatabaseDemoApp)
 
 
 #include "dbtest.h"                 /* Header file for this demonstration program */
 #include "listdb.h"                 /* Code to support the "Lookup" button on the editor dialog */
 
 IMPLEMENT_APP(DatabaseDemoApp)
 
-extern char ListDB_Selection[];        /* Used to return the first column value for the selected line from the listDB routines */
-extern char ListDB_Selection2[];    /* Used to return the second column value for the selected line from the listDB routines */
+extern wxChar ListDB_Selection[];   /* Used to return the first column value for the selected line from the listDB routines */
+extern wxChar ListDB_Selection2[];  /* Used to return the second column value for the selected line from the listDB routines */
 
 
-DatabaseDemoFrame *DemoFrame;       /* Pointer to the main frame */
+#ifdef wxODBC_BLOB_SUPPORT
+    #include "wx/file.h"
+    #include "wx/mstream.h"
+    #include "wx/image.h"
+    #include "wx/bitmap.h"
+    #include "wx/statbmp.h"
+#endif
 
 
-/* Pointer to the main database connection used in the program.  This
- * pointer would normally be used for doing things as database lookups
- * for user login names and passwords, getting workstation settings, etc.
- * ---> IMPORTANT <---
- * 
- *        For each database object created which uses this wxDB pointer
- *    connection to the database, when a CommitTrans() or RollBackTrans()
- *    will commit or rollback EVERY object which uses this wxDB pointer.
- *
- *    To allow each table object (those derived from wxTable) to be 
- *    individually committed or rolled back, you MUST use a different
- *    instance of wxDB in the constructor of the table.  Doing so creates 
- *        more overhead, and will use more database connections (some DBs have
- *    connection limits...), so use connections sparringly.
- *
- *        It is recommended that one "main" database connection be created for
- *        the entire program to use for READ-ONLY database accesses, but for each
- *        table object which will do a CommitTrans() or RollbackTrans() that a
- *        new wxDB object be created and used for it.
- */
-wxDB    *READONLY_DB;
+#if !wxUSE_ODBC
+  #error Sample cannot be compiled unless setup.h has wxUSE_ODBC set to 1
+#endif
 
 
-/*
- * This function will return the exact string(s) from the database engine
- * indicating all error conditions which have just occured during the
- * last call to the database engine.
- *
- * This demo uses the returned string by displaying it in a wxMessageBox.  The
- * formatting therefore is not the greatest, but this is just a demo, not a
- * finished product.  :-) gt
- *
- * NOTE: The value returned by this function is for temporary use only and
- *       should be copied for long term use
- */
-char *GetExtendedDBErrorMsg(char *ErrFile, int ErrLine)
+
+bool DataTypeSupported(wxDb *pDb, SWORD datatype, wxString *nativeDataTypeName)
 {
 {
-    static wxString msg;
+    wxDbSqlTypeInfo sqlTypeInfo;
 
 
-    wxString tStr;
+    bool breakpoint = false;
 
 
-    if (ErrFile || ErrLine)
-    {
-        msg += "File: ";
-        msg += ErrFile;
-        msg += "   Line: ";
-        tStr.Printf("%d",ErrLine);
-        msg += tStr.GetData();
-        msg += "\n";
-    }
-
-    msg.Append ("\nODBC errors:\n");
-    msg += "\n";
-    
-    /* Scan through each database connection displaying 
-     * any ODBC errors that have occured. */
-    wxDbList *pDbList;
-    for (pDbList = PtrBegDbList; pDbList; pDbList = pDbList->PtrNext)
-    {
-        // Skip over any free connections
-        if (pDbList->Free)
-            continue;
-        // Display errors for this connection
-        int i;
-        for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
-        {
-            if (pDbList->PtrDb->errorList[i])
-            {
-                msg.Append(pDbList->PtrDb->errorList[i]);
-                if (strcmp(pDbList->PtrDb->errorList[i],"") != 0)
-                    msg.Append("\n");
-            }
-        }
+    *nativeDataTypeName = wxEmptyString;
+    if (pDb->GetDataTypeInfo(datatype, sqlTypeInfo))
+    {
+        *nativeDataTypeName = sqlTypeInfo.TypeName;
+        breakpoint = true;
+    }
+
+    return breakpoint;
+
+}  // GetDataTypesSupported();
+
+
+
+void CheckSupportForAllDataTypes(wxDb *pDb)
+{
+    wxString nativeDataTypeName;
+
+    wxLogMessage(wxT("\nThe following datatypes are supported by the\ndatabase you are currently connected to:"));
+#ifdef SQL_C_BINARY
+    if (DataTypeSupported(pDb,SQL_C_BINARY, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_BINARY (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_BIT
+    if (DataTypeSupported(pDb,SQL_C_BIT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_BIT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_BOOKMARK
+    if (DataTypeSupported(pDb,SQL_C_BOOKMARK, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_BOOKMARK (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_CHAR
+    if (DataTypeSupported(pDb,SQL_C_CHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_CHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_DATE
+    if (DataTypeSupported(pDb,SQL_C_DATE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_DATE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_DEFAULT
+    if (DataTypeSupported(pDb,SQL_C_DEFAULT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_DEFAULT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_DOUBLE
+    if (DataTypeSupported(pDb,SQL_C_DOUBLE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_DOUBLE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_FLOAT
+    if (DataTypeSupported(pDb,SQL_C_FLOAT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_FLOAT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_GUID
+    if (DataTypeSupported(pDb,SQL_C_GUID, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_GUID (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_DAY
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_DAY_TO_HOUR
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_HOUR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY_TO_HOUR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_DAY_TO_MINUTE
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_MINUTE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY_TO_MINUTE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_DAY_TO_SECOND
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_SECOND, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY_TO_SECOND (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_HOUR
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_HOUR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_HOUR_TO_MINUTE
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_MINUTE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_HOUR_TO_MINUTE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_HOUR_TO_SECOND
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_SECOND, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_HOUR_TO_SECOND (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_MINUTE
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_MINUTE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_MINUTE_TO_SECOND
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE_TO_SECOND, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_MINUTE_TO_SECOND (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_MONTH
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_MONTH, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_MONTH (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_SECOND
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_SECOND, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_SECOND (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_YEAR
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_YEAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_INTERVAL_YEAR_TO_MONTH
+    if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR_TO_MONTH, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_INTERVAL_YEAR_TO_MONTH (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_LONG
+    if (DataTypeSupported(pDb,SQL_C_LONG, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_LONG (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_NUMERIC
+    if (DataTypeSupported(pDb,SQL_C_NUMERIC, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_NUMERIC (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_SBIGINT
+    if (DataTypeSupported(pDb,SQL_C_SBIGINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_SBIGINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_SHORT
+    if (DataTypeSupported(pDb,SQL_C_SHORT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_SHORT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_SLONG
+    if (DataTypeSupported(pDb,SQL_C_SLONG, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_SLONG (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_SSHORT
+    if (DataTypeSupported(pDb,SQL_C_SSHORT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_SSHORT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_STINYINT
+    if (DataTypeSupported(pDb,SQL_C_STINYINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_STINYINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_TIME
+    if (DataTypeSupported(pDb,SQL_C_TIME, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_TIME (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_TIMESTAMP
+    if (DataTypeSupported(pDb,SQL_C_TIMESTAMP, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_TIMESTAMP (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_TINYINT
+    if (DataTypeSupported(pDb,SQL_C_TINYINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_TINYINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_TYPE_DATE
+    if (DataTypeSupported(pDb,SQL_C_TYPE_DATE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_TYPE_DATE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_TYPE_TIME
+    if (DataTypeSupported(pDb,SQL_C_TYPE_TIME, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_TYPE_TIME (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_TYPE_TIMESTAMP
+    if (DataTypeSupported(pDb,SQL_C_TYPE_TIMESTAMP, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_TYPE_TIMESTAMP (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_UBIGINT
+    if (DataTypeSupported(pDb,SQL_C_UBIGINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_UBIGINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_ULONG
+    if (DataTypeSupported(pDb,SQL_C_ULONG, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_ULONG (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_USHORT
+    if (DataTypeSupported(pDb,SQL_C_USHORT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_USHORT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_UTINYINT
+    if (DataTypeSupported(pDb,SQL_C_UTINYINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_UTINYINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_VARBOOKMARK
+    if (DataTypeSupported(pDb,SQL_C_VARBOOKMARK, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_VARBOOKMARK (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_C_WXCHAR
+    if (DataTypeSupported(pDb,SQL_C_WXCHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_WXCHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+
+// Extended SQL types
+#ifdef SQL_DATE
+    if (DataTypeSupported(pDb,SQL_DATE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_DATE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_INTERVAL
+    if (DataTypeSupported(pDb,SQL_INTERVAL, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_INTERVAL (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_TIME
+    if (DataTypeSupported(pDb,SQL_TIME, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_TIME (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_TIMESTAMP
+    if (DataTypeSupported(pDb,SQL_TIMESTAMP, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_TIMESTAMP (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_LONGVARCHAR
+    if (DataTypeSupported(pDb,SQL_LONGVARCHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_LONGVARCHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_BINARY
+    if (DataTypeSupported(pDb,SQL_BINARY, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_BINARY (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_VARBINARY
+    if (DataTypeSupported(pDb,SQL_VARBINARY, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_VARBINARY (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_LONGVARBINARY
+    if (DataTypeSupported(pDb,SQL_LONGVARBINARY, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_LOGVARBINARY (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_BIGINT
+    if (DataTypeSupported(pDb,SQL_BIGINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_BIGINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_TINYINT
+    if (DataTypeSupported(pDb,SQL_TINYINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_TINYINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_BIT
+    if (DataTypeSupported(pDb,SQL_BIT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_BIT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_GUID
+    if (DataTypeSupported(pDb,SQL_GUID, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_GUID (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+
+#ifdef SQL_CHAR
+    if (DataTypeSupported(pDb,SQL_CHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_CHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_INTEGER
+    if (DataTypeSupported(pDb,SQL_INTEGER, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_INTEGER (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
     }
     }
-    msg += "\n";
+#endif
+#ifdef SQL_SMALLINT
+    if (DataTypeSupported(pDb,SQL_SMALLINT, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_SAMLLINT (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_REAL
+    if (DataTypeSupported(pDb,SQL_REAL, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_REAL (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_DOUBLE
+    if (DataTypeSupported(pDb,SQL_DOUBLE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_DOUBLE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_NUMERIC
+    if (DataTypeSupported(pDb,SQL_NUMERIC, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_NUMERIC (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_DATE
+    if (DataTypeSupported(pDb,SQL_DATE, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_DATE (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_TIME
+    if (DataTypeSupported(pDb,SQL_TIME, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_TIME (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_TIMESTAMP
+    if (DataTypeSupported(pDb,SQL_TIMESTAMP, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_TIMESTAMP (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_VARCHAR
+    if (DataTypeSupported(pDb,SQL_VARCHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_VARCHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
 
 
-    return (char*) (const char*) msg;
-}  // GetExtendedDBErrorMsg
+// UNICODE
+#ifdef SQL_C_TCHAR
+    if (DataTypeSupported(pDb,SQL_C_TCHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_C_TCHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_WVARCHAR
+    if (DataTypeSupported(pDb,SQL_WVARCHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_WVARCHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+#ifdef SQL_WCHAR
+    if (DataTypeSupported(pDb,SQL_WCHAR, &nativeDataTypeName))
+    {
+        nativeDataTypeName = wxT("SQL_WCHAR (") + nativeDataTypeName;
+        nativeDataTypeName += wxT(")\n");
+        wxLogMessage(nativeDataTypeName);
+    }
+#endif
+
+    wxLogMessage(wxT("Done\n"));
+}  // CheckSupportForAllDataTypes()
 
 
 bool DatabaseDemoApp::OnInit()
 {
 
 
 bool DatabaseDemoApp::OnInit()
 {
+    DbConnectInf    = NULL;
+    Contact         = NULL;
+
     // Create the main frame window
     // Create the main frame window
-    DemoFrame = new DatabaseDemoFrame(NULL, "wxWindows Database Demo", wxPoint(50, 50), wxSize(537, 480));
+    DemoFrame = new DatabaseDemoFrame(NULL, wxT("wxWidgets Database Demo"), wxPoint(50, 50), wxSize(537, 530));
 
     // Give it an icon
     DemoFrame->SetIcon(wxICON(db));
 
     // Make a menubar
     wxMenu *file_menu = new wxMenu;
 
     // Give it an icon
     DemoFrame->SetIcon(wxICON(db));
 
     // Make a menubar
     wxMenu *file_menu = new wxMenu;
-    file_menu->Append(FILE_CREATE, "&Create contact table");
-    file_menu->Append(FILE_EXIT, "E&xit");
+    file_menu->Append(FILE_CREATE_ID, wxT("&Create CONTACT table"));
+    file_menu->Append(FILE_RECREATE_TABLE, wxT("&Recreate CONTACT table"));
+    file_menu->Append(FILE_RECREATE_INDEXES, wxT("&Recreate CONTACT indexes"));
+#if wxUSE_GRID
+    file_menu->Append(FILE_DBGRID_TABLE,  wxT("&Open DB Grid example"));
+#endif
+    file_menu->Append(FILE_EXIT, wxT("E&xit"));
 
     wxMenu *edit_menu = new wxMenu;
 
     wxMenu *edit_menu = new wxMenu;
-    edit_menu->Append(EDIT_PARAMETERS, "&Parameters...");
+    edit_menu->Append(EDIT_PARAMETERS, wxT("&Parameters..."));
 
 
-    wxMenu *about_menu = new wxMenu;
-    about_menu->Append(ABOUT_DEMO, "&About");
+    wxMenu *help_menu = new wxMenu;
+    help_menu->Append(HELP_ABOUT, wxT("&About"));
 
     wxMenuBar *menu_bar = new wxMenuBar;
 
     wxMenuBar *menu_bar = new wxMenuBar;
-    menu_bar->Append(file_menu, "&File");
-    menu_bar->Append(edit_menu, "&Edit");
-    menu_bar->Append(about_menu, "&About");
+    menu_bar->Append(file_menu, wxT("&File"));
+    menu_bar->Append(edit_menu, wxT("&Edit"));
+    menu_bar->Append(help_menu, wxT("&Help"));
     DemoFrame->SetMenuBar(menu_bar);
 
     DemoFrame->SetMenuBar(menu_bar);
 
-    // Initialize the ODBC Environment for Database Operations
-    if (SQLAllocEnv(&DbConnectInf.Henv) != SQL_SUCCESS)
-    {
-        wxMessageBox("A problem occured while trying to get a connection to the data source","DB CONNECTION ERROR",wxOK | wxICON_EXCLAMATION);
-        return NULL;
-    }
-
     params.ODBCSource[0] = 0;
     params.UserName[0]   = 0;
     params.Password[0]   = 0;
     params.DirPath[0]    = 0;
 
     params.ODBCSource[0] = 0;
     params.UserName[0]   = 0;
     params.Password[0]   = 0;
     params.DirPath[0]    = 0;
 
+#ifdef wxODBC_BLOB_SUPPORT
+    wxInitAllImageHandlers();
+    wxImage::InitStandardHandlers();
+    wxBitmap::InitStandardHandlers();
+#endif
+
+    // Show the frame
+    DemoFrame->Show(true);
+
+    // Passing NULL for the SQL environment handle causes
+    // the wxDbConnectInf constructor to obtain a handle
+    // for you.
+    //
+    // WARNING: Be certain that you do not free this handle
+    //          directly with SQLFreeEnv().  Use either the
+    //          method ::FreeHenv() or delete the DbConnectInf.
+    DbConnectInf = new wxDbConnectInf(NULL, params.ODBCSource, params.UserName,
+                                      params.Password, params.DirPath);
+
+    if (!DbConnectInf || !DbConnectInf->GetHenv())
+    {
+        wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
+        wxDELETE(DbConnectInf);
+    }
+
+    if (!ReadParamFile(params))
+        DemoFrame->BuildParameterDialog(NULL);
+
+    if (!wxStrlen(params.ODBCSource))
+    {
+        wxDELETE(DbConnectInf);
+        return(false);
+    }
+
+    DbConnectInf->SetDsn(params.ODBCSource);
+    DbConnectInf->SetUserID(params.UserName);
+    DbConnectInf->SetPassword(params.Password);
+    DbConnectInf->SetDefaultDir(params.DirPath);
+
+    READONLY_DB = wxDbGetConnection(DbConnectInf);
+    if (READONLY_DB == 0)
+    {
+        wxMessageBox(wxT("Unable to connect to the data source.\n\nCheck the name of your data source to verify it has been correctly entered/spelled.\n\nWith some databases, the user name and password must\nbe created with full rights to the CONTACT table prior to making a connection\n(using tools provided by the database manufacturer)"), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
+        DemoFrame->BuildParameterDialog(NULL);
+        wxDELETE(DbConnectInf);
+        wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
+        return(false);
+    }
+
+    DemoFrame->BuildEditorDialog();
+
+    // Show the frame
+    DemoFrame->Refresh();
+
+    return true;
+}  // DatabaseDemoApp::OnInit()
+
+
+/*
+* Remove CR or CR/LF from a character string.
+*/
+wxChar* wxRemoveLineTerminator(wxChar* aString)
+{
+    int len = wxStrlen(aString);
+    while (len > 0 && (aString[len-1] == wxT('\r') || aString[len-1] == wxT('\n'))) {
+        aString[len-1] = wxT('\0');
+        len--;
+    }
+    return aString;
+}
+
+
+bool DatabaseDemoApp::ReadParamFile(Cparameters &params)
+{
     FILE *paramFile;
     FILE *paramFile;
-    if ((paramFile = fopen(paramFilename, "r")) == NULL)
+    if ((paramFile = wxFopen(PARAM_FILENAME, wxT("r"))) == NULL)
     {
         wxString tStr;
     {
         wxString tStr;
-        tStr.Printf("Unable to open the parameter file '%s' for reading.\n\nYou must specify the data source, user name, and\npassword that will be used and save those settings.",paramFilename);
-        wxMessageBox(tStr,"File I/O Error...",wxOK | wxICON_EXCLAMATION);
+        tStr.Printf(wxT("Unable to open the parameter file '%s' for reading.\n\nYou must specify the data source, user name, and\npassword that will be used and save those settings."),PARAM_FILENAME.c_str());
+        wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
 
 
-        DemoFrame->BuildParameterDialog(NULL);
-        if ((paramFile = fopen(paramFilename, "r")) == NULL)
-            return FALSE;
+        return false;
     }
 
     }
 
-    char buffer[1000+1];
-    fgets(buffer, sizeof(params.ODBCSource), paramFile);
-    buffer[strlen(buffer)-1] = '\0';
-    strcpy(params.ODBCSource,buffer);
+    wxChar buffer[1000+1];
+    wxFgets(buffer, sizeof(params.ODBCSource), paramFile);
+    wxRemoveLineTerminator(buffer);
+    wxStrcpy(params.ODBCSource,buffer);
 
 
-    fgets(buffer, sizeof(params.UserName), paramFile);
-    buffer[strlen(buffer)-1] = '\0';
-    strcpy(params.UserName,buffer);
+    wxFgets(buffer, sizeof(params.UserName), paramFile);
+    wxRemoveLineTerminator(buffer);
+    wxStrcpy(params.UserName,buffer);
 
 
-    fgets(buffer, sizeof(params.Password), paramFile);
-    buffer[strlen(buffer)-1] = '\0';
-    strcpy(params.Password,buffer);
+    wxFgets(buffer, sizeof(params.Password), paramFile);
+    wxRemoveLineTerminator(buffer);
+    wxStrcpy(params.Password,buffer);
 
 
-    fgets(buffer, sizeof(params.DirPath), paramFile);
-    buffer[strlen(buffer)-1] = '\0';
-    strcpy(params.DirPath,buffer);
+    wxFgets(buffer, sizeof(params.DirPath), paramFile);
+    wxRemoveLineTerminator(buffer);
+    wxStrcpy(params.DirPath,buffer);
 
     fclose(paramFile);
 
 
     fclose(paramFile);
 
-    // Connect to datasource
-    strcpy(DbConnectInf.Dsn,        params.ODBCSource);    // ODBC data source name (created with ODBC Administrator under Win95/NT)
-    strcpy(DbConnectInf.Uid,        params.UserName);      // database username - must already exist in the data source
-    strcpy(DbConnectInf.AuthStr,    params.Password);      // password database username
-    strcpy(DbConnectInf.defaultDir, params.DirPath);       // path where the table exists (needed for dBase)
+    return true;
+}  // DatabaseDemoApp::ReadParamFile()
 
 
-    READONLY_DB = wxDbGetConnection(&DbConnectInf);
-    if (READONLY_DB == 0)
+
+bool DatabaseDemoApp::WriteParamFile(Cparameters &WXUNUSED(params))
+{
+    FILE *paramFile;
+    if ((paramFile = wxFopen(PARAM_FILENAME, wxT("wt"))) == NULL)
     {
     {
-        wxMessageBox("Unable to connect to the data source.\n\nCheck the name of your data source to verify it has been correctly entered/spelled.\n\nWith some databases, the user name and password must\nbe created with full rights to the CONTACT table prior to making a connection\n(using tools provided by the database manufacturer)", "DB CONNECTION ERROR...",wxOK | wxICON_EXCLAMATION);
-        DemoFrame->BuildParameterDialog(NULL);
-        strcpy(DbConnectInf.Dsn,        "");
-        strcpy(DbConnectInf.Uid,        "");
-        strcpy(DbConnectInf.AuthStr,    "");
-        wxMessageBox("Now exiting program.\n\nRestart program to try any new settings.","Notice...",wxOK | wxICON_INFORMATION);
-        return(FALSE);
+        wxString tStr;
+        tStr.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME.c_str());
+        wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
+        return false;
     }
 
     }
 
-    DemoFrame->BuildEditorDialog();
+    wxFputs(wxGetApp().params.ODBCSource, paramFile);
+    wxFputc(wxT('\n'), paramFile);
+    wxFputs(wxGetApp().params.UserName, paramFile);
+    wxFputc(wxT('\n'), paramFile);
+    wxFputs(wxGetApp().params.Password, paramFile);
+    wxFputc(wxT('\n'), paramFile);
+    wxFputs(wxGetApp().params.DirPath, paramFile);
+    wxFputc(wxT('\n'), paramFile);
+    fclose(paramFile);
 
 
-    // Show the frame
-    DemoFrame->Show(TRUE);
+    return true;
+}  // DatabaseDemoApp::WriteParamFile()
+
+
+void DatabaseDemoApp::CreateDataTable(bool recreate)
+{
+    bool Ok = true;
+    if (recreate)
+       Ok = (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
+
+    if (!Ok)
+        return;
+
+    wxBeginBusyCursor();
+
+    bool success = true;
+
+    Contact->GetDb()->RollbackTrans();  // Make sure the current cursor is in a known/stable state
+
+    if (!Contact->CreateTable(recreate))
+    {
+        wxEndBusyCursor();
+        wxString tStr;
+        tStr = wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
+        wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__TFILE__,__LINE__),
+                     wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+
+        success = false;
+    }
+    else
+    {
+        if (!Contact->CreateIndexes(recreate))
+        {
+            wxEndBusyCursor();
+            wxString tStr;
+            tStr = wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+
+            success = false;
+        }
+    }
+    while (wxIsBusy())
+        wxEndBusyCursor();
+
+    if (success)
+        wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
+}  // DatabaseDemoApp::CreateDataTable()
 
 
-    return TRUE;
-}  // DatabaseDemoApp::OnInit()
 
 BEGIN_EVENT_TABLE(DatabaseDemoFrame, wxFrame)
 
 BEGIN_EVENT_TABLE(DatabaseDemoFrame, wxFrame)
-    EVT_MENU(FILE_CREATE, DatabaseDemoFrame::OnCreate)
+    EVT_MENU(FILE_CREATE_ID, DatabaseDemoFrame::OnCreate)
+    EVT_MENU(FILE_RECREATE_TABLE, DatabaseDemoFrame::OnRecreateTable)
+    EVT_MENU(FILE_RECREATE_INDEXES, DatabaseDemoFrame::OnRecreateIndexes)
+#if wxUSE_GRID
+    EVT_MENU(FILE_DBGRID_TABLE, DatabaseDemoFrame::OnDbGridTable)
+#endif
     EVT_MENU(FILE_EXIT, DatabaseDemoFrame::OnExit)
     EVT_MENU(EDIT_PARAMETERS, DatabaseDemoFrame::OnEditParameters)
     EVT_MENU(FILE_EXIT, DatabaseDemoFrame::OnExit)
     EVT_MENU(EDIT_PARAMETERS, DatabaseDemoFrame::OnEditParameters)
-    EVT_MENU(ABOUT_DEMO, DatabaseDemoFrame::OnAbout)
+    EVT_MENU(HELP_ABOUT, DatabaseDemoFrame::OnAbout)
     EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow)
 END_EVENT_TABLE()
 
     EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow)
 END_EVENT_TABLE()
 
+
 // DatabaseDemoFrame constructor
 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame *frame, const wxString& title,
 // DatabaseDemoFrame constructor
 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame *frame, const wxString& title,
-  const wxPoint& pos, const wxSize& size):
-  wxFrame(frame, -1, title, pos, size)
+                                     const wxPoint& pos, const wxSize& size):
+                                        wxFrame(frame, wxID_ANY, title, pos, size)
 {
 {
-// Put any code in necessary for initializing the main frame here
-}
+    // Put any code in necessary for initializing the main frame here
+    pEditorDlg = NULL;
+    pParamDlg  = NULL;
 
 
-void DatabaseDemoFrame::OnCreate(wxCommandEvent& event)
-{
-    CreateDataTable();
-}
+#if wxUSE_LOG
+    delete wxLog::SetActiveTarget(new wxLogStderr);
+#endif // wxUSE_LOG
+
+}  // DatabaseDemoFrame constructor
 
 
-void DatabaseDemoFrame::OnExit(wxCommandEvent& event)
+DatabaseDemoFrame::~DatabaseDemoFrame()
 {
 {
-    Close();
-}
+#if wxUSE_LOG
+    delete wxLog::SetActiveTarget(NULL);
+#endif // wxUSE_LOG
+}  // DatabaseDemoFrame destructor
 
 
-void DatabaseDemoFrame::OnEditParameters(wxCommandEvent& event)
+
+void DatabaseDemoFrame::OnCreate(wxCommandEvent& WXUNUSED(event))
 {
 {
-    if ((pEditorDlg->mode != mCreate) && (pEditorDlg->mode != mEdit))
-        BuildParameterDialog(this);
-    else
-        wxMessageBox("Cannot change database parameters while creating or editing a record","Notice...",wxOK | wxICON_INFORMATION);
-}
+    wxGetApp().CreateDataTable(false);
+}  // DatabaseDemoFrame::OnCreate()
+
 
 
-void DatabaseDemoFrame::OnAbout(wxCommandEvent& event)
+void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent& WXUNUSED(event))
 {
 {
-    wxMessageBox("wxWindows sample program for database classes\n\nContributed on 27 July 1998","About...",wxOK | wxICON_INFORMATION);
-}
+    wxGetApp().CreateDataTable(true);
+}  // DatabaseDemoFrame::OnRecreate()
 
 
-void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
+
+void DatabaseDemoFrame::OnRecreateIndexes(wxCommandEvent& WXUNUSED(event))
 {
 {
-    // Put any additional checking necessary to make certain it is alright
-    // to close the program here that is not done elsewhere
+    wxGetApp().Contact->GetDb()->RollbackTrans();  // Make sure the current cursor is in a known/stable state
 
 
-    // Clean up time
-    if (pEditorDlg->Close())
-        pEditorDlg = NULL;
-    else
-        event.Veto();
+    if (!wxGetApp().Contact->CreateIndexes(true))
+    {
+        while (wxIsBusy())
+            wxEndBusyCursor();
+        wxString tStr;
+        tStr = wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
+        wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                     wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
 
 
-    this->Destroy();
+    }
+     else
+        wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
 
 
-}  // DatabaseDemoFrame::OnCloseWindow()
+}  // DatabaseDemoFrame::OnRecreateIndexes()
 
 
 
 
-void DatabaseDemoFrame::CreateDataTable()
+#if wxUSE_GRID
+void DatabaseDemoFrame::OnDbGridTable(wxCommandEvent& WXUNUSED(event))
+{
+    DbGridFrame *frame = new DbGridFrame(this);
+    if (frame->Initialize())
+    {
+        frame->Show();
+    }
+}
+#endif
+
+void DatabaseDemoFrame::OnExit(wxCommandEvent& WXUNUSED(event))
 {
 {
-    bool Ok = (wxMessageBox("Any data currently residing in the table will be erased.\n\nAre you sure?","Confirm",wxYES_NO|wxICON_QUESTION) == wxYES);
+    Close();
+}  // DatabaseDemoFrame::OnExit()
 
 
-    if (!Ok)
-        return;
 
 
-    wxBeginBusyCursor();
+void DatabaseDemoFrame::OnEditParameters(wxCommandEvent& WXUNUSED(event))
+{
+    if ((pEditorDlg->mode != mCreate) && (pEditorDlg->mode != mEdit))
+        BuildParameterDialog(this);
+    else
+        wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
+}  // DatabaseDemoFrame::OnEditParameters()
 
 
-    bool success = TRUE;
 
 
-    Ccontact *Contact = new Ccontact();
-    if (!Contact)
-    {
-        wxEndBusyCursor();
-        wxMessageBox("Error allocating memory for 'Ccontact'object.\n\nTable was not created.","Error...",wxOK | wxICON_EXCLAMATION);
-        return;
-    }
+void DatabaseDemoFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+    wxMessageBox(wxT("wxWidgets sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK | wxICON_INFORMATION);
+}  // DatabaseDemoFrame::OnAbout()
 
 
-    if (!Contact->CreateTable(FALSE))
-    {
-        wxEndBusyCursor();
-        wxString tStr;
-        tStr  = "Error creating CONTACTS table.\nTable was not created.\n\n";
-        tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-        wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
-        success = FALSE;
-    }
-     else
+
+// Put any additional checking necessary to make certain it is alright
+// to close the program here that is not done elsewhere
+void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
+{
+    // Clean up time
+    if (pEditorDlg && pEditorDlg->Close())
+        pEditorDlg = NULL;
+    else
     {
     {
-        if (!Contact->CreateIndexes())
+        if (pEditorDlg)
         {
         {
-            wxEndBusyCursor();
-            wxString tStr;
-            tStr  = "Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n";
-            tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-            wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
-            success = FALSE;
+            event.Veto();
+            return;
         }
     }
         }
     }
-    while (wxIsBusy())
-        wxEndBusyCursor();
 
 
-    delete Contact;
+    wxDELETE(wxGetApp().Contact);
 
 
-    if (success)
-        wxMessageBox("Table and index(es) were successfully created.","Notice...",wxOK | wxICON_INFORMATION);
-}  // DatabaseDemoFrame::CreateDataTable()
+    // This function will close all the connections to the database that have been
+    // previously cached.
+    wxDbCloseConnections();
+
+    // Deletion of the wxDbConnectInf instance must be the LAST thing done that
+    // has anything to do with the database.  Deleting this before disconnecting,
+    // freeing/closing connections, etc will result in a crash!
+    wxDELETE(wxGetApp().DbConnectInf);
+
+    this->Destroy();
+
+}  // DatabaseDemoFrame::OnCloseWindow()
 
 
 void DatabaseDemoFrame::BuildEditorDialog()
 {
 
 
 void DatabaseDemoFrame::BuildEditorDialog()
 {
+    pEditorDlg = NULL;
     pEditorDlg = new CeditorDlg(this);
     pEditorDlg = new CeditorDlg(this);
-    if (!pEditorDlg)
-        wxMessageBox("Unable to create the editor dialog for some reason","Error...",wxOK | wxICON_EXCLAMATION);
+    if (pEditorDlg)
+    {
+        pEditorDlg->Initialize();
+        if (!pEditorDlg->initialized)
+        {
+            pEditorDlg->Close();
+            pEditorDlg = NULL;
+            wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
+            Close();
+        }
+    }
+    else
+    {
+        wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
+        Close();
+    }
 }  // DatabaseDemoFrame::BuildEditorDialog()
 
 
 }  // DatabaseDemoFrame::BuildEditorDialog()
 
 
@@ -348,30 +1010,35 @@ void DatabaseDemoFrame::BuildParameterDialog(wxWindow *parent)
     pParamDlg = new CparameterDlg(parent);
 
     if (!pParamDlg)
     pParamDlg = new CparameterDlg(parent);
 
     if (!pParamDlg)
-        wxMessageBox("Unable to create the parameter dialog for some reason","Error...",wxOK | wxICON_EXCLAMATION);
+        wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
 }  // DatabaseDemoFrame::BuildParameterDialog()
 
 
 /*
 }  // DatabaseDemoFrame::BuildParameterDialog()
 
 
 /*
- * Constructor note: If no wxDB object is passed in, a new connection to the database
+ * Constructor note: If no wxDb object is passed in, a new connection to the database
  *     is created for this instance of Ccontact.  This can be a slow process depending
  *     on the database engine being used, and some database engines have a limit on the
  *     is created for this instance of Ccontact.  This can be a slow process depending
  *     on the database engine being used, and some database engines have a limit on the
- *     number of connections (either hard limits, or license restricted) so care should 
- *     be used to use as few connections as is necessary.  
+ *     number of connections (either hard limits, or license restricted) so care should
+ *     be used to use as few connections as is necessary.
  *
  *
- * IMPORTANT: Objects which share a wxDB pointer are ALL acted upon whenever a member 
- *     function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying 
+ * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
+ *     function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
  *     or creating a table objects which use the same pDb, know that all the objects
  *     will be committed or rolled back when any of the objects has this function call made.
  */
  *     or creating a table objects which use the same pDb, know that all the objects
  *     will be committed or rolled back when any of the objects has this function call made.
  */
-Ccontact::Ccontact (wxDB *pwxDB) : wxTable(pwxDB ? pwxDB : wxDbGetConnection(&DbConnectInf),CONTACT_TABLE_NAME,CONTACT_NO_COLS,NULL,!QUERY_ONLY,DbConnectInf.defaultDir)
+Ccontact::Ccontact (wxDb *pwxDb) : wxDbTable(pwxDb ? pwxDb : wxDbGetConnection(wxGetApp().DbConnectInf),
+                                             CONTACT_TABLE_NAME, CONTACT_NO_COLS, (const wxString &)wxEmptyString,
+                                             !wxDB_QUERY_ONLY, wxGetApp().DbConnectInf->GetDefaultDir())
 {
     // This is used to represent whether the database connection should be released
     // when this instance of the object is deleted.  If using the same connection
 {
     // This is used to represent whether the database connection should be released
     // when this instance of the object is deleted.  If using the same connection
-    // for multiple instance of database objects, then the connection should only be 
+    // for multiple instance of database objects, then the connection should only be
     // released when the last database instance using the connection is deleted
     // released when the last database instance using the connection is deleted
-    freeDbConn = !pwxDB;
-    
+    freeDbConn = !pwxDb;
+
+    if (GetDb())
+        GetDb()->SetSqlLogging(sqlLogON);
+
     SetupColumns();
 
 }  // Ccontact Constructor
     SetupColumns();
 
 }  // Ccontact Constructor
@@ -394,9 +1061,11 @@ void Ccontact::Initialize()
     JoinDate.second    = 0;
     JoinDate.fraction  = 0;
     NativeLanguage     = langENGLISH;
     JoinDate.second    = 0;
     JoinDate.fraction  = 0;
     NativeLanguage     = langENGLISH;
-    IsDeveloper        = FALSE;
+    IsDeveloper        = false;
     Contributions      = 0;
     LinesOfCode        = 0L;
     Contributions      = 0;
     LinesOfCode        = 0L;
+    BlobSize           = 0L;
+    memset(Picture, 0, MAX_PICTURE_SIZE);
 }  // Ccontact::Initialize
 
 
 }  // Ccontact::Initialize
 
 
@@ -404,61 +1073,64 @@ Ccontact::~Ccontact()
 {
     if (freeDbConn)
     {
 {
     if (freeDbConn)
     {
-        if (!wxDbFreeConnection(pDb))
+        if (!wxDbFreeConnection(GetDb()))
         {
             wxString tStr;
         {
             wxString tStr;
-            tStr  = "Unable to Free the Ccontact data table handle\n\n";
-            tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-            wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+            tStr = wxT("Unable to Free the Ccontact data table handle\n\n");
+
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
         }
     }
 }  // Ccontract destructor
 
 
 /*
         }
     }
 }  // Ccontract destructor
 
 
 /*
- * Handles setting up all the connections for the interface from the wxTable
- * functions to interface to the data structure used to store records in 
+ * Handles setting up all the connections for the interface from the wxDbTable
+ * functions to interface to the data structure used to store records in
  * memory, and for all the column definitions that define the table structure
  */
 void Ccontact::SetupColumns()
 {
     // NOTE: Columns now are 8 character names, as that is all dBase can support.  Longer
     //       names can be used for other database engines
  * memory, and for all the column definitions that define the table structure
  */
 void Ccontact::SetupColumns()
 {
     // NOTE: Columns now are 8 character names, as that is all dBase can support.  Longer
     //       names can be used for other database engines
-    SetColDefs ( 0,"NAME",       DB_DATA_TYPE_VARCHAR,     Name,           SQL_C_CHAR,                 sizeof(Name),           TRUE, TRUE);  // Primary index
-    SetColDefs ( 1,"ADDRESS1",   DB_DATA_TYPE_VARCHAR,     Addr1,          SQL_C_CHAR,                 sizeof(Addr1),          FALSE,TRUE);
-    SetColDefs ( 2,"ADDRESS2",   DB_DATA_TYPE_VARCHAR,     Addr2,          SQL_C_CHAR,                 sizeof(Addr2),          FALSE,TRUE);
-    SetColDefs ( 3,"CITY",       DB_DATA_TYPE_VARCHAR,     City,           SQL_C_CHAR,                 sizeof(City),           FALSE,TRUE);
-    SetColDefs ( 4,"STATE",      DB_DATA_TYPE_VARCHAR,     State,          SQL_C_CHAR,                 sizeof(State),          FALSE,TRUE);
-    SetColDefs ( 5,"POSTCODE",   DB_DATA_TYPE_VARCHAR,     PostalCode,     SQL_C_CHAR,                 sizeof(PostalCode),     FALSE,TRUE);
-    SetColDefs ( 6,"COUNTRY",    DB_DATA_TYPE_VARCHAR,     Country,        SQL_C_CHAR,                 sizeof(Country),        FALSE,TRUE);
-    SetColDefs ( 7,"JOINDATE",   DB_DATA_TYPE_DATE,       &JoinDate,       SQL_C_TIMESTAMP,            sizeof(JoinDate),       FALSE,TRUE);
-    SetColDefs ( 8,"IS_DEV",     DB_DATA_TYPE_INTEGER,    &IsDeveloper,    SQL_C_BOOLEAN(IsDeveloper), sizeof(IsDeveloper),    FALSE,TRUE);
-    SetColDefs ( 9,"CONTRIBS",   DB_DATA_TYPE_INTEGER,    &Contributions,  SQL_C_USHORT,               sizeof(Contributions),  FALSE,TRUE);
-    SetColDefs (10,"LINE_CNT",   DB_DATA_TYPE_INTEGER,    &LinesOfCode,    SQL_C_ULONG,                sizeof(LinesOfCode),    FALSE,TRUE);
-    SetColDefs (11,"LANGUAGE",   DB_DATA_TYPE_INTEGER,    &NativeLanguage, SQL_C_ENUM,                 sizeof(NativeLanguage), FALSE,TRUE);
+    SetColDefs ( 0,wxT("NAME"),       DB_DATA_TYPE_VARCHAR,     Name,           SQL_C_WXCHAR,               sizeof(Name),           true, true);  // Primary index
+    SetColDefs ( 1,wxT("ADDRESS1"),   DB_DATA_TYPE_VARCHAR,     Addr1,          SQL_C_WXCHAR,               sizeof(Addr1),          false,true);
+    SetColDefs ( 2,wxT("ADDRESS2"),   DB_DATA_TYPE_VARCHAR,     Addr2,          SQL_C_WXCHAR,               sizeof(Addr2),          false,true);
+    SetColDefs ( 3,wxT("CITY"),       DB_DATA_TYPE_VARCHAR,     City,           SQL_C_WXCHAR,               sizeof(City),           false,true);
+    SetColDefs ( 4,wxT("STATE"),      DB_DATA_TYPE_VARCHAR,     State,          SQL_C_WXCHAR,               sizeof(State),          false,true);
+    SetColDefs ( 5,wxT("POSTCODE"),   DB_DATA_TYPE_VARCHAR,     PostalCode,     SQL_C_WXCHAR,               sizeof(PostalCode),     false,true);
+    SetColDefs ( 6,wxT("COUNTRY"),    DB_DATA_TYPE_VARCHAR,     Country,        SQL_C_WXCHAR,               sizeof(Country),        false,true);
+    SetColDefs ( 7,wxT("JOINDATE"),   DB_DATA_TYPE_DATE,       &JoinDate,       SQL_C_TIMESTAMP,            sizeof(JoinDate),       false,true);
+    SetColDefs ( 8,wxT("IS_DEV"),     DB_DATA_TYPE_INTEGER,    &IsDeveloper,    SQL_C_BOOLEAN(IsDeveloper), sizeof(IsDeveloper),    false,true);
+    SetColDefs ( 9,wxT("CONTRIBS"),   DB_DATA_TYPE_INTEGER,    &Contributions,  SQL_C_UTINYINT,             sizeof(Contributions),  false,true);
+    SetColDefs (10,wxT("LINE_CNT"),   DB_DATA_TYPE_INTEGER,    &LinesOfCode,    SQL_C_ULONG,                sizeof(LinesOfCode),    false,true);
+    SetColDefs (11,wxT("LANGUAGE"),   DB_DATA_TYPE_INTEGER,    &NativeLanguage, SQL_C_ENUM,                 sizeof(NativeLanguage), false,true);
+#ifdef wxODBC_BLOB_SUPPORT
+    SetColDefs (12,wxT("PICSIZE"),    DB_DATA_TYPE_INTEGER,    &BlobSize,       SQL_C_ULONG,                sizeof(BlobSize),       false,true);
+    SetColDefs (13,wxT("PICTURE"),    DB_DATA_TYPE_BLOB,        Picture,        SQL_C_BINARY,               sizeof(Picture),        false,true);
+#endif
 }  // Ccontact::SetupColumns
 
 
 }  // Ccontact::SetupColumns
 
 
-bool Ccontact::CreateIndexes(void)
+bool Ccontact::CreateIndexes(bool recreate)
 {
 {
-    // This index could easily be accomplished with an "orderBy" clause, 
+    // This index could easily be accomplished with an "orderBy" clause,
     // but is done to show how to construct a non-primary index.
     wxString    indexName;
     // but is done to show how to construct a non-primary index.
     wxString    indexName;
-    CidxDef     idxDef[2];
+    wxDbIdxDef  idxDef[2];
 
 
-    bool        Ok = TRUE;
+    wxStrcpy(idxDef[0].ColName, wxT("IS_DEV"));
+    idxDef[0].Ascending = true;
 
 
-    strcpy(idxDef[0].ColName, "IS_DEV");
-    idxDef[0].Ascending = TRUE;
+    wxStrcpy(idxDef[1].ColName, wxT("NAME"));
+    idxDef[1].Ascending = true;
 
 
-    strcpy(idxDef[1].ColName, "NAME");
-    idxDef[1].Ascending = TRUE;
+    indexName = GetTableName();
+    indexName += wxT("_IDX1");
 
 
-    indexName = CONTACT_TABLE_NAME;
-    indexName += "_IDX1";
-    Ok = CreateIndex((char*) (const char*) indexName, TRUE, 2, idxDef);
+    return CreateIndex(indexName.c_str(), true, 2, idxDef, recreate);
 
 
-    return Ok;
 }  // Ccontact::CreateIndexes()
 
 
 }  // Ccontact::CreateIndexes()
 
 
@@ -467,14 +1139,14 @@ bool Ccontact::CreateIndexes(void)
  * very efficient and tighter coding so that it is available where ever the object
  * is.  Great for use with multiple tables when not using views or outer joins
  */
  * very efficient and tighter coding so that it is available where ever the object
  * is.  Great for use with multiple tables when not using views or outer joins
  */
-bool Ccontact::FetchByName(char *name)
+bool Ccontact::FetchByName(const wxString &name)
 {
 {
-    whereStr.Printf("NAME = '%s'",name);
-    where = (char*) (const char*) this->whereStr;
-    orderBy = 0;
+    whereStr.Printf(wxT("NAME = '%s'"),name.c_str());
+    SetWhereClause(whereStr.c_str());
+    SetOrderByClause(wxEmptyString);
 
     if (!Query())
 
     if (!Query())
-        return(FALSE);
+        return(false);
 
     // Fetch the record
     return(GetNext());
 
     // Fetch the record
     return(GetNext());
@@ -497,174 +1169,24 @@ bool Ccontact::FetchByName(char *name)
  * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
  * object that is currently being worked with.
  */
  * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
  * object that is currently being worked with.
  */
+
 BEGIN_EVENT_TABLE(CeditorDlg, wxPanel)
 BEGIN_EVENT_TABLE(CeditorDlg, wxPanel)
-    EVT_BUTTON(-1,  CeditorDlg::OnButton)
+    EVT_BUTTON(wxID_ANY,  CeditorDlg::OnButton)
     EVT_CLOSE(CeditorDlg::OnCloseWindow)
 END_EVENT_TABLE()
     EVT_CLOSE(CeditorDlg::OnCloseWindow)
 END_EVENT_TABLE()
-CeditorDlg::CeditorDlg(wxWindow *parent) : wxPanel (parent, 1, 1, 460, 455)
+
+CeditorDlg::CeditorDlg(wxWindow *parent) : wxPanel (parent, 0, 0, 537, 530)
 {
     // Since the ::OnCommand() function is overridden, this prevents the widget
     // detection in ::OnCommand() until all widgets have been initialized to prevent
     // uninitialized pointers from crashing the program
 {
     // Since the ::OnCommand() function is overridden, this prevents the widget
     // detection in ::OnCommand() until all widgets have been initialized to prevent
     // uninitialized pointers from crashing the program
-    widgetPtrsSet = FALSE;
-
-    // Create the data structure and a new database connection.  
-    // (As there is not a pDb being passed in the constructor, a new database
-    // connection is created)
-    Contact = new Ccontact();
-
-    if (!Contact)
-    {
-        wxMessageBox("Unable to instantiate an instance of Ccontact","Error...",wxOK | wxICON_EXCLAMATION);
-        return;
-    }
-
-    // Check if the table exists or not.  If it doesn't, ask the user if they want to 
-    // create the table.  Continue trying to create the table until it exists, or user aborts
-    while (!Contact->pDb->TableExists((char *)CONTACT_TABLE_NAME,DbConnectInf.Uid,DbConnectInf.defaultDir))
-    {
-        wxString tStr;
-        tStr.Printf("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n",CONTACT_TABLE_NAME);
-        tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-        wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
-
-        bool createTable = (wxMessageBox("Do you wish to try to create/clear the CONTACTS table?","Confirm",wxYES_NO|wxICON_QUESTION) == wxYES);
-
-        if (!createTable)
-        {
-            delete Contact;
-            Close();
-            DemoFrame->Close();
-            return;
-        }
-        else
-            DemoFrame->CreateDataTable();
-    }
-
-    // Tables must be "opened" before anything other than creating/deleting table can be done
-    if (!Contact->Open())
-    {
-        // Table does exist, there was some problem opening it.  Currently this should
-        // never fail, except in the case of the table not exisiting.  Open() basically
-        // only sets up variable/pointer values, other than checking for table existence.
-        if (Contact->pDb->TableExists((char *)CONTACT_TABLE_NAME))
-        {
-            wxString tStr;
-            tStr.Printf("Unable to open the table '%s'.\n\n",CONTACT_TABLE_NAME);
-            tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-            wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
-            delete Contact;
-            Close();
-            DemoFrame->Close();
-            return;
-        }
-    }
-
-    // Build the dialog
-
-    (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP, "",  wxPoint(15, 1), wxSize(497,  69), 0, "FunctionGrp");
-    (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP, "", wxPoint(417, 1), wxSize(95, 242), 0, "SearchGrp");
-
-    pCreateBtn      = new wxButton(this, EDITOR_DIALOG_CREATE,           "&Create",     wxPoint( 25,  21), wxSize( 70,  35), 0, wxDefaultValidator, "CreateBtn");
-    pEditBtn        = new wxButton(this, EDITOR_DIALOG_EDIT,             "&Edit",       wxPoint(102,  21), wxSize( 70,  35), 0, wxDefaultValidator, "EditBtn");
-    pDeleteBtn      = new wxButton(this, EDITOR_DIALOG_DELETE,           "&Delete",     wxPoint(179,  21), wxSize( 70,  35), 0, wxDefaultValidator, "DeleteBtn");
-    pCopyBtn        = new wxButton(this, EDITOR_DIALOG_COPY,             "Cop&y",       wxPoint(256,  21), wxSize( 70,  35), 0, wxDefaultValidator, "CopyBtn");
-    pSaveBtn        = new wxButton(this, EDITOR_DIALOG_SAVE,             "&Save",       wxPoint(333,  21), wxSize( 70,  35), 0, wxDefaultValidator, "SaveBtn");
-    pCancelBtn      = new wxButton(this, EDITOR_DIALOG_CANCEL,           "C&ancel",     wxPoint(430,  21), wxSize( 70,  35), 0, wxDefaultValidator, "CancelBtn");
-    pPrevBtn        = new wxButton(this, EDITOR_DIALOG_PREV,             "<< &Prev",    wxPoint(430,  81), wxSize( 70,  35), 0, wxDefaultValidator, "PrevBtn");
-    pNextBtn        = new wxButton(this, EDITOR_DIALOG_NEXT,             "&Next >>",    wxPoint(430, 121), wxSize( 70,  35), 0, wxDefaultValidator, "NextBtn");
-    pQueryBtn       = new wxButton(this, EDITOR_DIALOG_QUERY,            "&Query",      wxPoint(430, 161), wxSize( 70,  35), 0, wxDefaultValidator, "QueryBtn");
-    pResetBtn       = new wxButton(this, EDITOR_DIALOG_RESET,            "&Reset",      wxPoint(430, 200), wxSize( 70,  35), 0, wxDefaultValidator, "ResetBtn");
-    pNameMsg        = new wxStaticText(this, EDITOR_DIALOG_NAME_MSG,     "Name:",       wxPoint( 17,  80), wxSize( -1,  -1), 0, "NameMsg");
-    pNameTxt        = new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT,      "",            wxPoint( 17,  97), wxSize(308,  25), 0, wxDefaultValidator, "NameTxt");
-    pNameListBtn    = new wxButton(this, EDITOR_DIALOG_LOOKUP,           "&Lookup",     wxPoint(333,  97), wxSize( 70,  24), 0, wxDefaultValidator, "LookupBtn");
-    pAddress1Msg    = new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG, "Address:",    wxPoint( 17, 130), wxSize( -1,  -1), 0, "Address1Msg");
-    pAddress1Txt    = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT,  "",            wxPoint( 17, 147), wxSize(308,  25), 0, wxDefaultValidator, "Address1Txt");
-    pAddress2Msg    = new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG, "Address:",    wxPoint( 17, 180), wxSize( -1,  -1), 0, "Address2Msg");
-    pAddress2Txt    = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT,  "",            wxPoint( 17, 197), wxSize(308,  25), 0, wxDefaultValidator, "Address2Txt");
-    pCityMsg        = new wxStaticText(this, EDITOR_DIALOG_CITY_MSG,     "City:",       wxPoint( 17, 230), wxSize( -1,  -1), 0, "CityMsg");
-    pCityTxt        = new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT,      "",            wxPoint( 17, 247), wxSize(225,  25), 0, wxDefaultValidator, "CityTxt");
-    pStateMsg       = new wxStaticText(this, EDITOR_DIALOG_STATE_MSG,    "State:",      wxPoint(250, 230), wxSize( -1,  -1), 0, "StateMsg");
-    pStateTxt       = new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT,     "",            wxPoint(250, 247), wxSize(153,  25), 0, wxDefaultValidator, "StateTxt");
-    pCountryMsg     = new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG,  "Country:",    wxPoint( 17, 280), wxSize( -1,  -1), 0, "CountryMsg");
-    pCountryTxt     = new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT,   "",            wxPoint( 17, 297), wxSize(225,  25), 0, wxDefaultValidator, "CountryTxt");
-    pPostalCodeMsg  = new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG,   "Postal Code:",wxPoint(250, 280), wxSize( -1,  -1), 0, "PostalCodeMsg");
-    pPostalCodeTxt  = new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT,    "",            wxPoint(250, 297), wxSize(153,  25), 0, wxDefaultValidator, "PostalCodeTxt");
-
-    wxString choice_strings[5];
-    choice_strings[0] = "English";
-    choice_strings[1] = "French";
-    choice_strings[2] = "German";
-    choice_strings[3] = "Spanish";
-    choice_strings[4] = "Other";
-
-    pNativeLangChoice = new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE,                        wxPoint( 17, 346), wxSize(277,  -1), 5, choice_strings);
-    pNativeLangMsg    = new wxStaticText(this, EDITOR_DIALOG_LANG_MSG,   "Native language:", wxPoint( 17, 330), wxSize( -1,  -1), 0, "NativeLangMsg");
-
-    wxString radio_strings[2];
-    radio_strings[0]  = "No";
-    radio_strings[1]  = "Yes";
-    pDeveloperRadio   = new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER,     "Developer:",       wxPoint(303, 330), wxSize( -1,  -1), 2, radio_strings, 2, wxHORIZONTAL);
-    pJoinDateMsg      = new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG,   "Date joined:",     wxPoint( 17, 380), wxSize( -1,  -1), 0, "JoinDateMsg");
-    pJoinDateTxt      = new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT,    "",                 wxPoint( 17, 397), wxSize(150,  25), 0, wxDefaultValidator, "JoinDateTxt");
-    pContribMsg       = new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG,"Contributions:",   wxPoint(175, 380), wxSize( -1,  -1), 0, "ContribMsg");
-    pContribTxt       = new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT, "",                 wxPoint(175, 397), wxSize(120,  25), 0, wxDefaultValidator, "ContribTxt");
-    pLinesMsg         = new wxStaticText(this, EDITOR_DIALOG_LINES_MSG,  "Lines of code:",   wxPoint(303, 380), wxSize( -1,  -1), 0, "LinesMsg");
-    pLinesTxt         = new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT,   "",                 wxPoint(303, 397), wxSize(100,  25), 0, wxDefaultValidator, "LinesTxt");
-
-    // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to 
-    // handle all widget processing
-    widgetPtrsSet = TRUE;
-
-    // Setup the orderBy and where clauses to return back a single record as the result set, 
-    // as there will only be one record being shown on the dialog at a time, this optimizes
-    // network traffic by only returning a one row result
-    
-    Contact->orderBy = "NAME";  // field name to sort by
-
-    // The wxString "whereStr" is not a member of the wxTable object, it is a member variable
-    // specifically in the Ccontact class.  It is used here for simpler construction of a varying
-    // length string, and then after the string is built, the wxTable member variable "where" is
-    // assigned the pointer to the constructed string.
-    //
-    // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s" 
-    // to achieve a single row (in this case the first name in alphabetical order).
-    
-    if (Contact->pDb->Dbms() != dbmsPOSTGRES)
-    {
-        Contact->whereStr.sprintf("NAME = (SELECT MIN(NAME) FROM %s)",Contact->tableName);
-        // NOTE: (const char*) returns a pointer which may not be valid later, so this is short term use only
-        Contact->where = (char*) (const char*) Contact->whereStr;
-    }
-    else
-        Contact->where = 0;
-
-    // Perform the Query to get the result set.  
-    // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.  
-    //       Only if there is a database error will Query() come back as FALSE
-    if (!Contact->Query())
-    {
-        wxString tStr;
-        tStr  = "ODBC error during Query()\n\n";
-        tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-        wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
-        GetParent()->Close();
-        return;
-    }
+    widgetPtrsSet = false;
 
 
-    // Since Query succeeded, now get the row that was returned
-    if (!Contact->GetNext())
-        // If the GetNext() failed at this point, then there are no rows to retrieve, 
-        // so clear the values in the members of "Contact" so that PutData() blanks the 
-        // widgets on the dialog
-        Contact->Initialize();
+    initialized = false;
 
     SetMode(mView);
 
     SetMode(mView);
-    PutData();
 
 
-    Show(TRUE);
+    Show(false);
 }  // CeditorDlg constructor
 
 
 }  // CeditorDlg constructor
 
 
@@ -673,29 +1195,27 @@ void CeditorDlg::OnCloseWindow(wxCloseEvent& event)
     // Clean up time
     if ((mode != mCreate) && (mode != mEdit))
     {
     // Clean up time
     if ((mode != mCreate) && (mode != mEdit))
     {
-        if (Contact)
-            delete Contact;
         this->Destroy();
     }
     else
     {
         this->Destroy();
     }
     else
     {
-        wxMessageBox("Must finish processing the current record being created/modified before exiting","Notice...",wxOK | wxICON_INFORMATION);
+        wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
         event.Veto();
     }
 }  // CeditorDlg::OnCloseWindow()
 
 
         event.Veto();
     }
 }  // CeditorDlg::OnCloseWindow()
 
 
-void CeditorDlg::OnButton( wxCommandEvent &event )
+void CeditorDlg::OnButton(wxCommandEvent &event)
 {
 {
-  wxWindow *win = (wxWindow*) event.GetEventObject();
-  OnCommand( *win, event );
-}
+    wxWindow *win = (wxWindow*) event.GetEventObject();
+    OnCommand( *win, event );
+}  // CeditorDlg::OnButton()
 
 
 
 
-void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
+void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& WXUNUSED(event))
 {
     wxString widgetName;
 {
     wxString widgetName;
-    
+
     widgetName = win.GetName();
 
     if (!widgetPtrsSet)
     widgetName = win.GetName();
 
     if (!widgetPtrsSet)
@@ -703,17 +1223,17 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
 
     if (widgetName == pCreateBtn->GetName())
     {
 
     if (widgetName == pCreateBtn->GetName())
     {
-        Contact->Initialize();
+        wxGetApp().Contact->Initialize();
         PutData();
         SetMode( mCreate );
         PutData();
         SetMode( mCreate );
-        pNameTxt->SetValue("");
+        pNameTxt->SetValue(wxEmptyString);
         pNameTxt->SetFocus();
         return;
     }
 
     if (widgetName == pEditBtn->GetName())
     {
         pNameTxt->SetFocus();
         return;
     }
 
     if (widgetName == pEditBtn->GetName())
     {
-        saveName = Contact->Name;
+        saveName = wxGetApp().Contact->Name;
         SetMode( mEdit );
         pNameTxt->SetFocus();
         return;
         SetMode( mEdit );
         pNameTxt->SetFocus();
         return;
@@ -722,28 +1242,27 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
     if (widgetName == pCopyBtn->GetName())
     {
         SetMode(mCreate);
     if (widgetName == pCopyBtn->GetName())
     {
         SetMode(mCreate);
-        pNameTxt->SetValue("");
+        pNameTxt->SetValue(wxEmptyString);
         pNameTxt->SetFocus();
         pNameTxt->SetFocus();
-
         return;
     }
 
     if (widgetName == pDeleteBtn->GetName())
     {
         return;
     }
 
     if (widgetName == pDeleteBtn->GetName())
     {
-        bool Ok = (wxMessageBox("Are you sure?","Confirm",wxYES_NO|wxICON_QUESTION) == wxYES);
+        bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
 
         if (!Ok)
             return;
 
 
         if (!Ok)
             return;
 
-        if (Ok && Contact->Delete())
+        if (Ok && wxGetApp().Contact->Delete())
         {
         {
-            // NOTE: Deletions are not finalized until a CommitTrans() is performed.  
-            //       If the commit were not performed, the program will continue to 
+            // NOTE: Deletions are not finalized until a CommitTrans() is performed.
+            //       If the commit were not performed, the program will continue to
             //       show the table contents as if they were deleted until this instance
             //       show the table contents as if they were deleted until this instance
-            //       of Ccontact is deleted.  If the Commit wasn't performed, the 
+            //       of Ccontact is deleted.  If the Commit wasn't performed, the
             //       database will automatically Rollback the changes when the database
             //       connection is terminated
             //       database will automatically Rollback the changes when the database
             //       connection is terminated
-            Contact->pDb->CommitTrans();
+            wxGetApp().Contact->GetDb()->CommitTrans();
 
             // Try to get the row that followed the just deleted row in the orderBy sequence
             if (!GetNextRec())
 
             // Try to get the row that followed the just deleted row in the orderBy sequence
             if (!GetNextRec())
@@ -753,7 +1272,7 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
                 if (!GetPrevRec())
                 {
                     // There are now no rows remaining, so clear the dialog widgets
                 if (!GetPrevRec())
                 {
                     // There are now no rows remaining, so clear the dialog widgets
-                    Contact->Initialize();
+                    wxGetApp().Contact->Initialize();
                     PutData();
                 }
             }
                     PutData();
                 }
             }
@@ -761,7 +1280,7 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
         }
         else
             // Delete failed
         }
         else
             // Delete failed
-            Contact->pDb->RollbackTrans();
+            wxGetApp().Contact->GetDb()->RollbackTrans();
 
         SetMode(mView);
         return;
 
         SetMode(mView);
         return;
@@ -775,14 +1294,14 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
 
     if (widgetName == pCancelBtn->GetName())
     {
 
     if (widgetName == pCancelBtn->GetName())
     {
-        bool Ok = (wxMessageBox("Are you sure?","Confirm",wxYES_NO|wxICON_QUESTION) == wxYES);
+        bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
 
         if (!Ok)
             return;
 
 
         if (!Ok)
             return;
 
-        if (!strcmp((const char*) saveName,""))
+        if (saveName.empty())
         {
         {
-            Contact->Initialize();
+            wxGetApp().Contact->Initialize();
             PutData();
             SetMode(mView);
             return;
             PutData();
             SetMode(mView);
             return;
@@ -790,7 +1309,7 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
         else
         {
             // Requery previous record
         else
         {
             // Requery previous record
-            if (Contact->FetchByName((char*) (const char*) saveName))
+            if (wxGetApp().Contact->FetchByName(saveName))
             {
                 PutData();
                 SetMode(mView);
             {
                 PutData();
                 SetMode(mView);
@@ -799,33 +1318,35 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
         }
 
         // Previous record not available, retrieve first record in table
         }
 
         // Previous record not available, retrieve first record in table
-        if (Contact->pDb->Dbms() != dbmsPOSTGRES)
+        if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
+            wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
         {
         {
-            Contact->whereStr  = "NAME = (SELECT MIN(NAME) FROM ";
-            Contact->whereStr += Contact->tableName;
-            Contact->whereStr += ")";
-            Contact->where = (char*) (const char*) Contact->whereStr;
+            wxGetApp().Contact->whereStr  = wxT("NAME = (SELECT MIN(NAME) FROM ");
+            wxGetApp().Contact->whereStr += wxGetApp().Contact->GetTableName();
+            wxGetApp().Contact->whereStr += wxT(")");
+            wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
         }
         else
         }
         else
-            Contact->where = 0;
+            wxGetApp().Contact->SetWhereClause(wxEmptyString);
 
 
-        if (!Contact->Query())
+        if (!wxGetApp().Contact->Query())
         {
             wxString tStr;
         {
             wxString tStr;
-            tStr  = "ODBC error during Query()\n\n";
-            tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-            wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+            tStr = wxT("ODBC error during Query()\n\n");
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+
             SetMode(mView);
             return;
         }
             SetMode(mView);
             return;
         }
-        if (Contact->GetNext())  // Successfully read first record
+        if (wxGetApp().Contact->GetNext())  // Successfully read first record
         {
             PutData();
             SetMode(mView);
             return;
         }
         // No contacts are available, clear dialog
         {
             PutData();
             SetMode(mView);
             return;
         }
         // No contacts are available, clear dialog
-        Contact->Initialize();
+        wxGetApp().Contact->Initialize();
         PutData();
         SetMode(mView);
         return;
         PutData();
         SetMode(mView);
         return;
@@ -848,52 +1369,53 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
     if (widgetName == pQueryBtn->GetName())
     {
         // Display the query dialog box
     if (widgetName == pQueryBtn->GetName())
     {
         // Display the query dialog box
-        char qryWhere[DB_MAX_WHERE_CLAUSE_LEN+1];
-        strcpy(qryWhere, (const char*) Contact->qryWhereStr);
-        char *tblName[] = {(char *)CONTACT_TABLE_NAME, 0};
-        new CqueryDlg(GetParent(), Contact->pDb, tblName, qryWhere);
+        wxChar qryWhere[DB_MAX_WHERE_CLAUSE_LEN+1];
+        wxStrcpy(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr);
+        wxChar *tblName[] = {(wxChar *)CONTACT_TABLE_NAME.c_str(), 0};
+        new CqueryDlg(GetParent(), wxGetApp().Contact->GetDb(), tblName, qryWhere);
 
         // Query the first record in the new record set and
         // display it, if the query string has changed.
 
         // Query the first record in the new record set and
         // display it, if the query string has changed.
-        if (strcmp(qryWhere, (const char*) Contact->qryWhereStr))
+        if (wxStrcmp(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr))
         {
         {
-            Contact->whereStr = "";
-            Contact->orderBy  = "NAME";
+            wxGetApp().Contact->whereStr.Empty();
+            wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
 
 
-            if (Contact->pDb->Dbms() != dbmsPOSTGRES)
+            if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
+                wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
             {
             {
-                Contact->whereStr  = "NAME = (SELECT MIN(NAME) FROM ";
-                Contact->whereStr += CONTACT_TABLE_NAME;
+                wxGetApp().Contact->whereStr  = wxT("NAME = (SELECT MIN(NAME) FROM ");
+                wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
             }
             }
-            
+
             // Append the query where string (if there is one)
             // Append the query where string (if there is one)
-            Contact->qryWhereStr  = qryWhere;
-            if (strlen(qryWhere))
+            wxGetApp().Contact->qryWhereStr  = qryWhere;
+            if (wxStrlen(qryWhere))
             {
             {
-                Contact->whereStr += " WHERE ";
-                Contact->whereStr += Contact->qryWhereStr;
+                wxGetApp().Contact->whereStr += wxT(" WHERE ");
+                wxGetApp().Contact->whereStr += wxGetApp().Contact->qryWhereStr;
             }
             // Close the expression with a right paren
             }
             // Close the expression with a right paren
-            Contact->whereStr += ")";
+            wxGetApp().Contact->whereStr += wxT(")");
             // Requery the table
             // Requery the table
-            Contact->where = (char*) (const char*) Contact->whereStr;
-            if (!Contact->Query())
+            wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
+            if (!wxGetApp().Contact->Query())
             {
                 wxString tStr;
             {
                 wxString tStr;
-                tStr  = "ODBC error during Query()\n\n";
-                tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-                wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+                tStr = wxT("ODBC error during Query()\n\n");
+                wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                             wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+
                 return;
             }
             // Display the first record from the query set
                 return;
             }
             // Display the first record from the query set
-            if (!Contact->GetNext())
-                Contact->Initialize();
+            if (!wxGetApp().Contact->GetNext())
+                wxGetApp().Contact->Initialize();
             PutData();
         }
 
         // Enable/Disable the reset button
             PutData();
         }
 
         // Enable/Disable the reset button
-        pResetBtn->Enable(!Contact->qryWhereStr.IsEmpty());
+        pResetBtn->Enable(!wxGetApp().Contact->qryWhereStr.empty());
 
         return;
     }  // Query button
 
         return;
     }  // Query button
@@ -902,61 +1424,345 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
     if (widgetName == pResetBtn->GetName())
     {
         // Clear the additional where criteria established by the query feature
     if (widgetName == pResetBtn->GetName())
     {
         // Clear the additional where criteria established by the query feature
-        Contact->qryWhereStr = "";
-        Contact->orderBy        = "NAME";
+        wxGetApp().Contact->qryWhereStr = wxEmptyString;
+        wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
 
 
-        if (Contact->pDb->Dbms() != dbmsPOSTGRES)
+        if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
+            wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
         {
         {
-            Contact->whereStr        = "NAME = (SELECT MIN(NAME) FROM ";
-            Contact->whereStr        += CONTACT_TABLE_NAME;
-            Contact->whereStr        += ")";
+            wxGetApp().Contact->whereStr  = wxT("NAME = (SELECT MIN(NAME) FROM ");
+            wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
+            wxGetApp().Contact->whereStr += wxT(")");
         }
 
         }
 
-        Contact->where            = (char*) (const char*) Contact->whereStr;
-        if (!Contact->Query())
+        wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
+        if (!wxGetApp().Contact->Query())
         {
             wxString tStr;
         {
             wxString tStr;
-            tStr  = "ODBC error during Query()\n\n";
-            tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-            wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+            tStr = wxT("ODBC error during Query()\n\n");
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
             return;
         }
             return;
         }
-        if (!Contact->GetNext())
-            Contact->Initialize();
+        if (!wxGetApp().Contact->GetNext())
+            wxGetApp().Contact->Initialize();
         PutData();
         PutData();
-        pResetBtn->Enable(FALSE);
+        pResetBtn->Enable(false);
 
         return;
     }  // Reset button
 
 
 
         return;
     }  // Reset button
 
 
-    if (widgetName == pNameListBtn->GetName())
+    if (widgetName == pNameListBtn->GetName())
+    {
+        new ClookUpDlg(/* wxWindow       *parent        */ this,
+                       /* const wxString &windowTitle   */ wxT("Select contact name"),
+                       /* const wxString &tableName     */ CONTACT_TABLE_NAME,
+                       /* const wxString &dispCol1      */ wxT("NAME"),
+                       /* const wxString &dispCol2      */ wxT("JOINDATE"),
+                       /* const wxString &where         */ wxT(""),
+                       /* const wxString &orderBy       */ wxT("NAME"),
+                       /* wxDb           *pDb           */ wxGetApp().READONLY_DB,
+                       /* const wxString &defDir        */ wxGetApp().DbConnectInf->GetDefaultDir(),
+                       /* bool            distinctValues*/ true,
+                       wxEmptyString, 20);
+
+        if (ListDB_Selection && wxStrlen(ListDB_Selection))
+        {
+            wxString w = wxT("NAME = '");
+            w += ListDB_Selection;
+            w += wxT("'");
+            GetRec(w);
+        }
+
+        return;
+    }
+
+    if (widgetName == pDataTypesBtn->GetName())
+    {
+        CheckSupportForAllDataTypes(wxGetApp().READONLY_DB);
+        wxMessageBox(wxT("Support datatypes was dumped to stdout."));
+        return;
+    }  // Data types Button
+
+    if (widgetName == pDbDiagsBtn->GetName())
+    {
+        DisplayDbDiagnostics(wxGetApp().READONLY_DB);
+        wxMessageBox(wxT("Diagnostics info was dumped to stdout."));
+        return;
+    }
+
+    if (widgetName == pCatalogBtn->GetName())
+    {
+        if (wxGetApp().Contact->GetDb()->Catalog(wxEmptyString, wxT("catalog.txt")))
+            wxMessageBox(wxT("The file 'catalog.txt' was created."));
+        else
+            wxMessageBox(wxT("Creation of the file 'catalog.txt' failed."));
+        return;
+    }
+
+#ifdef wxODBC_BLOB_SUPPORT
+    if (widgetName == pChooseImageBtn->GetName())
+    {
+        OnSelectPict();
+    }
+
+    if (widgetName == pShowImageBtn->GetName())
+    {
+        OnShowImage();
+    }
+#endif
+
+}  // CeditorDlg::OnCommand()
+
+
+bool CeditorDlg::Initialize()
+{
+    // Create the data structure and a new database connection.
+    // (As there is not a pDb being passed in the constructor, a new database
+    // connection is created)
+    wxGetApp().Contact = new Ccontact();
+
+    if (!wxGetApp().Contact)
+    {
+        wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
+        return false;
+    }
+
+    // Check if the table exists or not.  If it doesn't, ask the user if they want to
+    // create the table.  Continue trying to create the table until it exists, or user aborts
+    while (!wxGetApp().Contact->GetDb()->TableExists(CONTACT_TABLE_NAME,
+                                          wxGetApp().DbConnectInf->GetUserID(),
+                                          wxGetApp().DbConnectInf->GetDefaultDir()))
+    {
+        wxString tStr;
+        tStr.Printf(wxT("Unable to open the table '%s'.  The table may\nneed to be created.\n\nDo you wish to try to create/clear the table?\n\n"),CONTACT_TABLE_NAME.c_str());
+        bool createTable = (wxMessageBox(tStr.c_str(),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
+
+        if (!createTable)
+        {
+//            Close();
+            return false;
+        }
+        else
+            wxGetApp().CreateDataTable(false);
+    }
+
+    // Tables must be "opened" before anything other than creating/deleting table can be done
+    if (!wxGetApp().Contact->Open())
+    {
+        // Table does exist, or there was some problem opening it.  Currently this should
+        // never fail, except in the case of the table not exisiting or the current
+        // user has insufficent privileges to access the table
+#if 1
+// This code is experimenting with a new function that will hopefully be available
+// in the 2.4 release.  This check will determine whether the open failing was due
+// to the table not existing, or the users privileges being insufficient to
+// open the table.
+        if (!wxGetApp().Contact->GetDb()->TablePrivileges(CONTACT_TABLE_NAME, wxT("SELECT"),
+                                                wxGetApp().Contact->GetDb()->GetUsername(),
+                                                wxGetApp().Contact->GetDb()->GetUsername(),
+                                                wxGetApp().DbConnectInf->GetDefaultDir()))
+        {
+            wxString tStr;
+            tStr.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME.c_str());
+
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+        }
+        else
+#endif
+        if (!wxGetApp().Contact->GetDb()->TableExists(CONTACT_TABLE_NAME,
+                                           wxGetApp().Contact->GetDb()->GetUsername(),
+                                           wxGetApp().DbConnectInf->GetDefaultDir()))
+        {
+            wxString tStr;
+            tStr.Printf(wxT("Unable to open the table '%s' as the table\ndoes not appear to exist in the tablespace available\nto the currently logged in user.\n\n"),CONTACT_TABLE_NAME.c_str());
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+        }
+
+        return false;
+    }
+
+    // Build the dialog
+
+    (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP, wxEmptyString,  wxPoint(15, 1), wxSize(497,  69), 0, wxT("FunctionGrp"));
+    (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP, wxEmptyString, wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
+
+    pCreateBtn      = new wxButton(this, EDITOR_DIALOG_CREATE,           wxT("&Create"),     wxPoint( 25,  21), wxSize( 70,  35), 0, wxDefaultValidator, wxT("CreateBtn"));
+    pEditBtn        = new wxButton(this, EDITOR_DIALOG_EDIT,             wxT("&Edit"),       wxPoint(102,  21), wxSize( 70,  35), 0, wxDefaultValidator, wxT("EditBtn"));
+    pDeleteBtn      = new wxButton(this, EDITOR_DIALOG_DELETE,           wxT("&Delete"),     wxPoint(179,  21), wxSize( 70,  35), 0, wxDefaultValidator, wxT("DeleteBtn"));
+    pCopyBtn        = new wxButton(this, EDITOR_DIALOG_COPY,             wxT("Cop&y"),       wxPoint(256,  21), wxSize( 70,  35), 0, wxDefaultValidator, wxT("CopyBtn"));
+    pSaveBtn        = new wxButton(this, EDITOR_DIALOG_SAVE,             wxT("&Save"),       wxPoint(333,  21), wxSize( 70,  35), 0, wxDefaultValidator, wxT("SaveBtn"));
+    pCancelBtn      = new wxButton(this, EDITOR_DIALOG_CANCEL,           wxT("C&ancel"),     wxPoint(430,  21), wxSize( 70,  35), 0, wxDefaultValidator, wxT("CancelBtn"));
+    pPrevBtn        = new wxButton(this, EDITOR_DIALOG_PREV,             wxT("<< &Prev"),    wxPoint(430,  81), wxSize( 70,  35), 0, wxDefaultValidator, wxT("PrevBtn"));
+    pNextBtn        = new wxButton(this, EDITOR_DIALOG_NEXT,             wxT("&Next >>"),    wxPoint(430, 121), wxSize( 70,  35), 0, wxDefaultValidator, wxT("NextBtn"));
+    pQueryBtn       = new wxButton(this, EDITOR_DIALOG_QUERY,            wxT("&Query"),      wxPoint(430, 161), wxSize( 70,  35), 0, wxDefaultValidator, wxT("QueryBtn"));
+    pResetBtn       = new wxButton(this, EDITOR_DIALOG_RESET,            wxT("&Reset"),      wxPoint(430, 200), wxSize( 70,  35), 0, wxDefaultValidator, wxT("ResetBtn"));
+    pNameMsg        = new wxStaticText(this, EDITOR_DIALOG_NAME_MSG,     wxT("Name:"),       wxPoint( 17,  80), wxDefaultSize,    0, wxT("NameMsg"));
+    pNameTxt        = new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT,      wxEmptyString,      wxPoint( 17,  97), wxSize(308,  25), 0, wxDefaultValidator, wxT("NameTxt"));
+    pNameListBtn    = new wxButton(this, EDITOR_DIALOG_LOOKUP,           wxT("&Lookup"),     wxPoint(333,  97), wxSize( 70,  24), 0, wxDefaultValidator, wxT("LookupBtn"));
+    pAddress1Msg    = new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG, wxT("Address:"),    wxPoint( 17, 130), wxDefaultSize,    0, wxT("Address1Msg"));
+    pAddress1Txt    = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT,  wxEmptyString,      wxPoint( 17, 147), wxSize(308,  25), 0, wxDefaultValidator, wxT("Address1Txt"));
+    pAddress2Msg    = new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG, wxT("Address:"),    wxPoint( 17, 180), wxDefaultSize,    0, wxT("Address2Msg"));
+    pAddress2Txt    = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT,  wxEmptyString,      wxPoint( 17, 197), wxSize(308,  25), 0, wxDefaultValidator, wxT("Address2Txt"));
+    pCityMsg        = new wxStaticText(this, EDITOR_DIALOG_CITY_MSG,     wxT("City:"),       wxPoint( 17, 230), wxDefaultSize,    0, wxT("CityMsg"));
+    pCityTxt        = new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT,      wxEmptyString,      wxPoint( 17, 247), wxSize(225,  25), 0, wxDefaultValidator, wxT("CityTxt"));
+    pStateMsg       = new wxStaticText(this, EDITOR_DIALOG_STATE_MSG,    wxT("State:"),      wxPoint(250, 230), wxDefaultSize,    0, wxT("StateMsg"));
+    pStateTxt       = new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT,     wxEmptyString,      wxPoint(250, 247), wxSize(153,  25), 0, wxDefaultValidator, wxT("StateTxt"));
+    pCountryMsg     = new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG,  wxT("Country:"),    wxPoint( 17, 280), wxDefaultSize,    0, wxT("CountryMsg"));
+    pCountryTxt     = new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT,   wxEmptyString,      wxPoint( 17, 297), wxSize(225,  25), 0, wxDefaultValidator, wxT("CountryTxt"));
+    pPostalCodeMsg  = new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG,   wxT("Postal Code:"),wxPoint(250, 280), wxDefaultSize,    0, wxT("PostalCodeMsg"));
+    pPostalCodeTxt  = new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT,    wxEmptyString,      wxPoint(250, 297), wxSize(153,  25), 0, wxDefaultValidator, wxT("PostalCodeTxt"));
+
+    wxString choice_strings[5];
+    choice_strings[0] = wxT("English");
+    choice_strings[1] = wxT("French");
+    choice_strings[2] = wxT("German");
+    choice_strings[3] = wxT("Spanish");
+    choice_strings[4] = wxT("Other");
+
+    pNativeLangChoice = new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE,                             wxPoint( 17, 346), wxSize(277,  wxDefaultCoord), 5, choice_strings);
+    pNativeLangMsg    = new wxStaticText(this, EDITOR_DIALOG_LANG_MSG,   wxT("Native language:"), wxPoint( 17, 330), wxDefaultSize, 0, wxT("NativeLangMsg"));
+
+    wxString radio_strings[2];
+    radio_strings[0]  = wxT("No");
+    radio_strings[1]  = wxT("Yes");
+    pDeveloperRadio   = new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER,     wxT("Developer:"),       wxPoint(303, 330), wxDefaultSize, 2, radio_strings, 2, wxHORIZONTAL);
+    pJoinDateMsg      = new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG,   wxT("Date joined:"),     wxPoint( 17, 380), wxDefaultSize, 0, wxT("JoinDateMsg"));
+    pJoinDateTxt      = new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT,    wxEmptyString,           wxPoint( 17, 397), wxSize(150,  25), 0, wxDefaultValidator, wxT("JoinDateTxt"));
+    pContribMsg       = new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG,wxT("Contributions:"),   wxPoint(175, 380), wxDefaultSize, 0, wxT("ContribMsg"));
+    pContribTxt       = new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT, wxEmptyString,           wxPoint(175, 397), wxSize(120,  25), 0, wxDefaultValidator, wxT("ContribTxt"));
+    pLinesMsg         = new wxStaticText(this, EDITOR_DIALOG_LINES_MSG,  wxT("Lines of code:"),   wxPoint(303, 380), wxDefaultSize, 0, wxT("LinesMsg"));
+    pLinesTxt         = new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT,   wxEmptyString,           wxPoint(303, 397), wxSize(100,  25), 0, wxDefaultValidator, wxT("LinesTxt"));
+
+    pCatalogBtn       = new wxButton(this, EDITOR_DIALOG_CATALOG,        wxT("Catalo&g"),         wxPoint(430, 287), wxSize( 70,  35), 0, wxDefaultValidator, wxT("CatalogBtn"));
+    pDataTypesBtn     = new wxButton(this, EDITOR_DIALOG_DATATYPES,      wxT("Data&types"),       wxPoint(430, 337), wxSize( 70,  35), 0, wxDefaultValidator, wxT("DataTypesBtn"));
+    pDbDiagsBtn       = new wxButton(this, EDITOR_DIALOG_DB_DIAGS,       wxT("DB Dia&gs"),        wxPoint(430, 387), wxSize( 70,  35), 0, wxDefaultValidator, wxT("DbDiagsBtn"));
+
+#ifdef wxODBC_BLOB_SUPPORT
+    pPictureMsg       = new wxStaticText(this, EDITOR_DIALOG_PIC_MSG,     wxT("Picture:"),        wxPoint( 17,430), wxDefaultSize, 0, wxT("PicMsg"));
+    pPictSizeMsg      = new wxStaticText(this, EDITOR_DIALOG_PICSIZE_MSG, wxT("Picture Bytes:"),  wxPoint(175,430), wxDefaultSize, 0, wxT("PicSizeMsg"));
+    pChooseImageBtn      = new wxButton(this, EDITOR_DIALOG_PIC_BROWSE,      wxT("Select..."),       wxPoint( 17,447), wxSize( 70, 24), 0, wxDefaultValidator, wxT("PicBrowseBtn"));
+    pShowImageBtn        = new wxButton(this, EDITOR_DIALOG_PIC_SHOW,        wxT("Show..."),         wxPoint( 97,447), wxSize( 70, 24), 0, wxDefaultValidator, wxT("PictShowBtn"));
+    pPictSizeTxt      = new wxTextCtrl(this, EDITOR_DIALOG_PIC_SIZE_TEXT, wxEmptyString,          wxPoint(175,447), wxSize(120, 25), 0, wxDefaultValidator, wxT("PictSizeTxt"));
+#endif
+
+    // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
+    // handle all widget processing
+    widgetPtrsSet = true;
+
+    // Setup the orderBy and where clauses to return back a single record as the result set,
+    // as there will only be one record being shown on the dialog at a time, this optimizes
+    // network traffic by only returning a one row result
+
+    wxGetApp().Contact->SetOrderByClause(wxT("NAME"));  // field name to sort by
+
+    // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
+    // specifically in the Ccontact class.  It is used here for simpler construction of a varying
+    // length string, and then after the string is built, the wxDbTable member variable "where" is
+    // assigned the pointer to the constructed string.
+    //
+    // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
+    // to achieve a single row (in this case the first name in alphabetical order).
+
+    if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
+        wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
+    {
+        wxGetApp().Contact->whereStr.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
+                                            wxGetApp().Contact->GetTableName().c_str());
+        // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
+        wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr);
+    }
+    else
+       wxGetApp().Contact->SetWhereClause(wxEmptyString);
+
+    // Perform the Query to get the result set.
+    // NOTE: If there are no rows returned, that is a valid result, so Query() would return true.
+    //       Only if there is a database error will Query() come back as false
+    if (!wxGetApp().Contact->Query())
+    {
+        wxString tStr;
+        tStr = wxT("ODBC error during Query()\n\n");
+        wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                     wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+        return false;
+    }
+
+    // Since Query succeeded, now get the row that was returned
+    if (!wxGetApp().Contact->GetNext())
+        // If the GetNext() failed at this point, then there are no rows to retrieve,
+        // so clear the values in the members of "Contact" so that PutData() blanks the
+        // widgets on the dialog
+        wxGetApp().Contact->Initialize();
+/*
+    wxGetApp().Contact->GetDb()->RollbackTrans();
+*/
+    SetMode(mView);
+    PutData();
+
+    Show(true);
+
+    initialized = true;
+    return true;
+}  // CeditorDlg::Initialize()
+
+#ifdef wxODBC_BLOB_SUPPORT
+
+void CeditorDlg::OnSelectPict()
+{
+    wxFileDialog dlg(this, wxT("Choose an image file less than 60K"), wxEmptyString, wxEmptyString, wxT("JPEG files (*.jpg)|*.jpg|GIF files (*.gif)|*.gif|BMP files (*.bmp)|*.bmp|All Files (*.*)|*.*"), wxFD_OPEN);
+
+    if (dlg.ShowModal() == wxID_OK)
     {
     {
-        new ClookUpDlg(/* wxWindow  *parent        */ this,
-                       /* char      *windowTitle   */ "Select contact name",
-                       /* char      *tableName     */ (char *) CONTACT_TABLE_NAME,
-                       /* char      *dispCol1      */ "NAME",
-                       /* char      *dispCol2      */ "JOINDATE",
-                       /* char      *where         */ "",
-                       /* char      *orderBy       */ "NAME",
-                       /* bool      distinctValues */ TRUE);
+        wxFile file(dlg.GetPath());
 
 
-        if (ListDB_Selection && strlen(ListDB_Selection))
+        if (file.IsOpened())
         {
         {
-            wxString w = "NAME = '";
-            w += ListDB_Selection;
-            w += "'";
-            GetRec((char*) (const char*) w);
-        }
+            // assume not huge file in sample
+            long iSize = (long)file.Length();
 
 
-        return;
+            if ((iSize > 0) && (iSize < MAX_PICTURE_SIZE))
+            {
+                wxGetApp().Contact->BlobSize = (size_t)iSize;
+
+                memset(wxGetApp().Contact->Picture, 0, MAX_PICTURE_SIZE);
+
+                wxFileOffset iReadSize = file.Read(wxGetApp().Contact->Picture, (size_t)iSize);
+
+                if (iReadSize < iSize)
+                    wxMessageBox(wxT("Something bad happened while reading..."), wxT("BLOB Loading Error"), wxOK | wxICON_EXCLAMATION);
+
+                wxString tStr;
+                tStr.Printf(wxT("%ld"),iSize);
+                pPictSizeTxt->SetValue(tStr);
+            }
+            else
+                wxMessageBox(wxT("Selected File is TOO BIG.  60k is the max image size"), wxT("BLOB Loading Error"), wxOK | wxICON_EXCLAMATION);
+        }
+        else
+            wxMessageBox(wxT("Unable to open the requested image file"), wxT("File Access Error"), wxOK | wxICON_EXCLAMATION);
     }
     }
+}
 
 
-}  // CeditorDlg::OnCommand()
+void CeditorDlg::OnShowImage()
+{
+    if (wxGetApp().Contact->BlobSize > 0)
+    {
+        CimageDlg dlg(this, wxGetApp().Contact->Picture, wxGetApp().Contact->BlobSize);
 
 
+        dlg.ShowModal();
+    }
+}
+
+#endif
 
 void CeditorDlg::FieldsEditable()
 {
 
 void CeditorDlg::FieldsEditable()
 {
+    if (!widgetPtrsSet)
+        return;
+
     pNameTxt->Enable((mode == mCreate) || (mode == mEdit));
     pAddress1Txt->Enable((mode == mCreate) || (mode == mEdit));
     pAddress2Txt->Enable((mode == mCreate) || (mode == mEdit));
     pNameTxt->Enable((mode == mCreate) || (mode == mEdit));
     pAddress1Txt->Enable((mode == mCreate) || (mode == mEdit));
     pAddress2Txt->Enable((mode == mCreate) || (mode == mEdit));
@@ -971,23 +1777,29 @@ void CeditorDlg::FieldsEditable()
     pNativeLangChoice->Enable((mode == mCreate) || (mode == mEdit));
     pDeveloperRadio->Enable((mode == mCreate) || (mode == mEdit));
 
     pNativeLangChoice->Enable((mode == mCreate) || (mode == mEdit));
     pDeveloperRadio->Enable((mode == mCreate) || (mode == mEdit));
 
+#ifdef wxODBC_BLOB_SUPPORT
+    pPictSizeTxt->Enable(false);
+    pChooseImageBtn->Enable((mode == mCreate) || (mode == mEdit));
+    pShowImageBtn->Enable(wxGetApp().Contact && wxGetApp().Contact->BlobSize > 0); //((mode == mCreate) || (mode == mEdit));
+#endif
+
 }  // CeditorDlg::FieldsEditable()
 
 
 void CeditorDlg::SetMode(enum DialogModes m)
 {
 }  // CeditorDlg::FieldsEditable()
 
 
 void CeditorDlg::SetMode(enum DialogModes m)
 {
-    bool    edit = FALSE;
+    bool edit = false;
 
     mode = m;
     switch (mode)
     {
         case mCreate:
         case mEdit:
 
     mode = m;
     switch (mode)
     {
         case mCreate:
         case mEdit:
-            edit = TRUE;
+            edit = true;
             break;
         case mView:
         case mSearch:
             break;
         case mView:
         case mSearch:
-            edit = FALSE;
+            edit = false;
             break;
         default:
                 break;
             break;
         default:
                 break;
@@ -996,15 +1808,15 @@ void CeditorDlg::SetMode(enum DialogModes m)
     if (widgetPtrsSet)
     {
         pCreateBtn->Enable( !edit );
     if (widgetPtrsSet)
     {
         pCreateBtn->Enable( !edit );
-        pEditBtn->Enable( !edit && (strcmp(Contact->Name,"")!=0) );
-        pDeleteBtn->Enable( !edit && (strcmp(Contact->Name,"")!=0) );
-        pCopyBtn->Enable( !edit && (strcmp(Contact->Name,"")!=0) );
+        pEditBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name, wxEmptyString) != 0) );
+        pDeleteBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name, wxEmptyString)!=0) );
+        pCopyBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name, wxEmptyString)!=0) );
         pSaveBtn->Enable( edit );
         pCancelBtn->Enable( edit );
         pPrevBtn->Enable( !edit );
         pNextBtn->Enable( !edit );
         pQueryBtn->Enable( !edit );
         pSaveBtn->Enable( edit );
         pCancelBtn->Enable( edit );
         pPrevBtn->Enable( !edit );
         pNextBtn->Enable( !edit );
         pQueryBtn->Enable( !edit );
-        pResetBtn->Enable( !edit && !Contact->qryWhereStr.IsEmpty() );
+        pResetBtn->Enable( !edit && !wxGetApp().Contact->qryWhereStr.empty() );
         pNameListBtn->Enable( !edit );
     }
 
         pNameListBtn->Enable( !edit );
     }
 
@@ -1016,28 +1828,34 @@ bool CeditorDlg::PutData()
 {
     wxString tStr;
 
 {
     wxString tStr;
 
-    pNameTxt->SetValue(Contact->Name);
-    pAddress1Txt->SetValue(Contact->Addr1);
-    pAddress2Txt->SetValue(Contact->Addr2);
-    pCityTxt->SetValue(Contact->City);
-    pStateTxt->SetValue(Contact->State);
-    pCountryTxt->SetValue(Contact->Country);
-    pPostalCodeTxt->SetValue(Contact->PostalCode);
+    pNameTxt->SetValue(wxGetApp().Contact->Name);
+    pAddress1Txt->SetValue(wxGetApp().Contact->Addr1);
+    pAddress2Txt->SetValue(wxGetApp().Contact->Addr2);
+    pCityTxt->SetValue(wxGetApp().Contact->City);
+    pStateTxt->SetValue(wxGetApp().Contact->State);
+    pCountryTxt->SetValue(wxGetApp().Contact->Country);
+    pPostalCodeTxt->SetValue(wxGetApp().Contact->PostalCode);
 
 
-    tStr.Printf("%d/%d/%d",Contact->JoinDate.month,Contact->JoinDate.day,Contact->JoinDate.year);
+    tStr.Printf(wxT("%d/%d/%d"),wxGetApp().Contact->JoinDate.month,wxGetApp().Contact->JoinDate.day,wxGetApp().Contact->JoinDate.year);
     pJoinDateTxt->SetValue(tStr);
 
     pJoinDateTxt->SetValue(tStr);
 
-    tStr.Printf("%d",Contact->Contributions);
+    tStr.Printf(wxT("%d"),wxGetApp().Contact->Contributions);
     pContribTxt->SetValue(tStr);
 
     pContribTxt->SetValue(tStr);
 
-    tStr.Printf("%lu",Contact->LinesOfCode);
+    tStr.Printf(wxT("%lu"),wxGetApp().Contact->LinesOfCode);
     pLinesTxt->SetValue(tStr);
 
     pLinesTxt->SetValue(tStr);
 
-    pNativeLangChoice->SetSelection(Contact->NativeLanguage);
+    pNativeLangChoice->SetSelection(wxGetApp().Contact->NativeLanguage);
+
+    pDeveloperRadio->SetSelection(wxGetApp().Contact->IsDeveloper);
 
 
-    pDeveloperRadio->SetSelection(Contact->IsDeveloper);
+#ifdef wxODBC_BLOB_SUPPORT
+    tStr.Printf(wxT("%lu"),wxGetApp().Contact->BlobSize);
+    pPictSizeTxt->SetValue(tStr);
+    pShowImageBtn->Enable(wxGetApp().Contact->BlobSize > 0);
+#endif
 
 
-    return TRUE;
+    return true;
 }  // Ceditor::PutData()
 
 
 }  // Ceditor::PutData()
 
 
@@ -1045,7 +1863,7 @@ bool CeditorDlg::PutData()
  * Reads the data out of all the widgets on the dialog.  Some data evaluation is done
  * to ensure that there is a name entered and that the date field is valid.
  *
  * Reads the data out of all the widgets on the dialog.  Some data evaluation is done
  * to ensure that there is a name entered and that the date field is valid.
  *
- * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
+ * A return value of true means that valid data was retrieved from the dialog, otherwise
  * invalid data was found (and a message was displayed telling the user what to fix), and
  * the data was not placed into the appropraite fields of Ccontact
  */
  * invalid data was found (and a message was displayed telling the user what to fix), and
  * the data was not placed into the appropraite fields of Ccontact
  */
@@ -1055,59 +1873,59 @@ bool CeditorDlg::GetData()
 
     wxString tStr;
     tStr = pNameTxt->GetValue();
 
     wxString tStr;
     tStr = pNameTxt->GetValue();
-    if (!strcmp((const char*) tStr,""))
+    if (!wxStrcmp((const wxChar*) tStr, wxEmptyString))
     {
     {
-        wxMessageBox("A name is required for entry into the contact table","Notice...",wxOK | wxICON_INFORMATION);
-        return FALSE;
+        wxMessageBox(wxT("A name is required for entry into the contact table"), wxT("Notice..."), wxOK | wxICON_INFORMATION);
+        return false;
     }
 
     }
 
-    bool    invalid = FALSE;
-    int    mm,dd,yyyy;
+    bool   invalid = false;
+    int    mm = 1,dd = 1,yyyy = 2001;
     int    first, second;
 
     tStr = pJoinDateTxt->GetValue();
     int    first, second;
 
     tStr = pJoinDateTxt->GetValue();
-    if (tStr.Freq('/') != 2)
-        invalid = TRUE;
+    if (tStr.Freq(wxT('/')) != 2)
+        invalid = true;
 
     // Find the month, day, and year tokens
     if (!invalid)
     {
 
     // Find the month, day, and year tokens
     if (!invalid)
     {
-        first   = tStr.First('/');
-        second  = tStr.Last('/');
+        first   = tStr.First(wxT('/'));
+        second  = tStr.Last(wxT('/'));
 
 
-        mm      = atoi(tStr.SubString(0,first));
-        dd      = atoi(tStr.SubString(first+1,second));
-        yyyy    = atoi(tStr.SubString(second+1,tStr.Length()-1));
+        mm      = wxAtoi(tStr.SubString(0,first));
+        dd      = wxAtoi(tStr.SubString(first+1,second));
+        yyyy    = wxAtoi(tStr.SubString(second+1,tStr.Length()-1));
 
         invalid = !(mm && dd && yyyy);
     }
 
     // Force Year 2000 compliance
     if (!invalid && (yyyy < 1000))
 
         invalid = !(mm && dd && yyyy);
     }
 
     // Force Year 2000 compliance
     if (!invalid && (yyyy < 1000))
-        invalid = TRUE;
+        invalid = true;
 
     // Check the token ranges for validity
     if (!invalid)
     {
         if (yyyy > 9999)
 
     // Check the token ranges for validity
     if (!invalid)
     {
         if (yyyy > 9999)
-            invalid = TRUE;
+            invalid = true;
         else if ((mm < 1) || (mm > 12))
         else if ((mm < 1) || (mm > 12))
-            invalid = TRUE;
+            invalid = true;
         else
         {
             if (dd < 1)
         else
         {
             if (dd < 1)
-                invalid = TRUE;
+                invalid = true;
             else
             {
                 int days[12] = {31,28,31,30,31,30,
                                 31,31,30,31,30,31};
                 if (dd > days[mm-1])
                 {
             else
             {
                 int days[12] = {31,28,31,30,31,30,
                                 31,31,30,31,30,31};
                 if (dd > days[mm-1])
                 {
-                    invalid = TRUE;
+                    invalid = true;
                     if ((dd == 29) && (mm == 2))
                     {
                         if (((yyyy % 4) == 0) && (((yyyy % 100) != 0) || ((yyyy % 400) == 0)))
                     if ((dd == 29) && (mm == 2))
                     {
                         if (((yyyy % 4) == 0) && (((yyyy % 100) != 0) || ((yyyy % 400) == 0)))
-                            invalid = FALSE;
+                            invalid = false;
                     }
                 }
             }
                     }
                 }
             }
@@ -1116,32 +1934,32 @@ bool CeditorDlg::GetData()
 
     if (!invalid)
     {
 
     if (!invalid)
     {
-        Contact->JoinDate.month = mm;
-        Contact->JoinDate.day   = dd;
-        Contact->JoinDate.year  = yyyy;
+        wxGetApp().Contact->JoinDate.month = (unsigned short) mm;
+        wxGetApp().Contact->JoinDate.day   = (unsigned short) dd;
+        wxGetApp().Contact->JoinDate.year  = (short) yyyy;
     }
     else
     {
     }
     else
     {
-        wxMessageBox("Improper date format.  Please check the date\nspecified and try again.\n\nNOTE: Dates are in american format (MM/DD/YYYY)","Notice...",wxOK | wxICON_INFORMATION);
-        return FALSE;
+        wxMessageBox(wxT("Improper date format.  Please check the date\nspecified and try again.\n\nNOTE: Dates are in american format (MM/DD/YYYY)"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
+        return false;
     }
 
     tStr = pNameTxt->GetValue();
     }
 
     tStr = pNameTxt->GetValue();
-    strcpy(Contact->Name,(const char*) tStr);
-    strcpy(Contact->Addr1,pAddress1Txt->GetValue());
-    strcpy(Contact->Addr2,pAddress2Txt->GetValue());
-    strcpy(Contact->City,pCityTxt->GetValue());
-    strcpy(Contact->State,pStateTxt->GetValue());
-    strcpy(Contact->Country,pCountryTxt->GetValue());
-    strcpy(Contact->PostalCode,pPostalCodeTxt->GetValue());
+    wxStrcpy(wxGetApp().Contact->Name,(const wxChar*) tStr);
+    wxStrcpy(wxGetApp().Contact->Addr1,pAddress1Txt->GetValue());
+    wxStrcpy(wxGetApp().Contact->Addr2,pAddress2Txt->GetValue());
+    wxStrcpy(wxGetApp().Contact->City,pCityTxt->GetValue());
+    wxStrcpy(wxGetApp().Contact->State,pStateTxt->GetValue());
+    wxStrcpy(wxGetApp().Contact->Country,pCountryTxt->GetValue());
+    wxStrcpy(wxGetApp().Contact->PostalCode,pPostalCodeTxt->GetValue());
 
 
-    Contact->Contributions = atoi(pContribTxt->GetValue());
-    Contact->LinesOfCode = atol(pLinesTxt->GetValue());
+    wxGetApp().Contact->Contributions = (UCHAR)wxAtoi(pContribTxt->GetValue());
+    wxGetApp().Contact->LinesOfCode = wxAtol(pLinesTxt->GetValue());
 
 
-    Contact->NativeLanguage = (enum Language) pNativeLangChoice->GetSelection();
-    Contact->IsDeveloper = pDeveloperRadio->GetSelection() > 0;
+    wxGetApp().Contact->NativeLanguage = (enum Language) pNativeLangChoice->GetSelection();
+    wxGetApp().Contact->IsDeveloper = pDeveloperRadio->GetSelection() > 0;
 
 
-    return TRUE;
+    return true;
 }  // CeditorDlg::GetData()
 
 
 }  // CeditorDlg::GetData()
 
 
@@ -1150,17 +1968,17 @@ bool CeditorDlg::GetData()
  * try to insert/update the data to the table based on the current 'mode' the dialog
  * is set to.
  *
  * try to insert/update the data to the table based on the current 'mode' the dialog
  * is set to.
  *
- * A return value of TRUE means the insert/update was completed successfully, a return
- * value of FALSE means that Save() failed.  If returning FALSE, then this function
+ * A return value of true means the insert/update was completed successfully, a return
+ * value of false means that Save() failed.  If returning false, then this function
  * has displayed a detailed error message for the user.
  */
 bool CeditorDlg::Save()
 {
  * has displayed a detailed error message for the user.
  */
 bool CeditorDlg::Save()
 {
-    bool failed = FALSE;
+    bool failed = false;
 
     // Read the data in the widgets of the dialog to get the user's data
     if (!GetData())
 
     // Read the data in the widgets of the dialog to get the user's data
     if (!GetData())
-        failed = TRUE;
+        failed = true;
 
     // Perform any other required validations necessary before saving
     if (!failed)
 
     // Perform any other required validations necessary before saving
     if (!failed)
@@ -1169,7 +1987,7 @@ bool CeditorDlg::Save()
 
         if (mode == mCreate)
         {
 
         if (mode == mCreate)
         {
-            RETCODE result = Contact->Insert();
+            RETCODE result = (RETCODE)wxGetApp().Contact->Insert();
 
             failed = (result != DB_SUCCESS);
             if (failed)
 
             failed = (result != DB_SUCCESS);
             if (failed)
@@ -1179,39 +1997,41 @@ bool CeditorDlg::Save()
                 if (result == DB_ERR_INTEGRITY_CONSTRAINT_VIOL)
                 {
                     wxString tStr;
                 if (result == DB_ERR_INTEGRITY_CONSTRAINT_VIOL)
                 {
                     wxString tStr;
-                    tStr  = "A duplicate key value already exists in the table.\nUnable to save record\n\n";
-                    tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-                    wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+                    tStr = wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
+                    wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                                 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
                 }
                 else
                 {
                 }
                 else
                 {
-                    // Some other unexpexted error occurred
+                    // Some other unexpected error occurred
                     wxString tStr;
                     wxString tStr;
-                    tStr  = "Database insert failed\n\n";
-                    tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-                    wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+                    tStr = wxT("Database insert failed\n\n");
+                    wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                                 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
                 }
             }
         }
         else  // mode == mEdit
         {
                 }
             }
         }
         else  // mode == mEdit
         {
-            if (!Contact->Update())
+            wxGetApp().Contact->GetDb()->RollbackTrans();
+            wxGetApp().Contact->whereStr.Printf(wxT("NAME = '%s'"),saveName.c_str());
+            if (!wxGetApp().Contact->UpdateWhere(wxGetApp().Contact->whereStr))
             {
                 wxString tStr;
             {
                 wxString tStr;
-                tStr  = "Database update failed\n\n";
-                tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-                wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
-                failed = TRUE;
+                tStr = wxT("Database update failed\n\n");
+                wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                             wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+                failed = true;
             }
         }
 
         if (!failed)
         {
             }
         }
 
         if (!failed)
         {
-            Contact->pDb->CommitTrans();
+            wxGetApp().Contact->GetDb()->CommitTrans();
             SetMode(mView);  // Sets the dialog mode back to viewing after save is successful
         }
         else
             SetMode(mView);  // Sets the dialog mode back to viewing after save is successful
         }
         else
-            Contact->pDb->RollbackTrans();
+            wxGetApp().Contact->GetDb()->RollbackTrans();
 
         wxEndBusyCursor();
     }
 
         wxEndBusyCursor();
     }
@@ -1229,28 +2049,29 @@ bool CeditorDlg::GetNextRec()
 {
     wxString w;
 
 {
     wxString w;
 
-    if (Contact->pDb->Dbms() != dbmsPOSTGRES)
+    if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
+        wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
     {
     {
-        w  = "NAME = (SELECT MIN(NAME) FROM ";
-        w += Contact->tableName;
-        w += " WHERE NAME > '";
+        w  = wxT("NAME = (SELECT MIN(NAME) FROM ");
+        w += wxGetApp().Contact->GetTableName();
+        w += wxT(" WHERE NAME > '");
     }
     else
     }
     else
-        w = "(NAME > '";
+        w = wxT("(NAME > '");
 
 
-    w += Contact->Name;
-    w += "'";
+    w += wxGetApp().Contact->Name;
+    w += wxT("'");
 
     // If a query where string is currently set, append that criteria
 
     // If a query where string is currently set, append that criteria
-    if (!Contact->qryWhereStr.IsEmpty())
+    if (!wxGetApp().Contact->qryWhereStr.empty())
     {
     {
-        w += " AND (";
-        w += Contact->qryWhereStr;
-        w += ")";
+        w += wxT(" AND (");
+        w += wxGetApp().Contact->qryWhereStr;
+        w += wxT(")");
     }
 
     }
 
-    w += ")";
-    return(GetRec((char*) (const char*) w));
+    w += wxT(")");
+    return(GetRec(w));
 
 }  // CeditorDlg::GetNextRec()
 
 
 }  // CeditorDlg::GetNextRec()
 
@@ -1264,29 +2085,30 @@ bool CeditorDlg::GetPrevRec()
 {
     wxString w;
 
 {
     wxString w;
 
-    if (Contact->pDb->Dbms() != dbmsPOSTGRES)
+    if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
+        wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
     {
     {
-        w  = "NAME = (SELECT MAX(NAME) FROM ";
-        w += Contact->tableName;
-        w += " WHERE NAME < '";
+        w  = wxT("NAME = (SELECT MAX(NAME) FROM ");
+        w += wxGetApp().Contact->GetTableName();
+        w += wxT(" WHERE NAME < '");
     }
     else
     }
     else
-        w = "(NAME < '";
+        w = wxT("(NAME < '");
 
 
-    w += Contact->Name;
-    w += "'";
+    w += wxGetApp().Contact->Name;
+    w += wxT("'");
 
     // If a query where string is currently set, append that criteria
 
     // If a query where string is currently set, append that criteria
-    if (!Contact->qryWhereStr.IsEmpty())
+    if (!wxGetApp().Contact->qryWhereStr.empty())
     {
     {
-        w += " AND (";
-        w += Contact->qryWhereStr;
-        w += ")";
+        w += wxT(" AND (");
+        w += wxGetApp().Contact->qryWhereStr;
+        w += wxT(")");
     }
 
     }
 
-    w += ")";
+    w += wxT(")");
 
 
-    return(GetRec((char*) (const char*)w));
+    return(GetRec(w));
 
 }  // CeditorDlg::GetPrevRec()
 
 
 }  // CeditorDlg::GetPrevRec()
 
@@ -1295,28 +2117,28 @@ bool CeditorDlg::GetPrevRec()
  * This function is here to avoid duplicating this same code in both the
  * GetPrevRec() and GetNextRec() functions
  */
  * This function is here to avoid duplicating this same code in both the
  * GetPrevRec() and GetNextRec() functions
  */
-bool CeditorDlg::GetRec(char *whereStr)
+bool CeditorDlg::GetRec(const wxString &whereStr)
 {
 {
-    Contact->where = whereStr;
-    Contact->orderBy = "NAME";
+    wxGetApp().Contact->SetWhereClause(whereStr);
+    wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
 
 
-    if (!Contact->Query())
+    if (!wxGetApp().Contact->Query())
     {
         wxString tStr;
     {
         wxString tStr;
-        tStr  = "ODBC error during Query()\n\n";
-        tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-        wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+        tStr = wxT("ODBC error during Query()\n\n");
+        wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                     wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
 
 
-        return(FALSE);
+        return(false);
     }
 
     }
 
-    if (Contact->GetNext())
+    if (wxGetApp().Contact->GetNext())
     {
         PutData();
     {
         PutData();
-        return(TRUE);
+        return(true);
     }
     else
     }
     else
-        return(FALSE);
+        return(false);
 }  // CeditorDlg::GetRec()
 
 
 }  // CeditorDlg::GetRec()
 
 
@@ -1331,29 +2153,29 @@ BEGIN_EVENT_TABLE(CparameterDlg, wxDialog)
     EVT_CLOSE(CparameterDlg::OnCloseWindow)
 END_EVENT_TABLE()
 
     EVT_CLOSE(CparameterDlg::OnCloseWindow)
 END_EVENT_TABLE()
 
-CparameterDlg::CparameterDlg(wxWindow *parent) : wxDialog (parent, PARAMETER_DIALOG, "ODBC parameter settings", wxPoint(-1, -1), wxSize(400, 325))
+CparameterDlg::CparameterDlg(wxWindow *parent) : wxDialog (parent, PARAMETER_DIALOG, wxT("ODBC parameter settings"), wxDefaultPosition, wxSize(400, 325))
 {
     // Since the ::OnCommand() function is overridden, this prevents the widget
     // detection in ::OnCommand() until all widgets have been initialized to prevent
     // uninitialized pointers from crashing the program
 {
     // Since the ::OnCommand() function is overridden, this prevents the widget
     // detection in ::OnCommand() until all widgets have been initialized to prevent
     // uninitialized pointers from crashing the program
-    widgetPtrsSet = FALSE;
-
-    pParamODBCSourceMsg  = new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG,   "ODBC data sources:",   wxPoint( 10, 10),    wxSize( -1,  -1), 0, "ParamODBCSourceMsg");
-    pParamODBCSourceList = new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX,                          wxPoint( 10, 29),    wxSize(285, 150), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, "ParamODBCSourceList");
-    pParamUserNameMsg    = new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG,     "Database user name:",  wxPoint( 10, 193),   wxSize( -1,  -1), 0, "ParamUserNameMsg");
-    pParamUserNameTxt    = new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT,      "", wxPoint(10, 209),   wxSize( 140, 25),    0, wxDefaultValidator, "ParamUserNameTxt");
-    pParamPasswordMsg    = new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG, "Password:",            wxPoint(156, 193),   wxSize( -1,  -1), 0, "ParamPasswordMsg");
-    pParamPasswordTxt    = new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT,  "", wxPoint(156, 209),  wxSize( 140,  25),   0, wxDefaultValidator, "ParamPasswordTxt");
-    pParamDirPathMsg     = new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG,  "Directory:",           wxPoint( 10, 243),   wxSize( -1,  -1), 0, "ParamDirPathMsg");
-    pParamDirPathTxt     = new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT,   "",                     wxPoint( 10, 259),   wxSize(140,  25), 0, wxDefaultValidator, "ParamDirPathTxt");
-    pParamSaveBtn        = new wxButton(this, PARAMETER_DIALOG_SAVE,             "&Save",                wxPoint(310,  21),   wxSize( 70,  35), 0, wxDefaultValidator, "ParamSaveBtn");
-    pParamCancelBtn      = new wxButton(this, PARAMETER_DIALOG_CANCEL,           "C&ancel",              wxPoint(310,  66),   wxSize( 70,  35), 0, wxDefaultValidator, "ParamCancelBtn");
-
-    // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to 
+    widgetPtrsSet = false;
+
+    pParamODBCSourceMsg  = new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG,   wxT("ODBC data sources:"),   wxPoint( 10, 10),    wxDefaultSize, 0, wxT("ParamODBCSourceMsg"));
+    pParamODBCSourceList = new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX,                               wxPoint( 10, 29),    wxSize(285, 150), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("ParamODBCSourceList"));
+    pParamUserNameMsg    = new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG,     wxT("Database user name:"),  wxPoint( 10, 193),   wxDefaultSize, 0, wxT("ParamUserNameMsg"));
+    pParamUserNameTxt    = new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT,      wxEmptyString,               wxPoint(10, 209),   wxSize( 140, 25),    0, wxDefaultValidator, wxT("ParamUserNameTxt"));
+    pParamPasswordMsg    = new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG, wxT("Password:"),            wxPoint(156, 193),   wxDefaultSize, 0, wxT("ParamPasswordMsg"));
+    pParamPasswordTxt    = new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT,  wxEmptyString,               wxPoint(156, 209),  wxSize( 140,  25),   0, wxDefaultValidator, wxT("ParamPasswordTxt"));
+    pParamDirPathMsg     = new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG,  wxT("Directory:"),           wxPoint( 10, 243),   wxDefaultSize, 0, wxT("ParamDirPathMsg"));
+    pParamDirPathTxt     = new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT,   wxEmptyString,               wxPoint( 10, 259),   wxSize(140,  25), 0, wxDefaultValidator, wxT("ParamDirPathTxt"));
+    pParamSaveBtn        = new wxButton(this, PARAMETER_DIALOG_SAVE,             wxT("&Save"),                wxPoint(310,  21),   wxSize( 70,  35), 0, wxDefaultValidator, wxT("ParamSaveBtn"));
+    pParamCancelBtn      = new wxButton(this, PARAMETER_DIALOG_CANCEL,           wxT("C&ancel"),              wxPoint(310,  66),   wxSize( 70,  35), 0, wxDefaultValidator, wxT("ParamCancelBtn"));
+
+    // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
     // handle all widget processing
     // handle all widget processing
-    widgetPtrsSet = TRUE;
+    widgetPtrsSet = true;
 
 
-    saved = FALSE;
+    saved = false;
     savedParamSettings = wxGetApp().params;
 
     Centre(wxBOTH);
     savedParamSettings = wxGetApp().params;
 
     Centre(wxBOTH);
@@ -1368,7 +2190,7 @@ void CparameterDlg::OnCloseWindow(wxCloseEvent& event)
     // to close the program here that is not done elsewhere
     if (!saved)
     {
     // to close the program here that is not done elsewhere
     if (!saved)
     {
-        bool Ok = (wxMessageBox("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?","Confirm",wxYES_NO|wxICON_QUESTION) == wxYES);
+        bool Ok = (wxMessageBox(wxT("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
 
         if (!Ok)
         {
 
         if (!Ok)
         {
@@ -1381,9 +2203,15 @@ void CparameterDlg::OnCloseWindow(wxCloseEvent& event)
 
     if (GetParent() != NULL)
         GetParent()->SetFocus();
 
     if (GetParent() != NULL)
         GetParent()->SetFocus();
-    this->Destroy();
 
 
-}  // Cparameter::OnCloseWindow()
+    while (wxIsBusy())
+        wxEndBusyCursor();
+
+    Show(false);
+    SetReturnCode(0);  // added so BoundsChecker would not report use of uninitialized variable
+
+    this->Destroy();
+}  // CparameterDlg::OnCloseWindow()
 
 
 void CparameterDlg::OnButton( wxCommandEvent &event )
 
 
 void CparameterDlg::OnButton( wxCommandEvent &event )
@@ -1392,10 +2220,11 @@ void CparameterDlg::OnButton( wxCommandEvent &event )
     OnCommand( *win, event );
 }
 
     OnCommand( *win, event );
 }
 
-void CparameterDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
+
+void CparameterDlg::OnCommand(wxWindow& win, wxCommandEvent& WXUNUSED(event))
 {
     wxString widgetName;
 {
     wxString widgetName;
-    
+
     widgetName = win.GetName();
 
     if (!widgetPtrsSet)
     widgetName = win.GetName();
 
     if (!widgetPtrsSet)
@@ -1406,11 +2235,11 @@ void CparameterDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
         if (Save())
         {
             wxString tStr;
         if (Save())
         {
             wxString tStr;
-            tStr = "Database parameters have been saved.";
+            tStr = wxT("Database parameters have been saved.");
             if (GetParent() != NULL)  // The parameter dialog was not called during startup due to a missing cfg file
             if (GetParent() != NULL)  // The parameter dialog was not called during startup due to a missing cfg file
-                tStr += "\nNew parameters will take effect the next time the program is started.";
-            wxMessageBox(tStr,"Notice...",wxOK | wxICON_INFORMATION);
-            saved = TRUE;
+                tStr += wxT("\nNew parameters will take effect the next time the program is started.");
+            wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
+            saved = true;
             Close();
         }
         return;
             Close();
         }
         return;
@@ -1431,205 +2260,197 @@ bool CparameterDlg::PutData()
 
     // Fill in the fields from the params object
     if (wxGetApp().params.ODBCSource && wxStrlen(wxGetApp().params.ODBCSource))
 
     // Fill in the fields from the params object
     if (wxGetApp().params.ODBCSource && wxStrlen(wxGetApp().params.ODBCSource))
-        pParamODBCSourceList->SetStringSelection(wxGetApp().params.ODBCSource);
+    {
+        int index = pParamODBCSourceList->FindString(wxGetApp().params.ODBCSource);
+        if (index != wxNOT_FOUND)
+            pParamODBCSourceList->SetSelection(index);
+    }
     pParamUserNameTxt->SetValue(wxGetApp().params.UserName);
     pParamPasswordTxt->SetValue(wxGetApp().params.Password);
     pParamDirPathTxt->SetValue(wxGetApp().params.DirPath);
     pParamUserNameTxt->SetValue(wxGetApp().params.UserName);
     pParamPasswordTxt->SetValue(wxGetApp().params.Password);
     pParamDirPathTxt->SetValue(wxGetApp().params.DirPath);
-    return TRUE;
+    return true;
 }  // CparameterDlg::PutData()
 
 
 bool CparameterDlg::GetData()
 {
     wxString tStr;
 }  // CparameterDlg::PutData()
 
 
 bool CparameterDlg::GetData()
 {
     wxString tStr;
-    if (pParamODBCSourceList->GetStringSelection() != "")
+    if (pParamODBCSourceList->GetStringSelection() != wxEmptyString)
     {
         tStr = pParamODBCSourceList->GetStringSelection();
     {
         tStr = pParamODBCSourceList->GetStringSelection();
-        if (tStr.Length() > (sizeof(wxGetApp().params.ODBCSource)-1))
+        if (tStr.Length() > ((int)(sizeof(wxGetApp().params.ODBCSource) / sizeof(wxChar))-1))
         {
             wxString errmsg;
         {
             wxString errmsg;
-            errmsg.Printf("ODBC Data source name is longer than the data structure to hold it.\n'Cparameter.ODBCSource' must have a larger character array\nto handle a data source with this long of a name\n\nThe data source currently selected is %d characters long.",tStr.Length());
-            wxMessageBox(errmsg,"Internal program error...",wxOK | wxICON_EXCLAMATION);
-            return FALSE;
+            errmsg.Printf(wxT("ODBC Data source name is longer than the data structure to hold it.\n'Cparameter.ODBCSource' must have a larger character array\nto handle a data source with this long of a name\n\nThe data source currently selected is %d characters long."), tStr.Length());
+            wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
+            return false;
         }
         }
-        strcpy(wxGetApp().params.ODBCSource, tStr);
+        wxStrcpy(wxGetApp().params.ODBCSource, tStr);
     }
     else
     }
     else
-        return FALSE;
-    
+        return false;
+
     tStr = pParamUserNameTxt->GetValue();
     tStr = pParamUserNameTxt->GetValue();
-    if (tStr.Length() > (sizeof(wxGetApp().params.UserName)-1))
+    if (tStr.Length() > ((int)(sizeof(wxGetApp().params.UserName) / sizeof(wxChar))-1))
     {
         wxString errmsg;
     {
         wxString errmsg;
-        errmsg.Printf("User name is longer than the data structure to hold it.\n'Cparameter.UserName' must have a larger character array\nto handle a data source with this long of a name\n\nThe user name currently specified is %d characters long.",tStr.Length());
-        wxMessageBox(errmsg,"Internal program error...",wxOK | wxICON_EXCLAMATION);
-        return FALSE;
+        errmsg.Printf(wxT("User name is longer than the data structure to hold it.\n'Cparameter.UserName' must have a larger character array\nto handle a data source with this long of a name\n\nThe user name currently specified is %d characters long."), tStr.Length());
+        wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
+        return false;
     }
     }
-    strcpy(wxGetApp().params.UserName, tStr);
+    wxStrcpy(wxGetApp().params.UserName, tStr);
 
     tStr = pParamPasswordTxt->GetValue();
 
     tStr = pParamPasswordTxt->GetValue();
-    if (tStr.Length() > (sizeof(wxGetApp().params.Password)-1))
+    if (tStr.Length() > ((int)(sizeof(wxGetApp().params.Password) / sizeof(wxChar))-1))
     {
         wxString errmsg;
     {
         wxString errmsg;
-        errmsg.Printf("Password is longer than the data structure to hold it.\n'Cparameter.Password' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long.",tStr.Length());
-        wxMessageBox(errmsg,"Internal program error...",wxOK | wxICON_EXCLAMATION);
-        return FALSE;
+        errmsg.Printf(wxT("Password is longer than the data structure to hold it.\n'Cparameter.Password' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."), tStr.Length());
+        wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
+        return false;
     }
     }
-    strcpy(wxGetApp().params.Password,tStr);
+    wxStrcpy(wxGetApp().params.Password,tStr);
 
     tStr = pParamDirPathTxt->GetValue();
 
     tStr = pParamDirPathTxt->GetValue();
-    tStr.Replace("\\","/");
-    if (tStr.Length() > (sizeof(wxGetApp().params.DirPath)-1))
+    tStr.Replace(wxT("\\"),wxT("/"));
+    if (tStr.Length() > ((int)(sizeof(wxGetApp().params.DirPath) / sizeof(wxChar))-1))
     {
         wxString errmsg;
     {
         wxString errmsg;
-        errmsg.Printf("DirPath is longer than the data structure to hold it.\n'Cparameter.DirPath' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long.",tStr.Length());
-        wxMessageBox(errmsg,"Internal program error...",wxOK | wxICON_EXCLAMATION);
-        return FALSE;
+        errmsg.Printf(wxT("DirPath is longer than the data structure to hold it.\n'Cparameter.DirPath' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."), tStr.Length());
+        wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
+        return false;
     }
     }
-    strcpy(wxGetApp().params.DirPath,tStr);
-    return TRUE;
+    wxStrcpy(wxGetApp().params.DirPath,tStr);
+    return true;
 }  // CparameterDlg::GetData()
 
 
 bool CparameterDlg::Save()
 {
 }  // CparameterDlg::GetData()
 
 
 bool CparameterDlg::Save()
 {
-    Cparameters saveParams = wxGetApp().params;
+    // Copy the current params in case user cancels changing
+    // the params, so that we can reset them.
     if (!GetData())
     {
     if (!GetData())
     {
-        wxGetApp().params = saveParams;
-        return FALSE;
+        wxGetApp().params = savedParamSettings;
+        return false;
     }
 
     }
 
-    FILE *paramFile;
-    if ((paramFile = fopen(paramFilename, "wt")) == NULL)
-    {
-        wxString tStr;
-        tStr.Printf("Unable to write/overwrite '%s'.",paramFilename);
-        wxMessageBox(tStr,"File I/O Error...",wxOK | wxICON_EXCLAMATION);
-        return FALSE;
-    }
-
-    fputs(wxGetApp().params.ODBCSource, paramFile);
-    fputc('\n', paramFile);
-    fputs(wxGetApp().params.UserName, paramFile);
-    fputc('\n', paramFile);
-    fputs(wxGetApp().params.Password, paramFile);
-    fputc('\n', paramFile);
-    fputs(wxGetApp().params.DirPath, paramFile);
-    fputc('\n', paramFile);
-    fclose(paramFile);
+    wxGetApp().WriteParamFile(wxGetApp().params);
 
 
-    return TRUE;
+    return true;
 }  // CparameterDlg::Save()
 
 
 void CparameterDlg::FillDataSourceList()
 {
 }  // CparameterDlg::Save()
 
 
 void CparameterDlg::FillDataSourceList()
 {
-    char Dsn[SQL_MAX_DSN_LENGTH + 1];
-    char DsDesc[255];
-    wxStringList strList;
+    wxChar Dsn[SQL_MAX_DSN_LENGTH+1];
+    wxChar DsDesc[254+1];
+    wxSortedArrayString strArr;
 
 
-    while (wxDbGetDataSource(DbConnectInf.Henv, Dsn, SQL_MAX_DSN_LENGTH+1, DsDesc, 255))
-        strList.Add(Dsn);
+    while (wxDbGetDataSource(wxGetApp().DbConnectInf->GetHenv(), Dsn,
+                             SQL_MAX_DSN_LENGTH, DsDesc, 254))
+    {
+        strArr.Add(Dsn);
+    }
 
 
-    strList.Sort();
-    strList.Add("");
-    char **p = strList.ListToArray();
+    for (size_t i=0; i < strArr.GetCount(); i++)
+    {
+        pParamODBCSourceList->Append(strArr[i].c_str());
+    }
 
 
-    int i;
-    for (i = 0; strlen(p[i]); i++)
-        pParamODBCSourceList->Append(p[i]);
-}  // CparameterDlg::CparameterDlg::FillDataSourceList()
+}  // CparameterDlg::FillDataSourceList()
 
 
 BEGIN_EVENT_TABLE(CqueryDlg, wxDialog)
 
 
 BEGIN_EVENT_TABLE(CqueryDlg, wxDialog)
-    EVT_BUTTON(-1,  CqueryDlg::OnButton)
+    EVT_BUTTON(wxID_ANY,  CqueryDlg::OnButton)
     EVT_CLOSE(CqueryDlg::OnCloseWindow)
 END_EVENT_TABLE()
     EVT_CLOSE(CqueryDlg::OnCloseWindow)
 END_EVENT_TABLE()
+
+
 // CqueryDlg() constructor
 // CqueryDlg() constructor
-CqueryDlg::CqueryDlg(wxWindow *parent, wxDB *pDb, char *tblName[], char *pWhereArg) : wxDialog (parent, QUERY_DIALOG, "Query", wxPoint(-1, -1), wxSize(480, 360))
+CqueryDlg::CqueryDlg(wxWindow *parent, wxDb *pDb, wxChar *tblName[],
+                     const wxString &pWhereArg) :
+    wxDialog (parent, QUERY_DIALOG, wxT("Query"), wxDefaultPosition, wxSize(480, 360))
 {
     wxBeginBusyCursor();
 
     colInf = 0;
     dbTable = 0;
     masterTableName = tblName[0];
 {
     wxBeginBusyCursor();
 
     colInf = 0;
     dbTable = 0;
     masterTableName = tblName[0];
-    widgetPtrsSet = FALSE;
+    widgetPtrsSet = false;
     pDB = pDb;
 
     // Initialize the WHERE clause from the string passed in
     pDB = pDb;
 
     // Initialize the WHERE clause from the string passed in
-    pWhere = pWhereArg;                                            // Save a pointer to the output buffer
-    if (strlen(pWhere) > DB_MAX_WHERE_CLAUSE_LEN)        // Check the length of the buffer passed in
+    pWhere = pWhereArg;                                           // Save a pointer to the output buffer
+    if (pWhere.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN)  // Check the length of the buffer passed in
     {
         wxString s;
     {
         wxString s;
-        s.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN+1);
-        wxMessageBox(s,"Error...",wxOK | wxICON_EXCLAMATION);
+        s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
+        wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
         Close();
         return;
     }
 
         Close();
         return;
     }
 
-    pQueryCol1Msg           = new wxStaticText(this, QUERY_DIALOG_COL_MSG,    "Column 1:",   wxPoint( 10,  10), wxSize( 69,  16), 0, "QueryCol1Msg");
-    pQueryCol1Choice        = new wxChoice(this, QUERY_DIALOG_COL_CHOICE,                    wxPoint( 10,  27), wxSize(250,  27), 0, 0, 0, wxDefaultValidator, "QueryCol1Choice");
-    pQueryNotMsg            = new wxStaticText(this, QUERY_DIALOG_NOT_MSG,    "NOT",         wxPoint(268,  10), wxSize( -1,  -1), 0, "QueryNotMsg");
-    pQueryNotCheck          = new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX, "",            wxPoint(275,  37), wxSize( 20,  20), 0, wxDefaultValidator, "QueryNotCheck");
+    pQueryCol1Msg           = new wxStaticText(this, QUERY_DIALOG_COL_MSG,    wxT("Column 1:"), wxPoint( 10,  10), wxSize( 69,  16), 0, wxT("QueryCol1Msg"));
+    pQueryCol1Choice        = new wxChoice(this, QUERY_DIALOG_COL_CHOICE,                       wxPoint( 10,  27), wxSize(250,  27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol1Choice"));
+    pQueryNotMsg            = new wxStaticText(this, QUERY_DIALOG_NOT_MSG,    wxT("NOT"),       wxPoint(268,  10), wxDefaultSize,    0, wxT("QueryNotMsg"));
+    pQueryNotCheck          = new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX, wxEmptyString,    wxPoint(275,  37), wxSize( 20,  20), 0, wxDefaultValidator, wxT("QueryNotCheck"));
 
     wxString choice_strings[9];
 
     wxString choice_strings[9];
-    choice_strings[0] = "=";
-    choice_strings[1] = "<";
-    choice_strings[2] = ">";
-    choice_strings[3] = "<=";
-    choice_strings[4] = ">=";
-    choice_strings[5] = "Begins";
-    choice_strings[6] = "Contains";
-    choice_strings[7] = "Like";
-    choice_strings[8] = "Between";
-
-    pQueryOperatorMsg       = new wxStaticText(this, QUERY_DIALOG_OP_MSG,       "Operator:",            wxPoint(305,  10), wxSize( -1,  -1), 0, "QueryOperatorMsg");
-    pQueryOperatorChoice    = new wxChoice(this, QUERY_DIALOG_OP_CHOICE,                                wxPoint(305,  27), wxSize( 80,  27), 9, choice_strings, 0, wxDefaultValidator, "QueryOperatorChoice");
-    pQueryCol2Msg           = new wxStaticText(this, QUERY_DIALOG_COL2_MSG,     "Column 2:",            wxPoint( 10,  65), wxSize( 69,  16), 0, "QueryCol2Msg");
-    pQueryCol2Choice        = new wxChoice(this, QUERY_DIALOG_COL2_CHOICE,                              wxPoint( 10,  82), wxSize(250,  27), 0, 0, 0, wxDefaultValidator, "QueryCol2Choice");
-    pQuerySqlWhereMsg       = new wxStaticText(this, QUERY_DIALOG_WHERE_MSG,    "SQL where clause:",    wxPoint( 10, 141), wxSize( -1,  -1), 0, "QuerySqlWhereMsg");
-    pQuerySqlWhereMtxt      = new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT,     "",                     wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE, wxDefaultValidator, "QuerySqlWhereMtxt");
-    pQueryAddBtn            = new wxButton(this, QUERY_DIALOG_ADD,              "&Add",                 wxPoint(406,  24), wxSize( 56,  26), 0, wxDefaultValidator, "QueryAddBtn");
-    pQueryAndBtn            = new wxButton(this, QUERY_DIALOG_AND,              "A&nd",                 wxPoint(406,  58), wxSize( 56,  26), 0, wxDefaultValidator, "QueryAndBtn");
-    pQueryOrBtn                = new wxButton(this, QUERY_DIALOG_OR,            "&Or",                  wxPoint(406,  92), wxSize( 56,  26), 0, wxDefaultValidator, "QueryOrBtn");
-    pQueryLParenBtn         = new wxButton(this, QUERY_DIALOG_LPAREN,           "(",                    wxPoint(406, 126), wxSize( 26,  26), 0, wxDefaultValidator, "QueryLParenBtn");
-    pQueryRParenBtn         = new wxButton(this, QUERY_DIALOG_RPAREN,           ")",                    wxPoint(436, 126), wxSize( 26,  26), 0, wxDefaultValidator, "QueryRParenBtn");
-    pQueryDoneBtn           = new wxButton(this, QUERY_DIALOG_DONE,             "&Done",                wxPoint(406, 185), wxSize( 56,  26), 0, wxDefaultValidator, "QueryDoneBtn");
-    pQueryClearBtn          = new wxButton(this, QUERY_DIALOG_CLEAR,            "C&lear",               wxPoint(406, 218), wxSize( 56,  26), 0, wxDefaultValidator, "QueryClearBtn");
-    pQueryCountBtn          = new wxButton(this, QUERY_DIALOG_COUNT,            "&Count",               wxPoint(406, 252), wxSize( 56,  26), 0, wxDefaultValidator, "QueryCountBtn");
-    pQueryValue1Msg         = new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG,   "Value:",               wxPoint(277,  66), wxSize( -1,  -1), 0, "QueryValue1Msg");
-    pQueryValue1Txt         = new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT,    "",                     wxPoint(277,  83), wxSize(108,  25), 0, wxDefaultValidator, "QueryValue1Txt");
-    pQueryValue2Msg         = new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG,   "AND",                  wxPoint(238, 126), wxSize( -1,  -1), 0, "QueryValue2Msg");
-    pQueryValue2Txt         = new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT,    "",                     wxPoint(277, 120), wxSize(108,  25), 0, wxDefaultValidator, "QueryValue2Txt");
-    pQueryHintGrp           = new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP,    "",                     wxPoint( 10, 291), wxSize(377,  40), 0, "QueryHintGrp");
-    pQueryHintMsg           = new wxStaticText(this, QUERY_DIALOG_HINT_MSG,     "",                     wxPoint( 16, 306), wxSize( -1,  -1), 0, "QueryHintMsg");
-
-    widgetPtrsSet = TRUE;
+    choice_strings[0] = wxT("=");
+    choice_strings[1] = wxT("<");
+    choice_strings[2] = wxT(">");
+    choice_strings[3] = wxT("<=");
+    choice_strings[4] = wxT(">=");
+    choice_strings[5] = wxT("Begins");
+    choice_strings[6] = wxT("Contains");
+    choice_strings[7] = wxT("Like");
+    choice_strings[8] = wxT("Between");
+
+    pQueryOperatorMsg       = new wxStaticText(this, QUERY_DIALOG_OP_MSG,       wxT("Operator:"),         wxPoint(305,  10), wxDefaultSize, 0, wxT("QueryOperatorMsg"));
+    pQueryOperatorChoice    = new wxChoice(this, QUERY_DIALOG_OP_CHOICE,                                  wxPoint(305,  27), wxSize( 80,  27), 9, choice_strings, 0, wxDefaultValidator, wxT("QueryOperatorChoice"));
+    pQueryCol2Msg           = new wxStaticText(this, QUERY_DIALOG_COL2_MSG,     wxT("Column 2:"),         wxPoint( 10,  65), wxSize( 69,  16), 0, wxT("QueryCol2Msg"));
+    pQueryCol2Choice        = new wxChoice(this, QUERY_DIALOG_COL2_CHOICE,                                wxPoint( 10,  82), wxSize(250,  27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol2Choice"));
+    pQuerySqlWhereMsg       = new wxStaticText(this, QUERY_DIALOG_WHERE_MSG,    wxT("SQL where clause:"), wxPoint( 10, 141), wxDefaultSize, 0, wxT("QuerySqlWhereMsg"));
+    pQuerySqlWhereMtxt      = new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT,     wxEmptyString,            wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE, wxDefaultValidator, wxT("QuerySqlWhereMtxt"));
+    pQueryAddBtn            = new wxButton(this, QUERY_DIALOG_ADD,              wxT("&Add"),              wxPoint(406,  24), wxSize( 56,  26), 0, wxDefaultValidator, wxT("QueryAddBtn"));
+    pQueryAndBtn            = new wxButton(this, QUERY_DIALOG_AND,              wxT("A&nd"),              wxPoint(406,  58), wxSize( 56,  26), 0, wxDefaultValidator, wxT("QueryAndBtn"));
+    pQueryOrBtn             = new wxButton(this, QUERY_DIALOG_OR,               wxT("&Or"),               wxPoint(406,  92), wxSize( 56,  26), 0, wxDefaultValidator, wxT("QueryOrBtn"));
+    pQueryLParenBtn         = new wxButton(this, QUERY_DIALOG_LPAREN,           wxT("("),                 wxPoint(406, 126), wxSize( 26,  26), 0, wxDefaultValidator, wxT("QueryLParenBtn"));
+    pQueryRParenBtn         = new wxButton(this, QUERY_DIALOG_RPAREN,           wxT(")"),                 wxPoint(436, 126), wxSize( 26,  26), 0, wxDefaultValidator, wxT("QueryRParenBtn"));
+    pQueryDoneBtn           = new wxButton(this, QUERY_DIALOG_DONE,             wxT("&Done"),             wxPoint(406, 185), wxSize( 56,  26), 0, wxDefaultValidator, wxT("QueryDoneBtn"));
+    pQueryClearBtn          = new wxButton(this, QUERY_DIALOG_CLEAR,            wxT("C&lear"),            wxPoint(406, 218), wxSize( 56,  26), 0, wxDefaultValidator, wxT("QueryClearBtn"));
+    pQueryCountBtn          = new wxButton(this, QUERY_DIALOG_COUNT,            wxT("&Count"),            wxPoint(406, 252), wxSize( 56,  26), 0, wxDefaultValidator, wxT("QueryCountBtn"));
+    pQueryValue1Msg         = new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG,   wxT("Value:"),            wxPoint(277,  66), wxDefaultSize, 0, wxT("QueryValue1Msg"));
+    pQueryValue1Txt         = new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT,    wxEmptyString,            wxPoint(277,  83), wxSize(108,  25), 0, wxDefaultValidator, wxT("QueryValue1Txt"));
+    pQueryValue2Msg         = new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG,   wxT("AND"),               wxPoint(238, 126), wxDefaultSize, 0, wxT("QueryValue2Msg"));
+    pQueryValue2Txt         = new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT,    wxEmptyString,            wxPoint(277, 120), wxSize(108,  25), 0, wxDefaultValidator, wxT("QueryValue2Txt"));
+    pQueryHintGrp           = new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP,    wxEmptyString,            wxPoint( 10, 291), wxSize(377,  40), 0, wxT("QueryHintGrp"));
+    pQueryHintMsg           = new wxStaticText(this, QUERY_DIALOG_HINT_MSG,     wxEmptyString,            wxPoint( 16, 306), wxDefaultSize, 0, wxT("QueryHintMsg"));
+
+    widgetPtrsSet = true;
     // Initialize the dialog
     wxString qualName;
     // Initialize the dialog
     wxString qualName;
-    pQueryCol2Choice->Append("VALUE -->");
+    pQueryCol2Choice->Append(wxT("VALUE -->"));
     colInf = pDB->GetColumns(tblName);
 
     if (!colInf)
     {
         wxEndBusyCursor();
         wxString tStr;
     colInf = pDB->GetColumns(tblName);
 
     if (!colInf)
     {
         wxEndBusyCursor();
         wxString tStr;
-        tStr  = "ODBC error during GetColumns()\n\n";
-        tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-        wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+        tStr = wxT("ODBC error during GetColumns()\n\n");
+        wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                     wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
         return;
     }
 
     int i;
         return;
     }
 
     int i;
-    for (i = 0; colInf[i].colName && strlen(colInf[i].colName); i++)
+    for (i = 0; colInf[i].colName && wxStrlen(colInf[i].colName); i++)
     {
         // If there is more than one table being queried, qualify
         // the column names with the table name prefix.
     {
         // If there is more than one table being queried, qualify
         // the column names with the table name prefix.
-        if (tblName[1] && strlen(tblName[1]))
+        if (tblName[1] && wxStrlen(tblName[1]))
         {
         {
-            qualName.Printf("%s.%s", colInf[i].tableName, colInf[i].colName);
+            qualName.Printf(wxT("%s.%s"), colInf[i].tableName, colInf[i].colName);
             pQueryCol1Choice->Append(qualName);
             pQueryCol2Choice->Append(qualName);
         }
             pQueryCol1Choice->Append(qualName);
             pQueryCol2Choice->Append(qualName);
         }
@@ -1644,19 +2465,18 @@ CqueryDlg::CqueryDlg(wxWindow *parent, wxDB *pDb, char *tblName[], char *pWhereA
     pQueryCol2Choice->SetSelection(0);
     pQueryOperatorChoice->SetSelection(0);
 
     pQueryCol2Choice->SetSelection(0);
     pQueryOperatorChoice->SetSelection(0);
 
-    pQueryValue2Msg->Show(FALSE);
-    pQueryValue2Txt->Show(FALSE);
+    pQueryValue2Msg->Show(false);
+    pQueryValue2Txt->Show(false);
 
     pQueryHintMsg->SetLabel(langQRY_EQ);
 
 
     pQueryHintMsg->SetLabel(langQRY_EQ);
 
-    pQuerySqlWhereMtxt->SetValue(pWhere);
+    pQuerySqlWhereMtxt->SetValue(pWhere.c_str());
 
     wxEndBusyCursor();
 
     // Display the dialog window
     Centre(wxBOTH);
     ShowModal();
 
     wxEndBusyCursor();
 
     // Display the dialog window
     Centre(wxBOTH);
     ShowModal();
-
 }  // CqueryDlg() constructor
 
 
 }  // CqueryDlg() constructor
 
 
@@ -1665,13 +2485,14 @@ CqueryDlg::~CqueryDlg()
 }  // CqueryDlg::~CqueryDlg() destructor
 
 
 }  // CqueryDlg::~CqueryDlg() destructor
 
 
-void CqueryDlg::OnButton( wxCommandEvent &event )
+void CqueryDlg::OnButton(wxCommandEvent &event)
 {
   wxWindow *win = (wxWindow*) event.GetEventObject();
   OnCommand( *win, event );
 {
   wxWindow *win = (wxWindow*) event.GetEventObject();
   OnCommand( *win, event );
-}
+}  // CqueryDlg::OnButton()
+
 
 
-void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
+void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& WXUNUSED(event))
 {
     // Widget pointers won't be set when the dialog is constructed.
     // Control is passed through this function once for each widget on
 {
     // Widget pointers won't be set when the dialog is constructed.
     // Control is passed through this function once for each widget on
@@ -1687,93 +2508,93 @@ void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
         // Set the help text
         switch((qryOp) pQueryOperatorChoice->GetSelection())
         {
         // Set the help text
         switch((qryOp) pQueryOperatorChoice->GetSelection())
         {
-        case qryOpEQ:
-            pQueryHintMsg->SetLabel(langQRY_EQ);
-            break;
-        case qryOpLT:
-            pQueryHintMsg->SetLabel(langQRY_LT);
-            break;
-        case qryOpGT:
-            pQueryHintMsg->SetLabel(langQRY_GT);
-            break;
-        case qryOpLE:
-            pQueryHintMsg->SetLabel(langQRY_LE);
-            break;
-        case qryOpGE:
-            pQueryHintMsg->SetLabel(langQRY_GE);
-            break;
-        case qryOpBEGINS:
-            pQueryHintMsg->SetLabel(langQRY_BEGINS);
-            break;
-        case qryOpCONTAINS:
-            pQueryHintMsg->SetLabel(langQRY_CONTAINS);
-            break;
-        case qryOpLIKE:
-            pQueryHintMsg->SetLabel(langQRY_LIKE);
-            break;
-        case qryOpBETWEEN:
-            pQueryHintMsg->SetLabel(langQRY_BETWEEN);
-            break;
+            case qryOpEQ:
+                pQueryHintMsg->SetLabel(langQRY_EQ);
+                break;
+            case qryOpLT:
+                pQueryHintMsg->SetLabel(langQRY_LT);
+                break;
+            case qryOpGT:
+                pQueryHintMsg->SetLabel(langQRY_GT);
+                break;
+            case qryOpLE:
+                pQueryHintMsg->SetLabel(langQRY_LE);
+                break;
+            case qryOpGE:
+                pQueryHintMsg->SetLabel(langQRY_GE);
+                break;
+            case qryOpBEGINS:
+                pQueryHintMsg->SetLabel(langQRY_BEGINS);
+                break;
+            case qryOpCONTAINS:
+                pQueryHintMsg->SetLabel(langQRY_CONTAINS);
+                break;
+            case qryOpLIKE:
+                pQueryHintMsg->SetLabel(langQRY_LIKE);
+                break;
+            case qryOpBETWEEN:
+                pQueryHintMsg->SetLabel(langQRY_BETWEEN);
+                break;
         }
 
         // Hide the value2 widget
         }
 
         // Hide the value2 widget
-        pQueryValue2Msg->Show(FALSE);  // BETWEEN will show this widget
-        pQueryValue2Txt->Show(FALSE);  // BETWEEN will show this widget
+        pQueryValue2Msg->Show(false);  // BETWEEN will show this widget
+        pQueryValue2Txt->Show(false);  // BETWEEN will show this widget
 
         // Disable the NOT operator for <, <=, >, >=
         switch((qryOp) pQueryOperatorChoice->GetSelection())
         {
 
         // Disable the NOT operator for <, <=, >, >=
         switch((qryOp) pQueryOperatorChoice->GetSelection())
         {
-        case qryOpLT:
-        case qryOpGT:
-        case qryOpLE:
-        case qryOpGE:
-            pQueryNotCheck->SetValue(0);
-            pQueryNotCheck->Enable(FALSE);
-            break;
-        default:
-            pQueryNotCheck->Enable(TRUE);
-            break;
+            case qryOpLT:
+            case qryOpGT:
+            case qryOpLE:
+            case qryOpGE:
+                pQueryNotCheck->SetValue(0);
+                pQueryNotCheck->Enable(false);
+                break;
+            default:
+                pQueryNotCheck->Enable(true);
+                break;
         }
 
         // Manipulate the dialog to handle the selected operator
         switch((qryOp) pQueryOperatorChoice->GetSelection())
         {
         }
 
         // Manipulate the dialog to handle the selected operator
         switch((qryOp) pQueryOperatorChoice->GetSelection())
         {
-        case qryOpEQ:
-        case qryOpLT:
-        case qryOpGT:
-        case qryOpLE:
-        case qryOpGE:
-            pQueryCol2Choice->Enable(TRUE);
-            if (pQueryCol2Choice->GetSelection())    // Column name is highlighted
-            {
-                pQueryValue1Msg->Show(FALSE);
-                pQueryValue1Txt->Show(FALSE);
-            }
-            else                                                // "Value" is highlighted
-            {
-                pQueryValue1Msg->Show(TRUE);
-                pQueryValue1Txt->Show(TRUE);
+            case qryOpEQ:
+            case qryOpLT:
+            case qryOpGT:
+            case qryOpLE:
+            case qryOpGE:
+                pQueryCol2Choice->Enable(true);
+                if (pQueryCol2Choice->GetSelection())    // Column name is highlighted
+                {
+                    pQueryValue1Msg->Show(false);
+                    pQueryValue1Txt->Show(false);
+                }
+                else                                                // "Value" is highlighted
+                {
+                    pQueryValue1Msg->Show(true);
+                    pQueryValue1Txt->Show(true);
+                    pQueryValue1Txt->SetFocus();
+                }
+                break;
+            case qryOpBEGINS:
+            case qryOpCONTAINS:
+            case qryOpLIKE:
+                pQueryCol2Choice->SetSelection(0);
+                pQueryCol2Choice->Enable(false);
+                pQueryValue1Msg->Show(true);
+                pQueryValue1Txt->Show(true);
                 pQueryValue1Txt->SetFocus();
                 pQueryValue1Txt->SetFocus();
-            }
-            break;
-        case qryOpBEGINS:
-        case qryOpCONTAINS:
-        case qryOpLIKE:
-            pQueryCol2Choice->SetSelection(0);
-            pQueryCol2Choice->Enable(FALSE);
-            pQueryValue1Msg->Show(TRUE);
-            pQueryValue1Txt->Show(TRUE);
-            pQueryValue1Txt->SetFocus();
-            break;
-        case qryOpBETWEEN:
-            pQueryCol2Choice->SetSelection(0);
-            pQueryCol2Choice->Enable(FALSE);
-            pQueryValue2Msg->Show(TRUE);
-            pQueryValue2Txt->Show(TRUE);
-            pQueryValue1Msg->Show(TRUE);
-            pQueryValue1Txt->Show(TRUE);
-            pQueryValue1Txt->SetFocus();
-            break;
+                break;
+            case qryOpBETWEEN:
+                pQueryCol2Choice->SetSelection(0);
+                pQueryCol2Choice->Enable(false);
+                pQueryValue2Msg->Show(true);
+                pQueryValue2Txt->Show(true);
+                pQueryValue1Msg->Show(true);
+                pQueryValue1Txt->Show(true);
+                pQueryValue1Txt->SetFocus();
+                break;
         }
 
         return;
         }
 
         return;
@@ -1785,17 +2606,16 @@ void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
     {
         if (pQueryCol2Choice->GetSelection())    // Column name is highlighted
         {
     {
         if (pQueryCol2Choice->GetSelection())    // Column name is highlighted
         {
-            pQueryValue1Msg->Show(FALSE);
-            pQueryValue1Txt->Show(FALSE);
+            pQueryValue1Msg->Show(false);
+            pQueryValue1Txt->Show(false);
         }
         else                                                // "Value" is highlighted
         {
         }
         else                                                // "Value" is highlighted
         {
-            pQueryValue1Msg->Show(TRUE);
-            pQueryValue1Txt->Show(TRUE);
+            pQueryValue1Msg->Show(true);
+            pQueryValue1Txt->Show(true);
             pQueryValue1Txt->SetFocus();
         }
         return;
             pQueryValue1Txt->SetFocus();
         }
         return;
-
     }  // Column 2 choice
 
     // Add button
     }  // Column 2 choice
 
     // Add button
@@ -1803,71 +2623,65 @@ void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
     {
         ProcessAddBtn();
         return;
     {
         ProcessAddBtn();
         return;
-
     }  // Add button
 
     // And button
     if (widgetName == pQueryAndBtn->GetName())
     {
     }  // Add button
 
     // And button
     if (widgetName == pQueryAndBtn->GetName())
     {
-        AppendToWhere(" AND\n");
+        AppendToWhere(wxT(" AND\n"));
         return;
         return;
-
     }  // And button
 
     // Or button
     if (widgetName == pQueryOrBtn->GetName())
     {
     }  // And button
 
     // Or button
     if (widgetName == pQueryOrBtn->GetName())
     {
-        AppendToWhere(" OR\n");
+        AppendToWhere(wxT(" OR\n"));
         return;
         return;
-
     }  // Or button
 
     // Left Paren button
     if (widgetName == pQueryLParenBtn->GetName())
     {
     }  // Or button
 
     // Left Paren button
     if (widgetName == pQueryLParenBtn->GetName())
     {
-        AppendToWhere("(");
+        AppendToWhere(wxT("("));
         return;
         return;
-
     }  // Left Paren button
 
     // Right paren button
     if (widgetName == pQueryRParenBtn->GetName())
     {
     }  // Left Paren button
 
     // Right paren button
     if (widgetName == pQueryRParenBtn->GetName())
     {
-        AppendToWhere(")");
+        AppendToWhere(wxT(")"));
         return;
         return;
-
     }  // Right Paren button
 
     // Done button
     if (widgetName == pQueryDoneBtn->GetName())
     {
         // Be sure the where clause will not overflow the output buffer
     }  // Right Paren button
 
     // Done button
     if (widgetName == pQueryDoneBtn->GetName())
     {
         // Be sure the where clause will not overflow the output buffer
-        if (strlen(pQuerySqlWhereMtxt->GetValue()) > DB_MAX_WHERE_CLAUSE_LEN)
+        if (wxStrlen(pQuerySqlWhereMtxt->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN)
         {
             wxString s;
         {
             wxString s;
-            s.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN+1);
-            wxMessageBox(s,"Error...",wxOK | wxICON_EXCLAMATION);
+            s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
+            wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
             return;
         }
         // Validate the where clause for things such as matching parens
         if (!ValidateWhereClause())
             return;
         // Copy the where clause to the output buffer and exit
             return;
         }
         // Validate the where clause for things such as matching parens
         if (!ValidateWhereClause())
             return;
         // Copy the where clause to the output buffer and exit
-        strcpy(pWhere, pQuerySqlWhereMtxt->GetValue());
+        pWhere = pQuerySqlWhereMtxt->GetValue();
         Close();
         return;
         Close();
         return;
-
     }  // Done button
 
     // Clear button
     if (widgetName == pQueryClearBtn->GetName())
     {
     }  // Done button
 
     // Clear button
     if (widgetName == pQueryClearBtn->GetName())
     {
-        bool Ok = (wxMessageBox("Are you sure you wish to clear the Query?","Confirm",wxYES_NO|wxICON_QUESTION) == wxYES);
+        bool Ok = (wxMessageBox(wxT("Are you sure you wish to clear the Query?"), wxT("Confirm"), wxYES_NO|wxICON_QUESTION) == wxYES);
 
         if (Ok)
 
         if (Ok)
-            pQuerySqlWhereMtxt->SetValue("");
-        return;
+            pQuerySqlWhereMtxt->SetValue(wxEmptyString);
 
 
+        return;
     }  // Clear button
 
     // Count button
     }  // Clear button
 
     // Count button
@@ -1877,43 +2691,34 @@ void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
         ProcessCountBtn();
         wxEndBusyCursor();
         return;
         ProcessCountBtn();
         wxEndBusyCursor();
         return;
-
     }  // Count button
 
 }  // CqueryDlg::OnCommand
 
 
     }  // Count button
 
 }  // CqueryDlg::OnCommand
 
 
-void CqueryDlg::OnCloseWindow(wxCloseEvent& event)
+void CqueryDlg::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
 {
     // Clean up
 {
     // Clean up
-    if (colInf)
-    {
-        delete [] colInf;
-        colInf = 0;
-    }
+    wxDELETEA(colInf);
 
 
-    if (dbTable)
-    {
-        delete dbTable;
-        dbTable = 0;
-    }
+    wxDELETE(dbTable);
 
     GetParent()->SetFocus();
     while (wxIsBusy())
         wxEndBusyCursor();
 
 
     GetParent()->SetFocus();
     while (wxIsBusy())
         wxEndBusyCursor();
 
-       Show(FALSE);
-    this->Destroy();
+    Show(false);
+    SetReturnCode(1);  // added so BoundsChecker would not report use of uninitialized variable
 
 
+    this->Destroy();
 }  // CqueryDlg::OnCloseWindow()
 
 
 }  // CqueryDlg::OnCloseWindow()
 
 
-void CqueryDlg::AppendToWhere(char *s)
+void CqueryDlg::AppendToWhere(wxChar *s)
 {
 {
-        wxString whereStr = pQuerySqlWhereMtxt->GetValue();
-        whereStr += s;
-        pQuerySqlWhereMtxt->SetValue(whereStr);
-
+    wxString whereStr = pQuerySqlWhereMtxt->GetValue();
+    whereStr += s;
+    pQuerySqlWhereMtxt->SetValue(whereStr);
 }  // CqueryDlg::AppendToWhere()
 
 
 }  // CqueryDlg::AppendToWhere()
 
 
@@ -1925,7 +2730,7 @@ void CqueryDlg::ProcessAddBtn()
     if (pQueryCol2Choice->GetSelection() == 0)            // "Value" is selected
     {
         // Verify that value 1 is filled in
     if (pQueryCol2Choice->GetSelection() == 0)            // "Value" is selected
     {
         // Verify that value 1 is filled in
-        if (strlen(pQueryValue1Txt->GetValue()) == 0)
+        if (wxStrlen(pQueryValue1Txt->GetValue()) == 0)
         {
             wxBell();
             pQueryValue1Txt->SetFocus();
         {
             wxBell();
             pQueryValue1Txt->SetFocus();
@@ -1933,7 +2738,7 @@ void CqueryDlg::ProcessAddBtn()
         }
         // For the BETWEEN operator, value 2 must be filled in as well
         if (oper == qryOpBETWEEN &&
         }
         // For the BETWEEN operator, value 2 must be filled in as well
         if (oper == qryOpBETWEEN &&
-             strlen(pQueryValue2Txt->GetValue()) == 0)
+             wxStrlen(pQueryValue2Txt->GetValue()) == 0)
         {
             wxBell();
             pQueryValue2Txt->SetFocus();
         {
             wxBell();
             pQueryValue2Txt->SetFocus();
@@ -1943,77 +2748,77 @@ void CqueryDlg::ProcessAddBtn()
 
     // Build the expression and append it to the where clause window
     wxString s = pQueryCol1Choice->GetStringSelection();
 
     // Build the expression and append it to the where clause window
     wxString s = pQueryCol1Choice->GetStringSelection();
-    
+
     if (pQueryNotCheck->GetValue() && (oper != qryOpEQ))
     if (pQueryNotCheck->GetValue() && (oper != qryOpEQ))
-        s += " NOT";
-    
+        s += wxT(" NOT");
+
     switch(oper)
     {
     case qryOpEQ:
         if (pQueryNotCheck->GetValue())    // NOT box is checked
     switch(oper)
     {
     case qryOpEQ:
         if (pQueryNotCheck->GetValue())    // NOT box is checked
-            s += " <>";
+            s += wxT(" <>");
         else
         else
-            s += " =";
+            s += wxT(" =");
         break;
     case qryOpLT:
         break;
     case qryOpLT:
-        s += " <";
+        s += wxT(" <");
         break;
     case qryOpGT:
         break;
     case qryOpGT:
-        s += " >";
+        s += wxT(" >");
         break;
     case qryOpLE:
         break;
     case qryOpLE:
-        s += " <=";
+        s += wxT(" <=");
         break;
     case qryOpGE:
         break;
     case qryOpGE:
-        s += " >=";
+        s += wxT(" >=");
         break;
     case qryOpBEGINS:
     case qryOpCONTAINS:
     case qryOpLIKE:
         break;
     case qryOpBEGINS:
     case qryOpCONTAINS:
     case qryOpLIKE:
-        s += " LIKE";
+        s += wxT(" LIKE");
         break;
     case qryOpBETWEEN:
         break;
     case qryOpBETWEEN:
-        s += " BETWEEN";
+        s += wxT(" BETWEEN");
         break;
     }
 
         break;
     }
 
-    s += " ";
+    s += wxT(" ");
 
     int col1Idx = pQueryCol1Choice->GetSelection();
 
 
     int col1Idx = pQueryCol1Choice->GetSelection();
 
-    bool quote = FALSE;
+    bool quote = false;
     if (colInf[col1Idx].sqlDataType == SQL_VARCHAR  ||
         oper == qryOpBEGINS                         ||
         oper == qryOpCONTAINS                       ||
         oper == qryOpLIKE)
     if (colInf[col1Idx].sqlDataType == SQL_VARCHAR  ||
         oper == qryOpBEGINS                         ||
         oper == qryOpCONTAINS                       ||
         oper == qryOpLIKE)
-        quote = TRUE;
+        quote = true;
 
     if (pQueryCol2Choice->GetSelection())    // Column name
         s += pQueryCol2Choice->GetStringSelection();
     else  // Column 2 is a "value"
     {
         if (quote)
 
     if (pQueryCol2Choice->GetSelection())    // Column name
         s += pQueryCol2Choice->GetStringSelection();
     else  // Column 2 is a "value"
     {
         if (quote)
-            s += "'";
+            s += wxT("'");
         if (oper == qryOpCONTAINS)
         if (oper == qryOpCONTAINS)
-            s += "%";
+            s += wxT("%");
         s += pQueryValue1Txt->GetValue();
         if (oper == qryOpCONTAINS || oper == qryOpBEGINS)
         s += pQueryValue1Txt->GetValue();
         if (oper == qryOpCONTAINS || oper == qryOpBEGINS)
-            s += "%";
+            s += wxT("%");
         if (quote)
         if (quote)
-            s += "'";
+            s += wxT("'");
     }
 
     if (oper == qryOpBETWEEN)
     {
     }
 
     if (oper == qryOpBETWEEN)
     {
-        s += " AND ";
+        s += wxT(" AND ");
         if (quote)
         if (quote)
-            s += "'";
+            s += wxT("'");
         s += pQueryValue2Txt->GetValue();
         if (quote)
         s += pQueryValue2Txt->GetValue();
         if (quote)
-            s += "'";
+            s += wxT("'");
     }
 
     }
 
-    AppendToWhere((char*) (const char*) s);
+    AppendToWhere((wxChar*) (const wxChar*) s);
 
 }  // CqueryDlg::ProcessAddBtn()
 
 
 }  // CqueryDlg::ProcessAddBtn()
 
@@ -2023,45 +2828,49 @@ void CqueryDlg::ProcessCountBtn()
     if (!ValidateWhereClause())
         return;
 
     if (!ValidateWhereClause())
         return;
 
-    if (dbTable == 0)  // wxTable object needs to be created and opened
+    if (!dbTable)  // wxDbTable object needs to be created and opened
     {
     {
-        if (!(dbTable = new wxTable(pDB, masterTableName, 0, NULL, !QUERY_ONLY, DbConnectInf.defaultDir)))
+        dbTable = new wxDbTable(pDB, masterTableName, 0, (const wxString &)wxEmptyString,
+                                !wxDB_QUERY_ONLY,
+                                wxGetApp().DbConnectInf->GetDefaultDir());
+        if (!dbTable)
         {
         {
-            wxMessageBox("Memory allocation failed creating a wxTable object.","Error...",wxOK | wxICON_EXCLAMATION);
+            wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
             return;
         }
         if (!dbTable->Open())
         {
             wxString tStr;
             return;
         }
         if (!dbTable->Open())
         {
             wxString tStr;
-            tStr  = "ODBC error during Open()\n\n";
-            tStr += GetExtendedDBErrorMsg(__FILE__,__LINE__);
-            wxMessageBox(tStr,"ODBC Error...",wxOK | wxICON_EXCLAMATION);
+            tStr = wxT("ODBC error during Open()\n\n");
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
             return;
         }
     }
 
     // Count() with WHERE clause
             return;
         }
     }
 
     // Count() with WHERE clause
-        wxString whereStr;
+    wxString whereStr;
 
     whereStr = pQuerySqlWhereMtxt->GetValue();
 
     whereStr = pQuerySqlWhereMtxt->GetValue();
-        dbTable->where = (char *)whereStr.GetData();
+    dbTable->SetWhereClause(whereStr.c_str());
+
     ULONG whereCnt = dbTable->Count();
 
     // Count() of all records in the table
     ULONG whereCnt = dbTable->Count();
 
     // Count() of all records in the table
-    dbTable->where = 0;
+    dbTable->SetWhereClause(wxEmptyString);
     ULONG totalCnt = dbTable->Count();
 
     if (whereCnt > 0 || totalCnt == 0)
     {
         wxString tStr;
     ULONG totalCnt = dbTable->Count();
 
     if (whereCnt > 0 || totalCnt == 0)
     {
         wxString tStr;
-        tStr.Printf("%lu of %lu records match the query criteria.",whereCnt,totalCnt);
-        wxMessageBox(tStr,"Notice...",wxOK | wxICON_INFORMATION);
+        tStr.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt,totalCnt);
+        wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
     }
     else
     {
         wxString tStr;
     }
     else
     {
         wxString tStr;
-        tStr.Printf("%lu of %lu records match the query criteria.\n\nEither the criteria entered produced a result set\nwith no records, or there was a syntactical error\nin the clause you entered.\n\nPress the details button to see if any database errors were reported.",whereCnt,totalCnt);
-        wxMessageBox(tStr,"Notice...",wxOK | wxICON_INFORMATION);
+        tStr.Printf(wxT("%lu of %lu records match the query criteria.\n\nEither the criteria entered produced a result set\nwith no records, or there was a syntactical error\nin the clause you entered.\n\nPress the details button to see if any database errors were reported."),whereCnt,totalCnt);
+        wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
     }
 
     // After a wxMessageBox, the focus does not necessarily return to the
     }
 
     // After a wxMessageBox, the focus does not necessarily return to the
@@ -2076,42 +2885,549 @@ bool CqueryDlg::ValidateWhereClause()
 {
     wxString where = pQuerySqlWhereMtxt->GetValue();
 
 {
     wxString where = pQuerySqlWhereMtxt->GetValue();
 
-    if (where.Freq('(') != where.Freq(')'))
+    if (where.Freq(wxT('(')) != where.Freq(wxT(')')))
     {
     {
-        wxMessageBox("There are mismatched parenthesis in the constructed where clause","Error...",wxOK | wxICON_EXCLAMATION);
-        return(FALSE);
+        wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
+        return(false);
     }
     // After a wxMessageBox, the focus does not necessarily return to the
     // window which was the focus when the message box popped up, so return
     // focus to the Query dialog for certain
     SetFocus();
 
     }
     // After a wxMessageBox, the focus does not necessarily return to the
     // window which was the focus when the message box popped up, so return
     // focus to the Query dialog for certain
     SetFocus();
 
-    return(TRUE);
+    return(true);
 
 }  // CqueryDlg::ValidateWhereClause()
 
 
 }  // CqueryDlg::ValidateWhereClause()
 
+#ifdef wxODBC_BLOB_SUPPORT
+
+BEGIN_EVENT_TABLE(CimageDlg, wxDialog)
+    EVT_CLOSE(CimageDlg::OnCloseWindow)
+END_EVENT_TABLE()
+
+CimageDlg::CimageDlg(wxWindow *parent, wxChar *pImageData, off_t iSize)
+: wxDialog(parent, IMAGE_DIALOG, wxT("BLOB Image"), wxDefaultPosition, wxDefaultSize),
+m_pDisplayBmp(NULL),
+m_pBmp(NULL),
+m_pImage(NULL)
+{
+    wxMemoryInputStream inStream(pImageData, iSize);
+
+    if(inStream.IsOk())
+    {
+        m_pImage = new wxImage(inStream, wxBITMAP_TYPE_ANY);
+
+        if(m_pImage->Ok())
+        {
+            m_pBmp = new wxBitmap(*m_pImage);
+            m_pDisplayBmp = new wxStaticBitmap(this, IMAGE_DIALOG_STATIC_BMP, *m_pBmp, wxPoint(5,5), wxDefaultSize);
+
+            SetSize(m_pBmp->GetWidth() + 10, m_pBmp->GetHeight() + 30);
+        }
+    }
+}
+
+CimageDlg::~CimageDlg()
+{
+    if(m_pImage)
+        delete m_pImage;
+
+    if(m_pBmp)
+        delete m_pBmp;
+
+    if(m_pDisplayBmp)
+        delete m_pDisplayBmp;
+}
+
+void CimageDlg::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
+{
+    GetParent()->SetFocus();
+
+    Show(false);
+
+    this->Destroy();
+}
+
+#endif
+
+void DisplayDbDiagnostics(wxDb *pDb)
+{
+    wxString s, t;
+    bool comma;
+
+    s =  wxT("Diagnostics Output\n");
+    s += langDBINF_DB_NAME;
+    s += pDb->dbInf.dbmsName;
+    s += wxT("\n");
+
+    s += langDBINF_DB_VER;
+    s += pDb->dbInf.dbmsVer;
+    s += wxT("\n");
+
+    s += langDBINF_DRIVER_NAME;
+    s += pDb->dbInf.driverName;
+    s += wxT("\n");
+
+    s += langDBINF_DRIVER_ODBC_VER;
+    s += pDb->dbInf.odbcVer;
+    s += wxT("\n");
+
+    s += langDBINF_DRIVER_MGR_ODBC_VER;
+    s += pDb->dbInf.drvMgrOdbcVer;
+    s += wxT("\n");
+
+    s += langDBINF_DRIVER_VER;
+    s += pDb->dbInf.driverVer;
+    s += wxT("\n");
+
+    s += langDBINF_SERVER_NAME;
+    s += pDb->dbInf.serverName;
+    s += wxT("\n");
+
+    s += langDBINF_FILENAME;
+    s += pDb->dbInf.databaseName;
+    s += wxT("\n");
+
+    s += langDBINF_OUTER_JOINS;
+    s += pDb->dbInf.outerJoins;
+    s += wxT("\n");
+
+    s += langDBINF_STORED_PROC;
+    s += pDb->dbInf.procedureSupport;
+    s += wxT("\n");
+
+    if (pDb->dbInf.maxConnections)
+        t.sprintf(wxT("%s%d\n"), langDBINF_MAX_HDBC, pDb->dbInf.maxConnections);
+    else
+        t.sprintf(wxT("%s%s\n"), langDBINF_MAX_HDBC, langDBINF_UNLIMITED);
+    s += t;
+
+    if (pDb->dbInf.maxStmts)
+        t.sprintf(wxT("%s%d\n"), langDBINF_MAX_HSTMT, pDb->dbInf.maxStmts);
+    else
+        t.sprintf(wxT("%s%s\n"), langDBINF_MAX_HSTMT, langDBINF_UNLIMITED);
+    s += t;
+
+    s += langDBINF_API_LVL;
+    switch(pDb->dbInf.apiConfLvl)
+    {
+        case SQL_OAC_NONE:  s += langDBINF_NONE;        break;
+        case SQL_OAC_LEVEL1:    s += langDBINF_LEVEL1;  break;
+        case SQL_OAC_LEVEL2:    s += langDBINF_LEVEL2;  break;
+    }
+    s += wxT("\n");
+
+    s += langDBINF_CLI_LVL;
+    switch(pDb->dbInf.cliConfLvl)
+    {
+        case SQL_OSCC_NOT_COMPLIANT:    s += langDBINF_NOT_COMPLIANT;   break;
+        case SQL_OSCC_COMPLIANT:        s += langDBINF_COMPLIANT;           break;
+    }
+    s += wxT("\n");
+
+    s += langDBINF_SQL_LVL;
+    switch(pDb->dbInf.sqlConfLvl)
+    {
+        case SQL_OSC_MINIMUM:   s += langDBINF_MIN_GRAMMAR; break;
+        case SQL_OSC_CORE:      s += langDBINF_CORE_GRAMMAR;    break;
+        case SQL_OSC_EXTENDED:  s += langDBINF_EXT_GRAMMAR; break;
+    }
+    s += wxT("\n");
+
+    s += langDBINF_COMMIT_BEHAVIOR;
+    switch(pDb->dbInf.cursorCommitBehavior)
+    {
+        case SQL_CB_DELETE:     s += langDBINF_DELETE_CURSORS;  break;
+        case SQL_CB_CLOSE:      s += langDBINF_CLOSE_CURSORS;       break;
+        case SQL_CB_PRESERVE:   s += langDBINF_PRESERVE_CURSORS;    break;
+    }
+    s += wxT("\n");
+
+    s += langDBINF_ROLLBACK_BEHAVIOR;
+    switch(pDb->dbInf.cursorRollbackBehavior)
+    {
+        case SQL_CB_DELETE:     s += langDBINF_DELETE_CURSORS;  break;
+        case SQL_CB_CLOSE:      s += langDBINF_CLOSE_CURSORS;       break;
+        case SQL_CB_PRESERVE:   s += langDBINF_PRESERVE_CURSORS;    break;
+    }
+    s += wxT("\n");
+
+    s += langDBINF_SUPP_NOT_NULL;
+    switch(pDb->dbInf.supportNotNullClause)
+    {
+        case SQL_NNC_NULL:      s += langNO;    break;
+        case SQL_NNC_NON_NULL:  s += langYES;   break;
+    }
+    s += wxT("\n");
+
+    s += langDBINF_SUPP_IEF;
+    s += pDb->dbInf.supportIEF;
+    s += wxT("\n");
+
+    // DEFAULT setting for "Transaction Isolation Level"
+    s += langDBINF_TXN_ISOLATION;
+    switch(pDb->dbInf.txnIsolation)
+    {
+        case SQL_TXN_READ_UNCOMMITTED:  s += langDBINF_READ_UNCOMMITTED;    break;
+        case SQL_TXN_READ_COMMITTED:        s += langDBINF_READ_COMMITTED;  break;
+        case SQL_TXN_REPEATABLE_READ:       s += langDBINF_REPEATABLE_READ; break;
+        case SQL_TXN_SERIALIZABLE:          s += langDBINF_SERIALIZABLE;        break;
+#ifdef ODBC_V20
+        case SQL_TXN_VERSIONING:            s += langDBINF_VERSIONING;          break;
+#endif
+    }
+    s += wxT("\n");
+
+    // CURRENT setting for "Transaction Isolation Level"
+    long txnIsoLvl;
+    s += langDBINF_TXN_ISOLATION_CURR;
+    if (SQLGetConnectOption(pDb->GetHDBC(),SQL_TXN_ISOLATION,&txnIsoLvl) == SQL_SUCCESS)
+    {
+        switch(txnIsoLvl)
+        {
+            case SQL_TXN_READ_UNCOMMITTED:  s += langDBINF_READ_UNCOMMITTED;    break;
+            case SQL_TXN_READ_COMMITTED:        s += langDBINF_READ_COMMITTED;  break;
+            case SQL_TXN_REPEATABLE_READ:       s += langDBINF_REPEATABLE_READ; break;
+            case SQL_TXN_SERIALIZABLE:          s += langDBINF_SERIALIZABLE;        break;
+#ifdef ODBC_V20
+            case SQL_TXN_VERSIONING:            s += langDBINF_VERSIONING;          break;
+#endif
+        }
+    }
+    s += wxT("\n");
+
+#ifdef __VMS__
+#pragma message disable incboodep
+#endif
+    comma = false;
+    s += langDBINF_TXN_ISOLATION_OPTS;
+    if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_UNCOMMITTED)
+        {s += langDBINF_READ_UNCOMMITTED; comma++;}
+    if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_COMMITTED)
+        {if (comma++) s += wxT(", "); s += langDBINF_READ_COMMITTED;}
+    if (pDb->dbInf.txnIsolationOptions & SQL_TXN_REPEATABLE_READ)
+        {if (comma++) s += wxT(", "); s += langDBINF_REPEATABLE_READ;}
+    if (pDb->dbInf.txnIsolationOptions & SQL_TXN_SERIALIZABLE)
+        {if (comma++) s += wxT(", "); s += langDBINF_SERIALIZABLE;}
+#ifdef ODBC_V20
+    if (pDb->dbInf.txnIsolationOptions & SQL_TXN_VERSIONING)
+        {if (comma++) s += wxT(", "); s += langDBINF_VERSIONING;}
+#endif
+    s += wxT("\n");
+
+    comma = false;
+    s += langDBINF_FETCH_DIRS;
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_NEXT)
+        {s += langDBINF_NEXT; comma++;}
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_PRIOR)
+        {if (comma++) s += wxT(", "); s += langDBINF_PREV;}
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_FIRST)
+        {if (comma++) s += wxT(", "); s += langDBINF_FIRST;}
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_LAST)
+        {if (comma++) s += wxT(", "); s += langDBINF_LAST;}
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_ABSOLUTE)
+        {if (comma++) s += wxT(", "); s += langDBINF_ABSOLUTE;}
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RELATIVE)
+        {if (comma++) s += wxT(", "); s += langDBINF_RELATIVE;}
+#ifdef ODBC_V20
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RESUME)
+        {if (comma++) s += wxT(", "); s += langDBINF_RESUME;}
+#endif
+    if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_BOOKMARK)
+        {if (comma++) s += wxT(", "); s += langDBINF_BOOKMARK;}
+    s += wxT("\n");
+
+    comma = false;
+    s += langDBINF_LOCK_TYPES;
+    if (pDb->dbInf.lockTypes & SQL_LCK_NO_CHANGE)
+        {s += langDBINF_NO_CHANGE; comma++;}
+    if (pDb->dbInf.lockTypes & SQL_LCK_EXCLUSIVE)
+        {if (comma++) s += wxT(", "); s += langDBINF_EXCLUSIVE;}
+    if (pDb->dbInf.lockTypes & SQL_LCK_UNLOCK)
+        {if (comma++) s += wxT(", "); s += langDBINF_UNLOCK;}
+    s += wxT("\n");
+
+    comma = false;
+    s += langDBINF_POS_OPERS;
+    if (pDb->dbInf.posOperations & SQL_POS_POSITION)
+        {s += langDBINF_POSITION; comma++;}
+    if (pDb->dbInf.posOperations & SQL_POS_REFRESH)
+        {if (comma++) s += wxT(", "); s += langDBINF_REFRESH;}
+    if (pDb->dbInf.posOperations & SQL_POS_UPDATE)
+        {if (comma++) s += wxT(", "); s += langDBINF_UPD;}
+    if (pDb->dbInf.posOperations & SQL_POS_DELETE)
+        {if (comma++) s += wxT(", "); s += langDBINF_DEL;}
+    if (pDb->dbInf.posOperations & SQL_POS_ADD)
+        {if (comma++) s += wxT(", "); s += langDBINF_ADD;}
+    s += wxT("\n");
+
+    comma = false;
+    s += langDBINF_POS_STMTS;
+    if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_DELETE)
+        {s += langDBINF_POS_DEL; comma++;}
+    if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_UPDATE)
+        {if (comma++) s += wxT(", "); s += langDBINF_POS_UPD;}
+    if (pDb->dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
+        {if (comma++) s += wxT(", "); s += langDBINF_SELECT_FOR_UPD;}
+    s += wxT("\n");
+
+    comma = false;
+    s += langDBINF_SCROLL_CONCURR;
+    if (pDb->dbInf.scrollConcurrency & SQL_SCCO_READ_ONLY)
+        {s += langDBINF_READ_ONLY; comma++;}
+    if (pDb->dbInf.scrollConcurrency & SQL_SCCO_LOCK)
+        {if (comma++) s += wxT(", "); s += langDBINF_LOCK;}
+    if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_ROWVER)
+        {if (comma++) s += wxT(", "); s += langDBINF_OPT_ROWVER;}
+    if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_VALUES)
+        {if (comma++) s += wxT(", "); s += langDBINF_OPT_VALUES;}
+    s += wxT("\n");
+
+    comma = false;
+    s += langDBINF_SCROLL_OPTS;
+    if (pDb->dbInf.scrollOptions & SQL_SO_FORWARD_ONLY)
+        {s += langDBINF_FWD_ONLY; comma++;}
+    if (pDb->dbInf.scrollOptions & SQL_SO_STATIC)
+        {if (comma++) s += wxT(", "); s += langDBINF_STATIC;}
+    if (pDb->dbInf.scrollOptions & SQL_SO_KEYSET_DRIVEN)
+        {if (comma++) s += wxT(", "); s += langDBINF_KEYSET_DRIVEN;}
+    if (pDb->dbInf.scrollOptions & SQL_SO_DYNAMIC)
+        {if (comma++) s += wxT(", "); s += langDBINF_DYNAMIC;}
+    if (pDb->dbInf.scrollOptions & SQL_SO_MIXED)
+        {if (comma++) s += wxT(", "); s += langDBINF_MIXED;}
+    s += wxT("\n");
+
+    comma = false;
+    s += langDBINF_STATIC_SENS;
+    if (pDb->dbInf.staticSensitivity & SQL_SS_ADDITIONS)
+        {s += langDBINF_ADDITIONS; comma++;}
+    if (pDb->dbInf.staticSensitivity & SQL_SS_DELETIONS)
+        {if (comma++) s += wxT(", "); s += langDBINF_DELETIONS;}
+    if (pDb->dbInf.staticSensitivity & SQL_SS_UPDATES)
+        {if (comma++) s += wxT(", "); s += langDBINF_UPDATES;}
+    s += wxT("\n");
+#ifdef __VMS__
+#pragma message enable incboodep
+#endif
+
+
+    s += langDBINF_TXN_CAPABLE;
+    switch(pDb->dbInf.txnCapable)
+    {
+        case SQL_TC_NONE:           s += langNO;                        break;
+        case SQL_TC_DML:            s += langDBINF_DML_ONLY;        break;
+        case SQL_TC_DDL_COMMIT:     s += langDBINF_DDL_COMMIT;      break;
+        case SQL_TC_DDL_IGNORE:     s += langDBINF_DDL_IGNORE;      break;
+        case SQL_TC_ALL:            s += langDBINF_DDL_AND_DML; break;
+    }
+    s += wxT("\n");
+
+    t.sprintf(wxT("%s%lu\n"), langDBINF_LOGIN_TIMEOUT, pDb->dbInf.loginTimeout);
+    s += t;
+
+    // Oracle specific information
+    if (pDb->Dbms() == dbmsORACLE)
+    {
+        s += wxT("\n");
+        s += langDBINF_ORACLE_BANNER;
+        s += wxT("\n");
+
+        // Oracle cache hit ratio
+        SDWORD cb;
+        ULONG dbBlockGets;
+        pDb->ExecSql(wxT("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'"));
+        pDb->GetNext();
+        if (pDb->GetData(1, SQL_C_ULONG, &dbBlockGets, 0, &cb))
+        {
+            t.sprintf(wxT("%s: %lu\n"), langDBINF_DB_BLOCK_GETS, dbBlockGets);
+            s += t;
+        }
+
+        ULONG consistentGets;
+        pDb->ExecSql(wxT("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'"));
+        pDb->GetNext();
+        if (pDb->GetData(1, SQL_C_ULONG, &consistentGets, 0, &cb))
+        {
+            t.sprintf(wxT("%s: %lu\n"), langDBINF_CONSISTENT_GETS, consistentGets);
+            s += t;
+        }
+
+        ULONG physReads;
+        pDb->ExecSql(wxT("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'"));
+        pDb->GetNext();
+        if (pDb->GetData(1, SQL_C_ULONG, &physReads, 0, &cb))
+        {
+            t.sprintf(wxT("%s: %lu\n"), langDBINF_PHYSICAL_READS, physReads);
+            s += t;
+        }
+
+        ULONG hitRatio = (ULONG)((1.00 - ((float)physReads / (float)(dbBlockGets + consistentGets))) * 100.00);
+        t.sprintf(wxT("*** %s: %lu%%\n"), langDBINF_CACHE_HIT_RATIO, hitRatio);
+        s += t;
+
+        // Tablespace information
+        s += wxT("\n");
+        s += langDBINF_TABLESPACE_IO;
+        s += wxT("\n");
+        ULONG physWrites;
+        char tablespaceName[256+1];
+        pDb->ExecSql(wxT("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#"));
+        while (pDb->GetNext())
+        {
+            pDb->GetData(1, SQL_C_WXCHAR, tablespaceName, 256, &cb);
+            pDb->GetData(2, SQL_C_ULONG, &physReads,      0,   &cb);
+            pDb->GetData(3, SQL_C_ULONG, &physWrites,     0,   &cb);
+            t.sprintf(wxT("%s\n\t%s: %lu\t%s: %lu\n"), tablespaceName,
+                langDBINF_PHYSICAL_READS, physReads, langDBINF_PHYSICAL_WRITES, physWrites);
+            s += t;
+        }
+
+        s += wxT("\n");
+    }
+
+    s += wxT("End of Diagnostics\n");
+    wxLogMessage(s);
+
+}  // DisplayDbDiagnostics()
+
+#if wxUSE_GRID
+
+BEGIN_EVENT_TABLE(DbGridFrame, wxFrame)
+ //   EVT_CLOSE(DbGridFrame::OnCloseWindow)
+END_EVENT_TABLE()
+
+
+DbGridFrame::DbGridFrame(wxWindow *parent)
+    : wxFrame (parent, wxID_ANY, wxT("Database Table"),
+               wxDefaultPosition, wxSize(400, 325))
+{
+    initialized = false;
+}
+
+
+void DbGridFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
+{
+    this->Destroy();
+}
+
+
+bool DbGridFrame::Initialize()
+{
+    wxGrid *grid = new wxGrid(this, wxID_ANY, wxDefaultPosition);
+
+    grid->RegisterDataType(wxGRID_VALUE_DATETIME,
+                             new wxGridCellDateTimeRenderer(wxT("%d %b %Y")),
+                             new wxGridCellTextEditor);
+#ifdef CHOICEINT
+    grid->RegisterDataType(wxGRID_VALUE_CHOICEINT,
+                             new wxGridCellEnumRenderer,
+                             new wxGridCellEnumEditor);
+
+    wxString NativeLangChoice( wxString::Format(wxT("%s:%s,%s,%s,%s,%s"),wxGRID_VALUE_CHOICEINT,
+                            wxT("English"),
+                            wxT("French"),
+                            wxT("German"),
+                            wxT("Spanish"),
+                            wxT("Other") ));
+#endif
+
+    // Columns must match the sequence specified in SetColDef() calls
+    wxDbGridColInfo* cols =
+        new wxDbGridColInfo( 0,wxGRID_VALUE_STRING,wxT("Name"),
+        new wxDbGridColInfo( 1,wxGRID_VALUE_STRING,wxT("Address 1"),
+        new wxDbGridColInfo( 2,wxGRID_VALUE_STRING,wxT("Address 2"),
+        new wxDbGridColInfo( 3,wxGRID_VALUE_STRING,wxT("City"),
+        new wxDbGridColInfo( 4,wxGRID_VALUE_STRING,wxT("State"),
+        new wxDbGridColInfo( 5,wxGRID_VALUE_STRING,wxT("PostCode"),
+        new wxDbGridColInfo( 6,wxGRID_VALUE_STRING,wxT("Country"),
+        new wxDbGridColInfo( 7,wxGRID_VALUE_DBAUTO,wxT("Join Date"),
+        new wxDbGridColInfo( 8,wxGRID_VALUE_BOOL,  wxT("Developer"),
+        new wxDbGridColInfo( 9,wxGRID_VALUE_NUMBER,wxT("Contributions"),
+        new wxDbGridColInfo(10,wxGRID_VALUE_NUMBER,wxT("Lines Of Code"),
+#ifdef CHOICEINT
+        new wxDbGridColInfo(11,NativeLangChoice,   wxT("Native Language"),NULL))))))))))));
+#else
+        new wxDbGridColInfo(11,wxGRID_VALUE_NUMBER,wxT("Native Language"),NULL))))))))))));
+#endif
+
+    Ccontact *Contact = new Ccontact();
+    //wxGetApp().Contact
+
+    if (!Contact)
+    {
+        wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"), wxT("Error..."), wxOK | wxICON_EXCLAMATION);
+        return false;
+    }
+
+    if (!Contact->Open())
+    {
+        if (Contact->GetDb()->TableExists(CONTACT_TABLE_NAME, Contact->GetDb()->GetUsername(),
+                                          wxGetApp().DbConnectInf->GetDefaultDir()))
+        {
+            wxString tStr;
+            tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME.c_str());
+            wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                         wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+        }
+
+        return false;
+    }
+
+    // Execute the following query using the cursor designated
+    // for full table query
+    Contact->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY);
+
+    if (!Contact->Query())
+    {
+        wxString tStr;
+        tStr = wxT("ODBC error during Query()\n\n");
+        wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
+                     wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+        return false;
+    }
+
+    // No data has been read in from the database yet, so
+    // we need to initialize the data members to valid values
+    // so Fit() can correctly size the grid
+    Contact->Initialize();
+
+    wxDbGridTableBase* db = new wxDbGridTableBase(Contact, cols, wxUSE_QUERY, true);
+
+    delete cols;
+
+    grid->SetTable(db,true);
+    grid->SetMargins(0, 0);
 
 
+    grid->Fit();
+    wxSize size = grid->GetSize();
+    size.x += 10;
+    size.y += 10;
+    SetClientSize(size);
+    initialized = true;
+    return true;
+}  // DbGridFrame::Initialize()
 
 
+#endif // #if wxUSE_GRID
 
 /*
     TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
 
         int result = 0;
 
 /*
     TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
 
         int result = 0;
-        result = wxDbCreateDataSource("Microsoft Access Driver (*.mdb)","GLT-TEST2","GLT-Descrip",FALSE,"",this);
+        result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"), wxT("GLT-TEST2"), wxT("GLT-Descrip"), false, wxEmptyString, this);
         if (!result)
         {
             // check for errors caused by ConfigDSN based functions
             DWORD retcode = 0;
             WORD cb;
             wxChar errMsg[500+1];
         if (!result)
         {
             // check for errors caused by ConfigDSN based functions
             DWORD retcode = 0;
             WORD cb;
             wxChar errMsg[500+1];
-            errMsg[0] = '\0';
+            errMsg[0] = wxT('\0');
 
 
-            SQLInstallerError(1,&retcode,errMsg,500,&cb);
+            SQLInstallerError(1, &retcode, errMsg, 500, &cb);
 
 
-                       wxMessageBox("FAILED creating data source","FAILED");
+            wxMessageBox(wxT("FAILED creating data source"), wxT("FAILED"));
         }
         else
         }
         else
-            wxMessageBox("SUCCEEDED creating data source","SUCCESS");
+            wxMessageBox(wxT("SUCCEEDED creating data source"), wxT("SUCCESS"));
 */
 
 
 */