- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1508 lines
53 KiB
C++
1508 lines
53 KiB
C++
// BDE - (C) Copyright 1994 by Borland International
|
|
|
|
#include "query.h"
|
|
|
|
#define FILEHANDLESNEEDED 40
|
|
|
|
static char szStandard[] = "<STANDARD>";
|
|
|
|
static DBStructArray dbarray; // Global array of structures containing
|
|
// database connections (hDb's) and names.
|
|
|
|
static int iSelectedDbIndex; // Index to currently selected
|
|
// database connection.
|
|
|
|
void SetSelected(HWND hDlg);
|
|
|
|
//=================================================================
|
|
// Function:
|
|
// WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
|
|
//
|
|
// Input: hInstance - The handle that represents the applications
|
|
// unique instance ID
|
|
// hPrevInstance - Indicates if this is the first instance
|
|
// of the app
|
|
// lpCmdLine - Command line parameters (up to the app
|
|
// to parse)
|
|
// nCmdShow - TRUE = Show as non-icon application
|
|
//
|
|
// Return: Exit code (wParam value of WM_QUIT message)
|
|
//
|
|
// Description:
|
|
// This is the application entry point for the Query sample
|
|
// application. It will set up the app, init the instance,
|
|
// process all event driven messages, and clean up the
|
|
// application prior to returning to Windows.
|
|
//=================================================================
|
|
int _pascal
|
|
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
|
|
lpCmdLine = lpCmdLine;
|
|
nCmdShow = nCmdShow;
|
|
|
|
// Register CTL3D
|
|
Ctl3dRegister(hInstance);
|
|
Ctl3dAutoSubclass(hInstance);
|
|
|
|
// Make this a single instance program
|
|
if (hPrevInstance)
|
|
{
|
|
MessageBox(GetFocus(), "This application is already running!",
|
|
"Windows Driver", MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Start the application, and set the main dialog to not show until
|
|
// everything is setup.
|
|
hInst = hInstance;
|
|
if (InitApp(SW_SHOW) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Process all event driven messages.
|
|
while (GetMessage(&msg, NULL, NULL, NULL))
|
|
{
|
|
if ((hMainWnd == NULL) || (!IsDialogMessage(hMainWnd, &msg)))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
// Unregister CTL3D.
|
|
Ctl3dUnregister(hInstance);
|
|
|
|
return msg.wParam;
|
|
}
|
|
|
|
//====================================================================
|
|
// Function:
|
|
// InitApp(nCmdShow);
|
|
//
|
|
// Input: nCmdShow - Show the main window
|
|
//
|
|
// Return: TRUE - Init worked
|
|
// FALSE - Init failed
|
|
//
|
|
// Description:
|
|
// Create the application window & init any default
|
|
// of the main window.
|
|
//====================================================================
|
|
BOOL
|
|
InitApp (int nCmdShow)
|
|
{
|
|
WNDCLASS wc;
|
|
UINT16 i;
|
|
UINT16 uCount;
|
|
// Path returned by the GetPrivateProfileString() function
|
|
CHAR szRelativeTblDirectory[DBIMAXPATHLEN+1];
|
|
CHAR szMessage[(DBIMAXMSGLEN * 2)]; // Allocate enough space to
|
|
// contain message
|
|
|
|
// Init the application & create the needed windows.
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = MainWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = DLGWINDOWEXTRA;
|
|
wc.hInstance = hInst;
|
|
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(9999));
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = "MainWindowClass";
|
|
|
|
// Register the class.
|
|
if (!RegisterClass(&wc))
|
|
{
|
|
MessageBox(NULL, "RegisterClass failed!", "System Error",
|
|
MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Increase the number of file handles that are available to the
|
|
// system.
|
|
uCount = SetHandleCount(FILEHANDLESNEEDED);
|
|
if (uCount < FILEHANDLESNEEDED)
|
|
{
|
|
MessageBox(NULL, "Not enough file handles available. Please set"
|
|
" FILES=40 in your CONFIG.SYS.", "System Error",
|
|
MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the directory which contains the tables.
|
|
GetPrivateProfileString("QUERY",
|
|
"TblDir",
|
|
"..\\TABLES",
|
|
(LPSTR)szRelativeTblDirectory,
|
|
sizeof(szRelativeTblDirectory),
|
|
"bde.ini");
|
|
|
|
// Create a fully qualified pathname for the table directory.
|
|
if (MakeFullPath(szTblDirectory, szRelativeTblDirectory))
|
|
{
|
|
sprintf(szMessage, "Table Directory does not exist: %s",
|
|
szTblDirectory);
|
|
MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the private directory.
|
|
GetPrivateProfileString("QUERY",
|
|
"PrivateDir",
|
|
".",
|
|
(LPSTR)szRelativeTblDirectory,
|
|
sizeof(szRelativeTblDirectory),
|
|
"bde.ini");
|
|
|
|
// Create a fully qualified pathname for the table directory.
|
|
if (MakeFullPath(szPrivDirectory, szRelativeTblDirectory))
|
|
{
|
|
sprintf(szMessage, "Private Directory does not exist: %s."
|
|
"\r\nPlease check BDE.INI in your Windows directory.",
|
|
szPrivDirectory);
|
|
MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Initialize Database Engine.
|
|
if (QueryDbiInit() != DBIERR_NONE)
|
|
{
|
|
MessageBox(NULL, "Application will terminate", "Error", MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
// Explicitly initialize global array.
|
|
for (i = 0; i < MAX_DATABASE_HANDLES; i++)
|
|
{
|
|
dbarray[i].hdb = 0;
|
|
dbarray[i].szDatabaseName[0] = '\0';
|
|
}
|
|
|
|
// Create the dialog that serves as the main window.
|
|
hMainWnd = CreateDialog(hInst, "MainDlg", 0, NULL);
|
|
if (hMainWnd == NULL)
|
|
{
|
|
MessageBox(NULL, "CreateDialog failed!", "System Error",
|
|
MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
_wpOrigWndProc = SubClassWindow(GetDlgItem(hMainWnd, IDC_QUERY_EDIT),
|
|
EditSubClassProc);
|
|
|
|
_wpOrigWndProc1 = SubClassWindow(GetDlgItem(hMainWnd, IDC_RESULT_EDIT),
|
|
EditSubClassProc);
|
|
|
|
ShowWindow(hMainWnd, nCmdShow);
|
|
return TRUE;
|
|
}
|
|
|
|
// ===============================================================
|
|
// Function:
|
|
// MainWndProc(hWnd, msg, wParam, lParam);
|
|
//
|
|
// Description:
|
|
// This routine will process all messages for the primary
|
|
// application window. Included in this are all menu
|
|
// commands.
|
|
// ===============================================================
|
|
LRESULT CALLBACK
|
|
MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static FARPROC lpfnConnectDlgProc;
|
|
static DLGPROC lpfnAboutDlgProc;
|
|
static DBIQryLang eQryLang;
|
|
static CBPROGRESSDesc CbBuf;
|
|
char * szQuery = NULL;
|
|
static hDBICur hCur = 0;
|
|
DBIResult rslt;
|
|
LONG lTextLength;
|
|
static char szOutputErrorString[(DBIMAXMSGLEN * 6) + 80];
|
|
static char szSelectedDatabase[80];
|
|
static HFONT hFont;
|
|
DWORD lMinMax; // Contains both offset of first and
|
|
// last selected characters
|
|
WORD iStart; // Offset of first selected character
|
|
WORD iEnd; // Offset of last selected character
|
|
HWND hwnd;
|
|
HBRUSH hBrush;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_CREATE:
|
|
eQryLang = qrylangSQL;
|
|
|
|
// Set up default database.
|
|
dbarray[0].hdb = QueryGetStandardConnection();
|
|
iSelectedDbIndex = 0;
|
|
strcpy(dbarray[iSelectedDbIndex].szDatabaseName, szStandard);
|
|
|
|
if (dbarray[iSelectedDbIndex].hdb == 0)
|
|
{
|
|
MessageBox(NULL, "Unable to create STANDARD standard "
|
|
"database.", "Application Error",
|
|
MB_ICONHAND);
|
|
}
|
|
PostMessage(hWnd, WM_SETUP, 0, 0);
|
|
return FALSE;
|
|
|
|
case WM_SETUP:
|
|
hwnd = GetWindow(hWnd, GW_CHILD);
|
|
while (hwnd != NULL)
|
|
{
|
|
Ctl3dSubclassCtl(hwnd);
|
|
hwnd = GetWindow(hwnd, GW_HWNDNEXT);
|
|
}
|
|
|
|
if (! SendDlgItemMessage(hWnd, IDC_RADIO_QBE, BM_GETCHECK, 0, 0))
|
|
{
|
|
SendDlgItemMessage(hWnd, IDC_RADIO_SQL, BM_SETCHECK, 1, 0);
|
|
}
|
|
|
|
// Set the font of the edit controls to be a fixed pitch font.
|
|
hFont = (HFONT) GetStockObject(ANSI_FIXED_FONT);
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_SETFONT,
|
|
(WPARAM) hFont, FALSE);
|
|
SendDlgItemMessage(hWnd, IDC_RESULT_EDIT, WM_SETFONT,
|
|
(WPARAM) hFont, FALSE);
|
|
|
|
break;
|
|
|
|
case WM_CTLCOLOR:
|
|
hBrush = Ctl3dCtlColorEx(msg, wParam, lParam);
|
|
if (hBrush != (HBRUSH)0)
|
|
{
|
|
return (long)(WORD)hBrush;
|
|
}
|
|
else
|
|
{
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
Ctl3dColorChange();
|
|
return TRUE;
|
|
|
|
case WM_NCPAINT:
|
|
case WM_NCACTIVATE:
|
|
case WM_SETTEXT:
|
|
return Ctl3dDlgFramePaint(hWnd, msg, wParam, lParam);
|
|
|
|
case WM_SETFOCUS:
|
|
// Need to set the focus to the first element of the dialog box.
|
|
SetFocus(GetDlgItem(hWnd, IDC_QUERY_EDIT));
|
|
|
|
// Set static control displaying currently selected database.
|
|
if (dbarray[iSelectedDbIndex].hdb == NULL)
|
|
{
|
|
sprintf(szSelectedDatabase, "No connection established");
|
|
}
|
|
else
|
|
{
|
|
sprintf(szSelectedDatabase, "Current connection: %s",
|
|
dbarray[iSelectedDbIndex].szDatabaseName);
|
|
}
|
|
SendDlgItemMessage(hWnd, IDS_CURRENT_CONNECTION,
|
|
WM_SETTEXT, 0, (LPARAM) szSelectedDatabase);
|
|
|
|
return FALSE;
|
|
|
|
case WM_CLOSE:
|
|
// Done to get rid of the "Parameter Not used" warning.
|
|
// Done in this way in order to work with both BC++ and VC++.
|
|
lParam = lParam;
|
|
DestroyWindow(hWnd);
|
|
return FALSE;
|
|
|
|
case WM_DESTROY:
|
|
CleanUpAnswer(&hCur);
|
|
QueryDbiExit();
|
|
PostQuitMessage(0);
|
|
return FALSE;
|
|
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDC_EXIT:
|
|
DestroyWindow(hWnd);
|
|
return TRUE;
|
|
|
|
case IDC_RUN:
|
|
// Allow query to be run only if we have a
|
|
// valid database handle.
|
|
if (dbarray[0].hdb == 0)
|
|
{
|
|
MessageBox(NULL,
|
|
"No database connection established",
|
|
"Query SQL/QBE Example", MB_OK);
|
|
}
|
|
else
|
|
{
|
|
Cls();
|
|
DisplayProgress("");
|
|
|
|
// Get the length of the query from the Query edit
|
|
// control.
|
|
lTextLength = SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
|
|
WM_GETTEXTLENGTH,
|
|
0, 0);
|
|
|
|
// Allocate space to contain the query.
|
|
if ((szQuery = (char*) malloc((int) lTextLength + 1))
|
|
== NULL)
|
|
{
|
|
MessageBox(NULL, "Out of Memory!",
|
|
"Fatal Error", MB_ICONHAND);
|
|
return TRUE;
|
|
}
|
|
|
|
HourGlassCursor(TRUE);
|
|
|
|
// Setup the callback.
|
|
RegisterCallBack(hCur, cbGENPROGRESS,
|
|
(UINT32)"Query Data",
|
|
sizeof(CBPROGRESSDesc),
|
|
(pVOID)&CbBuf, GenProgCallBack);
|
|
|
|
// Get the text of the query from the Query edit
|
|
// control.
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_GETTEXT,
|
|
(int) lTextLength + 1,
|
|
(LPARAM) szQuery);
|
|
|
|
// Close the cursor if it is open.
|
|
CleanUpAnswer(&hCur);
|
|
|
|
// Execute the query.
|
|
rslt = QueryQExec(dbarray[iSelectedDbIndex].hdb,
|
|
eQryLang, szQuery,
|
|
szOutputErrorString, &hCur);
|
|
|
|
|
|
// Remove Callback function.
|
|
RegisterCallBack(hCur, cbGENPROGRESS,
|
|
(UINT32)"Query Data",
|
|
sizeof(CBPROGRESSDesc),
|
|
(pVOID)&CbBuf, NULL);
|
|
|
|
if (szQuery)
|
|
{
|
|
free(szQuery);
|
|
}
|
|
|
|
// Check if query failed.
|
|
if (rslt != DBIERR_NONE)
|
|
{
|
|
Cls();
|
|
Screen(szOutputErrorString);
|
|
|
|
HourGlassCursor(FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
// Terminate if no cursor was returned.
|
|
if (hCur == 0)
|
|
{
|
|
Cls();
|
|
Screen("No information returned from Query.");
|
|
|
|
HourGlassCursor(FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
Cls();
|
|
DisplayTable(hCur, 0);
|
|
}
|
|
HourGlassCursor(FALSE);
|
|
return TRUE;
|
|
|
|
case IDC_LOADQUERY:
|
|
LoadQuery(eQryLang);
|
|
return TRUE;
|
|
|
|
case IDC_SAVEQUERY:
|
|
SaveQuery(eQryLang);
|
|
return TRUE;
|
|
|
|
case IDC_SAVERESULT:
|
|
if (!hCur || !dbarray[0].hdb)
|
|
{
|
|
MessageBox(NULL, "No result set to save.",
|
|
"Error", MB_ICONHAND);
|
|
}
|
|
else
|
|
{
|
|
if (!SaveResultSet (hCur, dbarray[0].hdb))
|
|
{
|
|
MessageBox(NULL, "Error saving result set",
|
|
"Error", MB_ICONHAND);
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case IDC_CONNECT:
|
|
lpfnConnectDlgProc = MakeProcInstance
|
|
((FARPROC)ConnectDlgProc, hInst);
|
|
|
|
DialogBox(hInst, szConnectDialogName,
|
|
hWnd, (DLGPROC)lpfnConnectDlgProc);
|
|
|
|
FreeProcInstance(lpfnConnectDlgProc);
|
|
return TRUE;
|
|
|
|
case IDC_HELP:
|
|
MessageBox(NULL, szMainHelpText,
|
|
"Query SQL/QBE Example", MB_OK);
|
|
return TRUE;
|
|
|
|
case IDC_ABOUT:
|
|
lpfnAboutDlgProc = (DLGPROC)MakeProcInstance((FARPROC)
|
|
AboutDlg, hInst);
|
|
DialogBox(hInst, "AboutDlg", hWnd, lpfnAboutDlgProc);
|
|
FreeProcInstance((FARPROC)lpfnAboutDlgProc);
|
|
return TRUE;
|
|
|
|
case IDC_RADIO_QBE:
|
|
eQryLang = qrylangQBE;
|
|
return TRUE;
|
|
|
|
case IDC_RADIO_SQL:
|
|
eQryLang = qrylangSQL;
|
|
return TRUE;
|
|
|
|
case IDM_COPY:
|
|
// Determine which characters are selected.
|
|
lMinMax = SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
|
|
EM_GETSEL, 0, 0L);
|
|
|
|
// Get the first and last selected character.
|
|
iStart = LOWORD(lMinMax);
|
|
iEnd = HIWORD(lMinMax);
|
|
|
|
// If nothing is selected, select all.
|
|
if (iStart == iEnd)
|
|
{
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
|
|
EM_SETSEL, 0, 0xfffeL);
|
|
}
|
|
|
|
// Copy the selected text in the QUERY edit box.
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_COPY, 0, 0L);
|
|
return TRUE;
|
|
|
|
case IDM_PASTE:
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
|
|
WM_PASTE, 0, 0L);
|
|
return TRUE;
|
|
|
|
case IDM_CLEAR:
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
|
|
WM_SETTEXT, 0, (LPARAM)(LPCSTR)"");
|
|
return TRUE;
|
|
|
|
case IDM_CLEARRESULT:
|
|
SendDlgItemMessage(hWnd, IDC_RESULT_EDIT,
|
|
WM_SETTEXT, 0, (LPARAM)(LPCSTR)"");
|
|
return TRUE;
|
|
|
|
case IDM_DELETE:
|
|
PostMessage(hWnd, WM_COMMAND, IDM_CLEAR, 0l);
|
|
PostMessage(hWnd, WM_COMMAND, IDM_CLEARRESULT, 0l);
|
|
return TRUE;
|
|
|
|
case IDM_CUT:
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_COPY, 0, 0L);
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, EM_REPLACESEL, 0,
|
|
(LPARAM)(LPCSTR)"");
|
|
return TRUE;
|
|
|
|
case IDM_UNDO:
|
|
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, EM_UNDO, 0, 0L);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// EditSubClassProc(hWnd, msg, wParam, lParam)
|
|
//
|
|
// Input: hWnd - Handle of the window
|
|
// msg - Message
|
|
// wParam - WPARAM
|
|
// lParam - LPARAM
|
|
//
|
|
// Return: It returns the result of the procedure. It can return the
|
|
// result of the original edit control if the WM_CHAR is not a
|
|
// tab character.
|
|
//
|
|
// Description:
|
|
// This routine will process all I/O for the Comments edit
|
|
// control. It does this by first checking if the tab key was
|
|
// hit inside of the comment edit control. If it was it moves
|
|
// control to the next control item and then does NOT let the
|
|
// original edit control process the message. However, if the
|
|
// WM_CHAR is not a tab then it lets the original edit control
|
|
// process the message.
|
|
//======================================================================
|
|
long FAR _pascal _export
|
|
EditSubClassProc (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
|
|
{
|
|
LRESULT lResult = 0;
|
|
BOOL fCallOrigWndProc = TRUE;
|
|
INT16 iId;
|
|
UINT32 lType;
|
|
WNDPROC WndProc;
|
|
|
|
iId = GetDlgCtrlID(hWnd);
|
|
if (iId == IDC_QUERY_EDIT)
|
|
{
|
|
WndProc = (WNDPROC)_wpOrigWndProc;
|
|
}
|
|
else
|
|
{
|
|
WndProc = (WNDPROC)_wpOrigWndProc1;
|
|
}
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_GETDLGCODE:
|
|
return DLGC_WANTMESSAGE;
|
|
|
|
case WM_CHAR:
|
|
if (wParam == '\t')
|
|
{
|
|
if (GetKeyState(VK_SHIFT)<0)
|
|
{
|
|
if (iId == IDC_QUERY_EDIT)
|
|
{
|
|
iId = IDC_RESULT_EDIT;
|
|
}
|
|
else
|
|
{
|
|
iId = IDC_RUN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (iId == IDC_QUERY_EDIT)
|
|
{
|
|
lType = SendDlgItemMessage(hMainWnd, IDC_RADIO_SQL,
|
|
BM_GETCHECK, 0, 0L);
|
|
if (lType == 1)
|
|
{
|
|
iId = IDC_RADIO_SQL;
|
|
}
|
|
else
|
|
{
|
|
iId = IDC_RADIO_QBE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iId = IDC_QUERY_EDIT;
|
|
}
|
|
}
|
|
|
|
SetFocus(GetDlgItem(hMainWnd, iId));
|
|
fCallOrigWndProc = FALSE;
|
|
lResult = TRUE;
|
|
}
|
|
|
|
if (wParam == VK_ESCAPE)
|
|
{
|
|
MessageBeep(1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (fCallOrigWndProc)
|
|
{
|
|
lResult = CallWindowProc(WndProc, hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// AboutDlg(hWnd, msg, wParam, lParam)
|
|
//
|
|
// Input: hWnd, msg, wParam, lParam
|
|
//
|
|
// Return: TRUE - Dialog Created.
|
|
// FALSE - Dialog Failed to create.
|
|
//
|
|
// Description:
|
|
// This routine will process all I/O for the ABOUT dialog.
|
|
//======================================================================
|
|
BOOL FAR _pascal _export
|
|
AboutDlg (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
// Done to clear the unused warning.
|
|
lParam = lParam;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
ret = TRUE;
|
|
EndDialog(hWnd, ret);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// ConnectDlgProc(hDlg, message, wParam, lParam)
|
|
//
|
|
// Input: hDlg, message, wParam, lParam
|
|
//
|
|
// Return: TRUE if dialog procedure processes a message
|
|
// FALSE otherwise.
|
|
//
|
|
// Description:
|
|
// Dialog box procedure for the dialog box that establishes
|
|
// and removes connections to databases based on ALIASES
|
|
// defined in IDAPI.CFG.
|
|
//======================================================================
|
|
BOOL CALLBACK _export
|
|
ConnectDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int i;
|
|
char szAliasName[81];
|
|
WORD ListIndex;
|
|
int nIndex;
|
|
char szConnectionName[DBIMAXPATHLEN + 1];
|
|
static char szDirectory[DBIMAXPATHLEN+1];
|
|
char szTemp[DBIMAXPATHLEN + 1];
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
QueryResetConnectDialog(hDlg, dbarray, iSelectedDbIndex);
|
|
if (dbarray[0].hdb != 0)
|
|
{
|
|
GetWorkingDirectory(dbarray[0].hdb, szDirectory);
|
|
}
|
|
ShowWindow(hDlg, SW_HIDE);
|
|
PostMessage(hDlg, WM_MYSETUP, 0, 0);
|
|
return TRUE;
|
|
|
|
case WM_MYSETUP:
|
|
|
|
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
|
|
WM_GETTEXT,
|
|
DBIMAXPATHLEN, (LPARAM)szConnectionName);
|
|
|
|
// Check if this is the standard database.
|
|
if (!strcmp(szConnectionName, szStandard))
|
|
{
|
|
// Show the Directory controls.
|
|
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
|
|
SW_SHOW);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
|
|
SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
// Hide the Directory controls.
|
|
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
|
|
SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
|
|
SW_HIDE);
|
|
}
|
|
|
|
// Set the directory.
|
|
SendDlgItemMessage(hDlg, IDC_EDIT_DIRECTORY, WM_SETTEXT, 0,
|
|
(LPARAM)(LPCSTR)szDirectory);
|
|
|
|
ShowWindow(hDlg, SW_SHOW);
|
|
|
|
return TRUE;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hDlg, 0);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDC_LB_CONNECTIONS:
|
|
if (HIWORD(lParam) == LBN_SELCHANGE)
|
|
{
|
|
SetSelected(hDlg);
|
|
}
|
|
return TRUE;
|
|
|
|
case IDC_BTN_CONNECT:
|
|
// First check to see if any alias is selected,
|
|
// if not, beep.
|
|
ListIndex = (WORD)
|
|
SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
|
|
LB_GETCURSEL, 0, 0);
|
|
if (ListIndex == (WORD) LB_ERR)
|
|
{
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
return TRUE;
|
|
}
|
|
|
|
// If an alias is selected, run through
|
|
// the array of handles/descriptions to see if we
|
|
// have any free one's left.
|
|
for (i = 1; i < MAX_DATABASE_HANDLES; i++)
|
|
{
|
|
if (dbarray[i].hdb == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we don't, provide an error message.
|
|
if (i == MAX_DATABASE_HANDLES)
|
|
{
|
|
MessageBox(NULL, "Maximum database handles limit "
|
|
"reached.", "Error", MB_OK);
|
|
}
|
|
else
|
|
{
|
|
// If we do have room left in our array,
|
|
// try to establish connection. If successful,
|
|
// add database name to connections list.
|
|
|
|
HourGlassCursor(TRUE);
|
|
if ((dbarray[i].hdb =
|
|
QueryConnectToDatabase(hDlg)) != 0)
|
|
{
|
|
ListIndex = (WORD)
|
|
SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
|
|
LB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
|
|
LB_GETTEXT,
|
|
(WPARAM)ListIndex,
|
|
(LPARAM)szAliasName);
|
|
|
|
strcpy(dbarray[i].szDatabaseName, szAliasName);
|
|
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
|
|
LB_ADDSTRING, 0,
|
|
(LPARAM)szAliasName);
|
|
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
|
|
LB_SELECTSTRING,
|
|
(WPARAM)-1,
|
|
(LPARAM)szAliasName);
|
|
SetSelected(hDlg);
|
|
}
|
|
HourGlassCursor(FALSE);
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
case IDC_BTN_REMOVE:
|
|
// Disconnect from the selected connection.
|
|
nIndex = (WORD)
|
|
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
|
|
LB_GETCURSEL, 0, 0);
|
|
|
|
RemoveConnection(hDlg, dbarray, nIndex);
|
|
return TRUE;
|
|
|
|
case IDC_BTN_HELP:
|
|
// Display information on this application.
|
|
MessageBox(NULL, szConnectHelpText, "Help", MB_OK);
|
|
return TRUE;
|
|
|
|
case IDOK:
|
|
// find currently selected database based
|
|
// on the string in the static control
|
|
// displaying this information.
|
|
|
|
// Get currently selected database.
|
|
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
|
|
WM_GETTEXT, 80,
|
|
(LPARAM) szConnectionName);
|
|
|
|
// Compare currently selected database
|
|
// to the strings in the array and
|
|
// set iSelectedDbIndex based on that.
|
|
// iSelectedDbIndex is in turn used
|
|
// as the database handle used to
|
|
// execute queries.
|
|
for (i = 0; i < MAX_DATABASE_HANDLES,
|
|
dbarray[i].hdb != 0; i++)
|
|
{
|
|
if (strcmpi(dbarray[i].szDatabaseName,
|
|
szConnectionName) == 0)
|
|
{
|
|
iSelectedDbIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == MAX_DATABASE_HANDLES)
|
|
{
|
|
iSelectedDbIndex = 0;
|
|
}
|
|
|
|
// Check if this is the standard database.
|
|
if (!strcmp(szConnectionName, szStandard))
|
|
{
|
|
// Get currently selected directory.
|
|
SendDlgItemMessage(hDlg, IDC_EDIT_DIRECTORY,
|
|
WM_GETTEXT, DBIMAXPATHLEN,
|
|
(LPARAM)szTemp);
|
|
// Only set if changed.
|
|
if (strcmp(szTemp, szDirectory))
|
|
{
|
|
// Check if the directory exists.
|
|
if (!access(szTemp, 00))
|
|
{
|
|
if (SetWorkingDirectory(
|
|
dbarray[iSelectedDbIndex].hdb, szTemp))
|
|
{
|
|
SendDlgItemMessage(hDlg,
|
|
IDC_STATIC_STATUS,
|
|
WM_SETTEXT, 0,
|
|
(LPARAM) "Invalid Directory");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Display message if directory does not exist.
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_STATUS,
|
|
WM_SETTEXT, 0,
|
|
(LPARAM) "Invalid Directory");
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
EndDialog (hDlg, 0);
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog (hDlg, 0);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// SetSelected (hDlg)
|
|
//
|
|
// Input: hDlg - Handle of the Dialog
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description:
|
|
// This routine sets which connection the application uses
|
|
// for processing the query.
|
|
//======================================================================
|
|
void
|
|
SetSelected (HWND hDlg)
|
|
{
|
|
WORD ListIndex;
|
|
char szConnectionName[DBIMAXPATHLEN + 1];
|
|
|
|
// Determine which connection is selected.
|
|
ListIndex = (WORD)SendDlgItemMessage(hDlg,
|
|
IDC_LB_CONNECTIONS,
|
|
LB_GETCURSEL, 0, 0);
|
|
// Get the selected connection.
|
|
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS, LB_GETTEXT,
|
|
(WPARAM)ListIndex,
|
|
(LPARAM)szConnectionName);
|
|
|
|
// Set the Static control with the selected connection.
|
|
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
|
|
WM_SETTEXT,
|
|
0, (LPARAM) szConnectionName);
|
|
|
|
// Check if this is the standard database.
|
|
if (!strcmp(szConnectionName, szStandard))
|
|
{
|
|
// Show the Directory controls.
|
|
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
|
|
SW_SHOW);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
|
|
SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
// Hide the directory controls.
|
|
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
|
|
SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
|
|
SW_HIDE);
|
|
}
|
|
}
|
|
//======================================================================
|
|
// Function:
|
|
// HourGlassCursor(turnOn)
|
|
//
|
|
// Input: turnOn - Turn on or off the Hourglass cursor
|
|
//
|
|
// Return: TRUE
|
|
//
|
|
// Description:
|
|
// Turns the hourglass cursor on or off according to value
|
|
// specified in turnOn.
|
|
//======================================================================
|
|
BOOL CALLBACK
|
|
HourGlassCursor (BOOL turnOn)
|
|
{
|
|
if (turnOn)
|
|
{
|
|
if (SetCursor(LoadCursor(NULL, IDC_WAIT)))
|
|
{
|
|
ShowCursor(TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SetCursor(LoadCursor(NULL, IDC_ARROW)))
|
|
{
|
|
ShowCursor(TRUE);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// LoadQuery(QryType)
|
|
//
|
|
// Input: Query Type (DBIQryLang).
|
|
//
|
|
// Return: 1 if succesful,
|
|
// 0 if error
|
|
//
|
|
// Description:
|
|
// Using a Windows 3.1 Common Dialog, opens a file open
|
|
// dialog box to read a .QBE or .SQL query file into the
|
|
// query edit window.
|
|
//======================================================================
|
|
UINT16
|
|
LoadQuery (DBIQryLang QryType)
|
|
{
|
|
// File types for file open dialog box.
|
|
char* SQLFilter = "SQL Script(*.SQL)\0*.SQL\0"
|
|
"QBE Script(*.QBE)\0*.QBE\0";
|
|
char* QBEFilter = "QBE Script(*.QBE)\0*.QBE\0"
|
|
"SQL Script(*.SQL)\0*.SQL\0";
|
|
HFILE hFile; // Handle to the returned file
|
|
static char pBuf[256]; // filename
|
|
LONG flength; // length of file
|
|
char ch[1]; // input character
|
|
OPENFILENAME ofn; // structure used by File Open
|
|
// common dialog
|
|
char* szInputBuffer; // pointer to input buffer
|
|
char* start; // pointer used as a marker
|
|
|
|
// Init the structure used by File Open dialog.
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hMainWnd;
|
|
ofn.hInstance = hInst;
|
|
if (QryType == qrylangQBE)
|
|
{
|
|
ofn.lpstrFilter = QBEFilter;
|
|
}
|
|
else
|
|
{
|
|
ofn.lpstrFilter = SQLFilter;
|
|
}
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nFilterIndex = 1L;
|
|
ofn.lpstrFile = pBuf;
|
|
ofn.nMaxFile = 256;
|
|
ofn.lpstrFileTitle = NULL;
|
|
ofn.nMaxFileTitle = 0;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = NULL;
|
|
ofn.lpstrDefExt = NULL;
|
|
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
|
|
OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
|
|
|
|
// Use the FileOpen common dialog box to get the file name.
|
|
if (GetOpenFileName(&ofn))
|
|
{
|
|
// Open the selected file
|
|
hFile = _lopen(ofn.lpstrFile, READ);
|
|
|
|
if (hFile == HFILE_ERROR)
|
|
{
|
|
MessageBox(NULL, "Could Not Open File", "File Open",
|
|
MB_ICONHAND);
|
|
return 0;
|
|
}
|
|
|
|
// Compute length of string needed for file text.
|
|
flength = 0;
|
|
while (_lread(hFile, ch, 1) != 0)
|
|
{
|
|
if (ch[0] == '\n')
|
|
{
|
|
flength += 2; // Need two for newline so
|
|
// we can format for edit control.
|
|
}
|
|
else
|
|
{
|
|
flength++; // Otherwise length equals one per char.
|
|
}
|
|
}
|
|
// Add one for null.
|
|
flength += 1;
|
|
|
|
// Return to beginning of file.
|
|
_llseek(hFile, 0, 0);
|
|
|
|
// Allocate memory, pointer "start" will remember our place.
|
|
start = szInputBuffer = (char *) malloc((int) flength + 1);
|
|
memset(szInputBuffer, 0, (int) flength + 1);
|
|
|
|
if (!szInputBuffer)
|
|
{
|
|
MessageBox(NULL, "Unable to allocate memory", "Error", MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
while ( _lread(hFile, ch, 1) != 0)
|
|
{
|
|
if (ch[0] == '\n')
|
|
{
|
|
*szInputBuffer = '\r';
|
|
szInputBuffer++;
|
|
*szInputBuffer = '\n';
|
|
szInputBuffer++;
|
|
|
|
}
|
|
else // Otherwise just read in characters.
|
|
{
|
|
*szInputBuffer = ch[0];
|
|
szInputBuffer++;
|
|
}
|
|
}
|
|
|
|
// Reset to beginning of string.
|
|
szInputBuffer = start;
|
|
|
|
// Put the string into the edit control.
|
|
SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT, WM_SETTEXT,
|
|
0, (LPARAM) szInputBuffer);
|
|
|
|
// Cleanup.
|
|
free(szInputBuffer);
|
|
|
|
_lclose(hFile);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// SaveQuery(QryType)
|
|
//
|
|
// Input: Query Type (DBIQryLang).
|
|
//
|
|
// Return: 1 if succesful,
|
|
// 0 if error
|
|
//
|
|
// Description:
|
|
// Using a Windows 3.1 Common Dialog, opens a file save
|
|
// dialog box to save the contents of the query edit
|
|
// window to a .QBE or .SQL query file
|
|
//======================================================================
|
|
UINT16
|
|
SaveQuery (DBIQryLang QryType)
|
|
{
|
|
// File types for File Save dialog box.
|
|
char* SQLFilter = "SQL Script(*.SQL)\0*.SQL\0"
|
|
"QBE Script(*.QBE)\0*.QBE\0";
|
|
char* QBEFilter = "QBE Script(*.QBE)\0*.QBE\0"
|
|
"SQL Script(*.SQL)\0*.SQL\0";
|
|
static char pBuf[256]; // filename
|
|
HFILE hFile; // Handle to the file
|
|
OFSTRUCT ofStruct; // OpenFile structure
|
|
OPENFILENAME ofn; // structure used by File Open common dialog
|
|
char* szQuery; // pointer to text buffer
|
|
char* szSeek; // equals szQuery at first
|
|
LONG lTextLength; // length of text
|
|
|
|
// Init the structure used by File Open dialog.
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hMainWnd;
|
|
ofn.hInstance = hInst;
|
|
if (QryType == qrylangQBE)
|
|
{
|
|
ofn.lpstrFilter = QBEFilter;
|
|
}
|
|
else
|
|
{
|
|
ofn.lpstrFilter = SQLFilter;
|
|
}
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nFilterIndex = 1L;
|
|
ofn.lpstrFile = pBuf;
|
|
ofn.nMaxFile = 256;
|
|
ofn.lpstrFileTitle = NULL;
|
|
ofn.nMaxFileTitle = 0;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = NULL;
|
|
ofn.lpstrDefExt = NULL;
|
|
|
|
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
|
|
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
|
|
|
|
if (GetSaveFileName(&ofn))
|
|
{
|
|
// Determine the length of the text.
|
|
lTextLength = SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT,
|
|
WM_GETTEXTLENGTH,
|
|
0, 0);
|
|
// Allocate memory to contain the query.
|
|
if ((szQuery = szSeek = (char*) malloc((int)lTextLength + 1))
|
|
== NULL)
|
|
{
|
|
MessageBox(NULL, "Out of Memory!",
|
|
"Fatal Error", MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the query from the edit control.
|
|
SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT, WM_GETTEXT,
|
|
(int)lTextLength + 1, (LPARAM)szQuery);
|
|
|
|
// Open the selected file.
|
|
hFile = OpenFile(ofn.lpstrFile, &ofStruct, OF_CREATE);
|
|
|
|
// Check for errors.
|
|
if (hFile == HFILE_ERROR)
|
|
{
|
|
MessageBox(NULL, "Could Not Open File", "File Open",
|
|
MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Format the query and write to file.
|
|
while (*szQuery)
|
|
{
|
|
if (*szQuery == '\r')
|
|
{
|
|
szQuery++; // Ignore extra newline.
|
|
}
|
|
else
|
|
{
|
|
_lwrite(hFile, (void huge *)(szQuery++), 1);
|
|
}
|
|
}
|
|
|
|
// Close the file.
|
|
_lclose(hFile);
|
|
// Free memory.
|
|
free(szSeek);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// SaveResultSet(hCur, hDb)
|
|
//
|
|
// Input: hCur - Handle to the cursor of the in-memory table representing
|
|
// the result set of the last query.
|
|
// hDb - Handle to a STANDARD database.
|
|
//
|
|
// Return: 1 on success
|
|
// 0 on failure
|
|
//
|
|
// Description:
|
|
// Using a Windows 3.1 Common Dialog, opens a file save
|
|
// dialog box to save the contents of the query edit
|
|
// window to a .QBE or .SQL query file
|
|
//======================================================================
|
|
UINT16
|
|
SaveResultSet (hDBICur hCur, hDBIDb hDb)
|
|
{
|
|
static char pBuf[256]; // filename
|
|
char pString[300]; // Message String
|
|
OPENFILENAME ofn; // structure used by File Open common dialog
|
|
char* ScriptFilter = "Paradox Database(*.DB)|*.DB|";
|
|
CHAR chWildChar = '|'; // This is the wildcard separator
|
|
UINT16 uCtr = 0;
|
|
|
|
while (ScriptFilter[uCtr])
|
|
{
|
|
if (ScriptFilter[uCtr]==chWildChar)
|
|
{
|
|
ScriptFilter[uCtr]=0;
|
|
}
|
|
uCtr++;
|
|
}
|
|
|
|
// Init the structure used by File Open dialog.
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hMainWnd;
|
|
ofn.hInstance = hInst;
|
|
ofn.lpstrFilter = ScriptFilter;
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nFilterIndex = 1L;
|
|
ofn.lpstrFile = pBuf;
|
|
ofn.nMaxFile = 256;
|
|
ofn.lpstrFileTitle = NULL;
|
|
ofn.nMaxFileTitle = 0;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = NULL;
|
|
ofn.lpstrDefExt = "DB";
|
|
|
|
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
|
|
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
|
|
|
|
if (GetSaveFileName(&ofn))
|
|
{
|
|
if (!QuerySaveResultSet(hCur, hDb, pBuf))
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
wsprintf(pString, "%s was successfully created.", pBuf);
|
|
MessageBox(hMainWnd, pString, "Query SQL/QBE Example", MB_OK);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Function:
|
|
// RemoveConnection(hDlg, array, nIndex)
|
|
//
|
|
// Input: hDlg - Handle to the connection dialog box.
|
|
// array - A DBStructArray, i.e., an array of structures
|
|
// containing valid database names and handles
|
|
// nIndex - Index into the connection dialog box of
|
|
// the database connection to be removed.
|
|
//
|
|
// Return: 1 on success
|
|
//
|
|
// Description:
|
|
// Removes a database connection from the connection listbox
|
|
// inside the connection dialog box. Also removes the
|
|
// corrseponding structure from the array of structures passed
|
|
// via the array parameter and resets the currently selected
|
|
// selection to the STANDARD database.
|
|
//======================================================================
|
|
UINT16
|
|
RemoveConnection (HWND hDlg, DBStructArray array, int nIndex)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
switch(nIndex)
|
|
{
|
|
case 0:
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
MessageBox(NULL, "Cannot delete STANDARD database", "Error",
|
|
MB_ICONEXCLAMATION);
|
|
break;
|
|
|
|
case LB_ERR:
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
break;
|
|
|
|
default:
|
|
// Reset the static control showing currently selected dialog
|
|
// box back to the default.
|
|
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION, WM_SETTEXT,
|
|
0, (LPARAM) szStandard);
|
|
|
|
// Remove item from list box.
|
|
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS, LB_DELETESTRING,
|
|
nIndex, 0);
|
|
|
|
// Close database handle.
|
|
QueryDbiCloseDatabase(&array[nIndex].hdb);
|
|
|
|
// Pack array.
|
|
for (i = nIndex, j = nIndex + 1; j < MAX_DATABASE_HANDLES;
|
|
i++, j++)
|
|
{
|
|
array[i].hdb = array[j].hdb;
|
|
strcpy(array[i].szDatabaseName, array[j].szDatabaseName);
|
|
}
|
|
|
|
// Last member is now blank.
|
|
array[j].hdb = 0;
|
|
strcpy(array[j].szDatabaseName, "");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
//======================================================================
|
|
// Function:
|
|
// GenProgCallBack(ecbType, iClientData, pCbInfo)
|
|
//
|
|
// Input: ecbType - Callback type (CBType)
|
|
// iClientData - Pointer to client information that is passed into
|
|
// the callback function (UINT32)
|
|
// pCbInfo - The callback structure that holds the information
|
|
// about the current state of affairs with
|
|
// IDAPI(pVOID)
|
|
//
|
|
// Return: The action that should be taken (CBRType)
|
|
//
|
|
// Description:
|
|
// This function is called when IDAPI is running an internal
|
|
// process and the application setup the callback. The callback
|
|
// is sent the current CallBack type (ecbType) so that it can
|
|
// react appropriatly. It is sent the pointer to data that was
|
|
// passed into the DbiRegisterCallBack function. This data can
|
|
// be a Window handle, pointer to a structure etc. In this case
|
|
// it is simply a string. It is also sent information about the
|
|
// state of this callback in the structure that was passed into
|
|
// the DbiRegisterCallBack() function. In our example the
|
|
// callback is a progress callback - therefore, we passed a
|
|
// progress structure into DbiRegisterCallBack(). We always
|
|
// return cbrUSEDEF as we do not want to worry about the callback.
|
|
// However, if this was another callback return type you may want
|
|
// to return a different callback return type.
|
|
//======================================================================
|
|
CBRType DBIFN
|
|
GenProgCallBack (CBType ecbType, UINT32 iClientData, pVOID pCbInfo)
|
|
{
|
|
CBPROGRESSDesc *eCBPROGRESSDesc;
|
|
CHAR szMessage[DBIMAXMSGLEN + 1 + 30]; // Reserve space for max
|
|
// Message plus client
|
|
// data
|
|
|
|
memset(szMessage, 0, DBIMAXMSGLEN + 1);
|
|
|
|
// Set to stop a Unused variable warning.
|
|
iClientData=iClientData;
|
|
|
|
switch (ecbType)
|
|
{
|
|
// In case this is a General Progress callback display the progress
|
|
// information.
|
|
case cbGENPROGRESS:
|
|
|
|
// First cast the pVOID structure as a General Progress structure.
|
|
eCBPROGRESSDesc = (CBPROGRESSDesc far *)pCbInfo;
|
|
|
|
// Next if the percent done is -1 then the only relevent data is in
|
|
// the message string (szMsg).
|
|
if (eCBPROGRESSDesc->iPercentDone < 0)
|
|
{
|
|
wsprintf(szMessage, "%s", eCBPROGRESSDesc->szMsg);
|
|
DisplayProgress(szMessage);
|
|
}
|
|
else
|
|
{
|
|
// Otherwise you can use the percent done. Here we simply
|
|
// display the percent complete. But you can use this number
|
|
// to display a moving bar to graphically display the amount
|
|
// complete.
|
|
wsprintf(szMessage, "%s:%i",
|
|
eCBPROGRESSDesc->szMsg, eCBPROGRESSDesc->iPercentDone);
|
|
DisplayProgress(szMessage);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DisplayProgress(" ### In the Callback function");
|
|
}
|
|
return cbrUSEDEF;
|
|
}
|
|
|
|
//=====================================================================
|
|
// Function:
|
|
// MakeFullPath (pszDirectory, pszRelativeDirectory)
|
|
//
|
|
// Input: pszDirectory - String to contain the path to the tables
|
|
// directory
|
|
// pszRelativeDirectory - String which contains the relative offset
|
|
// from the current directory
|
|
//
|
|
// Return: int - If the directory exists
|
|
//
|
|
// Description:
|
|
// This function is used to get the fully qualified path to
|
|
// the directory which will contain the tables. This function
|
|
// will only work when pszRelativeDirectory contains either "."
|
|
// an absolute path, or <..\\..\\>TABLES.
|
|
//=====================================================================
|
|
int
|
|
MakeFullPath (pCHAR pszDirectory, pCHAR pszRelativeDirectory)
|
|
{
|
|
int iExists; // Does the directory exist?
|
|
int iLen; // Length of the path
|
|
int iLoop; // Loop counter
|
|
int iDepth = 0; // How many ..\\ in the directory
|
|
|
|
// Assume absolute path if second character is a ':'.
|
|
if (pszRelativeDirectory[1] == ':')
|
|
{
|
|
strcpy(pszDirectory, pszRelativeDirectory);
|
|
}
|
|
else if (!strcmp(pszRelativeDirectory, "."))
|
|
{
|
|
// Get the current working directory.
|
|
getcwd(pszDirectory, DBIMAXPATHLEN);
|
|
}
|
|
else
|
|
{
|
|
// Get the current working directory.
|
|
getcwd(pszDirectory, DBIMAXPATHLEN);
|
|
|
|
iLen = strlen(pszDirectory);
|
|
|
|
// Remove relative parts of the path.
|
|
iDepth = 0;
|
|
while (!strncmp(&pszRelativeDirectory[iDepth * 3], "..\\", 3))
|
|
{
|
|
for (iLoop = iLen; iLoop > -1; iLoop = iLoop - 1)
|
|
{
|
|
if (pszDirectory[iLoop] == '\\')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
iLen = iLoop - 1;
|
|
iDepth++;
|
|
}
|
|
|
|
// Copy the 'TABLES' directory to form the full path to the tables.
|
|
// Need to move szDirectory past the '\\' and szTblDirectory
|
|
// past the '..\\'.
|
|
strcpy(&pszDirectory[iLoop+1], &pszRelativeDirectory[(3 * iDepth)]);
|
|
}
|
|
|
|
// Check if the directory exists
|
|
iExists = access(pszDirectory, 00);
|
|
|
|
return iExists;
|
|
}
|
|
|