]> git.saurik.com Git - wxWidgets.git/blame - samples/db/dbtest.cpp
fixed the last of the off-by-one errors (some are refixed, again...)
[wxWidgets.git] / samples / db / dbtest.cpp
CommitLineData
108106cf
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: dbtest.cpp
3// Purpose: wxWindows database demo app
4// Author: George Tasker
5// Modified by:
6// Created: 1998
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Remstar International, Inc.
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12/*
e70e8f4c 13 * SYNOPSIS START
108106cf 14
e70e8f4c
GT
15 This sample program demonstrates the cross-platform ODBC database classes
16 donated by the development team at Remstar International.
108106cf 17
e70e8f4c 18 The table this sample is based on is developer contact table, and shows
f6bcfd97 19 some of the simple uses of the database classes wxDb and wxDbTable.
108106cf 20
e70e8f4c 21 * SYNOPSIS END
108106cf
JS
22 */
23
24#ifdef __GNUG__
25#pragma implementation "dbtest.h"
26#endif
27
28#include "wx/wxprec.h"
29
30#ifdef __BORLANDC__
31#pragma hdrstop
32#endif //__BORLANDC__
33
34#ifndef WX_PRECOMP
35#include <wx/wx.h>
36#endif //WX_PRECOMP
37
7e616b10
RR
38#ifdef __WXGTK__
39#include "db.xpm"
40#endif
41
5b077d48 42#include <stdio.h> /* Included strictly for reading the text file with the database parameters */
108106cf 43
3fe813a9
GT
44//#include <wx/db.h> /* Required in the file which will get the data source connection */
45//#include <wx/dbtable.h> /* Has the wxDbTable object from which all data objects will inherit their data table functionality */
108106cf 46
3fe813a9 47//extern wxDbList WXDLLEXPORT *PtrBegDbList; /* from db.cpp, used in getting back error results from db connections */
108106cf 48
f21b2fd8
GT
49#if wxUSE_NEW_GRID
50#include <wx/grid.h>
51#include <wx/generic/gridctrl.h>
52#include <wx/dbgrid.h>
53
54#define CHOICEINT
55#endif
56
5b077d48
RR
57#include "dbtest.h" /* Header file for this demonstration program */
58#include "listdb.h" /* Code to support the "Lookup" button on the editor dialog */
1fc5dd6f
JS
59
60IMPLEMENT_APP(DatabaseDemoApp)
61
049977d0
GT
62extern wxChar ListDB_Selection[]; /* Used to return the first column value for the selected line from the listDB routines */
63extern wxChar ListDB_Selection2[]; /* Used to return the second column value for the selected line from the listDB routines */
108106cf 64
5d59e67a
GT
65
66#if !wxUSE_ODBC
67 #error Sample cannot be compiled unless setup.h has wxUSE_ODBC set to 1
68#endif
69
70
3fe813a9
GT
71bool DataTypeSupported(wxDb *pDb, SWORD datatype)
72{
73 wxDbSqlTypeInfo sqlTypeInfo;
74
a4054ad1 75 bool breakpoint = FALSE;
3fe813a9
GT
76
77 if (pDb->GetDataTypeInfo(datatype, sqlTypeInfo))
a4054ad1 78 breakpoint = TRUE;
3fe813a9
GT
79
80 return breakpoint;
81
82} // GetDataTypesSupported();
83
84
85
86void CheckSupportForAllDataTypes(wxDb *pDb)
87{
3f030b48 88 wxLogMessage("\nThe following datatypes are supported by the\ndatabase you are currently connected to:");
3fe813a9 89#ifdef SQL_C_BINARY
3f030b48
GT
90 if (DataTypeSupported(pDb,SQL_C_BINARY))
91 wxLogMessage("SQL_C_BINARY");
3fe813a9
GT
92#endif
93#ifdef SQL_C_BIT
3f030b48
GT
94 if (DataTypeSupported(pDb,SQL_C_BIT))
95 wxLogMessage("SQL_C_BIT");
3fe813a9
GT
96#endif
97#ifdef SQL_C_BOOKMARK
3f030b48
GT
98 if (DataTypeSupported(pDb,SQL_C_BOOKMARK))
99 wxLogMessage("SQL_C_BOOKMARK");
3fe813a9
GT
100#endif
101#ifdef SQL_C_CHAR
3f030b48
GT
102 if (DataTypeSupported(pDb,SQL_C_CHAR))
103 wxLogMessage("SQL_C_CHAR");
3fe813a9
GT
104#endif
105#ifdef SQL_C_DATE
3f030b48
GT
106 if (DataTypeSupported(pDb,SQL_C_DATE))
107 wxLogMessage("SQL_C_DATE");
3fe813a9
GT
108#endif
109#ifdef SQL_C_DEFAULT
3f030b48
GT
110 if (DataTypeSupported(pDb,SQL_C_DEFAULT))
111 wxLogMessage("SQL_C_DEFAULT");
3fe813a9
GT
112#endif
113#ifdef SQL_C_DOUBLE
3f030b48
GT
114 if (DataTypeSupported(pDb,SQL_C_DOUBLE))
115 wxLogMessage("SQL_C_DOUBLE");
3fe813a9
GT
116#endif
117#ifdef SQL_C_FLOAT
3f030b48
GT
118 if (DataTypeSupported(pDb,SQL_C_FLOAT))
119 wxLogMessage("SQL_C_FLOAT");
3fe813a9
GT
120#endif
121#ifdef SQL_C_GUID
3f030b48
GT
122 if (DataTypeSupported(pDb,SQL_C_GUID))
123 wxLogMessage("SQL_C_GUID");
3fe813a9
GT
124#endif
125#ifdef SQL_C_INTERVAL_DAY
3f030b48
GT
126 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY))
127 wxLogMessage("SQL_C_INTERVAL_DAY");
3fe813a9
GT
128#endif
129#ifdef SQL_C_INTERVAL_DAY_TO_HOUR
3f030b48
GT
130 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_HOUR))
131 wxLogMessage("SQL_C_INTERVAL_DAY_TO_HOUR");
3fe813a9
GT
132#endif
133#ifdef SQL_C_INTERVAL_DAY_TO_MINUTE
3f030b48
GT
134 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_MINUTE))
135 wxLogMessage("SQL_C_INTERVAL_DAY_TO_MINUTE");
3fe813a9
GT
136#endif
137#ifdef SQL_C_INTERVAL_DAY_TO_SECOND
3f030b48
GT
138 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_SECOND))
139 wxLogMessage("SQL_C_INTERVAL_DAY_TO_SECOND");
3fe813a9
GT
140#endif
141#ifdef SQL_C_INTERVAL_HOUR
3f030b48
GT
142 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR))
143 wxLogMessage("SQL_C_INTERVAL_HOUR");
3fe813a9
GT
144#endif
145#ifdef SQL_C_INTERVAL_HOUR_TO_MINUTE
3f030b48
GT
146 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_MINUTE))
147 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_MINUTE");
3fe813a9
GT
148#endif
149#ifdef SQL_C_INTERVAL_HOUR_TO_SECOND
3f030b48
GT
150 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_SECOND))
151 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_SECOND");
3fe813a9
GT
152#endif
153#ifdef SQL_C_INTERVAL_MINUTE
3f030b48
GT
154 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE))
155 wxLogMessage("SQL_C_INTERVAL_MINUTE");
3fe813a9
GT
156#endif
157#ifdef SQL_C_INTERVAL_MINUTE_TO_SECOND
3f030b48
GT
158 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE_TO_SECOND))
159 wxLogMessage("SQL_C_INTERVAL_MINUTE_TO_SECOND");
3fe813a9
GT
160#endif
161#ifdef SQL_C_INTERVAL_MONTH
3f030b48
GT
162 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MONTH))
163 wxLogMessage("SQL_C_INTERVAL_MONTH");
3fe813a9
GT
164#endif
165#ifdef SQL_C_INTERVAL_SECOND
3f030b48
GT
166 if (DataTypeSupported(pDb,SQL_C_INTERVAL_SECOND))
167 wxLogMessage("SQL_C_INTERVAL_SECOND");
3fe813a9
GT
168#endif
169#ifdef SQL_C_INTERVAL_YEAR
3f030b48
GT
170 if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR))
171 wxLogMessage("SQL_C_INTERVAL_YEAR");
3fe813a9
GT
172#endif
173#ifdef SQL_C_INTERVAL_YEAR_TO_MONTH
3f030b48
GT
174 if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR_TO_MONTH))
175 wxLogMessage("SQL_C_INTERVAL_YEAR_TO_MONTH");
3fe813a9
GT
176#endif
177#ifdef SQL_C_LONG
3f030b48
GT
178 if (DataTypeSupported(pDb,SQL_C_LONG))
179 wxLogMessage("SQL_C_LONG");
3fe813a9
GT
180#endif
181#ifdef SQL_C_NUMERIC
3f030b48
GT
182 if (DataTypeSupported(pDb,SQL_C_NUMERIC))
183 wxLogMessage("SQL_C_NUMERIC");
3fe813a9
GT
184#endif
185#ifdef SQL_C_SBIGINT
3f030b48
GT
186 if (DataTypeSupported(pDb,SQL_C_SBIGINT))
187 wxLogMessage("SQL_C_SBIGINT");
3fe813a9
GT
188#endif
189#ifdef SQL_C_SHORT
3f030b48
GT
190 if (DataTypeSupported(pDb,SQL_C_SHORT))
191 wxLogMessage("SQL_C_SHORT");
3fe813a9
GT
192#endif
193#ifdef SQL_C_SLONG
3f030b48
GT
194 if (DataTypeSupported(pDb,SQL_C_SLONG))
195 wxLogMessage("SQL_C_SLONG");
3fe813a9
GT
196#endif
197#ifdef SQL_C_SSHORT
3f030b48
GT
198 if (DataTypeSupported(pDb,SQL_C_SSHORT))
199 wxLogMessage("SQL_C_SSHORT");
3fe813a9
GT
200#endif
201#ifdef SQL_C_STINYINT
3f030b48
GT
202 if (DataTypeSupported(pDb,SQL_C_STINYINT))
203 wxLogMessage("SQL_C_STINYINT");
3fe813a9
GT
204#endif
205#ifdef SQL_C_TIME
3f030b48
GT
206 if (DataTypeSupported(pDb,SQL_C_TIME))
207 wxLogMessage("SQL_C_TIME");
3fe813a9
GT
208#endif
209#ifdef SQL_C_TIMESTAMP
3f030b48
GT
210 if (DataTypeSupported(pDb,SQL_C_TIMESTAMP))
211 wxLogMessage("SQL_C_TIMESTAMP");
3fe813a9
GT
212#endif
213#ifdef SQL_C_TINYINT
3f030b48
GT
214 if (DataTypeSupported(pDb,SQL_C_TINYINT))
215 wxLogMessage("SQL_C_TINYINT");
3fe813a9
GT
216#endif
217#ifdef SQL_C_TYPE_DATE
3f030b48
GT
218 if (DataTypeSupported(pDb,SQL_C_TYPE_DATE))
219 wxLogMessage("SQL_C_TYPE_DATE");
3fe813a9
GT
220#endif
221#ifdef SQL_C_TYPE_TIME
3f030b48
GT
222 if (DataTypeSupported(pDb,SQL_C_TYPE_TIME))
223 wxLogMessage("SQL_C_TYPE_TIME");
3fe813a9
GT
224#endif
225#ifdef SQL_C_TYPE_TIMESTAMP
3f030b48
GT
226 if (DataTypeSupported(pDb,SQL_C_TYPE_TIMESTAMP))
227 wxLogMessage("SQL_C_TYPE_TIMESTAMP");
3fe813a9
GT
228#endif
229#ifdef SQL_C_UBIGINT
3f030b48
GT
230 if (DataTypeSupported(pDb,SQL_C_UBIGINT))
231 wxLogMessage("SQL_C_UBIGINT");
3fe813a9
GT
232#endif
233#ifdef SQL_C_ULONG
3f030b48
GT
234 if (DataTypeSupported(pDb,SQL_C_ULONG))
235 wxLogMessage("SQL_C_ULONG");
3fe813a9
GT
236#endif
237#ifdef SQL_C_USHORT
3f030b48
GT
238 if (DataTypeSupported(pDb,SQL_C_USHORT))
239 wxLogMessage("SQL_C_USHORT");
3fe813a9
GT
240#endif
241#ifdef SQL_C_UTINYINT
3f030b48
GT
242 if (DataTypeSupported(pDb,SQL_C_UTINYINT))
243 wxLogMessage("SQL_C_UTINYINT");
3fe813a9
GT
244#endif
245#ifdef SQL_C_VARBOOKMARK
3f030b48
GT
246 if (DataTypeSupported(pDb,SQL_C_VARBOOKMARK))
247 wxLogMessage("SQL_C_VARBOOKMARK");
3fe813a9
GT
248#endif
249
250// Extended SQL types
251#ifdef SQL_DATE
3f030b48
GT
252 if (DataTypeSupported(pDb,SQL_DATE))
253 wxLogMessage("SQL_DATE");
3fe813a9
GT
254#endif
255#ifdef SQL_INTERVAL
3f030b48
GT
256 if (DataTypeSupported(pDb,SQL_INTERVAL))
257 wxLogMessage("SQL_INTERVAL");
3fe813a9
GT
258#endif
259#ifdef SQL_TIME
3f030b48
GT
260 if (DataTypeSupported(pDb,SQL_TIME))
261 wxLogMessage("SQL_TIME");
3fe813a9
GT
262#endif
263#ifdef SQL_TIMESTAMP
3f030b48
GT
264 if (DataTypeSupported(pDb,SQL_TIMESTAMP))
265 wxLogMessage("SQL_TIMESTAMP");
3fe813a9
GT
266#endif
267#ifdef SQL_LONGVARCHAR
3f030b48
GT
268 if (DataTypeSupported(pDb,SQL_LONGVARCHAR))
269 wxLogMessage("SQL_LONGVARCHAR");
3fe813a9
GT
270#endif
271#ifdef SQL_BINARY
3f030b48
GT
272 if (DataTypeSupported(pDb,SQL_BINARY))
273 wxLogMessage("SQL_BINARY");
3fe813a9
GT
274#endif
275#ifdef SQL_VARBINARY
3f030b48
GT
276 if (DataTypeSupported(pDb,SQL_VARBINARY))
277 wxLogMessage("SQL_VARBINARY");
3fe813a9
GT
278#endif
279#ifdef SQL_LONGVARBINARY
3f030b48
GT
280 if (DataTypeSupported(pDb,SQL_LONGVARBINARY))
281 wxLogMessage("SQL_LONGVARBINARY");
3fe813a9
GT
282#endif
283#ifdef SQL_BIGINT
3f030b48
GT
284 if (DataTypeSupported(pDb,SQL_BIGINT))
285 wxLogMessage("SQL_BIGINT");
3fe813a9
GT
286#endif
287#ifdef SQL_TINYINT
3f030b48
GT
288 if (DataTypeSupported(pDb,SQL_TINYINT))
289 wxLogMessage("SQL_TINYINT");
3fe813a9
GT
290#endif
291#ifdef SQL_BIT
3f030b48
GT
292 if (DataTypeSupported(pDb,SQL_BIT))
293 wxLogMessage("SQL_BIT");
3fe813a9
GT
294#endif
295#ifdef SQL_GUID
3f030b48
GT
296 if (DataTypeSupported(pDb,SQL_GUID))
297 wxLogMessage("SQL_GUID");
3fe813a9
GT
298#endif
299
300#ifdef SQL_CHAR
3f030b48
GT
301 if (DataTypeSupported(pDb,SQL_CHAR))
302 wxLogMessage("SQL_CHAR");
3fe813a9
GT
303#endif
304#ifdef SQL_INTEGER
3f030b48
GT
305 if (DataTypeSupported(pDb,SQL_INTEGER))
306 wxLogMessage("SQL_INTEGER");
3fe813a9
GT
307#endif
308#ifdef SQL_SMALLINT
3f030b48
GT
309 if (DataTypeSupported(pDb,SQL_SMALLINT))
310 wxLogMessage("SQL_SMALLINT");
3fe813a9
GT
311#endif
312#ifdef SQL_REAL
3f030b48
GT
313 if (DataTypeSupported(pDb,SQL_REAL))
314 wxLogMessage("SQL_REAL");
3fe813a9
GT
315#endif
316#ifdef SQL_DOUBLE
3f030b48
GT
317 if (DataTypeSupported(pDb,SQL_DOUBLE))
318 wxLogMessage("SQL_DOUBLE");
3fe813a9
GT
319#endif
320#ifdef SQL_NUMERIC
3f030b48
GT
321 if (DataTypeSupported(pDb,SQL_NUMERIC))
322 wxLogMessage("SQL_NUMERIC");
3fe813a9
GT
323#endif
324#ifdef SQL_DATE
3f030b48
GT
325 if (DataTypeSupported(pDb,SQL_DATE))
326 wxLogMessage("SQL_DATE");
3fe813a9
GT
327#endif
328#ifdef SQL_TIME
3f030b48
GT
329 if (DataTypeSupported(pDb,SQL_TIME))
330 wxLogMessage("SQL_TIME");
3fe813a9
GT
331#endif
332#ifdef SQL_TIMESTAMP
3f030b48
GT
333 if (DataTypeSupported(pDb,SQL_TIMESTAMP))
334 wxLogMessage("SQL_TIMESTAMP");
3fe813a9
GT
335#endif
336#ifdef SQL_VARCHAR
3f030b48
GT
337 if (DataTypeSupported(pDb,SQL_VARCHAR))
338 wxLogMessage("SQL_VARCHAR");
3fe813a9
GT
339#endif
340
3fe813a9
GT
341// UNICODE
342#ifdef SQL_C_TCHAR
3f030b48
GT
343 if (DataTypeSupported(pDb,SQL_C_TCHAR))
344 wxLogMessage("SQL_C_TCHAR (Unicode support is possible)");
3fe813a9 345#endif
3f030b48
GT
346
347 wxLogMessage("\n");
3fe813a9
GT
348} // CheckSupportForAllDataTypes()
349
350
1fc5dd6f 351bool DatabaseDemoApp::OnInit()
108106cf 352{
ea24eeb2
GT
353 DbConnectInf = NULL;
354 Contact = NULL;
049977d0 355
e70e8f4c 356 // Create the main frame window
94613352 357 DemoFrame = new DatabaseDemoFrame(NULL, wxT("wxWindows Database Demo"), wxPoint(50, 50), wxSize(537, 480));
e70e8f4c
GT
358
359 // Give it an icon
360 DemoFrame->SetIcon(wxICON(db));
361
362 // Make a menubar
363 wxMenu *file_menu = new wxMenu;
94613352
GT
364 file_menu->Append(FILE_CREATE, wxT("&Create CONTACT table"));
365 file_menu->Append(FILE_RECREATE_TABLE, wxT("&Recreate CONTACT table"));
366 file_menu->Append(FILE_RECREATE_INDEXES, wxT("&Recreate CONTACT indexes"));
f21b2fd8
GT
367#if wxUSE_NEW_GRID
368 file_menu->Append(FILE_DBGRID_TABLE, wxT("&Open DB Grid example"));
369#endif
94613352 370 file_menu->Append(FILE_EXIT, wxT("E&xit"));
e70e8f4c
GT
371
372 wxMenu *edit_menu = new wxMenu;
94613352 373 edit_menu->Append(EDIT_PARAMETERS, wxT("&Parameters..."));
e70e8f4c 374
ea24eeb2
GT
375 wxMenu *help_menu = new wxMenu;
376 help_menu->Append(HELP_ABOUT, wxT("&About"));
e70e8f4c
GT
377
378 wxMenuBar *menu_bar = new wxMenuBar;
94613352
GT
379 menu_bar->Append(file_menu, wxT("&File"));
380 menu_bar->Append(edit_menu, wxT("&Edit"));
ea24eeb2 381 menu_bar->Append(help_menu, wxT("&Help"));
e70e8f4c
GT
382 DemoFrame->SetMenuBar(menu_bar);
383
e70e8f4c
GT
384 params.ODBCSource[0] = 0;
385 params.UserName[0] = 0;
386 params.Password[0] = 0;
387 params.DirPath[0] = 0;
388
3ca6a5f0 389 // Show the frame
a4054ad1 390 DemoFrame->Show(TRUE);
3ca6a5f0 391
049977d0
GT
392 // Passing NULL for the SQL environment handle causes
393 // the wxDbConnectInf constructor to obtain a handle
394 // for you.
395 //
396 // WARNING: Be certain that you do not free this handle
397 // directly with SQLFreeEnv(). Use either the
398 // method ::FreeHenv() or delete the DbConnectInf.
399 DbConnectInf = new wxDbConnectInf(NULL, params.ODBCSource, params.UserName,
400 params.Password, params.DirPath);
401
402 if (!DbConnectInf || !DbConnectInf->GetHenv())
403 {
404 wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
ea24eeb2 405 wxDELETE(DbConnectInf);
049977d0
GT
406 }
407
3fe813a9
GT
408 if (!ReadParamFile(params))
409 DemoFrame->BuildParameterDialog(NULL);
410
411 if (!wxStrlen(params.ODBCSource))
412 {
ea24eeb2 413 wxDELETE(DbConnectInf);
a4054ad1 414 return(FALSE);
3fe813a9
GT
415 }
416
417 DbConnectInf->SetDsn(params.ODBCSource);
418 DbConnectInf->SetUserID(params.UserName);
419 DbConnectInf->SetPassword(params.Password);
420 DbConnectInf->SetDefaultDir(params.DirPath);
421
049977d0
GT
422 READONLY_DB = wxDbGetConnection(DbConnectInf);
423 if (READONLY_DB == 0)
424 {
425 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);
426 DemoFrame->BuildParameterDialog(NULL);
ea24eeb2 427 wxDELETE(DbConnectInf);
049977d0 428 wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
a4054ad1 429 return(FALSE);
049977d0
GT
430 }
431
432 DemoFrame->BuildEditorDialog();
433
434 // Show the frame
435 DemoFrame->Refresh();
436
a4054ad1 437 return TRUE;
049977d0
GT
438} // DatabaseDemoApp::OnInit()
439
440
441bool DatabaseDemoApp::ReadParamFile(Cparameters &params)
442{
e70e8f4c 443 FILE *paramFile;
049977d0 444 if ((paramFile = fopen(PARAM_FILENAME, wxT("r"))) == NULL)
e70e8f4c
GT
445 {
446 wxString tStr;
049977d0 447 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);
94613352 448 wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c 449
a4054ad1 450 return FALSE;
e70e8f4c
GT
451 }
452
94613352 453 wxChar buffer[1000+1];
e70e8f4c 454 fgets(buffer, sizeof(params.ODBCSource), paramFile);
94613352 455 buffer[wxStrlen(buffer)-1] = wxT('\0');
f6bcfd97 456 wxStrcpy(params.ODBCSource,buffer);
e70e8f4c
GT
457
458 fgets(buffer, sizeof(params.UserName), paramFile);
94613352 459 buffer[wxStrlen(buffer)-1] = wxT('\0');
f6bcfd97 460 wxStrcpy(params.UserName,buffer);
e70e8f4c
GT
461
462 fgets(buffer, sizeof(params.Password), paramFile);
94613352 463 buffer[wxStrlen(buffer)-1] = wxT('\0');
f6bcfd97 464 wxStrcpy(params.Password,buffer);
e70e8f4c
GT
465
466 fgets(buffer, sizeof(params.DirPath), paramFile);
94613352 467 buffer[wxStrlen(buffer)-1] = wxT('\0');
f6bcfd97 468 wxStrcpy(params.DirPath,buffer);
e70e8f4c
GT
469
470 fclose(paramFile);
471
a4054ad1 472 return TRUE;
049977d0 473} // DatabaseDemoApp::ReadParamFile()
e70e8f4c 474
049977d0
GT
475
476bool DatabaseDemoApp::WriteParamFile(Cparameters &params)
477{
478 FILE *paramFile;
479 if ((paramFile = fopen(PARAM_FILENAME, wxT("wt"))) == NULL)
e70e8f4c 480 {
049977d0
GT
481 wxString tStr;
482 tStr.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME);
483 wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 484 return FALSE;
e70e8f4c
GT
485 }
486
049977d0
GT
487 fputs(wxGetApp().params.ODBCSource, paramFile);
488 fputc(wxT('\n'), paramFile);
489 fputs(wxGetApp().params.UserName, paramFile);
490 fputc(wxT('\n'), paramFile);
491 fputs(wxGetApp().params.Password, paramFile);
492 fputc(wxT('\n'), paramFile);
493 fputs(wxGetApp().params.DirPath, paramFile);
494 fputc(wxT('\n'), paramFile);
495 fclose(paramFile);
108106cf 496
a4054ad1 497 return TRUE;
049977d0
GT
498} // DatabaseDemoApp::WriteParamFile()
499
500
501void DatabaseDemoApp::CreateDataTable(bool recreate)
502{
a4054ad1 503 bool Ok = TRUE;
049977d0
GT
504 if (recreate)
505 Ok = (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
506
507 if (!Ok)
508 return;
509
510 wxBeginBusyCursor();
511
a4054ad1 512 bool success = TRUE;
049977d0 513
ea24eeb2 514 Contact->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
049977d0
GT
515
516 if (!Contact->CreateTable(recreate))
517 {
518 wxEndBusyCursor();
519 wxString tStr;
f21b2fd8
GT
520 tStr = wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
521 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__FILE__,__LINE__),
522 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
523
a4054ad1 524 success = FALSE;
049977d0
GT
525 }
526 else
527 {
69a2b59d 528 if (!Contact->CreateIndexes(recreate))
049977d0
GT
529 {
530 wxEndBusyCursor();
531 wxString tStr;
f21b2fd8
GT
532 tStr = wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
533 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__FILE__,__LINE__),
534 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
535
a4054ad1 536 success = FALSE;
049977d0
GT
537 }
538 }
539 while (wxIsBusy())
540 wxEndBusyCursor();
541
049977d0
GT
542 if (success)
543 wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
544} // DatabaseDemoApp::CreateDataTable()
108106cf 545
3ca6a5f0 546
1fc5dd6f
JS
547BEGIN_EVENT_TABLE(DatabaseDemoFrame, wxFrame)
548 EVT_MENU(FILE_CREATE, DatabaseDemoFrame::OnCreate)
3ca6a5f0
BP
549 EVT_MENU(FILE_RECREATE_TABLE, DatabaseDemoFrame::OnRecreateTable)
550 EVT_MENU(FILE_RECREATE_INDEXES, DatabaseDemoFrame::OnRecreateIndexes)
f21b2fd8
GT
551#if wxUSE_NEW_GRID
552 EVT_MENU(FILE_DBGRID_TABLE, DatabaseDemoFrame::OnDbGridTable)
553#endif
1fc5dd6f
JS
554 EVT_MENU(FILE_EXIT, DatabaseDemoFrame::OnExit)
555 EVT_MENU(EDIT_PARAMETERS, DatabaseDemoFrame::OnEditParameters)
ea24eeb2 556 EVT_MENU(HELP_ABOUT, DatabaseDemoFrame::OnAbout)
1fc5dd6f
JS
557 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow)
558END_EVENT_TABLE()
108106cf 559
3ca6a5f0 560
108106cf 561// DatabaseDemoFrame constructor
1fc5dd6f 562DatabaseDemoFrame::DatabaseDemoFrame(wxFrame *frame, const wxString& title,
3ca6a5f0
BP
563 const wxPoint& pos, const wxSize& size):
564 wxFrame(frame, -1, title, pos, size)
108106cf 565{
3ca6a5f0
BP
566 // Put any code in necessary for initializing the main frame here
567 pEditorDlg = NULL;
568 pParamDlg = NULL;
3f030b48
GT
569
570 delete wxLog::SetActiveTarget(new wxLogStderr);
571
3ca6a5f0
BP
572} // DatabaseDemoFrame constructor
573
3f030b48
GT
574DatabaseDemoFrame::~DatabaseDemoFrame()
575{
576 delete wxLog::SetActiveTarget(NULL);
577} // DatabaseDemoFrame destructor
578
108106cf 579
1fc5dd6f
JS
580void DatabaseDemoFrame::OnCreate(wxCommandEvent& event)
581{
a4054ad1 582 wxGetApp().CreateDataTable(FALSE);
3ca6a5f0
BP
583} // DatabaseDemoFrame::OnCreate()
584
585
586void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent& event)
587{
a4054ad1 588 wxGetApp().CreateDataTable(TRUE);
3ca6a5f0
BP
589} // DatabaseDemoFrame::OnRecreate()
590
591
592void DatabaseDemoFrame::OnRecreateIndexes(wxCommandEvent& event)
593{
69a2b59d
GT
594 wxGetApp().Contact->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
595
a4054ad1 596 if (!wxGetApp().Contact->CreateIndexes(TRUE))
3ca6a5f0 597 {
ea24eeb2
GT
598 while (wxIsBusy())
599 wxEndBusyCursor();
600 wxString tStr;
f21b2fd8
GT
601 tStr = wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
602 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
603 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
604
3ca6a5f0 605 }
69a2b59d 606 else
ea24eeb2 607 wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
3ca6a5f0 608
3ca6a5f0 609} // DatabaseDemoFrame::OnRecreateIndexes()
108106cf 610
ea24eeb2 611
f21b2fd8
GT
612#if wxUSE_NEW_GRID
613void DatabaseDemoFrame::OnDbGridTable(wxCommandEvent& )
614{
615 DbGridFrame *frame = new DbGridFrame(this);
616 if (frame->Initialize())
617 {
618 frame->Show();
619 }
620}
621#endif
622
1fc5dd6f 623void DatabaseDemoFrame::OnExit(wxCommandEvent& event)
108106cf 624{
3f755e2d 625 Close();
3ca6a5f0
BP
626} // DatabaseDemoFrame::OnExit()
627
108106cf 628
1fc5dd6f
JS
629void DatabaseDemoFrame::OnEditParameters(wxCommandEvent& event)
630{
e70e8f4c
GT
631 if ((pEditorDlg->mode != mCreate) && (pEditorDlg->mode != mEdit))
632 BuildParameterDialog(this);
633 else
94613352 634 wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
3ca6a5f0
BP
635} // DatabaseDemoFrame::OnEditParameters()
636
1fc5dd6f
JS
637
638void DatabaseDemoFrame::OnAbout(wxCommandEvent& event)
639{
94613352 640 wxMessageBox(wxT("wxWindows sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK | wxICON_INFORMATION);
3ca6a5f0
BP
641} // DatabaseDemoFrame::OnAbout()
642
108106cf 643
049977d0
GT
644// Put any additional checking necessary to make certain it is alright
645// to close the program here that is not done elsewhere
1fc5dd6f 646void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
108106cf 647{
3f755e2d 648 // Clean up time
3ca6a5f0 649 if (pEditorDlg && pEditorDlg->Close())
3f755e2d
GT
650 pEditorDlg = NULL;
651 else
f6bcfd97 652 {
3ca6a5f0
BP
653 if (pEditorDlg)
654 {
655 event.Veto();
656 return;
657 }
f6bcfd97
BP
658 }
659
ea24eeb2
GT
660 wxDELETE(wxGetApp().Contact);
661
3ca6a5f0
BP
662 // This function will close all the connections to the database that have been
663 // previously cached.
664 wxDbCloseConnections();
665
049977d0
GT
666 // Deletion of the wxDbConnectInf instance must be the LAST thing done that
667 // has anything to do with the database. Deleting this before disconnecting,
668 // freeing/closing connections, etc will result in a crash!
ea24eeb2 669 wxDELETE(wxGetApp().DbConnectInf);
3f755e2d 670
1fc5dd6f 671 this->Destroy();
3f755e2d 672
e3065973 673} // DatabaseDemoFrame::OnCloseWindow()
108106cf
JS
674
675
108106cf
JS
676void DatabaseDemoFrame::BuildEditorDialog()
677{
3ca6a5f0 678 pEditorDlg = NULL;
e70e8f4c 679 pEditorDlg = new CeditorDlg(this);
3ca6a5f0
BP
680 if (pEditorDlg)
681 {
682 pEditorDlg->Initialize();
683 if (!pEditorDlg->initialized)
684 {
685 pEditorDlg->Close();
973f2539 686 pEditorDlg = NULL;
94613352 687 wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
049977d0 688 Close();
3ca6a5f0
BP
689 }
690 }
691 else
692 {
94613352 693 wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
049977d0 694 Close();
3ca6a5f0 695 }
108106cf
JS
696} // DatabaseDemoFrame::BuildEditorDialog()
697
698
699void DatabaseDemoFrame::BuildParameterDialog(wxWindow *parent)
700{
e70e8f4c 701 pParamDlg = new CparameterDlg(parent);
108106cf 702
e70e8f4c 703 if (!pParamDlg)
94613352 704 wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
108106cf
JS
705} // DatabaseDemoFrame::BuildParameterDialog()
706
707
708/*
f6bcfd97 709 * Constructor note: If no wxDb object is passed in, a new connection to the database
108106cf
JS
710 * is created for this instance of Ccontact. This can be a slow process depending
711 * on the database engine being used, and some database engines have a limit on the
712 * number of connections (either hard limits, or license restricted) so care should
713 * be used to use as few connections as is necessary.
e70e8f4c 714 *
f6bcfd97 715 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
108106cf
JS
716 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
717 * or creating a table objects which use the same pDb, know that all the objects
718 * will be committed or rolled back when any of the objects has this function call made.
719 */
049977d0
GT
720Ccontact::Ccontact (wxDb *pwxDb) : wxDbTable(pwxDb ? pwxDb : wxDbGetConnection(wxGetApp().DbConnectInf),
721 CONTACT_TABLE_NAME, CONTACT_NO_COLS, wxT(""),
722 !wxDB_QUERY_ONLY, wxGetApp().DbConnectInf->GetDefaultDir())
108106cf 723{
e70e8f4c
GT
724 // This is used to represent whether the database connection should be released
725 // when this instance of the object is deleted. If using the same connection
726 // for multiple instance of database objects, then the connection should only be
727 // released when the last database instance using the connection is deleted
f6bcfd97 728 freeDbConn = !pwxDb;
e70e8f4c 729
3fe813a9
GT
730 if (GetDb())
731 GetDb()->SetSqlLogging(sqlLogON);
732
e70e8f4c 733 SetupColumns();
108106cf
JS
734
735} // Ccontact Constructor
736
737
738void Ccontact::Initialize()
739{
e70e8f4c
GT
740 Name[0] = 0;
741 Addr1[0] = 0;
742 Addr2[0] = 0;
743 City[0] = 0;
744 State[0] = 0;
745 PostalCode[0] = 0;
746 Country[0] = 0;
747 JoinDate.year = 1980;
748 JoinDate.month = 1;
749 JoinDate.day = 1;
750 JoinDate.hour = 0;
751 JoinDate.minute = 0;
752 JoinDate.second = 0;
753 JoinDate.fraction = 0;
754 NativeLanguage = langENGLISH;
a4054ad1 755 IsDeveloper = FALSE;
e70e8f4c
GT
756 Contributions = 0;
757 LinesOfCode = 0L;
108106cf
JS
758} // Ccontact::Initialize
759
760
761Ccontact::~Ccontact()
762{
e70e8f4c
GT
763 if (freeDbConn)
764 {
f6bcfd97 765 if (!wxDbFreeConnection(GetDb()))
e70e8f4c
GT
766 {
767 wxString tStr;
f21b2fd8
GT
768 tStr = wxT("Unable to Free the Ccontact data table handle\n\n");
769
770 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
771 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
772 }
773 }
108106cf
JS
774} // Ccontract destructor
775
776
777/*
f6bcfd97 778 * Handles setting up all the connections for the interface from the wxDbTable
108106cf
JS
779 * functions to interface to the data structure used to store records in
780 * memory, and for all the column definitions that define the table structure
781 */
f21b2fd8 782void Ccontact::SetupColumns()
108106cf 783{
e70e8f4c
GT
784 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
785 // names can be used for other database engines
a4054ad1
GT
786 SetColDefs ( 0,wxT("NAME"), DB_DATA_TYPE_VARCHAR, Name, SQL_C_CHAR, sizeof(Name), TRUE, TRUE); // Primary index
787 SetColDefs ( 1,wxT("ADDRESS1"), DB_DATA_TYPE_VARCHAR, Addr1, SQL_C_CHAR, sizeof(Addr1), FALSE,TRUE);
788 SetColDefs ( 2,wxT("ADDRESS2"), DB_DATA_TYPE_VARCHAR, Addr2, SQL_C_CHAR, sizeof(Addr2), FALSE,TRUE);
789 SetColDefs ( 3,wxT("CITY"), DB_DATA_TYPE_VARCHAR, City, SQL_C_CHAR, sizeof(City), FALSE,TRUE);
790 SetColDefs ( 4,wxT("STATE"), DB_DATA_TYPE_VARCHAR, State, SQL_C_CHAR, sizeof(State), FALSE,TRUE);
791 SetColDefs ( 5,wxT("POSTCODE"), DB_DATA_TYPE_VARCHAR, PostalCode, SQL_C_CHAR, sizeof(PostalCode), FALSE,TRUE);
792 SetColDefs ( 6,wxT("COUNTRY"), DB_DATA_TYPE_VARCHAR, Country, SQL_C_CHAR, sizeof(Country), FALSE,TRUE);
793 SetColDefs ( 7,wxT("JOINDATE"), DB_DATA_TYPE_DATE, &JoinDate, SQL_C_TIMESTAMP, sizeof(JoinDate), FALSE,TRUE);
794 SetColDefs ( 8,wxT("IS_DEV"), DB_DATA_TYPE_INTEGER, &IsDeveloper, SQL_C_BOOLEAN(IsDeveloper), sizeof(IsDeveloper), FALSE,TRUE);
795 SetColDefs ( 9,wxT("CONTRIBS"), DB_DATA_TYPE_INTEGER, &Contributions, SQL_C_UTINYINT, sizeof(Contributions), FALSE,TRUE);
796 SetColDefs (10,wxT("LINE_CNT"), DB_DATA_TYPE_INTEGER, &LinesOfCode, SQL_C_ULONG, sizeof(LinesOfCode), FALSE,TRUE);
797 SetColDefs (11,wxT("LANGUAGE"), DB_DATA_TYPE_INTEGER, &NativeLanguage, SQL_C_ENUM, sizeof(NativeLanguage), FALSE,TRUE);
3fe813a9 798#if wxODBC_BLOB_EXPERIMENT > 0
a4054ad1 799 SetColDefs (12,wxT("PICTURE"), DB_DATA_TYPE_BLOB, Picture, SQL_LONGVARBINARY, sizeof(Picture), FALSE,TRUE);
3fe813a9 800#endif
108106cf
JS
801} // Ccontact::SetupColumns
802
803
69a2b59d 804bool Ccontact::CreateIndexes(bool recreate)
108106cf 805{
e70e8f4c
GT
806 // This index could easily be accomplished with an "orderBy" clause,
807 // but is done to show how to construct a non-primary index.
808 wxString indexName;
f6bcfd97 809 wxDbIdxDef idxDef[2];
108106cf 810
a4054ad1 811 bool Ok = TRUE;
108106cf 812
f6bcfd97 813 wxStrcpy(idxDef[0].ColName, "IS_DEV");
a4054ad1 814 idxDef[0].Ascending = TRUE;
108106cf 815
f6bcfd97 816 wxStrcpy(idxDef[1].ColName, "NAME");
a4054ad1 817 idxDef[1].Ascending = TRUE;
108106cf 818
f6bcfd97 819 indexName = GetTableName();
e70e8f4c 820 indexName += "_IDX1";
a4054ad1 821 Ok = CreateIndex(indexName.c_str(), TRUE, 2, idxDef, recreate);
108106cf 822
e70e8f4c 823 return Ok;
108106cf
JS
824} // Ccontact::CreateIndexes()
825
826
827/*
828 * Having a function to do a query on the primary key (and possibly others) is
829 * very efficient and tighter coding so that it is available where ever the object
830 * is. Great for use with multiple tables when not using views or outer joins
831 */
049977d0 832bool Ccontact::FetchByName(const wxString &name)
108106cf 833{
24e2b35d 834 whereStr.Printf(wxT("NAME = '%s'"),name.c_str());
f6bcfd97 835 SetWhereClause(whereStr.c_str());
94613352 836 SetOrderByClause(wxT(""));
108106cf 837
e70e8f4c 838 if (!Query())
a4054ad1 839 return(FALSE);
108106cf 840
e70e8f4c
GT
841 // Fetch the record
842 return(GetNext());
108106cf
JS
843
844} // Ccontact::FetchByName()
845
846
847/*
848 *
849 * ************* DIALOGS ***************
850 *
851 */
852
853
854/* CeditorDlg constructor
855 *
856 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
857 * This dialog actually is drawn in the main frame of the program
858 *
859 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
860 * object that is currently being worked with.
861 */
f6fcbb63
RR
862
863BEGIN_EVENT_TABLE(CeditorDlg, wxPanel)
864 EVT_BUTTON(-1, CeditorDlg::OnButton)
3f755e2d 865 EVT_CLOSE(CeditorDlg::OnCloseWindow)
f6fcbb63
RR
866END_EVENT_TABLE()
867
3ca6a5f0 868CeditorDlg::CeditorDlg(wxWindow *parent) : wxPanel (parent, 0, 0, 537, 480)
108106cf 869{
e70e8f4c
GT
870 // Since the ::OnCommand() function is overridden, this prevents the widget
871 // detection in ::OnCommand() until all widgets have been initialized to prevent
872 // uninitialized pointers from crashing the program
a4054ad1 873 widgetPtrsSet = FALSE;
e70e8f4c 874
a4054ad1 875 initialized = FALSE;
e70e8f4c 876
3fe813a9
GT
877 SetMode(mView);
878
a4054ad1 879 Show(FALSE);
108106cf
JS
880} // CeditorDlg constructor
881
882
e3065973 883void CeditorDlg::OnCloseWindow(wxCloseEvent& event)
108106cf 884{
e70e8f4c 885 // Clean up time
3f755e2d 886 if ((mode != mCreate) && (mode != mEdit))
e70e8f4c 887 {
e70e8f4c
GT
888 this->Destroy();
889 }
890 else
891 {
94613352 892 wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
e70e8f4c
GT
893 event.Veto();
894 }
e3065973 895} // CeditorDlg::OnCloseWindow()
108106cf
JS
896
897
3ca6a5f0 898void CeditorDlg::OnButton(wxCommandEvent &event)
f6fcbb63 899{
3ca6a5f0
BP
900 wxWindow *win = (wxWindow*) event.GetEventObject();
901 OnCommand( *win, event );
902} // CeditorDlg::OnButton()
f6fcbb63 903
65d7ddc4 904
108106cf
JS
905void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
906{
e70e8f4c
GT
907 wxString widgetName;
908
909 widgetName = win.GetName();
910
911 if (!widgetPtrsSet)
912 return;
913
914 if (widgetName == pCreateBtn->GetName())
915 {
ea24eeb2 916 wxGetApp().Contact->Initialize();
e70e8f4c
GT
917 PutData();
918 SetMode( mCreate );
94613352 919 pNameTxt->SetValue(wxT(""));
e70e8f4c
GT
920 pNameTxt->SetFocus();
921 return;
922 }
923
924 if (widgetName == pEditBtn->GetName())
925 {
ea24eeb2 926 saveName = wxGetApp().Contact->Name;
e70e8f4c
GT
927 SetMode( mEdit );
928 pNameTxt->SetFocus();
929 return;
930 }
931
932 if (widgetName == pCopyBtn->GetName())
933 {
934 SetMode(mCreate);
94613352 935 pNameTxt->SetValue(wxT(""));
e70e8f4c
GT
936 pNameTxt->SetFocus();
937 return;
938 }
939
940 if (widgetName == pDeleteBtn->GetName())
941 {
94613352 942 bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
e70e8f4c
GT
943
944 if (!Ok)
945 return;
946
ea24eeb2 947 if (Ok && wxGetApp().Contact->Delete())
e70e8f4c
GT
948 {
949 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
950 // If the commit were not performed, the program will continue to
951 // show the table contents as if they were deleted until this instance
952 // of Ccontact is deleted. If the Commit wasn't performed, the
953 // database will automatically Rollback the changes when the database
954 // connection is terminated
ea24eeb2 955 wxGetApp().Contact->GetDb()->CommitTrans();
e70e8f4c
GT
956
957 // Try to get the row that followed the just deleted row in the orderBy sequence
958 if (!GetNextRec())
959 {
960 // There was now row (in sequence) after the just deleted row, so get the
961 // row which preceded the just deleted row
962 if (!GetPrevRec())
963 {
964 // There are now no rows remaining, so clear the dialog widgets
ea24eeb2 965 wxGetApp().Contact->Initialize();
e70e8f4c
GT
966 PutData();
967 }
968 }
969 SetMode(mode); // force reset of button enable/disable
970 }
971 else
972 // Delete failed
ea24eeb2 973 wxGetApp().Contact->GetDb()->RollbackTrans();
e70e8f4c
GT
974
975 SetMode(mView);
976 return;
977 }
978
979 if (widgetName == pSaveBtn->GetName())
980 {
981 Save();
982 return;
983 }
984
985 if (widgetName == pCancelBtn->GetName())
986 {
94613352 987 bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
e70e8f4c
GT
988
989 if (!Ok)
990 return;
991
94613352 992 if (saveName.IsEmpty())
e70e8f4c 993 {
ea24eeb2 994 wxGetApp().Contact->Initialize();
e70e8f4c
GT
995 PutData();
996 SetMode(mView);
997 return;
998 }
999 else
1000 {
1001 // Requery previous record
ea24eeb2 1002 if (wxGetApp().Contact->FetchByName(saveName))
e70e8f4c
GT
1003 {
1004 PutData();
1005 SetMode(mView);
1006 return;
1007 }
1008 }
1009
1010 // Previous record not available, retrieve first record in table
ea24eeb2
GT
1011 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1012 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1013 {
ea24eeb2
GT
1014 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1015 wxGetApp().Contact->whereStr += wxGetApp().Contact->GetTableName();
1016 wxGetApp().Contact->whereStr += wxT(")");
1017 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
e70e8f4c
GT
1018 }
1019 else
ea24eeb2 1020 wxGetApp().Contact->SetWhereClause(wxT(""));
e70e8f4c 1021
ea24eeb2 1022 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1023 {
1024 wxString tStr;
f21b2fd8
GT
1025 tStr = wxT("ODBC error during Query()\n\n");
1026 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1027 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1028
e70e8f4c
GT
1029 SetMode(mView);
1030 return;
1031 }
ea24eeb2 1032 if (wxGetApp().Contact->GetNext()) // Successfully read first record
e70e8f4c
GT
1033 {
1034 PutData();
1035 SetMode(mView);
1036 return;
1037 }
1038 // No contacts are available, clear dialog
ea24eeb2 1039 wxGetApp().Contact->Initialize();
e70e8f4c
GT
1040 PutData();
1041 SetMode(mView);
1042 return;
1043 } // Cancel Button
1044
1045 if (widgetName == pPrevBtn->GetName())
1046 {
1047 if (!GetPrevRec())
1048 wxBell();
1049 return;
1050 } // Prev Button
1051
1052 if (widgetName == pNextBtn->GetName())
1053 {
1054 if (!GetNextRec())
1055 wxBell();
1056 return;
1057 } // Next Button
1058
1059 if (widgetName == pQueryBtn->GetName())
1060 {
1061 // Display the query dialog box
94613352 1062 wxChar qryWhere[DB_MAX_WHERE_CLAUSE_LEN+1];
ea24eeb2 1063 wxStrcpy(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr);
94613352 1064 wxChar *tblName[] = {(wxChar *)CONTACT_TABLE_NAME, 0};
ea24eeb2 1065 new CqueryDlg(GetParent(), wxGetApp().Contact->GetDb(), tblName, qryWhere);
e70e8f4c
GT
1066
1067 // Query the first record in the new record set and
1068 // display it, if the query string has changed.
ea24eeb2 1069 if (wxStrcmp(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr))
e70e8f4c 1070 {
ea24eeb2
GT
1071 wxGetApp().Contact->whereStr.Empty();
1072 wxGetApp().Contact->SetOrderByClause("NAME");
e70e8f4c 1073
ea24eeb2
GT
1074 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1075 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1076 {
ea24eeb2
GT
1077 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1078 wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
e70e8f4c
GT
1079 }
1080
1081 // Append the query where string (if there is one)
ea24eeb2 1082 wxGetApp().Contact->qryWhereStr = qryWhere;
f6bcfd97 1083 if (wxStrlen(qryWhere))
e70e8f4c 1084 {
ea24eeb2
GT
1085 wxGetApp().Contact->whereStr += wxT(" WHERE ");
1086 wxGetApp().Contact->whereStr += wxGetApp().Contact->qryWhereStr;
e70e8f4c
GT
1087 }
1088 // Close the expression with a right paren
ea24eeb2 1089 wxGetApp().Contact->whereStr += wxT(")");
e70e8f4c 1090 // Requery the table
ea24eeb2
GT
1091 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
1092 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1093 {
1094 wxString tStr;
f21b2fd8
GT
1095 tStr = wxT("ODBC error during Query()\n\n");
1096 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1097 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1098
e70e8f4c
GT
1099 return;
1100 }
1101 // Display the first record from the query set
ea24eeb2
GT
1102 if (!wxGetApp().Contact->GetNext())
1103 wxGetApp().Contact->Initialize();
e70e8f4c
GT
1104 PutData();
1105 }
1106
1107 // Enable/Disable the reset button
ea24eeb2 1108 pResetBtn->Enable(!wxGetApp().Contact->qryWhereStr.IsEmpty());
e70e8f4c
GT
1109
1110 return;
1111 } // Query button
1112
1113
1114 if (widgetName == pResetBtn->GetName())
1115 {
1116 // Clear the additional where criteria established by the query feature
ea24eeb2
GT
1117 wxGetApp().Contact->qryWhereStr = wxT("");
1118 wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
e70e8f4c 1119
ea24eeb2
GT
1120 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1121 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1122 {
ea24eeb2
GT
1123 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1124 wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
1125 wxGetApp().Contact->whereStr += wxT(")");
e70e8f4c
GT
1126 }
1127
ea24eeb2
GT
1128 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
1129 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1130 {
1131 wxString tStr;
f21b2fd8
GT
1132 tStr = wxT("ODBC error during Query()\n\n");
1133 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1134 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
1135 return;
1136 }
ea24eeb2
GT
1137 if (!wxGetApp().Contact->GetNext())
1138 wxGetApp().Contact->Initialize();
e70e8f4c 1139 PutData();
a4054ad1 1140 pResetBtn->Enable(FALSE);
e70e8f4c
GT
1141
1142 return;
1143 } // Reset button
1144
1145
1146 if (widgetName == pNameListBtn->GetName())
1147 {
049977d0 1148 new ClookUpDlg(/* wxWindow *parent */ this,
94613352
GT
1149 /* wxChar *windowTitle */ wxT("Select contact name"),
1150 /* wxChar *tableName */ (wxChar *) CONTACT_TABLE_NAME,
1151 /* wxChar *dispCol1 */ wxT("NAME"),
1152 /* wxChar *dispCol2 */ wxT("JOINDATE"),
1153 /* wxChar *where */ wxT(""),
1154 /* wxChar *orderBy */ wxT("NAME"),
049977d0
GT
1155 /* wxDb *pDb */ wxGetApp().READONLY_DB,
1156 /* const wxString &defDir */ wxGetApp().DbConnectInf->GetDefaultDir(),
a4054ad1 1157 /* bool distinctValues */ TRUE);
e70e8f4c 1158
f6bcfd97 1159 if (ListDB_Selection && wxStrlen(ListDB_Selection))
e70e8f4c 1160 {
94613352 1161 wxString w = wxT("NAME = '");
e70e8f4c 1162 w += ListDB_Selection;
94613352 1163 w += wxT("'");
049977d0 1164 GetRec(w);
e70e8f4c
GT
1165 }
1166
1167 return;
1168 }
3f030b48
GT
1169
1170 if (widgetName == pDataTypesBtn->GetName())
1171 {
1172 CheckSupportForAllDataTypes(wxGetApp().READONLY_DB);
69a2b59d 1173 wxMessageBox("Support datatypes was dumped to stdout.");
3f030b48
GT
1174 return;
1175 } // Data types Button
1176
1177 if (widgetName == pDbDiagsBtn->GetName())
1178 {
1179 DisplayDbDiagnostics(wxGetApp().READONLY_DB);
69a2b59d
GT
1180 wxMessageBox("Diagnostics info was dumped to stdout.");
1181 return;
1182 }
1183
1184 if (widgetName == pCatalogBtn->GetName())
1185 {
1186 if (wxGetApp().Contact->GetDb()->Catalog("","catalog.txt"))
1187 wxMessageBox("The file 'catalog.txt' was created.");
1188 else
1189 wxMessageBox("Creation of the file 'catalog.txt' was failed.");
3f030b48
GT
1190 return;
1191 }
1192
108106cf
JS
1193} // CeditorDlg::OnCommand()
1194
1195
3ca6a5f0
BP
1196bool CeditorDlg::Initialize()
1197{
1198 // Create the data structure and a new database connection.
1199 // (As there is not a pDb being passed in the constructor, a new database
1200 // connection is created)
ea24eeb2 1201 wxGetApp().Contact = new Ccontact();
3ca6a5f0 1202
ea24eeb2 1203 if (!wxGetApp().Contact)
3ca6a5f0 1204 {
94613352 1205 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1206 return FALSE;
3ca6a5f0
BP
1207 }
1208
1209 // Check if the table exists or not. If it doesn't, ask the user if they want to
1210 // create the table. Continue trying to create the table until it exists, or user aborts
ea24eeb2 1211 while (!wxGetApp().Contact->GetDb()->TableExists((wxChar *)CONTACT_TABLE_NAME,
049977d0
GT
1212 wxGetApp().DbConnectInf->GetUserID(),
1213 wxGetApp().DbConnectInf->GetDefaultDir()))
3ca6a5f0
BP
1214 {
1215 wxString tStr;
f21b2fd8
GT
1216 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);
1217 bool createTable = (wxMessageBox(tStr.c_str(),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
3ca6a5f0
BP
1218
1219 if (!createTable)
1220 {
1221// Close();
a4054ad1 1222 return FALSE;
3ca6a5f0
BP
1223 }
1224 else
a4054ad1 1225 wxGetApp().CreateDataTable(FALSE);
3ca6a5f0
BP
1226 }
1227
1228 // Tables must be "opened" before anything other than creating/deleting table can be done
ea24eeb2 1229 if (!wxGetApp().Contact->Open())
3ca6a5f0
BP
1230 {
1231 // Table does exist, or there was some problem opening it. Currently this should
973f2539 1232 // never fail, except in the case of the table not exisiting or the current
3ca6a5f0 1233 // user has insufficent privileges to access the table
3fe813a9 1234#if 1
3ca6a5f0
BP
1235// This code is experimenting with a new function that will hopefully be available
1236// in the 2.4 release. This check will determine whether the open failing was due
1237// to the table not existing, or the users privileges being insufficient to
1238// open the table.
ea24eeb2
GT
1239 if (!wxGetApp().Contact->GetDb()->TablePrivileges(CONTACT_TABLE_NAME, wxT("SELECT"),
1240 wxGetApp().Contact->GetDb()->GetUsername(),
69a2b59d
GT
1241 wxGetApp().Contact->GetDb()->GetUsername(),
1242 wxGetApp().DbConnectInf->GetDefaultDir()))
3ca6a5f0
BP
1243 {
1244 wxString tStr;
3fe813a9 1245 tStr.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME);
f21b2fd8
GT
1246
1247 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1248 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
3ca6a5f0
BP
1249 }
1250 else
1251#endif
ea24eeb2
GT
1252 if (!wxGetApp().Contact->GetDb()->TableExists(CONTACT_TABLE_NAME,
1253 wxGetApp().Contact->GetDb()->GetUsername(),
3fe813a9 1254 wxGetApp().DbConnectInf->GetDefaultDir()))
3ca6a5f0
BP
1255 {
1256 wxString tStr;
3fe813a9 1257 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);
f21b2fd8
GT
1258 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1259 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
3ca6a5f0
BP
1260 }
1261
a4054ad1 1262 return FALSE;
3ca6a5f0
BP
1263 }
1264
1265 // Build the dialog
1266
94613352
GT
1267 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP, wxT(""), wxPoint(15, 1), wxSize(497, 69), 0, wxT("FunctionGrp"));
1268 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP, wxT(""), wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
1269
1270 pCreateBtn = new wxButton(this, EDITOR_DIALOG_CREATE, wxT("&Create"), wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CreateBtn"));
1271 pEditBtn = new wxButton(this, EDITOR_DIALOG_EDIT, wxT("&Edit"), wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("EditBtn"));
1272 pDeleteBtn = new wxButton(this, EDITOR_DIALOG_DELETE, wxT("&Delete"), wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DeleteBtn"));
1273 pCopyBtn = new wxButton(this, EDITOR_DIALOG_COPY, wxT("Cop&y"), wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CopyBtn"));
1274 pSaveBtn = new wxButton(this, EDITOR_DIALOG_SAVE, wxT("&Save"), wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("SaveBtn"));
1275 pCancelBtn = new wxButton(this, EDITOR_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CancelBtn"));
1276 pPrevBtn = new wxButton(this, EDITOR_DIALOG_PREV, wxT("<< &Prev"), wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator, wxT("PrevBtn"));
1277 pNextBtn = new wxButton(this, EDITOR_DIALOG_NEXT, wxT("&Next >>"), wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator, wxT("NextBtn"));
1278 pQueryBtn = new wxButton(this, EDITOR_DIALOG_QUERY, wxT("&Query"), wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator, wxT("QueryBtn"));
1279 pResetBtn = new wxButton(this, EDITOR_DIALOG_RESET, wxT("&Reset"), wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ResetBtn"));
1280 pNameMsg = new wxStaticText(this, EDITOR_DIALOG_NAME_MSG, wxT("Name:"), wxPoint( 17, 80), wxSize( -1, -1), 0, wxT("NameMsg"));
1281 pNameTxt = new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT, wxT(""), wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator, wxT("NameTxt"));
1282 pNameListBtn = new wxButton(this, EDITOR_DIALOG_LOOKUP, wxT("&Lookup"), wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator, wxT("LookupBtn"));
1283 pAddress1Msg = new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG, wxT("Address:"), wxPoint( 17, 130), wxSize( -1, -1), 0, wxT("Address1Msg"));
1284 pAddress1Txt = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT, wxT(""), wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator, wxT("Address1Txt"));
1285 pAddress2Msg = new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG, wxT("Address:"), wxPoint( 17, 180), wxSize( -1, -1), 0, wxT("Address2Msg"));
1286 pAddress2Txt = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT, wxT(""), wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator, wxT("Address2Txt"));
1287 pCityMsg = new wxStaticText(this, EDITOR_DIALOG_CITY_MSG, wxT("City:"), wxPoint( 17, 230), wxSize( -1, -1), 0, wxT("CityMsg"));
1288 pCityTxt = new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT, wxT(""), wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator, wxT("CityTxt"));
1289 pStateMsg = new wxStaticText(this, EDITOR_DIALOG_STATE_MSG, wxT("State:"), wxPoint(250, 230), wxSize( -1, -1), 0, wxT("StateMsg"));
1290 pStateTxt = new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT, wxT(""), wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator, wxT("StateTxt"));
1291 pCountryMsg = new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG, wxT("Country:"), wxPoint( 17, 280), wxSize( -1, -1), 0, wxT("CountryMsg"));
1292 pCountryTxt = new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT, wxT(""), wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator, wxT("CountryTxt"));
1293 pPostalCodeMsg = new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG, wxT("Postal Code:"),wxPoint(250, 280), wxSize( -1, -1), 0, wxT("PostalCodeMsg"));
1294 pPostalCodeTxt = new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT, wxT(""), wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator, wxT("PostalCodeTxt"));
3ca6a5f0
BP
1295
1296 wxString choice_strings[5];
94613352
GT
1297 choice_strings[0] = wxT("English");
1298 choice_strings[1] = wxT("French");
1299 choice_strings[2] = wxT("German");
1300 choice_strings[3] = wxT("Spanish");
1301 choice_strings[4] = wxT("Other");
3ca6a5f0 1302
94613352
GT
1303 pNativeLangChoice = new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings);
1304 pNativeLangMsg = new wxStaticText(this, EDITOR_DIALOG_LANG_MSG, wxT("Native language:"), wxPoint( 17, 330), wxSize( -1, -1), 0, wxT("NativeLangMsg"));
3ca6a5f0
BP
1305
1306 wxString radio_strings[2];
94613352
GT
1307 radio_strings[0] = wxT("No");
1308 radio_strings[1] = wxT("Yes");
1309 pDeveloperRadio = new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER, wxT("Developer:"), wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings, 2, wxHORIZONTAL);
1310 pJoinDateMsg = new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG, wxT("Date joined:"), wxPoint( 17, 380), wxSize( -1, -1), 0, wxT("JoinDateMsg"));
1311 pJoinDateTxt = new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT, wxT(""), wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator, wxT("JoinDateTxt"));
1312 pContribMsg = new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG,wxT("Contributions:"), wxPoint(175, 380), wxSize( -1, -1), 0, wxT("ContribMsg"));
1313 pContribTxt = new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT, wxT(""), wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator, wxT("ContribTxt"));
1314 pLinesMsg = new wxStaticText(this, EDITOR_DIALOG_LINES_MSG, wxT("Lines of code:"), wxPoint(303, 380), wxSize( -1, -1), 0, wxT("LinesMsg"));
1315 pLinesTxt = new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT, wxT(""), wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator, wxT("LinesTxt"));
3ca6a5f0 1316
69a2b59d 1317 pCatalogBtn = new wxButton(this, EDITOR_DIALOG_CATALOG, wxT("Catalo&g"), wxPoint(430, 287), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CatalogBtn"));
3f030b48
GT
1318 pDataTypesBtn = new wxButton(this, EDITOR_DIALOG_DATATYPES, wxT("Data&types"), wxPoint(430, 337), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DataTypesBtn"));
1319 pDbDiagsBtn = new wxButton(this, EDITOR_DIALOG_DB_DIAGS, wxT("DB Dia&gs"), wxPoint(430, 387), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DbDiagsBtn"));
1320
3ca6a5f0
BP
1321 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1322 // handle all widget processing
a4054ad1 1323 widgetPtrsSet = TRUE;
3ca6a5f0
BP
1324
1325 // Setup the orderBy and where clauses to return back a single record as the result set,
1326 // as there will only be one record being shown on the dialog at a time, this optimizes
1327 // network traffic by only returning a one row result
1328
ea24eeb2 1329 wxGetApp().Contact->SetOrderByClause(wxT("NAME")); // field name to sort by
3ca6a5f0
BP
1330
1331 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
1332 // specifically in the Ccontact class. It is used here for simpler construction of a varying
1333 // length string, and then after the string is built, the wxDbTable member variable "where" is
1334 // assigned the pointer to the constructed string.
1335 //
1336 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
1337 // to achieve a single row (in this case the first name in alphabetical order).
1338
ea24eeb2
GT
1339 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1340 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
3ca6a5f0 1341 {
ea24eeb2
GT
1342 wxGetApp().Contact->whereStr.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
1343 wxGetApp().Contact->GetTableName().c_str());
94613352 1344 // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
ea24eeb2 1345 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr);
3ca6a5f0
BP
1346 }
1347 else
ea24eeb2 1348 wxGetApp().Contact->SetWhereClause(wxT(""));
3ca6a5f0
BP
1349
1350 // Perform the Query to get the result set.
a4054ad1
GT
1351 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
1352 // Only if there is a database error will Query() come back as FALSE
ea24eeb2 1353 if (!wxGetApp().Contact->Query())
3ca6a5f0
BP
1354 {
1355 wxString tStr;
f21b2fd8
GT
1356 tStr = wxT("ODBC error during Query()\n\n");
1357 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1358 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1359 return FALSE;
3ca6a5f0
BP
1360 }
1361
1362 // Since Query succeeded, now get the row that was returned
ea24eeb2 1363 if (!wxGetApp().Contact->GetNext())
3ca6a5f0
BP
1364 // If the GetNext() failed at this point, then there are no rows to retrieve,
1365 // so clear the values in the members of "Contact" so that PutData() blanks the
1366 // widgets on the dialog
ea24eeb2
GT
1367 wxGetApp().Contact->Initialize();
1368/*
1369 wxGetApp().Contact->GetDb()->RollbackTrans();
1370*/
3ca6a5f0
BP
1371 SetMode(mView);
1372 PutData();
1373
a4054ad1 1374 Show(TRUE);
3ca6a5f0 1375
a4054ad1
GT
1376 initialized = TRUE;
1377 return TRUE;
3ca6a5f0
BP
1378} // CeditorDlg::Initialize()
1379
1380
108106cf
JS
1381void CeditorDlg::FieldsEditable()
1382{
3fe813a9
GT
1383 if (!widgetPtrsSet)
1384 return;
1385
e70e8f4c
GT
1386 pNameTxt->Enable((mode == mCreate) || (mode == mEdit));
1387 pAddress1Txt->Enable((mode == mCreate) || (mode == mEdit));
1388 pAddress2Txt->Enable((mode == mCreate) || (mode == mEdit));
1389 pCityTxt->Enable((mode == mCreate) || (mode == mEdit));
1390 pStateTxt->Enable((mode == mCreate) || (mode == mEdit));
1391 pPostalCodeTxt->Enable((mode == mCreate) || (mode == mEdit));
1392 pCountryTxt->Enable((mode == mCreate) || (mode == mEdit));
1393
1394 pJoinDateTxt->Enable((mode == mCreate) || (mode == mEdit));
1395 pContribTxt->Enable((mode == mCreate) || (mode == mEdit));
1396 pLinesTxt->Enable((mode == mCreate) || (mode == mEdit));
1397 pNativeLangChoice->Enable((mode == mCreate) || (mode == mEdit));
1398 pDeveloperRadio->Enable((mode == mCreate) || (mode == mEdit));
108106cf
JS
1399
1400} // CeditorDlg::FieldsEditable()
1401
1402
1403void CeditorDlg::SetMode(enum DialogModes m)
1404{
a4054ad1 1405 bool edit = FALSE;
e70e8f4c
GT
1406
1407 mode = m;
1408 switch (mode)
1409 {
1410 case mCreate:
1411 case mEdit:
a4054ad1 1412 edit = TRUE;
e70e8f4c
GT
1413 break;
1414 case mView:
1415 case mSearch:
a4054ad1 1416 edit = FALSE;
e70e8f4c
GT
1417 break;
1418 default:
1419 break;
1420 };
1421
1422 if (widgetPtrsSet)
1423 {
1424 pCreateBtn->Enable( !edit );
ea24eeb2
GT
1425 pEditBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name,wxT(""))!=0) );
1426 pDeleteBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name,wxT(""))!=0) );
1427 pCopyBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name,wxT(""))!=0) );
e70e8f4c
GT
1428 pSaveBtn->Enable( edit );
1429 pCancelBtn->Enable( edit );
1430 pPrevBtn->Enable( !edit );
1431 pNextBtn->Enable( !edit );
1432 pQueryBtn->Enable( !edit );
ea24eeb2 1433 pResetBtn->Enable( !edit && !wxGetApp().Contact->qryWhereStr.IsEmpty() );
e70e8f4c
GT
1434 pNameListBtn->Enable( !edit );
1435 }
1436
1437 FieldsEditable();
108106cf
JS
1438} // CeditorDlg::SetMode()
1439
1440
1fc5dd6f 1441bool CeditorDlg::PutData()
108106cf 1442{
e70e8f4c 1443 wxString tStr;
108106cf 1444
ea24eeb2
GT
1445 pNameTxt->SetValue(wxGetApp().Contact->Name);
1446 pAddress1Txt->SetValue(wxGetApp().Contact->Addr1);
1447 pAddress2Txt->SetValue(wxGetApp().Contact->Addr2);
1448 pCityTxt->SetValue(wxGetApp().Contact->City);
1449 pStateTxt->SetValue(wxGetApp().Contact->State);
1450 pCountryTxt->SetValue(wxGetApp().Contact->Country);
1451 pPostalCodeTxt->SetValue(wxGetApp().Contact->PostalCode);
108106cf 1452
ea24eeb2 1453 tStr.Printf(wxT("%d/%d/%d"),wxGetApp().Contact->JoinDate.month,wxGetApp().Contact->JoinDate.day,wxGetApp().Contact->JoinDate.year);
e70e8f4c 1454 pJoinDateTxt->SetValue(tStr);
108106cf 1455
ea24eeb2 1456 tStr.Printf(wxT("%d"),wxGetApp().Contact->Contributions);
e70e8f4c 1457 pContribTxt->SetValue(tStr);
108106cf 1458
ea24eeb2 1459 tStr.Printf(wxT("%lu"),wxGetApp().Contact->LinesOfCode);
e70e8f4c 1460 pLinesTxt->SetValue(tStr);
108106cf 1461
ea24eeb2 1462 pNativeLangChoice->SetSelection(wxGetApp().Contact->NativeLanguage);
108106cf 1463
ea24eeb2 1464 pDeveloperRadio->SetSelection(wxGetApp().Contact->IsDeveloper);
108106cf 1465
a4054ad1 1466 return TRUE;
108106cf
JS
1467} // Ceditor::PutData()
1468
1469
1470/*
1471 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1472 * to ensure that there is a name entered and that the date field is valid.
1473 *
a4054ad1 1474 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
108106cf
JS
1475 * invalid data was found (and a message was displayed telling the user what to fix), and
1476 * the data was not placed into the appropraite fields of Ccontact
1477 */
1fc5dd6f 1478bool CeditorDlg::GetData()
108106cf 1479{
e70e8f4c
GT
1480 // Validate that the data currently entered into the widgets is valid data
1481
1482 wxString tStr;
1483 tStr = pNameTxt->GetValue();
94613352 1484 if (!wxStrcmp((const wxChar*) tStr,wxT("")))
e70e8f4c 1485 {
94613352 1486 wxMessageBox(wxT("A name is required for entry into the contact table"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
a4054ad1 1487 return FALSE;
e70e8f4c
GT
1488 }
1489
a4054ad1 1490 bool invalid = FALSE;
e70e8f4c
GT
1491 int mm,dd,yyyy;
1492 int first, second;
1493
1494 tStr = pJoinDateTxt->GetValue();
94613352 1495 if (tStr.Freq(wxT('/')) != 2)
a4054ad1 1496 invalid = TRUE;
e70e8f4c
GT
1497
1498 // Find the month, day, and year tokens
1499 if (!invalid)
1500 {
94613352
GT
1501 first = tStr.First(wxT('/'));
1502 second = tStr.Last(wxT('/'));
e70e8f4c
GT
1503
1504 mm = atoi(tStr.SubString(0,first));
1505 dd = atoi(tStr.SubString(first+1,second));
1506 yyyy = atoi(tStr.SubString(second+1,tStr.Length()-1));
1507
1508 invalid = !(mm && dd && yyyy);
1509 }
1510
1511 // Force Year 2000 compliance
1512 if (!invalid && (yyyy < 1000))
a4054ad1 1513 invalid = TRUE;
e70e8f4c
GT
1514
1515 // Check the token ranges for validity
1516 if (!invalid)
1517 {
1518 if (yyyy > 9999)
a4054ad1 1519 invalid = TRUE;
e70e8f4c 1520 else if ((mm < 1) || (mm > 12))
a4054ad1 1521 invalid = TRUE;
e70e8f4c
GT
1522 else
1523 {
1524 if (dd < 1)
a4054ad1 1525 invalid = TRUE;
e70e8f4c
GT
1526 else
1527 {
1528 int days[12] = {31,28,31,30,31,30,
1529 31,31,30,31,30,31};
1530 if (dd > days[mm-1])
1531 {
a4054ad1 1532 invalid = TRUE;
e70e8f4c
GT
1533 if ((dd == 29) && (mm == 2))
1534 {
1535 if (((yyyy % 4) == 0) && (((yyyy % 100) != 0) || ((yyyy % 400) == 0)))
a4054ad1 1536 invalid = FALSE;
e70e8f4c
GT
1537 }
1538 }
1539 }
1540 }
1541 }
1542
1543 if (!invalid)
1544 {
ea24eeb2
GT
1545 wxGetApp().Contact->JoinDate.month = mm;
1546 wxGetApp().Contact->JoinDate.day = dd;
1547 wxGetApp().Contact->JoinDate.year = yyyy;
e70e8f4c
GT
1548 }
1549 else
1550 {
94613352 1551 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);
a4054ad1 1552 return FALSE;
e70e8f4c
GT
1553 }
1554
1555 tStr = pNameTxt->GetValue();
ea24eeb2
GT
1556 wxStrcpy(wxGetApp().Contact->Name,(const wxChar*) tStr);
1557 wxStrcpy(wxGetApp().Contact->Addr1,pAddress1Txt->GetValue());
1558 wxStrcpy(wxGetApp().Contact->Addr2,pAddress2Txt->GetValue());
1559 wxStrcpy(wxGetApp().Contact->City,pCityTxt->GetValue());
1560 wxStrcpy(wxGetApp().Contact->State,pStateTxt->GetValue());
1561 wxStrcpy(wxGetApp().Contact->Country,pCountryTxt->GetValue());
1562 wxStrcpy(wxGetApp().Contact->PostalCode,pPostalCodeTxt->GetValue());
e70e8f4c 1563
ea24eeb2
GT
1564 wxGetApp().Contact->Contributions = atoi(pContribTxt->GetValue());
1565 wxGetApp().Contact->LinesOfCode = atol(pLinesTxt->GetValue());
e70e8f4c 1566
ea24eeb2
GT
1567 wxGetApp().Contact->NativeLanguage = (enum Language) pNativeLangChoice->GetSelection();
1568 wxGetApp().Contact->IsDeveloper = pDeveloperRadio->GetSelection() > 0;
e70e8f4c 1569
a4054ad1 1570 return TRUE;
108106cf
JS
1571} // CeditorDlg::GetData()
1572
1573
1574/*
1575 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1576 * try to insert/update the data to the table based on the current 'mode' the dialog
1577 * is set to.
1578 *
a4054ad1
GT
1579 * A return value of TRUE means the insert/update was completed successfully, a return
1580 * value of FALSE means that Save() failed. If returning FALSE, then this function
108106cf
JS
1581 * has displayed a detailed error message for the user.
1582 */
1fc5dd6f 1583bool CeditorDlg::Save()
108106cf 1584{
a4054ad1 1585 bool failed = FALSE;
e70e8f4c
GT
1586
1587 // Read the data in the widgets of the dialog to get the user's data
1588 if (!GetData())
a4054ad1 1589 failed = TRUE;
e70e8f4c
GT
1590
1591 // Perform any other required validations necessary before saving
1592 if (!failed)
1593 {
1594 wxBeginBusyCursor();
1595
1596 if (mode == mCreate)
1597 {
ea24eeb2 1598 RETCODE result = wxGetApp().Contact->Insert();
e70e8f4c
GT
1599
1600 failed = (result != DB_SUCCESS);
1601 if (failed)
1602 {
1603 // Some errors may be expected, like a duplicate key, so handle those instances with
1604 // specific error messages.
1605 if (result == DB_ERR_INTEGRITY_CONSTRAINT_VIOL)
1606 {
1607 wxString tStr;
f21b2fd8
GT
1608 tStr = wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
1609 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1610 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
1611 }
1612 else
1613 {
5d59e67a 1614 // Some other unexpected error occurred
e70e8f4c 1615 wxString tStr;
f21b2fd8
GT
1616 tStr = wxT("Database insert failed\n\n");
1617 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1618 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
1619 }
1620 }
1621 }
1622 else // mode == mEdit
1623 {
5d59e67a 1624 wxGetApp().Contact->GetDb()->RollbackTrans();
ea24eeb2
GT
1625 wxGetApp().Contact->whereStr.Printf("NAME = '%s'",saveName.c_str());
1626 if (!wxGetApp().Contact->UpdateWhere(wxGetApp().Contact->whereStr))
e70e8f4c
GT
1627 {
1628 wxString tStr;
f21b2fd8
GT
1629 tStr = wxT("Database update failed\n\n");
1630 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1631 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1632 failed = TRUE;
e70e8f4c
GT
1633 }
1634 }
1635
1636 if (!failed)
1637 {
ea24eeb2 1638 wxGetApp().Contact->GetDb()->CommitTrans();
e70e8f4c
GT
1639 SetMode(mView); // Sets the dialog mode back to viewing after save is successful
1640 }
1641 else
ea24eeb2 1642 wxGetApp().Contact->GetDb()->RollbackTrans();
e70e8f4c
GT
1643
1644 wxEndBusyCursor();
1645 }
1646
1647 return !failed;
108106cf
JS
1648} // CeditorDlg::Save()
1649
1650
1651/*
1652 * Where this program is only showing a single row at a time in the dialog,
1653 * a special where clause must be built to find just the single row which,
1654 * in sequence, would follow the currently displayed row.
1655 */
1fc5dd6f 1656bool CeditorDlg::GetNextRec()
108106cf 1657{
e70e8f4c
GT
1658 wxString w;
1659
ea24eeb2
GT
1660 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1661 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1662 {
94613352 1663 w = wxT("NAME = (SELECT MIN(NAME) FROM ");
ea24eeb2 1664 w += wxGetApp().Contact->GetTableName();
94613352 1665 w += wxT(" WHERE NAME > '");
e70e8f4c
GT
1666 }
1667 else
94613352 1668 w = wxT("(NAME > '");
e70e8f4c 1669
ea24eeb2 1670 w += wxGetApp().Contact->Name;
94613352 1671 w += wxT("'");
e70e8f4c
GT
1672
1673 // If a query where string is currently set, append that criteria
ea24eeb2 1674 if (!wxGetApp().Contact->qryWhereStr.IsEmpty())
e70e8f4c 1675 {
94613352 1676 w += wxT(" AND (");
ea24eeb2 1677 w += wxGetApp().Contact->qryWhereStr;
94613352 1678 w += wxT(")");
e70e8f4c
GT
1679 }
1680
94613352 1681 w += wxT(")");
049977d0 1682 return(GetRec(w));
108106cf
JS
1683
1684} // CeditorDlg::GetNextRec()
1685
1686
1687/*
1688 * Where this program is only showing a single row at a time in the dialog,
1689 * a special where clause must be built to find just the single row which,
1690 * in sequence, would precede the currently displayed row.
1691 */
1fc5dd6f 1692bool CeditorDlg::GetPrevRec()
108106cf 1693{
e70e8f4c 1694 wxString w;
108106cf 1695
ea24eeb2
GT
1696 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1697 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1698 {
94613352 1699 w = wxT("NAME = (SELECT MAX(NAME) FROM ");
ea24eeb2 1700 w += wxGetApp().Contact->GetTableName();
94613352 1701 w += wxT(" WHERE NAME < '");
e70e8f4c
GT
1702 }
1703 else
94613352 1704 w = wxT("(NAME < '");
65d7ddc4 1705
ea24eeb2 1706 w += wxGetApp().Contact->Name;
94613352 1707 w += wxT("'");
108106cf 1708
e70e8f4c 1709 // If a query where string is currently set, append that criteria
ea24eeb2 1710 if (!wxGetApp().Contact->qryWhereStr.IsEmpty())
e70e8f4c 1711 {
94613352 1712 w += wxT(" AND (");
ea24eeb2 1713 w += wxGetApp().Contact->qryWhereStr;
94613352 1714 w += wxT(")");
e70e8f4c 1715 }
108106cf 1716
94613352 1717 w += wxT(")");
108106cf 1718
049977d0 1719 return(GetRec(w));
108106cf
JS
1720
1721} // CeditorDlg::GetPrevRec()
1722
1723
1724/*
1725 * This function is here to avoid duplicating this same code in both the
1726 * GetPrevRec() and GetNextRec() functions
1727 */
049977d0 1728bool CeditorDlg::GetRec(const wxString &whereStr)
108106cf 1729{
ea24eeb2
GT
1730 wxGetApp().Contact->SetWhereClause(whereStr);
1731 wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
e70e8f4c 1732
ea24eeb2 1733 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1734 {
1735 wxString tStr;
f21b2fd8
GT
1736 tStr = wxT("ODBC error during Query()\n\n");
1737 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1738 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c 1739
a4054ad1 1740 return(FALSE);
e70e8f4c
GT
1741 }
1742
ea24eeb2 1743 if (wxGetApp().Contact->GetNext())
e70e8f4c
GT
1744 {
1745 PutData();
a4054ad1 1746 return(TRUE);
e70e8f4c
GT
1747 }
1748 else
a4054ad1 1749 return(FALSE);
108106cf
JS
1750} // CeditorDlg::GetRec()
1751
1752
1753
1754/*
1755 * CparameterDlg constructor
1756 */
e3065973
JS
1757
1758BEGIN_EVENT_TABLE(CparameterDlg, wxDialog)
65d7ddc4
GT
1759 EVT_BUTTON(PARAMETER_DIALOG_SAVE, CparameterDlg::OnButton)
1760 EVT_BUTTON(PARAMETER_DIALOG_CANCEL, CparameterDlg::OnButton)
e3065973
JS
1761 EVT_CLOSE(CparameterDlg::OnCloseWindow)
1762END_EVENT_TABLE()
1763
94613352 1764CparameterDlg::CparameterDlg(wxWindow *parent) : wxDialog (parent, PARAMETER_DIALOG, wxT("ODBC parameter settings"), wxPoint(-1, -1), wxSize(400, 325))
108106cf 1765{
e70e8f4c
GT
1766 // Since the ::OnCommand() function is overridden, this prevents the widget
1767 // detection in ::OnCommand() until all widgets have been initialized to prevent
1768 // uninitialized pointers from crashing the program
a4054ad1 1769 widgetPtrsSet = FALSE;
e70e8f4c 1770
94613352
GT
1771 pParamODBCSourceMsg = new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG, wxT("ODBC data sources:"), wxPoint( 10, 10), wxSize( -1, -1), 0, wxT("ParamODBCSourceMsg"));
1772 pParamODBCSourceList = new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("ParamODBCSourceList"));
1773 pParamUserNameMsg = new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG, wxT("Database user name:"), wxPoint( 10, 193), wxSize( -1, -1), 0, wxT("ParamUserNameMsg"));
1774 pParamUserNameTxt = new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT, wxT(""), wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator, wxT("ParamUserNameTxt"));
1775 pParamPasswordMsg = new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG, wxT("Password:"), wxPoint(156, 193), wxSize( -1, -1), 0, wxT("ParamPasswordMsg"));
1776 pParamPasswordTxt = new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT, wxT(""), wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator, wxT("ParamPasswordTxt"));
1777 pParamDirPathMsg = new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG, wxT("Directory:"), wxPoint( 10, 243), wxSize( -1, -1), 0, wxT("ParamDirPathMsg"));
1778 pParamDirPathTxt = new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT, wxT(""), wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator, wxT("ParamDirPathTxt"));
1779 pParamSaveBtn = new wxButton(this, PARAMETER_DIALOG_SAVE, wxT("&Save"), wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ParamSaveBtn"));
1780 pParamCancelBtn = new wxButton(this, PARAMETER_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ParamCancelBtn"));
e70e8f4c
GT
1781
1782 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1783 // handle all widget processing
a4054ad1 1784 widgetPtrsSet = TRUE;
e70e8f4c 1785
a4054ad1 1786 saved = FALSE;
e70e8f4c
GT
1787 savedParamSettings = wxGetApp().params;
1788
1789 Centre(wxBOTH);
1790 PutData();
1791 ShowModal();
108106cf
JS
1792} // CparameterDlg constructor
1793
1794
e3065973 1795void CparameterDlg::OnCloseWindow(wxCloseEvent& event)
108106cf 1796{
e70e8f4c
GT
1797 // Put any additional checking necessary to make certain it is alright
1798 // to close the program here that is not done elsewhere
1799 if (!saved)
1800 {
94613352 1801 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);
3ca6a5f0 1802
e70e8f4c 1803 if (!Ok)
e3065973
JS
1804 {
1805 event.Veto();
e70e8f4c 1806 return;
e3065973 1807 }
3ca6a5f0 1808
e70e8f4c
GT
1809 wxGetApp().params = savedParamSettings;
1810 }
108106cf 1811
e70e8f4c
GT
1812 if (GetParent() != NULL)
1813 GetParent()->SetFocus();
e3065973 1814
3ca6a5f0
BP
1815 while (wxIsBusy())
1816 wxEndBusyCursor();
1817
a4054ad1 1818 Show(FALSE);
3ca6a5f0
BP
1819 SetReturnCode(0); // added so BoundsChecker would not report use of uninitialized variable
1820
1821 this->Destroy();
1822} // CparameterDlg::OnCloseWindow()
108106cf
JS
1823
1824
65d7ddc4
GT
1825void CparameterDlg::OnButton( wxCommandEvent &event )
1826{
e70e8f4c
GT
1827 wxWindow *win = (wxWindow*) event.GetEventObject();
1828 OnCommand( *win, event );
65d7ddc4
GT
1829}
1830
3ca6a5f0 1831
108106cf
JS
1832void CparameterDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
1833{
e70e8f4c
GT
1834 wxString widgetName;
1835
1836 widgetName = win.GetName();
1837
1838 if (!widgetPtrsSet)
1839 return;
1840
1841 if (widgetName == pParamSaveBtn->GetName())
1842 {
1843 if (Save())
1844 {
1845 wxString tStr;
94613352 1846 tStr = wxT("Database parameters have been saved.");
e70e8f4c 1847 if (GetParent() != NULL) // The parameter dialog was not called during startup due to a missing cfg file
94613352
GT
1848 tStr += wxT("\nNew parameters will take effect the next time the program is started.");
1849 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
a4054ad1 1850 saved = TRUE;
e70e8f4c
GT
1851 Close();
1852 }
1853 return;
1854 }
1855
1856 if (widgetName == pParamCancelBtn->GetName())
1857 {
1858 Close();
1859 return;
1860 }
108106cf
JS
1861} // CparameterDlg::OnCommand()
1862
1863
1fc5dd6f 1864bool CparameterDlg::PutData()
108106cf 1865{
e70e8f4c
GT
1866 // Fill the data source list box
1867 FillDataSourceList();
1868
1869 // Fill in the fields from the params object
1870 if (wxGetApp().params.ODBCSource && wxStrlen(wxGetApp().params.ODBCSource))
1871 pParamODBCSourceList->SetStringSelection(wxGetApp().params.ODBCSource);
1872 pParamUserNameTxt->SetValue(wxGetApp().params.UserName);
1873 pParamPasswordTxt->SetValue(wxGetApp().params.Password);
1874 pParamDirPathTxt->SetValue(wxGetApp().params.DirPath);
a4054ad1 1875 return TRUE;
108106cf
JS
1876} // CparameterDlg::PutData()
1877
1878
1fc5dd6f 1879bool CparameterDlg::GetData()
108106cf 1880{
e70e8f4c 1881 wxString tStr;
94613352 1882 if (pParamODBCSourceList->GetStringSelection() != wxT(""))
e70e8f4c
GT
1883 {
1884 tStr = pParamODBCSourceList->GetStringSelection();
1885 if (tStr.Length() > (sizeof(wxGetApp().params.ODBCSource)-1))
1886 {
1887 wxString errmsg;
94613352
GT
1888 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());
1889 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1890 return FALSE;
e70e8f4c 1891 }
f6bcfd97 1892 wxStrcpy(wxGetApp().params.ODBCSource, tStr);
e70e8f4c
GT
1893 }
1894 else
a4054ad1 1895 return FALSE;
e70e8f4c
GT
1896
1897 tStr = pParamUserNameTxt->GetValue();
1898 if (tStr.Length() > (sizeof(wxGetApp().params.UserName)-1))
1899 {
1900 wxString errmsg;
94613352
GT
1901 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());
1902 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1903 return FALSE;
e70e8f4c 1904 }
f6bcfd97 1905 wxStrcpy(wxGetApp().params.UserName, tStr);
e70e8f4c
GT
1906
1907 tStr = pParamPasswordTxt->GetValue();
1908 if (tStr.Length() > (sizeof(wxGetApp().params.Password)-1))
1909 {
1910 wxString errmsg;
94613352
GT
1911 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());
1912 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1913 return FALSE;
e70e8f4c 1914 }
f6bcfd97 1915 wxStrcpy(wxGetApp().params.Password,tStr);
e70e8f4c
GT
1916
1917 tStr = pParamDirPathTxt->GetValue();
94613352 1918 tStr.Replace(wxT("\\"),wxT("/"));
e70e8f4c
GT
1919 if (tStr.Length() > (sizeof(wxGetApp().params.DirPath)-1))
1920 {
1921 wxString errmsg;
94613352
GT
1922 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());
1923 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1924 return FALSE;
e70e8f4c 1925 }
f6bcfd97 1926 wxStrcpy(wxGetApp().params.DirPath,tStr);
a4054ad1 1927 return TRUE;
108106cf
JS
1928} // CparameterDlg::GetData()
1929
1930
1fc5dd6f 1931bool CparameterDlg::Save()
108106cf 1932{
049977d0
GT
1933 // Copy the current params in case user cancels changing
1934 // the params, so that we can reset them.
e70e8f4c
GT
1935 if (!GetData())
1936 {
049977d0 1937 wxGetApp().params = savedParamSettings;
a4054ad1 1938 return FALSE;
e70e8f4c
GT
1939 }
1940
049977d0 1941 wxGetApp().WriteParamFile(wxGetApp().params);
e70e8f4c 1942
a4054ad1 1943 return TRUE;
108106cf
JS
1944} // CparameterDlg::Save()
1945
1946
1947void CparameterDlg::FillDataSourceList()
1948{
94613352
GT
1949 wxChar Dsn[SQL_MAX_DSN_LENGTH + 1];
1950 wxChar DsDesc[255];
e70e8f4c 1951 wxStringList strList;
108106cf 1952
049977d0
GT
1953 while (wxDbGetDataSource(wxGetApp().DbConnectInf->GetHenv(), Dsn,
1954 SQL_MAX_DSN_LENGTH+1, DsDesc, 255))
e70e8f4c 1955 strList.Add(Dsn);
108106cf 1956
e70e8f4c 1957 strList.Sort();
94613352
GT
1958 strList.Add(wxT(""));
1959 wxChar **p = strList.ListToArray();
108106cf 1960
e70e8f4c 1961 int i;
f6bcfd97 1962 for (i = 0; wxStrlen(p[i]); i++)
e70e8f4c 1963 pParamODBCSourceList->Append(p[i]);
3ca6a5f0 1964
ea24eeb2 1965 wxDELETEA(p);
3fe813a9 1966} // CparameterDlg::FillDataSourceList()
108106cf
JS
1967
1968
f6fcbb63
RR
1969BEGIN_EVENT_TABLE(CqueryDlg, wxDialog)
1970 EVT_BUTTON(-1, CqueryDlg::OnButton)
e3065973 1971 EVT_CLOSE(CqueryDlg::OnCloseWindow)
f6fcbb63 1972END_EVENT_TABLE()
3ca6a5f0 1973
f6fcbb63 1974
108106cf 1975// CqueryDlg() constructor
d3358961
GT
1976CqueryDlg::CqueryDlg(wxWindow *parent, wxDb *pDb, wxChar *tblName[],
1977 const wxString &pWhereArg) :
1978 wxDialog (parent, QUERY_DIALOG, wxT("Query"), wxPoint(-1, -1), wxSize(480, 360))
108106cf 1979{
e70e8f4c
GT
1980 wxBeginBusyCursor();
1981
1982 colInf = 0;
1983 dbTable = 0;
1984 masterTableName = tblName[0];
a4054ad1 1985 widgetPtrsSet = FALSE;
e70e8f4c
GT
1986 pDB = pDb;
1987
1988 // Initialize the WHERE clause from the string passed in
d3358961
GT
1989 pWhere = pWhereArg; // Save a pointer to the output buffer
1990 if (pWhere.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN) // Check the length of the buffer passed in
e70e8f4c
GT
1991 {
1992 wxString s;
94613352
GT
1993 s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
1994 wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
1995 Close();
1996 return;
1997 }
1998
94613352
GT
1999 pQueryCol1Msg = new wxStaticText(this, QUERY_DIALOG_COL_MSG, wxT("Column 1:"), wxPoint( 10, 10), wxSize( 69, 16), 0, wxT("QueryCol1Msg"));
2000 pQueryCol1Choice = new wxChoice(this, QUERY_DIALOG_COL_CHOICE, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol1Choice"));
2001 pQueryNotMsg = new wxStaticText(this, QUERY_DIALOG_NOT_MSG, wxT("NOT"), wxPoint(268, 10), wxSize( -1, -1), 0, wxT("QueryNotMsg"));
2002 pQueryNotCheck = new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX, wxT(""), wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator, wxT("QueryNotCheck"));
e70e8f4c
GT
2003
2004 wxString choice_strings[9];
94613352
GT
2005 choice_strings[0] = wxT("=");
2006 choice_strings[1] = wxT("<");
2007 choice_strings[2] = wxT(">");
2008 choice_strings[3] = wxT("<=");
2009 choice_strings[4] = wxT(">=");
2010 choice_strings[5] = wxT("Begins");
2011 choice_strings[6] = wxT("Contains");
2012 choice_strings[7] = wxT("Like");
2013 choice_strings[8] = wxT("Between");
2014
2015 pQueryOperatorMsg = new wxStaticText(this, QUERY_DIALOG_OP_MSG, wxT("Operator:"), wxPoint(305, 10), wxSize( -1, -1), 0, wxT("QueryOperatorMsg"));
2016 pQueryOperatorChoice = new wxChoice(this, QUERY_DIALOG_OP_CHOICE, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings, 0, wxDefaultValidator, wxT("QueryOperatorChoice"));
2017 pQueryCol2Msg = new wxStaticText(this, QUERY_DIALOG_COL2_MSG, wxT("Column 2:"), wxPoint( 10, 65), wxSize( 69, 16), 0, wxT("QueryCol2Msg"));
2018 pQueryCol2Choice = new wxChoice(this, QUERY_DIALOG_COL2_CHOICE, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol2Choice"));
2019 pQuerySqlWhereMsg = new wxStaticText(this, QUERY_DIALOG_WHERE_MSG, wxT("SQL where clause:"), wxPoint( 10, 141), wxSize( -1, -1), 0, wxT("QuerySqlWhereMsg"));
2020 pQuerySqlWhereMtxt = new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT, wxT(""), wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE, wxDefaultValidator, wxT("QuerySqlWhereMtxt"));
2021 pQueryAddBtn = new wxButton(this, QUERY_DIALOG_ADD, wxT("&Add"), wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryAddBtn"));
2022 pQueryAndBtn = new wxButton(this, QUERY_DIALOG_AND, wxT("A&nd"), wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryAndBtn"));
2023 pQueryOrBtn = new wxButton(this, QUERY_DIALOG_OR, wxT("&Or"), wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryOrBtn"));
2024 pQueryLParenBtn = new wxButton(this, QUERY_DIALOG_LPAREN, wxT("("), wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator, wxT("QueryLParenBtn"));
2025 pQueryRParenBtn = new wxButton(this, QUERY_DIALOG_RPAREN, wxT(")"), wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator, wxT("QueryRParenBtn"));
2026 pQueryDoneBtn = new wxButton(this, QUERY_DIALOG_DONE, wxT("&Done"), wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryDoneBtn"));
2027 pQueryClearBtn = new wxButton(this, QUERY_DIALOG_CLEAR, wxT("C&lear"), wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryClearBtn"));
2028 pQueryCountBtn = new wxButton(this, QUERY_DIALOG_COUNT, wxT("&Count"), wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryCountBtn"));
2029 pQueryValue1Msg = new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG, wxT("Value:"), wxPoint(277, 66), wxSize( -1, -1), 0, wxT("QueryValue1Msg"));
2030 pQueryValue1Txt = new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT, wxT(""), wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator, wxT("QueryValue1Txt"));
2031 pQueryValue2Msg = new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG, wxT("AND"), wxPoint(238, 126), wxSize( -1, -1), 0, wxT("QueryValue2Msg"));
2032 pQueryValue2Txt = new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT, wxT(""), wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator, wxT("QueryValue2Txt"));
2033 pQueryHintGrp = new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP, wxT(""), wxPoint( 10, 291), wxSize(377, 40), 0, wxT("QueryHintGrp"));
2034 pQueryHintMsg = new wxStaticText(this, QUERY_DIALOG_HINT_MSG, wxT(""), wxPoint( 16, 306), wxSize( -1, -1), 0, wxT("QueryHintMsg"));
e70e8f4c 2035
a4054ad1 2036 widgetPtrsSet = TRUE;
e70e8f4c
GT
2037 // Initialize the dialog
2038 wxString qualName;
94613352 2039 pQueryCol2Choice->Append(wxT("VALUE -->"));
e70e8f4c
GT
2040 colInf = pDB->GetColumns(tblName);
2041
2042 if (!colInf)
2043 {
2044 wxEndBusyCursor();
2045 wxString tStr;
f21b2fd8
GT
2046 tStr = wxT("ODBC error during GetColumns()\n\n");
2047 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2048 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2049 return;
2050 }
2051
2052 int i;
f6bcfd97 2053 for (i = 0; colInf[i].colName && wxStrlen(colInf[i].colName); i++)
e70e8f4c
GT
2054 {
2055 // If there is more than one table being queried, qualify
2056 // the column names with the table name prefix.
f6bcfd97 2057 if (tblName[1] && wxStrlen(tblName[1]))
e70e8f4c 2058 {
94613352 2059 qualName.Printf(wxT("%s.%s"), colInf[i].tableName, colInf[i].colName);
e70e8f4c
GT
2060 pQueryCol1Choice->Append(qualName);
2061 pQueryCol2Choice->Append(qualName);
2062 }
2063 else // Single table query, append just the column names
2064 {
2065 pQueryCol1Choice->Append(colInf[i].colName);
2066 pQueryCol2Choice->Append(colInf[i].colName);
2067 }
2068 }
2069
2070 pQueryCol1Choice->SetSelection(0);
2071 pQueryCol2Choice->SetSelection(0);
2072 pQueryOperatorChoice->SetSelection(0);
2073
a4054ad1
GT
2074 pQueryValue2Msg->Show(FALSE);
2075 pQueryValue2Txt->Show(FALSE);
e70e8f4c
GT
2076
2077 pQueryHintMsg->SetLabel(langQRY_EQ);
2078
d3358961 2079 pQuerySqlWhereMtxt->SetValue(pWhere.c_str());
e70e8f4c
GT
2080
2081 wxEndBusyCursor();
2082
2083 // Display the dialog window
2084 Centre(wxBOTH);
2085 ShowModal();
108106cf
JS
2086} // CqueryDlg() constructor
2087
2088
4c4a393f
GT
2089CqueryDlg::~CqueryDlg()
2090{
2091} // CqueryDlg::~CqueryDlg() destructor
2092
2093
3ca6a5f0 2094void CqueryDlg::OnButton(wxCommandEvent &event)
f6fcbb63
RR
2095{
2096 wxWindow *win = (wxWindow*) event.GetEventObject();
2097 OnCommand( *win, event );
3ca6a5f0
BP
2098} // CqueryDlg::OnButton()
2099
f6fcbb63 2100
108106cf
JS
2101void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
2102{
e70e8f4c
GT
2103 // Widget pointers won't be set when the dialog is constructed.
2104 // Control is passed through this function once for each widget on
2105 // a dialog as the dialog is constructed.
2106 if (!widgetPtrsSet)
2107 return;
2108
2109 wxString widgetName = win.GetName();
2110
2111 // Operator choice box
2112 if (widgetName == pQueryOperatorChoice->GetName())
2113 {
2114 // Set the help text
2115 switch((qryOp) pQueryOperatorChoice->GetSelection())
2116 {
3ca6a5f0
BP
2117 case qryOpEQ:
2118 pQueryHintMsg->SetLabel(langQRY_EQ);
2119 break;
2120 case qryOpLT:
2121 pQueryHintMsg->SetLabel(langQRY_LT);
2122 break;
2123 case qryOpGT:
2124 pQueryHintMsg->SetLabel(langQRY_GT);
2125 break;
2126 case qryOpLE:
2127 pQueryHintMsg->SetLabel(langQRY_LE);
2128 break;
2129 case qryOpGE:
2130 pQueryHintMsg->SetLabel(langQRY_GE);
2131 break;
2132 case qryOpBEGINS:
2133 pQueryHintMsg->SetLabel(langQRY_BEGINS);
2134 break;
2135 case qryOpCONTAINS:
2136 pQueryHintMsg->SetLabel(langQRY_CONTAINS);
2137 break;
2138 case qryOpLIKE:
2139 pQueryHintMsg->SetLabel(langQRY_LIKE);
2140 break;
2141 case qryOpBETWEEN:
2142 pQueryHintMsg->SetLabel(langQRY_BETWEEN);
2143 break;
e70e8f4c
GT
2144 }
2145
2146 // Hide the value2 widget
a4054ad1
GT
2147 pQueryValue2Msg->Show(FALSE); // BETWEEN will show this widget
2148 pQueryValue2Txt->Show(FALSE); // BETWEEN will show this widget
e70e8f4c
GT
2149
2150 // Disable the NOT operator for <, <=, >, >=
2151 switch((qryOp) pQueryOperatorChoice->GetSelection())
2152 {
3ca6a5f0
BP
2153 case qryOpLT:
2154 case qryOpGT:
2155 case qryOpLE:
2156 case qryOpGE:
2157 pQueryNotCheck->SetValue(0);
a4054ad1 2158 pQueryNotCheck->Enable(FALSE);
3ca6a5f0
BP
2159 break;
2160 default:
a4054ad1 2161 pQueryNotCheck->Enable(TRUE);
3ca6a5f0 2162 break;
e70e8f4c
GT
2163 }
2164
2165 // Manipulate the dialog to handle the selected operator
2166 switch((qryOp) pQueryOperatorChoice->GetSelection())
2167 {
3ca6a5f0
BP
2168 case qryOpEQ:
2169 case qryOpLT:
2170 case qryOpGT:
2171 case qryOpLE:
2172 case qryOpGE:
a4054ad1 2173 pQueryCol2Choice->Enable(TRUE);
3ca6a5f0
BP
2174 if (pQueryCol2Choice->GetSelection()) // Column name is highlighted
2175 {
a4054ad1
GT
2176 pQueryValue1Msg->Show(FALSE);
2177 pQueryValue1Txt->Show(FALSE);
3ca6a5f0
BP
2178 }
2179 else // "Value" is highlighted
2180 {
a4054ad1
GT
2181 pQueryValue1Msg->Show(TRUE);
2182 pQueryValue1Txt->Show(TRUE);
3ca6a5f0
BP
2183 pQueryValue1Txt->SetFocus();
2184 }
2185 break;
2186 case qryOpBEGINS:
2187 case qryOpCONTAINS:
2188 case qryOpLIKE:
2189 pQueryCol2Choice->SetSelection(0);
a4054ad1
GT
2190 pQueryCol2Choice->Enable(FALSE);
2191 pQueryValue1Msg->Show(TRUE);
2192 pQueryValue1Txt->Show(TRUE);
e70e8f4c 2193 pQueryValue1Txt->SetFocus();
3ca6a5f0
BP
2194 break;
2195 case qryOpBETWEEN:
2196 pQueryCol2Choice->SetSelection(0);
a4054ad1
GT
2197 pQueryCol2Choice->Enable(FALSE);
2198 pQueryValue2Msg->Show(TRUE);
2199 pQueryValue2Txt->Show(TRUE);
2200 pQueryValue1Msg->Show(TRUE);
2201 pQueryValue1Txt->Show(TRUE);
3ca6a5f0
BP
2202 pQueryValue1Txt->SetFocus();
2203 break;
e70e8f4c
GT
2204 }
2205
2206 return;
2207
2208 } // Operator choice box
2209
2210 // Column 2 choice
2211 if (widgetName == pQueryCol2Choice->GetName())
2212 {
2213 if (pQueryCol2Choice->GetSelection()) // Column name is highlighted
2214 {
a4054ad1
GT
2215 pQueryValue1Msg->Show(FALSE);
2216 pQueryValue1Txt->Show(FALSE);
e70e8f4c
GT
2217 }
2218 else // "Value" is highlighted
2219 {
a4054ad1
GT
2220 pQueryValue1Msg->Show(TRUE);
2221 pQueryValue1Txt->Show(TRUE);
e70e8f4c
GT
2222 pQueryValue1Txt->SetFocus();
2223 }
2224 return;
e70e8f4c
GT
2225 } // Column 2 choice
2226
2227 // Add button
2228 if (widgetName == pQueryAddBtn->GetName())
2229 {
2230 ProcessAddBtn();
2231 return;
e70e8f4c
GT
2232 } // Add button
2233
2234 // And button
2235 if (widgetName == pQueryAndBtn->GetName())
2236 {
94613352 2237 AppendToWhere(wxT(" AND\n"));
e70e8f4c 2238 return;
e70e8f4c
GT
2239 } // And button
2240
2241 // Or button
2242 if (widgetName == pQueryOrBtn->GetName())
2243 {
94613352 2244 AppendToWhere(wxT(" OR\n"));
e70e8f4c 2245 return;
e70e8f4c
GT
2246 } // Or button
2247
2248 // Left Paren button
2249 if (widgetName == pQueryLParenBtn->GetName())
2250 {
94613352 2251 AppendToWhere(wxT("("));
e70e8f4c 2252 return;
e70e8f4c
GT
2253 } // Left Paren button
2254
2255 // Right paren button
2256 if (widgetName == pQueryRParenBtn->GetName())
2257 {
94613352 2258 AppendToWhere(wxT(")"));
e70e8f4c 2259 return;
e70e8f4c
GT
2260 } // Right Paren button
2261
2262 // Done button
2263 if (widgetName == pQueryDoneBtn->GetName())
2264 {
2265 // Be sure the where clause will not overflow the output buffer
3ca6a5f0 2266 if (wxStrlen(pQuerySqlWhereMtxt->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN)
e70e8f4c
GT
2267 {
2268 wxString s;
94613352
GT
2269 s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
2270 wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2271 return;
2272 }
2273 // Validate the where clause for things such as matching parens
2274 if (!ValidateWhereClause())
2275 return;
2276 // Copy the where clause to the output buffer and exit
d3358961 2277 pWhere = pQuerySqlWhereMtxt->GetValue();
e70e8f4c
GT
2278 Close();
2279 return;
e70e8f4c
GT
2280 } // Done button
2281
2282 // Clear button
2283 if (widgetName == pQueryClearBtn->GetName())
2284 {
94613352 2285 bool Ok = (wxMessageBox(wxT("Are you sure you wish to clear the Query?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
e70e8f4c
GT
2286
2287 if (Ok)
94613352 2288 pQuerySqlWhereMtxt->SetValue(wxT(""));
e70e8f4c 2289 return;
e70e8f4c
GT
2290 } // Clear button
2291
2292 // Count button
2293 if (widgetName == pQueryCountBtn->GetName())
2294 {
2295 wxBeginBusyCursor();
2296 ProcessCountBtn();
2297 wxEndBusyCursor();
2298 return;
e70e8f4c 2299 } // Count button
108106cf
JS
2300
2301} // CqueryDlg::OnCommand
2302
2303
e3065973 2304void CqueryDlg::OnCloseWindow(wxCloseEvent& event)
108106cf 2305{
e70e8f4c 2306 // Clean up
ea24eeb2 2307 wxDELETEA(colInf);
e70e8f4c 2308
ea24eeb2 2309 wxDELETE(dbTable);
e70e8f4c
GT
2310
2311 GetParent()->SetFocus();
2312 while (wxIsBusy())
2313 wxEndBusyCursor();
108106cf 2314
a4054ad1 2315 Show(FALSE);
3ca6a5f0 2316 SetReturnCode(1); // added so BoundsChecker would not report use of uninitialized variable
e3065973 2317
3ca6a5f0 2318 this->Destroy();
e3065973 2319} // CqueryDlg::OnCloseWindow()
108106cf 2320
108106cf 2321
94613352 2322void CqueryDlg::AppendToWhere(wxChar *s)
108106cf 2323{
3ca6a5f0
BP
2324 wxString whereStr = pQuerySqlWhereMtxt->GetValue();
2325 whereStr += s;
2326 pQuerySqlWhereMtxt->SetValue(whereStr);
108106cf
JS
2327} // CqueryDlg::AppendToWhere()
2328
2329
2330void CqueryDlg::ProcessAddBtn()
2331{
e70e8f4c
GT
2332 qryOp oper = (qryOp) pQueryOperatorChoice->GetSelection();
2333
2334 // Verify that eveything is filled in correctly
2335 if (pQueryCol2Choice->GetSelection() == 0) // "Value" is selected
2336 {
2337 // Verify that value 1 is filled in
f6bcfd97 2338 if (wxStrlen(pQueryValue1Txt->GetValue()) == 0)
e70e8f4c
GT
2339 {
2340 wxBell();
2341 pQueryValue1Txt->SetFocus();
2342 return;
2343 }
2344 // For the BETWEEN operator, value 2 must be filled in as well
2345 if (oper == qryOpBETWEEN &&
f6bcfd97 2346 wxStrlen(pQueryValue2Txt->GetValue()) == 0)
e70e8f4c
GT
2347 {
2348 wxBell();
2349 pQueryValue2Txt->SetFocus();
2350 return;
2351 }
2352 }
2353
2354 // Build the expression and append it to the where clause window
2355 wxString s = pQueryCol1Choice->GetStringSelection();
2356
2357 if (pQueryNotCheck->GetValue() && (oper != qryOpEQ))
94613352 2358 s += wxT(" NOT");
e70e8f4c
GT
2359
2360 switch(oper)
2361 {
2362 case qryOpEQ:
2363 if (pQueryNotCheck->GetValue()) // NOT box is checked
94613352 2364 s += wxT(" <>");
e70e8f4c 2365 else
94613352 2366 s += wxT(" =");
e70e8f4c
GT
2367 break;
2368 case qryOpLT:
94613352 2369 s += wxT(" <");
e70e8f4c
GT
2370 break;
2371 case qryOpGT:
94613352 2372 s += wxT(" >");
e70e8f4c
GT
2373 break;
2374 case qryOpLE:
94613352 2375 s += wxT(" <=");
e70e8f4c
GT
2376 break;
2377 case qryOpGE:
94613352 2378 s += wxT(" >=");
e70e8f4c
GT
2379 break;
2380 case qryOpBEGINS:
2381 case qryOpCONTAINS:
2382 case qryOpLIKE:
94613352 2383 s += wxT(" LIKE");
e70e8f4c
GT
2384 break;
2385 case qryOpBETWEEN:
94613352 2386 s += wxT(" BETWEEN");
e70e8f4c
GT
2387 break;
2388 }
2389
94613352 2390 s += wxT(" ");
e70e8f4c
GT
2391
2392 int col1Idx = pQueryCol1Choice->GetSelection();
2393
a4054ad1 2394 bool quote = FALSE;
e70e8f4c
GT
2395 if (colInf[col1Idx].sqlDataType == SQL_VARCHAR ||
2396 oper == qryOpBEGINS ||
2397 oper == qryOpCONTAINS ||
2398 oper == qryOpLIKE)
a4054ad1 2399 quote = TRUE;
e70e8f4c
GT
2400
2401 if (pQueryCol2Choice->GetSelection()) // Column name
2402 s += pQueryCol2Choice->GetStringSelection();
2403 else // Column 2 is a "value"
2404 {
2405 if (quote)
94613352 2406 s += wxT("'");
e70e8f4c 2407 if (oper == qryOpCONTAINS)
94613352 2408 s += wxT("%");
e70e8f4c
GT
2409 s += pQueryValue1Txt->GetValue();
2410 if (oper == qryOpCONTAINS || oper == qryOpBEGINS)
94613352 2411 s += wxT("%");
e70e8f4c 2412 if (quote)
94613352 2413 s += wxT("'");
e70e8f4c
GT
2414 }
2415
2416 if (oper == qryOpBETWEEN)
2417 {
94613352 2418 s += wxT(" AND ");
e70e8f4c 2419 if (quote)
94613352 2420 s += wxT("'");
e70e8f4c
GT
2421 s += pQueryValue2Txt->GetValue();
2422 if (quote)
94613352 2423 s += wxT("'");
e70e8f4c
GT
2424 }
2425
94613352 2426 AppendToWhere((wxChar*) (const wxChar*) s);
108106cf
JS
2427
2428} // CqueryDlg::ProcessAddBtn()
2429
2430
2431void CqueryDlg::ProcessCountBtn()
2432{
e70e8f4c
GT
2433 if (!ValidateWhereClause())
2434 return;
2435
3fe813a9 2436 if (!dbTable) // wxDbTable object needs to be created and opened
e70e8f4c 2437 {
3fe813a9
GT
2438 dbTable = new wxDbTable(pDB, masterTableName, 0, wxT(""),
2439 !wxDB_QUERY_ONLY,
2440 wxGetApp().DbConnectInf->GetDefaultDir());
2441 if (!dbTable)
e70e8f4c 2442 {
94613352 2443 wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2444 return;
2445 }
2446 if (!dbTable->Open())
2447 {
2448 wxString tStr;
f21b2fd8
GT
2449 tStr = wxT("ODBC error during Open()\n\n");
2450 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2451 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2452 return;
2453 }
2454 }
2455
2456 // Count() with WHERE clause
f6bcfd97 2457 wxString whereStr;
4c4a393f
GT
2458
2459 whereStr = pQuerySqlWhereMtxt->GetValue();
f6bcfd97 2460 dbTable->SetWhereClause(whereStr.c_str());
94613352 2461
e70e8f4c
GT
2462 ULONG whereCnt = dbTable->Count();
2463
2464 // Count() of all records in the table
94613352 2465 dbTable->SetWhereClause(wxT(""));
e70e8f4c
GT
2466 ULONG totalCnt = dbTable->Count();
2467
2468 if (whereCnt > 0 || totalCnt == 0)
2469 {
2470 wxString tStr;
94613352
GT
2471 tStr.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt,totalCnt);
2472 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
e70e8f4c
GT
2473 }
2474 else
2475 {
2476 wxString tStr;
94613352
GT
2477 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);
2478 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
e70e8f4c
GT
2479 }
2480
2481 // After a wxMessageBox, the focus does not necessarily return to the
2482 // window which was the focus when the message box popped up, so return
2483 // focus to the Query dialog for certain
2484 SetFocus();
108106cf
JS
2485
2486} // CqueryDlg::ProcessCountBtn()
2487
2488
1fc5dd6f 2489bool CqueryDlg::ValidateWhereClause()
108106cf 2490{
e70e8f4c
GT
2491 wxString where = pQuerySqlWhereMtxt->GetValue();
2492
94613352 2493 if (where.Freq(wxT('(')) != where.Freq(wxT(')')))
e70e8f4c 2494 {
94613352 2495 wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 2496 return(FALSE);
e70e8f4c
GT
2497 }
2498 // After a wxMessageBox, the focus does not necessarily return to the
2499 // window which was the focus when the message box popped up, so return
2500 // focus to the Query dialog for certain
2501 SetFocus();
2502
a4054ad1 2503 return(TRUE);
108106cf
JS
2504
2505} // CqueryDlg::ValidateWhereClause()
3f755e2d
GT
2506
2507
2508
3f030b48
GT
2509void DisplayDbDiagnostics(wxDb *pDb)
2510{
69a2b59d 2511 wxString s, t;
a4054ad1 2512 bool comma = FALSE;
69a2b59d
GT
2513
2514 s = langDBINF_DB_NAME;
2515 s += pDb->dbInf.dbmsName;
2516 s += "\n";
2517
2518 s += langDBINF_DB_VER;
2519 s += pDb->dbInf.dbmsVer;
2520 s += "\n";
2521
2522 s += langDBINF_DRIVER_NAME;
2523 s += pDb->dbInf.driverName;
2524 s += "\n";
2525
2526 s += langDBINF_DRIVER_ODBC_VER;
2527 s += pDb->dbInf.odbcVer;
2528 s += "\n";
2529
2530 s += langDBINF_DRIVER_MGR_ODBC_VER;
2531 s += pDb->dbInf.drvMgrOdbcVer;
2532 s += "\n";
2533
2534 s += langDBINF_DRIVER_VER;
2535 s += pDb->dbInf.driverVer;
2536 s += "\n";
2537
2538 s += langDBINF_SERVER_NAME;
2539 s += pDb->dbInf.serverName;
2540 s += "\n";
2541
2542 s += langDBINF_FILENAME;
2543 s += pDb->dbInf.databaseName;
2544 s += "\n";
2545
2546 s += langDBINF_OUTER_JOINS;
2547 s += pDb->dbInf.outerJoins;
2548 s += "\n";
2549
2550 s += langDBINF_STORED_PROC;
2551 s += pDb->dbInf.procedureSupport;
2552 s += "\n";
2553
2554 if (pDb->dbInf.maxConnections)
2555 t.sprintf("%s%d\n", langDBINF_MAX_HDBC, pDb->dbInf.maxConnections);
2556 else
2557 t.sprintf("%s%s\n", langDBINF_MAX_HDBC, langDBINF_UNLIMITED);
2558 s += t;
2559
2560 if (pDb->dbInf.maxStmts)
2561 t.sprintf("%s%d\n", langDBINF_MAX_HSTMT, pDb->dbInf.maxStmts);
2562 else
2563 t.sprintf("%s%s\n", langDBINF_MAX_HSTMT, langDBINF_UNLIMITED);
2564 s += t;
2565
2566 s += langDBINF_API_LVL;
2567 switch(pDb->dbInf.apiConfLvl)
2568 {
2569 case SQL_OAC_NONE: s += langDBINF_NONE; break;
2570 case SQL_OAC_LEVEL1: s += langDBINF_LEVEL1; break;
2571 case SQL_OAC_LEVEL2: s += langDBINF_LEVEL2; break;
2572 }
2573 s += "\n";
2574
2575 s += langDBINF_CLI_LVL;
2576 switch(pDb->dbInf.cliConfLvl)
2577 {
2578 case SQL_OSCC_NOT_COMPLIANT: s += langDBINF_NOT_COMPLIANT; break;
2579 case SQL_OSCC_COMPLIANT: s += langDBINF_COMPLIANT; break;
2580 }
2581 s += "\n";
2582
2583 s += langDBINF_SQL_LVL;
2584 switch(pDb->dbInf.sqlConfLvl)
2585 {
2586 case SQL_OSC_MINIMUM: s += langDBINF_MIN_GRAMMAR; break;
2587 case SQL_OSC_CORE: s += langDBINF_CORE_GRAMMAR; break;
2588 case SQL_OSC_EXTENDED: s += langDBINF_EXT_GRAMMAR; break;
2589 }
2590 s += "\n";
2591
2592 s += langDBINF_COMMIT_BEHAVIOR;
2593 switch(pDb->dbInf.cursorCommitBehavior)
2594 {
2595 case SQL_CB_DELETE: s += langDBINF_DELETE_CURSORS; break;
2596 case SQL_CB_CLOSE: s += langDBINF_CLOSE_CURSORS; break;
2597 case SQL_CB_PRESERVE: s += langDBINF_PRESERVE_CURSORS; break;
2598 }
2599 s += "\n";
2600
2601 s += langDBINF_ROLLBACK_BEHAVIOR;
2602 switch(pDb->dbInf.cursorRollbackBehavior)
2603 {
2604 case SQL_CB_DELETE: s += langDBINF_DELETE_CURSORS; break;
2605 case SQL_CB_CLOSE: s += langDBINF_CLOSE_CURSORS; break;
2606 case SQL_CB_PRESERVE: s += langDBINF_PRESERVE_CURSORS; break;
2607 }
2608 s += "\n";
2609
2610 s += langDBINF_SUPP_NOT_NULL;
2611 switch(pDb->dbInf.supportNotNullClause)
2612 {
2613 case SQL_NNC_NULL: s += langNO; break;
2614 case SQL_NNC_NON_NULL: s += langYES; break;
2615 }
2616 s += "\n";
2617
2618 s += langDBINF_SUPP_IEF;
2619 s += pDb->dbInf.supportIEF;
2620 s += "\n";
2621
2622 // DEFAULT setting for "Transaction Isolation Level"
2623 s += langDBINF_TXN_ISOLATION;
2624 switch(pDb->dbInf.txnIsolation)
2625 {
2626 case SQL_TXN_READ_UNCOMMITTED: s += langDBINF_READ_UNCOMMITTED; break;
2627 case SQL_TXN_READ_COMMITTED: s += langDBINF_READ_COMMITTED; break;
2628 case SQL_TXN_REPEATABLE_READ: s += langDBINF_REPEATABLE_READ; break;
2629 case SQL_TXN_SERIALIZABLE: s += langDBINF_SERIALIZABLE; break;
3f030b48 2630#ifdef ODBC_V20
69a2b59d
GT
2631 case SQL_TXN_VERSIONING: s += langDBINF_VERSIONING; break;
2632#endif
2633 }
2634 s += "\n";
2635
2636 // CURRENT setting for "Transaction Isolation Level"
2637 long txnIsoLvl;
2638 s += langDBINF_TXN_ISOLATION_CURR;
2639 if (SQLGetConnectOption(pDb->GetHDBC(),SQL_TXN_ISOLATION,&txnIsoLvl) == SQL_SUCCESS)
2640 {
2641 switch(txnIsoLvl)
2642 {
2643 case SQL_TXN_READ_UNCOMMITTED: s += langDBINF_READ_UNCOMMITTED; break;
2644 case SQL_TXN_READ_COMMITTED: s += langDBINF_READ_COMMITTED; break;
2645 case SQL_TXN_REPEATABLE_READ: s += langDBINF_REPEATABLE_READ; break;
2646 case SQL_TXN_SERIALIZABLE: s += langDBINF_SERIALIZABLE; break;
3f030b48 2647#ifdef ODBC_V20
69a2b59d
GT
2648 case SQL_TXN_VERSIONING: s += langDBINF_VERSIONING; break;
2649#endif
2650 }
2651 }
2652 s += "\n";
2653
a4054ad1 2654 comma = FALSE;
69a2b59d
GT
2655 s += langDBINF_TXN_ISOLATION_OPTS;
2656 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_UNCOMMITTED)
2657 {s += langDBINF_READ_UNCOMMITTED; comma++;}
2658 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_COMMITTED)
2659 {if (comma++) s += ", "; s += langDBINF_READ_COMMITTED;}
2660 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_REPEATABLE_READ)
2661 {if (comma++) s += ", "; s += langDBINF_REPEATABLE_READ;}
2662 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_SERIALIZABLE)
2663 {if (comma++) s += ", "; s += langDBINF_SERIALIZABLE;}
3f030b48 2664#ifdef ODBC_V20
69a2b59d
GT
2665 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_VERSIONING)
2666 {if (comma++) s += ", "; s += langDBINF_VERSIONING;}
2667#endif
2668 s += "\n";
2669
a4054ad1 2670 comma = FALSE;
69a2b59d
GT
2671 s += langDBINF_FETCH_DIRS;
2672 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_NEXT)
2673 {s += langDBINF_NEXT; comma++;}
2674 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_PRIOR)
2675 {if (comma++) s += ", "; s += langDBINF_PREV;}
2676 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_FIRST)
2677 {if (comma++) s += ", "; s += langDBINF_FIRST;}
2678 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_LAST)
2679 {if (comma++) s += ", "; s += langDBINF_LAST;}
2680 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_ABSOLUTE)
2681 {if (comma++) s += ", "; s += langDBINF_ABSOLUTE;}
2682 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RELATIVE)
2683 {if (comma++) s += ", "; s += langDBINF_RELATIVE;}
3f030b48 2684#ifdef ODBC_V20
69a2b59d
GT
2685 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RESUME)
2686 {if (comma++) s += ", "; s += langDBINF_RESUME;}
2687#endif
2688 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_BOOKMARK)
2689 {if (comma++) s += ", "; s += langDBINF_BOOKMARK;}
2690 s += "\n";
2691
a4054ad1 2692 comma = FALSE;
69a2b59d
GT
2693 s += langDBINF_LOCK_TYPES;
2694 if (pDb->dbInf.lockTypes & SQL_LCK_NO_CHANGE)
2695 {s += langDBINF_NO_CHANGE; comma++;}
2696 if (pDb->dbInf.lockTypes & SQL_LCK_EXCLUSIVE)
2697 {if (comma++) s += ", "; s += langDBINF_EXCLUSIVE;}
2698 if (pDb->dbInf.lockTypes & SQL_LCK_UNLOCK)
2699 {if (comma++) s += ", "; s += langDBINF_UNLOCK;}
2700 s += "\n";
2701
a4054ad1 2702 comma = FALSE;
69a2b59d
GT
2703 s += langDBINF_POS_OPERS;
2704 if (pDb->dbInf.posOperations & SQL_POS_POSITION)
2705 {s += langDBINF_POSITION; comma++;}
2706 if (pDb->dbInf.posOperations & SQL_POS_REFRESH)
2707 {if (comma++) s += ", "; s += langDBINF_REFRESH;}
2708 if (pDb->dbInf.posOperations & SQL_POS_UPDATE)
2709 {if (comma++) s += ", "; s += langDBINF_UPD;}
2710 if (pDb->dbInf.posOperations & SQL_POS_DELETE)
2711 {if (comma++) s += ", "; s += langDBINF_DEL;}
2712 if (pDb->dbInf.posOperations & SQL_POS_ADD)
2713 {if (comma++) s += ", "; s += langDBINF_ADD;}
2714 s += "\n";
2715
a4054ad1 2716 comma = FALSE;
69a2b59d
GT
2717 s += langDBINF_POS_STMTS;
2718 if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_DELETE)
2719 {s += langDBINF_POS_DEL; comma++;}
2720 if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_UPDATE)
2721 {if (comma++) s += ", "; s += langDBINF_POS_UPD;}
2722 if (pDb->dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
2723 {if (comma++) s += ", "; s += langDBINF_SELECT_FOR_UPD;}
2724 s += "\n";
2725
a4054ad1 2726 comma = FALSE;
69a2b59d
GT
2727 s += langDBINF_SCROLL_CONCURR;
2728 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_READ_ONLY)
2729 {s += langDBINF_READ_ONLY; comma++;}
2730 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_LOCK)
2731 {if (comma++) s += ", "; s += langDBINF_LOCK;}
2732 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_ROWVER)
2733 {if (comma++) s += ", "; s += langDBINF_OPT_ROWVER;}
2734 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_VALUES)
2735 {if (comma++) s += ", "; s += langDBINF_OPT_VALUES;}
2736 s += "\n";
2737
a4054ad1 2738 comma = FALSE;
69a2b59d
GT
2739 s += langDBINF_SCROLL_OPTS;
2740 if (pDb->dbInf.scrollOptions & SQL_SO_FORWARD_ONLY)
2741 {s += langDBINF_FWD_ONLY; comma++;}
2742 if (pDb->dbInf.scrollOptions & SQL_SO_STATIC)
2743 {if (comma++) s += ", "; s += langDBINF_STATIC;}
2744 if (pDb->dbInf.scrollOptions & SQL_SO_KEYSET_DRIVEN)
2745 {if (comma++) s += ", "; s += langDBINF_KEYSET_DRIVEN;}
2746 if (pDb->dbInf.scrollOptions & SQL_SO_DYNAMIC)
2747 {if (comma++) s += ", "; s += langDBINF_DYNAMIC;}
2748 if (pDb->dbInf.scrollOptions & SQL_SO_MIXED)
2749 {if (comma++) s += ", "; s += langDBINF_MIXED;}
2750 s += "\n";
2751
a4054ad1 2752 comma = FALSE;
69a2b59d
GT
2753 s += langDBINF_STATIC_SENS;
2754 if (pDb->dbInf.staticSensitivity & SQL_SS_ADDITIONS)
2755 {s += langDBINF_ADDITIONS; comma++;}
2756 if (pDb->dbInf.staticSensitivity & SQL_SS_DELETIONS)
2757 {if (comma++) s += ", "; s += langDBINF_DELETIONS;}
2758 if (pDb->dbInf.staticSensitivity & SQL_SS_UPDATES)
2759 {if (comma++) s += ", "; s += langDBINF_UPDATES;}
2760 s += "\n";
2761
2762
2763 s += langDBINF_TXN_CAPABLE;
2764 switch(pDb->dbInf.txnCapable)
2765 {
2766 case SQL_TC_NONE: s += langNO; break;
2767 case SQL_TC_DML: s += langDBINF_DML_ONLY; break;
2768 case SQL_TC_DDL_COMMIT: s += langDBINF_DDL_COMMIT; break;
2769 case SQL_TC_DDL_IGNORE: s += langDBINF_DDL_IGNORE; break;
2770 case SQL_TC_ALL: s += langDBINF_DDL_AND_DML; break;
2771 }
2772 s += "\n";
2773
2774 t.sprintf("%s%d\n", langDBINF_LOGIN_TIMEOUT, pDb->dbInf.loginTimeout);
2775 s += t;
2776
2777 // Oracle specific information
2778 if (pDb->Dbms() == dbmsORACLE)
2779 {
2780 s += "\n";
2781 s += langDBINF_ORACLE_BANNER;
2782 s += "\n";
2783
2784 // Oracle cache hit ratio
2785 SDWORD cb;
2786 ULONG dbBlockGets;
2787 pDb->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'");
2788 pDb->GetNext();
2789 if (pDb->GetData(1, SQL_C_ULONG, &dbBlockGets, 0, &cb))
2790 {
2791 t.sprintf("%s: %lu\n", langDBINF_DB_BLOCK_GETS, dbBlockGets);
2792 s += t;
2793 }
2794
2795 ULONG consistentGets;
2796 pDb->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'");
2797 pDb->GetNext();
2798 if (pDb->GetData(1, SQL_C_ULONG, &consistentGets, 0, &cb))
2799 {
2800 t.sprintf("%s: %lu\n", langDBINF_CONSISTENT_GETS, consistentGets);
2801 s += t;
2802 }
2803
2804 ULONG physReads;
2805 pDb->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'");
2806 pDb->GetNext();
2807 if (pDb->GetData(1, SQL_C_ULONG, &physReads, 0, &cb))
2808 {
2809 t.sprintf("%s: %lu\n", langDBINF_PHYSICAL_READS, physReads);
2810 s += t;
2811 }
2812
2813 ULONG hitRatio = (ULONG)((1.00 - ((float)physReads / (float)(dbBlockGets + consistentGets))) * 100.00);
2814 t.sprintf("*** %s: %lu%%\n", langDBINF_CACHE_HIT_RATIO, hitRatio);
2815 s += t;
2816
2817 // Tablespace information
2818 s += "\n";
2819 s += langDBINF_TABLESPACE_IO;
2820 s += "\n";
2821 ULONG physWrites;
2822 char tablespaceName[257];
2823 pDb->ExecSql("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#");
2824 while (pDb->GetNext())
2825 {
2826 pDb->GetData(1, SQL_C_CHAR, tablespaceName, 257, &cb);
2827 pDb->GetData(2, SQL_C_ULONG, &physReads, 0, &cb);
2828 pDb->GetData(3, SQL_C_ULONG, &physWrites, 0, &cb);
2829 t.sprintf("%s\n\t%s: %lu\t%s: %lu\n", tablespaceName,
2830 langDBINF_PHYSICAL_READS, physReads, langDBINF_PHYSICAL_WRITES, physWrites);
2831 s += t;
2832 }
2833
2834 s += "\n";
2835 }
3f030b48
GT
2836
2837 wxLogMessage(s);
2838
2839} // DisplayDbDiagnostics()
2840
f21b2fd8
GT
2841#if wxUSE_NEW_GRID
2842
2843BEGIN_EVENT_TABLE(DbGridFrame, wxFrame)
2844 // EVT_CLOSE(DbGridFrame::OnCloseWindow)
2845END_EVENT_TABLE()
2846
2847
2848DbGridFrame::DbGridFrame(wxWindow *parent)
2849 : wxFrame (parent, -1, wxT("Database Table"),
2850 wxDefaultPosition, wxSize(400, 325))
2851{
a4054ad1 2852 initialized = FALSE;
f21b2fd8
GT
2853}
2854
2855
2856void DbGridFrame::OnCloseWindow(wxCloseEvent& event)
2857{
2858 this->Destroy();
2859}
2860
2861
2862bool DbGridFrame::Initialize()
2863{
2864 wxGrid *grid = new wxGrid(this, -1, wxDefaultPosition);
2865
2866 grid->RegisterDataType(wxGRID_VALUE_DATETIME,
2867 new wxGridCellDateTimeRenderer(_T("%d %b %Y")),
2868 new wxGridCellTextEditor);
2869#ifdef CHOICEINT
2870 grid->RegisterDataType(wxGRID_VALUE_CHOICEINT,
2871 new wxGridCellEnumRenderer,
2872 new wxGridCellEnumEditor);
2873
2874 wxString NativeLangChoice( wxString::Format("%s:%s,%s,%s,%s,%s",wxGRID_VALUE_CHOICEINT,
2875 wxT("English"),
2876 wxT("French"),
2877 wxT("German"),
2878 wxT("Spanish"),
2879 wxT("Other") ));
2880#endif
2881
2882 // Columns must match the sequence specified in SetColDef() calls
2883 wxDbGridColInfo* cols =
2884 new wxDbGridColInfo( 0,wxGRID_VALUE_STRING,wxT("Name"),
2885 new wxDbGridColInfo( 1,wxGRID_VALUE_STRING,wxT("Address 1"),
2886 new wxDbGridColInfo( 2,wxGRID_VALUE_STRING,wxT("Address 2"),
2887 new wxDbGridColInfo( 3,wxGRID_VALUE_STRING,wxT("City"),
2888 new wxDbGridColInfo( 4,wxGRID_VALUE_STRING,wxT("State"),
2889 new wxDbGridColInfo( 5,wxGRID_VALUE_STRING,wxT("PostCode"),
2890 new wxDbGridColInfo( 6,wxGRID_VALUE_STRING,wxT("Country"),
2891 new wxDbGridColInfo( 7,wxGRID_VALUE_DBAUTO,wxT("Join Date"),
2892 new wxDbGridColInfo( 8,wxGRID_VALUE_BOOL, wxT("Developer"),
2893 new wxDbGridColInfo( 9,wxGRID_VALUE_NUMBER,wxT("Contributions"),
2894 new wxDbGridColInfo(10,wxGRID_VALUE_NUMBER,wxT("Lines Of Code"),
2895#ifdef CHOICEINT
2896 new wxDbGridColInfo(11,NativeLangChoice, wxT("Native Language"),NULL))))))))))));
2897#else
2898 new wxDbGridColInfo(11,wxGRID_VALUE_NUMBER,wxT("Native Language"),NULL))))))))))));
2899#endif
2900
2901 Ccontact *Contact = new Ccontact();
2902 //wxGetApp().Contact
2903
2904 if (!Contact)
2905 {
2906 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"), wxT("Error..."), wxOK | wxICON_EXCLAMATION);
a4054ad1 2907 return FALSE;
f21b2fd8
GT
2908 }
2909
2910 if (!Contact->Open())
2911 {
2912 if (Contact->GetDb()->TableExists(CONTACT_TABLE_NAME, Contact->GetDb()->GetUsername(),
2913 wxGetApp().DbConnectInf->GetDefaultDir()))
2914 {
2915 wxString tStr;
2916 tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME);
2917 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2918 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2919 }
2920
a4054ad1 2921 return FALSE;
f21b2fd8
GT
2922 }
2923
2924 // Execute the following query using the cursor designated
2925 // for full table query
2926 Contact->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY);
2927
2928 if (!Contact->Query())
2929 {
2930 wxString tStr;
2931 tStr = wxT("ODBC error during Query()\n\n");
2932 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2933 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 2934 return FALSE;
f21b2fd8
GT
2935 }
2936
2937 // No data has been read in from the database yet, so
2938 // we need to initialize the data members to valid values
2939 // so Fit() can correctly size the grid
2940 Contact->Initialize();
2941
a4054ad1 2942 wxDbGridTableBase* db = new wxDbGridTableBase(Contact, cols, wxUSE_QUERY, TRUE);
f21b2fd8
GT
2943
2944 delete cols;
2945
a4054ad1 2946 grid->SetTable(db,TRUE);
f21b2fd8 2947 grid->SetMargins(0, 0);
3f030b48 2948
f21b2fd8
GT
2949 grid->Fit();
2950 wxSize size = grid->GetSize();
2951 size.x += 10;
2952 size.y += 10;
2953 SetClientSize(size);
a4054ad1
GT
2954 initialized = TRUE;
2955 return TRUE;
f21b2fd8 2956} // DbGridFrame::Initialize()
3f030b48 2957
f21b2fd8 2958#endif // #if wxUSE_NEW_GRID
3f755e2d
GT
2959
2960/*
2961 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2962
2963 int result = 0;
a4054ad1 2964 result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"),wxT("GLT-TEST2"),wxT("GLT-Descrip"),FALSE,wxT(""),this);
3f755e2d
GT
2965 if (!result)
2966 {
2967 // check for errors caused by ConfigDSN based functions
2968 DWORD retcode = 0;
2969 WORD cb;
2970 wxChar errMsg[500+1];
94613352 2971 errMsg[0] = wxT('\0');
3f755e2d
GT
2972
2973 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2974
94613352 2975 wxMessageBox(wxT("FAILED creating data source"),wxT("FAILED"));
3f755e2d
GT
2976 }
2977 else
94613352 2978 wxMessageBox(wxT("SUCCEEDED creating data source"),wxT("SUCCESS"));
3f755e2d
GT
2979*/
2980
2981